Переглянути джерело

made initial and final section "nopaf"
added checks for unused paf

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

felixf 6 роки тому
батько
коміт
e703a7f865
2 змінених файлів з 31 додано та 14 видалено
  1. 9 3
      source/FoxIntermediateBackend.Mod
  2. 22 11
      source/FoxSemanticChecker.Mod

+ 9 - 3
source/FoxIntermediateBackend.Mod

@@ -665,7 +665,6 @@ TYPE
 
 			IF scope.body # NIL THEN
 
-
 				IF implementationVisitor.emitLabels THEN ir.Emit(LabelInstruction(scope.body.position)) END;
 
 				IF ~inline THEN
@@ -759,6 +758,7 @@ TYPE
 				END;
 
 				IF ~inline  & ~(procedureType.noPAF) & ~x.isEntry & ~x.isExit THEN
+					(*
 					IF ToMemoryUnits(system,stackSize) > 4*1024-256 THEN (* stack frame potentially larger than page size *) (*! get page size from backend *)
 						(*! unnecessary with new implementation of ENTER -- should potentially be called by backend
 						IF implementationVisitor.GetRuntimeProcedure(implementationVisitor.builtinsModuleName,"EnsureAllocatedStack",procedure,TRUE) THEN
@@ -769,7 +769,7 @@ TYPE
 						END;
 						*)
 					END;
-
+					*)
 
 					ir.EmitAt(pc(*+2*),implementationVisitor.Enter(x.position,callingConvention,ToMemoryUnits(system,stackSize))); (*!!*)
 
@@ -867,6 +867,8 @@ TYPE
 							END;
 						END;
 					END
+				ELSIF ~inline THEN
+					ir.Emit(Nop(x.position)); (* jump label *)
 				END;
 			ELSE (* force body for procedures *)
 				implementationVisitor.EmitEnter(ir, x.position,x,callingConvention,0);
@@ -7586,7 +7588,7 @@ TYPE
 		**)
 		PROCEDURE GetTemporaryVariable(type: SyntaxTree.Type; register: BOOLEAN; untraced: BOOLEAN): SyntaxTree.Variable;
 		VAR name: SyntaxTree.Identifier;  variable, v: SyntaxTree.Variable;
-		scope: SyntaxTree.Scope; duplicate: BOOLEAN; offset, index: LONGINT;
+			scope: SyntaxTree.Scope; duplicate: BOOLEAN; offset, index: LONGINT;
 		BEGIN
 			IF ~register THEN
 				v := temporaries.GetFreeVariable(type, untraced, index);
@@ -7594,6 +7596,9 @@ TYPE
 				index := temporaries.registerIndex; INC(temporaries.registerIndex);
 			END;
 			scope := currentScope;
+			IF (scope IS SyntaxTree.ProcedureScope) & (scope(SyntaxTree.ProcedureScope).ownerProcedure.type(SyntaxTree.ProcedureType).noPAF) THEN
+				Error(scope(SyntaxTree.ProcedureScope).ownerProcedure.position,"implementation restriction: cannot allocate temporary variable in procedure without activation frame");
+			END;
 			(*
 			v := NIL; (* disable free variable managemenet for the time being *)
 			*)
@@ -7604,6 +7609,7 @@ TYPE
 			variable.SetAccess(SyntaxTree.Hidden);
 			variable.SetUntraced(untraced);
 
+
 			IF v = NIL THEN
 				temporaries.AddVariable(variable);
 

+ 22 - 11
source/FoxSemanticChecker.Mod

@@ -6506,8 +6506,10 @@ TYPE
 				IF HasValue(modifiers, Global.NamePcOffset, position, value) THEN procedureType.SetPcOffset(LONGINT(value)) (* TODO: fix explicit integer truncation *) END;
 
 				IF HasFlag(modifiers,Global.NameNoPAF,position) THEN procedureType.SetNoPAF(TRUE) END;
-				IF HasFlag(modifiers, Global.NameEntry,position) THEN procedure.SetEntry(TRUE)
-				ELSIF (procedure.scope IS SyntaxTree.ModuleScope) & HasFlag(modifiers, Global.NameExit, position) THEN procedure.SetExit(TRUE)
+				IF (procedure.scope IS SyntaxTree.ModuleScope) THEN
+					IF HasFlag(modifiers, Global.NameEntry,position) THEN procedure.SetEntry(TRUE); procedureType.SetNoPAF(TRUE);
+					ELSIF HasFlag(modifiers, Global.NameExit, position) THEN procedure.SetExit(TRUE); procedureType.SetNoPAF(TRUE);
+					END;
 				END;
 				IF HasValue(modifiers,Global.NameAligned,position,value) THEN procedure.SetAlignment(FALSE,LONGINT(value)) (* TODO: fix explicit integer truncation *)
 				ELSIF HasValue(modifiers,Global.NameFixed,position,value) THEN procedure.SetAlignment(TRUE,LONGINT(value)) (* TODO: fix explicit integer truncation *)
@@ -7867,14 +7869,16 @@ TYPE
 		 move implementation checker to a separate object ? *)
 		PROCEDURE Implementation(scope: SyntaxTree.Scope);
 		VAR prevScope: SyntaxTree.Scope; procedure: SyntaxTree.Procedure; prevIsRealtime, prevIsBodyProcedure, prevIsCellNet: BOOLEAN;
+			procedureType: SyntaxTree.ProcedureType;
 		BEGIN
 			prevIsRealtime := currentIsRealtime;
 			prevIsBodyProcedure := currentIsBodyProcedure;
 			prevIsCellNet := currentIsCellNet;
 			prevScope := currentScope;
 			currentScope := scope;
-			IF (scope IS SyntaxTree.ProcedureScope) THEN
-				procedure := scope(SyntaxTree.ProcedureScope).ownerProcedure;
+			WITH scope: SyntaxTree.ProcedureScope DO
+				procedure := scope.ownerProcedure;
+				procedureType := procedure.type(SyntaxTree.ProcedureType);
 				currentIsBodyProcedure := currentIsBodyProcedure OR procedure.isBodyProcedure;
 				currentIsRealtime := currentIsRealtime OR procedure.type.isRealtime;
 				currentIsCellNet := InCellNetScope(procedure.scope) OR cellsAreObjects;
@@ -7883,15 +7887,22 @@ TYPE
 					Warning(procedure.position,"unsupported inline procedure - must be assembler code")
 				END;
 				*)
-			END;
-			IF (scope IS SyntaxTree.ProcedureScope) & (scope(SyntaxTree.ProcedureScope).body # NIL) (* & ~(scope IS SyntaxTree.RecordScope) *) THEN
+				IF scope.body # NIL THEN
 				(* module body, record bodies are wrapped into an artifical procedure *)
-				IF (phase = InlinePhase) & (IsOberonInline(procedure)) THEN
-					Body(scope(SyntaxTree.ProcedureScope).body)
-				ELSIF (phase = ImplementationPhase) & ~IsOberonInline(procedure) THEN
-					Body(scope(SyntaxTree.ProcedureScope).body)
+					IF (phase = InlinePhase) & (IsOberonInline(procedure)) THEN
+						Body(scope(SyntaxTree.ProcedureScope).body)
+					ELSIF (phase = ImplementationPhase) & ~IsOberonInline(procedure) THEN
+						Body(scope(SyntaxTree.ProcedureScope).body)
+					END;
 				END;
-				
+				IF procedureType.noPAF THEN 
+					IF scope.firstVariable # NIL THEN
+						Error(procedure.position, "forbidden variable in procedure without activation frame");
+					ELSIF procedureType.firstParameter # NIL THEN
+						Error(procedure.position, "forbidden parameter in procedure without activation frame");
+					END;
+				END;
+			ELSE				
 			END;
 			currentScope := prevScope;
 			currentIsRealtime := prevIsRealtime;