This commit is contained in:
Matthijs ter Woord 2016-06-15 11:45:30 -04:00
parent bbb8265166
commit feef7db59a

View file

@ -1,4 +1,4 @@
//#define VMT_DEBUG
//#define VMT_DEBUG
using System;
using System.Collections.Generic;
using System.Diagnostics;
@ -21,6 +21,7 @@ using Cosmos.IL2CPU.Plugs;
using Cosmos.IL2CPU.X86.IL;
using Mono.Cecil;
using XSharp.Compiler;
using static XSharp.Compiler.XSRegisters;
using Add = Cosmos.Assembler.x86.Add;
using Call = Cosmos.Assembler.x86.Call;
using FieldInfo = Cosmos.IL2CPU.X86.IL.FieldInfo;
@ -160,14 +161,14 @@ namespace Cosmos.IL2CPU
if (DebugEnabled && StackCorruptionDetection)
{
// if StackCorruption detection is active, we're also going to emit a stack overflow detection
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EAX), "Before_Kernel_Stack");
XS.Compare(XSRegisters.OldToNewRegister(RegistersEnum.EAX), XSRegisters.OldToNewRegister(RegistersEnum.ESP));
XS.Set(OldToNewRegister(RegistersEnum.EAX), "Before_Kernel_Stack");
XS.Compare(OldToNewRegister(RegistersEnum.EAX), OldToNewRegister(RegistersEnum.ESP));
new ConditionalJump { Condition = ConditionalTestEnum.LessThan, DestinationLabel = mCurrentMethodLabel + ".StackOverflowCheck_End" };
new ClearInterruptFlag();
// don't remove the call. It seems pointless, but we need it to retrieve the EIP value
new Call { DestinationLabel = mCurrentMethodLabel + ".StackOverflowCheck_GetAddress" };
new Label(mCurrentMethodLabel + ".StackOverflowCheck_GetAddress");
XS.Pop(XSRegisters.OldToNewRegister(RegistersEnum.EAX));
XS.Pop(OldToNewRegister(RegistersEnum.EAX));
new Mov { DestinationRef = ElementReference.New("DebugStub_CallerEIP"), DestinationIsIndirect = true, SourceReg = RegistersEnum.EAX };
new Call { DestinationLabel = "DebugStub_SendStackOverflowOccurred" };
new Halt();
@ -183,18 +184,18 @@ namespace Cosmos.IL2CPU
var xName = DataMember.FilterStringForIncorrectChars("CCTOR_CALLED__" + LabelName.GetFullName(aMethod.MethodBase.DeclaringType));
var xAsmMember = new DataMember(xName, (byte)0);
Assembler.DataMembers.Add(xAsmMember);
new Compare { DestinationRef = ElementReference.New(xName), DestinationIsIndirect = true, Size = 8, SourceValue = 1 };
XS.Compare(xName, 1, destinationIsIndirect: true, size: RegisterSize.Byte8);
new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = ".BeforeQuickReturn" };
new Mov { DestinationRef = ElementReference.New(xName), DestinationIsIndirect = true, Size = 8, SourceValue = 1 };
XS.Set(xName, 1, destinationIsIndirect: true, size: RegisterSize.Byte8);
new Jump { DestinationLabel = ".AfterCCTorAlreadyCalledCheck" };
new Label(".BeforeQuickReturn");
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.ECX), 0);
XS.Set(OldToNewRegister(RegistersEnum.ECX), 0);
new Return { };
new Label(".AfterCCTorAlreadyCalledCheck");
}
XS.Push(XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EBP), XSRegisters.OldToNewRegister(RegistersEnum.ESP));
XS.Push(OldToNewRegister(RegistersEnum.EBP));
XS.Set(OldToNewRegister(RegistersEnum.EBP), OldToNewRegister(RegistersEnum.ESP));
if (DebugMode == DebugMode.Source)
{
@ -343,7 +344,7 @@ namespace Cosmos.IL2CPU
};
}
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.ECX), 0);
XS.Set(OldToNewRegister(RegistersEnum.ECX), 0);
var xTotalArgsSize = (from item in aMethod.MethodBase.GetParameters()
select (int)ILOp.Align(ILOp.SizeOfType(item.ParameterType), 4)).Sum();
if (!aMethod.MethodBase.IsStatic)
@ -386,7 +387,7 @@ namespace Cosmos.IL2CPU
var xOffset = GetResultCodeOffset(xReturnSize, (uint)xTotalArgsSize);
for (int i = 0; i < ((int)(xReturnSize/4)); i++)
{
XS.Pop(XSRegisters.OldToNewRegister(RegistersEnum.EAX));
XS.Pop(OldToNewRegister(RegistersEnum.EAX));
new Mov { DestinationReg = RegistersEnum.EBP, DestinationIsIndirect = true, DestinationDisplacement = (int)(xOffset + ((i + 0) * 4)), SourceReg = RegistersEnum.EAX };
}
// extra stack space is the space reserved for example when a "public static int TestMethod();" method is called, 4 bytes is pushed, to make room for result;
@ -405,13 +406,13 @@ namespace Cosmos.IL2CPU
if (xLocalsSize >= 256)
{
XS.Add(XSRegisters.OldToNewRegister(RegistersEnum.ESP), 255);
XS.Add(OldToNewRegister(RegistersEnum.ESP), 255);
xLocalsSize -= 255;
}
}
if (xLocalsSize > 0)
{
XS.Add(XSRegisters.OldToNewRegister(RegistersEnum.ESP), xLocalsSize);
XS.Add(OldToNewRegister(RegistersEnum.ESP), xLocalsSize);
}
}
}
@ -419,21 +420,21 @@ namespace Cosmos.IL2CPU
{
// if debugstub is active, emit a stack corruption detection. at this point EBP and ESP should have the same value.
// if not, we should somehow break here.
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EAX), XSRegisters.OldToNewRegister(RegistersEnum.ESP));
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EBX), XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Compare(XSRegisters.OldToNewRegister(RegistersEnum.EAX), XSRegisters.OldToNewRegister(RegistersEnum.EBX));
XS.Set(OldToNewRegister(RegistersEnum.EAX), OldToNewRegister(RegistersEnum.ESP));
XS.Set(OldToNewRegister(RegistersEnum.EBX), OldToNewRegister(RegistersEnum.EBP));
XS.Compare(OldToNewRegister(RegistersEnum.EAX), OldToNewRegister(RegistersEnum.EBX));
new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = xLabelExc + "__2" };
new ClearInterruptFlag();
// don't remove the call. It seems pointless, but we need it to retrieve the EIP value
new Call { DestinationLabel = xLabelExc + ".MethodFooterStackCorruptionCheck_Break_on_location" };
new Label(xLabelExc + ".MethodFooterStackCorruptionCheck_Break_on_location");
XS.Pop(XSRegisters.OldToNewRegister(RegistersEnum.EAX));
XS.Pop(OldToNewRegister(RegistersEnum.EAX));
new Mov { DestinationRef = ElementReference.New("DebugStub_CallerEIP"), DestinationIsIndirect = true, SourceReg = RegistersEnum.EAX };
new Call { DestinationLabel = "DebugStub_SendStackCorruptionOccurred" };
new Halt();
}
new Label(xLabelExc + "__2");
XS.Pop(XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Pop(OldToNewRegister(RegistersEnum.EBP));
var xRetSize = ((int)xTotalArgsSize) - ((int)xReturnSize);
if (xRetSize < 0)
{
@ -858,7 +859,7 @@ namespace Cosmos.IL2CPU
var xSize = X86.IL.Call.GetStackSizeToReservate(aTargetMethod.MethodBase);
if (xSize > 0)
{
XS.Sub(XSRegisters.OldToNewRegister(RegistersEnum.ESP), xSize);
XS.Sub(OldToNewRegister(RegistersEnum.ESP), xSize);
}
new Call { DestinationLabel = ILOp.GetMethodLabel(aTargetMethod) };
var xMethodInfo = aMethod.MethodBase as SysReflection.MethodInfo;
@ -879,7 +880,7 @@ namespace Cosmos.IL2CPU
}
for (int i = 0; i < xResultSize / 4; i++)
{
XS.Add(XSRegisters.OldToNewRegister(RegistersEnum.ESP), 4);
XS.Add(OldToNewRegister(RegistersEnum.ESP), 4);
}
}, aNextLabel);
}
@ -909,8 +910,8 @@ namespace Cosmos.IL2CPU
{
XS.Comment("---------------------------------------------------------");
new Label(InitVMTCodeLabel);
XS.Push(XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EBP), XSRegisters.OldToNewRegister(RegistersEnum.ESP));
XS.Push(OldToNewRegister(RegistersEnum.EBP));
XS.Set(OldToNewRegister(RegistersEnum.EBP), OldToNewRegister(RegistersEnum.ESP));
mSequences = new DebugInfo.SequencePoint[0];
var xSetTypeInfoRef = VTablesImplRefs.SetTypeInfoRef;
@ -1166,7 +1167,7 @@ namespace Cosmos.IL2CPU
#endif
new Label("_END_OF_" + InitVMTCodeLabel);
XS.Pop(XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Pop(OldToNewRegister(RegistersEnum.EBP));
new Return();
}
@ -1373,8 +1374,8 @@ namespace Cosmos.IL2CPU
// at the time the datamembers for literal strings are created, the type id for string is not yet determined.
// for now, we fix this at runtime.
new Label(InitStringIDsLabel);
XS.Push(XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EBP), XSRegisters.OldToNewRegister(RegistersEnum.ESP));
XS.Push(OldToNewRegister(RegistersEnum.EBP));
XS.Set(OldToNewRegister(RegistersEnum.EBP), OldToNewRegister(RegistersEnum.ESP));
new Mov { DestinationReg = RegistersEnum.EAX, SourceRef = ElementReference.New(ILOp.GetTypeIDLabel(typeof(String))), SourceIsIndirect = true };
new Mov { DestinationRef = ElementReference.New("static_field__System_String_Empty"), DestinationIsIndirect = true, SourceRef = ElementReference.New(LdStr.GetContentsArrayName("")) };
@ -1398,12 +1399,12 @@ namespace Cosmos.IL2CPU
new Mov { DestinationRef = ElementReference.New(xDataMember.Name), DestinationIsIndirect = true, SourceReg = RegistersEnum.EAX };
}
Assembler.WriteDebugVideo("Done");
XS.Pop(XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Pop(OldToNewRegister(RegistersEnum.EBP));
new Return();
new Label(CosmosAssembler.EntryPointName);
XS.Push(XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EBP), XSRegisters.OldToNewRegister(RegistersEnum.ESP));
XS.Push(OldToNewRegister(RegistersEnum.EBP));
XS.Set(OldToNewRegister(RegistersEnum.EBP), OldToNewRegister(RegistersEnum.ESP));
new Call { DestinationLabel = InitVMTCodeLabel };
Assembler.WriteDebugVideo("Initializing string IDs.");
new Call { DestinationLabel = InitStringIDsLabel };
@ -1418,7 +1419,7 @@ namespace Cosmos.IL2CPU
new Label(xCurLabel);
X86.IL.Call.DoExecute(Assembler, null, aEntrypoint.DeclaringType.BaseType.GetMethod("Start"), null, xCurLabel, CosmosAssembler.EntryPointName + ".AfterStart", DebugEnabled);
new Label(CosmosAssembler.EntryPointName + ".AfterStart");
XS.Pop(XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Pop(OldToNewRegister(RegistersEnum.EBP));
new Return();
if (ShouldOptimize)
@ -1510,19 +1511,19 @@ namespace Cosmos.IL2CPU
// if debugstub is active, emit a stack corruption detection. at this point EBP and ESP should have the same value.
// if not, we should somehow break here.
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EAX), XSRegisters.OldToNewRegister(RegistersEnum.ESP));
XS.Set(XSRegisters.OldToNewRegister(RegistersEnum.EBX), XSRegisters.OldToNewRegister(RegistersEnum.EBP));
XS.Set(OldToNewRegister(RegistersEnum.EAX), OldToNewRegister(RegistersEnum.ESP));
XS.Set(OldToNewRegister(RegistersEnum.EBX), OldToNewRegister(RegistersEnum.EBP));
if (xStackDifference != 0)
{
XS.Add(XSRegisters.OldToNewRegister(RegistersEnum.EAX), xStackDifference.Value);
XS.Add(OldToNewRegister(RegistersEnum.EAX), xStackDifference.Value);
}
XS.Compare(XSRegisters.OldToNewRegister(RegistersEnum.EAX), XSRegisters.OldToNewRegister(RegistersEnum.EBX));
XS.Compare(OldToNewRegister(RegistersEnum.EAX), OldToNewRegister(RegistersEnum.EBX));
new ConditionalJump { Condition = ConditionalTestEnum.Equal, DestinationLabel = xLabel + ".StackCorruptionCheck_End" };
new ClearInterruptFlag();
// don't remove the call. It seems pointless, but we need it to retrieve the EIP value
new Call { DestinationLabel = xLabel + ".StackCorruptionCheck_GetAddress" };
new Label(xLabel + ".StackCorruptionCheck_GetAddress");
XS.Pop(XSRegisters.OldToNewRegister(RegistersEnum.EAX));
XS.Pop(OldToNewRegister(RegistersEnum.EAX));
new Mov { DestinationRef = ElementReference.New("DebugStub_CallerEIP"), DestinationIsIndirect = true, SourceReg = RegistersEnum.EAX };
new Call { DestinationLabel = "DebugStub_SendStackCorruptionOccurred" };
new Halt();