From d6a2c080fa5317915863574efc0ead4fae86356a Mon Sep 17 00:00:00 2001 From: mterwoord_cp <7cd3fd84a0151ea055c2f79e4d2eef9576fe9afesxUZAwxD> Date: Mon, 31 Aug 2009 16:47:03 +0000 Subject: [PATCH] --- source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs | 613 ++++++++---------- source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stloc.cs | 66 +- source2/IL2PCU/Cosmos.IL2CPU.X86/ILOp.cs | 5 + source2/IL2PCU/Cosmos.IL2CPU/Assembler.cs | 4 +- .../IL2PCU/Cosmos.IL2CPU/Cosmos.IL2CPU.csproj | 1 + source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs | 75 +++ .../MethodAndTypeLabelsHolder.cs | 12 + source2/IL2PCU/Cosmos.IL2CPU/StackContents.cs | 8 + 8 files changed, 423 insertions(+), 361 deletions(-) create mode 100644 source2/IL2PCU/Cosmos.IL2CPU/MethodAndTypeLabelsHolder.cs diff --git a/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs b/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs index 9fcd0ed97..f49697cfa 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Newobj.cs @@ -5,370 +5,299 @@ using CPUx86 = Indy.IL2CPU.Assembler.X86; using Cosmos.IL2CPU.ILOpCodes; namespace Cosmos.IL2CPU.X86.IL { - [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Newobj )] - public class Newobj : ILOp - { - public Newobj( Cosmos.IL2CPU.Assembler aAsmblr ) - : base( aAsmblr ) - { - } + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Newobj)] + public class Newobj : ILOp + { + public Newobj(Cosmos.IL2CPU.Assembler aAsmblr) + : base(aAsmblr) + { + } - public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) - { - OpMethod xMethod = ( OpMethod )aOpCode; - // Is this checking for plugs? - // if (DynamicMethodEmit.GetHasDynamicMethod(CtorDef)) { - // CtorDef = DynamicMethodEmit.GetDynamicMethod(CtorDef); - // } + public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) + { + OpMethod xMethod = (OpMethod)aOpCode; + string xCurrentLabel = GetLabel(aMethod, aOpCode); + // TODO: enable this again + // if (DynamicMethodEmit.GetHasDynamicMethod(CtorDef)) { + // CtorDef = DynamicMethodEmit.GetDynamicMethod(CtorDef); + // } - //var xAllocInfo = GetService().GetMethodInfo(GCImplementationRefs.AllocNewObjectRef, false); + //var xAllocInfo = GetService().GetMethodInfo(GCImplementationRefs.AllocNewObjectRef, false); - // Assemble( - // Assembler, - // CtorDef, - // GetService().GetTypeIdLabel(CtorDef.DeclaringType), - // CurrentLabel, - // MethodInformation, - // (int)ILOffset, - // mNextLabel, - // GetService().GetTypeInfo(CtorDef.DeclaringType), - // GetService().GetMethodInfo(CtorDef, false), - // GetServiceProvider(), - // xAllocInfo.LabelName - // ); - // } - // - // public static void Assemble( - // Assembler.Assembler aAssembler, - // MethodBase aCtorDef, - // string aTypeId, - // string aCurrentLabel, - // MethodInformation aCurrentMethodInformation, - // int aCurrentILOffset, - // string aNextLabel, - // TypeInformation aCtorDeclTypeInfo, - // MethodInformation aCtorMethodInfo, - // IServiceProvider aServiceProvider, - // string aAllocMemLabel - // ) + // Assemble( + // Assembler, + // CtorDef, + // GetService().GetTypeIdLabel(CtorDef.DeclaringType), + // CurrentLabel, + // MethodInformation, + // (int)ILOffset, + // mNextLabel, + // GetService().GetTypeInfo(CtorDef.DeclaringType), + // GetService().GetMethodInfo(CtorDef, false), + // GetServiceProvider(), + // xAllocInfo.LabelName + // ); + // } + // + // public static void Assemble( + // Assembler.Assembler aAssembler, + // MethodBase aCtorDef, + // string aTypeId, + // string aCurrentLabel, + // MethodInformation aCurrentMethodInformation, + // int aCurrentILOffset, + // string aNextLabel, + // TypeInformation aCtorDeclTypeInfo, + // MethodInformation aCtorMethodInfo, + // IServiceProvider aServiceProvider, + // string aAllocMemLabel + // ) - //TODO: What is this for? - // if (aCtorDef != null) { - // //if (!aCtorDef.DeclaringType.FullName.StartsWith("Indy.IL2CPU.MultiArrayEmit.ContType")) - // // Engine.QueueMethod(aCtorDef); - // } else { - // throw new ArgumentNullException("aCtorDef"); - // } + //TODO: What is this for? + // if (aCtorDef != null) { + // //if (!aCtorDef.DeclaringType.FullName.StartsWith("Indy.IL2CPU.MultiArrayEmit.ContType")) + // // Engine.QueueMethod(aCtorDef); + // } else { + // throw new ArgumentNullException("aCtorDef"); + // } - var xType = xMethod.Value.DeclaringType; + var xType = xMethod.Value.DeclaringType; - // If not ValueType, then we need gc - if( !xType.IsValueType ) - { - var xParams = xMethod.Value.GetParameters(); - for( int i = 1; i < xParams.Length; i++ ) - { - Assembler.Stack.Pop(); - } + // If not ValueType, then we need gc + if (!xType.IsValueType) + { + var xParams = xMethod.Value.GetParameters(); + for (int i = 1; i < xParams.Length; i++) + { + Assembler.Stack.Pop(); + } - uint xMemSize = GetFieldStorageSize( xType ); - int xExtraSize = 20; - new CPUx86.Push { DestinationValue = ( uint )( xMemSize + xExtraSize ) }; + uint xMemSize = GetFieldStorageSize(xType); + int xExtraSize = 20; + new CPUx86.Push { DestinationValue = (uint)(xMemSize + xExtraSize) }; - new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName( GCImplementationRefs.AllocNewObjectRef ) }; - new CPUx86.Test { DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 }; - 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 }; - //var xIncRefInfo = aServiceProvider.GetService().GetMethodInfo( GCImplementationRefs.IncRefCountRef, false ); - // TODO: Why call incref twice? - // new Assembler.X86.Call { DestinationLabel = xIncRefInfo.LabelName }; - // new CPUx86.Call { DestinationLabel = xIncRefInfo.LabelName }; + // todo: probably we want to check for exceptions after calling Alloc + new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(GCImplementationRefs.AllocNewObjectRef) }; + 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 }; + + // We IncRef here twice because it's effectively pushed on the stack twice: + // * once for the .ctor parameter + // * once for the "returnvalue" of the newobj il op - new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName( GCImplementationRefs.IncRefCountRef ) }; + // todo: probably we want to check for exceptions after calling IncRef + new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(GCImplementationRefs.IncRefCountRef) }; + new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(GCImplementationRefs.IncRefCountRef) }; - uint xObjSize = 0; - //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values - //where item.NeedsGC - //select item ).Count(); + uint xObjSize = 0; + //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values + //where item.NeedsGC + //select item ).Count(); - //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values - //where item.NeedsGC - //select item ).Count(); - int xGCFieldCount = xType.GetFields().Count( x => x.FieldType.IsValueType ); + //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values + //where item.NeedsGC + //select item ).Count(); + int xGCFieldCount = xType.GetFields().Count(x => x.FieldType.IsValueType); - string strTypeId = xMethod.Value.DeclaringType.FullName; + string strTypeId = xMethod.Value.DeclaringType.FullName; - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.Move { DestinationReg = CPUx86.Registers.EBX, SourceRef = Indy.IL2CPU.Assembler.ElementReference.New( strTypeId ), SourceIsIndirect = true }; - new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EBX }; - new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = ( uint )InstanceTypeEnum.NormalObject, Size = 32 }; - new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 8, SourceValue = ( uint )xGCFieldCount, Size = 32 }; - uint xSize = ( uint )( ( ( from item in xParams - let xQSize = Align(GetFieldStorageSize( item.GetType() ), 4 ) - select ( int )xQSize ).Take( xParams.Length - 1 ).Sum() ) ); + new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Move { DestinationReg = CPUx86.Registers.EBX, SourceRef = Indy.IL2CPU.Assembler.ElementReference.New(strTypeId), SourceIsIndirect = true }; + new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EBX }; + new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = (uint)InstanceTypeEnum.NormalObject, Size = 32 }; + new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = 8, SourceValue = (uint)xGCFieldCount, Size = 32 }; + uint xSize = (uint)(((from item in xParams + let xQSize = Align(GetFieldStorageSize(item.GetType()), 4) + select (int)xQSize).Take(xParams.Length - 1).Sum())); - for( int i = 1; i < xParams.Length; i++ ) - { - new Comment( String.Format( "Arg {0}: {1}", i, GetFieldStorageSize( xParams[i].GetType() ) ) ); - for( int j = 0; j < GetFieldStorageSize( xParams[ i ].GetType() ); j += 4 ) - { - new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = ( int )( xSize + 4 ) }; - } - } + for (int i = 1; i < xParams.Length; i++) + { + new Comment(String.Format("Arg {0}: {1}", i, GetFieldStorageSize(xParams[i].GetType()))); + for (int j = 0; j < GetFieldStorageSize(xParams[i].GetType()); j += 4) + { + new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize + 4) }; + } + } - new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName( xMethod.Value ) }; - new CPUx86.Test { DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 }; - //new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = aCurrentLabel + "_NO_ERROR_4" }; - throw new Exception("Notimpl"); + new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(xMethod.Value) }; + new CPUx86.Test { DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 }; + new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = xCurrentLabel + "_NO_ERROR_4" }; - //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ ) - //{ - // new CPUx86.Add - // { - // DestinationReg = CPUx86.Registers.ESP, - // SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0 - // ? aCtorMethodInfo.Arguments[ i ].Size - // : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 ) - // }; - //} - PushAlignedParameterSize( xMethod.Value ); + //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ ) + //{ + // new CPUx86.Add + // { + // DestinationReg = CPUx86.Registers.ESP, + // SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0 + // ? aCtorMethodInfo.Arguments[ i ].Size + // : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 ) + // }; + //} + PushAlignedParameterSize(xMethod.Value); +// an exception occurred, we need to cleanup the stack, and jump to the exit + new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; + foreach (var xStackInt in Assembler.Stack) + { + new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xStackInt.Size }; + } + JumpToExceptionExit(aMethod); - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; - //foreach( StackContent xStackInt in Assembler.Stack ) - //{ - // new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = ( uint )xStackInt.Size }; - //} - //Call.EmitExceptionLogic( aAssembler, - // ( uint )aCurrentILOffset, - // aCurrentMethodInformation, - // aCurrentLabel + "_NO_ERROR_4", - // false, - // null ); - //new Label( aCurrentLabel + "_NO_ERROR_4" ); - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; + new Label(xCurrentLabel + "_NO_ERROR_4"); + new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ ) - //{ - // new CPUx86.Add - // { - // DestinationReg = CPUx86.Registers.ESP, - // SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0 - // ? aCtorMethodInfo.Arguments[ i ].Size - // : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 ) - // }; - //} - PushAlignedParameterSize( xMethod.Value ); + //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ ) + //{ + // new CPUx86.Add + // { + // DestinationReg = CPUx86.Registers.ESP, + // SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0 + // ? aCtorMethodInfo.Arguments[ i ].Size + // : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 ) + // }; + //} + PushAlignedParameterSize(xMethod.Value); - new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; - Assembler.Stack.Push( 4, xMethod.Value.DeclaringType ); - throw new NotImplementedException(); - } - else - { - // /* - // * Current sitation on stack: - // * $ESP Arg - // * $ESP+.. other items - // * - // * What should happen: - // * + The stack should be increased to allow space to contain: - // * + .ctor arguments - // * + struct _pointer_ (ref to start of emptied space) - // * + empty space for struct - // * + arguments should be copied to the new place - // * + old place where arguments were should be cleared - // * + pointer should be set - // * + call .ctor - // */ - // var xStorageSize = aCtorDeclTypeInfo.StorageSize; - // if (xStorageSize % 4 != 0) - // { - // xStorageSize += 4 - (xStorageSize % 4); - // } - // uint xArgSize = 0; - // foreach (var xArg in aCtorMethodInfo.Arguments.Skip(1)) - // { - // xArgSize += xArg.Size + (xArg.Size % 4 == 0 - // ? 0 - // : (4 - (xArg.Size % 4))); - // } - // int xExtraArgSize = (int)(xStorageSize - xArgSize); - // if (xExtraArgSize < 0) - // { - // xExtraArgSize = 0; - // } - // if (xExtraArgSize>0) - // { - // new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xExtraArgSize }; - // } - // new CPUx86.Push { DestinationReg = Registers.ESP }; - // aAssembler.Stack.Push(new StackContent(4)); - // //at this point, we need to move copy all arguments over. - // for (int i = 0;i<(xArgSize/4);i++) - // { - // new CPUx86.Push { DestinationReg = Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xStorageSize + 4) }; // + 4 because the ptr is pushed too - // new CPUx86.Move { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xStorageSize + 4 + 4), SourceValue = 0, Size = 32 }; - // } - // var xCall = new Call(aCtorDef, - // (uint)aCurrentILOffset, - // true, - // aNextLabel); - // xCall.SetServiceProvider(aServiceProvider); - // xCall.Assembler = aAssembler; - // xCall.Assemble(); - // aAssembler.Stack.Push(new StackContent((int)xStorageSize, - // aCtorDef.DeclaringType)); - throw new NotImplementedException(); - } - } + new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; + Assembler.Stack.Push(4, xMethod.Value.DeclaringType); + } + else + { + // /* + // * Current sitation on stack: + // * $ESP Arg + // * $ESP+.. other items + // * + // * What should happen: + // * + The stack should be increased to allow space to contain: + // * + .ctor arguments + // * + struct _pointer_ (ref to start of emptied space) + // * + empty space for struct + // * + arguments should be copied to the new place + // * + old place where arguments were should be cleared + // * + pointer should be set + // * + call .ctor + // */ + // var xStorageSize = aCtorDeclTypeInfo.StorageSize; + // if (xStorageSize % 4 != 0) + // { + // xStorageSize += 4 - (xStorageSize % 4); + // } + // uint xArgSize = 0; + // foreach (var xArg in aCtorMethodInfo.Arguments.Skip(1)) + // { + // xArgSize += xArg.Size + (xArg.Size % 4 == 0 + // ? 0 + // : (4 - (xArg.Size % 4))); + // } + // int xExtraArgSize = (int)(xStorageSize - xArgSize); + // if (xExtraArgSize < 0) + // { + // xExtraArgSize = 0; + // } + // if (xExtraArgSize>0) + // { + // new CPUx86.Sub { DestinationReg = CPUx86.Registers.ESP, SourceValue = (uint)xExtraArgSize }; + // } + // new CPUx86.Push { DestinationReg = Registers.ESP }; + // aAssembler.Stack.Push(new StackContent(4)); + // //at this point, we need to move copy all arguments over. + // for (int i = 0;i<(xArgSize/4);i++) + // { + // new CPUx86.Push { DestinationReg = Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xStorageSize + 4) }; // + 4 because the ptr is pushed too + // new CPUx86.Move { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xStorageSize + 4 + 4), SourceValue = 0, Size = 32 }; + // } + // var xCall = new Call(aCtorDef, + // (uint)aCurrentILOffset, + // true, + // aNextLabel); + // xCall.SetServiceProvider(aServiceProvider); + // xCall.Assembler = aAssembler; + // xCall.Assemble(); + // aAssembler.Stack.Push(new StackContent((int)xStorageSize, + // aCtorDef.DeclaringType)); + throw new NotImplementedException(); + } + } - private uint Align( uint aSize, uint aAlign ) - { - return aSize % 4 == 0 ? aSize : ( ( aSize / aAlign ) * aAlign ) + 1; - } + private void JumpToExceptionExit(MethodInfo aMethod) + { + // todo: port to numeric labels + new CPUx86.Jump{DestinationLabel= MethodInfoLabelGenerator.GenerateLabelName(aMethod.MethodBase) + "___EXCEPTION___EXIT"}; + } - private void PushAlignedParameterSize( System.Reflection.MethodBase aMethod ) - { - System.Reflection.ParameterInfo[] xParams = aMethod.GetParameters(); + private void JumpToExit(MethodInfo aMethod) + { + throw new NotImplementedException(); + } - uint xSize; + private uint Align(uint aSize, uint aAlign) + { + return aSize % 4 == 0 ? aSize : ((aSize / aAlign) * aAlign) + 1; + } - for( int i = 1; i < xParams.Length; i++ ) - { - xSize = GetFieldStorageSize( xParams[ i ].GetType() ); - new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = Align( xSize, 4 ) }; - } - } - // using System.Collections.Generic; - // using System.Diagnostics; - // using System.Linq; - // using System.Reflection; - // using Indy.IL2CPU.Assembler; - // using Indy.IL2CPU.Assembler.X86; - // using CPU=Indy.IL2CPU.Assembler; - // using CPUx86=Indy.IL2CPU.Assembler.X86; - // using Asm=Indy.IL2CPU.Assembler; - // using Assembler=Indy.IL2CPU.Assembler.Assembler; - // using Indy.IL2CPU.Compiler; - // - // namespace Indy.IL2CPU.IL.X86 - // { - // [OpCode(OpCodeEnum.Newobj)] - // public class Newobj : Op - // { - // public MethodBase CtorDef; - // public string CurrentLabel; - // public uint ILOffset; - // public MethodInformation MethodInformation; - // - // public static void ScanOp(MethodBase aCtor, IServiceProvider aProvider) - // { - // Call.ScanOp(aCtor, aProvider); - // Call.ScanOp(GCImplementationRefs.AllocNewObjectRef, aProvider); - // Call.ScanOp(CPU.Assembler.CurrentExceptionOccurredRef, aProvider); - // Call.ScanOp(GCImplementationRefs.IncRefCountRef, aProvider); - // } - // - // public static void ScanOp(ILReader aReader, MethodInformation aMethodInfo, SortedList aMethodData, IServiceProvider aProvider) - // { - // var xCtorDef = aReader.OperandValueMethod; - // ScanOp(xCtorDef, aProvider); - // } - // - // public Newobj(ILReader aReader, - // MethodInformation aMethodInfo) - // : base(aReader, - // aMethodInfo) - // { - // CtorDef = aReader.OperandValueMethod; - // CurrentLabel = GetInstructionLabel(aReader); - // MethodInformation = aMethodInfo; - // ILOffset = aReader.Position; - // mNextLabel = GetInstructionLabel(aReader.NextPosition); - // } - // - // private string mNextLabel; - // } + private void PushAlignedParameterSize(System.Reflection.MethodBase aMethod) + { + System.Reflection.ParameterInfo[] xParams = aMethod.GetParameters(); - //TODO: Likely this is used by other things besides newobj - // and thus should be moved to a different location - private uint GetFieldStorageSize( Type aType ) - { - if( aType.FullName == "System.Void" ) - { - return 0; - } - else if( ( !aType.IsValueType && aType.IsClass ) || aType.IsInterface ) - { - return 4; - } - switch( aType.FullName ) - { - case "System.Char": - return 2; - case "System.Byte": - case "System.SByte": - return 1; - case "System.UInt16": - case "System.Int16": - return 2; - case "System.UInt32": - case "System.Int32": - return 4; - case "System.UInt64": - case "System.Int64": - return 8; - //TODO: for now hardcode IntPtr and UIntPtr to be 32-bit - case "System.UIntPtr": - case "System.IntPtr": - return 4; - case "System.Boolean": - return 1; - case "System.Single": - return 4; - case "System.Double": - return 8; - case "System.Decimal": - return 16; - case "System.Guid": - return 16; - case "System.Enum": - return 4; - case "System.DateTime": - return 8; - } - if( aType.FullName != null && aType.FullName.EndsWith( "*" ) ) - { - // pointer - return 4; - } - // array - //TypeSpecification xTypeSpec = aType as TypeSpecification; - //if (xTypeSpec != null) { - // return 4; - //} - if( aType.IsEnum ) - { - return GetFieldStorageSize( aType.GetField( "value__" ).FieldType ); - } - if( aType.IsValueType ) - { - var xSla = aType.StructLayoutAttribute; - if( xSla != null ) - { - if( xSla.Size > 0 ) - { - return ( uint )xSla.Size; - } - } - } - uint xResult; - //GetTypeFieldInfo(aType, out xResult); - throw new Exception( "TODO" ); - return xResult; - } + uint xSize; - } -} + for (int i = 1; i < xParams.Length; i++) + { + xSize = GetFieldStorageSize(xParams[i].GetType()); + new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = Align(xSize, 4) }; + } + } + // using System.Collections.Generic; + // using System.Diagnostics; + // using System.Linq; + // using System.Reflection; + // using Indy.IL2CPU.Assembler; + // using Indy.IL2CPU.Assembler.X86; + // using CPU=Indy.IL2CPU.Assembler; + // using CPUx86=Indy.IL2CPU.Assembler.X86; + // using Asm=Indy.IL2CPU.Assembler; + // using Assembler=Indy.IL2CPU.Assembler.Assembler; + // using Indy.IL2CPU.Compiler; + // + // namespace Indy.IL2CPU.IL.X86 + // { + // [OpCode(OpCodeEnum.Newobj)] + // public class Newobj : Op + // { + // public MethodBase CtorDef; + // public string CurrentLabel; + // public uint ILOffset; + // public MethodInformation MethodInformation; + // + // public static void ScanOp(MethodBase aCtor, IServiceProvider aProvider) + // { + // Call.ScanOp(aCtor, aProvider); + // Call.ScanOp(GCImplementationRefs.AllocNewObjectRef, aProvider); + // Call.ScanOp(CPU.Assembler.CurrentExceptionOccurredRef, aProvider); + // Call.ScanOp(GCImplementationRefs.IncRefCountRef, aProvider); + // } + // + // public static void ScanOp(ILReader aReader, MethodInformation aMethodInfo, SortedList aMethodData, IServiceProvider aProvider) + // { + // var xCtorDef = aReader.OperandValueMethod; + // ScanOp(xCtorDef, aProvider); + // } + // + // public Newobj(ILReader aReader, + // MethodInformation aMethodInfo) + // : base(aReader, + // aMethodInfo) + // { + // CtorDef = aReader.OperandValueMethod; + // CurrentLabel = GetInstructionLabel(aReader); + // MethodInformation = aMethodInfo; + // ILOffset = aReader.Position; + // mNextLabel = GetInstructionLabel(aReader.NextPosition); + // } + // + // private string mNextLabel; + // } + } +} \ No newline at end of file diff --git a/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stloc.cs b/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stloc.cs index 949796d74..8bf58b93a 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stloc.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU.X86/IL/Stloc.cs @@ -1,29 +1,61 @@ using System; +using Cosmos.IL2CPU.ILOpCodes; +using CPUx86 = Indy.IL2CPU.Assembler.X86; +using System.Collections.Generic; +using System.Reflection; +using Indy.IL2CPU; namespace Cosmos.IL2CPU.X86.IL { [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Stloc)] - public class Stloc: ILOp + public class Stloc : ILOp { - public Stloc(Cosmos.IL2CPU.Assembler aAsmblr):base(aAsmblr) + public Stloc(Cosmos.IL2CPU.Assembler aAsmblr) + : base(aAsmblr) { } - public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) { - throw new NotImplementedException(); - } + private uint GetStackCount(MethodInfo aMethod, LocalVariableInfo aField) + { + var xSize = GetFieldStorageSize(aField.LocalType); + var xResult = xSize / 4; + if (xSize % 4 == 0) + { + xResult++; + } + return xResult; + } + + private uint GetEBPOffsetForLocal(MethodInfo aMethod, OpVar aOp) + { + var xBody = aMethod.MethodBase.GetMethodBody(); + uint xOffset = 0; + foreach (var xField in xBody.LocalVariables) + { + xOffset += GetStackCount(aMethod, xField); + } + return xOffset; + } + + public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) + { + var xField = aOpCode as ILOpCodes.OpVar; + var xFieldInfo = aMethod.MethodBase.GetMethodBody().LocalVariables[xField.Value]; + var xEBPOffset = GetEBPOffsetForLocal(aMethod, xField); + if (!xFieldInfo.LocalType.IsValueType) + { + new CPUx86.Push { DestinationReg = CPUx86.Registers.EBP, DestinationIsIndirect = true, DestinationDisplacement =(int) xEBPOffset }; + new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(GCImplementationRefs.DecRefCountRef) }; + } + for (int i = (int)GetStackCount(aMethod, xFieldInfo) - 1; i >= 0; i--) + { + new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; ; + new CPUx86.Move { DestinationReg = CPUx86.Registers.EBP, DestinationIsIndirect = true, DestinationDisplacement =(int)( xEBPOffset + (i * 4)), SourceReg = CPUx86.Registers.EAX }; + } + // no need to inc again, items on the transient stack are also counted + Assembler.Stack.Pop(); + } - - // using System; - // using System.Linq; - // using Indy.IL2CPU.Assembler; - // - // - // using CPUx86 = Indy.IL2CPU.Assembler.X86; - // - // namespace Indy.IL2CPU.IL.X86 { - // [OpCode(OpCodeEnum.Stloc)] - // public class Stloc: Op { // private bool mNeedsGC = false; // private MethodInformation.Variable mLocal; // private string mBaseLabel; @@ -60,6 +92,6 @@ namespace Cosmos.IL2CPU.X86.IL // } // } // } - + } } diff --git a/source2/IL2PCU/Cosmos.IL2CPU.X86/ILOp.cs b/source2/IL2PCU/Cosmos.IL2CPU.X86/ILOp.cs index 3a72fdfd9..9df680e35 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU.X86/ILOp.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU.X86/ILOp.cs @@ -15,5 +15,10 @@ namespace Cosmos.IL2CPU.X86 { Assembler = ( Assembler )aAsmblr; } + + protected string GetLabel(MethodInfo aMethod, ILOpCode aOpCode) + { + return MethodInfoLabelGenerator.GenerateLabelName(aMethod.MethodBase) + "__DOT__" + aOpCode.Position.ToString("X8").ToUpper(); + } } } diff --git a/source2/IL2PCU/Cosmos.IL2CPU/Assembler.cs b/source2/IL2PCU/Cosmos.IL2CPU/Assembler.cs index 721061f90..9ccdc1e2d 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU/Assembler.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU/Assembler.cs @@ -11,8 +11,8 @@ namespace Cosmos.IL2CPU { protected ILOp[] mILOpsHi = new ILOp[ 256 ]; // Contains info on the current stack structure. What type are on the stack, etc - public readonly StackContents Stack = new StackContents(); - + public readonly StackContents Stack = new StackContents(); + private static ReaderWriterLocker mCurrentInstanceLocker = new ReaderWriterLocker(); private static SortedList> mCurrentInstance = new SortedList>(); protected internal List mInstructions = new List(); diff --git a/source2/IL2PCU/Cosmos.IL2CPU/Cosmos.IL2CPU.csproj b/source2/IL2PCU/Cosmos.IL2CPU/Cosmos.IL2CPU.csproj index 1280ea019..905293b39 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU/Cosmos.IL2CPU.csproj +++ b/source2/IL2PCU/Cosmos.IL2CPU/Cosmos.IL2CPU.csproj @@ -76,6 +76,7 @@ + diff --git a/source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs b/source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs index c5b9ec5f3..47bca746a 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU/ILOp.cs @@ -17,5 +17,80 @@ namespace Cosmos.IL2CPU // could be used for other things, profiling, analysis, reporting, etc public abstract void Execute( MethodInfo aMethod, ILOpCode aOpCode ); + protected static uint GetFieldStorageSize(Type aType) + { + if (aType.FullName == "System.Void") + { + return 0; + } + else if ((!aType.IsValueType && aType.IsClass) || aType.IsInterface) + { + return 4; + } + switch (aType.FullName) + { + case "System.Char": + return 2; + case "System.Byte": + case "System.SByte": + return 1; + case "System.UInt16": + case "System.Int16": + return 2; + case "System.UInt32": + case "System.Int32": + return 4; + case "System.UInt64": + case "System.Int64": + return 8; + //TODO: for now hardcode IntPtr and UIntPtr to be 32-bit + case "System.UIntPtr": + case "System.IntPtr": + return 4; + case "System.Boolean": + return 1; + case "System.Single": + return 4; + case "System.Double": + return 8; + case "System.Decimal": + return 16; + case "System.Guid": + return 16; + case "System.Enum": + return 4; + case "System.DateTime": + return 8; + } + if (aType.FullName != null && aType.FullName.EndsWith("*")) + { + // pointer + return 4; + } + // array + //TypeSpecification xTypeSpec = aType as TypeSpecification; + //if (xTypeSpec != null) { + // return 4; + //} + if (aType.IsEnum) + { + return GetFieldStorageSize(aType.GetField("value__").FieldType); + } + if (aType.IsValueType) + { + var xSla = aType.StructLayoutAttribute; + if (xSla != null) + { + if (xSla.Size > 0) + { + return (uint)xSla.Size; + } + } + } + uint xResult; + //GetTypeFieldInfo(aType, out xResult); + throw new Exception("TODO"); + return xResult; + } } } diff --git a/source2/IL2PCU/Cosmos.IL2CPU/MethodAndTypeLabelsHolder.cs b/source2/IL2PCU/Cosmos.IL2CPU/MethodAndTypeLabelsHolder.cs new file mode 100644 index 000000000..ab196c6c1 --- /dev/null +++ b/source2/IL2PCU/Cosmos.IL2CPU/MethodAndTypeLabelsHolder.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Cosmos.IL2CPU +{ + public static class MethodAndTypeLabelsHolder + { + //public static readonly uint + } +} diff --git a/source2/IL2PCU/Cosmos.IL2CPU/StackContents.cs b/source2/IL2PCU/Cosmos.IL2CPU/StackContents.cs index a06b8406a..2d5863a7c 100644 --- a/source2/IL2PCU/Cosmos.IL2CPU/StackContents.cs +++ b/source2/IL2PCU/Cosmos.IL2CPU/StackContents.cs @@ -80,5 +80,13 @@ namespace Cosmos.IL2CPU { mStack.Push(new Item(aSize, aIsNumber, aIsFloat, aIsSigned)); } + public IEnumerator GetEnumerator() + { + foreach (var item in mStack) + { + yield return item; + } + } + } } \ No newline at end of file