diff --git a/source/Cosmos.IL2CPU/.editorconfig b/source/Cosmos.IL2CPU/.editorconfig index 02fb045d2..a40820f7c 100644 --- a/source/Cosmos.IL2CPU/.editorconfig +++ b/source/Cosmos.IL2CPU/.editorconfig @@ -21,6 +21,12 @@ indent_size = 2 [IL/Call.cs] indent_size = 4 +[IL/Callvirt.cs] +indent_size = 4 + +[IL/Newobj.cs] +indent_size = 4 + [AppAssembler.cs] indent_size = 4 diff --git a/source/Cosmos.IL2CPU/IL/Call.cs b/source/Cosmos.IL2CPU/IL/Call.cs index 43e94ffc3..447cd7985 100644 --- a/source/Cosmos.IL2CPU/IL/Call.cs +++ b/source/Cosmos.IL2CPU/IL/Call.cs @@ -16,162 +16,196 @@ using Cosmos.Assembler; using SysReflection = System.Reflection; -namespace Cosmos.IL2CPU.X86.IL { - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Call)] - public class Call: ILOp { - // private string LabelName; - // private uint mResultSize; - // private uint? TotalArgumentSize = null; - // private bool mIsDebugger_Break = false; - // private uint[] ArgumentSizes = new uint[0]; - // private MethodInformation mMethodInfo; - // private MethodInformation mTargetMethodInfo; - // private string mNextLabelName; - // private uint mCurrentILOffset; - // private MethodBase mMethod; - - public Call(Cosmos.Assembler.Assembler aAsmblr) - : base(aAsmblr) { - } - - public static uint GetStackSizeToReservate(MethodBase aMethod) { - - var xMethodInfo = aMethod as SysReflection.MethodInfo; - uint xReturnSize = 0; - if (xMethodInfo != null) { - xReturnSize = SizeOfType(xMethodInfo.ReturnType); - } - if (xReturnSize == 0) { - return 0; - } - // todo: implement exception support - int xExtraStackSize = (int)Align(xReturnSize, 4); - var xParameters = aMethod.GetParameters(); - foreach (var xItem in xParameters) { - xExtraStackSize -= (int)Align(SizeOfType(xItem.ParameterType), 4); - } - if (!xMethodInfo.IsStatic) { - xExtraStackSize -= GetNativePointerSize(xMethodInfo); - } - if (xExtraStackSize > 0) { - return (uint)xExtraStackSize; - } - return 0; - } - - private static int GetNativePointerSize(SysReflection.MethodInfo xMethodInfo) - { - // old code, which goof up everything for structs - //return (int)Align(SizeOfType(xMethodInfo.DeclaringType), 4); - // TODO native pointer size, so that COSMOS could be 64 bit OS - return 4; - } - - public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { - var xOpMethod = aOpCode as OpMethod; - DoExecute(Assembler, aMethod, xOpMethod.Value, aOpCode, LabelName.Get(aMethod.MethodBase), DebugEnabled); - } - - public static void DoExecute(Cosmos.Assembler.Assembler Assembler, MethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aCurrent, string currentLabel, bool debugEnabled) +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Call)] + public class Call: ILOp { - DoExecute(Assembler, aCurrentMethod, aTargetMethod, aCurrent, currentLabel, ILOp.GetLabel(aCurrentMethod, aCurrent.NextPosition), debugEnabled); - } + // private string LabelName; + // private uint mResultSize; + // private uint? TotalArgumentSize = null; + // private bool mIsDebugger_Break = false; + // private uint[] ArgumentSizes = new uint[0]; + // private MethodInformation mMethodInfo; + // private MethodInformation mTargetMethodInfo; + // private string mNextLabelName; + // private uint mCurrentILOffset; + // private MethodBase mMethod; - public static void DoExecute(Cosmos.Assembler.Assembler Assembler, MethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aCurrent, string currentLabel, string nextLabel, bool debugEnabled) { - //if (aTargetMethod.IsVirtual) { - // Callvirt.DoExecute(Assembler, aCurrentMethod, aTargetMethod, aTargetMethodUID, aCurrentPosition); - // return; - //} - var xMethodInfo = aTargetMethod as SysReflection.MethodInfo; - - // mTargetMethodInfo = GetService().GetMethodInfo(mMethod - // , mMethod, mMethodDescription, null, mCurrentMethodInfo.DebugMode); - string xNormalAddress; - if (aTargetMethod.IsStatic || !aTargetMethod.IsVirtual || aTargetMethod.IsFinal) { - xNormalAddress = LabelName.Get(aTargetMethod); - } else { - xNormalAddress = LabelName.Get(aTargetMethod); - //throw new Exception("Call: non-concrete method called: '" + aTargetMethod.GetFullName() + "'"); - } - var xParameters = aTargetMethod.GetParameters(); - int xArgCount = xParameters.Length; - // todo: implement exception support - uint xExtraStackSize = GetStackSizeToReservate(aTargetMethod); - if (!aTargetMethod.IsStatic && debugEnabled) + public Call(Cosmos.Assembler.Assembler aAsmblr) + : base(aAsmblr) { - uint xThisOffset = 0; - foreach (var xItem in xParameters) - { - xThisOffset += Align(SizeOfType(xItem.ParameterType), 4); - } - var stackOffsetToCheck = xThisOffset; - DoNullReferenceCheck(Assembler, debugEnabled, stackOffsetToCheck); } - if (xExtraStackSize > 0) { - new CPUx86.Sub { - DestinationReg = CPUx86.Registers.ESP, - SourceValue = (uint)xExtraStackSize - }; - } - new CPUx86.Call { - DestinationLabel = xNormalAddress - }; + public static uint GetStackSizeToReservate(MethodBase aMethod) + { - uint xReturnSize=0; - if (xMethodInfo != null) - { - xReturnSize = SizeOfType(xMethodInfo.ReturnType); - } - if (aCurrentMethod != null) - { - EmitExceptionLogic(Assembler, aCurrentMethod, aCurrent, true, - delegate() - { - var xStackOffsetBefore = aCurrent.StackOffsetBeforeExecution; + var xMethodInfo = aMethod as SysReflection.MethodInfo; + uint xReturnSize = 0; + if (xMethodInfo != null) + { + xReturnSize = SizeOfType(xMethodInfo.ReturnType); + } + if (xReturnSize == 0) + { + return 0; + } - uint xPopSize = 0; - foreach (var type in aCurrent.StackPopTypes) - { - xPopSize += Align(SizeOfType(type), 4); - } + // todo: implement exception support + int xExtraStackSize = (int)Align(xReturnSize, 4); + var xParameters = aMethod.GetParameters(); + foreach (var xItem in xParameters) + { + xExtraStackSize -= (int)Align(SizeOfType(xItem.ParameterType), 4); + } + if (!xMethodInfo.IsStatic) + { + xExtraStackSize -= GetNativePointerSize(xMethodInfo); + } + if (xExtraStackSize > 0) + { + return (uint)xExtraStackSize; + } + return 0; + } - var xResultSize = xReturnSize; - if (xResultSize % 4 != 0) - { - xResultSize += 4 - (xResultSize % 4); - } + private static int GetNativePointerSize(SysReflection.MethodInfo xMethodInfo) + { + // old code, which goof up everything for structs + //return (int)Align(SizeOfType(xMethodInfo.DeclaringType), 4); + // TODO native pointer size, so that COSMOS could be 64 bit OS + return 4; + } - if (xStackOffsetBefore > (xPopSize + xResultSize)) - { - if (xResultSize > 0) - { - new Comment("Cleanup return"); - // cleanup result values - for (int i = 0; i < xResultSize / 4; i++) - { - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; - } - } + public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) + { + var xOpMethod = aOpCode as OpMethod; + DoExecute(Assembler, aMethod, xOpMethod.Value, aOpCode, LabelName.Get(aMethod.MethodBase), DebugEnabled); + } - if (xPopSize > 0) - { - var xExtraStack = xStackOffsetBefore - xPopSize - xResultSize; - new Comment("Cleanup extra stack"); - // cleanup result values - for (int i = 0; i < xExtraStack / 4; i++) - { - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; - } - } - } - }, nextLabel); + public static void DoExecute(Cosmos.Assembler.Assembler Assembler, MethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aCurrent, string currentLabel, bool debugEnabled) + { + DoExecute(Assembler, aCurrentMethod, aTargetMethod, aCurrent, currentLabel, ILOp.GetLabel(aCurrentMethod, aCurrent.NextPosition), debugEnabled); + } - } - if (xMethodInfo == null || SizeOfType(xMethodInfo.ReturnType) == 0) { - return; - } + public static void DoExecute(Cosmos.Assembler.Assembler Assembler, MethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aCurrent, string currentLabel, string nextLabel, bool debugEnabled) + { + //if (aTargetMethod.IsVirtual) { + // Callvirt.DoExecute(Assembler, aCurrentMethod, aTargetMethod, aTargetMethodUID, aCurrentPosition); + // return; + //} + var xMethodInfo = aTargetMethod as SysReflection.MethodInfo; + // mTargetMethodInfo = GetService().GetMethodInfo(mMethod + // , mMethod, mMethodDescription, null, mCurrentMethodInfo.DebugMode); + string xNormalAddress; + if (aTargetMethod.IsStatic + || !aTargetMethod.IsVirtual + || aTargetMethod.IsFinal) + { + xNormalAddress = LabelName.Get(aTargetMethod); + } + else + { + xNormalAddress = LabelName.Get(aTargetMethod); + + //throw new Exception("Call: non-concrete method called: '" + aTargetMethod.GetFullName() + "'"); + } + var xParameters = aTargetMethod.GetParameters(); + int xArgCount = xParameters.Length; + + // todo: implement exception support + uint xExtraStackSize = GetStackSizeToReservate(aTargetMethod); + if (!aTargetMethod.IsStatic && debugEnabled) + { + uint xThisOffset = 0; + foreach (var xItem in xParameters) + { + xThisOffset += Align(SizeOfType(xItem.ParameterType), 4); + } + var stackOffsetToCheck = xThisOffset; + DoNullReferenceCheck(Assembler, debugEnabled, stackOffsetToCheck); + } + + if (xExtraStackSize > 0) + { + new CPUx86.Sub + { + DestinationReg = CPUx86.Registers.ESP, + SourceValue = (uint)xExtraStackSize + }; + } + new CPUx86.Call + { + DestinationLabel = xNormalAddress + }; + + uint xReturnSize = 0; + if (xMethodInfo != null) + { + xReturnSize = SizeOfType(xMethodInfo.ReturnType); + } + if (aCurrentMethod != null) + { + EmitExceptionLogic(Assembler, aCurrentMethod, aCurrent, true, + delegate() + { + var xStackOffsetBefore = aCurrent.StackOffsetBeforeExecution; + + uint xPopSize = 0; + foreach (var type in aCurrent.StackPopTypes) + { + xPopSize += Align(SizeOfType(type), 4); + } + + var xResultSize = xReturnSize; + if (xResultSize % 4 != 0) + { + xResultSize += 4 - (xResultSize % 4); + } + new Comment("xStackOffsetBefore = " + xStackOffsetBefore); + new Comment("xPopSize = " + xPopSize); + new Comment("xResultSize = " + xResultSize); + if (xStackOffsetBefore > xResultSize) + { + if (xResultSize > 0) + { + new Comment("Cleanup return"); + + // cleanup result values + for (int i = 0; i < xResultSize / 4; i++) + { + new CPUx86.Add + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 + }; + } + } + + if (xStackOffsetBefore > 0) + { + var xExtraStack = xStackOffsetBefore - xPopSize - xResultSize; + new Comment("Cleanup extra stack"); + + // cleanup result values + for (int i = 0; i < xStackOffsetBefore / 4; i++) + { + new CPUx86.Add + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 + }; + } + } + } + }, nextLabel); + + } + if (xMethodInfo == null + || SizeOfType(xMethodInfo.ReturnType) == 0) + { + return; + } + + } } - } } diff --git a/source/Cosmos.IL2CPU/IL/Callvirt.cs b/source/Cosmos.IL2CPU/IL/Callvirt.cs index 02f56a983..3ecd8e2bf 100644 --- a/source/Cosmos.IL2CPU/IL/Callvirt.cs +++ b/source/Cosmos.IL2CPU/IL/Callvirt.cs @@ -32,10 +32,13 @@ namespace Cosmos.IL2CPU.X86.IL // mTargetMethodInfo = GetService().GetMethodInfo(mMethod // , mMethod, mMethodDescription, null, mCurrentMethodInfo.DebugMode); string xNormalAddress = ""; - if (aTargetMethod.IsStatic || !aTargetMethod.IsVirtual || aTargetMethod.IsFinal) + if (aTargetMethod.IsStatic + || !aTargetMethod.IsVirtual + || aTargetMethod.IsFinal) { xNormalAddress = LabelName.Get(aTargetMethod); } + // mMethodIdentifier = GetService().GetMethodIdLabel(mMethod); int xArgCount = aTargetMethod.GetParameters().Length; @@ -45,6 +48,7 @@ namespace Cosmos.IL2CPU.X86.IL { xReturnSize = Align(SizeOfType(xMethodInfo.ReturnType), 4); } + // Extracted from MethodInformation: Calculated offset // var xRoundedSize = ReturnSize; //if (xRoundedSize % 4 > 0) { @@ -76,9 +80,15 @@ namespace Cosmos.IL2CPU.X86.IL { if (xExtraStackSize > 0) { - new CPUx86.Sub {DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xExtraStackSize}; + new CPUx86.Sub + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xExtraStackSize + }; } - new CPUx86.Call {DestinationLabel = xNormalAddress}; + new CPUx86.Call + { + DestinationLabel = xNormalAddress + }; } else { @@ -88,10 +98,22 @@ namespace Cosmos.IL2CPU.X86.IL * $esp + mThisOffset This */ - new CPUx86.Mov {DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = (int)xThisOffset}; - new CPUx86.Mov {DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true}; - new CPUx86.Push {DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true}; - new CPUx86.Push {DestinationValue = aTargetMethodUID}; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = (int)xThisOffset + }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true + }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true + }; + new CPUx86.Push + { + DestinationValue = aTargetMethodUID + }; new CPUx86.Call { DestinationLabel = LabelName.Get(VTablesImplRefs.GetMethodAddressForTypeRef) @@ -112,7 +134,10 @@ namespace Cosmos.IL2CPU.X86.IL // mLabelName + "_AfterAddressCheck", // true, // xEmitCleanup ); - new CPUx86.Pop {DestinationReg = CPU.RegistersEnum.ECX}; + new CPUx86.Pop + { + DestinationReg = CPU.RegistersEnum.ECX + }; new Label(xCurrentMethodLabel + ".AfterAddressCheck"); if (xMethodInfo.DeclaringType == typeof(object)) @@ -124,13 +149,23 @@ namespace Cosmos.IL2CPU.X86.IL * $esp + mThisOffset This */ // we need to see if $this is a boxed object, and if so, we need to box it - new CPUx86.Mov {DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = (int)xThisOffset}; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = (int)xThisOffset + }; + //new CPUx86.Compare { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = ( ( uint )InstanceTypeEnum.BoxedValueType ), Size = 32 }; // EAX contains the handle now, lets dereference it - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true + }; - new CPUx86.Compare {DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = (int)InstanceTypeEnum.BoxedValueType, Size = 32}; + new CPUx86.Compare + { + DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = (int)InstanceTypeEnum.BoxedValueType, Size = 32 + }; /* * On the stack now: @@ -140,9 +175,12 @@ namespace Cosmos.IL2CPU.X86.IL * ECX contains the method to call * EAX contains the type pointer (not the handle!!) */ - new CPUx86.ConditionalJump {Condition = CPUx86.ConditionalTestEnum.NotEqual, DestinationLabel = xCurrentMethodLabel + ".NotBoxedThis"}; + new CPUx86.ConditionalJump + { + Condition = CPUx86.ConditionalTestEnum.NotEqual, DestinationLabel = xCurrentMethodLabel + ".NotBoxedThis" + }; - /* + /* * On the stack now: * $esp Params * $esp + mThisOffset This @@ -151,9 +189,15 @@ namespace Cosmos.IL2CPU.X86.IL * EAX contains the type pointer (not the handle!!) */ - new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = ( uint )ObjectImpl.FieldDataOffset }; + new CPUx86.Add + { + DestinationReg = CPUx86.Registers.EAX, SourceValue = (uint)ObjectImpl.FieldDataOffset + }; - new CPUx86.Mov {DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)xThisOffset, SourceReg = CPUx86.Registers.EAX}; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)xThisOffset, SourceReg = CPUx86.Registers.EAX + }; /* * On the stack now: * $esp Params @@ -165,9 +209,15 @@ namespace Cosmos.IL2CPU.X86.IL new Label(xCurrentMethodLabel + ".NotBoxedThis"); if (xExtraStackSize > 0) { - new CPUx86.Sub {DestinationReg = CPUx86.Registers.ESP, SourceValue = xExtraStackSize}; + new CPUx86.Sub + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = xExtraStackSize + }; } - new CPUx86.Call {DestinationReg = CPUx86.Registers.ECX}; + new CPUx86.Call + { + DestinationReg = CPUx86.Registers.ECX + }; new Label(xCurrentMethodLabel + ".AfterNotBoxedThis"); } ILOp.EmitExceptionLogic(Assembler, aMethod, aOp, true, @@ -192,10 +242,14 @@ namespace Cosmos.IL2CPU.X86.IL if (xResultSize > 0) { new Comment("Cleanup return"); + // cleanup result values for (int i = 0; i < xResultSize / 4; i++) { - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; + new CPUx86.Add + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 + }; } } @@ -203,10 +257,14 @@ namespace Cosmos.IL2CPU.X86.IL { var xExtraStack = xStackOffsetBefore - xPopSize - xResultSize; new Comment("Cleanup extra stack"); + // cleanup result values for (int i = 0; i < xExtraStack / 4; i++) { - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; + new CPUx86.Add + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 + }; } } } diff --git a/source/Cosmos.IL2CPU/IL/Newobj.cs b/source/Cosmos.IL2CPU/IL/Newobj.cs index 7ea377e32..d762b5113 100644 --- a/source/Cosmos.IL2CPU/IL/Newobj.cs +++ b/source/Cosmos.IL2CPU/IL/Newobj.cs @@ -10,7 +10,7 @@ using SysReflection = System.Reflection; namespace Cosmos.IL2CPU.X86.IL { [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Newobj)] - public class Newobj : ILOp + public class Newobj: ILOp { public Newobj(Cosmos.Assembler.Assembler aAsmblr) : base(aAsmblr) @@ -26,7 +26,7 @@ namespace Cosmos.IL2CPU.X86.IL Assemble(Assembler, aMethod, xMethod, xCurrentLabel, xType, xMethod.Value); } - public static void Assemble(Cosmos.Assembler.Assembler aAssembler, MethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor) + public static void Assemble(Cosmos.Assembler.Assembler aAssembler, MethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor) { // call cctor: if (aMethod != null) @@ -34,7 +34,10 @@ namespace Cosmos.IL2CPU.X86.IL var xCctor = (objectType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault(); if (xCctor != null) { - new CPUx86.Call { DestinationLabel = LabelName.Get(xCctor) }; + new CPUx86.Call + { + DestinationLabel = LabelName.Get(xCctor) + }; ILOp.EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck"); new Label(".AfterCCTorExceptionCheck"); } @@ -43,6 +46,7 @@ namespace Cosmos.IL2CPU.X86.IL if (objectType.IsValueType) { #region Valuetypes + new Comment("ValueType"); /* * Current sitation on stack: @@ -67,6 +71,7 @@ namespace Cosmos.IL2CPU.X86.IL { throw new Exception("ValueType storage size cannot be 0."); } + //var xStorageSize = aCtorDeclTypeInfo.StorageSize; uint xArgSize = 0; @@ -82,28 +87,44 @@ namespace Cosmos.IL2CPU.X86.IL new Comment("Shift: " + xShift); if (xShift < 0) { - new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)Math.Abs(xShift) }; + new CPUx86.Sub + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)Math.Abs(xShift) + }; } else if (xShift > 0) { - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xShift }; + new CPUx86.Add + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xShift + }; } + // push struct ptr - new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.ESP + }; + // Shift args foreach (var xParam in xParameterList) { uint xArgSizeForThis = Align(SizeOfType(xParam.ParameterType), 4); for (int i = 1; i <= xArgSizeForThis / 4; i++) { - new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)xStorageSize }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)xStorageSize + }; } } new Call(aAssembler).Execute(aMethod, xMethod); + // Need to put these *after* the call because the Call pops the args from the stack // and we have mucked about on the stack, so this makes it right before the next // op. + #endregion Valuetypes } else @@ -114,51 +135,113 @@ namespace Cosmos.IL2CPU.X86.IL // array length + 8 bool xHasCalcSize = false; + // try calculating size: if (constructor.DeclaringType == typeof(string)) { - if (xParams.Length == 1 && xParams[0].ParameterType == typeof(char[])) + if (xParams.Length == 1 + && xParams[0].ParameterType == typeof(char[])) { xHasCalcSize = true; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true + }; + // EAX contains a memory handle now, lets dereference it to a pointer - new CPUx86.Mov {DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.RegistersEnum.EAX, SourceIsIndirect = true}; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true, SourceDisplacement = 8 }; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EDX, SourceValue = 2 }; - new CPUx86.Multiply { DestinationReg = CPUx86.Registers.EDX }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.RegistersEnum.EAX, SourceIsIndirect = true + }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true, SourceDisplacement = 8 + }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EDX, SourceValue = 2 + }; + new CPUx86.Multiply + { + DestinationReg = CPUx86.Registers.EDX + }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.EAX + }; } - else if (xParams.Length == 3 && xParams[0].ParameterType == typeof(char[]) && xParams[1].ParameterType == typeof(int) && xParams[2].ParameterType == typeof(int)) + else if (xParams.Length == 3 + && xParams[0].ParameterType == typeof(char[]) + && xParams[1].ParameterType == typeof(int) + && xParams[2].ParameterType == typeof(int)) { xHasCalcSize = true; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true }; - new CPUx86.ShiftLeft { DestinationReg = CPUx86.Registers.EAX, SourceValue = 1 }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true + }; + new CPUx86.ShiftLeft + { + DestinationReg = CPUx86.Registers.EAX, SourceValue = 1 + }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.EAX + }; } - else if (xParams.Length == 2 && xParams[0].ParameterType == typeof(char) && xParams[1].ParameterType == typeof(int)) + else if (xParams.Length == 2 + && xParams[0].ParameterType == typeof(char) + && xParams[1].ParameterType == typeof(int)) { xHasCalcSize = true; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true }; - new CPUx86.ShiftLeft { DestinationReg = CPUx86.Registers.EAX, SourceValue = 1 }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true + }; + new CPUx86.ShiftLeft + { + DestinationReg = CPUx86.Registers.EAX, SourceValue = 1 + }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.EAX + }; } else throw new NotImplementedException("In NewObj, a string ctor implementation is missing!"); } uint xMemSize = GetStorageSize(objectType); int xExtraSize = 12; // additional size for set values after alloc - new CPUx86.Push { DestinationValue = (uint)(xMemSize + xExtraSize) }; + new CPUx86.Push + { + DestinationValue = (uint)(xMemSize + xExtraSize) + }; if (xHasCalcSize) { - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX }; + new CPUx86.Pop + { + DestinationReg = CPUx86.Registers.EAX + }; + new CPUx86.Add + { + DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX + }; } // todo: probably we want to check for exceptions after calling Alloc - new CPUx86.Call { DestinationLabel = LabelName.Get(GCImplementationRefs.AllocNewObjectRef) }; + new CPUx86.Call + { + DestinationLabel = LabelName.Get(GCImplementationRefs.AllocNewObjectRef) + }; new Label(".AfterAlloc"); - new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true + }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true + }; // it's on the stack now 3 times. Once from the Alloc return value, twice from the pushes @@ -175,12 +258,30 @@ namespace Cosmos.IL2CPU.X86.IL // todo: use a cleaner approach here. this class shouldnt assemble the string string strTypeId = GetTypeIDLabel(constructor.DeclaringType); - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true }; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EBX, SourceRef = Cosmos.Assembler.ElementReference.New(strTypeId), SourceIsIndirect = true }; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EBX }; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = (uint)InstanceTypeEnum.NormalObject, Size = 32 }; - new CPUx86.Mov { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 8, SourceValue = (uint)xGCFieldCount, Size = 32 }; + new CPUx86.Pop + { + DestinationReg = CPUx86.Registers.EAX + }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true + }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EBX, SourceRef = Cosmos.Assembler.ElementReference.New(strTypeId), SourceIsIndirect = true + }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EBX + }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = (uint)InstanceTypeEnum.NormalObject, Size = 32 + }; + new CPUx86.Mov + { + DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 8, SourceValue = (uint)xGCFieldCount, Size = 32 + }; uint xSize = (uint)(((from item in xParams let xQSize = Align(SizeOfType(item.ParameterType), 4) select (int)xQSize).Take(xParams.Length).Sum())); @@ -191,16 +292,28 @@ namespace Cosmos.IL2CPU.X86.IL new Comment(aAssembler, String.Format("Arg {0}: {1}", xParam.Name, xParamSize)); for (int i = 0; i < xParamSize; i += 4) { - new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize + 4) }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize + 4) + }; } } - new CPUx86.Call { DestinationLabel = LabelName.Get(constructor) }; + new CPUx86.Call + { + DestinationLabel = LabelName.Get(constructor) + }; if (aMethod != null) { - new CPUx86.Test { DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 }; + new CPUx86.Test + { + DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 + }; string xNoErrorLabel = currentLabel + ".NoError" + LabelName.LabelCount.ToString(); - new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = xNoErrorLabel }; + new CPUx86.ConditionalJump + { + Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = xNoErrorLabel + }; //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ ) //{ @@ -213,8 +326,13 @@ namespace Cosmos.IL2CPU.X86.IL // }; //} PushAlignedParameterSize(constructor); + // an exception occurred, we need to cleanup the stack, and jump to the exit - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; + new CPUx86.Add + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 + }; + //new Comment(aAssembler, "[ Newobj.Execute cleanup start count = " + aAssembler.Stack.Count.ToString() + " ]"); //foreach( var xStackInt in Assembler.Stack ) //{ @@ -225,7 +343,10 @@ namespace Cosmos.IL2CPU.X86.IL Jump_Exception(aMethod); new Label(xNoErrorLabel); } - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Pop + { + DestinationReg = CPUx86.Registers.EAX + }; //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ ) //{ @@ -239,7 +360,10 @@ namespace Cosmos.IL2CPU.X86.IL //} PushAlignedParameterSize(constructor); - new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Push + { + DestinationReg = CPUx86.Registers.EAX + }; } } @@ -252,7 +376,10 @@ namespace Cosmos.IL2CPU.X86.IL for (int i = 0; i < xParams.Length; i++) { xSize = SizeOfType(xParams[i].ParameterType); - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = Align(xSize, 4) }; + new CPUx86.Add + { + DestinationReg = CPUx86.Registers.ESP, SourceValue = Align(xSize, 4) + }; } new Comment("[ Newobj.PushAlignedParameterSize end ]"); }