Browse Source

Improved and simplified parameter register handling:
- retreive parameter register from backend in intermediate backend (using type and calling convention)
- necessary because floating point parameter registers did not have the correct index

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

felixf 7 năm trước cách đây
mục cha
commit
81fc79f11e

+ 57 - 60
source/FoxAMDBackend.Mod

@@ -944,55 +944,7 @@ TYPE
 				Assembler.SetSymbol(physical,virtual.symbol.name,virtual.symbol.fingerprint,virtual.symbolOffset,virtual.offset+4*part);
 			END;
 		END GetMemory;
-
-		PROCEDURE HardwareIntegerRegister(index: LONGINT; sizeInBits: LONGINT): LONGINT;
-		BEGIN
-			index := index MOD 32;
-			sizeInBits := sizeInBits DIV 8;
-			WHILE sizeInBits > 1 DO (* jump to register section that corresponds to the number of bits *)
-				INC(index,32);
-				sizeInBits := sizeInBits DIV 2;
-			END;
-			RETURN index
-		END HardwareIntegerRegister;
-
-		PROCEDURE HardwareFloatRegister(index: LONGINT; sizeInBits: LONGINT): LONGINT;
-		BEGIN HALT(200); (* not yet implemented *)
-		END HardwareFloatRegister;
-
-		PROCEDURE GetTypedHardwareRegister(index: LONGINT; type: IntermediateCode.Type): LONGINT;
-		VAR size: LONGINT;
-		BEGIN
-			IF type.form IN IntermediateCode.Integer THEN
-				RETURN HardwareIntegerRegister(index, type.sizeInBits)
-			ELSIF type.form = IntermediateCode.Float THEN
-				RETURN HardwareFloatRegister(index, type.sizeInBits)
-			ELSE
-				HALT(100);
-			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
-			RETURN GetTypedHardwareRegister(RAX + index, type);
-			ASSERT(0 <= index); 
-			ASSERT(index <= 15);
-			RETURN physical;
-		END ParameterRegister;
-
+		
 		PROCEDURE GetRegister(CONST virtual: IntermediateCode.Operand; part:LONGINT; VAR physical: Assembler.Operand; VAR ticket: Ticket);
 		VAR type: IntermediateCode.Type; virtualRegister, tempReg: LONGINT;
 			tmp,imm: Assembler.Operand; index: LONGINT;
@@ -3204,7 +3156,8 @@ TYPE
 		bits: LONGINT;
 		traceable: BOOLEAN;
 		forceFPU: BOOLEAN;
-		winAPIRegisters, cRegisters: Backend.Registers;
+		winAPIRegisters: ARRAY 4 OF LONGINT;
+		cRegisters: ARRAY 6 OF LONGINT;
 
 		PROCEDURE &InitBackendAMD64;
 		BEGIN
@@ -3212,13 +3165,11 @@ TYPE
 			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;
@@ -3300,21 +3251,67 @@ 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;
+		(* return number of general purpose registery used as parameter register in calling convention *)
+		PROCEDURE NumberParameterRegisters*(callingConvention: SyntaxTree.CallingConvention): SIZE;
 		BEGIN
 			IF bits = 32 THEN
-				RETURN NIL;
+				RETURN 0;
 			ELSE
 				CASE callingConvention OF
-					SyntaxTree.CCallingConvention: RETURN cRegisters;
-					|SyntaxTree.WinAPICallingConvention:  RETURN winAPIRegisters;
-					|SyntaxTree.DarwinCCallingConvention: RETURN cRegisters; 
+					|SyntaxTree.WinAPICallingConvention:  RETURN 4;
+					|SyntaxTree.CCallingConvention, SyntaxTree.DarwinCCallingConvention: RETURN 6; 
 				ELSE
-					RETURN NIL;
+					RETURN 0;
 				END;
 			END
-		END GetParameterRegisters;
+		END NumberParameterRegisters;
+		
+		
+
+		(* 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 HardwareIntegerRegister(index: LONGINT; sizeInBits: LONGINT): LONGINT;
+		BEGIN
+			index := index MOD 32;
+			sizeInBits := sizeInBits DIV 8;
+			WHILE sizeInBits > 1 DO (* jump to register section that corresponds to the number of bits *)
+				INC(index,32);
+				sizeInBits := sizeInBits DIV 2;
+			END;
+			RETURN index
+		END HardwareIntegerRegister;
+
+		PROCEDURE HardwareFloatRegister(index: LONGINT; sizeInBits: LONGINT): LONGINT;
+		BEGIN 
+			ASSERT((sizeInBits = 32) OR (sizeInBits = 64));
+			RETURN XMM0 + index;
+		END HardwareFloatRegister;
+		
+		PROCEDURE ParameterRegister(callingConvention: SyntaxTree.CallingConvention;  type: IntermediateCode.Type; index: LONGINT): LONGINT;
+		VAR size: LONGINT; 
+		BEGIN
+			IF type.form IN IntermediateCode.Integer THEN
+				CASE callingConvention OF
+					|SyntaxTree.WinAPICallingConvention:  index := winAPIRegisters[index];
+					|SyntaxTree.CCallingConvention, SyntaxTree.DarwinCCallingConvention: index := cRegisters[index]
+				END;
+				RETURN HardwareIntegerRegister(RAX + index, type.sizeInBits)
+			ELSIF type.form = IntermediateCode.Float THEN
+				index := index + 1; (* start with XMM1 *)
+				RETURN HardwareFloatRegister(index, type.sizeInBits)
+			ELSE
+				HALT(100);
+			END;
+		END ParameterRegister;
 
 		PROCEDURE SupportedInstruction(CONST instruction: IntermediateCode.Instruction; VAR moduleName, procedureName: ARRAY OF CHAR): BOOLEAN;
 		BEGIN

+ 1 - 5
source/FoxBackend.Mod

@@ -6,7 +6,6 @@ IMPORT
 
 TYPE
 	SectionName = ARRAY 256 OF CHAR;
-	Registers*= POINTER TO ARRAY OF LONGINT;
 
 	Backend* = OBJECT
 	VAR
@@ -90,10 +89,7 @@ TYPE
 			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; position: Basic.Position; errorNumber: LONGINT; CONST err: ARRAY OF CHAR);
 		BEGIN

+ 7 - 9
source/FoxCodeGenerators.Mod

@@ -196,6 +196,7 @@ TYPE
 			PROCEDURE GetRegisterAllocation;
 			CONST MaxParameterRegisters=16;
 			VAR pc,i: LONGINT; parameterRegisters: ARRAY MaxParameterRegisters OF IntermediateCode.Operand;
+				parameterRegister: LONGINT;
 
 				PROCEDURE RegisterUsage(CONST instruction: IntermediateCode.Instruction);
 				VAR i: LONGINT;
@@ -206,7 +207,8 @@ TYPE
 						IF operand.register > 0 THEN
 							allocation.Use(operand.register,inPC);
 							IF operand.registerClass.class = IntermediateCode.Parameter THEN (* store recent parameter registers *)
-								parameterRegisters[operand.registerClass.number] := operand;
+								parameterRegisters[parameterRegister] := operand;
+								INC(parameterRegister);
 							END;
 						END;
 						IF operand.rule # NIL THEN
@@ -220,10 +222,11 @@ TYPE
 					Use(instruction.op2);
 					Use(instruction.op3);
 					IF instruction.opcode = IntermediateCode.call THEN (* mark all currently used parameter registers used in this instruction *)
-						FOR i := 0 TO MaxParameterRegisters-1 DO
+						FOR i := 0 TO parameterRegister-1 DO
 							Use(parameterRegisters[i]);
 							IntermediateCode.InitOperand(parameterRegisters[i]);
 						END;
+						parameterRegister := 0;
 					END;
 				END RegisterUsage;
 			BEGIN
@@ -231,6 +234,7 @@ TYPE
 				FOR i := 0 TO MaxParameterRegisters-1 DO
 					IntermediateCode.InitOperand(parameterRegisters[i]);
 				END;
+				parameterRegister := 0;
 				FOR pc := 0 TO in.pc-1 DO
 					inPC := pc;
 					RegisterUsage(in.instructions[pc]);
@@ -902,12 +906,6 @@ TYPE
 		BEGIN HALT(100) (* abstract *)
 		END ExchangeTickets;
 
-		PROCEDURE ParameterRegister*(CONST type: IntermediateCode.Type; number: LONGINT): LONGINT;
-		BEGIN HALT(100) (* abstract *)
-		END ParameterRegister;
-
-
-
 		(*---------------------------- ticket handling and register allocation ----------------------------*)
 
 		(* Spill register of a ticket, if any *)
@@ -1123,7 +1121,7 @@ TYPE
 				GetPartType(type,part,partType);
 				IF partType.form # IntermediateCode.Undefined THEN
 					IF class.class = IntermediateCode.Parameter THEN
-						AllocateThis(ParameterRegister(partType, class.number));
+						AllocateThis(class.number);
 					ELSE
 						MapTicket(partType,lastuse)
 					END;

+ 20 - 17
source/FoxIntermediateBackend.Mod

@@ -589,8 +589,7 @@ TYPE
 			cc: LONGINT;
 			cellType: SyntaxTree.CellType;
 			registerNumber: LONGINT;
-			registerParameter: Backend.Registers;
-			registerParameters: LONGINT;
+			registerParameters: SIZE;
 			registerClass: IntermediateCode.RegisterClass;
 			type: IntermediateCode.Type;
 			formalParameter: SyntaxTree.Parameter;
@@ -739,11 +738,8 @@ TYPE
 					*)
 
 					IF procedureType.callingConvention # SyntaxTree.OberonCallingConvention THEN
-						registerParameter := backend.GetParameterRegisters(procedureType.callingConvention);
+						registerParameters := backend.NumberParameterRegisters(procedureType.callingConvention);
 						
-						IF registerParameter = NIL THEN registerParameters := 0 
-						ELSE registerParameters := LEN(registerParameter) 
-						END;
 						
 						(* assumption: registers are passed left to right and left parameters are in registers *)
 						formalParameter := procedureType.firstParameter;
@@ -751,13 +747,13 @@ TYPE
 							IF ~PassInRegister(formalParameter) THEN
 								Error(formalParameter.position,"Calling convention error: cannot be passed as register");
 							ELSE
-								IntermediateCode.InitRegisterClass(registerClass, IntermediateCode.Parameter, registerParameter[registerNumber]);
 								IF formalParameter.type.IsRecordType() THEN
 									ASSERT (formalParameter.kind IN {SyntaxTree.VarParameter, SyntaxTree.ConstParameter});
 									type := addressType;
 								ELSE
 									type := GetType(system, formalParameter.type);
 								END;
+								IntermediateCode.InitParameterRegisterClass(registerClass, backend.ParameterRegister(procedureType.callingConvention, type, registerNumber));
 								src := IntermediateCode.Register(type, registerClass, implementationVisitor.AcquireRegister(type, registerClass));
 								IntermediateCode.InitMemory(dest,type,implementationVisitor.sp,ToMemoryUnits(system,formalParameter.offsetInBits - system.addressSize));
 								ir.Emit(Mov(Basic.invalidPosition,dest, src));
@@ -4638,7 +4634,7 @@ TYPE
 			VAR registerClass: IntermediateCode.RegisterClass; parameterRegister: IntermediateCode.Operand;
 			BEGIN
 				IF numberRegister >= 0 THEN
-					IntermediateCode.InitRegisterClass(registerClass, IntermediateCode.Parameter, SHORT(numberRegister));
+					IntermediateCode.InitParameterRegisterClass(registerClass, backend.ParameterRegister(callingConvention,op.type,numberRegister));
 					IntermediateCode.InitRegister(parameterRegister, op.type, registerClass, AcquireRegister(op.type, registerClass));
 					Emit(Mov(position,parameterRegister, op));
 				ELSE
@@ -4646,7 +4642,6 @@ TYPE
 				END
 			END Pass;
 
-
 			PROCEDURE PushArrayLens(formalType,actualType: SyntaxTree.Type; dim: LONGINT);
 			VAR tmp: IntermediateCode.Operand; actualArrayBase: SyntaxTree.Type;
 			BEGIN
@@ -4774,7 +4769,7 @@ TYPE
 						PutMathArrayField(arrayDestinationTag,nil,MathFlagsOffset);
 
 					(* case 1d 
-						P(...,T,...) push: process left arguments, create array descriptor with given number of dimensions from T on stack						
+						P(...,T,...) push: process left arguments, create array descriptor with given s of dimensions from T on stack						
 						+ case 1e
 						P(.. PT() ... ); 
 					*)
@@ -5557,8 +5552,7 @@ TYPE
 			isCallOfDynamicOperator, hasDynamicOperands: BOOLEAN;
 			identifierNumber: LONGINT;
 
-			parameterRegister: Backend.Registers;
-			parameterRegisters: LONGINT;
+			parameterRegisters: SIZE;
 			passByRegister: BOOLEAN; registerNumber,stackSize: LONGINT;
 			procedure: SyntaxTree.Procedure;
 
@@ -5801,10 +5795,7 @@ TYPE
 			firstWriteBackCall := NIL; (* reset write-back call list *)
 
 			IF procedureType.callingConvention # SyntaxTree.OberonCallingConvention THEN
-				parameterRegister := backend.GetParameterRegisters(procedureType.callingConvention);
-				IF parameterRegister = NIL THEN parameterRegisters := 0 
-				ELSE parameterRegisters := LEN(parameterRegister) 
-				END; 
+				parameterRegisters := backend.NumberParameterRegisters(procedureType.callingConvention);
 				
 				passByRegister := parameterRegisters > 0;
 				registerNumber := 0;
@@ -5816,7 +5807,7 @@ TYPE
 						IF ~PassInRegister(formalParameter) THEN
 							Error(actualParameter.position,"cannot be passed by register")
 						ELSE
-							PushParameter(actualParameter, formalParameter, procedureType.callingConvention, FALSE, dummy,parameterRegister[i]);
+							PushParameter(actualParameter, formalParameter, procedureType.callingConvention, FALSE, dummy,i);
 						END;
 						INC(registerNumber);
 					ELSE
@@ -13670,6 +13661,18 @@ TYPE
 			SetRuntimeModuleName(DefaultRuntimeModuleName);
 			SetTraceModuleName(DefaultTraceModuleName);
 		END InitIntermediateBackend;
+		
+		(* must be overwritten by actual backend, if parameter registers should be used *)
+		PROCEDURE NumberParameterRegisters*(callingConvention: SyntaxTree.CallingConvention): SIZE;
+		BEGIN
+			RETURN 0; (* default case: no parameter registers *)
+		END NumberParameterRegisters;
+
+		(* must be overwritten by actual backend, if parameter registers should be used *)
+		PROCEDURE ParameterRegister*(callingConvention: SyntaxTree.CallingConvention; type: IntermediateCode.Type; index: LONGINT): LONGINT;
+		BEGIN
+			HALT(100); (* abstract *)
+		END ParameterRegister;
 
 		PROCEDURE GenerateIntermediate*(x: SyntaxTree.Module; supportedInstruction: SupportedInstructionProcedure; supportedImmediate: SupportedImmediateProcedure): Sections.Module;
 		VAR

+ 5 - 1
source/FoxIntermediateCode.Mod

@@ -71,7 +71,7 @@ CONST
 	NofOpcodes*= 40;
 
 	NotYetCalculatedSize = -2;
-
+	
 TYPE
 	Type*=RECORD
 		form-: SHORTINT; (* SignedInteger, UnsignedInteger or Float *)
@@ -1092,6 +1092,10 @@ TYPE
 	BEGIN registerClass.class := class; registerClass.number := INTEGER(number)
 	END InitRegisterClass;
 
+	PROCEDURE InitParameterRegisterClass*(VAR registerClass: RegisterClass; number: LONGINT);
+	BEGIN registerClass.class := Parameter; registerClass.number := INTEGER(number)
+	END InitParameterRegisterClass;
+	
 	PROCEDURE NewType*(form: SHORTINT; sizeInBits: INTEGER): Type;
 	VAR type: Type;
 	BEGIN InitType(type, form, sizeInBits); RETURN type