This commit is contained in:
mterwoord_cp 2009-08-31 16:47:03 +00:00
parent b09d8af85e
commit d6a2c080fa
8 changed files with 423 additions and 361 deletions

View file

@ -5,370 +5,299 @@ using CPUx86 = Indy.IL2CPU.Assembler.X86;
using Cosmos.IL2CPU.ILOpCodes; using Cosmos.IL2CPU.ILOpCodes;
namespace Cosmos.IL2CPU.X86.IL namespace Cosmos.IL2CPU.X86.IL
{ {
[Cosmos.IL2CPU.OpCode( ILOpCode.Code.Newobj )] [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Newobj)]
public class Newobj : ILOp public class Newobj : ILOp
{ {
public Newobj( Cosmos.IL2CPU.Assembler aAsmblr ) public Newobj(Cosmos.IL2CPU.Assembler aAsmblr)
: base( aAsmblr ) : base(aAsmblr)
{ {
} }
public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
{ {
OpMethod xMethod = ( OpMethod )aOpCode; OpMethod xMethod = (OpMethod)aOpCode;
// Is this checking for plugs? string xCurrentLabel = GetLabel(aMethod, aOpCode);
// if (DynamicMethodEmit.GetHasDynamicMethod(CtorDef)) { // TODO: enable this again
// CtorDef = DynamicMethodEmit.GetDynamicMethod(CtorDef); // if (DynamicMethodEmit.GetHasDynamicMethod(CtorDef)) {
// } // CtorDef = DynamicMethodEmit.GetDynamicMethod(CtorDef);
// }
//var xAllocInfo = GetService<IMetaDataInfoService>().GetMethodInfo(GCImplementationRefs.AllocNewObjectRef, false); //var xAllocInfo = GetService<IMetaDataInfoService>().GetMethodInfo(GCImplementationRefs.AllocNewObjectRef, false);
// Assemble( // Assemble(
// Assembler, // Assembler,
// CtorDef, // CtorDef,
// GetService<IMetaDataInfoService>().GetTypeIdLabel(CtorDef.DeclaringType), // GetService<IMetaDataInfoService>().GetTypeIdLabel(CtorDef.DeclaringType),
// CurrentLabel, // CurrentLabel,
// MethodInformation, // MethodInformation,
// (int)ILOffset, // (int)ILOffset,
// mNextLabel, // mNextLabel,
// GetService<IMetaDataInfoService>().GetTypeInfo(CtorDef.DeclaringType), // GetService<IMetaDataInfoService>().GetTypeInfo(CtorDef.DeclaringType),
// GetService<IMetaDataInfoService>().GetMethodInfo(CtorDef, false), // GetService<IMetaDataInfoService>().GetMethodInfo(CtorDef, false),
// GetServiceProvider(), // GetServiceProvider(),
// xAllocInfo.LabelName // xAllocInfo.LabelName
// ); // );
// } // }
// //
// public static void Assemble( // public static void Assemble(
// Assembler.Assembler aAssembler, // Assembler.Assembler aAssembler,
// MethodBase aCtorDef, // MethodBase aCtorDef,
// string aTypeId, // string aTypeId,
// string aCurrentLabel, // string aCurrentLabel,
// MethodInformation aCurrentMethodInformation, // MethodInformation aCurrentMethodInformation,
// int aCurrentILOffset, // int aCurrentILOffset,
// string aNextLabel, // string aNextLabel,
// TypeInformation aCtorDeclTypeInfo, // TypeInformation aCtorDeclTypeInfo,
// MethodInformation aCtorMethodInfo, // MethodInformation aCtorMethodInfo,
// IServiceProvider aServiceProvider, // IServiceProvider aServiceProvider,
// string aAllocMemLabel // string aAllocMemLabel
// ) // )
//TODO: What is this for? //TODO: What is this for?
// if (aCtorDef != null) { // if (aCtorDef != null) {
// //if (!aCtorDef.DeclaringType.FullName.StartsWith("Indy.IL2CPU.MultiArrayEmit.ContType")) // //if (!aCtorDef.DeclaringType.FullName.StartsWith("Indy.IL2CPU.MultiArrayEmit.ContType"))
// // Engine.QueueMethod(aCtorDef); // // Engine.QueueMethod(aCtorDef);
// } else { // } else {
// throw new ArgumentNullException("aCtorDef"); // throw new ArgumentNullException("aCtorDef");
// } // }
var xType = xMethod.Value.DeclaringType; var xType = xMethod.Value.DeclaringType;
// If not ValueType, then we need gc // If not ValueType, then we need gc
if( !xType.IsValueType ) if (!xType.IsValueType)
{ {
var xParams = xMethod.Value.GetParameters(); var xParams = xMethod.Value.GetParameters();
for( int i = 1; i < xParams.Length; i++ ) for (int i = 1; i < xParams.Length; i++)
{ {
Assembler.Stack.Pop(); Assembler.Stack.Pop();
} }
uint xMemSize = GetFieldStorageSize( xType ); uint xMemSize = GetFieldStorageSize(xType);
int xExtraSize = 20; int xExtraSize = 20;
new CPUx86.Push { DestinationValue = ( uint )( xMemSize + xExtraSize ) }; new CPUx86.Push { DestinationValue = (uint)(xMemSize + xExtraSize) };
new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName( GCImplementationRefs.AllocNewObjectRef ) }; // todo: probably we want to check for exceptions after calling Alloc
new CPUx86.Test { DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 }; 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 };
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<IMetaDataInfoService>().GetMethodInfo( GCImplementationRefs.IncRefCountRef, false );
// TODO: Why call incref twice?
// new Assembler.X86.Call { DestinationLabel = xIncRefInfo.LabelName };
// new CPUx86.Call { DestinationLabel = xIncRefInfo.LabelName };
new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName( GCImplementationRefs.IncRefCountRef ) }; // 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
uint xObjSize = 0; // todo: probably we want to check for exceptions after calling IncRef
//int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(GCImplementationRefs.IncRefCountRef) };
//where item.NeedsGC new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(GCImplementationRefs.IncRefCountRef) };
//select item ).Count();
//int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values uint xObjSize = 0;
//where item.NeedsGC //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values
//select item ).Count(); //where item.NeedsGC
int xGCFieldCount = xType.GetFields().Count( x => x.FieldType.IsValueType ); //select item ).Count();
string strTypeId = xMethod.Value.DeclaringType.FullName; //int xGCFieldCount = ( from item in aCtorDeclTypeInfo.Fields.Values
//where item.NeedsGC
//select item ).Count();
int xGCFieldCount = xType.GetFields().Count(x => x.FieldType.IsValueType);
new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; string strTypeId = xMethod.Value.DeclaringType.FullName;
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 CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX };
{ new CPUx86.Move { DestinationReg = CPUx86.Registers.EBX, SourceRef = Indy.IL2CPU.Assembler.ElementReference.New(strTypeId), SourceIsIndirect = true };
new Comment( String.Format( "Arg {0}: {1}", i, GetFieldStorageSize( xParams[i].GetType() ) ) ); new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EBX };
for( int j = 0; j < GetFieldStorageSize( xParams[ i ].GetType() ); j += 4 ) 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 };
new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, DestinationDisplacement = ( int )( xSize + 4 ) }; uint xSize = (uint)(((from item in xParams
} let xQSize = Align(GetFieldStorageSize(item.GetType()), 4)
} select (int)xQSize).Take(xParams.Length - 1).Sum()));
new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName( xMethod.Value ) }; for (int i = 1; i < xParams.Length; i++)
new CPUx86.Test { DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 }; {
//new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = aCurrentLabel + "_NO_ERROR_4" }; new Comment(String.Format("Arg {0}: {1}", i, GetFieldStorageSize(xParams[i].GetType())));
throw new Exception("Notimpl"); 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 < aCtorMethodInfo.Arguments.Length; i++ ) new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(xMethod.Value) };
//{ new CPUx86.Test { DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 };
// new CPUx86.Add new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = xCurrentLabel + "_NO_ERROR_4" };
// {
// 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.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = 4 }; //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ )
//foreach( StackContent xStackInt in Assembler.Stack ) //{
//{ // new CPUx86.Add
// new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, SourceValue = ( uint )xStackInt.Size }; // {
//} // DestinationReg = CPUx86.Registers.ESP,
//Call.EmitExceptionLogic( aAssembler, // SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0
// ( uint )aCurrentILOffset, // ? aCtorMethodInfo.Arguments[ i ].Size
// aCurrentMethodInformation, // : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 )
// aCurrentLabel + "_NO_ERROR_4", // };
// false, //}
// null ); PushAlignedParameterSize(xMethod.Value);
//new Label( aCurrentLabel + "_NO_ERROR_4" ); // an exception occurred, we need to cleanup the stack, and jump to the exit
new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; 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);
//for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ ) new Label(xCurrentLabel + "_NO_ERROR_4");
//{ new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX };
// 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 }; //for( int i = 1; i < aCtorMethodInfo.Arguments.Length; i++ )
Assembler.Stack.Push( 4, xMethod.Value.DeclaringType ); //{
throw new NotImplementedException(); // new CPUx86.Add
} // {
else // DestinationReg = CPUx86.Registers.ESP,
{ // SourceValue = ( aCtorMethodInfo.Arguments[ i ].Size % 4 == 0
// /* // ? aCtorMethodInfo.Arguments[ i ].Size
// * Current sitation on stack: // : ( ( aCtorMethodInfo.Arguments[ i ].Size / 4 ) * 4 ) + 1 )
// * $ESP Arg // };
// * $ESP+.. other items //}
// * PushAlignedParameterSize(xMethod.Value);
// * 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 ) new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
{ Assembler.Stack.Push(4, xMethod.Value.DeclaringType);
return aSize % 4 == 0 ? aSize : ( ( aSize / aAlign ) * aAlign ) + 1; }
} 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 void PushAlignedParameterSize( System.Reflection.MethodBase aMethod ) private void JumpToExceptionExit(MethodInfo aMethod)
{ {
System.Reflection.ParameterInfo[] xParams = aMethod.GetParameters(); // todo: port to numeric labels
new CPUx86.Jump{DestinationLabel= MethodInfoLabelGenerator.GenerateLabelName(aMethod.MethodBase) + "___EXCEPTION___EXIT"};
}
uint xSize; private void JumpToExit(MethodInfo aMethod)
{
throw new NotImplementedException();
}
for( int i = 1; i < xParams.Length; i++ ) private uint Align(uint aSize, uint aAlign)
{ {
xSize = GetFieldStorageSize( xParams[ i ].GetType() ); return aSize % 4 == 0 ? aSize : ((aSize / aAlign) * aAlign) + 1;
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<string, object> 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;
// }
//TODO: Likely this is used by other things besides newobj private void PushAlignedParameterSize(System.Reflection.MethodBase aMethod)
// and thus should be moved to a different location {
private uint GetFieldStorageSize( Type aType ) System.Reflection.ParameterInfo[] xParams = aMethod.GetParameters();
{
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<string, object> 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;
// }
}
} }

View file

@ -1,29 +1,61 @@
using System; 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 namespace Cosmos.IL2CPU.X86.IL
{ {
[Cosmos.IL2CPU.OpCode(ILOpCode.Code.Stloc)] [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) { private uint GetStackCount(MethodInfo aMethod, LocalVariableInfo aField)
throw new NotImplementedException(); {
} 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 bool mNeedsGC = false;
// private MethodInformation.Variable mLocal; // private MethodInformation.Variable mLocal;
// private string mBaseLabel; // private string mBaseLabel;

View file

@ -15,5 +15,10 @@ namespace Cosmos.IL2CPU.X86
{ {
Assembler = ( Assembler )aAsmblr; Assembler = ( Assembler )aAsmblr;
} }
protected string GetLabel(MethodInfo aMethod, ILOpCode aOpCode)
{
return MethodInfoLabelGenerator.GenerateLabelName(aMethod.MethodBase) + "__DOT__" + aOpCode.Position.ToString("X8").ToUpper();
}
} }
} }

View file

@ -11,7 +11,7 @@ namespace Cosmos.IL2CPU {
protected ILOp[] mILOpsHi = new ILOp[ 256 ]; protected ILOp[] mILOpsHi = new ILOp[ 256 ];
// Contains info on the current stack structure. What type are on the stack, etc // 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 ReaderWriterLocker mCurrentInstanceLocker = new ReaderWriterLocker();
private static SortedList<int, Stack<Assembler>> mCurrentInstance = new SortedList<int, Stack<Assembler>>(); private static SortedList<int, Stack<Assembler>> mCurrentInstance = new SortedList<int, Stack<Assembler>>();

View file

@ -76,6 +76,7 @@
<Compile Include="ILReader.cs" /> <Compile Include="ILReader.cs" />
<Compile Include="Instruction.cs" /> <Compile Include="Instruction.cs" />
<Compile Include="Label.cs" /> <Compile Include="Label.cs" />
<Compile Include="MethodAndTypeLabelsHolder.cs" />
<Compile Include="MethodInfo.cs" /> <Compile Include="MethodInfo.cs" />
<Compile Include="MethodInfoLabelGenerator.cs" /> <Compile Include="MethodInfoLabelGenerator.cs" />
<Compile Include="OpCodeAttribute.cs" /> <Compile Include="OpCodeAttribute.cs" />

View file

@ -17,5 +17,80 @@ namespace Cosmos.IL2CPU
// could be used for other things, profiling, analysis, reporting, etc // could be used for other things, profiling, analysis, reporting, etc
public abstract void Execute( MethodInfo aMethod, ILOpCode aOpCode ); 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;
}
} }
} }

View file

@ -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
}
}

View file

@ -80,5 +80,13 @@ namespace Cosmos.IL2CPU {
mStack.Push(new Item(aSize, aIsNumber, aIsFloat, aIsSigned)); mStack.Push(new Item(aSize, aIsNumber, aIsFloat, aIsSigned));
} }
public IEnumerator<Item> GetEnumerator()
{
foreach (var item in mStack)
{
yield return item;
}
}
} }
} }