Fixed some issues with wtong types on the stack.

This commit is contained in:
Charles Betros 2016-03-24 08:52:02 -05:00
parent b283a07631
commit 83ad5f34cf
3 changed files with 368 additions and 349 deletions

View file

@ -2,34 +2,37 @@ using System;
using Cosmos.IL2CPU.ILOpCodes;
using CPUx86 = Cosmos.Assembler.x86;
namespace Cosmos.IL2CPU.X86.IL {
[Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldloca)]
public class Ldloca: ILOp {
public Ldloca(Cosmos.Assembler.Assembler aAsmblr)
: base(aAsmblr) {
}
namespace Cosmos.IL2CPU.X86.IL
{
[Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldloca)]
public class Ldloca : ILOp
{
public Ldloca(Cosmos.Assembler.Assembler aAsmblr)
: base(aAsmblr)
{
}
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode) {
var xOpVar = (OpVar)aOpCode;
var xAddress = GetEBPOffsetForLocal(aMethod, xOpVar.Value);
if (aMethod.MethodBase.Name == "Init" && aMethod.MethodBase.DeclaringType.Name == "Program")
{
Console.Write("");
}
xAddress += (GetStackCountForLocal(aMethod, aMethod.MethodBase.GetMethodBody().LocalVariables[xOpVar.Value]) - 1) * 4;
public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
{
var xOpVar = (OpVar) aOpCode;
var xAddress = GetEBPOffsetForLocal(aMethod, xOpVar.Value);
xAddress += (GetStackCountForLocal(aMethod, aMethod.MethodBase.GetMethodBody().LocalVariables[xOpVar.Value]) - 1)*4;
// xAddress contains full size of locals, excluding the actual local
new CPUx86.Mov {
DestinationReg = CPUx86.Registers.EAX,
SourceReg = CPUx86.Registers.EBP
};
new CPUx86.Sub {
DestinationReg = CPUx86.Registers.EAX,
SourceValue = xAddress
};
new CPUx86.Push {
DestinationReg = CPUx86.Registers.EAX,
};
// xAddress contains full size of locals, excluding the actual local
new CPUx86.Mov
{
DestinationReg = CPUx86.Registers.EAX,
SourceReg = CPUx86.Registers.EBP
};
new CPUx86.Sub
{
DestinationReg = CPUx86.Registers.EAX,
SourceValue = xAddress
};
new CPUx86.Push
{
DestinationReg = CPUx86.Registers.EAX,
};
}
}
}
}

View file

@ -8,246 +8,249 @@ using FieldInfo = System.Reflection.FieldInfo;
namespace Cosmos.IL2CPU.ILOpCodes
{
public class OpField : ILOpCode
{
public readonly FieldInfo Value;
public OpField(Code aOpCode, int aPos, int aNextPos, FieldInfo aValue, ExceptionHandlingClause aCurrentExceptionHandler)
: base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler)
public class OpField : ILOpCode
{
Value = aValue;
}
public readonly FieldInfo Value;
public override int GetNumberOfStackPops(MethodBase aMethod)
{
switch (OpCode)
{
case Code.Stsfld:
return 1;
case Code.Ldsfld:
return 0;
case Code.Stfld:
return 2;
case Code.Ldfld:
return 1;
case Code.Ldsflda:
return 0;
case Code.Ldflda:
return 1;
default:
throw new NotImplementedException("OpCode '" + OpCode + "' not implemented!");
}
}
public OpField(Code aOpCode, int aPos, int aNextPos, FieldInfo aValue, ExceptionHandlingClause aCurrentExceptionHandler)
: base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler)
{
Value = aValue;
}
public override int GetNumberOfStackPushes(MethodBase aMethod)
{
switch (OpCode)
{
case Code.Stsfld:
return 0;
case Code.Ldsfld:
return 1;
case Code.Stfld:
return 0;
case Code.Ldfld:
return 1;
case Code.Ldsflda:
return 1;
case Code.Ldflda:
return 1;
default:
throw new NotImplementedException("OpCode '" + OpCode + "' not implemented!");
}
}
protected override void DoInitStackAnalysis(MethodBase aMethod)
{
base.DoInitStackAnalysis(aMethod);
switch (OpCode)
{
case Code.Ldsfld:
StackPushTypes[0] = Value.FieldType;
if (StackPushTypes[0].IsEnum)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
}
return;
case Code.Ldsflda:
StackPushTypes[0] = typeof(IntPtr);
return;
case Code.Ldfld:
StackPushTypes[0] = Value.FieldType;
if (StackPushTypes[0].IsEnum)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
}
if (!Value.DeclaringType.IsValueType)
{
StackPopTypes[0] = Value.DeclaringType;
}
return;
case Code.Ldflda:
StackPopTypes[0] = Value.DeclaringType;
if (StackPopTypes[0].IsEnum)
{
StackPopTypes[0] = StackPopTypes[0].GetEnumUnderlyingType();
}
if (StackPopTypes[0].IsValueType && !StackPopTypes[0].IsPrimitive)
{
StackPopTypes[0] = StackPopTypes[0].MakePointerType();
}
StackPushTypes[0] = typeof(IntPtr);
return;
}
}
protected override void DoInterpretStackTypes(ref bool aSituationChanged)
{
base.DoInterpretStackTypes(ref aSituationChanged);
switch (OpCode)
{
case Code.Stfld:
if (StackPopTypes[1] == null)
{
return;
}
var expectedType = Value.FieldType;
if (expectedType.IsEnum)
{
expectedType = expectedType.GetEnumUnderlyingType();
}
else if (Value.DeclaringType.IsValueType && !Value.DeclaringType.IsPrimitive)
{
expectedType = typeof(void*);
}
if (StackPopTypes[1] == expectedType ||
StackPopTypes[1] == Value.FieldType)
{
return;
}
if (IsIntegralType(expectedType) &&
IsIntegralType(StackPopTypes[1]))
{
return;
}
if (expectedType == typeof(bool))
{
if (StackPopTypes[1] == typeof(int))
public override int GetNumberOfStackPops(MethodBase aMethod)
{
switch (OpCode)
{
return;
case Code.Stsfld:
return 1;
case Code.Ldsfld:
return 0;
case Code.Stfld:
return 2;
case Code.Ldfld:
return 1;
case Code.Ldsflda:
return 0;
case Code.Ldflda:
return 1;
default:
throw new NotImplementedException("OpCode '" + OpCode + "' not implemented!");
}
}
if (StackPopTypes[1] == typeof(NullRef))
{
return;
}
if (expectedType.IsAssignableFrom(StackPopTypes[1]))
{
return;
}
if (StackPopTypes[0] == null)
{
return;
}
}
if (Value.FieldType.IsAssignableFrom(StackPopTypes[0]))
{
return;
}
if (IsIntegralType(Value.FieldType) &&
IsIntegralType(StackPopTypes[0]))
{
return;
}
if (Value.FieldType == typeof(bool) &&
IsIntegralType(StackPopTypes[0]))
{
return;
}
if (Value.FieldType.IsEnum)
{
if (IsIntegralType(StackPopTypes[0]))
public override int GetNumberOfStackPushes(MethodBase aMethod)
{
switch (OpCode)
{
return;
case Code.Stsfld:
return 0;
case Code.Ldsfld:
return 1;
case Code.Stfld:
return 0;
case Code.Ldfld:
return 1;
case Code.Ldsflda:
return 1;
case Code.Ldflda:
return 1;
default:
throw new NotImplementedException("OpCode '" + OpCode + "' not implemented!");
}
}
if (IsPointer(Value.FieldType) &&
IsPointer(StackPopTypes[0]))
{
return;
}
if (Value.FieldType.IsClass &&
StackPopTypes[0] == typeof(NullRef))
{
return;
}
throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + expectedType.FullName + ")");
// throw new Exception("Wrong Poptype encountered!");
case Code.Stsfld:
if (StackPopTypes[0] == null)
{
return;
}
expectedType = Value.FieldType;
if (expectedType.IsEnum)
{
expectedType = expectedType.GetEnumUnderlyingType();
}
if (StackPopTypes[0] == expectedType ||
StackPopTypes[0] == Value.FieldType)
{
return;
}
if (IsIntegralType(expectedType) &&
IsIntegralType(StackPopTypes[0]))
{
return;
}
if (expectedType == typeof(bool))
{
if (StackPopTypes[0] == typeof(int))
}
protected override void DoInitStackAnalysis(MethodBase aMethod)
{
base.DoInitStackAnalysis(aMethod);
switch (OpCode)
{
return;
case Code.Ldsfld:
StackPushTypes[0] = Value.FieldType;
if (StackPushTypes[0].IsEnum)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
}
return;
case Code.Ldsflda:
StackPushTypes[0] = typeof(IntPtr);
return;
case Code.Ldfld:
StackPushTypes[0] = Value.FieldType;
if (StackPushTypes[0].IsEnum)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
}
if (!Value.DeclaringType.IsValueType)
{
StackPopTypes[0] = Value.DeclaringType;
}
return;
case Code.Ldflda:
StackPopTypes[0] = Value.DeclaringType;
if (StackPopTypes[0].IsEnum)
{
StackPopTypes[0] = StackPopTypes[0].GetEnumUnderlyingType();
}
if (StackPopTypes[0].IsValueType &&
!StackPopTypes[0].IsPrimitive)
{
StackPopTypes[0] = StackPopTypes[0].MakePointerType();
}
StackPushTypes[0] = typeof(IntPtr);
return;
default:
break;
}
}
if (expectedType.IsAssignableFrom(StackPopTypes[0]))
{
return;
}
if (StackPopTypes[0] == typeof(NullRef))
{
return;
}
if ((StackPopTypes[0] == typeof(IntPtr)
|| StackPopTypes[0] == typeof(UIntPtr))
& expectedType.IsPointer)
{
return;
}
throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + expectedType.FullName + ")");
case Code.Ldfld:
if (StackPopTypes[0] == null)
{
return;
}
if (!Value.DeclaringType.IsValueType)
{
return;
}
if (StackPopTypes[0] == Value.DeclaringType.MakePointerType() ||
StackPopTypes[0] == Value.DeclaringType.MakeByRefType() ||
StackPopTypes[0] == typeof(void*) ||
StackPopTypes[0] == typeof(IntPtr))
{
return;
}
if (StackPopTypes[0] == Value.DeclaringType)
{
return;
}
throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + Value.DeclaringType.FullName + ")");
}
}
protected override void DoInterpretStackTypes(ref bool aSituationChanged)
{
base.DoInterpretStackTypes(ref aSituationChanged);
switch (OpCode)
{
case Code.Stfld:
if (StackPopTypes[1] == null)
{
return;
}
var expectedType = Value.FieldType;
if (expectedType.IsEnum)
{
expectedType = expectedType.GetEnumUnderlyingType();
}
else if (Value.DeclaringType.IsValueType && !Value.DeclaringType.IsPrimitive)
{
expectedType = typeof(void*);
}
if (StackPopTypes[1] == expectedType ||
StackPopTypes[1] == Value.FieldType)
{
return;
}
if (IsIntegralType(expectedType) &&
IsIntegralType(StackPopTypes[1]))
{
return;
}
if (expectedType == typeof(bool))
{
if (StackPopTypes[1] == typeof(int))
{
return;
}
}
if (StackPopTypes[1] == typeof(NullRef))
{
return;
}
if (expectedType.IsAssignableFrom(StackPopTypes[1]))
{
return;
}
if (StackPopTypes[0] == null)
{
return;
}
if (Value.FieldType.IsAssignableFrom(StackPopTypes[0]))
{
return;
}
if (IsIntegralType(Value.FieldType) &&
IsIntegralType(StackPopTypes[0]))
{
return;
}
if (Value.FieldType == typeof(bool) &&
IsIntegralType(StackPopTypes[0]))
{
return;
}
if (Value.FieldType.IsEnum)
{
if (IsIntegralType(StackPopTypes[0]))
{
return;
}
}
if (IsPointer(Value.FieldType) &&
IsPointer(StackPopTypes[0]))
{
return;
}
if (Value.FieldType.IsClass &&
StackPopTypes[0] == typeof(NullRef))
{
return;
}
throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + expectedType.FullName + ")");
// throw new Exception("Wrong Poptype encountered!");
case Code.Stsfld:
if (StackPopTypes[0] == null)
{
return;
}
expectedType = Value.FieldType;
if (expectedType.IsEnum)
{
expectedType = expectedType.GetEnumUnderlyingType();
}
if (StackPopTypes[0] == expectedType ||
StackPopTypes[0] == Value.FieldType)
{
return;
}
if (IsIntegralType(expectedType) &&
IsIntegralType(StackPopTypes[0]))
{
return;
}
if (expectedType == typeof(bool))
{
if (StackPopTypes[0] == typeof(int))
{
return;
}
}
if (expectedType.IsAssignableFrom(StackPopTypes[0]))
{
return;
}
if (StackPopTypes[0] == typeof(NullRef))
{
return;
}
if ((StackPopTypes[0] == typeof(IntPtr)
|| StackPopTypes[0] == typeof(UIntPtr))
& expectedType.IsPointer)
{
return;
}
throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + expectedType.FullName + ")");
case Code.Ldfld:
if (StackPopTypes[0] == null)
{
return;
}
if (!Value.DeclaringType.IsValueType)
{
return;
}
if (StackPopTypes[0] == Value.DeclaringType.MakePointerType() ||
StackPopTypes[0] == Value.DeclaringType.MakeByRefType() ||
StackPopTypes[0] == typeof(void*) ||
StackPopTypes[0] == typeof(IntPtr))
{
return;
}
if (StackPopTypes[0] == Value.DeclaringType)
{
return;
}
throw new Exception("Wrong Poptype encountered! (Type = " + StackPopTypes[0].FullName + ", expected = " + Value.DeclaringType.FullName + ")");
}
}
}
}
}

View file

@ -6,104 +6,117 @@ using System.Text;
namespace Cosmos.IL2CPU.ILOpCodes
{
public class OpVar : ILOpCode
{
public readonly UInt16 Value;
public OpVar(Code aOpCode, int aPos, int aNextPos, UInt16 aValue, ExceptionHandlingClause aCurrentExceptionHandler)
: base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler)
public class OpVar : ILOpCode
{
Value = aValue;
}
public readonly UInt16 Value;
public override int GetNumberOfStackPops(MethodBase aMethod)
{
switch (OpCode)
{
case Code.Ldloc:
case Code.Ldloca:
case Code.Ldarg:
case Code.Ldarga:
return 0;
case Code.Stloc:
case Code.Starg:
return 1;
default:
throw new NotImplementedException("OpCode '" + OpCode + "' not implemented!");
}
}
public OpVar(Code aOpCode, int aPos, int aNextPos, UInt16 aValue,
ExceptionHandlingClause aCurrentExceptionHandler)
: base(aOpCode, aPos, aNextPos, aCurrentExceptionHandler)
{
Value = aValue;
}
public override int GetNumberOfStackPushes(MethodBase aMethod)
{
switch (OpCode)
{
case Code.Stloc:
case Code.Starg:
return 0;
case Code.Ldloc:
case Code.Ldloca:
case Code.Ldarg:
case Code.Ldarga:
return 1;
default:
throw new NotImplementedException("OpCode '" + OpCode + "' not implemented!");
}
}
protected override void DoInitStackAnalysis(MethodBase aMethod)
{
base.DoInitStackAnalysis(aMethod);
switch (OpCode)
{
case Code.Ldloc:
case Code.Ldloca:
var xBody = aMethod.GetMethodBody();
if (xBody != null)
{
StackPushTypes[0] = xBody.LocalVariables[Value].LocalType;
if (StackPushTypes[0].IsEnum)
public override int GetNumberOfStackPops(MethodBase aMethod)
{
switch (OpCode)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
case Code.Ldloc:
case Code.Ldloca:
case Code.Ldarg:
case Code.Ldarga:
return 0;
case Code.Stloc:
case Code.Starg:
return 1;
default:
throw new NotImplementedException("OpCode '" + OpCode + "' not implemented!");
}
else if ((OpCode == Code.Ldloca) && (!StackPushTypes[0].IsValueType))
}
public override int GetNumberOfStackPushes(MethodBase aMethod)
{
switch (OpCode)
{
StackPushTypes[0] = StackPushTypes[0].MakePointerType();
case Code.Stloc:
case Code.Starg:
return 0;
case Code.Ldloc:
case Code.Ldloca:
case Code.Ldarg:
case Code.Ldarga:
return 1;
default:
throw new NotImplementedException("OpCode '" + OpCode + "' not implemented!");
}
}
return;
case Code.Ldarg:
case Code.Ldarga:
var xArgIndexCorrection = 0;
if (!aMethod.IsStatic)
{
if (Value == 0)
}
protected override void DoInitStackAnalysis(MethodBase aMethod)
{
base.DoInitStackAnalysis(aMethod);
var xArgIndexCorrection = 0;
var xBody = aMethod.GetMethodBody();
var xParams = aMethod.GetParameters();
switch (OpCode)
{
StackPushTypes[0] = aMethod.DeclaringType;
if (StackPushTypes[0].IsEnum)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
}
else if ((OpCode == Code.Ldarga) || ((OpCode == Code.Ldarg) && (StackPushTypes[0].IsValueType)))
{
StackPushTypes[0] = StackPushTypes[0].MakePointerType();
}
return;
case Code.Ldloc:
if (xBody != null)
{
StackPushTypes[0] = xBody.LocalVariables[Value].LocalType;
if (StackPushTypes[0].IsEnum)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
}
}
return;
case Code.Ldloca:
if (xBody != null)
{
StackPushTypes[0] = xBody.LocalVariables[Value].LocalType.MakePointerType();
}
return;
case Code.Ldarg:
if (!aMethod.IsStatic)
{
if (Value == 0)
{
StackPushTypes[0] = aMethod.DeclaringType;
if (StackPushTypes[0].IsEnum)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
}
else if (StackPushTypes[0].IsValueType)
{
StackPushTypes[0] = StackPushTypes[0].MakePointerType();
}
return;
}
xArgIndexCorrection = -1;
}
StackPushTypes[0] = xParams[Value + xArgIndexCorrection].ParameterType;
if (StackPushTypes[0].IsEnum)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
}
return;
case Code.Ldarga:
if (!aMethod.IsStatic)
{
if (Value == 0)
{
if (StackPushTypes[0].IsValueType)
{
StackPushTypes[0] = StackPushTypes[0].MakePointerType();
}
return;
}
xArgIndexCorrection = -1;
}
StackPushTypes[0] = xParams[Value + xArgIndexCorrection].ParameterType;
StackPushTypes[0] = StackPushTypes[0].MakePointerType();
return;
}
xArgIndexCorrection = -1;
}
var xParams = aMethod.GetParameters();
StackPushTypes[0] = xParams[Value + xArgIndexCorrection].ParameterType;
if (StackPushTypes[0].IsEnum)
{
StackPushTypes[0] = StackPushTypes[0].GetEnumUnderlyingType();
}
else if (OpCode == Code.Ldarga)
{
StackPushTypes[0] = StackPushTypes[0].MakePointerType();
}
return;
}
}
}
}
}
}