2
0
Эх сурвалжийг харах

patched code for dynamic operator overloading. Todo: improve reference to parameters.

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6633 8c9fc860-2736-0410-a75d-ab315db34111
felixf 9 жил өмнө
parent
commit
6e4b6fada4

+ 90 - 70
source/FoxIntermediateBackend.Mod

@@ -5510,7 +5510,7 @@ TYPE
 				ASSERT(procedureType.callingConvention = SyntaxTree.OberonCallingConvention);
 
 				(* check if a dynamic operator call should be performed *)
-				isCallOfDynamicOperator := x.left(SyntaxTree.SymbolDesignator).symbol(SyntaxTree.Operator).isDynamic
+				isCallOfDynamicOperator := x.left(SyntaxTree.SymbolDesignator).symbol(SyntaxTree.Operator).isDynamic;
 			ELSE
 				isCallOfDynamicOperator := FALSE
 			END;
@@ -5551,75 +5551,7 @@ TYPE
 				symbol := x.left(SyntaxTree.SymbolDesignator).symbol;
 			END;
 
-			IF isCallOfDynamicOperator & hasDynamicOperands THEN
-				IF dump # NIL THEN dump.String("++++++++++ dynamic operator call ++++++++++"); dump.Ln; dump.Update END; (* TENTATIVE *)
-				(* push ID *)
-				(* IF dump # NIL THEN dump.String("push ID"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
-				ASSERT(x.left IS SyntaxTree.SymbolDesignator);
-				identifierNumber := Global.GetSymbol(module.module.case, x.left(SyntaxTree.SymbolDesignator).symbol.name);
-				Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), identifierNumber)));
-
-				formalParameter := procedureType.firstParameter;
-				FOR i := 0 TO parameters.Length() - 1 DO
-					IF formalParameter.access # SyntaxTree.Hidden THEN
-						ASSERT(i < 2);
-						IF IsStrictlyPointerToRecord(formalParameter.type) THEN
-							(* push pointer *)
-							(* IF dump # NIL THEN dump.String("push pointer"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
-							IF formalParameter.kind = SyntaxTree.VarParameter THEN
-								(* add dereference *)
-								(* IF dump # NIL THEN dump.String("dereference pointer"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
-								ReleaseIntermediateOperand(parameterBackups[i]);
-								MakeMemory(parameterBackups[i], parameterBackups[i], addressType, 0)
-							END;
-							Emit(Push(position,parameterBackups[i]));
-							ReleaseIntermediateOperand(parameterBackups[i]);
-
-							(* push typetag *)
-							(* IF dump # NIL THEN dump.String("push typetag"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
-							recordType := formalParameter.type.resolved(SyntaxTree.PointerType).pointerBase.resolved(SyntaxTree.RecordType);
-							arg := TypeDescriptorAdr(recordType);
-							IF ~newObjectFile THEN IntermediateCode.MakeMemory(arg, addressType) END;
-							Emit(Push(position,arg));
-						ELSE
-							(* push 'NonPointer' *)
-							(* IF dump # NIL THEN dump.String("push 'NonPointer'"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
-							Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), NonPointer)));
-
-							(* push fingerprint *)
-							(* IF dump # NIL THEN dump.String("push fingerprint"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
-							fingerPrint := fingerPrinter.TypeFP(formalParameter.type.resolved);
-							Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), fingerPrint.shallow))) (* TODO: push the type's fingerprint *)
-						END
-					END;
-					formalParameter := formalParameter.nextParameter
-				END;
-
-				(* for unary operators: complete the information for the second parameter *)
-				IF procedureType.numberParameters < 2 THEN
-					(* push 'NonPointer' *)
-					(* IF dump # NIL THEN dump.String("push 'NonPointer'"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
-					Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), NonPointer)));
-
-					(* push 'NoType' *)
-					(* IF dump # NIL THEN dump.String("push 'NoType'"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
-					Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), NoType)));
-				END;
-
-				(* call operator selection procedure *)
-				IF GetRuntimeProcedure("FoxOperatorRuntime", "SelectOperator", operatorSelectionProcedure, TRUE) THEN
-					StaticCallOperand(operatorSelectionProcedureOperand, operatorSelectionProcedure);
-					Emit(Call(position,operatorSelectionProcedureOperand.op, ProcedureParametersSize(system, operatorSelectionProcedure)));
-					ReleaseOperand(operatorSelectionProcedureOperand);
-
-					(* use the address that the operator selection procedure returned as the target address of the call *)
-					InitOperand(operand, ModeValue);
-					operand.op := IntermediateCode.Register(addressType, IntermediateCode.GeneralPurposeRegister, AcquireRegister(addressType,IntermediateCode.GeneralPurposeRegister));
-					Emit(Result(position,operand.op))
-				END
-			ELSE
-				Evaluate(x.left, operand)
-			END;
+			Evaluate(x.left, operand);
 
 			IF symbol IS SyntaxTree.Procedure THEN
 				IF x.left IS SyntaxTree.SupercallDesignator THEN
@@ -5727,6 +5659,94 @@ TYPE
 			ELSIF (symbol IS SyntaxTree.Variable) OR (symbol IS SyntaxTree.Parameter) THEN
 				parametersSize := ParametersSize(system,procedureType,FALSE);
 			END;
+
+
+			IF isCallOfDynamicOperator & hasDynamicOperands THEN
+			(*
+				dynamic operator overloading:
+				first push parameters, regularly:
+				[self]
+				par1
+				par2 
+				
+				then push parameters for GetOperator
+				identifier
+				ptr1
+				tag
+				ptr2
+				tag
+				call GetOperatorRuntimeProc
+				
+				call Operator
+			*)
+				IF dump # NIL THEN dump.String("++++++++++ dynamic operator call ++++++++++"); dump.Ln; dump.Update END; (* TENTATIVE *)
+				(* push ID *)
+				(* IF dump # NIL THEN dump.String("push ID"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
+				ASSERT(x.left IS SyntaxTree.SymbolDesignator);
+				identifierNumber := Global.GetSymbol(module.module.case, x.left(SyntaxTree.SymbolDesignator).symbol.name);
+				Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), identifierNumber)));
+
+				formalParameter := procedureType.firstParameter;
+				FOR i := 0 TO parameters.Length() - 1 DO
+					IF formalParameter.access # SyntaxTree.Hidden THEN
+						ASSERT(i < 2);
+						IF IsStrictlyPointerToRecord(formalParameter.type) THEN
+							(* push pointer *)
+							(* IF dump # NIL THEN dump.String("push pointer"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
+							IF formalParameter.kind = SyntaxTree.VarParameter THEN
+								(* add dereference *)
+								(* IF dump # NIL THEN dump.String("dereference pointer"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
+							(*! better: do refer to stack above than using parameter backups !!*)
+								ReleaseIntermediateOperand(parameterBackups[i]);
+								MakeMemory(parameterBackups[i], parameterBackups[i], addressType, 0)
+							END;
+							Emit(Push(position,parameterBackups[i]));
+							ReleaseIntermediateOperand(parameterBackups[i]);
+
+							(* push typetag *)
+							(* IF dump # NIL THEN dump.String("push typetag"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
+							recordType := formalParameter.type.resolved(SyntaxTree.PointerType).pointerBase.resolved(SyntaxTree.RecordType);
+							arg := TypeDescriptorAdr(recordType);
+							IF ~newObjectFile THEN IntermediateCode.MakeMemory(arg, addressType) END;
+							Emit(Push(position,arg));
+						ELSE
+							(* push 'NonPointer' *)
+							(* IF dump # NIL THEN dump.String("push 'NonPointer'"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
+							Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), NonPointer)));
+
+							(* push fingerprint *)
+							(* IF dump # NIL THEN dump.String("push fingerprint"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
+							fingerPrint := fingerPrinter.TypeFP(formalParameter.type.resolved);
+							Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), fingerPrint.shallow))) (* TODO: push the type's fingerprint *)
+						END
+					END;
+					formalParameter := formalParameter.nextParameter
+				END;
+
+				(* for unary operators: complete the information for the second parameter *)
+				IF procedureType.numberParameters < 2 THEN
+					(* push 'NonPointer' *)
+					(* IF dump # NIL THEN dump.String("push 'NonPointer'"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
+					Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), NonPointer)));
+
+					(* push 'NoType' *)
+					(* IF dump # NIL THEN dump.String("push 'NoType'"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
+					Emit(Push(position,IntermediateCode.Immediate(IntermediateCode.GetType(system, system.longintType), NoType)));
+				END;
+
+				(* call operator selection procedure *)
+				IF GetRuntimeProcedure("FoxOperatorRuntime", "SelectOperator", operatorSelectionProcedure, TRUE) THEN
+					StaticCallOperand(operatorSelectionProcedureOperand, operatorSelectionProcedure);
+					Emit(Call(position,operatorSelectionProcedureOperand.op, ProcedureParametersSize(system, operatorSelectionProcedure)));
+					ReleaseOperand(operatorSelectionProcedureOperand);
+
+					(* use the address that the operator selection procedure returned as the target address of the call *)
+					InitOperand(operand, ModeValue);
+					operand.op := IntermediateCode.Register(addressType, IntermediateCode.GeneralPurposeRegister, AcquireRegister(addressType,IntermediateCode.GeneralPurposeRegister));
+					Emit(Result(position,operand.op))
+				END
+			END;
+
 						
 			ReleaseParameterRegisters();
 			IF (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) OR SysvABI(procedureType.callingConvention) THEN