/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown if divide operands are floating point numbers or if attempting to divide 64-bit numbers. /// </exception> /// <exception cref="System.InvalidOperationException"> /// Thrown if either operand is < 4 bytes long. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { StackItem testItem = conversionState.CurrentStackFrame.Stack.Pop(); if (testItem.isFloat) { //TODO - Support floats throw new NotSupportedException("Switch for floats no supported!"); } else if (testItem.sizeOnStackInBytes != 4) { //TODO - Support other sizes throw new NotSupportedException("Switch for non-int32s not supported!"); } conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); for (int i = 0; i < theOp.ValueBytes.Length / 4; i++) { int branchOffset = theOp.NextOffset + Utilities.ReadInt32(theOp.ValueBytes, i * 4); ILOp opToGoTo = conversionState.Input.At(branchOffset); int branchPos = conversionState.PositionOf(opToGoTo); conversionState.Append(new ASMOps.Cmp() { Arg1 = "EAX", Arg2 = i.ToString() }); conversionState.Append(new ASMOps.Jmp() { JumpType = ASMOps.JmpOp.JumpEqual, DestILPosition = branchPos }); } }
/// <summary> /// See base class documentation. /// <para>To Do's:</para> /// <list type="bullet"> /// <item> /// <term>To do</term> /// <description>Implement storing of float arguments.</description> /// </item> /// </list> /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotImplementedException"> /// Thrown when storing a float argument is required as it currently hasn't been /// implemented. /// </exception> /// <exception cref="System.ArgumentException"> /// Thrown when an invalid number of bytes is specified for the argument to store. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Get the index of the argument to load Int16 index = 0; switch ((OpCodes)theOp.opCode.Value) { case OpCodes.Starg: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Starg_S: index = (Int16)theOp.ValueBytes[0]; break; } Types.VariableInfo argInfo = conversionState.Input.TheMethodInfo.ArgumentInfos[index]; //Used to store the number of bytes to add to EBP to get to the arg int BytesOffsetFromEBP = argInfo.Offset; //Pop the argument value from the stack int bytesForArg = argInfo.TheTypeInfo.SizeOnStackInBytes; for (int i = 0; i < bytesForArg; i += 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "[EBP+" + (BytesOffsetFromEBP+i) + "]" }); } //Pop the arg value from our stack conversionState.CurrentStackFrame.Stack.Pop(); }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop(); StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop(); if (itemA.sizeOnStackInBytes == 4 && itemB.sizeOnStackInBytes == 4) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false, isValue = true }); } else if (itemA.sizeOnStackInBytes == 8 && itemB.sizeOnStackInBytes == 8) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false, isValue = true }); } else { throw new NotSupportedException("Unsupported number of bytes for compare equal to!"); } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown when the metadata token is not for method metadata. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Load token i.e. typeref //It should also support methodref and fieldrefs int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0); try { Type theType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken); if (theType == null) { throw new NullReferenceException(); } string typeTableId = conversionState.TheILLibrary.GetTypeInfo(theType).ID; conversionState.AddExternalLabel(typeTableId); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = typeTableId }); conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false, isValue = false }); } catch { throw new NotSupportedException("The metadata token specifies a fieldref or methodref which isn't supported yet!"); } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop(); StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop(); if (itemA.sizeOnStackInBytes == 4 && itemB.sizeOnStackInBytes == 4) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false }); } else if (itemA.sizeOnStackInBytes == 8 && itemB.sizeOnStackInBytes == 8) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 8, isGCManaged = false }); } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Push the previous method's ebp conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EBP" }); //Set ebp for this method //See calling convention spec - this allows easy access of //args and locals within the method without having to track //temporary values (which would be a nightmare with the //exception handling implementation that the kernel uses!) conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "ESP", Dest = "EBP" }); //Allocate stack space for locals //Only bother if there are any locals if (conversionState.Input.TheMethodInfo.LocalInfos.Count > 0) { int totalBytes = 0; foreach (Types.VariableInfo aLocal in conversionState.Input.TheMethodInfo.LocalInfos) { totalBytes += aLocal.TheTypeInfo.SizeOnStackInBytes; } //We do not use "sub esp, X" (see below) because that leaves //junk memory - we need memory to be "initialised" to 0 //so that local variables are null unless properly initialised. //This prevents errors in the GC. for (int i = 0; i < totalBytes / 4; i++) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "0" }); } //result.AppendLine(string.Format("sub esp, {0}", totalBytes)); } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> public override void Convert(ILConversionState conversionState, ILOp theOp) { int dwordsToRotate = theOp.ValueBytes == null ? 2 : BitConverter.ToInt32(theOp.ValueBytes, 0); int bytesShift = 0; for (int i = 0; i < dwordsToRotate; i++) { if (i == 0) { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + bytesShift.ToString() + "]", Dest = "EAX" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + (bytesShift + 4).ToString() + "]", Dest = "EBX" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "EBX", Dest = "[ESP+" + bytesShift.ToString() + "]" }); } else if (i == dwordsToRotate - 1) { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "[ESP+" + bytesShift.ToString() + "]" }); } else { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "[ESP+" + (bytesShift + 4).ToString() + "]", Dest = "EBX" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "EBX", Dest = "[ESP+" + bytesShift.ToString() + "]" }); } bytesShift += 4; } rotateStackItems(conversionState, theOp.StackSwitch_Items, 1); }
public override void Convert(ILConversionState conversionState, ILOp theOp) { //Save return address conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$ra" }); //Push the previous method's fp conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$fp" }); //Set fp for this method conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$sp", Dest = "$fp", MoveType = ASMOps.Mov.MoveTypes.RegToReg }); //Allocate stack space for locals //Only bother if there are any locals if (conversionState.Input.TheMethodInfo.LocalInfos.Count > 0) { int totalBytes = 0; foreach (Types.VariableInfo aLocal in conversionState.Input.TheMethodInfo.LocalInfos) { totalBytes += aLocal.TheTypeInfo.SizeOnStackInBytes; } //We do not use "sub esp, X" (see below) because that leaves //junk memory - we need memory to be "initialised" to 0 //so that local variables are null unless properly initialised. //This prevents errors in the GC. for (int i = 0; i < totalBytes / 4; i++) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$zero" }); } //result.AppendLine(string.Format("sub esp, {0}", totalBytes)); } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { MethodBase constructorMethod = theOp.MethodToCall; Type objectType = constructorMethod.DeclaringType; if (typeof(Delegate).IsAssignableFrom(objectType)) { StackItem funcPtrItem = conversionState.CurrentStackFrame.Stack.Pop(); ; conversionState.CurrentStackFrame.Stack.Pop(); conversionState.CurrentStackFrame.Stack.Push(funcPtrItem); return; } Types.MethodInfo constructorMethodInfo = conversionState.TheILLibrary.GetMethodInfo(constructorMethod); ParameterInfo[] allParams = constructorMethod.GetParameters(); foreach (ParameterInfo aParam in allParams) { conversionState.CurrentStackFrame.Stack.Pop(); } conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isNewGCObject = true, isGCManaged = true, isValue = false }); }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> public override void Convert(ILConversionState conversionState, ILOp theOp) { int dwordsToRotate = theOp.ValueBytes == null ? 2 : BitConverter.ToInt32(theOp.ValueBytes, 0); int bytesShift = 0; for (int i = 0; i < dwordsToRotate; i++) { if (i == 0) { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = bytesShift.ToString() + "($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = (bytesShift + 4).ToString() + "($sp)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t1", Dest = bytesShift.ToString() + "($sp)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory }); } else if (i == dwordsToRotate - 1) { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = bytesShift + "($sp)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory }); } else { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = (bytesShift + 4).ToString() + "($sp)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t1", Dest = bytesShift.ToString() + "($sp)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory }); } bytesShift += 4; } rotateStackItems(conversionState, theOp.StackSwitch_Items, 1); }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { StackItem addressItem = conversionState.CurrentStackFrame.Stack.Pop(); int bytesToLoad = 0; switch ((OpCodes)theOp.opCode.Value) { case OpCodes.Ldind_U1: case OpCodes.Ldind_I1: bytesToLoad = 1; break; case OpCodes.Ldind_U2: case OpCodes.Ldind_I2: bytesToLoad = 2; break; case OpCodes.Ldind_U4: case OpCodes.Ldind_I4: case OpCodes.Ldind_I: bytesToLoad = 4; break; case OpCodes.Ldind_I8: bytesToLoad = 8; break; case OpCodes.Ldind_Ref: bytesToLoad = Options.AddressSizeInBytes; break; } conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = bytesToLoad == 8 ? 8 : 4, isFloat = false, isGCManaged = false }); }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown if either or both values to not are floating point values or /// if the values are 8 bytes in size. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Pop item to negate StackItem itemA = conversionState.CurrentStackFrame.Stack.Peek(); if (itemA.isFloat) { //SUPPORT - floats throw new NotSupportedException("Negate float vals not suppported yet!"); } if (itemA.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); //To not, arg Xor -1 conversionState.Append(new ASMOps.Mov() { Dest = "$t4", Src = "0xFFFFFFFF", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg }); conversionState.Append(new ASMOps.Xor() { Dest = "$t0", Src1 = "$t0", Src2 = "$t4" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t0" }); } else if (itemA.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t3" }); conversionState.Append(new ASMOps.Mov() { Dest = "$t4", Src = "0xFFFFFFFF", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg }); conversionState.Append(new ASMOps.Xor() { Dest = "$t0", Src1 = "$t0", Src2 = "$t4" }); conversionState.Append(new ASMOps.Xor() { Dest = "$t3", Src1 = "$t3", Src2 = "$t4" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t3" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t0" }); } else { throw new NotSupportedException("Stack item size not supported by neg op!"); } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown when loading a static float field. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Load static field //Load the metadata token used to get the type info int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0); //Get the type info for the object to load Type theType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken); Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theType); //Get the object size information int size = theTypeInfo.SizeOnStackInBytes; //Load the object onto the stack conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "ECX" }); for (int i = size - 4; i >= 0; i -= 4) { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "[ECX+" + i.ToString() + "]", Dest = "EAX" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EAX" }); } int extra = size % 4; for (int i = extra - 1; i >= 0; i--) { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "[ECX+" + i.ToString() + "]", Dest = "AL" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Byte, Src = "AL" }); } conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = size, isGCManaged = false }); }
public static void InsertPageFaultDetection(ILConversionState conversionState, string reg, int offset, ILOp.OpCodes opCode) { if (PageFaultDetectionEnabled) { conversionState.Append(new ASMOps.Call() { Target = PageFaultDetectionMethod }); } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { StackItem itemToConvert = conversionState.CurrentStackFrame.Stack.Pop(); int numBytesToConvertTo = 0; switch ((OpCodes)theOp.opCode.Value) { case OpCodes.Conv_U: numBytesToConvertTo = 4; break; case OpCodes.Conv_U1: numBytesToConvertTo = 1; break; case OpCodes.Conv_U2: numBytesToConvertTo = 2; break; case OpCodes.Conv_U4: numBytesToConvertTo = 4; break; case OpCodes.Conv_U8: numBytesToConvertTo = 8; break; } bool pushEDX = numBytesToConvertTo == 8; conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = (pushEDX ? 8 : 4), isFloat = false, isGCManaged = false }); }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0); FieldInfo theField = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken); switch ((OpCodes)theOp.opCode.Value) { case OpCodes.Ldsfld: { Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType); int size = theTypeInfo.SizeOnStackInBytes; bool isFloat = Utilities.IsFloat(theField.FieldType); conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = isFloat, sizeOnStackInBytes = (size == 8 ? 8 : 4), isGCManaged = theTypeInfo.IsGCManaged, isValue = theTypeInfo.IsValueType }); } break; case OpCodes.Ldsflda: conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false, isValue = false }); break; } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0); FieldInfo theField = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken); bool valueisFloat = Utilities.IsFloat(theField.FieldType); Types.TypeInfo fieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType); int stackSize = fieldTypeInfo.SizeOnStackInBytes; StackItem objPointer = conversionState.CurrentStackFrame.Stack.Pop(); if ((OpCodes)theOp.opCode.Value == OpCodes.Ldflda) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false }); } else { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = valueisFloat, sizeOnStackInBytes = stackSize, isGCManaged = fieldTypeInfo.IsGCManaged }); } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { //Pop in reverse order to push StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop(); StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop(); if (itemA.sizeOnStackInBytes == 4 && itemB.sizeOnStackInBytes == 4) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false, isValue = itemA.isValue && itemB.isValue }); } else if (itemA.sizeOnStackInBytes == 8 && itemB.sizeOnStackInBytes == 8) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, isNewGCObject = false, sizeOnStackInBytes = 8, isGCManaged = false, isValue = itemA.isValue && itemB.isValue }); } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown if either or both values to shift left are floating point values or /// if the values are 8 bytes in size. /// </exception> /// <exception cref="System.InvalidOperationException"> /// Thrown if either or both values to multiply are not 4 or 8 bytes /// in size or if the values are of different size. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { StackItem theItem = conversionState.CurrentStackFrame.Stack.Peek(); if (theItem.isFloat) { //SUPPORT - Not op for floats throw new NotSupportedException("Not op not supported for float operands!"); } if (theItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); conversionState.Append(new ASMOps.Not() { Dest = "EAX" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EAX" }); } else if (theItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EBX" }); conversionState.Append(new ASMOps.Not() { Dest = "EAX" }); conversionState.Append(new ASMOps.Not() { Dest = "EBX" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EBX" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EAX" }); } else { throw new NotSupportedException("Not op not supported for operand size!"); } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { Int16 index = 0; switch ((OpCodes)theOp.opCode.Value) { case OpCodes.Ldarg: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldarg_0: index = 0; break; case OpCodes.Ldarg_1: index = 1; break; case OpCodes.Ldarg_2: index = 2; break; case OpCodes.Ldarg_3: index = 3; break; case OpCodes.Ldarg_S: index = (Int16)theOp.ValueBytes[0]; break; case OpCodes.Ldarga: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldarga_S: index = (Int16)theOp.ValueBytes[0]; break; } List<Type> allParams = conversionState.Input.TheMethodInfo.UnderlyingInfo.GetParameters().Select(x => x.ParameterType).ToList(); if (!conversionState.Input.TheMethodInfo.IsStatic) { allParams.Insert(0, conversionState.Input.TheMethodInfo.UnderlyingInfo.DeclaringType); } if ((OpCodes)theOp.opCode.Value == OpCodes.Ldarga || (OpCodes)theOp.opCode.Value == OpCodes.Ldarga_S) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = 4, isFloat = false, isGCManaged = false }); } else { Types.TypeInfo paramTypeInfo = conversionState.TheILLibrary.GetTypeInfo(allParams[index]); int bytesForArg = paramTypeInfo.SizeOnStackInBytes; conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = bytesForArg, isFloat = false, isGCManaged = paramTypeInfo.IsGCManaged }); } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown when loading a static float field. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Load the metadata token used to get the type info int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0); //Get the type info for the object to load Type theType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken); Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theType); //Get the object size information int size = theTypeInfo.IsValueType ? theTypeInfo.SizeOnHeapInBytes : theTypeInfo.SizeOnStackInBytes; conversionState.CurrentStackFrame.Stack.Pop(); conversionState.CurrentStackFrame.Stack.Pop(); //Load the object onto the stack conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Dest = "ECX", Src = "[ESP+" + theTypeInfo.SizeOnStackInBytes + "]" }); if (size == 1) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[ECX]" }); } else if (size == 2) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[ECX]" }); } else if (size >= 4) { for (int i = 0; i < size; i += 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); switch (size - i) { case 1: conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[ECX+" + i + "]" }); break; case 2: conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[ECX+" + i + "]" }); break; case 3: conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "AL", Dest = "[ECX+" + i + "]" }); conversionState.Append(new ASMOps.Shr() { Src = "16", Dest = "EAX" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "AX", Dest = "[ECX+" + (i + 1) + "]" }); break; default: conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "EAX", Dest = "[ECX+" + i + "]" }); break; } } } else { throw new ArgumentOutOfRangeException("Storing object with unsupported size! Size: " + size.ToString()); } conversionState.Append(new ASMOps.Add() { Dest = "ESP", Src = "4" }); }
public override void Preprocess(ILPreprocessState preprocessState, ILOp theOp) { for (int i = 0; i < theOp.ValueBytes.Length / 4; i++) { int branchOffset = theOp.NextOffset + Utilities.ReadInt32(theOp.ValueBytes, i * 4); ILOp opToGoTo = preprocessState.Input.At(branchOffset); opToGoTo.LabelRequired = true; } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false }); }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { MethodBase methodToCall = theOp.MethodToCall; Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall); if (methodToCall is MethodInfo) { Type retType = ((MethodInfo)methodToCall).ReturnType; Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType); StackItem returnItem = new StackItem() { isFloat = Utilities.IsFloat(retType), sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes, isGCManaged = retTypeInfo.IsGCManaged, isValue = retTypeInfo.IsValueType }; int bytesToAdd = 0; List<Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList(); if (!methodToCall.IsStatic) { allParams.Insert(0, methodToCall.DeclaringType); } foreach (Type aParam in allParams) { conversionState.CurrentStackFrame.Stack.Pop(); bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes; } if (bytesToAdd > 0) { if (returnItem.sizeOnStackInBytes != 0) { conversionState.CurrentStackFrame.Stack.Push(returnItem); } } else if (returnItem.sizeOnStackInBytes != 0) { conversionState.CurrentStackFrame.Stack.Push(returnItem); } } else if (methodToCall is ConstructorInfo) { ConstructorInfo aConstructor = (ConstructorInfo)methodToCall; if (aConstructor.IsStatic) { //Static constructors do not have parameters or return values } else { ParameterInfo[] allParams = methodToCall.GetParameters(); foreach (ParameterInfo aParam in allParams) { conversionState.CurrentStackFrame.Stack.Pop(); } } } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { Int16 index = 0; switch ((OpCodes)theOp.opCode.Value) { case OpCodes.Ldarg: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldarg_0: index = 0; break; case OpCodes.Ldarg_1: index = 1; break; case OpCodes.Ldarg_2: index = 2; break; case OpCodes.Ldarg_3: index = 3; break; case OpCodes.Ldarg_S: index = (Int16)theOp.ValueBytes[0]; break; case OpCodes.Ldarga: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldarga_S: index = (Int16)theOp.ValueBytes[0]; break; } if ((OpCodes)theOp.opCode.Value == OpCodes.Ldarga || (OpCodes)theOp.opCode.Value == OpCodes.Ldarga_S) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = 4, isFloat = false, isGCManaged = false, isValue = false }); } else { Types.VariableInfo argInfo = conversionState.Input.TheMethodInfo.ArgumentInfos[index]; Types.TypeInfo paramTypeInfo = argInfo.TheTypeInfo; int bytesForArg = paramTypeInfo.SizeOnStackInBytes; conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = bytesForArg, isFloat = false, isGCManaged = paramTypeInfo.IsGCManaged, isValue = paramTypeInfo.IsValueType }); } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { Type retType = (conversionState.Input.TheMethodInfo.IsConstructor ? typeof(void) : ((MethodInfo)conversionState.Input.TheMethodInfo.UnderlyingInfo).ReturnType); Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType); if (retTypeInfo.SizeOnStackInBytes != 0) { conversionState.CurrentStackFrame.Stack.Pop(); } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown when the return value is a float or the size on the stack /// in bytes is not 4 or 8 bytes. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Store the return value //Get the return type Type retType = (conversionState.Input.TheMethodInfo.IsConstructor ? typeof(void) : ((MethodInfo)conversionState.Input.TheMethodInfo.UnderlyingInfo).ReturnType); Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType); //Get the size of the return type on stack int retSize = retTypeInfo.SizeOnStackInBytes; //If the size isn't 0 (i.e. isn't "void" which has no return value) if (retSize != 0) { //Pop the return value off our stack StackItem retItem = conversionState.CurrentStackFrame.Stack.Pop(); //If it is float, well, we don't support it yet... if (retItem.isFloat) { //SUPPORT - floats throw new NotSupportedException("Floats return type not supported yet!"); } //Otherwise, store the return value at [ebp+8] //[ebp+8] because that is last "argument" // - read the calling convention spec else { for(int i = 0; i < retSize; i += 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Dest = "[EBP+" + (i + 8) + "]", Src = "EAX" }); } } } //Once return value is off the stack, remove the locals //Deallocate stack space for locals //Only bother if there are any locals if (conversionState.Input.TheMethodInfo.LocalInfos.Count > 0) { //Get the total size of all locals int totalBytes = 0; foreach (Types.VariableInfo aLocal in conversionState.Input.TheMethodInfo.LocalInfos) { totalBytes += aLocal.TheTypeInfo.SizeOnStackInBytes; } //Move esp past the locals conversionState.Append(new ASMOps.Add() { Src = totalBytes.ToString(), Dest = "ESP" }); } //Restore ebp to previous method's ebp conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EBP" }); //This pop also takes last value off the stack which //means top item is the return address //So ret command can now be correctly executed. }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// If either value is < 4 bytes in length or /// operands are not of the same size. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Pop item to negate StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop(); if(itemA.isFloat) { //SUPPORT - floats throw new NotSupportedException("Negate float vals not suppported yet!"); } // Two's Complement negation // - "Not" value then add 1 if(itemA.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); conversionState.Append(new ASMOps.Neg() { Arg = "EAX" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EAX" }); } else if (itemA.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EDX" }); // Not the value conversionState.Append(new ASMOps.Not() { Dest = "EAX" }); conversionState.Append(new ASMOps.Not() { Dest = "EDX" }); // Then add 1 conversionState.Append(new ASMOps.Mov() { Src = "1", Dest = "EBX", Size = ASMOps.OperandSize.Dword }); conversionState.Append(new ASMOps.Mov() { Src = "0", Dest = "ECX", Size = ASMOps.OperandSize.Dword }); //Add ecx:ebx to edx:eax //Add low bits conversionState.Append(new ASMOps.Add() { Src = "EBX", Dest = "EAX" }); //Add high bits including any carry from //when low bits were added conversionState.Append(new ASMOps.Add() { Src = "ECX", Dest = "EDX", WithCarry = true }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EDX" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EAX" }); } else { throw new NotSupportedException("Stack item size not supported by neg op!"); } conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = itemA.isFloat, sizeOnStackInBytes = itemA.sizeOnStackInBytes, isGCManaged = itemA.isGCManaged, isValue = itemA.isValue }); }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown if the value to store is floating point. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0); FieldInfo theField = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken); Types.FieldInfo theFieldInfo = conversionState.GetFieldInfo(theField.DeclaringType, theField.Name); Types.TypeInfo theFieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theFieldInfo.FieldType); string fieldId = theFieldInfo.ID; int size = /*theFieldTypeInfo.IsValueType ? theFieldTypeInfo.SizeOnHeapInBytes : */theFieldTypeInfo.SizeOnStackInBytes; bool isFloat = Utilities.IsFloat(theField.FieldType); conversionState.AddExternalLabel(fieldId); StackItem value = conversionState.CurrentStackFrame.Stack.Pop(); if (isFloat) { //SUPPORT - floats throw new NotSupportedException("Storing static fields of type float not supported yet!"); } conversionState.Append(new ASMOps.La() { Dest = "$t4", Label = fieldId }); if (size == 1) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Byte, Src = "$t1", Dest = "0($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory }); } else if (size == 2) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Halfword, Src = "$t1", Dest = "0($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory }); } else if (size == 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "0($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory }); } else if (size == 8) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "0($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory }); conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "4($t4)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory }); } else { throw new ArgumentOutOfRangeException("Storing static field that has stack size greater than 8 not supported!"); } if (value.sizeOnStackInBytes - size > 0) { conversionState.Append(new ASMOps.Add() { Src1 = "$sp", Src2 = (value.sizeOnStackInBytes - size).ToString(), Dest = "$sp" }); } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> public override void Convert(ILConversionState conversionState, ILOp theOp) { if (theOp.IsDebugOp) { conversionState.Append(new ASMOps.Int() { IntNum = "3" }); } else { conversionState.Append(new ASMOps.Nop()); } }
/// <summary> /// Gets the position (index) of the specified IL op. /// </summary> /// <param name="anOp">The op to get the position of.</param> /// <returns>The position.</returns> public int PositionOf(ILOp anOp) { return(ILOps.IndexOf(anOp)); }
/// <summary> /// Gets the position (index) of the specified IL op. /// </summary> /// <param name="anOp">The op to get the position of.</param> /// <returns>The position.</returns> public int PositionOf(ILOp anOp) { return(Input.PositionOf(anOp)); }
/// <summary> /// Performs only the op's stack operations on the specified conversion state. /// </summary> /// <param name="conversionState">The conversion state to perform stack operations on.</param> /// <param name="theOp">The op being processed.</param> public virtual void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { }
/// <summary> /// Preprocesses the specified IL op. /// </summary> /// <param name="preprocessState">The preprocessor state to perform preprocessing on.</param> /// <param name="theOp">The op being processed.</param> public virtual void Preprocess(ILPreprocessState preprocessState, ILOp theOp) { }
/// <summary> /// Converts the op using the specified conversion state. /// </summary> /// <param name="conversionState">The current conversion state.</param> /// <param name="theOp">The op to convert.</param> public virtual void Convert(ILConversionState conversionState, ILOp theOp) { }
/// <summary> /// Scans the specified non-plugged IL block. /// </summary> /// <param name="TheLibrary">The library currently being compiled.</param> /// <param name="theMethodInfo">The method which generated the IL block.</param> /// <param name="theILBlock">The IL block to scan.</param> /// <returns>CompileResult.OK.</returns> private static CompileResult ScanNonpluggedILBlock(ILLibrary TheLibrary, Types.MethodInfo theMethodInfo, ILBlock theILBlock) { CompileResult result = CompileResult.OK; ASM.ASMBlock TheASMBlock = new ASM.ASMBlock() { OriginMethodInfo = theMethodInfo, Priority = theMethodInfo.Priority }; ILConversionState convState = new ILConversionState() { TheILLibrary = TheLibrary, CurrentStackFrame = new StackFrame(), Input = theILBlock, Result = TheASMBlock }; foreach (ILOp anOp in theILBlock.ILOps) { try { string commentText = TheASMBlock.GenerateILOpLabel(convState.PositionOf(anOp), "") + " -- " + anOp.opCode.ToString() + " -- Offset: " + anOp.Offset.ToString("X2"); ASM.ASMOp newCommentOp = TargetArchitecture.CreateASMOp(ASM.OpCodes.Comment, commentText); TheASMBlock.ASMOps.Add(newCommentOp); int currCount = TheASMBlock.ASMOps.Count; if (anOp is ILOps.MethodStart) { TargetArchitecture.MethodStartOp.Convert(convState, anOp); } else if (anOp is ILOps.MethodEnd) { TargetArchitecture.MethodEndOp.Convert(convState, anOp); } else if (anOp is ILOps.StackSwitch) { TargetArchitecture.StackSwitchOp.Convert(convState, anOp); } else { ILOp ConverterOp = TargetArchitecture.TargetILOps[(ILOp.OpCodes)anOp.opCode.Value]; ConverterOp.Convert(convState, anOp); } if (anOp.LabelRequired) { if (currCount < TheASMBlock.ASMOps.Count) { TheASMBlock.ASMOps[currCount].ILLabelPosition = convState.PositionOf(anOp); TheASMBlock.ASMOps[currCount].RequiresILLabel = true; } } } catch (KeyNotFoundException) { result = CompileResult.PartialFailure; Logger.LogError(Errors.ILCompiler_ScanILOpFailure_ErrorCode, theMethodInfo.ToString(), anOp.Offset, string.Format(Errors.ErrorMessages[Errors.ILCompiler_ScanILOpFailure_ErrorCode], "Conversion IL op not found: " + Enum.GetName(typeof(ILOp.OpCodes), anOp.opCode.Value) + ".")); } catch (InvalidOperationException) { result = CompileResult.PartialFailure; Logger.LogError(Errors.ILCompiler_ScanILOpFailure_ErrorCode, theMethodInfo.ToString(), anOp.Offset, string.Format(Errors.ErrorMessages[Errors.ILCompiler_ScanILOpFailure_ErrorCode], Enum.GetName(typeof(ILOp.OpCodes), anOp.opCode.Value))); } catch (NotSupportedException ex) { result = CompileResult.PartialFailure; Logger.LogError(Errors.ILCompiler_ScanILOpFailure_ErrorCode, theMethodInfo.ToString(), anOp.Offset, string.Format(Errors.ErrorMessages[Errors.ILCompiler_ScanILOpFailure_ErrorCode], "An IL op reported something as not supported. " + Enum.GetName(typeof(ILOp.OpCodes), anOp.opCode.Value) + ". " + ex.Message)); } catch (Exception ex) { result = CompileResult.Fail; Logger.LogError(Errors.ILCompiler_ScanILOpFailure_ErrorCode, theMethodInfo.ToString(), anOp.Offset, string.Format(Errors.ErrorMessages[Errors.ILCompiler_ScanILOpFailure_ErrorCode], ex.Message)); } } TheLibrary.TheASMLibrary.ASMBlocks.Add(TheASMBlock); return(result); }