public ILImporter(ILInterpreter interpreter, MethodDesc method, MethodIL methodIL) { _ilBytes = methodIL.GetILBytes(); _method = method; _methodIL = methodIL; _interpreter = interpreter; var ilExceptionRegions = methodIL.GetExceptionRegions(); _exceptionRegions = new ExceptionRegion[methodIL.GetExceptionRegions().Length]; for (int i = 0; i < ilExceptionRegions.Length; i++) { _exceptionRegions[i] = new ExceptionRegion() { ILRegion = ilExceptionRegions[i] }; } }
public ILImporter(ILScanner compilation, MethodDesc method, MethodIL methodIL = null) { if (methodIL == null) { methodIL = compilation.GetMethodIL(method); } else { _isFallbackBodyCompilation = true; } // This is e.g. an "extern" method in C# without a DllImport or InternalCall. if (methodIL == null) { ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramSpecific, method); } _compilation = compilation; _factory = (ILScanNodeFactory)compilation.NodeFactory; _ilBytes = methodIL.GetILBytes(); _canonMethodIL = methodIL; // Get the runtime determined method IL so that this works right in shared code // and tokens in shared code resolve to runtime determined types. MethodIL uninstantiatiedMethodIL = methodIL.GetMethodILDefinition(); if (methodIL != uninstantiatiedMethodIL) { MethodDesc sharedMethod = method.GetSharedRuntimeFormMethodTarget(); _methodIL = new InstantiatedMethodIL(sharedMethod, uninstantiatiedMethodIL); } else { _methodIL = methodIL; } _canonMethod = method; var ilExceptionRegions = methodIL.GetExceptionRegions(); _exceptionRegions = new ExceptionRegion[ilExceptionRegions.Length]; for (int i = 0; i < ilExceptionRegions.Length; i++) { _exceptionRegions[i] = new ExceptionRegion() { ILRegion = ilExceptionRegions[i] }; } }
public ILImporter(WebAssemblyCodegenCompilation compilation, MethodDesc method, MethodIL methodIL, string mangledName) { Module = compilation.Module; _compilation = compilation; _method = method; _methodIL = methodIL; _ilBytes = methodIL.GetILBytes(); _locals = methodIL.GetLocals(); var ilExceptionRegions = methodIL.GetExceptionRegions(); _exceptionRegions = new ExceptionRegion[ilExceptionRegions.Length]; for (int i = 0; i < ilExceptionRegions.Length; i++) { _exceptionRegions[i] = new ExceptionRegion() { ILRegion = ilExceptionRegions[i] }; } _llvmFunction = GetOrCreateLLVMFunction(mangledName); _builder = LLVM.CreateBuilder(); }
public override ILExceptionRegion[] GetExceptionRegions() { return(_methodIL.GetExceptionRegions()); }
/// <summary> /// Computes the maximum number of items that can be pushed onto the CIL evaluation stack. /// </summary> public static int ComputeMaxStack(this MethodIL methodIL) { const int StackHeightNotSet = Int32.MinValue; byte[] ilbytes = methodIL.GetILBytes(); int currentOffset = 0; int stackHeight = 0; int maxStack = 0; // TODO: Use Span<T> for this and stackalloc the array if reasonably sized int[] stackHeights = new int[ilbytes.Length]; for (int i = 0; i < stackHeights.Length; i++) { stackHeights[i] = StackHeightNotSet; } // Catch and filter clauses have a known non-zero stack height. foreach (ILExceptionRegion region in methodIL.GetExceptionRegions()) { if (region.Kind == ILExceptionRegionKind.Catch) { stackHeights[region.HandlerOffset] = 1; } else if (region.Kind == ILExceptionRegionKind.Filter) { stackHeights[region.FilterOffset] = 1; stackHeights[region.HandlerOffset] = 1; } } while (currentOffset < ilbytes.Length) { ILOpcode opcode = (ILOpcode)ilbytes[currentOffset]; if (opcode == ILOpcode.prefix1) { opcode = 0x100 + (ILOpcode)ilbytes[currentOffset + 1]; } // The stack height could be unknown if the previous instruction // was an unconditional control transfer. // In that case we check if we have a known stack height due to // this instruction being a target of a previous branch or an EH block. if (stackHeight == StackHeightNotSet) { stackHeight = stackHeights[currentOffset]; } // If we still don't know the stack height, ECMA-335 III.1.7.5 // "Backward branch constraint" demands the evaluation stack be empty. if (stackHeight == StackHeightNotSet) { stackHeight = 0; } // Remeber the stack height at this offset. Debug.Assert(stackHeights[currentOffset] == StackHeightNotSet || stackHeights[currentOffset] == stackHeight); stackHeights[currentOffset] = stackHeight; bool isVariableSize = false; switch (opcode) { case ILOpcode.arglist: case ILOpcode.dup: case ILOpcode.ldc_i4: case ILOpcode.ldc_i4_0: case ILOpcode.ldc_i4_1: case ILOpcode.ldc_i4_2: case ILOpcode.ldc_i4_3: case ILOpcode.ldc_i4_4: case ILOpcode.ldc_i4_5: case ILOpcode.ldc_i4_6: case ILOpcode.ldc_i4_7: case ILOpcode.ldc_i4_8: case ILOpcode.ldc_i4_m1: case ILOpcode.ldc_i4_s: case ILOpcode.ldc_i8: case ILOpcode.ldc_r4: case ILOpcode.ldc_r8: case ILOpcode.ldftn: case ILOpcode.ldnull: case ILOpcode.ldsfld: case ILOpcode.ldsflda: case ILOpcode.ldstr: case ILOpcode.ldtoken: case ILOpcode.ldarg: case ILOpcode.ldarg_0: case ILOpcode.ldarg_1: case ILOpcode.ldarg_2: case ILOpcode.ldarg_3: case ILOpcode.ldarg_s: case ILOpcode.ldarga: case ILOpcode.ldarga_s: case ILOpcode.ldloc: case ILOpcode.ldloc_0: case ILOpcode.ldloc_1: case ILOpcode.ldloc_2: case ILOpcode.ldloc_3: case ILOpcode.ldloc_s: case ILOpcode.ldloca: case ILOpcode.ldloca_s: case ILOpcode.sizeof_: stackHeight += 1; break; case ILOpcode.add: case ILOpcode.add_ovf: case ILOpcode.add_ovf_un: case ILOpcode.and: case ILOpcode.ceq: case ILOpcode.cgt: case ILOpcode.cgt_un: case ILOpcode.clt: case ILOpcode.clt_un: case ILOpcode.div: case ILOpcode.div_un: case ILOpcode.initobj: case ILOpcode.ldelem: case ILOpcode.ldelem_i: case ILOpcode.ldelem_i1: case ILOpcode.ldelem_i2: case ILOpcode.ldelem_i4: case ILOpcode.ldelem_i8: case ILOpcode.ldelem_r4: case ILOpcode.ldelem_r8: case ILOpcode.ldelem_ref: case ILOpcode.ldelem_u1: case ILOpcode.ldelem_u2: case ILOpcode.ldelem_u4: case ILOpcode.ldelema: case ILOpcode.mkrefany: case ILOpcode.mul: case ILOpcode.mul_ovf: case ILOpcode.mul_ovf_un: case ILOpcode.or: case ILOpcode.pop: case ILOpcode.rem: case ILOpcode.rem_un: case ILOpcode.shl: case ILOpcode.shr: case ILOpcode.shr_un: case ILOpcode.stsfld: case ILOpcode.sub: case ILOpcode.sub_ovf: case ILOpcode.sub_ovf_un: case ILOpcode.xor: case ILOpcode.starg: case ILOpcode.starg_s: case ILOpcode.stloc: case ILOpcode.stloc_0: case ILOpcode.stloc_1: case ILOpcode.stloc_2: case ILOpcode.stloc_3: case ILOpcode.stloc_s: Debug.Assert(stackHeight > 0); stackHeight -= 1; break; case ILOpcode.throw_: Debug.Assert(stackHeight > 0); stackHeight = StackHeightNotSet; break; case ILOpcode.br: case ILOpcode.leave: case ILOpcode.brfalse: case ILOpcode.brtrue: case ILOpcode.beq: case ILOpcode.bge: case ILOpcode.bge_un: case ILOpcode.bgt: case ILOpcode.bgt_un: case ILOpcode.ble: case ILOpcode.ble_un: case ILOpcode.blt: case ILOpcode.blt_un: case ILOpcode.bne_un: { int target = currentOffset + ReadInt32(ilbytes, currentOffset + 1) + 5; int adjustment; bool isConditional; if (opcode == ILOpcode.br || opcode == ILOpcode.leave) { isConditional = false; adjustment = 0; } else if (opcode == ILOpcode.brfalse || opcode == ILOpcode.brtrue) { isConditional = true; adjustment = 1; } else { isConditional = true; adjustment = 2; } Debug.Assert(stackHeight >= adjustment); stackHeight -= adjustment; Debug.Assert(stackHeights[target] == StackHeightNotSet || stackHeights[target] == stackHeight); // Forward branch carries information about stack height at a future // offset. We need to remember it. if (target > currentOffset) { stackHeights[target] = stackHeight; } if (!isConditional) { stackHeight = StackHeightNotSet; } } break; case ILOpcode.br_s: case ILOpcode.leave_s: case ILOpcode.brfalse_s: case ILOpcode.brtrue_s: case ILOpcode.beq_s: case ILOpcode.bge_s: case ILOpcode.bge_un_s: case ILOpcode.bgt_s: case ILOpcode.bgt_un_s: case ILOpcode.ble_s: case ILOpcode.ble_un_s: case ILOpcode.blt_s: case ILOpcode.blt_un_s: case ILOpcode.bne_un_s: { int target = currentOffset + (sbyte)ilbytes[currentOffset + 1] + 2; int adjustment; bool isConditional; if (opcode == ILOpcode.br_s || opcode == ILOpcode.leave_s) { isConditional = false; adjustment = 0; } else if (opcode == ILOpcode.brfalse_s || opcode == ILOpcode.brtrue_s) { isConditional = true; adjustment = 1; } else { isConditional = true; adjustment = 2; } Debug.Assert(stackHeight >= adjustment); stackHeight -= adjustment; Debug.Assert(stackHeights[target] == StackHeightNotSet || stackHeights[target] == stackHeight); // Forward branch carries information about stack height at a future // offset. We need to remember it. if (target > currentOffset) { stackHeights[target] = stackHeight; } if (!isConditional) { stackHeight = StackHeightNotSet; } } break; case ILOpcode.call: case ILOpcode.calli: case ILOpcode.callvirt: case ILOpcode.newobj: { int token = ReadILToken(ilbytes, currentOffset + 1); object obj = methodIL.GetObject(token); MethodSignature sig = obj is MethodSignature ? (MethodSignature)obj : ((MethodDesc)obj).Signature; int adjustment = sig.Length; if (opcode == ILOpcode.newobj) { adjustment--; } else { if (opcode == ILOpcode.calli) { adjustment++; } if (!sig.IsStatic) { adjustment++; } if (!sig.ReturnType.IsVoid) { adjustment--; } } Debug.Assert(stackHeight >= adjustment); stackHeight -= adjustment; } break; case ILOpcode.ret: { bool hasReturnValue = !methodIL.OwningMethod.Signature.ReturnType.IsVoid; if (hasReturnValue) { stackHeight -= 1; } Debug.Assert(stackHeight == 0); stackHeight = StackHeightNotSet; } break; case ILOpcode.cpobj: case ILOpcode.stfld: case ILOpcode.stind_i: case ILOpcode.stind_i1: case ILOpcode.stind_i2: case ILOpcode.stind_i4: case ILOpcode.stind_i8: case ILOpcode.stind_r4: case ILOpcode.stind_r8: case ILOpcode.stind_ref: case ILOpcode.stobj: Debug.Assert(stackHeight > 1); stackHeight -= 2; break; case ILOpcode.cpblk: case ILOpcode.initblk: case ILOpcode.stelem: case ILOpcode.stelem_i: case ILOpcode.stelem_i1: case ILOpcode.stelem_i2: case ILOpcode.stelem_i4: case ILOpcode.stelem_i8: case ILOpcode.stelem_r4: case ILOpcode.stelem_r8: case ILOpcode.stelem_ref: Debug.Assert(stackHeight > 2); stackHeight -= 3; break; case ILOpcode.break_: case ILOpcode.constrained: case ILOpcode.no: case ILOpcode.nop: case ILOpcode.readonly_: case ILOpcode.tail: case ILOpcode.unaligned: case ILOpcode.volatile_: break; case ILOpcode.endfilter: Debug.Assert(stackHeight > 0); stackHeight = StackHeightNotSet; break; case ILOpcode.jmp: case ILOpcode.rethrow: case ILOpcode.endfinally: stackHeight = StackHeightNotSet; break; case ILOpcode.box: case ILOpcode.castclass: case ILOpcode.ckfinite: case ILOpcode.conv_i: case ILOpcode.conv_i1: case ILOpcode.conv_i2: case ILOpcode.conv_i4: case ILOpcode.conv_i8: case ILOpcode.conv_ovf_i: case ILOpcode.conv_ovf_i_un: case ILOpcode.conv_ovf_i1: case ILOpcode.conv_ovf_i1_un: case ILOpcode.conv_ovf_i2: case ILOpcode.conv_ovf_i2_un: case ILOpcode.conv_ovf_i4: case ILOpcode.conv_ovf_i4_un: case ILOpcode.conv_ovf_i8: case ILOpcode.conv_ovf_i8_un: case ILOpcode.conv_ovf_u: case ILOpcode.conv_ovf_u_un: case ILOpcode.conv_ovf_u1: case ILOpcode.conv_ovf_u1_un: case ILOpcode.conv_ovf_u2: case ILOpcode.conv_ovf_u2_un: case ILOpcode.conv_ovf_u4: case ILOpcode.conv_ovf_u4_un: case ILOpcode.conv_ovf_u8: case ILOpcode.conv_ovf_u8_un: case ILOpcode.conv_r_un: case ILOpcode.conv_r4: case ILOpcode.conv_r8: case ILOpcode.conv_u: case ILOpcode.conv_u1: case ILOpcode.conv_u2: case ILOpcode.conv_u4: case ILOpcode.conv_u8: case ILOpcode.isinst: case ILOpcode.ldfld: case ILOpcode.ldflda: case ILOpcode.ldind_i: case ILOpcode.ldind_i1: case ILOpcode.ldind_i2: case ILOpcode.ldind_i4: case ILOpcode.ldind_i8: case ILOpcode.ldind_r4: case ILOpcode.ldind_r8: case ILOpcode.ldind_ref: case ILOpcode.ldind_u1: case ILOpcode.ldind_u2: case ILOpcode.ldind_u4: case ILOpcode.ldlen: case ILOpcode.ldobj: case ILOpcode.ldvirtftn: case ILOpcode.localloc: case ILOpcode.neg: case ILOpcode.newarr: case ILOpcode.not: case ILOpcode.refanytype: case ILOpcode.refanyval: case ILOpcode.unbox: case ILOpcode.unbox_any: Debug.Assert(stackHeight > 0); break; case ILOpcode.switch_: Debug.Assert(stackHeight > 0); isVariableSize = true; stackHeight -= 1; currentOffset += 1 + (ReadInt32(ilbytes, currentOffset + 1) * 4) + 4; break; default: Debug.Fail("Unknown instruction"); break; } if (!isVariableSize) { currentOffset += opcode.GetSize(); } maxStack = Math.Max(maxStack, stackHeight); } return(maxStack); }
public ILImporter(Compilation compilation, CppWriter writer, MethodDesc method, MethodIL methodIL) { _compilation = compilation; _nodeFactory = _compilation.NodeFactory; _writer = writer; _method = method; _methodSignature = method.Signature; _typeSystemContext = method.Context; if (!_methodSignature.IsStatic) _thisType = method.OwningType; _methodIL = methodIL; _ilBytes = _methodIL.GetILBytes(); _locals = _methodIL.GetLocals(); var ilExceptionRegions = _methodIL.GetExceptionRegions(); _exceptionRegions = new ExceptionRegion[ilExceptionRegions.Length]; for (int i = 0; i < ilExceptionRegions.Length; i++) { _exceptionRegions[i] = new ExceptionRegion() { ILRegion = ilExceptionRegions[i] }; } }
private MethodIL Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, out CORINFO_METHOD_INFO methodInfo) { // MethodIL can be provided externally for the case of a method whose IL was replaced because we couldn't compile it. if (methodIL == null) methodIL = _compilation.GetMethodIL(method); if (methodIL == null) { methodInfo = default(CORINFO_METHOD_INFO); return null; } methodInfo.ftn = ObjectToHandle(method); methodInfo.scope = (CORINFO_MODULE_STRUCT_*)ObjectToHandle(methodIL); var ilCode = methodIL.GetILBytes(); methodInfo.ILCode = (byte*)GetPin(ilCode); methodInfo.ILCodeSize = (uint)ilCode.Length; methodInfo.maxStack = (uint)methodIL.MaxStack; methodInfo.EHcount = (uint)methodIL.GetExceptionRegions().Length; methodInfo.options = methodIL.IsInitLocals ? CorInfoOptions.CORINFO_OPT_INIT_LOCALS : (CorInfoOptions)0; methodInfo.regionKind = CorInfoRegionKind.CORINFO_REGION_NONE; Get_CORINFO_SIG_INFO(method, out methodInfo.args); Get_CORINFO_SIG_INFO(methodIL.GetLocals(), out methodInfo.locals); return methodIL; }