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 }); }
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(); } } } }
/// <summary> /// Reads a plugged method. /// </summary> /// <param name="aMethodInfo">The method to read.</param> /// <returns>The new IL block for the method.</returns> public static ILBlock ReadPlugged(Types.MethodInfo aMethodInfo) { string PlugPath = aMethodInfo.PlugAttribute.ASMFilePath; return(new ILBlock() { PlugPath = string.IsNullOrWhiteSpace(PlugPath) ? " " : PlugPath, TheMethodInfo = aMethodInfo }); }
/// <summary> /// Reads the specified method. /// </summary> /// <param name="aMethodInfo">The method to read.</param> /// <returns>The new IL block for the method.</returns> public static ILBlock Read(Types.MethodInfo aMethodInfo) { if (aMethodInfo.IsPlugged) { return(ReadPlugged(aMethodInfo)); } else { return(ReadNonPlugged(aMethodInfo)); } }
/// <summary> /// Scans the specified 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 ScanPluggedILBlock(ILLibrary TheLibrary, Types.MethodInfo theMethodInfo, ILBlock theILBlock) { TheLibrary.TheASMLibrary.ASMBlocks.Add(new ASM.ASMBlock() { PlugPath = theILBlock.PlugPath, OriginMethodInfo = theMethodInfo, Priority = theMethodInfo.Priority }); return(CompileResult.OK); }
/// <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) { //Get the ID (i.e. ASM label) of the method to load a pointer to Types.MethodInfo methodInfo = conversionState.TheILLibrary.GetMethodInfo(theOp.MethodToCall); string methodID = methodInfo.ID; bool addExternalLabel = methodID != conversionState.Input.TheMethodInfo.ID; //If we want to load the pointer at a specified IL op number: if (theOp.LoadAtILOpAfterOp != null) { ILBlock anILBlock = conversionState.TheILLibrary.GetILBlock(methodInfo); int index = anILBlock.ILOps.IndexOf(theOp.LoadAtILOpAfterOp); if (index == -1) { throw new NullReferenceException("LoadAtILOpAfterOp not found in IL block!"); } index++; methodID = ASM.ASMBlock.GenerateLabel(methodID, anILBlock.PositionOf(anILBlock.ILOps[index])); } else if (theOp.LoadAtILOffset != int.MaxValue) { //Append the IL sub-label to the ID ILBlock anILBlock = conversionState.TheILLibrary.GetILBlock(methodInfo); methodID = ASM.ASMBlock.GenerateLabel(methodID, anILBlock.PositionOf(anILBlock.At(theOp.LoadAtILOffset))); //Note: This is used by try/catch/finally blocks for pushing pointers // to catch/finally handlers and filters } if (addExternalLabel) { conversionState.AddExternalLabel(methodID); } //Push the pointer to the function conversionState.Append(new ASMOps.La() { Dest = "$t4", Label = methodID }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t4" }); conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false }); }
public override void Preprocess(ILPreprocessState preprocessState, ILOp theOp) { Types.MethodInfo methodInfo = preprocessState.TheILLibrary.GetMethodInfo(theOp.MethodToCall); if (theOp.LoadAtILOpAfterOp != null) { ILBlock anILBlock = preprocessState.TheILLibrary.GetILBlock(methodInfo); int index = anILBlock.ILOps.IndexOf(theOp.LoadAtILOpAfterOp); index++; anILBlock.ILOps[index].LabelRequired = true; } else if (theOp.LoadAtILOffset != int.MaxValue) { int offset = theOp.LoadAtILOffset; ILOp theLoadedOp = preprocessState.TheILLibrary.GetILBlock(methodInfo).At(offset); theLoadedOp.LabelRequired = true; } }
/// <summary> /// Gets the IL block for the specified method. /// </summary> /// <param name="theInfo">The method to get the IL block of.</param> /// <param name="checkDepLibs">Whether to check dependencies or not.</param> /// <returns>The IL block or null if none found.</returns> public ILBlock GetILBlock(Types.MethodInfo theInfo, bool checkDepLibs = true) { if (ILBlocks.ContainsKey(theInfo)) { return(ILBlocks[theInfo]); } if (checkDepLibs) { foreach (ILLibrary depLib in Dependencies) { ILBlock result = depLib.GetILBlock(theInfo); if (result != null) { return(result); } } } return(null); }
/// <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) { StackItem theItem = conversionState.CurrentStackFrame.Stack.Pop(); if (theItem.isNewGCObject) { //Decrement ref count //Get the ID of method to call as it will be labeled in the output ASM. Types.MethodInfo anInfo = conversionState.GetDecrementRefCountMethodInfo(); string methodID = anInfo.ID; conversionState.AddExternalLabel(anInfo.ID); //Append the actual call conversionState.Append(new ASMOps.Call() { Target = methodID }); } conversionState.Append(new ASMOps.Add() { Src = theItem.sizeOnStackInBytes.ToString(), Dest = "ESP" }); }
/// <summary> /// Gets the method info for the specified method. /// </summary> /// <param name="theMethod">The method to get method info for.</param> /// <returns>The method info or null if not found.</returns> public Types.MethodInfo GetMethodInfo(MethodBase theMethod) { foreach (Types.TypeInfo aTypeInfo in TypeInfos) { foreach (Types.MethodInfo aMethodInfo in aTypeInfo.MethodInfos) { if (aMethodInfo.UnderlyingInfo.Equals(theMethod)) { return(aMethodInfo); } } } foreach (ILLibrary depLib in Dependencies) { Types.MethodInfo result = depLib.GetMethodInfo(theMethod); if (result != null) { return(result); } } return(null); }
/// <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) { MethodBase constructorMethod = theOp.MethodToCall; Type objectType = constructorMethod.DeclaringType; //New obj must: // - Ignore for creation of Delegates // - Allocate memory on the heap for the object // - If no memory is left, throw a panic attack because we're out of memory... // - Call the specified constructor if (typeof(Delegate).IsAssignableFrom(objectType)) { conversionState.Append(new ASMOps.Comment("Ignore newobj calls for Delegates")); //Still need to: // - Remove the "object" param but preserve the "function pointer" StackItem funcPtrItem = conversionState.CurrentStackFrame.Stack.Pop();; conversionState.CurrentStackFrame.Stack.Pop(); conversionState.CurrentStackFrame.Stack.Push(funcPtrItem); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "4($sp)", MoveType = ASMOps.Mov.MoveTypes.SrcRegToDestMemory }); conversionState.Append(new ASMOps.Add() { Src1 = "$sp", Src2 = "4", Dest = "$sp" }); return; } Types.MethodInfo constructorMethodInfo = conversionState.TheILLibrary.GetMethodInfo(constructorMethod); conversionState.AddExternalLabel(conversionState.GetNewObjMethodInfo().ID); conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID); conversionState.AddExternalLabel(constructorMethodInfo.ID); int currOpPosition = conversionState.PositionOf(theOp); //Attempt to allocate memory on the heap for the new object //This involves: // - Pushing the type reference onto the stack // - Calling GC NewObj method // - Check the pointer == 0, if so, out of memory //Push type reference string typeIdStr = conversionState.TheILLibrary.GetTypeInfo(objectType).ID; conversionState.AddExternalLabel(typeIdStr); conversionState.Append(new ASMOps.La() { Dest = "$t4", Label = typeIdStr }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t4" }); //Push a word for return value (i.e. new object pointer) conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$zero" }); //Get the GC.NewObj method ID (i.e. ASM label) string methodLabel = conversionState.GetNewObjMethodInfo().ID; //Call GC.NewObj conversionState.Append(new ASMOps.Call() { Target = methodLabel }); //Pop the return value (i.e. new object pointer) conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); //Remove arg 0 from stack conversionState.Append(new ASMOps.Add() { Src1 = "$sp", Src2 = "4", Dest = "$sp" }); //Check if pointer == 0? //If it isn't 0, not out of memory so continue execution conversionState.Append(new ASMOps.Branch() { BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t0", DestILPosition = currOpPosition, Extension = "NotNullMem" }); //If we are out of memory, we have a massive problem //Because it means we don't have space to create a new exception object //So ultimately we just have to throw a kernel panic //Throw a panic attack... ( :/ ) by calling kernel Halt(uint lastAddress) //result.AppendLine("call GetEIP"); //result.AppendLine("push dword esp"); //result.AppendLine("push dword ebp"); //result.AppendLine("pushad"); //result.AppendLine("mov dword eax, 0xDEADBEEF"); //result.AppendLine("mov dword ebx, 0x1"); //result.AppendLine("mov dword ecx, 1"); //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_GC_Enabled], 1"); //result.AppendLine("mov dword [staticfield_System_Boolean_Kernel_FOS_System_Heap_PreventAllocation], 0"); //result.AppendLine("jmp method_System_Void_RETEND_Kernel_PreReqs_DECLEND_PageFaultDetection_NAMEEND___Fail"); conversionState.Append(new ASMOps.Call() { Target = "GetEIP" }); conversionState.AddExternalLabel("GetEIP"); conversionState.Append(new ASMOps.Call() { Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID }); //Insert the not null label conversionState.Append(new ASMOps.Label() { ILPosition = currOpPosition, Extension = "NotNullMem" }); //Call the specified constructor //This involves: // - Push empty dword onto stack // - Move all args down by one dword // - Move object reference into dword as first arg // - Call constructor conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$zero" }); int sizeOfArgs = 0; ParameterInfo[] allParams = constructorMethod.GetParameters(); foreach (ParameterInfo aParam in allParams) { sizeOfArgs += conversionState.TheILLibrary.GetTypeInfo(aParam.ParameterType).SizeOnStackInBytes; conversionState.CurrentStackFrame.Stack.Pop(); } conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$sp", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.RegToReg }); if (sizeOfArgs > 0) { if (sizeOfArgs % 4 != 0) { throw new InvalidOperationException("sizeOfArgs not exact multiple of 4!"); } conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = (sizeOfArgs / 4).ToString(), Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg }); conversionState.Append(new ASMOps.Label() { ILPosition = currOpPosition, Extension = "ShiftArgsLoop" }); //Decrement counter ($t2) conversionState.Append(new ASMOps.Sub() { Src1 = "$t2", Src2 = "1", Dest = "$t2" }); //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t1)", Dest = "$t3" }); GlobalMethods.LoadData(conversionState, theOp, "$t1", "$t3", 4, 4); //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t3", Dest = "0($t1)" }); GlobalMethods.StoreData(conversionState, theOp, "$t1", "$t3", 0, 4); conversionState.Append(new ASMOps.Add() { Src1 = "$t1", Src2 = "4", Dest = "$t1" }); conversionState.Append(new ASMOps.Branch() { BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t2", DestILPosition = currOpPosition, Extension = "ShiftArgsLoop" }); } //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t0", Dest = "0($t1)" }); GlobalMethods.StoreData(conversionState, theOp, "$t1", "$t0", 0, 4); conversionState.Append(new ASMOps.Call() { Target = constructorMethodInfo.ID }); //Only remove args from stack - we want the object pointer to remain on the stack conversionState.Append(new ASMOps.Add() { Src1 = "$sp", Src2 = sizeOfArgs.ToString(), Dest = "$sp" }); conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isNewGCObject = true, isGCManaged = true }); }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { MethodBase methodToCall = theOp.MethodToCall; Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall); if (methodToCall is MethodInfo) { if (typeof(Delegate).IsAssignableFrom(((MethodInfo)methodToCall).DeclaringType)) { List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList(); 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 = 4; foreach (Type aParam in allParams) { conversionState.CurrentStackFrame.Stack.Pop(); bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes; } if (returnItem.sizeOnStackInBytes != 0) { conversionState.CurrentStackFrame.Stack.Push(returnItem); } } else { string methodIDValueWanted = methodToCallInfo.IDValue.ToString(); int currOpPosition = conversionState.PositionOf(theOp); Types.TypeInfo declaringTypeInfo = conversionState.TheILLibrary.GetTypeInfo(methodToCall.DeclaringType); 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); } } } }
/// <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 any argument or the return value is a floating point number. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { MethodBase methodToCall = theOp.MethodToCall; Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall); conversionState.AddExternalLabel(conversionState.GetThrowNullReferenceExceptionMethodInfo().ID); conversionState.AddExternalLabel(conversionState.GetThrowIndexOutOfRangeExceptionMethodInfo().ID); //The method to call is a method base //A method base can be either a method info i.e. a normal method //or a constructor method. The two types are treated separately. if (methodToCall is MethodInfo) { //Need to do callvirt related stuff to load address of method to call // - Check for invoke of a delegate - if so, treat rather differently from normal callvirt if (typeof(Delegate).IsAssignableFrom(((MethodInfo)methodToCall).DeclaringType)) { //Callvirt to delegate method // - We only support calls to Invoke at the moment if (methodToCall.Name != "Invoke") { throw new NotSupportedException("Callvirt to Delegate method not supported! Method name: " + methodToCall.Name); } int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => conversionState.TheILLibrary.GetTypeInfo(x.ParameterType).SizeOnStackInBytes).Sum(); // - Move into $t0 address of function to call from stack - delegate reference is function pointer //All the parameters for the method that was called List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList(); int bytesForParams = allParams.Select(x => conversionState.TheILLibrary.GetTypeInfo(x).SizeOnStackInBytes).Sum(); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = bytesForParams + "($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); //Allocate space on the stack for the return value as necessary 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 }; //We do not push the return value onto the stack unless it has size > 0 //We do not push the return value onto our stack at this point - it is pushed after the call is done if (returnItem.sizeOnStackInBytes != 0) { if (returnItem.isFloat) { //SUPPORT - floats throw new NotSupportedException("Cannot handle float return values!"); } else if (returnItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$zero" }); } else if (returnItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$zero" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$zero" }); } else { throw new NotSupportedException("Invalid return stack operand size!"); } } //Append the actual call conversionState.Append(new ASMOps.Call() { Target = "$t0" }); //After a call, we need to remove the return value and parameters from the stack //This is most easily done by just adding the total number of bytes for params and //return value to the stack pointer ($sp register). //Stores the number of bytes to add // - Initially at least 4 for the delegate (method) ref/pointer int bytesToAdd = 4; //Go through all params that must be removed foreach (Type aParam in allParams) { //Pop the paramter off our stack //(Note: Return value was never pushed onto our stack. See above) conversionState.CurrentStackFrame.Stack.Pop(); //Add the size of the paramter to the total number of bytes to pop bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes; } //If there is a return value on the stack if (returnItem.sizeOnStackInBytes != 0) { //We need to store the return value then pop all the params //We now push the return value onto our stack as, //after all is said and done below, it will be the //top item on the stack conversionState.CurrentStackFrame.Stack.Push(returnItem); //SUPPORT - floats (with above) //Pop the return value into the $t0 register //We will push it back on after params are skipped over. if (returnItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); } else if (returnItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t3" }); } } //Skip over the params conversionState.Append(new ASMOps.Add() { Src1 = "$sp", Src2 = bytesToAdd.ToString(), Dest = "$sp" }); //If necessary, push the return value onto the stack. if (returnItem.sizeOnStackInBytes != 0) { //SUPPORT - floats (with above) //The return value was stored in $t0 //So push it back onto the stack if (returnItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t0" }); } else if (returnItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t3" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t0" }); } } } else { //Normal callvirt // - Get object ref from loaded args // - Check object ref not null // - Get type table entry from object ref // - Get method table from type table entry // - Scan method table for the method we want // - If found, load method address // - Else, check for parent type method table // - If no parent type method table, throw exception // - Else, scan parent type method table string methodIDValueWanted = methodToCallInfo.IDValue.ToString(); int currOpPosition = conversionState.PositionOf(theOp); Types.TypeInfo declaringTypeInfo = conversionState.TheILLibrary.GetTypeInfo(methodToCall.DeclaringType); //DB_Type declaringDBType = DebugDatabase.GetType(conversionState.GetTypeID(methodToCall.DeclaringType)); //Get object ref int bytesForAllParams = ((MethodInfo)methodToCall).GetParameters().Select(x => conversionState.TheILLibrary.GetTypeInfo(x.ParameterType).SizeOnStackInBytes).Sum(); conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = bytesForAllParams + "($sp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); //Check object ref conversionState.Append(new ASMOps.Branch() { BranchType = ASMOps.BranchOp.BranchNotZero, Src1 = "$t0", Src2 = "$zero", DestILPosition = currOpPosition, Extension = "NotNull" }); conversionState.Append(new ASMOps.Call() { Target = "GetEIP" }); conversionState.AddExternalLabel("GetEIP"); conversionState.Append(new ASMOps.Call() { Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID }); conversionState.Append(new ASMOps.Label() { ILPosition = currOpPosition, Extension = "NotNull" }); //Get type ref int typeOffset = conversionState.TheILLibrary.GetFieldInfo(declaringTypeInfo, "_Type").OffsetInBytes; //conversionState.Append(new ASMOps.La() { Dest = "$t1", Label = "type_Testing1_String" }); //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = typeOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", typeOffset, 4); //Get method table ref int methodTablePtrOffset = conversionState.GetTypeFieldOffset("MethodTablePtr"); //conversionState.Append(new ASMOps.La() { Dest = "$t0", Label = "type_Testing1_String_MethodTable" }); //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = methodTablePtrOffset.ToString() + "($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", methodTablePtrOffset, 4); //Loop through entries conversionState.Append(new ASMOps.Label() { ILPosition = currOpPosition, Extension = "LoopMethodTable" }); //Load ID Val for current entry //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "0($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 0, 4); //Compare to wanted ID value conversionState.Append(new ASMOps.Mov() { Src = methodIDValueWanted, Dest = "$t4", MoveType = ASMOps.Mov.MoveTypes.ImmediateToReg }); //If equal, load method address into $t0 conversionState.Append(new ASMOps.Branch() { BranchType = ASMOps.BranchOp.BranchNotEqual, Src1 = "$t1", Src2 = "$t4", DestILPosition = currOpPosition, Extension = "NotEqual" }); //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t0)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t0", 4, 4); conversionState.Append(new ASMOps.Branch() { BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "Call" }); conversionState.Append(new ASMOps.Label() { ILPosition = currOpPosition, Extension = "NotEqual" }); //Else, compare to 0 to check for end of table conversionState.Append(new ASMOps.Branch() { BranchType = ASMOps.BranchOp.BranchZero, Src1 = "$t1", DestILPosition = currOpPosition, Extension = "EndOfTable" }); //Not 0? Move to next entry then loop again conversionState.Append(new ASMOps.Add() { Src1 = "$t0", Src2 = "8", Dest = "$t0" }); conversionState.Append(new ASMOps.Branch() { BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "LoopMethodTable" }); conversionState.Append(new ASMOps.Label() { ILPosition = currOpPosition, Extension = "EndOfTable" }); //Compare address value to 0 //If not zero, there is a parent method table to check //conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "4($t0)", Dest = "$t1", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); GlobalMethods.LoadData(conversionState, theOp, "$t0", "$t1", 4, 4); conversionState.Append(new ASMOps.Branch() { BranchType = ASMOps.BranchOp.BranchZero, Src1 = "$t1", DestILPosition = currOpPosition, Extension = "NotFound" }); //Load parent method table and loop conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$t1", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.RegToReg }); conversionState.Append(new ASMOps.Branch() { BranchType = ASMOps.BranchOp.Branch, DestILPosition = currOpPosition, Extension = "LoopMethodTable" }); conversionState.Append(new ASMOps.Label() { ILPosition = currOpPosition, Extension = "NotFound" }); //Throw exception! conversionState.Append(new ASMOps.Call() { Target = "GetEIP" }); conversionState.AddExternalLabel("GetEIP"); conversionState.Append(new ASMOps.Call() { Target = conversionState.GetThrowNullReferenceExceptionMethodInfo().ID }); conversionState.Append(new ASMOps.Label() { ILPosition = currOpPosition, Extension = "Call" }); //Allocate space on the stack for the return value as necessary 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 }; //We do not push the return value onto the stack unless it has size > 0 //We do not push the return value onto our stack at this point - it is pushed after the call is done if (returnItem.sizeOnStackInBytes != 0) { if (returnItem.isFloat) { //SUPPORT - floats throw new NotSupportedException("Cannot handle float return values!"); } else if (returnItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$zero" }); } else if (returnItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$zero" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$zero" }); } else { throw new NotSupportedException("Invalid return stack operand size!"); } } //Append the actual call conversionState.Append(new ASMOps.Call() { Target = "$t0" }); //After a call, we need to remove the return value and parameters from the stack //This is most easily done by just adding the total number of bytes for params and //return value to the stack pointer ($sp register). //Stores the number of bytes to add int bytesToAdd = 0; //All the parameters for the method that was called List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList(); //Go through each one if (!methodToCall.IsStatic) { allParams.Insert(0, methodToCall.DeclaringType); } foreach (Type aParam in allParams) { //Pop the parameter off our stack //(Note: Return value was never pushed onto our stack. See above) conversionState.CurrentStackFrame.Stack.Pop(); //Add the size of the parameter to the total number of bytes to pop bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes; } //If the number of bytes to add to skip over params is > 0 if (bytesToAdd > 0) { //If there is a return value on the stack if (returnItem.sizeOnStackInBytes != 0) { //We need to store the return value then pop all the params //We now push the return value onto our stack as, //after all is said and done below, it will be the //top item on the stack conversionState.CurrentStackFrame.Stack.Push(returnItem); //SUPPORT - floats (with above) //Pop the return value into the $t0 register //We will push it back on after params are skipped over. if (returnItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); } else if (returnItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t0" }); conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Word, Dest = "$t3" }); } } //Skip over the params conversionState.Append(new ASMOps.Add() { Src1 = "$sp", Src2 = bytesToAdd.ToString(), Dest = "$sp" }); //If necessary, push the return value onto the stack. if (returnItem.sizeOnStackInBytes != 0) { //SUPPORT - floats (with above) //The return value was stored in $t0 //So push it back onto the stack if (returnItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t0" }); } else if (returnItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t3" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t0" }); } } } //No params to skip over but we might still need to store return value else if (returnItem.sizeOnStackInBytes != 0) { //The return value will be the top item on the stack. //So all we need to do is push the return item onto our stack. conversionState.CurrentStackFrame.Stack.Push(returnItem); } } } else if (methodToCall is ConstructorInfo) { throw new NotSupportedException("How the hell are we getting callvirts to constructor methods?!"); } }
/// <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 any argument or the return value is a floating point number. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { MethodBase methodToCall = theOp.MethodToCall; Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall); conversionState.AddExternalLabel(methodToCallInfo.ID); //The method to call is a method base //A method base can be either a method info i.e. a normal method //or a constructor method. The two types are treated separately. if (methodToCall is MethodInfo) { //Allocate space on the stack for the return value as necessary 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 }; //We do not push the return value onto the stack unless it has size > 0 //We do not push the return value onto our stack at this point - it is pushed after the call is done if (returnItem.sizeOnStackInBytes != 0) { if (returnItem.isFloat) { //SUPPORT - floats throw new NotSupportedException("Cannot handle float return values!"); } else if (returnItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "0" }); } else if (returnItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "0" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "0" }); } else { throw new NotSupportedException("Invalid return stack operand size!"); } } //Append the actual call conversionState.Append(new ASMOps.Call() { Target = methodToCallInfo.ID }); //After a call, we need to remove the return value and parameters from the stack //This is most easily done by just adding the total number of bytes for params and //return value to the stack pointer (ESP register). //Stores the number of bytes to add int bytesToAdd = 0; //All the parameters for the method that was called List <Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList(); //Go through each one if (!methodToCall.IsStatic) { allParams.Insert(0, methodToCall.DeclaringType); } foreach (Type aParam in allParams) { //Pop the paramter off our stack //(Note: Return value was never pushed onto our stack. See above) conversionState.CurrentStackFrame.Stack.Pop(); //Add the size of the paramter to the total number of bytes to pop bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes; } //If the number of bytes to add to skip over params is > 0 if (bytesToAdd > 0) { //If there is a return value on the stack if (returnItem.sizeOnStackInBytes != 0) { //We need to store the return value then pop all the params //We now push the return value onto our stack as, //after all is said and done below, it will be the //top item on the stack conversionState.CurrentStackFrame.Stack.Push(returnItem); //SUPPORT - floats (with above) //Pop the return value into the eax register //We will push it back on after params are skipped over. if (returnItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); } else if (returnItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EAX" }); conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "EDX" }); } } //Skip over the params conversionState.Append(new ASMOps.Add() { Src = bytesToAdd.ToString(), Dest = "ESP" }); //If necessary, push the return value onto the stack. if (returnItem.sizeOnStackInBytes != 0) { //SUPPORT - floats (with above) //The return value was stored in eax //So push it back onto the stack if (returnItem.sizeOnStackInBytes == 4) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EAX" }); } else if (returnItem.sizeOnStackInBytes == 8) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EDX" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EAX" }); } } } //No params to skip over but we might still need to store return value else if (returnItem.sizeOnStackInBytes != 0) { //The return value will be the top item on the stack. //So all we need to do is push the return item onto our stack. 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 //Append the actual call conversionState.Append(new ASMOps.Call() { Target = methodToCallInfo.ID }); } else { //Append the actual call conversionState.Append(new ASMOps.Call() { Target = methodToCallInfo.ID }); //After a call, we need to remove the parameters from the stack //This is most easily done by just adding the total number of bytes for params //to the stack pointer (ESP register). //Stores the number of bytes to add int bytesToAdd = 0; //All the parameters for the method that was called ParameterInfo[] allParams = methodToCall.GetParameters(); //Go through each one foreach (ParameterInfo aParam in allParams) { //Pop the paramter off our stack //(Note: Return value was never pushed onto our stack. See above) conversionState.CurrentStackFrame.Stack.Pop(); //Add the size of the paramter to the total number of bytes to pop bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam.ParameterType).SizeOnStackInBytes; } //Add 4 bytes for the instance ref bytesToAdd += 4; //If the number of bytes to add to skip over params is > 0 if (bytesToAdd > 0) { //Skip over the params conversionState.Append(new ASMOps.Add() { Src = bytesToAdd.ToString(), Dest = "ESP" }); } } } }
/// <summary> /// Reads a non-plugged method. /// </summary> /// <param name="aMethodInfo">The method to read.</param> /// <returns>The new IL block for the method.</returns> public static ILBlock ReadNonPlugged(Types.MethodInfo aMethodInfo) { ILBlock result = new ILBlock() { TheMethodInfo = aMethodInfo }; MethodBody methodBody = aMethodInfo.MethodBody; //Method body for something like [DelegateType].Invoke() is null. // So just return an empty method if that is this case. if (methodBody != null) { foreach (LocalVariableInfo aLocal in methodBody.LocalVariables) { aMethodInfo.LocalInfos.Add(new Types.VariableInfo() { UnderlyingType = aLocal.LocalType, Position = aLocal.LocalIndex }); } byte[] ILBytes = methodBody.GetILAsByteArray(); int ILBytesPos = 0; while (ILBytesPos < ILBytes.Length) { OpCode currOpCode; ushort currOpCodeID = 0; int currOpBytesSize = 0; if (ILBytes[ILBytesPos] == 0xFE) { currOpCodeID = (ushort)(0xFE00 + (short)ILBytes[ILBytesPos + 1]); currOpBytesSize += 2; } else { currOpCodeID = (ushort)ILBytes[ILBytesPos]; currOpBytesSize++; } currOpCode = AllOpCodes[currOpCodeID]; int operandSize = 0; switch (currOpCode.OperandType) { #region Operands case OperandType.InlineBrTarget: operandSize = 4; break; case OperandType.InlineField: operandSize = 4; break; case OperandType.InlineI: operandSize = 4; break; case OperandType.InlineI8: operandSize = 8; break; case OperandType.InlineMethod: operandSize = 4; break; case OperandType.InlineNone: //No operands = no op size break; case OperandType.InlineR: operandSize = 8; break; case OperandType.InlineSig: operandSize = 4; break; case OperandType.InlineString: operandSize = 4; break; case OperandType.InlineSwitch: { uint count = Utilities.ReadUInt32(ILBytes, ILBytesPos + currOpBytesSize); currOpBytesSize += 4; operandSize = (int)(count * 4); } break; case OperandType.InlineTok: operandSize = 4; break; case OperandType.InlineType: operandSize = 4; break; case OperandType.InlineVar: operandSize = 2; break; case OperandType.ShortInlineBrTarget: operandSize = 1; break; case OperandType.ShortInlineI: operandSize = 1; break; case OperandType.ShortInlineR: operandSize = 4; break; case OperandType.ShortInlineVar: operandSize = 1; break; default: throw new Exception("Unrecognised operand type!"); #endregion } MethodBase methodToCall = null; byte[] valueBytes = new byte[operandSize]; if (operandSize > 0) { Array.Copy(ILBytes, ILBytesPos + currOpBytesSize, valueBytes, 0, operandSize); if (currOpCode.Equals(OpCodes.Call) || currOpCode.Equals(OpCodes.Calli) || currOpCode.Equals(OpCodes.Callvirt) || currOpCode.Equals(OpCodes.Ldftn) || currOpCode.Equals(OpCodes.Newobj)) { int MethodMetadataToken = Utilities.ReadInt32(valueBytes, 0); methodToCall = aMethodInfo.UnderlyingInfo.Module.ResolveMethod(MethodMetadataToken); } } result.ILOps.Add(new ILOp() { opCode = currOpCode, Offset = ILBytesPos, BytesSize = currOpBytesSize + operandSize, ValueBytes = valueBytes, MethodToCall = methodToCall }); ILBytesPos += currOpBytesSize + operandSize; } foreach (ExceptionHandlingClause aClause in methodBody.ExceptionHandlingClauses) { ExceptionHandledBlock exBlock = result.GetExactExceptionHandledBlock(aClause.TryOffset); if (exBlock == null) { exBlock = new ExceptionHandledBlock(); exBlock.Offset = aClause.TryOffset; exBlock.Length = aClause.TryLength; result.ExceptionHandledBlocks.Add(exBlock); } switch (aClause.Flags) { case ExceptionHandlingClauseOptions.Fault: case ExceptionHandlingClauseOptions.Clause: { CatchBlock catchBlock = new CatchBlock() { Offset = aClause.HandlerOffset, Length = aClause.HandlerLength, //Though not used, we may as well set it anyway FilterType = aClause.CatchType }; exBlock.CatchBlocks.Add(catchBlock); } break; case ExceptionHandlingClauseOptions.Finally: { FinallyBlock finallyBlock = new FinallyBlock() { Offset = aClause.HandlerOffset, Length = aClause.HandlerLength }; exBlock.FinallyBlocks.Add(finallyBlock); } break; default: Logger.LogError("IL0010", "", 0, "Exception handling clause not supported! Type: " + aClause.Flags.ToString()); break; } } } return(result); }
/// <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); }