This commit is contained in:
kudzu_cp 2011-07-11 01:42:13 +00:00
parent b8b6100333
commit dea9bfb587
2 changed files with 218 additions and 240 deletions

View file

@ -6,45 +6,89 @@ using Cosmos.IL2CPU.ILOpCodes;
using Cosmos.IL2CPU.IL.CustomImplementations.System; using Cosmos.IL2CPU.IL.CustomImplementations.System;
using System.Reflection; using System.Reflection;
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.Compiler.Assembler.Assembler aAsmblr)
{ : base(aAsmblr) {
public Newobj( Cosmos.Compiler.Assembler.Assembler 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; string xCurrentLabel = GetLabel(aMethod, aOpCode);
string xCurrentLabel = GetLabel( aMethod, aOpCode );
var xType = xMethod.Value.DeclaringType; var xType = xMethod.Value.DeclaringType;
Assemble(Assembler, aMethod, xMethod, xCurrentLabel, xType, xMethod.Value); Assemble(Assembler, aMethod, xMethod, xCurrentLabel, xType, xMethod.Value);
} }
public static void Assemble(Assembler aAssembler, MethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor) public static void Assemble(Assembler aAssembler, MethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor) {
{
// call cctor: // call cctor:
if (aMethod != null) if (aMethod != null) {
{
var xCctor = (objectType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault(); var xCctor = (objectType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? new ConstructorInfo[0]).SingleOrDefault();
if (xCctor != null) if (xCctor != null) {
{
new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(xCctor) }; new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(xCctor) };
ILOp.EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck"); ILOp.EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck");
new Label(".AfterCCTorExceptionCheck"); new Label(".AfterCCTorExceptionCheck");
} }
} }
// If not ValueType, then we need gc if (objectType.IsValueType) {
if (!objectType.IsValueType) /*
{ * 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 = Align(SizeOfType(objectType), 4);
//var xStorageSize = aCtorDeclTypeInfo.StorageSize;
//uint xArgSize = 0;
var xParams = constructor.GetParameters(); var xParams = constructor.GetParameters();
for (int i = 0; i < xParams.Length; i++) uint xArgSize = (uint)(((from item in xParams.Skip(1)
{ let xQSize = Align(SizeOfType(item.ParameterType), 4)
select (int)xQSize).Take(xParams.Length - 1).Sum()));
//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 = CPUx86.Registers.ESP };
aAssembler.Stack.Push(new StackContents.Item(4, null));
//at this point, we need to move copy all arguments over.
for (int i = 0; i < (xArgSize / 4); i++) {
new CPUx86.Push { DestinationReg = CPUx86.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 };
}
new Call(aAssembler).Execute(aMethod, xMethod);
//var xCall = new Call( aCtorDef,
// ( uint )aCurrentILOffset,
// true,
// aNextLabel );
//xCall.SetServiceProvider( aServiceProvider );
//xCall.Assembler = aAssembler;
//xCall.Assemble();
aAssembler.Stack.Push(new StackContents.Item(xStorageSize, objectType));
} else {
// If not ValueType, then we need gc
var xParams = constructor.GetParameters();
for (int i = 0; i < xParams.Length; i++) {
aAssembler.Stack.Pop(); aAssembler.Stack.Pop();
} }
@ -52,22 +96,18 @@ namespace Cosmos.IL2CPU.X86.IL
bool xHasCalcSize = false; bool xHasCalcSize = false;
// try calculating size: // try calculating size:
if (constructor.DeclaringType == typeof(string)) 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; xHasCalcSize = true;
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true };
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true, SourceDisplacement = 8 }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true, SourceDisplacement = 8 };
new CPUx86.Move { DestinationReg = CPUx86.Registers.EDX, SourceValue = 2 }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EDX, SourceValue = 2 };
new CPUx86.Multiply { DestinationReg = CPUx86.Registers.EDX }; new CPUx86.Multiply { DestinationReg = CPUx86.Registers.EDX };
new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
} } else if (xParams.Length == 3
else if (xParams.Length == 3
&& xParams[0].ParameterType == typeof(char[]) && xParams[0].ParameterType == typeof(char[])
&& xParams[1].ParameterType == typeof(int) && xParams[1].ParameterType == typeof(int)
&& xParams[2].ParameterType == typeof(int)) && xParams[2].ParameterType == typeof(int)) {
{
xHasCalcSize = true; xHasCalcSize = true;
new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true }; new CPUx86.Push { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true };
} }
@ -75,8 +115,7 @@ namespace Cosmos.IL2CPU.X86.IL
uint xMemSize = GetStorageSize(objectType); uint xMemSize = GetStorageSize(objectType);
int xExtraSize = 20; int xExtraSize = 20;
new CPUx86.Push { DestinationValue = (uint)(xMemSize + xExtraSize) }; new CPUx86.Push { DestinationValue = (uint)(xMemSize + xExtraSize) };
if (xHasCalcSize) if (xHasCalcSize) {
{
new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX };
new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX }; new CPUx86.Add { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX };
} }
@ -108,8 +147,7 @@ namespace Cosmos.IL2CPU.X86.IL
let xQSize = Align(SizeOfType(item.ParameterType), 4) let xQSize = Align(SizeOfType(item.ParameterType), 4)
select (int)xQSize).Take(xParams.Length).Sum())); select (int)xQSize).Take(xParams.Length).Sum()));
foreach (var xParam in xParams) foreach (var xParam in xParams) {
{
uint xParamSize = Align(SizeOfType(xParam.ParameterType), 4); uint xParamSize = Align(SizeOfType(xParam.ParameterType), 4);
new Comment(aAssembler, String.Format("Arg {0}: {1}", xParam.Name, xParamSize)); new Comment(aAssembler, String.Format("Arg {0}: {1}", xParam.Name, xParamSize));
for (int i = 0; i < xParamSize; i += 4) { for (int i = 0; i < xParamSize; i += 4) {
@ -118,8 +156,7 @@ namespace Cosmos.IL2CPU.X86.IL
} }
new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(constructor) }; new CPUx86.Call { DestinationLabel = MethodInfoLabelGenerator.GenerateLabelName(constructor) };
if (aMethod != null) if (aMethod != null) {
{
new CPUx86.Test { DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 }; new CPUx86.Test { DestinationReg = CPUx86.Registers.ECX, SourceValue = 2 };
string xNoErrorLabel = currentLabel + "_NO_ERROR_" + MethodInfoLabelGenerator.LabelCount.ToString(); string xNoErrorLabel = currentLabel + "_NO_ERROR_" + MethodInfoLabelGenerator.LabelCount.ToString();
new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = xNoErrorLabel }; new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = xNoErrorLabel };
@ -170,78 +207,18 @@ namespace Cosmos.IL2CPU.X86.IL
new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX };
aAssembler.Stack.Push(4, constructor.DeclaringType); aAssembler.Stack.Push(4, constructor.DeclaringType);
} }
else
{
//throw new Exception("Not implemented yet: .ctor on value type");
/*
* 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 = Align(SizeOfType(objectType), 4);
//var xStorageSize = aCtorDeclTypeInfo.StorageSize;
//uint xArgSize = 0;
var xParams = constructor.GetParameters();
uint xArgSize = (uint)(((from item in xParams.Skip(1)
let xQSize = Align(SizeOfType(item.ParameterType), 4)
select (int)xQSize).Take(xParams.Length - 1).Sum()));
//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 = CPUx86.Registers.ESP };
aAssembler.Stack.Push(new StackContents.Item(4, null));
//at this point, we need to move copy all arguments over.
for (int i = 0; i < (xArgSize / 4); i++)
{
new CPUx86.Push { DestinationReg = CPUx86.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 };
}
new Call(aAssembler).Execute(aMethod, xMethod);
//var xCall = new Call( aCtorDef,
// ( uint )aCurrentILOffset,
// true,
// aNextLabel );
//xCall.SetServiceProvider( aServiceProvider );
//xCall.Assembler = aAssembler;
//xCall.Assemble();
aAssembler.Stack.Push(new StackContents.Item(xStorageSize, objectType));
}
} }
private static void PushAlignedParameterSize( System.Reflection.MethodBase aMethod ) private static void PushAlignedParameterSize(System.Reflection.MethodBase aMethod) {
{
System.Reflection.ParameterInfo[] xParams = aMethod.GetParameters(); System.Reflection.ParameterInfo[] xParams = aMethod.GetParameters();
uint xSize; uint xSize;
new Comment("[ Newobj.PushAlignedParameterSize start count = " + xParams.Length.ToString() + " ]" ); new Comment("[ Newobj.PushAlignedParameterSize start count = " + xParams.Length.ToString() + " ]");
for( int i = 0; i < xParams.Length; i++ ) for (int i = 0; i < xParams.Length; i++) {
{ xSize = SizeOfType(xParams[i].ParameterType);
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 ]" ); new Comment("[ Newobj.PushAlignedParameterSize end ]");
} }
} }
} }

View file

@ -18,13 +18,14 @@ namespace BreakpointsKernel {
} }
public override void Run() { public override void Run() {
UInt32 x = 32; UInt32 x = 1;
UInt32? xSize; UInt32? xSize;
xSize = 8; xSize = 2;
aSize = 3;
mSize = 7; mSize = 4;
bool xHasValue = mSize.HasValue; // .HasValue is false bool xHasValue = mSize.HasValue; // .HasValue is false
Chk(xHasValue); Chk(xHasValue);
x = mSize.Value; x = mSize.Value;