Преглед изворни кода

Preparations for Unix x64: 64-bit calling convention (being different from that of the WinAPI)
Moved decision about register parameters to backend: new method GetParameterRegisters(callingConvention) returning an array of indices that are subsequently mapped to hardware registers by the code generator
No numberParameterRegisters in Global.System any more.

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6602 8c9fc860-2736-0410-a75d-ab315db34111

felixf пре 9 година
родитељ
комит
316732e6df

+ 49 - 13
source/FoxAMDBackend.Mod

@@ -936,15 +936,24 @@ TYPE
 			END;
 		END GetTypedHardwareRegister;
 
+		(* returns the following register (or part thereof)
+			0: regRAX; 
+			1: regRCX; 
+			2: regRDX; 
+			3: regRBX;
+			4: regRSP; 
+			5: regRBP; 
+			6: regRSI; 
+			7: regRDI;
+			8 .. 15: regRx;
+		*)
+
 		PROCEDURE ParameterRegister(CONST type: IntermediateCode.Type; index: LONGINT): LONGINT;
 		VAR physical: LONGINT;
 		BEGIN
-			CASE index OF
-				0: RETURN GetTypedHardwareRegister(RCX,type)
-				|1: RETURN GetTypedHardwareRegister(RDX,type)
-				|2: RETURN GetTypedHardwareRegister(R8,type)
-				|3: RETURN GetTypedHardwareRegister(R9,type)
-			END;
+			RETURN GetTypedHardwareRegister(RAX + index, type);
+			ASSERT(0 <= index); 
+			ASSERT(index <= 15);
 			RETURN physical;
 		END ParameterRegister;
 
@@ -964,11 +973,6 @@ TYPE
 			ELSIF virtual.register = IntermediateCode.SP THEN
 				Assert(part=Low,"forbidden partitioned register on SP");
 				physical := opSP;
-			(*! done by generic part:
-				ELSIF virtual.register <= IntermediateCode.ParameterRegister THEN
-				index := IntermediateCode.ParameterRegister - virtualRegister;
-				physical := registerOperands[ParameterRegister(index, type)];
-			*)
 			ELSIF virtual.register = IntermediateCode.AP THEN
 				ASSERT(backend.cooperative);
 				Assert(part=Low,"forbidden partitioned register on AP");
@@ -3088,12 +3092,28 @@ TYPE
 		bits: LONGINT;
 		traceable: BOOLEAN;
 		forceFPU: BOOLEAN;
+		winAPIRegisters, cRegisters: Backend.Registers;
 
 		PROCEDURE &InitBackendAMD64;
 		BEGIN
 			InitIntermediateBackend;
 			bits := 32;
 			forceFPU := FALSE;
+						
+			NEW(winAPIRegisters, 4); 
+			winAPIRegisters[0] := RCX - RAX;
+			winAPIRegisters[1] := RDX - RAX;
+			winAPIRegisters[2] := R8 - RAX;
+			winAPIRegisters[3] := R9 - RAX; 
+			
+			NEW(cRegisters, 6);
+			cRegisters[0] := RDI - RAX;
+			cRegisters[1] := RSI - RAX;
+			cRegisters[2] := RDX - RAX;
+			cRegisters[3] := RCX - RAX; 
+			cRegisters[4] := R8 - RAX;
+			cRegisters[5] := R9 - RAX; 
+			
 		END InitBackendAMD64;
 
 		PROCEDURE Initialize(diagnostics: Diagnostics.Diagnostics; log: Streams.Writer; flags: SET; checker: SemanticChecker.Checker; system: Global.System);
@@ -3153,11 +3173,11 @@ TYPE
 		BEGIN
 			IF system = NIL THEN
 				IF bits=32 THEN
-					NEW(system,8,8,32, 8,32,32,32,64,0,cooperative);
+					NEW(system,8,8,32, 8,32,32,32,64,cooperative);
 					Global.SetDefaultDeclarations(system,8);
 					Global.SetDefaultOperators(system);
 				ELSE
-					NEW(system,8,8,64,8,64,64,64,128,4 (* parameter registers *),cooperative);
+					NEW(system,8,8,64,8,64,64,64,128,cooperative);
 					Global.SetDefaultDeclarations(system,8);
 					Global.SetDefaultOperators(system);
 				END;
@@ -3167,6 +3187,22 @@ TYPE
 			RETURN system
 		END GetSystem;
 
+		(* return index of general purpose register used as parameter register in calling convention *)
+		PROCEDURE GetParameterRegisters*(callingConvention: SyntaxTree.CallingConvention): Backend.Registers;
+		BEGIN
+			IF bits = 32 THEN
+				RETURN NIL;
+			ELSE
+				CASE callingConvention OF
+					SyntaxTree.CCallingConvention: RETURN cRegisters;
+					|SyntaxTree.WinAPICallingConvention:  RETURN winAPIRegisters;
+					|SyntaxTree.DarwinCCallingConvention: RETURN cRegisters; 
+				ELSE
+					RETURN NIL;
+				END;
+			END
+		END GetParameterRegisters;
+
 		PROCEDURE SupportedInstruction(CONST instruction: IntermediateCode.Instruction; VAR moduleName, procedureName: ARRAY OF CHAR): BOOLEAN;
 		BEGIN
 			RETURN cg.Supported(instruction,moduleName,procedureName);

+ 1 - 1
source/FoxARMBackend.Mod

@@ -3188,7 +3188,7 @@ TYPE
 				registerParameters = 0
 				*)
 
-				NEW(system, 8, 8, 32, (*32*) 8, 32, 8, 32, 32 * 2, 0, cooperative);
+				NEW(system, 8, 8, 32, (*32*) 8, 32, 8, 32, 32 * 2, cooperative);
 
 				IF oberon07 THEN
 					IF Trace THEN D.String("Oberon07"); D.Ln END;

+ 6 - 1
source/FoxBackend.Mod

@@ -6,6 +6,7 @@ IMPORT
 
 TYPE
 	SectionName = ARRAY 256 OF CHAR;
+	Registers*= POINTER TO ARRAY OF LONGINT;
 
 	Backend* = OBJECT
 	VAR
@@ -55,7 +56,6 @@ TYPE
 		BEGIN
 			hasLinkRegister := TRUE;
 		END SetHasLinkRegister;
-		
 
 		PROCEDURE SetInstructionWidth* (instructionWidth: LONGINT);
 		BEGIN
@@ -83,6 +83,11 @@ TYPE
 		BEGIN
 			RETURN Global.DefaultSystem();
 		END GetSystem;
+		
+		PROCEDURE GetParameterRegisters*(callingConvention: SyntaxTree.CallingConvention): Registers;
+		BEGIN
+			RETURN NIL; (* default case: no parameter registers *)
+		END GetParameterRegisters;
 
 		PROCEDURE Error*(CONST source: ARRAY OF CHAR; errorNumber, errorPosition: LONGINT; CONST err: ARRAY OF CHAR);
 		BEGIN

+ 1 - 1
source/FoxCodeGenerators.Mod

@@ -194,7 +194,7 @@ TYPE
 			END ResolveLocalFixups;
 
 			PROCEDURE GetRegisterAllocation;
-			CONST MaxParameterRegisters=8;
+			CONST MaxParameterRegisters=16;
 			VAR pc,i: LONGINT; parameterRegisters: ARRAY MaxParameterRegisters OF IntermediateCode.Operand;
 
 				PROCEDURE RegisterUsage(CONST instruction: IntermediateCode.Instruction);

+ 2 - 5
source/FoxGlobal.Mod

@@ -229,8 +229,6 @@ TYPE
 		(* type sizes defined by backend *)
 		addressSize-: LONGINT;
 
-		registerParameters-: LONGINT; (* how many parameters are passed via registers *)
-
 		(* system type mapping, in a later version only the global (unisgned) types should be used
 			the following two types are only there for compatibility with the system as is
 			problematic are mainly the conversions between (signed) Oberon types and (unsigned) addressType.
@@ -243,7 +241,7 @@ TYPE
 		CanPassInRegister-: PassInRegisterProc;
 		cellsAreObjects-: BOOLEAN;
 
-		PROCEDURE &InitSystem*(codeUnit, dataUnit: LONGINT; addressSize, minVarAlign, maxVarAlign, minParAlign, maxParAlign, offsetFirstPar, registerParameters: LONGINT; cooperative: BOOLEAN);
+		PROCEDURE &InitSystem*(codeUnit, dataUnit: LONGINT; addressSize, minVarAlign, maxVarAlign, minParAlign, maxParAlign, offsetFirstPar: LONGINT; cooperative: BOOLEAN);
 		VAR i: LONGINT;
 		BEGIN
 			ASSERT(dataUnit > 0);
@@ -259,7 +257,6 @@ TYPE
 			SELF.parameterAlignment.min := minParAlign;
 			SELF.parameterAlignment.max := maxParAlign;
 			SELF.offsetFirstParameter := offsetFirstPar;
-			SELF.registerParameters := registerParameters;
 			IF cooperative THEN INC(SELF.offsetFirstParameter,addressSize) END;
 			activeCellsCapabilities := NIL;
 			BuildScopes(SELF);
@@ -948,7 +945,7 @@ TYPE
 	PROCEDURE DefaultSystem*(): System;
 	VAR system: System;
 	BEGIN
-		NEW(system,8,8,32, 8,32,32,32,64,0,FALSE);
+		NEW(system,8,8,32, 8,32,32,32,64,FALSE);
 		SetDefaultDeclarations(system,8);
 		SetDefaultOperators(system);
 		RETURN system

+ 23 - 8
source/FoxIntermediateBackend.Mod

@@ -597,6 +597,8 @@ TYPE
 			cc: LONGINT;
 			cellType: SyntaxTree.CellType;
 			registerNumber: LONGINT;
+			registerParameter: Backend.Registers;
+			registerParameters: LONGINT;
 			registerClass: IntermediateCode.RegisterClass;
 			type: IntermediateCode.Type;
 			formalParameter: SyntaxTree.Parameter;
@@ -736,12 +738,18 @@ TYPE
 					*)
 
 					IF procedureType.callingConvention # SyntaxTree.OberonCallingConvention THEN
+						registerParameter := backend.GetParameterRegisters(procedureType.callingConvention);
+						
+						IF registerParameter = NIL THEN registerParameters := 0 
+						ELSE registerParameters := LEN(registerParameter) 
+						END;
+						
 						formalParameter := procedureType.lastParameter;
-						WHILE (formalParameter # NIL) & (registerNumber < system.registerParameters) DO
+						WHILE (formalParameter # NIL) & (registerNumber < registerParameters) DO
 							IF ~PassInRegister(formalParameter) THEN
 								Error(formalParameter.position,"Calling convention error: cannot be passed as register");
 							ELSE
-								IntermediateCode.InitRegisterClass(registerClass, IntermediateCode.Parameter, SHORT(registerNumber));
+								IntermediateCode.InitRegisterClass(registerClass, IntermediateCode.Parameter, registerParameter[registerNumber]);
 								type := GetType(system, formalParameter.type);
 								src := IntermediateCode.Register(type, registerClass, implementationVisitor.AcquireRegister(type, registerClass));
 								IntermediateCode.InitMemory(dest,GetType(system,formalParameter.type),implementationVisitor.fp,ToMemoryUnits(system,formalParameter.offsetInBits));
@@ -5343,6 +5351,8 @@ TYPE
 			isCallOfDynamicOperator, hasDynamicOperands: BOOLEAN;
 			identifierNumber: LONGINT;
 
+			parameterRegister: Backend.Registers;
+			parameterRegisters: LONGINT;
 			passByRegister: BOOLEAN; registerNumber,stackSize: LONGINT;
 			procedure: SyntaxTree.Procedure;
 
@@ -5637,17 +5647,22 @@ TYPE
 			firstWriteBackCall := NIL; (* reset write-back call list *)
 
 			IF procedureType.callingConvention # SyntaxTree.OberonCallingConvention THEN
-				passByRegister := system.registerParameters > 0;
+				parameterRegister := backend.GetParameterRegisters(procedureType.callingConvention);
+				IF parameterRegister = NIL THEN parameterRegisters := 0 
+				ELSE parameterRegisters := LEN(parameterRegister) 
+				END; 
+				
+				passByRegister := parameterRegisters > 0;
 				registerNumber := 0;
 				formalParameter := procedureType.lastParameter;
 				FOR i := parameters.Length() - 1 TO 0 BY -1 DO
 					actualParameter := parameters.GetExpression(i);
 					PrepareParameter(actualParameter, formalParameter);
-					IF passByRegister & (i < system.registerParameters) THEN
+					IF passByRegister & (i < parameterRegisters) THEN
 						IF ~PassInRegister(formalParameter) THEN
 							Error(actualParameter.position,"cannot be passed by register")
 						ELSE
-							PushParameter(actualParameter, formalParameter, procedureType.callingConvention, FALSE, dummy,i);
+							PushParameter(actualParameter, formalParameter, procedureType.callingConvention, FALSE, dummy,parameterRegister[i]);
 						END;
 						INC(registerNumber);
 					ELSE
@@ -5656,7 +5671,7 @@ TYPE
 					formalParameter := formalParameter.prevParameter;
 				END;
 				IF passByRegister & (registerNumber > 0) THEN
-					stackSize := ToMemoryUnits(system,system.registerParameters*addressType.sizeInBits);
+					stackSize := ToMemoryUnits(system,parameterRegisters*addressType.sizeInBits);
 					Emit(Sub(position,sp,sp,IntermediateCode.Immediate(addressType,stackSize)));
 				END;
 			ELSE
@@ -5714,8 +5729,8 @@ TYPE
 			END;
 
 			IF procedureType.callingConvention = SyntaxTree.CCallingConvention THEN
-				IF passByRegister & (registerNumber > 0) & (registerNumber < system.registerParameters) THEN (* allocated space for all registers *)
-					parametersSize := ToMemoryUnits(system,system.registerParameters*addressType.sizeInBits);
+				IF passByRegister & (registerNumber > 0) & (registerNumber < parameterRegisters) THEN (* allocated space for all registers *)
+					parametersSize := ToMemoryUnits(system,parameterRegisters*addressType.sizeInBits);
 				END;
 				size := IntermediateCode.Immediate(addressType,parametersSize);
 				Emit(Add(position,sp,sp,size));

+ 2 - 2
source/FoxIntermediateCode.Mod

@@ -1027,8 +1027,8 @@ TYPE
 	BEGIN type.length := length
 	END ToVectorType;
 
-	PROCEDURE InitRegisterClass*(VAR registerClass: RegisterClass; class: SHORTINT; number: INTEGER);
-	BEGIN registerClass.class := class; registerClass.number := number
+	PROCEDURE InitRegisterClass*(VAR registerClass: RegisterClass; class: SHORTINT; number: LONGINT);
+	BEGIN registerClass.class := class; registerClass.number := INTEGER(number)
 	END InitRegisterClass;
 
 	PROCEDURE NewType*(form: SHORTINT; sizeInBits: INTEGER): Type;

+ 1 - 1
source/FoxInterpreterBackend.Mod

@@ -377,7 +377,7 @@ TYPE
 		PROCEDURE GetSystem(): Global.System;
 		VAR system: Global.System;
 		BEGIN
-			NEW (system, 8, 8, 32, 1, 1, 1, 1, addressSize * 2,0, cooperative);
+			NEW (system, 8, 8, 32, 1, 1, 1, 1, addressSize * 2,cooperative);
 			Global.SetDefaultDeclarations(system,8);
 			Global.SetDefaultOperators(system);
 			RETURN system;

+ 3 - 2
source/FoxSyntaxTree.Mod

@@ -60,6 +60,7 @@ TYPE
 	BinaryCode*= BitSets.BitSet;
 	String*= Scanner.StringType;
 	IdentifierString*= Scanner.IdentifierString;
+	CallingConvention*= LONGINT;
 
 	(** visitor pattern implementation *)
 	(* to use this object in your implementation, copy and paste and replace "x: " by "x: SyntaxTree." *)
@@ -1701,7 +1702,7 @@ TYPE
 
 			isDelegate-,isInterrupt-,noPAF-,noReturn-: BOOLEAN;
 			pcOffset-: LONGINT; (* PC offset: used for ARM interrupt procedures *)
-			callingConvention-: LONGINT;
+			callingConvention-: CallingConvention;
 			stackAlignment-: LONGINT;
 			parameterOffset-: LONGINT; (* stack parameter offset caused by parameters on stack *)
 
@@ -1767,7 +1768,7 @@ TYPE
 		BEGIN returnParameter := parameter
 		END SetReturnParameter;
 
-		PROCEDURE SetCallingConvention*(cc: LONGINT);
+		PROCEDURE SetCallingConvention*(cc: CallingConvention);
 		BEGIN callingConvention := cc
 		END SetCallingConvention;
 

+ 1 - 1
source/FoxTRMBackend.Mod

@@ -2208,7 +2208,7 @@ TYPE
 		PROCEDURE GetSystem(): Global.System;
 		VAR system: System;
 		BEGIN
-			NEW(system, 18, 32, 32, 32, 32, 32, 32, 64(* parameter offset 0: handled locally *), 0 (* no pass of parameters in registers *) , cooperative);
+			NEW(system, 18, 32, 32, 32, 32, 32, 32, 64(* parameter offset 0: handled locally *),  cooperative);
 			Global.SetDefaultDeclarations(system,32);
 			Global.SetDefaultOperators(system);
 			RETURN system

+ 1 - 1
source/FoxTranspilerBackend.Mod

@@ -1450,7 +1450,7 @@ TYPE
 		PROCEDURE GetSystem*(): Global.System;
 		VAR system: Global.System;
 		BEGIN
-			NEW(system, 8, 8, addressSize, 8, 32, 32, 32, 64,0, FALSE);
+			NEW(system, 8, 8, addressSize, 8, 32, 32, 32, 64, FALSE);
 			Global.SetDefaultDeclarations(system,8);
 			Global.SetDefaultOperators(system);
 			RETURN system;