浏览代码

Added Platform Calling Convention
(Portability of libraries between different host OS such as Windows/Linux

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

felixf 7 年之前
父节点
当前提交
d7e0caff9c
共有 4 个文件被更改,包括 118 次插入92 次删除
  1. 3 1
      source/FoxGlobal.Mod
  2. 112 91
      source/FoxIntermediateBackend.Mod
  3. 2 0
      source/FoxSemanticChecker.Mod
  4. 1 0
      source/FoxSyntaxTree.Mod

+ 3 - 1
source/FoxGlobal.Mod

@@ -8,6 +8,7 @@ CONST
 	(* system flag names *)
 	(* system flag names *)
 	StringWinAPI* = "WINAPI";
 	StringWinAPI* = "WINAPI";
 	StringC* = "C";
 	StringC* = "C";
+	StringPlatformCC* = "PlatformCC";
 	StringMovable*="MOVABLE";
 	StringMovable*="MOVABLE";
 	StringUntraced* = "UNTRACED";
 	StringUntraced* = "UNTRACED";
 	StringDelegate* = "DELEGATE";
 	StringDelegate* = "DELEGATE";
@@ -189,7 +190,7 @@ VAR
 	(* names *)
 	(* names *)
 	SelfParameterName-,ReturnParameterName-,SystemName-,systemName-,PointerReturnName-, ResultName-,
 	SelfParameterName-,ReturnParameterName-,SystemName-,systemName-,PointerReturnName-, ResultName-,
 	A2Name-,ArrayBaseName-, ComplexNumbersName-, RecordBodyName-,ModuleBodyName-,
 	A2Name-,ArrayBaseName-, ComplexNumbersName-, RecordBodyName-,ModuleBodyName-,
-	NameWinAPI-,NameC-,NameMovable-,NameUntraced-,NameDelegate-,NameInterrupt-, NamePcOffset-, NameNoPAF-,NameEntry-, NameExit-, NameFixed-,NameFictive-, NameAligned-,NameStackAligned-,
+	NameWinAPI-,NameC-,NamePlatformCC-,NameMovable-,NameUntraced-,NameDelegate-,NameInterrupt-, NamePcOffset-, NameNoPAF-,NameEntry-, NameExit-, NameFixed-,NameFictive-, NameAligned-,NameStackAligned-,
 	NameExclusive-,NameActive-,NamePriority-,NameSafe-,NameRealtime-, NameDynamic-, NameFingerprint-, NameDataMemorySize-, NameCodeMemorySize-
 	NameExclusive-,NameActive-,NamePriority-,NameSafe-,NameRealtime-, NameDynamic-, NameFingerprint-, NameDataMemorySize-, NameCodeMemorySize-
 	, NameChannelWidth-, NameChannelDepth-, NameChannelModule-, NameVector-, NameFloatingPoint-, NameNoMul-,NameNonBlockingIO-, NameTRM-, NameTRMS-, NameEngine-, NameFinal-, NameAbstract-,
 	, NameChannelWidth-, NameChannelDepth-, NameChannelModule-, NameVector-, NameFloatingPoint-, NameNoMul-,NameNonBlockingIO-, NameTRM-, NameTRMS-, NameEngine-, NameFinal-, NameAbstract-,
 	NameBackend-, NameRuntime-, NameFrequencyDivider-, NameRegister-,NameNoReturn-,NamePlain-,NameUnsafe-,NameDisposable-,NameUnchecked-,NameUncooperative-: SyntaxTree.Identifier;
 	NameBackend-, NameRuntime-, NameFrequencyDivider-, NameRegister-,NameNoReturn-,NamePlain-,NameUnsafe-,NameDisposable-,NameUnchecked-,NameUncooperative-: SyntaxTree.Identifier;
@@ -1736,6 +1737,7 @@ TYPE
 
 
 		NameWinAPI := SyntaxTree.NewIdentifier(StringWinAPI);
 		NameWinAPI := SyntaxTree.NewIdentifier(StringWinAPI);
 		NameC := SyntaxTree.NewIdentifier(StringC);
 		NameC := SyntaxTree.NewIdentifier(StringC);
+		NamePlatformCC := SyntaxTree.NewIdentifier(StringPlatformCC);
 		NameMovable := SyntaxTree.NewIdentifier(StringMovable);
 		NameMovable := SyntaxTree.NewIdentifier(StringMovable);
 		NameUntraced := SyntaxTree.NewIdentifier(StringUntraced);
 		NameUntraced := SyntaxTree.NewIdentifier(StringUntraced);
 		NameDelegate := SyntaxTree.NewIdentifier(StringDelegate);
 		NameDelegate := SyntaxTree.NewIdentifier(StringDelegate);

+ 112 - 91
source/FoxIntermediateBackend.Mod

@@ -112,6 +112,10 @@ CONST
 		
 		
 		WarningDynamicLoading = FALSE;
 		WarningDynamicLoading = FALSE;
 		
 		
+		SysvABI = {SyntaxTree.CCallingConvention, SyntaxTree.DarwinCCallingConvention}; 
+		SysvABIorWINAPI = {SyntaxTree.CCallingConvention, SyntaxTree.DarwinCCallingConvention, SyntaxTree.WinAPICallingConvention}; 
+		
+	
 TYPE
 TYPE
 	Position=SyntaxTree.Position;
 	Position=SyntaxTree.Position;
 	SupportedInstructionProcedure* = PROCEDURE {DELEGATE} (CONST instr: IntermediateCode.Instruction; VAR moduleName,procedureName: ARRAY OF CHAR): BOOLEAN;
 	SupportedInstructionProcedure* = PROCEDURE {DELEGATE} (CONST instr: IntermediateCode.Instruction; VAR moduleName,procedureName: ARRAY OF CHAR): BOOLEAN;
@@ -576,7 +580,6 @@ TYPE
 			END;
 			END;
 		END Parameters;
 		END Parameters;
 
 
-
 		PROCEDURE Procedure(x: SyntaxTree.Procedure);
 		PROCEDURE Procedure(x: SyntaxTree.Procedure);
 		VAR scope: SyntaxTree.ProcedureScope;
 		VAR scope: SyntaxTree.ProcedureScope;
 			prevScope: SyntaxTree.Scope;
 			prevScope: SyntaxTree.Scope;
@@ -710,9 +713,9 @@ TYPE
 				END;
 				END;
 			END;
 			END;
 
 
-			cc := procedureType.callingConvention;
+			cc := backend.CallingConvention(procedureType.callingConvention);
 			IF cc = SyntaxTree.WinAPICallingConvention THEN
 			IF cc = SyntaxTree.WinAPICallingConvention THEN
-				parametersSize := ProcedureParametersSize(backend.system,x);
+				parametersSize := ProcedureParametersSize(backend.system,x, cc);
 			ELSE
 			ELSE
 				parametersSize := 0;
 				parametersSize := 0;
 			END;
 			END;
@@ -738,13 +741,13 @@ TYPE
 					ir.Emit(Nop(position)); (* placeholder for fill *)
 					ir.Emit(Nop(position)); (* placeholder for fill *)
 					*)
 					*)
 
 
-					IF (procedureType.callingConvention # SyntaxTree.OberonCallingConvention) & (~SysvABI(procedureType.callingConvention) OR (system.addressSize # 64)) THEN
-						registerParameters := backend.NumberParameterRegisters(procedureType.callingConvention);
+					IF (cc # SyntaxTree.OberonCallingConvention) & (~(cc IN SysvABI) OR (system.addressSize # 64)) THEN
+						registerParameters := backend.NumberParameterRegisters(cc);
 
 
 						(* assumption: registers are passed left to right and left parameters are in registers *)
 						(* assumption: registers are passed left to right and left parameters are in registers *)
 						formalParameter := procedureType.firstParameter;
 						formalParameter := procedureType.firstParameter;
 						WHILE (formalParameter # NIL) & (registerNumber < registerParameters) DO
 						WHILE (formalParameter # NIL) & (registerNumber < registerParameters) DO
-							IF ~PassInRegister(formalParameter) THEN
+							IF ~PassInRegister(formalParameter, cc) THEN
 								Error(formalParameter.position,"Calling convention error: cannot be passed as register");
 								Error(formalParameter.position,"Calling convention error: cannot be passed as register");
 							ELSE
 							ELSE
 								IF formalParameter.type.IsRecordType() THEN
 								IF formalParameter.type.IsRecordType() THEN
@@ -753,7 +756,7 @@ TYPE
 								ELSE
 								ELSE
 									type := GetType(system, formalParameter.type);
 									type := GetType(system, formalParameter.type);
 								END;
 								END;
-								IntermediateCode.InitParameterRegisterClass(registerClass, backend.ParameterRegister(procedureType.callingConvention, type, registerNumber));
+								IntermediateCode.InitParameterRegisterClass(registerClass, backend.ParameterRegister(cc, type, registerNumber));
 								src := IntermediateCode.Register(type, registerClass, implementationVisitor.AcquireRegister(type, registerClass));
 								src := IntermediateCode.Register(type, registerClass, implementationVisitor.AcquireRegister(type, registerClass));
 								IntermediateCode.InitMemory(dest,type,implementationVisitor.sp,ToMemoryUnits(system,formalParameter.offsetInBits - system.addressSize));
 								IntermediateCode.InitMemory(dest,type,implementationVisitor.sp,ToMemoryUnits(system,formalParameter.offsetInBits - system.addressSize));
 								ir.Emit(Mov(Basic.invalidPosition,dest, src));
 								ir.Emit(Mov(Basic.invalidPosition,dest, src));
@@ -769,13 +772,13 @@ TYPE
 					END;
 					END;
 					pc := ir.pc-1;
 					pc := ir.pc-1;
 
 
-					IF SysvABI(procedureType.callingConvention) & (system.addressSize = 64) THEN
-						registerParameters := backend.NumberParameterRegisters(procedureType.callingConvention);
+					IF (cc IN SysvABI) & (system.addressSize = 64) THEN
+						registerParameters := backend.NumberParameterRegisters(cc);
 
 
 						(* assumption: registers are passed left to right and left parameters are in registers *)
 						(* assumption: registers are passed left to right and left parameters are in registers *)
 						formalParameter := procedureType.firstParameter;
 						formalParameter := procedureType.firstParameter;
 						WHILE (formalParameter # NIL) & (registerNumber < registerParameters) DO
 						WHILE (formalParameter # NIL) & (registerNumber < registerParameters) DO
-							IF ~PassInRegister(formalParameter) THEN
+							IF ~PassInRegister(formalParameter, cc) THEN
 								Error(formalParameter.position,"Calling convention error: cannot be passed as register");
 								Error(formalParameter.position,"Calling convention error: cannot be passed as register");
 							ELSE
 							ELSE
 								IF formalParameter.type.IsRecordType() THEN
 								IF formalParameter.type.IsRecordType() THEN
@@ -784,7 +787,7 @@ TYPE
 								ELSE
 								ELSE
 									type := GetType(system, formalParameter.type);
 									type := GetType(system, formalParameter.type);
 								END;
 								END;
-								IntermediateCode.InitParameterRegisterClass(registerClass, backend.ParameterRegister(procedureType.callingConvention, type, registerNumber));
+								IntermediateCode.InitParameterRegisterClass(registerClass, backend.ParameterRegister(cc, type, registerNumber));
 								src := IntermediateCode.Register(type, registerClass, implementationVisitor.AcquireRegister(type, registerClass));
 								src := IntermediateCode.Register(type, registerClass, implementationVisitor.AcquireRegister(type, registerClass));
 								implementationVisitor.currentScope := currentScope;
 								implementationVisitor.currentScope := currentScope;
 								variable := implementationVisitor.GetTemporaryVariable(formalParameter.type,FALSE,FALSE);
 								variable := implementationVisitor.GetTemporaryVariable(formalParameter.type,FALSE,FALSE);
@@ -800,7 +803,7 @@ TYPE
 
 
 				END;
 				END;
 
 
-				implementationVisitor.tagsAvailable := procedureType.callingConvention = SyntaxTree.OberonCallingConvention;
+				implementationVisitor.tagsAvailable := cc = SyntaxTree.OberonCallingConvention;
 
 
 				implementationVisitor.Body(scope.body,currentScope,ir,isModuleBody);
 				implementationVisitor.Body(scope.body,currentScope,ir,isModuleBody);
 
 
@@ -844,8 +847,8 @@ TYPE
 						*)
 						*)
 					END;
 					END;
 
 
-					IF procedureType.callingConvention = SyntaxTree.WinAPICallingConvention THEN
-						parametersSize := ProcedureParametersSize(backend.system,x);
+					IF cc = SyntaxTree.WinAPICallingConvention THEN
+						parametersSize := ProcedureParametersSize(backend.system,x, cc);
 					ELSE
 					ELSE
 						parametersSize := 0;
 						parametersSize := 0;
 					END;
 					END;
@@ -1657,7 +1660,7 @@ TYPE
 						call.Resolve(section.pc);
 						call.Resolve(section.pc);
 						Emit(Push(Basic.invalidPosition, reg));
 						Emit(Push(Basic.invalidPosition, reg));
 						ReleaseIntermediateOperand(reg);
 						ReleaseIntermediateOperand(reg);
-						parametersSize := ProcedureParametersSize(backend.system,procedure);
+						parametersSize := ProcParametersSize(procedure);
 						IntermediateCode.InitImmediate(op2,addressType, parametersSize);
 						IntermediateCode.InitImmediate(op2,addressType, parametersSize);
 						Emit(Push(Basic.invalidPosition, op2));
 						Emit(Push(Basic.invalidPosition, op2));
 						CallThis(position, "Activities","ExpandStack",2);
 						CallThis(position, "Activities","ExpandStack",2);
@@ -3309,10 +3312,10 @@ TYPE
 			IF GetRuntimeProcedure(moduleName,procedureName,procedure,numberParameters < 0) THEN (* ready for dynamic linking *)
 			IF GetRuntimeProcedure(moduleName,procedureName,procedure,numberParameters < 0) THEN (* ready for dynamic linking *)
 				StaticCallOperand(result,procedure);
 				StaticCallOperand(result,procedure);
 				IF numberParameters < 0 THEN
 				IF numberParameters < 0 THEN
-					size := ProcedureParametersSize(system,procedure);
+					size := ProcParametersSize(procedure);
 				ELSE
 				ELSE
 					size := ToMemoryUnits(system,numberParameters * system.addressSize);
 					size := ToMemoryUnits(system,numberParameters * system.addressSize);
-					IF checkNumParameters & (size # ProcedureParametersSize(system,procedure)) THEN
+					IF checkNumParameters & (size # ProcParametersSize(procedure)) THEN
 						Error(position,"runtime call parameter count mismatch");
 						Error(position,"runtime call parameter count mismatch");
 					END;
 					END;
 				END;
 				END;
@@ -4640,7 +4643,7 @@ TYPE
 					Emit(Push(position,IntermediateCode.Immediate(sizeType,suffixRanges)));
 					Emit(Push(position,IntermediateCode.Immediate(sizeType,suffixRanges)));
 
 
 					StaticCallOperand(procOp,procedure);
 					StaticCallOperand(procOp,procedure);
-					Emit(Call(position,procOp.op,ProcedureParametersSize(system,procedure)));
+					Emit(Call(position,procOp.op,ProcParametersSize(procedure)));
 					ReleaseOperand(procOp);
 					ReleaseOperand(procOp);
 				END;
 				END;
 				RestoreRegisters(saved);
 				RestoreRegisters(saved);
@@ -5604,6 +5607,7 @@ TYPE
 			parameterRegisters: SIZE;
 			parameterRegisters: SIZE;
 			passByRegister: BOOLEAN; registerNumber,stackSize: LONGINT;
 			passByRegister: BOOLEAN; registerNumber,stackSize: LONGINT;
 			procedure: SyntaxTree.Procedure;
 			procedure: SyntaxTree.Procedure;
+			cc: SyntaxTree.CallingConvention;
 
 
 			PROCEDURE BackupGlobalState;
 			PROCEDURE BackupGlobalState;
 			BEGIN
 			BEGIN
@@ -5725,7 +5729,7 @@ TYPE
 
 
 			resultDesignator := procedureResultDesignator; procedureResultDesignator := NIL;
 			resultDesignator := procedureResultDesignator; procedureResultDesignator := NIL;
 			procedureType := x.left.type.resolved(SyntaxTree.ProcedureType);
 			procedureType := x.left.type.resolved(SyntaxTree.ProcedureType);
-
+			cc := backend.CallingConvention(procedureType.callingConvention);
 
 
 			dest := destination; destination := emptyOperand;
 			dest := destination; destination := emptyOperand;
 			SaveRegisters();ReleaseUsedRegisters(saved);
 			SaveRegisters();ReleaseUsedRegisters(saved);
@@ -5735,7 +5739,7 @@ TYPE
 			IF (x.left IS SyntaxTree.SymbolDesignator) & (x.left(SyntaxTree.SymbolDesignator).symbol IS SyntaxTree.Operator) THEN
 			IF (x.left IS SyntaxTree.SymbolDesignator) & (x.left(SyntaxTree.SymbolDesignator).symbol IS SyntaxTree.Operator) THEN
 				(* an operator is called *)
 				(* an operator is called *)
 				(* IF dump # NIL THEN dump.String("*** begin of operator call ***"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
 				(* IF dump # NIL THEN dump.String("*** begin of operator call ***"); dump.Ln; dump.Update END; *) (* TENTATIVE *)
-				ASSERT(procedureType.callingConvention = SyntaxTree.OberonCallingConvention);
+				ASSERT(cc = SyntaxTree.OberonCallingConvention);
 
 
 				(* check if a dynamic operator call should be performed *)
 				(* 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;
@@ -5743,23 +5747,23 @@ TYPE
 				isCallOfDynamicOperator := FALSE
 				isCallOfDynamicOperator := FALSE
 			END;
 			END;
 
 
-			IF backend.cooperative & (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) THEN
+			IF backend.cooperative & (cc = SyntaxTree.WinAPICallingConvention) THEN
 				Emit(Push(position, ap));
 				Emit(Push(position, ap));
 			END;
 			END;
 
 
 			alignment := procedureType.stackAlignment;
 			alignment := procedureType.stackAlignment;
-			IF SysvABIorWINAPI(procedureType.callingConvention) & (system.addressSize = 64) THEN
+			IF (cc IN SysvABIorWINAPI) & (system.addressSize = 64) THEN
 				alignment := 16 (* bytes *);
 				alignment := 16 (* bytes *);
 			END;
 			END;
 			IF alignment > 1 THEN
 			IF alignment > 1 THEN
 				IntermediateCode.InitRegister(reg,addressType,IntermediateCode.GeneralPurposeRegister,AcquireRegister(addressType,IntermediateCode.GeneralPurposeRegister));
 				IntermediateCode.InitRegister(reg,addressType,IntermediateCode.GeneralPurposeRegister,AcquireRegister(addressType,IntermediateCode.GeneralPurposeRegister));
 				Emit(Mov(position,reg, sp));
 				Emit(Mov(position,reg, sp));
-				gap := ParametersSize(system, procedureType, FALSE); (* account for all parameters being pushed *)
-				IF (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) & (system.addressSize =64) THEN
+				gap := ParametersSize(system, procedureType,cc, FALSE); (* account for all parameters being pushed *)
+				IF (cc = SyntaxTree.WinAPICallingConvention) & (system.addressSize =64) THEN
 					IF gap < 4*ToMemoryUnits(system,system.addressSize) THEN (* in WINAPI 64bit there is at least space for four registers on the stack *)
 					IF gap < 4*ToMemoryUnits(system,system.addressSize) THEN (* in WINAPI 64bit there is at least space for four registers on the stack *)
 						gap := 4*ToMemoryUnits(system,system.addressSize); 
 						gap := 4*ToMemoryUnits(system,system.addressSize); 
 					END;
 					END;
-				ELSIF (SysvABI(procedureType.callingConvention) ) & (system.addressSize =64) THEN
+				ELSIF (cc IN SysvABI) & (system.addressSize =64) THEN
 					gap := gap - 6*ToMemoryUnits(system,system.addressSize); (* the first 6 parameters are passed via registers in SysVABI *)
 					gap := gap - 6*ToMemoryUnits(system,system.addressSize); (* the first 6 parameters are passed via registers in SysVABI *)
 					IF gap < 0 THEN 
 					IF gap < 0 THEN 
 						gap := 0
 						gap := 0
@@ -5777,11 +5781,11 @@ TYPE
 				ReleaseIntermediateOperand(reg);
 				ReleaseIntermediateOperand(reg);
 			END;
 			END;
 
 
-			IF SysvABI(procedureType.callingConvention) & (system.addressSize = 32) THEN
+			IF (cc IN SysvABI) & (system.addressSize = 32) THEN
 				(* align stack to 16-byte boundary *)
 				(* align stack to 16-byte boundary *)
 				IntermediateCode.InitImmediate(mask,addressType,-16);
 				IntermediateCode.InitImmediate(mask,addressType,-16);
 				Emit(And(position,sp, sp, mask));
 				Emit(And(position,sp, sp, mask));
-				gap := (-ParametersSize( system, procedureType, FALSE )) MOD 16;
+				gap := (-ParametersSize( system, procedureType, cc, FALSE )) MOD 16;
 				IF gap # 0 THEN
 				IF gap # 0 THEN
 					IntermediateCode.InitImmediate(size,addressType,gap);
 					IntermediateCode.InitImmediate(size,addressType,gap);
 					Emit(Sub(position,sp,sp,size))
 					Emit(Sub(position,sp,sp,size))
@@ -5838,7 +5842,7 @@ TYPE
 			 		Emit(Push(position,returnValue.op));
 			 		Emit(Push(position,returnValue.op));
 			 		ReleaseOperand(returnValue);
 			 		ReleaseOperand(returnValue);
 				ELSE*)
 				ELSE*)
-					PushParameter(d,procedureType.returnParameter,procedureType.callingConvention, FALSE, dummy,-1)
+					PushParameter(d,procedureType.returnParameter,cc, FALSE, dummy,-1)
 					(*
 					(*
 		 		END;
 		 		END;
 		 		*)
 		 		*)
@@ -5846,8 +5850,8 @@ TYPE
 
 
 			firstWriteBackCall := NIL; (* reset write-back call list *)
 			firstWriteBackCall := NIL; (* reset write-back call list *)
 
 
-			IF procedureType.callingConvention # SyntaxTree.OberonCallingConvention THEN
-				parameterRegisters := backend.NumberParameterRegisters(procedureType.callingConvention);
+			IF cc # SyntaxTree.OberonCallingConvention THEN
+				parameterRegisters := backend.NumberParameterRegisters(cc);
 				
 				
 				passByRegister := parameterRegisters > 0;
 				passByRegister := parameterRegisters > 0;
 				registerNumber := 0;
 				registerNumber := 0;
@@ -5856,18 +5860,18 @@ TYPE
 					actualParameter := parameters.GetExpression(i);
 					actualParameter := parameters.GetExpression(i);
 					PrepareParameter(actualParameter, formalParameter);
 					PrepareParameter(actualParameter, formalParameter);
 					IF passByRegister & (i < parameterRegisters) THEN
 					IF passByRegister & (i < parameterRegisters) THEN
-						IF ~PassInRegister(formalParameter) THEN
+						IF ~PassInRegister(formalParameter,cc) THEN
 							Error(actualParameter.position,"cannot be passed by register")
 							Error(actualParameter.position,"cannot be passed by register")
 						ELSE
 						ELSE
-							PushParameter(actualParameter, formalParameter, procedureType.callingConvention, FALSE, dummy,i);
+							PushParameter(actualParameter, formalParameter, cc, FALSE, dummy,i);
 						END;
 						END;
 						INC(registerNumber);
 						INC(registerNumber);
 					ELSE
 					ELSE
-						PushParameter(actualParameter, formalParameter, procedureType.callingConvention, FALSE, dummy,-1);
+						PushParameter(actualParameter, formalParameter, cc, FALSE, dummy,-1);
 					END;
 					END;
 					formalParameter := formalParameter.prevParameter;
 					formalParameter := formalParameter.prevParameter;
 				END;
 				END;
-				IF passByRegister (* & (registerNumber > 0)*)  & ~SysvABI(procedureType.callingConvention) THEN
+				IF passByRegister (* & (registerNumber > 0)*)  & ~(cc IN SysvABI) THEN
 					(* WINAPI: always (!) reserve 4 addresses for fastcall registers *)
 					(* WINAPI: always (!) reserve 4 addresses for fastcall registers *)
 					stackSize := ToMemoryUnits(system,parameterRegisters*addressType.sizeInBits);
 					stackSize := ToMemoryUnits(system,parameterRegisters*addressType.sizeInBits);
 					Emit(Sub(position,sp,sp,IntermediateCode.Immediate(addressType,stackSize)));
 					Emit(Sub(position,sp,sp,IntermediateCode.Immediate(addressType,stackSize)));
@@ -5884,14 +5888,14 @@ TYPE
 						IF isCallOfDynamicOperator  & IsStrictlyPointerToRecord(formalParameter.type) & (formalParameter.access # SyntaxTree.Hidden) THEN (* TODO: remove hidden parameters *)
 						IF isCallOfDynamicOperator  & IsStrictlyPointerToRecord(formalParameter.type) & (formalParameter.access # SyntaxTree.Hidden) THEN (* TODO: remove hidden parameters *)
 							ASSERT(i < 2);
 							ASSERT(i < 2);
 							hasDynamicOperands := TRUE;
 							hasDynamicOperands := TRUE;
-							PushParameter(actualParameter, formalParameter, procedureType.callingConvention, TRUE, parameterBackups[i],-1)
+							PushParameter(actualParameter, formalParameter, cc, TRUE, parameterBackups[i],-1)
 						ELSE
 						ELSE
 							IF passByRegister & (registerNumber > 0) THEN
 							IF passByRegister & (registerNumber > 0) THEN
 								stackSize := ToMemoryUnits(system,registerNumber*addressType.sizeInBits);
 								stackSize := ToMemoryUnits(system,registerNumber*addressType.sizeInBits);
 								Emit(Sub(position,sp,sp,IntermediateCode.Immediate(addressType,stackSize)));
 								Emit(Sub(position,sp,sp,IntermediateCode.Immediate(addressType,stackSize)));
 							END;
 							END;
 							passByRegister := FALSE;
 							passByRegister := FALSE;
-							PushParameter(actualParameter, formalParameter, procedureType.callingConvention, FALSE, dummy,-1);
+							PushParameter(actualParameter, formalParameter, cc, FALSE, dummy,-1);
 						END;
 						END;
 						formalParameter := formalParameter.nextParameter;
 						formalParameter := formalParameter.nextParameter;
 					END;
 					END;
@@ -5904,9 +5908,9 @@ TYPE
 					Emit(Push(position,reg));
 					Emit(Push(position,reg));
 					ReleaseIntermediateOperand(reg);
 					ReleaseIntermediateOperand(reg);
 				END;
 				END;
-				parametersSize := ProcedureParametersSize(system,symbol(SyntaxTree.Procedure));
+				parametersSize := ProcParametersSize(symbol(SyntaxTree.Procedure));
 			ELSIF (symbol IS SyntaxTree.Variable) OR (symbol IS SyntaxTree.Parameter) THEN
 			ELSIF (symbol IS SyntaxTree.Variable) OR (symbol IS SyntaxTree.Parameter) THEN
-				parametersSize := ParametersSize(system,procedureType,FALSE);
+				parametersSize := ParametersSize(system,procedureType,cc, FALSE);
 			END;
 			END;
 
 
 
 
@@ -5986,7 +5990,7 @@ TYPE
 				(* call operator selection procedure *)
 				(* call operator selection procedure *)
 				IF GetRuntimeProcedure("FoxOperatorRuntime", "SelectOperator", operatorSelectionProcedure, TRUE) THEN
 				IF GetRuntimeProcedure("FoxOperatorRuntime", "SelectOperator", operatorSelectionProcedure, TRUE) THEN
 					StaticCallOperand(operatorSelectionProcedureOperand, operatorSelectionProcedure);
 					StaticCallOperand(operatorSelectionProcedureOperand, operatorSelectionProcedure);
-					Emit(Call(position,operatorSelectionProcedureOperand.op, ProcedureParametersSize(system, operatorSelectionProcedure)));
+					Emit(Call(position,operatorSelectionProcedureOperand.op, ProcParametersSize( operatorSelectionProcedure)));
 					ReleaseOperand(operatorSelectionProcedureOperand);
 					ReleaseOperand(operatorSelectionProcedureOperand);
 
 
 					(* use the address that the operator selection procedure returned as the target address of the call *)
 					(* use the address that the operator selection procedure returned as the target address of the call *)
@@ -5999,12 +6003,12 @@ TYPE
 						
 						
 			ReleaseParameterRegisters();
 			ReleaseParameterRegisters();
 			
 			
-			IF ~(symbol IS SyntaxTree.Procedure) & backend.trackLeave & ~isUnchecked & (procedureType.callingConvention IN {SyntaxTree.WinAPICallingConvention, SyntaxTree.CCallingConvention}) THEN
+			IF ~(symbol IS SyntaxTree.Procedure) & backend.trackLeave & ~isUnchecked & (cc IN {SyntaxTree.WinAPICallingConvention, SyntaxTree.CCallingConvention}) THEN
 				SaveRegisters();ReleaseUsedRegisters(saved2);
 				SaveRegisters();ReleaseUsedRegisters(saved2);
 				CallThis(position,"Objects","LeaveA2",0);
 				CallThis(position,"Objects","LeaveA2",0);
 				RestoreRegisters(saved2);
 				RestoreRegisters(saved2);
 			END;
 			END;
-			IF (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) OR SysvABI(procedureType.callingConvention) THEN
+			IF (cc = SyntaxTree.WinAPICallingConvention) OR (cc IN SysvABI) THEN
 				Emit(Call(position,operand.op,0));
 				Emit(Call(position,operand.op,0));
 			ELSE
 			ELSE
 				Emit(Call(position,operand.op,parametersSize));
 				Emit(Call(position,operand.op,parametersSize));
@@ -6020,7 +6024,7 @@ TYPE
 				Emit(Result(position,return));
 				Emit(Result(position,return));
 			END;
 			END;
 
 
-			IF  ~(symbol IS SyntaxTree.Procedure) & backend.trackLeave & ~isUnchecked & (procedureType.callingConvention  IN {SyntaxTree.WinAPICallingConvention, SyntaxTree.CCallingConvention}) THEN
+			IF  ~(symbol IS SyntaxTree.Procedure) & backend.trackLeave & ~isUnchecked & (cc  IN {SyntaxTree.WinAPICallingConvention, SyntaxTree.CCallingConvention}) THEN
 				IF  (procedureType.returnType # NIL) & ~structuredReturnType  THEN 
 				IF  (procedureType.returnType # NIL) & ~structuredReturnType  THEN 
 					Emit(Push(position, return));
 					Emit(Push(position, return));
 					CallThis(position,"Objects","ReenterA2",0);
 					CallThis(position,"Objects","ReenterA2",0);
@@ -6031,7 +6035,7 @@ TYPE
 			END;
 			END;
 			
 			
 			(* === return parameter space === *)
 			(* === return parameter space === *)
-			IF (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) & passByRegister (* & (registerNumber > 0) *) THEN
+			IF (cc = SyntaxTree.WinAPICallingConvention) & passByRegister (* & (registerNumber > 0) *) THEN
 				parametersSize := ToMemoryUnits(system,parameters.Length()*addressType.sizeInBits);
 				parametersSize := ToMemoryUnits(system,parameters.Length()*addressType.sizeInBits);
 				(* cleanup all space for all parameters *) 
 				(* cleanup all space for all parameters *) 
 				IF parametersSize < 32 THEN 
 				IF parametersSize < 32 THEN 
@@ -6042,7 +6046,7 @@ TYPE
 				Emit(Add(position,sp,sp,size))
 				Emit(Add(position,sp,sp,size))
 			END; 
 			END; 
 
 
-			IF SysvABI(procedureType.callingConvention) THEN
+			IF (cc IN SysvABI) THEN
 				IF passByRegister THEN 
 				IF passByRegister THEN 
 					IF parameters.Length() > parameterRegisters THEN
 					IF parameters.Length() > parameterRegisters THEN
 						parametersSize := ToMemoryUnits(system,(parameters.Length()-parameterRegisters)*addressType.sizeInBits)
 						parametersSize := ToMemoryUnits(system,(parameters.Length()-parameterRegisters)*addressType.sizeInBits)
@@ -6080,7 +6084,7 @@ TYPE
 				Emit(Pop(position,sp));
 				Emit(Pop(position,sp));
 			END;
 			END;
 
 
-			IF backend.cooperative & (procedureType.callingConvention = SyntaxTree.WinAPICallingConvention) THEN
+			IF backend.cooperative & (cc = SyntaxTree.WinAPICallingConvention) THEN
 				Emit(Pop(position, ap));
 				Emit(Pop(position, ap));
 			END;
 			END;
 
 
@@ -6276,7 +6280,7 @@ TYPE
 				IntermediateCode.InitImmediate(reg, IntermediateCode.GetType(system,system.longintType), procedureNumber);
 				IntermediateCode.InitImmediate(reg, IntermediateCode.GetType(system,system.longintType), procedureNumber);
 				Emit(Push(position,reg));
 				Emit(Push(position,reg));
 				StaticCallOperand(result,procedure);
 				StaticCallOperand(result,procedure);
-				Emit(Call(position,result.op,ProcedureParametersSize(system,procedure)));
+				Emit(Call(position,result.op,ProcParametersSize(procedure)));
 				ReleaseOperand(result);
 				ReleaseOperand(result);
 			END;
 			END;
 		END ProfilerEnterExit;
 		END ProfilerEnterExit;
@@ -6298,7 +6302,7 @@ TYPE
 				profileInit.Emit(Push(position,result.tag));
 				profileInit.Emit(Push(position,result.tag));
 				profileInit.Emit(Push(position,result.op));
 				profileInit.Emit(Push(position,result.op));
 				StaticCallOperand(result,procedure);
 				StaticCallOperand(result,procedure);
-				profileInit.Emit(Call(position,result.op,ProcedureParametersSize(system,procedure)));
+				profileInit.Emit(Call(position,result.op,ProcParametersSize(procedure)));
 				ReleaseOperand(result);
 				ReleaseOperand(result);
 			END;
 			END;
 		END ProfilerAddProcedure;
 		END ProfilerAddProcedure;
@@ -6319,7 +6323,7 @@ TYPE
 				profileInit.Emit(Push(position,result.tag));
 				profileInit.Emit(Push(position,result.tag));
 				profileInit.Emit(Push(position,result.op));
 				profileInit.Emit(Push(position,result.op));
 				StaticCallOperand(result,procedure);
 				StaticCallOperand(result,procedure);
-				profileInit.Emit(Call(position,result.op,ProcedureParametersSize(system,procedure)));
+				profileInit.Emit(Call(position,result.op,ProcParametersSize(procedure)));
 				ReleaseOperand(result);
 				ReleaseOperand(result);
 			END;
 			END;
 		END ProfilerAddModule;
 		END ProfilerAddModule;
@@ -6421,7 +6425,7 @@ TYPE
 					ReleaseOperand(operatorOperand);
 					ReleaseOperand(operatorOperand);
 
 
 					StaticCallOperand(runtimeProcedureOperand, runtimeProcedure);
 					StaticCallOperand(runtimeProcedureOperand, runtimeProcedure);
-					operatorInitializationCodeSection.Emit(Call(position,runtimeProcedureOperand.op, ProcedureParametersSize(system, runtimeProcedure)));
+					operatorInitializationCodeSection.Emit(Call(position,runtimeProcedureOperand.op, ProcParametersSize( runtimeProcedure)));
 					ReleaseOperand(runtimeProcedureOperand)
 					ReleaseOperand(runtimeProcedureOperand)
 				END
 				END
 				(* IF dump # NIL THEN dump.String("*** end of operator registration ***"); dump.Ln; dump.Update END *) (* TENTATIVE *)
 				(* IF dump # NIL THEN dump.String("*** end of operator registration ***"); dump.Ln; dump.Update END *) (* TENTATIVE *)
@@ -6467,11 +6471,11 @@ TYPE
 			BEGIN
 			BEGIN
 				IF procedure # NIL THEN
 				IF procedure # NIL THEN
 					StaticCallOperand(result,procedure);
 					StaticCallOperand(result,procedure);
-					size := ProcedureParametersSize(system,procedure);
+					size := ProcParametersSize(procedure);
 				ELSE
 				ELSE
 					Symbol(procedureVariable, result);
 					Symbol(procedureVariable, result);
 					LoadValue(result, procedureVariable.type.resolved);
 					LoadValue(result, procedureVariable.type.resolved);
-					size := ParametersSize(system, procedureVariable.type.resolved(SyntaxTree.ProcedureType), FALSE);
+					size := ParametersSize(system, procedureVariable.type.resolved(SyntaxTree.ProcedureType), backend.CallingConvention(procedureVariable.type.resolved(SyntaxTree.ProcedureType).callingConvention), FALSE);
 				END;
 				END;
 				Emit(Call(position,result.op,size));
 				Emit(Call(position,result.op,size));
 			END CallProcedure;
 			END CallProcedure;
@@ -7619,6 +7623,7 @@ TYPE
 			prevScope: SyntaxTree.Scope;
 			prevScope: SyntaxTree.Scope;
 			firstPar: LONGINT;
 			firstPar: LONGINT;
 			saved: RegisterEntry;
 			saved: RegisterEntry;
+			cc: SyntaxTree.CallingConvention;
 
 
 			PROCEDURE CallBodies(self: IntermediateCode.Operand; type: SyntaxTree.Type);
 			PROCEDURE CallBodies(self: IntermediateCode.Operand; type: SyntaxTree.Type);
 			VAR recordScope: SyntaxTree.RecordScope; procedure: SyntaxTree.Procedure; body: SyntaxTree.Body; flags: LONGINT;
 			VAR recordScope: SyntaxTree.RecordScope; procedure: SyntaxTree.Procedure; body: SyntaxTree.Body; flags: LONGINT;
@@ -7661,7 +7666,7 @@ TYPE
 					ELSE
 					ELSE
 						Emit(Push(position,self));
 						Emit(Push(position,self));
 						StaticCallOperand(callop,procedure);
 						StaticCallOperand(callop,procedure);
-						Emit(Call(position,callop.op,ProcedureParametersSize(system,procedure)));
+						Emit(Call(position,callop.op,ProcParametersSize(procedure)));
 					END;
 					END;
 					Emit(Pop(position,self));
 					Emit(Pop(position,self));
 				END;
 				END;
@@ -8100,7 +8105,7 @@ TYPE
 							ELSE
 							ELSE
 								symbol := NewSection(module.allSections, Sections.CodeSection, name,constructor,commentPrintout # NIL);
 								symbol := NewSection(module.allSections, Sections.CodeSection, name,constructor,commentPrintout # NIL);
 							END;
 							END;
-							Emit(Call(position,IntermediateCode.Address(addressType, symbol.name, GetFingerprint(constructor), 0),ProcedureParametersSize(system,constructor) - ToMemoryUnits(system,addressType.sizeInBits)));
+							Emit(Call(position,IntermediateCode.Address(addressType, symbol.name, GetFingerprint(constructor), 0),ProcParametersSize(constructor) - ToMemoryUnits(system,addressType.sizeInBits)));
 							IntermediateCode.InitRegister(pointer,addressType,IntermediateCode.GeneralPurposeRegister,AcquireRegister(addressType,IntermediateCode.GeneralPurposeRegister));
 							IntermediateCode.InitRegister(pointer,addressType,IntermediateCode.GeneralPurposeRegister,AcquireRegister(addressType,IntermediateCode.GeneralPurposeRegister));
 							Emit(Pop(position,pointer));
 							Emit(Pop(position,pointer));
 						END;
 						END;
@@ -8185,7 +8190,7 @@ TYPE
 							ELSE
 							ELSE
 								symbol := NewSection(module.allSections, Sections.CodeSection, name,constructor,commentPrintout # NIL);
 								symbol := NewSection(module.allSections, Sections.CodeSection, name,constructor,commentPrintout # NIL);
 							END;
 							END;
-							Emit(Call(position,IntermediateCode.Address(addressType, symbol.name, GetFingerprint(constructor), 0),ProcedureParametersSize(system,constructor)));
+							Emit(Call(position,IntermediateCode.Address(addressType, symbol.name, GetFingerprint(constructor), 0),ProcParametersSize(constructor)));
 						ELSE
 						ELSE
 							ReleaseIntermediateOperand(pointer);
 							ReleaseIntermediateOperand(pointer);
 						END;
 						END;
@@ -8514,13 +8519,14 @@ TYPE
 						IF GetRuntimeProcedure("FoxArrayBase","AllocateTensorX",procedure,TRUE) THEN
 						IF GetRuntimeProcedure("FoxArrayBase","AllocateTensorX",procedure,TRUE) THEN
 							left := SyntaxTree.NewSymbolDesignator(Basic.invalidPosition,NIL,procedure);
 							left := SyntaxTree.NewSymbolDesignator(Basic.invalidPosition,NIL,procedure);
 							procedureType := procedure.type(SyntaxTree.ProcedureType);
 							procedureType := procedure.type(SyntaxTree.ProcedureType);
+							cc := backend.CallingConvention(procedureType.callingConvention);
 							left.SetType(procedure.type);
 							left.SetType(procedure.type);
 							formalParameter := procedureType.firstParameter;
 							formalParameter := procedureType.firstParameter;
 							(* push array to allocate *)
 							(* push array to allocate *)
-							PushParameter(p0, formalParameter, procedureType.callingConvention, FALSE, dummy,-1);
+							PushParameter(p0, formalParameter, cc, FALSE, dummy,-1);
 							formalParameter :=formalParameter.nextParameter;
 							formalParameter :=formalParameter.nextParameter;
 							(* push length array *)
 							(* push length array *)
-							PushParameter(p1, formalParameter, procedureType.callingConvention, FALSE, dummy,-1);
+							PushParameter(p1, formalParameter, cc, FALSE, dummy,-1);
 							(* push size *)
 							(* push size *)
 							type := t0;
 							type := t0;
 							WHILE (type IS SyntaxTree.MathArrayType) & (type(SyntaxTree.MathArrayType).form # SyntaxTree.Static) DO
 							WHILE (type IS SyntaxTree.MathArrayType) & (type(SyntaxTree.MathArrayType).form # SyntaxTree.Static) DO
@@ -8540,7 +8546,7 @@ TYPE
 							Emit(Push(position,tmp)); (* type descriptor *)
 							Emit(Push(position,tmp)); (* type descriptor *)
 
 
 							StaticCallOperand(result,procedure);
 							StaticCallOperand(result,procedure);
-							Emit(Call(position,result.op,ProcedureParametersSize(system,procedure)));
+							Emit(Call(position,result.op,ProcParametersSize(procedure)));
 							ReleaseOperand(result);
 							ReleaseOperand(result);
 						END;
 						END;
 						(*
 						(*
@@ -8629,7 +8635,7 @@ TYPE
 						ReleaseOperand(l);
 						ReleaseOperand(l);
 
 
 						StaticCallOperand(result,procedure);
 						StaticCallOperand(result,procedure);
-						Emit(Call(position,result.op,ProcedureParametersSize(system,procedure)));
+						Emit(Call(position,result.op,ProcParametersSize(procedure)));
 						ReleaseOperand(result);
 						ReleaseOperand(result);
 						
 						
 						tmp := IntermediateCode.Immediate(addressType,ToMemoryUnits(system,dim*system.addressSize));
 						tmp := IntermediateCode.Immediate(addressType,ToMemoryUnits(system,dim*system.addressSize));
@@ -8774,7 +8780,7 @@ TYPE
 						ELSE
 						ELSE
 							symbol := NewSection(module.allSections, Sections.CodeSection, name, constructor, commentPrintout # NIL);
 							symbol := NewSection(module.allSections, Sections.CodeSection, name, constructor, commentPrintout # NIL);
 						END;
 						END;
-						Emit(Call(position,IntermediateCode.Address(addressType, symbol.name, GetFingerprint(constructor), 0),ProcedureParametersSize(system,constructor)));
+						Emit(Call(position,IntermediateCode.Address(addressType, symbol.name, GetFingerprint(constructor), 0),ProcParametersSize(constructor)));
 					(*ELSE
 					(*ELSE
 						ReleaseIntermediateOperand(pointer);*)
 						ReleaseIntermediateOperand(pointer);*)
 					END;
 					END;
@@ -9373,7 +9379,7 @@ TYPE
 				result.op := basereg;
 				result.op := basereg;
 				procedure := scope(SyntaxTree.ProcedureScope).ownerProcedure;
 				procedure := scope(SyntaxTree.ProcedureScope).ownerProcedure;
 				procedureType := procedure.type(SyntaxTree.ProcedureType);
 				procedureType := procedure.type(SyntaxTree.ProcedureType);
-				parametersSize := ProcedureParametersSize(system,procedure);
+				parametersSize := ProcParametersSize(procedure);
 				IntermediateCode.AddOffset(result.op,ToMemoryUnits(system,addressType.sizeInBits)*(procedureType.parametersOffset+1)+parametersSize);
 				IntermediateCode.AddOffset(result.op,ToMemoryUnits(system,addressType.sizeInBits)*(procedureType.parametersOffset+1)+parametersSize);
 				IF backend.cooperative THEN
 				IF backend.cooperative THEN
 					IntermediateCode.AddOffset(result.op,ToMemoryUnits(system,addressType.sizeInBits));
 					IntermediateCode.AddOffset(result.op,ToMemoryUnits(system,addressType.sizeInBits));
@@ -10009,7 +10015,7 @@ TYPE
 					size := ToMemoryUnits(system,system.SizeOf(rightBase));
 					size := ToMemoryUnits(system,system.SizeOf(rightBase));
 					Emit(Push(position,IntermediateCode.Immediate(sizeType,size)));
 					Emit(Push(position,IntermediateCode.Immediate(sizeType,size)));
 					StaticCallOperand(result,procedure);
 					StaticCallOperand(result,procedure);
-					Emit(Call(position,result.op,ProcedureParametersSize(system,procedure)));
+					Emit(Call(position,result.op,ProcParametersSize(procedure)));
 					ReleaseOperand(result);
 					ReleaseOperand(result);
 				END;
 				END;
 				RestoreRegisters(saved);
 				RestoreRegisters(saved);
@@ -10079,7 +10085,7 @@ TYPE
 				IF SemanticChecker.ReturnedAsParameter(right.type)  THEN
 				IF SemanticChecker.ReturnedAsParameter(right.type)  THEN
 					IF right IS SyntaxTree.ProcedureCallDesignator THEN
 					IF right IS SyntaxTree.ProcedureCallDesignator THEN
 						procedureType := right(SyntaxTree.ProcedureCallDesignator).left.type.resolved(SyntaxTree.ProcedureType);
 						procedureType := right(SyntaxTree.ProcedureCallDesignator).left.type.resolved(SyntaxTree.ProcedureType);
-						RETURN procedureType.callingConvention = SyntaxTree.OberonCallingConvention
+						RETURN backend.CallingConvention(procedureType.callingConvention) = SyntaxTree.OberonCallingConvention
 					ELSIF right IS SyntaxTree.BuiltinCallDesignator THEN
 					ELSIF right IS SyntaxTree.BuiltinCallDesignator THEN
 						WITH right: SyntaxTree.BuiltinCallDesignator DO
 						WITH right: SyntaxTree.BuiltinCallDesignator DO
 							IF right.id = Global.Reshape THEN RETURN TRUE
 							IF right.id = Global.Reshape THEN RETURN TRUE
@@ -10719,7 +10725,7 @@ TYPE
 					IF locked THEN Lock(FALSE) END;
 					IF locked THEN Lock(FALSE) END;
 					IF ~backend.cooperative & profile THEN ProfilerEnterExit(numberProcedures,FALSE) END;
 					IF ~backend.cooperative & profile THEN ProfilerEnterExit(numberProcedures,FALSE) END;
 					(* "RETURN RESULT" -> no assignment, it is assumed that result has been written to return parameter via structured return type *)
 					(* "RETURN RESULT" -> no assignment, it is assumed that result has been written to return parameter via structured return type *)
-				ELSIF (type IS SyntaxTree.BasicType) & ~(type IS SyntaxTree.RangeType) & ~(type IS SyntaxTree.ComplexType) & ~type.IsPointer() OR (type IS SyntaxTree.EnumerationType) OR (procedureType.callingConvention # SyntaxTree.OberonCallingConvention) THEN
+				ELSIF (type IS SyntaxTree.BasicType) & ~(type IS SyntaxTree.RangeType) & ~(type IS SyntaxTree.ComplexType) & ~type.IsPointer() OR (type IS SyntaxTree.EnumerationType) OR (backend.CallingConvention(procedureType.callingConvention) # SyntaxTree.OberonCallingConvention) THEN
 					(* return without structured return parameter *)
 					(* return without structured return parameter *)
 					Evaluate(expression,res);
 					Evaluate(expression,res);
 					delegate := (type IS SyntaxTree.ProcedureType) & (type(SyntaxTree.ProcedureType).isDelegate);
 					delegate := (type IS SyntaxTree.ProcedureType) & (type(SyntaxTree.ProcedureType).isDelegate);
@@ -10819,15 +10825,15 @@ TYPE
 			IF backend.cooperative THEN
 			IF backend.cooperative THEN
 				BrL(exitLabel);
 				BrL(exitLabel);
 			ELSE
 			ELSE
-				cc := procedureType(SyntaxTree.ProcedureType).callingConvention;
+				cc := backend.CallingConvention(procedureType.callingConvention);
 				IF cc = SyntaxTree.WinAPICallingConvention THEN
 				IF cc = SyntaxTree.WinAPICallingConvention THEN
-					parametersSize := ProcedureParametersSize(backend.system,procedure);
+					parametersSize := ProcedureParametersSize(backend.system,procedure, cc);
 				ELSE
 				ELSE
 					parametersSize := 0;
 					parametersSize := 0;
 				END;
 				END;
 
 
-				EmitLeave(section, position,procedure, procedure.type(SyntaxTree.ProcedureType).callingConvention);
-				Emit(Exit(position,procedure.type(SyntaxTree.ProcedureType).pcOffset,procedure.type(SyntaxTree.ProcedureType).callingConvention, parametersSize));
+				EmitLeave(section, position,procedure, cc);
+				Emit(Exit(position,procedure.type(SyntaxTree.ProcedureType).pcOffset,cc, parametersSize));
 			END;
 			END;
 			IF Trace THEN TraceExit("VisitReturnStatement") END;
 			IF Trace THEN TraceExit("VisitReturnStatement") END;
 		END VisitReturnStatement;
 		END VisitReturnStatement;
@@ -10889,7 +10895,7 @@ TYPE
 				symbol := NewSection(module.allSections, Sections.CodeSection, name,proc,commentPrintout # NIL);
 				symbol := NewSection(module.allSections, Sections.CodeSection, name,proc,commentPrintout # NIL);
 				IntermediateCode.InitAddress(call,addressType,name, GetFingerprint(proc), 0);
 				IntermediateCode.InitAddress(call,addressType,name, GetFingerprint(proc), 0);
 				res := NewRegisterOperand(IntermediateCode.GetType(system,system.booleanType));
 				res := NewRegisterOperand(IntermediateCode.GetType(system,system.booleanType));
-				Emit(Call(position,call,ProcedureParametersSize(system,proc)));
+				Emit(Call(position,call,ProcParametersSize(proc)));
 				Emit(Result(position,res));
 				Emit(Result(position,res));
 				(*
 				(*
 				AcquireThisRegister(IntermediateCode.GetType(system,system.booleanType),IntermediateCode.Result);
 				AcquireThisRegister(IntermediateCode.GetType(system,system.booleanType),IntermediateCode.Result);
@@ -10950,7 +10956,7 @@ TYPE
 				GetBaseRegister(op.op,currentScope,scope);
 				GetBaseRegister(op.op,currentScope,scope);
 				procedure := scope(SyntaxTree.ProcedureScope).ownerProcedure;
 				procedure := scope(SyntaxTree.ProcedureScope).ownerProcedure;
 				procedureType := procedure.type(SyntaxTree.ProcedureType);
 				procedureType := procedure.type(SyntaxTree.ProcedureType);
-				parametersSize := ProcedureParametersSize(system,procedure);
+				parametersSize := ProcParametersSize(procedure);
 				IntermediateCode.AddOffset(op.op,ToMemoryUnits(system,addressType.sizeInBits)*(procedureType.parametersOffset+1)+parametersSize);
 				IntermediateCode.AddOffset(op.op,ToMemoryUnits(system,addressType.sizeInBits)*(procedureType.parametersOffset+1)+parametersSize);
 				IF backend.cooperative THEN
 				IF backend.cooperative THEN
 					IntermediateCode.AddOffset(op.op,ToMemoryUnits(system,addressType.sizeInBits));
 					IntermediateCode.AddOffset(op.op,ToMemoryUnits(system,addressType.sizeInBits));
@@ -11126,9 +11132,9 @@ TYPE
 
 
 				IF currentIsInline THEN RETURN END;
 				IF currentIsInline THEN RETURN END;
 
 
-				cc := procedureType(SyntaxTree.ProcedureType).callingConvention;
+				cc := backend.CallingConvention(procedureType(SyntaxTree.ProcedureType).callingConvention);
 				IF cc = SyntaxTree.WinAPICallingConvention THEN
 				IF cc = SyntaxTree.WinAPICallingConvention THEN
-					parametersSize := ProcedureParametersSize(backend.system,procedure);
+					parametersSize := ProcedureParametersSize(backend.system,procedure,cc);
 				ELSE
 				ELSE
 					parametersSize := 0;
 					parametersSize := 0;
 				END;
 				END;
@@ -11138,6 +11144,12 @@ TYPE
 
 
 			IF Trace THEN TraceExit("VisitCode") END;
 			IF Trace THEN TraceExit("VisitCode") END;
 		END VisitCode;
 		END VisitCode;
+		
+		PROCEDURE ProcParametersSize(procedure: SyntaxTree.Procedure): LONGINT;
+		BEGIN
+			RETURN ProcedureParametersSize(system, procedure, backend.CallingConvention(procedure.type(SyntaxTree.ProcedureType).callingConvention)); 
+		END ProcParametersSize;
+		
 
 
 		PROCEDURE ParameterCopies(x: SyntaxTree.ProcedureType);
 		PROCEDURE ParameterCopies(x: SyntaxTree.ProcedureType);
 		VAR parameter: SyntaxTree.Parameter; type, base: SyntaxTree.Type; 
 		VAR parameter: SyntaxTree.Parameter; type, base: SyntaxTree.Type; 
@@ -13259,7 +13271,7 @@ TYPE
 						parameter := parameter.nextParameter;
 						parameter := parameter.nextParameter;
 					END;
 					END;
 					IF scope(SyntaxTree.ProcedureScope).ownerProcedure.type(SyntaxTree.ProcedureType).isDelegate THEN 
 					IF scope(SyntaxTree.ProcedureScope).ownerProcedure.type(SyntaxTree.ProcedureType).isDelegate THEN 
-						parametersSize := ProcedureParametersSize(module.system,scope(SyntaxTree.ProcedureScope).ownerProcedure);
+						parametersSize := implementationVisitor.ProcParametersSize(scope(SyntaxTree.ProcedureScope).ownerProcedure);
 						INC(parametersSize,ToMemoryUnits(module.system,module.system.addressSize));
 						INC(parametersSize,ToMemoryUnits(module.system,module.system.addressSize));
 						IF implementationVisitor.backend.preciseGC THEN
 						IF implementationVisitor.backend.preciseGC THEN
 							INC(parametersSize,ToMemoryUnits(module.system,module.system.addressSize));
 							INC(parametersSize,ToMemoryUnits(module.system,module.system.addressSize));
@@ -13716,6 +13728,7 @@ TYPE
 		cellsAreObjects: BOOLEAN;
 		cellsAreObjects: BOOLEAN;
 		preciseGC, trackLeave, writeBarriers: BOOLEAN; 
 		preciseGC, trackLeave, writeBarriers: BOOLEAN; 
 		experiment: BOOLEAN; 
 		experiment: BOOLEAN; 
+		platformCallingConvention: SyntaxTree.CallingConvention;
 		
 		
 		PROCEDURE &InitIntermediateBackend*;
 		PROCEDURE &InitIntermediateBackend*;
 		BEGIN
 		BEGIN
@@ -13840,6 +13853,7 @@ TYPE
 			options.Add(0X,"trackLeave", Options.Flag);
 			options.Add(0X,"trackLeave", Options.Flag);
 			options.Add(0X,"writeBarriers", Options.Flag);
 			options.Add(0X,"writeBarriers", Options.Flag);
 			options.Add(0X,"experiment", Options.Flag);
 			options.Add(0X,"experiment", Options.Flag);
+			options.Add(0X,"platformCC", Options.String);
 		END DefineOptions;
 		END DefineOptions;
 
 
 		PROCEDURE GetOptions*(options: Options.Options);
 		PROCEDURE GetOptions*(options: Options.Options);
@@ -13872,11 +13886,27 @@ TYPE
 			trackLeave := options.GetFlag("trackLeave");
 			trackLeave := options.GetFlag("trackLeave");
 			writeBarriers := options.GetFlag("writeBarriers");
 			writeBarriers := options.GetFlag("writeBarriers");
 			experiment := options.GetFlag("experiment");
 			experiment := options.GetFlag("experiment");
+			platformCallingConvention := SyntaxTree.OberonCallingConvention;
+			IF options.GetString("platformCC", name) THEN
+				IF name = Global.StringC THEN platformCallingConvention := SyntaxTree.CCallingConvention
+				ELSIF name = Global.StringWinAPI THEN platformCallingConvention := SyntaxTree.WinAPICallingConvention
+				END;
+			END
 		END GetOptions;
 		END GetOptions;
 
 
 		PROCEDURE DefaultSymbolFileFormat*(): Formats.SymbolFileFormat;
 		PROCEDURE DefaultSymbolFileFormat*(): Formats.SymbolFileFormat;
 		BEGIN RETURN SymbolFileFormat.Get()
 		BEGIN RETURN SymbolFileFormat.Get()
 		END DefaultSymbolFileFormat;
 		END DefaultSymbolFileFormat;
+		
+		PROCEDURE CallingConvention*(cc: SyntaxTree.CallingConvention): SyntaxTree.CallingConvention;
+		BEGIN
+			IF cc = SyntaxTree.PlatformCallingConvention THEN 
+				RETURN platformCallingConvention 
+			ELSE
+				RETURN cc
+			END; 
+		END CallingConvention;
+		
 
 
 	END IntermediateBackend;
 	END IntermediateBackend;
 
 
@@ -13956,19 +13986,19 @@ TYPE
 		END;
 		END;
 	END CommonAlignment;
 	END CommonAlignment;
 	
 	
-	PROCEDURE PassBySingleReference(parameter: SyntaxTree.Parameter): BOOLEAN;
+	PROCEDURE PassBySingleReference(parameter: SyntaxTree.Parameter; cc: SyntaxTree.CallingConvention): BOOLEAN;
 	BEGIN
 	BEGIN
 		IF parameter.kind = SyntaxTree.ValueParameter THEN RETURN FALSE
 		IF parameter.kind = SyntaxTree.ValueParameter THEN RETURN FALSE
 		ELSIF parameter.kind = SyntaxTree.ConstParameter THEN
 		ELSIF parameter.kind = SyntaxTree.ConstParameter THEN
-			RETURN (parameter.type.resolved IS SyntaxTree.RecordType) OR (parameter.type.resolved IS SyntaxTree.ArrayType) & SysvABIorWINAPI(parameter.ownerType(SyntaxTree.ProcedureType).callingConvention)
+			RETURN (parameter.type.resolved IS SyntaxTree.RecordType) OR (parameter.type.resolved IS SyntaxTree.ArrayType) & (cc IN SysvABIorWINAPI)
 		ELSIF parameter.kind = SyntaxTree.VarParameter THEN
 		ELSIF parameter.kind = SyntaxTree.VarParameter THEN
-			RETURN ~(parameter.type.resolved IS SyntaxTree.ArrayType) & ~(parameter.type.resolved IS SyntaxTree.MathArrayType) OR (parameter.type.resolved IS SyntaxTree.ArrayType) & SysvABIorWINAPI(parameter.ownerType(SyntaxTree.ProcedureType).callingConvention)
+			RETURN ~(parameter.type.resolved IS SyntaxTree.ArrayType) & ~(parameter.type.resolved IS SyntaxTree.MathArrayType) OR (parameter.type.resolved IS SyntaxTree.ArrayType) & (cc IN SysvABIorWINAPI)
 		END
 		END
 	END PassBySingleReference;
 	END PassBySingleReference;
 
 
-	PROCEDURE PassInRegister(parameter: SyntaxTree.Parameter): BOOLEAN;
+	PROCEDURE PassInRegister(parameter: SyntaxTree.Parameter; cc: SyntaxTree.CallingConvention): BOOLEAN;
 	BEGIN
 	BEGIN
-		RETURN  ~parameter.type.IsComposite() OR PassBySingleReference(parameter)
+		RETURN  ~parameter.type.IsComposite() OR PassBySingleReference(parameter,cc)
 	END PassInRegister;
 	END PassInRegister;
 
 
 	PROCEDURE AddRegisterEntry(VAR queue: RegisterEntry; register: LONGINT; class: IntermediateCode.RegisterClass; type: IntermediateCode.Type);
 	PROCEDURE AddRegisterEntry(VAR queue: RegisterEntry; register: LONGINT; class: IntermediateCode.RegisterClass; type: IntermediateCode.Type);
@@ -14338,8 +14368,8 @@ TYPE
 		Global.GetSymbolSegmentedName(typeDeclaration,name);
 		Global.GetSymbolSegmentedName(typeDeclaration,name);
 	END GetRecordTypeName;
 	END GetRecordTypeName;
 
 
-	PROCEDURE ParametersSize(system: Global.System; procedureType: SyntaxTree.ProcedureType; isNested: BOOLEAN): LONGINT;
-	VAR parSize: LONGINT; parameter: SyntaxTree.Parameter;
+	PROCEDURE ParametersSize(system: Global.System; procedureType: SyntaxTree.ProcedureType; cc: SyntaxTree.CallingConvention; isNested: BOOLEAN): LONGINT;
+	VAR parSize: LONGINT; parameter: SyntaxTree.Parameter; 
 	BEGIN
 	BEGIN
 		parSize := 0;
 		parSize := 0;
 
 
@@ -14352,7 +14382,7 @@ TYPE
 		
 		
 		parameter :=procedureType.lastParameter;
 		parameter :=procedureType.lastParameter;
 		WHILE (parameter # NIL) DO
 		WHILE (parameter # NIL) DO
-			IF SysvABIorWINAPI(procedureType.callingConvention) THEN
+			IF cc IN SysvABIorWINAPI THEN
 				INC(parSize, system.addressSize); 
 				INC(parSize, system.addressSize); 
 			ELSE
 			ELSE
 				INC(parSize,system.SizeOfParameter(parameter));
 				INC(parSize,system.SizeOfParameter(parameter));
@@ -14387,13 +14417,13 @@ TYPE
 		RETURN scope # NIL;
 		RETURN scope # NIL;
 	END InCellScope;
 	END InCellScope;
 
 
-	PROCEDURE ProcedureParametersSize*(system: Global.System; procedure: SyntaxTree.Procedure): LONGINT;
+	PROCEDURE ProcedureParametersSize*(system: Global.System; procedure: SyntaxTree.Procedure; cc: SyntaxTree.CallingConvention): LONGINT;
 	BEGIN
 	BEGIN
 		(*IF (procedure.scope IS SyntaxTree.CellScope) & (procedure = procedure.scope(SyntaxTree.CellScope).constructor) & ~backend.cellsAreObjects THEN
 		(*IF (procedure.scope IS SyntaxTree.CellScope) & (procedure = procedure.scope(SyntaxTree.CellScope).constructor) & ~backend.cellsAreObjects THEN
 			RETURN 0
 			RETURN 0
 		ELSE
 		ELSE
 		*)
 		*)
-			RETURN ParametersSize(system,procedure.type(SyntaxTree.ProcedureType),IsNested(procedure));
+			RETURN ParametersSize(system,procedure.type(SyntaxTree.ProcedureType),cc, IsNested(procedure));
 		(*END;*)
 		(*END;*)
 	END ProcedureParametersSize;
 	END ProcedureParametersSize;
 
 
@@ -14439,15 +14469,6 @@ TYPE
 		RETURN instruction
 		RETURN instruction
 	END Conv;
 	END Conv;
 	
 	
-	PROCEDURE SysvABI( cc: LONGINT ): BOOLEAN;
-	BEGIN
-		RETURN (cc IN {SyntaxTree.CCallingConvention, SyntaxTree.DarwinCCallingConvention})
-	END SysvABI;
-
-	PROCEDURE SysvABIorWINAPI( cc: LONGINT ): BOOLEAN;
-	BEGIN
-		RETURN (cc IN {SyntaxTree.CCallingConvention, SyntaxTree.DarwinCCallingConvention, SyntaxTree.WinAPICallingConvention})
-	END SysvABIorWINAPI;
 
 
 	PROCEDURE Call*(position: Basic.Position;op: IntermediateCode.Operand; parSize: LONGINT): IntermediateCode.Instruction;
 	PROCEDURE Call*(position: Basic.Position;op: IntermediateCode.Operand; parSize: LONGINT): IntermediateCode.Instruction;
 	VAR instruction: IntermediateCode.Instruction;
 	VAR instruction: IntermediateCode.Instruction;

+ 2 - 0
source/FoxSemanticChecker.Mod

@@ -936,6 +936,8 @@ TYPE
 					ELSE
 					ELSE
 						procedureType.SetCallingConvention(SyntaxTree.CCallingConvention)
 						procedureType.SetCallingConvention(SyntaxTree.CCallingConvention)
 					END
 					END
+				ELSIF HasFlag(modifiers,Global.NamePlatformCC, position) THEN
+					procedureType.SetCallingConvention(SyntaxTree.PlatformCallingConvention); 
 				ELSIF HasFlag(modifiers, Global.NameNoReturn,position) THEN
 				ELSIF HasFlag(modifiers, Global.NameNoReturn,position) THEN
 					procedureType.SetNoReturn(TRUE);
 					procedureType.SetNoReturn(TRUE);
 				END;
 				END;

+ 1 - 0
source/FoxSyntaxTree.Mod

@@ -22,6 +22,7 @@ CONST
 	WinAPICallingConvention* =2;
 	WinAPICallingConvention* =2;
 	DarwinCCallingConvention* =3;
 	DarwinCCallingConvention* =3;
 	InterruptCallingConvention* = 4;
 	InterruptCallingConvention* = 4;
+	PlatformCallingConvention*= 5;
 
 
 	(** Access Flags *)
 	(** Access Flags *)
 	InternalRead* = 0;			(** can read symbol in same module *)
 	InternalRead* = 0;			(** can read symbol in same module *)