/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Add(v=vs.110).aspx * Description : Adds two values and pushes the result onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 2) { throw new Exception("Internal Compiler Error: vStack.Count < 2"); } var itemA = Optimizer.vStack.Pop(); var itemB = Optimizer.vStack.Pop(); var size = Math.Max(Helper.GetTypeSize(itemA.OperandType, Config.TargetPlatform), Helper.GetTypeSize(itemB.OperandType, Config.TargetPlatform)); /* The stack transitional behavior, in sequential order, is: * value1 is pushed onto the stack. * value2 is pushed onto the stack. * value2 and value1 are popped from the stack; value1 is added to value2. * The result is pushed onto the stack. */ switch (Config.TargetPlatform) { case Architecture.x86: { if (itemA.IsFloat || itemB.IsFloat || size > 4) { throw new Exception(string.Format("UnImplemented '{0}'", msIL)); } if (!itemA.SystemStack || !itemB.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; new Add { DestinationReg = Register.ESP, SourceReg = Register.EAX, DestinationIndirect = true }; Optimizer.vStack.Push(new StackItem(itemA.OperandType)); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Conv_I1(v=vs.110).aspx * Description : Converts the value on top of the evaluation stack to native int */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var item = Optimizer.vStack.Pop(); var size = Helper.GetTypeSize(item.OperandType, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * value is pushed onto the stack. * value is popped from the stack and the conversion operation is attempted. * If the conversion is successful, the resulting value is pushed onto the stack. */ switch (Config.TargetPlatform) { case Architecture.x86: { if (item.IsFloat || size > 4) { throw new Exception(string.Format("UnImplemented '{0}'", msIL)); } if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; new Movsx { DestinationReg = Register.EAX, SourceReg = Register.AL, Size = 8 }; new Push { DestinationReg = Register.EAX }; Optimizer.vStack.Push(new StackItem(typeof(int))); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Switch(v=vs.110).aspx * Description : Implements a jump table. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var branches = ((OpSwitch)xOp).Value; /* The stack transitional behavior, in sequential order, is: * A value is pushed onto the stack. * The value is popped off the stack and execution is transferred to the instruction at the offset indexed by the value, where the value is less than N. */ var item = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; for (int i = 0; i < branches.Length; i++) { new Cmp { DestinationReg = Register.EAX, SourceRef = "0x" + i.ToString("X") }; new Jmp { Condition = ConditionalJump.JE, DestinationRef = Helper.GetLabel(branches[i]) }; Optimizer.SaveStack(branches[i]); } Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Stelem_Ref(v=vs.110).aspx * Description : Replaces the array element at a given index with the object ref value (type O) on the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 3) { throw new Exception("Internal Compiler Error: vStack.Count < 3"); } /* The stack transitional behavior, in sequential order, is: * An object reference to an array, array, is pushed onto the stack. * An index value, index, to an element in array is pushed onto the stack. * A value of the type specified in the instruction is pushed onto the stack. * The value, the index, and the array reference are popped from the stack; the value is put into the array element at the given index. */ var itemA = Optimizer.vStack.Pop(); var itemB = Optimizer.vStack.Pop(); var itemC = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (!itemA.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } if (!itemB.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } if (!itemC.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } Stelem_il.Executex86(4); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } Optimizer.SaveStack(xOp.NextPosition); }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Dup(v=vs.110).aspx * Description : Copies the current topmost value on the evaluation stack, and then pushes the copy onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var item = Optimizer.vStack.Peek(); var size = Helper.GetTypeSize(item.OperandType, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * value is pushed onto the stack. * value is popped off of the stack for duplication. * value is pushed back onto the stack. * A duplicate value is pushed onto the stack. */ switch (Config.TargetPlatform) { case Architecture.x86: { if (size > 4) { throw new Exception(string.Format("UnImplemented '{0}'", msIL)); } if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Push { DestinationReg = Register.ESP, DestinationIndirect = true }; Optimizer.vStack.Push(new StackItem(item.OperandType)); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldelem_U4(v=vs.110).aspx * Description : Loads the element with type unsigned int32 at a specified array index onto the top of the evaluation stack as an int32. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 2) { throw new Exception("Internal Compiler Error: vStack.Count < 2"); } /* The stack transitional behavior, in sequential order, is: * An object reference array is pushed onto the stack. * An index value index is pushed onto the stack. * index and array are popped from the stack; the value stored at position index in array is looked up. * The value is pushed onto the stack. */ var itemA = Optimizer.vStack.Pop(); var itemB = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (!itemA.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } if (!itemB.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } Ldelem_il.Executex86(4, false); Optimizer.vStack.Push(new StackItem(typeof(uint))); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldlen(v=vs.110).aspx * Description : Pushes the number of elements of a zero-based, one-dimensional array onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } /* The stack transitional behavior, in sequential order, is: * An object reference to an array is pushed onto the stack. * The array reference is popped from the stack and the length is computed. * The length is pushed onto the stack. */ var item = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; new Push { DestinationReg = Register.EAX, DestinationDisplacement = 8, DestinationIndirect = true }; Optimizer.vStack.Push(new StackItem(typeof(uint))); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldflda(v=vs.110).aspx * Description : Finds the address of a field in the object whose reference is currently on the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var field = ((OpField)xOp).Value; var offset = Helper.GetFieldOffset(field.DeclaringType, field, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * An object reference (or pointer) is pushed onto the stack. * The object reference (or pointer) is popped from the stack; the address of the specified field in the object is found. * The address of the specified field is pushed onto the stack. */ var item = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Add { DestinationReg = Register.ESP, DestinationIndirect = true, SourceRef = "0x" + offset.ToString("X") }; } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } Optimizer.vStack.Push(new StackItem(typeof(uint))); Optimizer.SaveStack(xOp.NextPosition); }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Stind_R8(v=vs.110).aspx * Description : Stores a value of type float64 at a supplied address. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 2) { throw new Exception("Internal Compiler Error: vStack.Count < 2"); } /* The stack transitional behavior, in sequential order, is: * An address is pushed onto the stack. * A value is pushed onto the stack. * The value and the address are popped from the stack; the value is stored at the address. */ var itemA = Optimizer.vStack.Pop(); var itemB = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (!itemA.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } if (!itemB.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } Stind_I_il.Executex86(8); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } Optimizer.SaveStack(xOp.NextPosition); }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldnull(v=vs.110).aspx * Description : Pushes a null reference (type O) onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { /* The stack transitional behavior, in sequential order, is: * A null object reference is pushed onto the stack. */ switch (Config.TargetPlatform) { case Architecture.x86: { new Push { DestinationRef = "0x0" }; Optimizer.vStack.Push(new StackItem(typeof(uint))); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldloc(v=vs.110).aspx * Description : Loads the local variable at a specific index onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { var index = ((OpVar)xOp).Value; var body = method.GetMethodBody(); var EBPoffset = Helper.GetVariableOffset(body, index, Config.TargetPlatform); var varType = body.LocalVariables[index].LocalType; var size = Helper.GetTypeSize(varType, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * The local variable value at the specified index is pushed onto the stack. */ switch (Config.TargetPlatform) { case Architecture.x86: { if (size > 4) { throw new Exception("LocalVariable size > 4 not supported"); } new Push { DestinationReg = Register.EBP, DestinationIndirect = true, DestinationDisplacement = -EBPoffset }; } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } Optimizer.vStack.Push(new StackItem(varType)); Optimizer.SaveStack(xOp.NextPosition); }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Leave(v=vs.110).aspx * Description : Exits a protected region of code, unconditionally transferring control to a specific target instruction. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { var offset = ((OpBranch)xOp).Value; var xTrueLabel = Helper.GetLabel(offset); /* No evaluation stack behaviors are performed by this operation. */ switch (Config.TargetPlatform) { case Architecture.x86: { new Jmp { DestinationRef = xTrueLabel }; Optimizer.SaveStack(offset); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Sizeof(v=vs.110).aspx * Description : Pushes the size, in bytes, of a supplied value type onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { var type = ((OpType)xOp).Value; /* The stack transitional behavior, in sequential order, is: * The size (in bytes) of the supplied value type (valType) is pushed onto the stack. */ switch (Config.TargetPlatform) { case Architecture.x86: { new Push { DestinationRef = "0x" + Helper.GetTypeSize(type, Config.TargetPlatform).ToString("X") }; Optimizer.vStack.Push(new StackItem(typeof(uint))); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldsflda(v=vs.110).aspx * Description : Pushes the address of a static field onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { var field = ((OpField)xOp).Value; var fieldName = field.FullName(); var size = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform); string cctor_addref = null; var cctor = (field.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) ?? new ConstructorInfo[0]).SingleOrDefault(); if (cctor != null) { cctor_addref = cctor.FullName(); } /* The stack transitional behavior, in sequential order, is: * The value of the specific field is pushed onto the stack. */ switch (Config.TargetPlatform) { case Architecture.x86: { new Push { DestinationRef = fieldName }; Optimizer.vStack.Push(new StackItem(typeof(uint))); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Throw(v=vs.110).aspx * Description : Throws the exception object currently on the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var item = Optimizer.vStack.Pop(); /* The stack transitional behavior, in sequential order, is: * An object reference (to an exception) is pushed onto the stack. * The object reference is popped from the stack and the exception thrown. */ switch (Config.TargetPlatform) { case Architecture.x86: { if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.ECX }; new Jmp { DestinationRef = xOp.HandlerRef }; } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldobj(v=vs.110).aspx * Description : Copies the value type object pointed to by an address to the top of the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var xOpType = ((OpType)xOp).Value; var size = Helper.GetTypeSize(xOpType, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * The address of a value type object is pushed onto the stack. * The address is popped from the stack and the instance at that particular address is looked up. * The value of the object stored at that address is pushed onto the stack. */ var item = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; for (int i = 1; i <= (size / 4); i++) { new Push { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = (size - (i * 4)) }; } switch (size % 4) { case 0: break; case 1: { new Movzx { DestinationReg = Register.EAX, SourceReg = Register.ESI, SourceIndirect = true, Size = 8 }; new Push { DestinationReg = Register.EAX }; } break; case 2: { new Movzx { DestinationReg = Register.EAX, SourceReg = Register.ESI, SourceIndirect = true, Size = 16 }; new Push { DestinationReg = Register.EAX }; } break; default: throw new Exception("Unsupported Size"); } Optimizer.vStack.Push(new StackItem(xOpType)); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Clt_Un(v=vs.110).aspx * Description : Compares the unsigned or unordered values value1 and value2. If value1 is less than value2, then the integer value 1 (int32) is pushed onto the evaluation stack; otherwise 0 (int32) is pushed onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 2) { throw new Exception("Internal Compiler Error: vStack.Count < 2"); } var itemA = Optimizer.vStack.Pop(); var itemB = Optimizer.vStack.Pop(); var xCurrentLabel = Helper.GetLabel(xOp.Position); var xNextLabel = Helper.GetLabel(xOp.NextPosition); var size = Math.Max(Helper.GetTypeSize(itemA.OperandType, Config.TargetPlatform), Helper.GetTypeSize(itemB.OperandType, Config.TargetPlatform)); /* The stack transitional behavior, in sequential order, is: * value1 is pushed onto the stack. * value2 is pushed onto the stack. * value2 and value1 are popped from the stack; clt.un tests if value1 is less than value2. * If value1 is less than value2, 1 is pushed onto the stack; otherwise 0 is pushed onto the stack. */ switch (Config.TargetPlatform) { case Architecture.x86: { if (itemA.IsFloat || itemB.IsFloat || size > 4) { throw new Exception(string.Format("UnImplemented '{0}'", msIL)); } if (!itemA.SystemStack || !itemB.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; new Pop { DestinationReg = Register.EDX }; new Cmp { DestinationReg = Register.EDX, SourceReg = Register.EAX }; new Setb { DestinationReg = Register.AL }; new Movzx { DestinationReg = Register.EAX, SourceReg = Register.AL, Size = 8 }; new Push { DestinationReg = Register.EAX }; Optimizer.vStack.Push(new StackItem(typeof(bool))); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Call(v=vs.110).aspx * Description : Calls the method indicated by the passed method descriptor. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { var xOpMethod = (OpMethod)xOp; var target = xOpMethod.Value; var targetinfo = target as MethodInfo; var addressRefernce = target.FullName(); bool NoException = target.GetCustomAttribute <NoExceptionAttribute>() != null; var parameters = target.GetParameters(); int count = parameters.Length; int stacksize = parameters.Select(a => Helper.GetTypeSize(a.ParameterType, Config.TargetPlatform, true)).Sum(); int returnSize = 0; if (targetinfo != null) { returnSize = Helper.GetTypeSize(targetinfo.ReturnType, Config.TargetPlatform, true); } if (!target.IsStatic) { count++; Type ArgType = target.DeclaringType; if (target.DeclaringType.IsValueType) { ArgType = ArgType.MakeByRefType(); } stacksize += Helper.GetTypeSize(ArgType, Config.TargetPlatform, true); } if (Optimizer.vStack.Count < count) { throw new Exception("Internal Compiler Error: vStack.Count < expected size"); } /* The stack transitional behavior, in sequential order, is: * Method arguments arg1 through argN are pushed onto the stack. * Method arguments arg1 through argN are popped from the stack; the method call is performed with these arguments * and control is transferred to the method referred to by the method descriptor. When complete, * a return value is generated by the callee method and sent to the caller. * The return value is pushed onto the stack. */ int index = count; while (index > 0) { Optimizer.vStack.Pop(); index--; } switch (Config.TargetPlatform) { case Architecture.x86: { if (returnSize > 8) { throw new Exception(string.Format("UnImplemented '{0}' Return-type: '{1}'", msIL, targetinfo.ReturnType)); } new Call { DestinationRef = addressRefernce }; switch (xOpMethod.CallingConvention) { case CallingConvention.StdCall: break; case CallingConvention.Cdecl: { new Add { DestinationReg = Register.ESP, SourceRef = "0x" + stacksize.ToString("X") }; } break; default: throw new Exception(string.Format("CallingConvention '{0}' not supported", xOpMethod.CallingConvention)); } if (!NoException) { new Test { DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF" }; new Jmp { Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef }; Optimizer.SaveStack(xOp.HandlerPosition); } if (targetinfo != null && targetinfo.ReturnType != typeof(void)) { if (returnSize == 8) { new Push { DestinationReg = Register.EDX } } ; new Push { DestinationReg = Register.EAX }; Optimizer.vStack.Push(new StackItem(targetinfo.ReturnType)); } Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldsfld(v=vs.110).aspx * Description : Pushes the value of a static field onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { var field = ((OpField)xOp).Value; var fieldName = field.FullName(); var size = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform); string cctor_addref = null; var cctor = (field.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) ?? new ConstructorInfo[0]).SingleOrDefault(); if (cctor != null) { cctor_addref = cctor.FullName(); } /* The stack transitional behavior, in sequential order, is: * The value of the specific field is pushed onto the stack. */ switch (Config.TargetPlatform) { case Architecture.x86: { if (!string.IsNullOrEmpty(cctor_addref) && cctor != method) { new Call { DestinationRef = cctor_addref } } ; for (int i = 1; i <= (size / 4); i++) { new Push { DestinationRef = fieldName, DestinationIndirect = true, DestinationDisplacement = (size - (i * 4)) }; } switch (size % 4) { case 0: break; case 1: { new Movzx { DestinationReg = Register.EAX, SourceRef = fieldName, SourceIndirect = true, Size = 8 }; new Push { DestinationReg = Register.EAX }; } break; case 2: { new Movzx { DestinationReg = Register.EAX, SourceRef = fieldName, SourceIndirect = true, Size = 16 }; new Push { DestinationReg = Register.EAX }; } break; default: throw new Exception("Unsupported Size"); } Optimizer.vStack.Push(new StackItem(field.FieldType)); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
internal abstract void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer);
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldfld(v=vs.110).aspx * Description : Finds the value of a field in the object whose reference is currently on the evaluation stack */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var field = ((OpField)xOp).Value; var offset = Helper.GetFieldOffset(field.DeclaringType, field, Config.TargetPlatform); var size = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * An object reference (or pointer) is pushed onto the stack. * The object reference (or pointer) is popped from the stack; the value of the specified field in the object is found. * The value stored in the field is pushed onto the stack. */ var item = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; for (int i = 1; i <= (size / 4); i++) { new Push { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = (size - (i * 4) + offset) }; } switch (size % 4) { case 0: break; case 1: { new Movzx { DestinationReg = Register.EAX, SourceReg = Register.EAX, SourceIndirect = true, SourceDisplacement = offset, Size = 8 }; new Push { DestinationReg = Register.EAX }; } break; case 2: { new Movzx { DestinationReg = Register.EAX, SourceReg = Register.EAX, SourceIndirect = true, SourceDisplacement = offset, Size = 16 }; new Push { DestinationReg = Register.EAX }; } break; default: throw new Exception("Unsupported Size"); } } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } Optimizer.vStack.Push(new StackItem(field.FieldType)); Optimizer.SaveStack(xOp.NextPosition); }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Stsfld(v=vs.110).aspx * Description : Replaces the value of a static field with a value from the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var field = ((OpField)xOp).Value; var fieldName = field.FullName(); var size = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform); string cctor_addref = null; var cctor = (field.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) ?? new ConstructorInfo[0]).SingleOrDefault(); if (cctor != null) { cctor_addref = cctor.FullName(); } /* The stack transitional behavior, in sequential order, is: * A value is pushed onto the stack. * A value is popped from the stack and stored in field. */ var item = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { for (int i = 0; i < (size / 4); i++) { new Pop { DestinationReg = Register.EAX }; new Mov { DestinationRef = fieldName, DestinationIndirect = true, DestinationDisplacement = (i * 4), SourceReg = Register.EAX }; } int offset = size / 4; switch (size % 4) { case 0: break; case 1: { new Pop { DestinationReg = Register.EAX }; new Mov { DestinationRef = fieldName, DestinationIndirect = true, DestinationDisplacement = offset * 4, SourceReg = Register.AL, Size = 8 }; } break; case 2: { new Pop { DestinationReg = Register.EAX }; new Mov { DestinationRef = fieldName, DestinationIndirect = true, DestinationDisplacement = offset * 4, SourceReg = Register.AX, Size = 16 }; } break; default: throw new Exception("Unsupported Size"); } } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } Optimizer.SaveStack(xOp.NextPosition); }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Stfld(v=vs.110).aspx * Description : Replaces the value stored in the field of an object reference or pointer with a new value. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 2) { throw new Exception("Internal Compiler Error: vStack.Count < 2"); } var field = ((OpField)xOp).Value; var offset = Helper.GetFieldOffset(field.DeclaringType, field, Config.TargetPlatform); var size = Helper.GetTypeSize(field.FieldType, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * An object reference or pointer is pushed onto the stack. * A value is pushed onto the stack. * The value and the object reference/pointer are popped from the stack; the value of field in the object is replaced with the supplied value. */ var itemA = Optimizer.vStack.Pop(); var itemB = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (size > 4) { throw new Exception("Field Size > 4 not supported"); } if (!itemA.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } if (!itemB.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; new Pop { DestinationReg = Register.EDX }; switch (size) { case 1: { new Mov { DestinationReg = Register.EDX, DestinationDisplacement = offset, DestinationIndirect = true, SourceReg = Register.AL, Size = 8 }; } break; case 2: { new Mov { DestinationReg = Register.EDX, DestinationDisplacement = offset, DestinationIndirect = true, SourceReg = Register.AX, Size = 16 }; } break; case 4: { new Mov { DestinationReg = Register.EDX, DestinationDisplacement = offset, DestinationIndirect = true, SourceReg = Register.EAX }; } break; case 3: { new Mov { DestinationReg = Register.EDX, DestinationDisplacement = offset, DestinationIndirect = true, SourceReg = Register.AX, Size = 16 }; new Shr { DestinationReg = Register.EAX, SourceRef = "0x10" }; new Mov { DestinationReg = Register.EDX, DestinationIndirect = true, DestinationDisplacement = 2 + offset, SourceReg = Register.AL, Size = 8 }; } break; } } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } Optimizer.SaveStack(xOp.NextPosition); }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Ldelema(v=vs.110).aspx * Description : Loads the address of the array element at a specified array index onto the top of the evaluation stack as type & (managed pointer). */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 2) { throw new Exception("Internal Compiler Error: vStack.Count < 2"); } var operand = ((OpType)xOp).Value; var size = Helper.GetTypeSize(operand, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * An object reference array is pushed onto the stack. * An index value index is pushed onto the stack. * index and array are popped from the stack; the value stored at position index in array is looked up. * The address is pushed onto the stack. */ var itemA = Optimizer.vStack.Pop(); var itemB = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (size > 4) { throw new Exception(string.Format("UnImplemented '{0}'", msIL)); } if (!itemA.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } if (!itemB.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; new Mov { DestinationReg = Register.EDX, SourceRef = "0x" + size.ToString("X") }; new Mul { DestinationReg = Register.EDX }; new Pop { DestinationReg = Register.EDX }; new Add { DestinationReg = Register.EDX, SourceReg = Register.EAX }; new Add { DestinationReg = Register.EDX, SourceRef = "0x10" }; new Push { DestinationReg = Register.EDX }; } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } Optimizer.vStack.Push(new StackItem(typeof(uint))); Optimizer.SaveStack(xOp.NextPosition); }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Newarr(v=vs.110).aspx * Description : Pushes an object reference to a new zero-based, one-dimensional array whose elements are of a specific type onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var type = ((OpType)xOp).Value; var size = Helper.GetTypeSize(type, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * The number of elements in the array is pushed onto the stack. * The number of elements is popped from the stack and the array is created. * An object reference to the new array is pushed onto the stack. */ var item = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Mov { DestinationReg = Register.ESI, SourceReg = Register.ESP, SourceIndirect = true }; new Mov { DestinationReg = Register.EAX, SourceRef = "0x" + size.ToString() }; new Mul { DestinationReg = Register.ESI }; new Add { DestinationReg = Register.EAX, SourceRef = "0x10" }; new Push { DestinationReg = Register.EAX }; new Call { DestinationRef = Helper.Heap_Label, IsLabel = true }; new Test { DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF" }; new Jmp { Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef }; new Pop { DestinationReg = Register.ESI }; new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, SourceRef = "0x" + type.GetHashCode().ToString("X") }; new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 4, SourceRef = "0x2" }; new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 8, SourceReg = Register.ESI }; new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 12, SourceRef = "0x" + size.ToString("X") }; new Push { DestinationReg = Register.EAX }; Optimizer.vStack.Push(new StackItem(typeof(Array))); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Starg(v=vs.110).aspx * Description : Stores the value on top of the evaluation stack in the argument slot at a specified index. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { if (Optimizer.vStack.Count < 1) { throw new Exception("Internal Compiler Error: vStack.Count < 1"); } var index = ((OpVar)xOp).Value; int EBPoffset = Ldarg_il.GetArgumentOffset(Config, method, index); Type ArgType = null; if (!method.IsStatic) { if (index == 0) { ArgType = method.DeclaringType; if (method.DeclaringType.IsValueType) { ArgType = ArgType.MakeByRefType(); } } else { ArgType = method.GetParameters()[index - 1].ParameterType; } } else { ArgType = method.GetParameters()[index].ParameterType; } int ArgSize = Helper.GetTypeSize(ArgType, Config.TargetPlatform); /* The stack transitional behavior, in sequential order, is: * The value currently on top of the stack is popped and placed in argument slot num. */ var item = Optimizer.vStack.Pop(); switch (Config.TargetPlatform) { case Architecture.x86: { if (ArgSize > 4) { throw new Exception("Unsupported ArgSize"); } if (!item.SystemStack) { throw new Exception(string.Format("UnImplemented-RegisterType '{0}'", msIL)); } new Pop { DestinationReg = Register.EAX }; new Mov { DestinationReg = Register.EBP, DestinationIndirect = true, DestinationDisplacement = EBPoffset, SourceReg = Register.EAX }; } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } Optimizer.SaveStack(xOp.NextPosition); }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Newobj(v=vs.110).aspx * Description : Creates a new object or a new instance of a value type, pushing an object reference (type O) onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { var xOpMethod = (OpMethod)xOp; var functionInfo = xOpMethod.Value; var addressRefernce = functionInfo.FullName(); var parameters = functionInfo.GetParameters(); var type = functionInfo.DeclaringType; int FieldIsClassType = 0; var memsize = Helper.GetStorageSize(type, Config.TargetPlatform, ref FieldIsClassType); var paramsize = parameters.Sum(para => Helper.GetTypeSize(para.ParameterType, Config.TargetPlatform, true)); Verbose.Warning("{0} : ByRefCount '{1}'", type.FullName, FieldIsClassType); int count = parameters.Length; if (Optimizer.vStack.Count < count) { throw new Exception("Internal Compiler Error: vStack.Count < expected size"); } if (xOpMethod.CallingConvention != CallingConvention.StdCall) { throw new Exception(string.Format("CallingConvention '{0}' not supported", xOpMethod.CallingConvention)); } /* The stack transitional behavior, in sequential order, is: * Arguments arg1 through argn are pushed on the stack in sequence. * Arguments argn through arg1 are popped from the stack and passed to ctor for object creation. * A reference to the new object is pushed onto the stack. */ int index = count; while (index > 0) { Optimizer.vStack.Pop(); index--; } switch (Config.TargetPlatform) { case Architecture.x86: { if (type.IsValueType) { throw new Exception("Newobj ValueType not implemented"); } if (type == typeof(string)) { if (parameters.Length == 1) { var param = parameters[0].ParameterType.ToString(); if (param == "System.Char[]") { new Mov { DestinationReg = Register.EAX, SourceReg = Register.ESP, SourceIndirect = true }; new Mov { DestinationReg = Register.EAX, SourceReg = Register.EAX, SourceIndirect = true, SourceDisplacement = 8 }; new Shl { DestinationReg = Register.EAX, SourceRef = "0x1" }; } else if (param == "System.Char*") { new Push { DestinationReg = Register.ESP, DestinationIndirect = true }; new Call { DestinationRef = "GetLength.System.Char*", IsLabel = true }; new Shl { DestinationReg = Register.EAX, SourceRef = "0x1" }; } else if (param == "System.SByte*") { new Push { DestinationReg = Register.ESP, DestinationIndirect = true }; new Call { DestinationRef = "GetLength.System.SByte*", IsLabel = true }; new Shl { DestinationReg = Register.EAX, SourceRef = "0x1" }; } else { throw new Exception("String constructor not implemented"); } } else if (parameters.Length == 3) { new Mov { DestinationReg = Register.EAX, SourceReg = Register.ESP, SourceIndirect = true }; new Shl { DestinationReg = Register.EAX, SourceRef = "0x1" }; } else if (parameters.Length == 2) { new Mov { DestinationReg = Register.EAX, SourceReg = Register.ESP, SourceIndirect = true }; new Shl { DestinationReg = Register.EAX, SourceRef = "0x1" }; } else { throw new Exception("String constructor not supported"); } new Add { DestinationReg = Register.EAX, SourceRef = "0x" + memsize.ToString("X") }; new Push { DestinationReg = Register.EAX }; } else { new Push { DestinationRef = "0x" + memsize.ToString("X") } }; new Call { DestinationRef = Helper.Heap_Label, IsLabel = true }; new Test { DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF" }; new Jmp { Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef }; new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, SourceRef = "0x" + type.GetHashCode().ToString("X") }; new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 4, SourceRef = "0x" + (0x1 | FieldIsClassType << 2).ToString("X") }; new Mov { DestinationReg = Register.EAX, DestinationIndirect = true, DestinationDisplacement = 8, SourceRef = "0x" + memsize.ToString("X") }; new Push { DestinationReg = Register.EAX }; new Push { DestinationReg = Register.EAX }; for (int i = 0; i < count; i++) { if (Helper.GetTypeSize(parameters[i].ParameterType, Config.TargetPlatform) > 4) { throw new Exception("unsupported size"); } new Push { DestinationReg = Register.ESP, DestinationDisplacement = (paramsize + 4), DestinationIndirect = true }; } new Call { DestinationRef = functionInfo.FullName() }; new Test { DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF" }; new Jmp { Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef }; new Pop { DestinationReg = Register.EAX }; new Add { DestinationReg = Register.ESP, SourceRef = "0x" + paramsize.ToString("X") }; new Push { DestinationReg = Register.EAX }; Optimizer.vStack.Push(new StackItem(type)); Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }
/* * URL : https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Callvirt(v=vs.110).aspx * Description : Calls a late-bound method on an object, pushing the return value onto the evaluation stack. */ internal override void Execute(Options Config, OpCodeType xOp, MethodBase method, Optimizer Optimizer) { var xOpMethod = (OpMethod)xOp; var functionInfo = xOpMethod.Value as MethodInfo; var addressRefernce = functionInfo.FullName(); var parameters = functionInfo.GetParameters(); var size = parameters.Sum(a => Helper.GetTypeSize(a.ParameterType, Config.TargetPlatform, true)); int returnSize = 0; if (functionInfo != null) { returnSize = Helper.GetTypeSize(functionInfo.ReturnType, Config.TargetPlatform, true); } int count = parameters.Length; if (!functionInfo.IsStatic) { count++; } if (Optimizer.vStack.Count < count) { throw new Exception("Internal Compiler Error: vStack.Count < expected size"); } if (xOpMethod.CallingConvention != CallingConvention.StdCall) { throw new Exception(string.Format("CallingConvention '{0}' not supported", xOpMethod.CallingConvention)); } /* The stack transitional behavior, in sequential order, is: * An object reference obj is pushed onto the stack. * Method arguments arg1 through argN are pushed onto the stack. * Method arguments arg1 through argN and the object reference obj are popped from the stack; * the method call is performed with these arguments and control is transferred to the method * in obj referred to by the method metadata token. When complete, a return value is generated * by the callee method and sent to the caller. * The return value is pushed onto the stack. */ while (count > 0) { Optimizer.vStack.Pop(); count--; } switch (Config.TargetPlatform) { case Architecture.x86: { if (returnSize > 8) { throw new Exception(string.Format("UnImplemented '{0}' Return-type: '{1}'", msIL, functionInfo.ReturnType)); } if (functionInfo.IsStatic || functionInfo.IsFinal || !functionInfo.IsVirtual || !functionInfo.IsAbstract) { new Call { DestinationRef = addressRefernce }; new Test { DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF" }; new Jmp { Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef }; Optimizer.SaveStack(xOp.HandlerPosition); } else { new Mov { DestinationReg = Register.EAX, SourceReg = Register.ESP, SourceDisplacement = size, SourceIndirect = true }; new Mov { DestinationReg = Register.EAX, SourceReg = Register.EAX, SourceIndirect = true }; new Push { DestinationRef = Helper.VTable_Flush }; new Push { DestinationRef = "0x" + xOpMethod.MethodUID.ToString("X") }; new Push { DestinationReg = Register.EAX }; new Call { DestinationRef = Helper.VTable_Label, IsLabel = true }; new Test { DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF" }; new Jmp { Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef }; Optimizer.SaveStack(xOp.HandlerPosition); if (functionInfo.DeclaringType == typeof(object)) { throw new Exception("Callvirt Object Declaring type not implemented"); } new Call { DestinationRef = "EAX" }; new Test { DestinationReg = Register.ECX, SourceRef = "0xFFFFFFFF" }; new Jmp { Condition = ConditionalJump.JNZ, DestinationRef = xOp.HandlerRef }; } if (functionInfo.ReturnType != typeof(void)) { if (returnSize == 8) { new Push { DestinationReg = Register.EDX } } ; new Push { DestinationReg = Register.EAX }; Optimizer.vStack.Push(new StackItem(functionInfo.ReturnType)); } Optimizer.SaveStack(xOp.NextPosition); } break; default: throw new Exception(string.Format("Unsupported target platform '{0}' for MSIL '{1}'", Config.TargetPlatform, msIL)); } }