using System; using CPUx86 = Cosmos.Compiler.Assembler.X86; using CPU = Cosmos.Compiler.Assembler.X86; using Cosmos.Compiler.Assembler; using System.Reflection; using Cosmos.IL2CPU.IL.CustomImplementations.System; namespace Cosmos.IL2CPU.X86.IL { /// /// Pushes an object reference to a new zero-based, one-dimensional array whose elements are of a specific type onto the evaluation stack. /// [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Newarr )] public class Newarr : ILOp { public Newarr( Cosmos.Compiler.Assembler.Assembler aAsmblr ) : base( aAsmblr ) { } public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) { Cosmos.IL2CPU.ILOpCodes.OpType xType = ( Cosmos.IL2CPU.ILOpCodes.OpType )aOpCode; uint xSize = SizeOfType( xType.Value ); string xTypeID = GetTypeIDLabel(typeof(Array)); MethodBase xCtor = typeof( Array ).GetConstructors( BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance )[ 0 ]; string xCtorName = MethodInfoLabelGenerator.GenerateLabelName( xCtor ); new Comment( Assembler, "Element Size = " + xSize ); // element count is on the stack var xElementCountSize = Assembler.Stack.Pop().Size; new CPUx86.Pop { DestinationReg = CPUx86.Registers.ESI }; new CPUx86.Push { DestinationReg = CPUx86.Registers.ESI }; //Assembler.StackSizes.Push(xElementCountSize); new CPUx86.Push { DestinationValue = xSize }; Assembler.Stack.Push( new StackContents.Item( 4, typeof( uint ) ) ); new Mul( Assembler ).Execute( aMethod, aOpCode ); // the total items size is now on the stack new CPUx86.Push { DestinationValue = ( ObjectImpl.FieldDataOffset + 4 ) }; Assembler.Stack.Push( new StackContents.Item( 4, typeof( uint ) ) ); new Add( Assembler ).Execute( aMethod, aOpCode ); // the total array size is now on the stack. 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 }; Assembler.Stack.Push( new StackContents.Item( 4, typeof( Array ) ) ); new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EBX, SourceRef = ElementReference.New( xTypeID ), SourceIsIndirect = true }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EBX }; new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = 4 }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceValue = ( uint )InstanceTypeEnum.Array, Size = 32 }; new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = 4 }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.ESI, Size = 32 }; new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = 4 }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceValue = ( uint )xSize, Size = 32 }; new CPUx86.Call { DestinationLabel = xCtorName }; } } }