Exemplo n.º 1
0
        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]
                };
            }
        }
Exemplo n.º 2
0
        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]
                };
            }
        }
Exemplo n.º 3
0
        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();
        }
Exemplo n.º 4
0
 public override ILExceptionRegion[] GetExceptionRegions()
 {
     return(_methodIL.GetExceptionRegions());
 }
Exemplo n.º 5
0
        /// <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);
        }
Exemplo n.º 6
0
        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] };
            }
        }
Exemplo n.º 7
0
        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;
        }