Example #1
0
        public static MibcConfig ParseMibcConfig(TypeSystemContext tsc, PEReader pEReader)
        {
            EcmaModule mibcModule    = EcmaModule.Create(tsc, pEReader, null);
            EcmaMethod mibcConfigMth = (EcmaMethod)mibcModule.GetGlobalModuleType().GetMethod(nameof(MibcConfig), null);

            if (mibcConfigMth == null)
            {
                return(null);
            }

            var ilBody   = EcmaMethodIL.Create(mibcConfigMth);
            var ilReader = new ILReader(ilBody.GetILBytes());

            // Parse:
            //
            //   ldstr "key1"
            //   ldstr "value1"
            //   pop
            //   pop
            //   ldstr "key2"
            //   ldstr "value2"
            //   pop
            //   pop
            //   ...
            //   ret
            string fieldName = null;
            Dictionary <string, string> keyValue = new();

            while (ilReader.HasNext)
            {
                ILOpcode opcode = ilReader.ReadILOpcode();
                switch (opcode)
                {
                case ILOpcode.ldstr:
                    var ldStrValue = (string)ilBody.GetObject(ilReader.ReadILToken());
                    if (fieldName != null)
                    {
                        keyValue[fieldName] = ldStrValue;
                    }
                    else
                    {
                        fieldName = ldStrValue;
                    }
                    break;

                case ILOpcode.ret:
                case ILOpcode.pop:
                    fieldName = null;
                    break;

                default:
                    throw new InvalidOperationException($"Unexpected opcode: {opcode}");
                }
            }

            return(MibcConfig.FromKeyValueMap(keyValue));
        }
Example #2
0
        private void ImportBranch(ILOpcode opcode, BasicBlock target, BasicBlock fallthrough)
        {
            ImportFallthrough(target);

            if (fallthrough != null)
            {
                ImportFallthrough(fallthrough);
            }
        }
Example #3
0
            private static bool ScanMethodBodyForFieldAccess(MethodIL body, bool write, out FieldDesc?found)
            {
                // Tries to find the backing field for a property getter/setter.
                // Returns true if this is a method body that we can unambiguously analyze.
                // The found field could still be null if there's no backing store.
                found = null;

                ILReader ilReader = new ILReader(body.GetILBytes());

                while (ilReader.HasNext)
                {
                    ILOpcode opcode = ilReader.ReadILOpcode();
                    switch (opcode)
                    {
                    case ILOpcode.ldsfld when !write:
                    case ILOpcode.ldfld when !write:
                    case ILOpcode.stsfld when write:
                    case ILOpcode.stfld when write:
                    {
                        // This writes/reads multiple fields - can't guess which one is the backing store.
                        // Return failure.
                        if (found != null)
                        {
                            found = null;
                            return(false);
                        }
                        found = (FieldDesc)body.GetObject(ilReader.ReadILToken());
                    }
                    break;

                    default:
                        ilReader.Skip(opcode);
                        break;
                    }
                }

                if (found == null)
                {
                    // Doesn't access any fields. Could be e.g. "Type Foo => typeof(Bar);"
                    // Return success.
                    return(true);
                }

                if (found.OwningType != body.OwningMethod.OwningType ||
                    found.IsStatic != body.OwningMethod.Signature.IsStatic ||
                    !found.HasCustomAttribute("System.Runtime.CompilerServices", "CompilerGeneratedAttribute"))
                {
                    // A couple heuristics to make sure we got the right field.
                    // Return failure.
                    found = null;
                    return(false);
                }

                return(true);
            }
Example #4
0
        public ILOpcode ReadILOpcode()
        {
            ILOpcode opcode = (ILOpcode)ReadILByte();

            if (opcode == ILOpcode.prefix1)
            {
                opcode = (ILOpcode)(0x100 + ReadILByte());
            }

            return(opcode);
        }
Example #5
0
        public bool TryReadRet()
        {
            ILOpcode opcode = PeekILOpcode();

            if (opcode == ILOpcode.ret)
            {
                ReadILOpcode();
                return(true);
            }
            return(false);
        }
Example #6
0
        public bool TryReadPop()
        {
            ILOpcode opcode = PeekILOpcode();

            if (opcode == ILOpcode.pop)
            {
                ReadILOpcode();
                return(true);
            }
            return(false);
        }
Example #7
0
        public ILOpcode PeekILOpcode()
        {
            ILOpcode opcode = (ILOpcode)_ilBytes[_currentOffset];

            if (opcode == ILOpcode.prefix1)
            {
                opcode = (ILOpcode)(0x100 + _ilBytes[_currentOffset + 1]);
            }

            return(opcode);
        }
Example #8
0
        private void ImportCasting(ILOpcode opcode, int token)
        {
            TypeDesc type = (TypeDesc)_methodIL.GetObject(token);

            if (type.IsRuntimeDeterminedSubtype)
            {
                _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandleForCasting, type), "IsInst/CastClass");
            }
            else
            {
                _dependencies.Add(_compilation.ComputeConstantLookup(ReadyToRunHelperId.TypeHandleForCasting, type), "IsInst/CastClass");
            }
        }
Example #9
0
        public void Emit(ILOpcode opcode, ILCodeLabel label)
        {
            Debug.Assert(opcode == ILOpcode.br || opcode == ILOpcode.brfalse ||
                         opcode == ILOpcode.brtrue || opcode == ILOpcode.beq ||
                         opcode == ILOpcode.bge || opcode == ILOpcode.bgt ||
                         opcode == ILOpcode.ble || opcode == ILOpcode.blt ||
                         opcode == ILOpcode.bne_un || opcode == ILOpcode.bge_un ||
                         opcode == ILOpcode.bgt_un || opcode == ILOpcode.ble_un ||
                         opcode == ILOpcode.blt_un || opcode == ILOpcode.leave);

            Emit(opcode);
            _offsetsNeedingPatching.Add(new LabelAndOffset(label, _length));
            EmitUInt32(4);
        }
Example #10
0
 private void ImportBinaryOperation(ILOpcode opcode)
 {
     switch (opcode)
     {
     case ILOpcode.add_ovf:
     case ILOpcode.add_ovf_un:
     case ILOpcode.mul_ovf:
     case ILOpcode.mul_ovf_un:
     case ILOpcode.sub_ovf:
     case ILOpcode.sub_ovf_un:
         _dependencies.Add(GetHelperEntrypoint(ReadyToRunHelper.Overflow), "_ovf");
         break;
     }
 }
Example #11
0
 public int ReadBranchDestination(ILOpcode currentOpcode)
 {
     if ((currentOpcode >= ILOpcode.br_s && currentOpcode <= ILOpcode.blt_un_s) ||
         currentOpcode == ILOpcode.leave_s)
     {
         return((sbyte)ReadILByte() + Offset);
     }
     else
     {
         Debug.Assert((currentOpcode >= ILOpcode.br && currentOpcode <= ILOpcode.blt_un) ||
                      currentOpcode == ILOpcode.leave);
         return((int)ReadILUInt32() + Offset);
     }
 }
        public static void Scan(ref DependencyList list, NodeFactory factory, MethodIL methodIL)
        {
            ILReader reader = new ILReader(methodIL.GetILBytes());

            Tracker tracker = new Tracker(methodIL);

            // The algorithm here is really primitive: we scan the IL forward in a single pass, remembering
            // the last type/string/token we saw.
            //
            // We then intrinsically recognize a couple methods that consume this information.
            //
            // This has obvious problems since we don't have exact knowledge of the parameters passed
            // (something being in front of a call doesn't mean it's a parameter to the call). But since
            // this is a heuristic, it's okay. We want this to be as fast as possible.
            //
            // The main purposes of this scanner is to make following patterns work:
            //
            // * Enum.GetValues(typeof(Foo)) - this is very common and we need to make sure Foo[] is compiled.
            // * Type.GetType("Foo, Bar").GetMethod("Blah") - framework uses this to work around layering problems.
            // * typeof(Foo<>).MakeGenericType(arg).GetMethod("Blah") - used in e.g. LINQ expressions implementation
            // * Marshal.SizeOf(typeof(Foo)) - very common and we need to make sure interop data is generated

            while (reader.HasNext)
            {
                ILOpcode opcode = reader.ReadILOpcode();
                switch (opcode)
                {
                case ILOpcode.ldstr:
                    tracker.TrackStringToken(reader.ReadILToken());
                    break;

                case ILOpcode.ldtoken:
                    tracker.TrackLdTokenToken(reader.ReadILToken());
                    break;

                case ILOpcode.call:
                case ILOpcode.callvirt:
                    var method = methodIL.GetObject(reader.ReadILToken()) as MethodDesc;
                    if (method != null)
                    {
                        HandleCall(ref list, factory, methodIL, method, ref tracker);
                    }
                    break;

                default:
                    reader.Skip(opcode);
                    break;
                }
            }
        }
Example #13
0
        /// <summary>
        /// Parse MIbcGroup method and return enumerable of MethodProfileData
        ///
        /// Like the AssemblyDictionary method, data is encoded via IL instructions. The format is
        ///
        /// ldtoken methodInProfileData
        /// Any series of instructions that does not include pop
        /// pop
        /// {Repeat N times for N methods described}
        ///
        /// This format is designed to be extensible to hold more data as we add new per method profile data without breaking existing parsers.
        /// </summary>
        static IEnumerable <MethodProfileData> ReadMIbcGroup(TypeSystemContext tsc, EcmaMethod method)
        {
            EcmaMethodIL ilBody = EcmaMethodIL.Create(method);

            byte[] ilBytes             = ilBody.GetILBytes();
            int    currentOffset       = 0;
            object metadataObject      = null;
            object methodNotResolvable = new object();

            while (currentOffset < ilBytes.Length)
            {
                ILOpcode opcode = (ILOpcode)ilBytes[currentOffset];
                if (opcode == ILOpcode.prefix1)
                {
                    opcode = 0x100 + (ILOpcode)ilBytes[currentOffset + 1];
                }
                switch (opcode)
                {
                case ILOpcode.ldtoken:
                    if (metadataObject == null)
                    {
                        uint token = (uint)(ilBytes[currentOffset + 1] + (ilBytes[currentOffset + 2] << 8) + (ilBytes[currentOffset + 3] << 16) + (ilBytes[currentOffset + 4] << 24));
                        try
                        {
                            metadataObject = ilBody.GetObject((int)token);
                        }
                        catch (TypeSystemException)
                        {
                            // The method being referred to may be missing. In that situation,
                            // use the methodNotResolvable sentinel to indicate that this record should be ignored
                            metadataObject = methodNotResolvable;
                        }
                    }
                    break;

                case ILOpcode.pop:
                    if (metadataObject != methodNotResolvable)
                    {
                        MethodProfileData mibcData = new MethodProfileData((MethodDesc)metadataObject, MethodProfilingDataFlags.ReadMethodCode, 0xFFFFFFFF);
                        yield return(mibcData);
                    }
                    metadataObject = null;
                    break;
                }

                // This isn't correct if there is a switch opcode, but since we won't do that, its ok
                currentOffset += opcode.GetSize();
            }
        }
Example #14
0
        private void ImportLdFtn(int token, ILOpcode opCode)
        {
            // Is this a verifiable delegate creation? If so, we will handle it when we reach the newobj
            if (_ilBytes[_currentOffset] == (byte)ILOpcode.newobj)
            {
                int delegateToken = ReadILTokenAt(_currentOffset + 1);
                var delegateType  = ((MethodDesc)_methodIL.GetObject(delegateToken)).OwningType;
                if (delegateType.IsDelegate)
                {
                    return;
                }
            }

            ImportCall(opCode, token);
        }
Example #15
0
        public ILOpcode PeekILOpcode()
        {
            ILOpcode opcode = (ILOpcode)_ilBytes[_currentOffset];

            if (opcode == ILOpcode.prefix1)
            {
                if (_currentOffset + 2 > _ilBytes.Length)
                {
                    ThrowHelper.ThrowInvalidProgramException();
                }
                opcode = (ILOpcode)(0x100 + _ilBytes[_currentOffset + 1]);
            }

            return(opcode);
        }
Example #16
0
        private void ImportCompareOperation(ILOpcode opcode)
        {
            var op1 = _stack.Pop();
            var op2 = _stack.Pop();

            // StackValueKind is carefully ordered to make this work (assuming the IL is valid)
            StackValueKind kind;

            if (op1.Kind > op2.Kind)
            {
                kind = op1.Kind;
            }
            else
            {
                kind = op2.Kind;
            }

            LLVMValueRef result;

            switch (opcode)
            {
            case ILOpcode.ceq:
                result = LLVM.BuildICmp(_builder, LLVMIntPredicate.LLVMIntEQ, op2.LLVMValue, op1.LLVMValue, "ceq");
                break;

            case ILOpcode.cgt:
                result = LLVM.BuildICmp(_builder, LLVMIntPredicate.LLVMIntSGT, op2.LLVMValue, op1.LLVMValue, "cgt");
                break;

            case ILOpcode.clt:
                result = LLVM.BuildICmp(_builder, LLVMIntPredicate.LLVMIntSLT, op2.LLVMValue, op1.LLVMValue, "clt");
                break;

            case ILOpcode.cgt_un:
                result = LLVM.BuildICmp(_builder, LLVMIntPredicate.LLVMIntUGT, op2.LLVMValue, op1.LLVMValue, "cgt_un");
                break;

            case ILOpcode.clt_un:
                result = LLVM.BuildICmp(_builder, LLVMIntPredicate.LLVMIntULT, op2.LLVMValue, op1.LLVMValue, "clt_un");
                break;

            default:
                throw new NotSupportedException();     // unreachable
            }

            PushExpression(kind, "", result, GetWellKnownType(WellKnownType.SByte));
        }
        private void ImportCall(ILOpcode opcode, int token)
        {
            MethodDesc callee = (MethodDesc)_methodIL.GetObject(token);

            if (callee.IsPInvoke)
            {
                ImportRawPInvoke(callee);
                return;
            }

            // we don't really have virtual call support, but we'll treat it as direct for now
            if (opcode != ILOpcode.call && opcode != ILOpcode.callvirt)
            {
                throw new NotImplementedException();
            }
            HandleCall(callee);
        }
Example #18
0
        /// <summary>
        /// Skips over a "foo == typeof(Bar)" or "typeof(Foo) == typeof(Bar)" sequence.
        /// </summary>
        private static bool IsTypeEqualityTest(MethodIL methodIL, ILReader reader, out ILReader afterTest)
        {
            afterTest = default;

            if (reader.ReadILOpcode() != ILOpcode.call)
            {
                return(false);
            }
            MethodDesc method = methodIL.GetObject(reader.ReadILToken()) as MethodDesc;

            if (method == null || method.Name != "GetTypeFromHandle" && !method.OwningType.IsSystemType())
            {
                return(false);
            }

            ILOpcode opcode = reader.ReadILOpcode();

            if (opcode == ILOpcode.ldtoken)
            {
                reader.ReadILToken();
                opcode = reader.ReadILOpcode();
                if (opcode != ILOpcode.call)
                {
                    return(false);
                }
                method = methodIL.GetObject(reader.ReadILToken()) as MethodDesc;
                if (method == null || method.Name != "GetTypeFromHandle" && !method.OwningType.IsSystemType())
                {
                    return(false);
                }
                opcode = reader.ReadILOpcode();
            }
            if (opcode != ILOpcode.call)
            {
                return(false);
            }
            method = methodIL.GetObject(reader.ReadILToken()) as MethodDesc;
            if (method == null || method.Name != "op_Equality" && !method.OwningType.IsSystemType())
            {
                return(false);
            }

            afterTest = reader;
            return(true);
        }
Example #19
0
        public void Skip(ILOpcode opcode)
        {
            if (!opcode.IsValid())
            {
                ThrowHelper.ThrowInvalidProgramException();
            }

            if (opcode != ILOpcode.switch_)
            {
                int opcodeSize = (byte)opcode != (int)opcode ? 2 : 1;
                _currentOffset += opcode.GetSize() - opcodeSize;
            }
            else
            {
                // "switch" opcode is special
                uint count = ReadILUInt32();
                _currentOffset += checked ((int)(count * 4));
            }
        }
Example #20
0
            public int MoveNext(int offset)
            {
                if (_foundEndOfPrevBlock || _methodBranchTargets.Contains(offset))
                {
                    _currentBlockIndex++;
                    _foundEndOfPrevBlock = false;
                }

                var reader = new ILReader(_methodBody.GetILBytes());

                reader.Seek(offset);
                ILOpcode opcode = reader.ReadILOpcode();

                if (opcode.IsControlFlowInstruction())
                {
                    _foundEndOfPrevBlock = true;
                }

                return(CurrentBlockIndex);
            }
Example #21
0
 public static bool IsControlFlowInstruction(this ILOpcode opcode)
 {
     switch (opcode)
     {
     case ILOpcode.br_s:
     case ILOpcode.br:
     case ILOpcode.brfalse_s:
     case ILOpcode.brtrue_s:
     case ILOpcode.beq_s:
     case ILOpcode.bge_s:
     case ILOpcode.bgt_s:
     case ILOpcode.ble_s:
     case ILOpcode.blt_s:
     case ILOpcode.bne_un_s:
     case ILOpcode.bge_un_s:
     case ILOpcode.bgt_un_s:
     case ILOpcode.ble_un_s:
     case ILOpcode.blt_un_s:
     case ILOpcode.brfalse:
     case ILOpcode.brtrue:
     case ILOpcode.beq:
     case ILOpcode.bge:
     case ILOpcode.bgt:
     case ILOpcode.ble:
     case ILOpcode.blt:
     case ILOpcode.bne_un:
     case ILOpcode.bge_un:
     case ILOpcode.bgt_un:
     case ILOpcode.ble_un:
     case ILOpcode.blt_un:
     case ILOpcode.switch_:
     case ILOpcode.leave:
     case ILOpcode.leave_s:
     case ILOpcode.endfilter:
     case ILOpcode.endfinally:
     case ILOpcode.throw_:
     case ILOpcode.rethrow:
         return(true);
     }
     return(false);
 }
Example #22
0
 private static bool ILOpcodeHasToken(ILOpcode opcode)
 {
     switch (opcode)
     {
     case ILOpcode.jmp:
     case ILOpcode.call:
     case ILOpcode.calli:
     case ILOpcode.callvirt:
     case ILOpcode.cpobj:
     case ILOpcode.ldobj:
     case ILOpcode.ldstr:
     case ILOpcode.newobj:
     case ILOpcode.castclass:
     case ILOpcode.isinst:
     case ILOpcode.unbox:
     case ILOpcode.ldfld:
     case ILOpcode.ldflda:
     case ILOpcode.stfld:
     case ILOpcode.ldsfld:
     case ILOpcode.ldsflda:
     case ILOpcode.stsfld:
     case ILOpcode.stobj:
     case ILOpcode.box:
     case ILOpcode.newarr:
     case ILOpcode.ldelema:
     case ILOpcode.ldelem:
     case ILOpcode.stelem:
     case ILOpcode.unbox_any:
     case ILOpcode.refanyval:
     case ILOpcode.mkrefany:
     case ILOpcode.ldtoken:
     case ILOpcode.ldftn:
     case ILOpcode.ldvirtftn:
     case ILOpcode.initobj:
     case ILOpcode.constrained:
     case ILOpcode.sizeof_:
         return(true);
     }
     return(false);
 }
Example #23
0
        private void ImportUnbox(int token, ILOpcode opCode)
        {
            TypeDesc type = (TypeDesc)_methodIL.GetObject(token);

            if (!type.IsValueType)
            {
                if (opCode == ILOpcode.unbox_any)
                {
                    // When applied to a reference type, unbox_any has the same effect as castclass.
                    ImportCasting(ILOpcode.castclass, token);
                }
                return;
            }

            if (type.IsRuntimeDeterminedSubtype)
            {
                _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandle, type), "Unbox");
            }
            else
            {
                _dependencies.Add(_factory.NecessaryTypeSymbol(type), "Unbox");
            }

            ReadyToRunHelper helper;

            if (opCode == ILOpcode.unbox)
            {
                helper = ReadyToRunHelper.Unbox;
            }
            else
            {
                Debug.Assert(opCode == ILOpcode.unbox_any);
                helper = ReadyToRunHelper.Unbox_Nullable;
            }

            _dependencies.Add(GetHelperEntrypoint(helper), "Unbox");
        }
Example #24
0
        static IEnumerable <MIbcData> ReadMIbcData(TraceTypeSystemContext tsc, FileInfo outputFileName, byte[] moduleBytes)
        {
            var peReader = new System.Reflection.PortableExecutable.PEReader(System.Collections.Immutable.ImmutableArray.Create <byte>(moduleBytes));
            var module   = EcmaModule.Create(tsc, peReader, null, null, new CustomCanonResolver(tsc));

            var          loadedMethod = (EcmaMethod)module.GetGlobalModuleType().GetMethod("AssemblyDictionary", null);
            EcmaMethodIL ilBody       = EcmaMethodIL.Create(loadedMethod);

            byte[] ilBytes       = ilBody.GetILBytes();
            int    currentOffset = 0;

            while (currentOffset < ilBytes.Length)
            {
                ILOpcode opcode = (ILOpcode)ilBytes[currentOffset];
                if (opcode == ILOpcode.prefix1)
                {
                    opcode = 0x100 + (ILOpcode)ilBytes[currentOffset + 1];
                }
                switch (opcode)
                {
                case ILOpcode.ldtoken:
                    UInt32 token = (UInt32)(ilBytes[currentOffset + 1] + (ilBytes[currentOffset + 2] << 8) + (ilBytes[currentOffset + 3] << 16) + (ilBytes[currentOffset + 4] << 24));
                    foreach (var data in ReadMIbcGroup(tsc, (EcmaMethod)ilBody.GetObject((int)token)))
                    {
                        yield return(data);
                    }
                    break;

                case ILOpcode.pop:
                    break;
                }

                // This isn't correct if there is a switch opcode, but since we won't do that, its ok
                currentOffset += opcode.GetSize();
            }
            GC.KeepAlive(peReader);
        }
Example #25
0
        public static HashSet <int> ComputeBranchTargets(this MethodIL methodBody)
        {
            HashSet <int> branchTargets = new HashSet <int>();
            var           reader        = new ILReader(methodBody.GetILBytes());

            while (reader.HasNext)
            {
                ILOpcode opcode = reader.ReadILOpcode();
                if (opcode >= ILOpcode.br_s && opcode <= ILOpcode.blt_un)
                {
                    branchTargets.Add(reader.ReadBranchDestination(opcode));
                }
                else if (opcode == ILOpcode.switch_)
                {
                    uint count   = reader.ReadILUInt32();
                    int  jmpBase = reader.Offset + (int)(4 * count);
                    for (uint i = 0; i < count; i++)
                    {
                        branchTargets.Add((int)reader.ReadILUInt32() + jmpBase);
                    }
                }
                else
                {
                    reader.Skip(opcode);
                }
            }
            foreach (ILExceptionRegion einfo in methodBody.GetExceptionRegions())
            {
                if (einfo.Kind == ILExceptionRegionKind.Filter)
                {
                    branchTargets.Add(einfo.FilterOffset);
                }
                branchTargets.Add(einfo.HandlerOffset);
            }
            return(branchTargets);
        }
Example #26
0
        public static bool IsBranch(this ILOpcode opcode)
        {
            if (opcode >= ILOpcode.br && opcode <= ILOpcode.blt_un)
            {
                return(true);
            }

            if (opcode >= ILOpcode.br_s && opcode <= ILOpcode.blt_un_s)
            {
                return(true);
            }

            if (opcode == ILOpcode.leave_s)
            {
                return(true);
            }

            if (opcode == ILOpcode.leave)
            {
                return(true);
            }

            return(false);
        }
Example #27
0
        private void ImportCall(ILOpcode opcode, int token)
        {
            bool callViaSlot = false;
            bool delegateInvoke = false;
            bool callViaInterfaceDispatch = false;
            DelegateCreationInfo delegateInfo = null;

            MethodDesc method = (MethodDesc)_methodIL.GetObject(token);

            if (method.IsIntrinsic)
            {
                if (ImportIntrinsicCall(method))
                    return;
            }

            TypeDesc constrained = null;
            if (opcode != ILOpcode.newobj)
            {
                if ((_pendingPrefix & Prefix.Constrained) != 0 && opcode == ILOpcode.callvirt)
                {
                    _pendingPrefix &= ~Prefix.Constrained;
                    constrained = _constrained;

                    bool forceUseRuntimeLookup;
                    MethodDesc directMethod = constrained.GetClosestDefType().TryResolveConstraintMethodApprox(method.OwningType, method, out forceUseRuntimeLookup);

                    if (forceUseRuntimeLookup)
                        throw new NotImplementedException();

                    if (directMethod != null)
                    {
                        method = directMethod;
                        opcode = ILOpcode.call;
                    }
                    else
                    {
                        // Dereference "this"
                        int thisPosition = _stack.Top - (method.Signature.Length + 1);
                        string tempName = NewTempName();

                        Append(GetStackValueKindCPPTypeName(StackValueKind.ObjRef));
                        Append(" ");
                        Append(tempName);
                        Append(" = *(");
                        Append(GetStackValueKindCPPTypeName(StackValueKind.ObjRef));
                        Append("*)");
                        Append(_stack[thisPosition]);
                        AppendSemicolon();

                        _stack[thisPosition] = new ExpressionEntry(StackValueKind.ObjRef, tempName);
                    }
                }
            }

            TypeDesc owningType = method.OwningType;

            TypeDesc retType = null;

            {
                if (opcode == ILOpcode.newobj)
                {
                    retType = owningType;

                    if (owningType.IsString)
                    {
                        // String constructors actually look like regular method calls
                        method = method.GetStringInitializer();
                        opcode = ILOpcode.call;
                    }
                    else if (owningType.IsArray)
                    {
                        ImportNewObjArray(owningType, method);
                        return;
                    }
                    else if (owningType.IsDelegate)
                    {
                        delegateInfo = _compilation.GetDelegateCtor(owningType, ((LdTokenEntry<MethodDesc>)_stack.Peek()).LdToken);
                        method = delegateInfo.Constructor.Method;
                    }
                }
                else
                if (owningType.IsDelegate)
                {
                    if (method.Name == "Invoke")
                    {
                        opcode = ILOpcode.call;
                        delegateInvoke = true;
                    }
                }
            }

            if (opcode == ILOpcode.callvirt)
            {
                // TODO: Null checks

                if (method.IsVirtual)
                {
                    // TODO: Full resolution of virtual methods
                    if (!method.IsNewSlot)
                        throw new NotImplementedException();

                    if (method.OwningType.IsInterface)
                        callViaInterfaceDispatch = true;
                    else
                        callViaSlot = true;

                    _dependencies.Add(_nodeFactory.VirtualMethodUse(method));
                }
            }

            if (!callViaSlot && !delegateInvoke && !callViaInterfaceDispatch)
                AddMethodReference(method);

            if (opcode == ILOpcode.newobj)
                AddTypeReference(retType, true);

            var methodSignature = method.Signature;

            if (retType == null)
                retType = methodSignature.ReturnType;

            string temp = null;
            StackValueKind retKind = StackValueKind.Unknown;
            var needNewLine = false;

            if (callViaInterfaceDispatch)
            {
                _dependencies.Add(_nodeFactory.ReadyToRunHelper(ReadyToRunHelperId.VirtualCall, method));
                ExpressionEntry v = (ExpressionEntry)_stack[_stack.Top - (methodSignature.Length + 1)];

                string typeDefName = _writer.GetCppMethodName(method);
                _writer.AppendSignatureTypeDef(_builder,  typeDefName, method.Signature, method.OwningType);

                string functionPtr = NewTempName();
                AppendEmptyLine();

                Append("void*");
                Append(functionPtr);
                Append(" = (void*) ((");
                Append(typeDefName);
                // Call method to find implementation address
                Append(") System_Private_CoreLib::System::Runtime::DispatchResolve::FindInterfaceMethodImplementationTarget(");

                // Get EEType of current object (interface implementation)
                Append("::System_Private_CoreLib::System::Object::get_EEType((::System_Private_CoreLib::System::Object*)");
                Append(v.Name);
                Append(")");

                Append(", ");

                // Get EEType of interface
                Append("((::System_Private_CoreLib::Internal::Runtime::EEType *)(");
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::__getMethodTable()))");

                Append(", ");

                // Get slot of implementation
                Append("(uint16_t)");
                Append("(");
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::");
                Append("__getslot__");
                Append(_writer.GetCppMethodName(method));
                Append("(");
                Append(v.Name);
                Append("))");

                Append("));");

                PushExpression(StackValueKind.ByRef, functionPtr);
            }

            if (!retType.IsVoid)
            {
                retKind = GetStackValueKind(retType);
                temp = NewTempName();

                AppendLine();
                Append(GetStackValueKindCPPTypeName(retKind, retType));
                Append(" ");
                Append(temp);
                if (retType.IsValueType && opcode == ILOpcode.newobj)
                {
                    Append(";");
                    needNewLine = true;
                }
                else
                {
                    Append(" = ");

                    if (retType.IsPointer)
                    {
                        Append("(intptr_t)");
                    }
                }
            }
            else
            {
                needNewLine = true;
            }
            AddTypeReference(method.OwningType, true);

            if (opcode == ILOpcode.newobj)
            {
                if (!retType.IsValueType)
                {
                    // We do not reset needNewLine since we still need for the next statement.
                    if (needNewLine)
                        AppendLine();
                    Append("__allocate_object(");
                    Append(_writer.GetCppTypeName(retType));
                    Append("::__getMethodTable())");
                    AppendSemicolon();
                    needNewLine = true;

                    if (delegateInfo != null && delegateInfo.Thunk != null)
                    {
                        MethodDesc thunkMethod = delegateInfo.Thunk.Method;
                        AddMethodReference(thunkMethod);

                        // Update stack with new name.
                        ((ExpressionEntry)_stack[_stack.Top - 2]).Name = temp;

                        var sb = new CppGenerationBuffer();
                        AppendLine();
                        sb.Append("(intptr_t)&");
                        sb.Append(_writer.GetCppTypeName(thunkMethod.OwningType));
                        sb.Append("::");
                        sb.Append(_writer.GetCppMethodName(thunkMethod));

                        PushExpression(StackValueKind.NativeInt, sb.ToString());
                    }
                }
            }

            if (needNewLine)
                AppendLine();

            if (callViaSlot || delegateInvoke)
            {
                ExpressionEntry v = (ExpressionEntry)_stack[_stack.Top - (methodSignature.Length + 1)];
                Append("(*");
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::");
                Append(delegateInvoke ? "__invoke__" : "__getslot__");
                Append(_writer.GetCppMethodName(method));
                Append("(");
                Append(v);
                Append("))");

                if (delegateInvoke)
                {
                    v.Name =
                        "((" + _writer.GetCppSignatureTypeName(GetWellKnownType(WellKnownType.MulticastDelegate)) + ")" +
                            v.Name + ")->m_firstParameter";
                }
            }
            else if (callViaInterfaceDispatch)
            {
                Append("((");
                Append(_writer.GetCppMethodName(method));
                Append(")");
                ExpressionEntry v = (ExpressionEntry)_stack.Pop();
                Append(v);
                Append(")");
            }
            else
            {
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::");
                Append(_writer.GetCppMethodName(method));
            }

            TypeDesc thisArgument = null;
            Append("(");
            if (opcode == ILOpcode.newobj)
            {
                Append("(");
                if (retType.IsValueType)
                {
                    Append(_writer.GetCppSignatureTypeName(retType.MakeByRefType()));
                    Append(")");
                    Append("&" + temp);
                }
                else
                {
                    Append(_writer.GetCppSignatureTypeName(retType));
                    Append(")");
                    Append(temp);
                }
                if (methodSignature.Length > 0)
                    Append(", ");
            }
            else
            {
                if (!methodSignature.IsStatic)
                {
                    thisArgument = owningType;
                    if (thisArgument.IsValueType)
                        thisArgument = thisArgument.MakeByRefType();
                }
            }
            PassCallArguments(methodSignature, thisArgument);
            Append(")");

            if (temp != null)
            {
                Debug.Assert(retKind != StackValueKind.Unknown, "Valid return type");
                PushExpression(retKind, temp, retType);
            }
            AppendSemicolon();
        }
Example #28
0
        private void ImportCall(ILOpcode opcode, int token)
        {
            bool callViaSlot = false;
            bool delegateInvoke = false;
            DelegateInfo delegateInfo = null;
            bool mdArrayCreate = false;

            MethodDesc method = (MethodDesc)_methodIL.GetObject(token);

            if (method.IsIntrinsic)
            {
                if (ImportIntrinsicCall(method))
                    return;
            }

            TypeDesc constrained = null;
            if (opcode != ILOpcode.newobj)
            {
                if ((_pendingPrefix & Prefix.Constrained) != 0 && opcode == ILOpcode.callvirt)
                {
                    _pendingPrefix &= ~Prefix.Constrained;
                    constrained = _constrained;

                    // TODO:
                    throw new NotImplementedException();
                }
            }

            TypeDesc owningType = method.OwningType;

            TypeDesc retType = null;

            {
                if (opcode == ILOpcode.newobj)
                    retType = owningType;

                if (opcode == ILOpcode.newobj)
                {
                    if (owningType.IsString)
                    {
                        // String constructors actually look like regular method calls
                        method = method.GetStringInitializer();
                        opcode = ILOpcode.call;

                        // WORKAROUND: the static method expects an extra arg
                        // Annoyingly, it needs to be before all the others
                        if (_stackTop >= _stack.Length)
                            Array.Resize(ref _stack, 2 * _stackTop + 3);
                        for (int i = _stackTop - 1; i > _stackTop - method.Signature.Length; i--)
                            _stack[i + 1] = _stack[i];
                        _stackTop++;
                        _stack[_stackTop - method.Signature.Length] =
                            new StackValue { Kind = StackValueKind.ObjRef, Value = new Value("0") };
                    }
                    else if (owningType.IsArray)
                    {
                        mdArrayCreate = true;
                    }
                    else if (owningType.IsDelegate)
                    {
                        delegateInfo = _compilation.GetDelegateCtor((MethodDesc)_stack[_stackTop - 1].Value.Aux);
                        method = delegateInfo.Ctor;
                    }
                }
                else
                if (owningType.IsDelegate)
                {
                    if (method.Name == "Invoke")
                    {
                        opcode = ILOpcode.call;
                        delegateInvoke = true;
                    }
                }
            }

            if (opcode == ILOpcode.callvirt)
            {
                // TODO: Null checks

                if (method.IsVirtual)
                {
                    // TODO: Full resolution of virtual methods
                    if (!method.IsNewSlot)
                        throw new NotImplementedException();

                    // TODO: Interface calls
                    if (method.OwningType.IsInterface)
                        throw new NotImplementedException();

                    _dependencies.Add(_nodeFactory.VirtualMethodUse(method));

                    callViaSlot = true;
                }
            }

            if (!callViaSlot && !delegateInvoke && !mdArrayCreate)
                AddMethodReference(method);

            if (opcode == ILOpcode.newobj)
                AddTypeReference(retType, true);

            var methodSignature = method.Signature;

            if (retType == null)
                retType = methodSignature.ReturnType;

            string temp = null;
            StackValueKind retKind = StackValueKind.Unknown;

            if (!retType.IsVoid)
            {
                retKind = GetStackValueKind(retType);
                temp = NewTempName();

                Append(GetStackValueKindCPPTypeName(retKind, retType));
                Append(" ");
                Append(temp);
                if (retType.IsValueType && opcode == ILOpcode.newobj)
                {
                    Append(";");
                }
                else
                {
                    Append("=");

                    if (retType.IsPointer)
                    {
                        Append("(intptr_t)");
                    }
                }
            }

            if (opcode == ILOpcode.newobj && !mdArrayCreate)
            {
                if (!retType.IsValueType)
                {
                    Append("__allocate_object(");
                    Append(_writer.GetCppTypeName(retType));
                    Append("::__getMethodTable())");
                    Finish();

                    if (delegateInfo != null && delegateInfo.ShuffleThunk != null)
                    {
                        AddMethodReference(delegateInfo.ShuffleThunk);

                        _stack[_stackTop - 2].Value.Name = temp;

                        StringBuilder sb = new StringBuilder();
                        sb.Append("(intptr_t)&");
                        sb.Append(_writer.GetCppTypeName(delegateInfo.ShuffleThunk.OwningType));
                        sb.Append("::");
                        sb.Append(_writer.GetCppMethodName(delegateInfo.ShuffleThunk));

                        Push(StackValueKind.NativeInt, new Value(sb.ToString()), null);
                    }
                }
            }

            if (callViaSlot || delegateInvoke)
            {
                Append("(*");
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::");
                Append(delegateInvoke ? "__invoke__" : "__getslot__");
                Append(_writer.GetCppMethodName(method));
                Append("(");
                Append(_stack[_stackTop - (methodSignature.Length + 1)].Value.Name);
                Append("))");

                if (delegateInvoke)
                {
                    _stack[_stackTop - (methodSignature.Length + 1)].Value.Name =
                        "((" + _writer.GetCppSignatureTypeName(GetWellKnownType(WellKnownType.MulticastDelegate)) + ")" +
                            _stack[_stackTop - (methodSignature.Length + 1)].Value.Name + ")->m_firstParameter";
                }
            }
            else if (mdArrayCreate)
            {
                Append("RhNewMDArray");
            }
            else
            {
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::");
                Append(_writer.GetCppMethodName(method));
            }

            TypeDesc thisArgument = null;
            Append("(");
            if (mdArrayCreate)
            {
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::__getMethodTable(), ");
                Append(IntToString(((ArrayType)method.OwningType).Rank));
                Append(", ");
            }
            else if (opcode == ILOpcode.newobj)
            {
                Append("(");
                if (retType.IsValueType)
                {
                    Append(_writer.GetCppSignatureTypeName(retType.MakeByRefType()));
                    Append(")");
                    Append("&" + temp);
                }
                else
                {
                    Append(_writer.GetCppSignatureTypeName(retType));
                    Append(")");
                    Append(temp);
                }
                if (methodSignature.Length > 0)
                    Append(", ");
            }
            else
            {
                if (!methodSignature.IsStatic)
                {
                    thisArgument = owningType;
                    if (thisArgument.IsValueType)
                        thisArgument = thisArgument.MakeByRefType();
                }
            }
            PassCallArguments(methodSignature, thisArgument);
            Append(")");

            if (temp != null)
                Push(retKind, new Value(temp), retType);
            Finish();
        }
Example #29
0
        public void Emit(ILOpcode opcode, ILCodeLabel label)
        {
            Debug.Assert(opcode == ILOpcode.br || opcode == ILOpcode.brfalse ||
                opcode == ILOpcode.brtrue || opcode == ILOpcode.beq ||
                opcode == ILOpcode.bge || opcode == ILOpcode.bgt ||
                opcode == ILOpcode.ble || opcode == ILOpcode.blt ||
                opcode == ILOpcode.bne_un || opcode == ILOpcode.bge_un ||
                opcode == ILOpcode.bgt_un || opcode == ILOpcode.ble_un ||
                opcode == ILOpcode.blt_un || opcode == ILOpcode.leave);

            Emit(opcode);
            _offsetsNeedingPatching.Add(new LabelAndOffset(label, _length));
            EmitUInt32(4);
        }
Example #30
0
        private void ImportCall(ILOpcode opcode, int token)
        {
            bool callViaSlot = false;
            bool delegateInvoke = false;
            DelegateCreationInfo delegateInfo = null;
            bool mdArrayCreate = false;

            MethodDesc method = (MethodDesc)_methodIL.GetObject(token);

            if (method.IsIntrinsic)
            {
                if (ImportIntrinsicCall(method))
                    return;
            }

            TypeDesc constrained = null;
            if (opcode != ILOpcode.newobj)
            {
                if ((_pendingPrefix & Prefix.Constrained) != 0 && opcode == ILOpcode.callvirt)
                {
                    _pendingPrefix &= ~Prefix.Constrained;
                    constrained = _constrained;

                    bool forceUseRuntimeLookup;
                    MethodDesc directMethod = constrained.GetClosestMetadataType().TryResolveConstraintMethodApprox(method.OwningType, method, out forceUseRuntimeLookup);
                    if (directMethod == null || forceUseRuntimeLookup)
                        throw new NotImplementedException();

                    method = directMethod;
                    opcode = ILOpcode.call;
                }
            }

            TypeDesc owningType = method.OwningType;

            TypeDesc retType = null;

            {
                if (opcode == ILOpcode.newobj)
                    retType = owningType;

                if (opcode == ILOpcode.newobj)
                {
                    if (owningType.IsString)
                    {
                        // String constructors actually look like regular method calls
                        method = method.GetStringInitializer();
                        opcode = ILOpcode.call;

                        // WORKAROUND: the static method expects an extra arg
                        // Annoyingly, it needs to be before all the others
                        _stack.InsertAt(new ExpressionEntry(StackValueKind.ObjRef, "0"), _stack.Top - method.Signature.Length + 1);
                    }
                    else if (owningType.IsArray)
                    {
                        mdArrayCreate = true;
                    }
                    else if (owningType.IsDelegate)
                    {
                        delegateInfo = _compilation.GetDelegateCtor(owningType, ((LdTokenEntry<MethodDesc>)_stack.Peek()).LdToken);
                        method = delegateInfo.Constructor.Method;
                    }
                }
                else
                if (owningType.IsDelegate)
                {
                    if (method.Name == "Invoke")
                    {
                        opcode = ILOpcode.call;
                        delegateInvoke = true;
                    }
                }
            }

            if (opcode == ILOpcode.callvirt)
            {
                // TODO: Null checks

                if (method.IsVirtual)
                {
                    // TODO: Full resolution of virtual methods
                    if (!method.IsNewSlot)
                        throw new NotImplementedException();

                    // TODO: Interface calls
                    if (method.OwningType.IsInterface)
                        throw new NotImplementedException();

                    _dependencies.Add(_nodeFactory.VirtualMethodUse(method));

                    callViaSlot = true;
                }
            }

            if (!callViaSlot && !delegateInvoke && !mdArrayCreate)
                AddMethodReference(method);

            if (opcode == ILOpcode.newobj)
                AddTypeReference(retType, true);

            var methodSignature = method.Signature;

            if (retType == null)
                retType = methodSignature.ReturnType;

            string temp = null;
            StackValueKind retKind = StackValueKind.Unknown;
            var needNewLine = false;

            if (!retType.IsVoid)
            {
                retKind = GetStackValueKind(retType);
                temp = NewTempName();

                AppendLine();
                Append(GetStackValueKindCPPTypeName(retKind, retType));
                Append(" ");
                Append(temp);
                if (retType.IsValueType && opcode == ILOpcode.newobj)
                {
                    Append(";");
                    needNewLine = true;
                }
                else
                {
                    Append(" = ");

                    if (retType.IsPointer)
                    {
                        Append("(intptr_t)");
                    }
                }
            }
            else
            {
                needNewLine = true;
            }

            if (opcode == ILOpcode.newobj && !mdArrayCreate)
            {
                if (!retType.IsValueType)
                {
                    // We do not reset needNewLine since we still need for the next statement.
                    if (needNewLine)
                        AppendLine();
                    Append("__allocate_object(");
                    Append(_writer.GetCppTypeName(retType));
                    Append("::__getMethodTable())");
                    AppendSemicolon();
                    needNewLine = true;

                    if (delegateInfo != null && delegateInfo.Thunk != null)
                    {
                        MethodDesc thunkMethod = delegateInfo.Thunk.Method;
                        AddMethodReference(thunkMethod);

                        // Update stack with new name.
                        ((ExpressionEntry) _stack[_stack.Top - 2]).Name = temp;

                        var sb = new CppGenerationBuffer();
                        AppendLine();
                        sb.Append("(intptr_t)&");
                        sb.Append(_writer.GetCppTypeName(thunkMethod.OwningType));
                        sb.Append("::");
                        sb.Append(_writer.GetCppMethodName(thunkMethod));

                        PushExpression(StackValueKind.NativeInt, sb.ToString());
                    }
                }
            }

            if (needNewLine)
                AppendLine();

            if (callViaSlot || delegateInvoke)
            {
                // While waiting for C# return by ref, get this reference and insert it back
                // if it is a delegate invoke.
                ExpressionEntry v = (ExpressionEntry) _stack[_stack.Top - (methodSignature.Length + 1)];
                Append("(*");
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::");
                Append(delegateInvoke ? "__invoke__" : "__getslot__");
                Append(_writer.GetCppMethodName(method));
                Append("(");
                Append(v);
                Append("))");

                if (delegateInvoke)
                {
                    v.Name =
                        "((" + _writer.GetCppSignatureTypeName(GetWellKnownType(WellKnownType.MulticastDelegate)) + ")" +
                            v.Name + ")->m_firstParameter";
                }
            }
            else if (mdArrayCreate)
            {
                Append("RhNewMDArray");
            }
            else
            {
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::");
                Append(_writer.GetCppMethodName(method));
            }

            TypeDesc thisArgument = null;
            Append("(");
            if (mdArrayCreate)
            {
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::__getMethodTable(), ");
                Append(((ArrayType)method.OwningType).Rank.ToStringInvariant());
                Append(", ");
            }
            else if (opcode == ILOpcode.newobj)
            {
                Append("(");
                if (retType.IsValueType)
                {
                    Append(_writer.GetCppSignatureTypeName(retType.MakeByRefType()));
                    Append(")");
                    Append("&" + temp);
                }
                else
                {
                    Append(_writer.GetCppSignatureTypeName(retType));
                    Append(")");
                    Append(temp);
                }
                if (methodSignature.Length > 0)
                    Append(", ");
            }
            else
            {
                if (!methodSignature.IsStatic)
                {
                    thisArgument = owningType;
                    if (thisArgument.IsValueType)
                        thisArgument = thisArgument.MakeByRefType();
                }
            }
            PassCallArguments(methodSignature, thisArgument);
            Append(")");

            if (temp != null)
            {
                Debug.Assert(retKind != StackValueKind.Unknown, "Valid return type");
                PushExpression(retKind, temp, retType);
            }
            AppendSemicolon();
        }
Example #31
0
        private void ImportCasting(ILOpcode opcode, int token)
        {
            TypeDesc type = (TypeDesc)_methodIL.GetObject(token);

            var value = _stack.Pop();
            PushTemp(StackValueKind.ObjRef, type);

            AddTypeReference(type, false);

            Append(opcode == ILOpcode.isinst ? "__isinst" : "__castclass");
            Append("(");
            Append(value);
            Append(", ");
            Append(_writer.GetCppTypeName(type));
            Append("::__getMethodTable())");
            AppendSemicolon();
        }
Example #32
0
        private void ImportUnbox(int token, ILOpcode opCode)
        {
            var type = ResolveTypeToken(token);

            var obj = _stack.Pop();

            if (opCode == ILOpcode.unbox)
            {
                PushTemp(StackValueKind.ByRef, type.MakeByRefType());
            }
            else
            {
                PushTemp(GetStackValueKind(type), type);
            }

            if (type.IsValueType)
            {
                // TODO: Unbox of nullable types
                if (type.IsNullable)
                    throw new NotImplementedException();

                if (opCode == ILOpcode.unbox_any)
                {
                    string typeName = GetStackValueKindCPPTypeName(GetStackValueKind(type), type);
                    Append("*(");
                    Append(typeName);
                    Append("*)");
                }

                Append("(");
                Append(_writer.GetCppSignatureTypeName(type));
                Append("*)");
                Append("((void **)");
                Append(obj);
                Append("+1)");
            }
            else
            {
                // TODO: Cast
                Append(obj);
            }

            AppendSemicolon();
        }
Example #33
0
        private void ImportCasting(ILOpcode opcode, int token)
        {
            TypeDesc type = (TypeDesc)_methodIL.GetObject(token);

            if (type.IsInterface || type.IsArray)
                throw new NotImplementedException();

            var value = Pop();
            PushTemp(StackValueKind.ObjRef, type);

            Append(opcode == ILOpcode.isinst ? "__isinst_class" : "__castclass_class");
            Append("(");
            Append(value.Value.Name);
            Append(", ");
            Append(_writer.GetCppTypeName(type));
            Append("::__getMethodTable())");
            Finish();
        }
Example #34
0
        private void ImportCompareOperation(ILOpcode opcode)
        {
            var op1 = _stack.Pop();
            var op2 = _stack.Pop();

            // StackValueKind is carefully ordered to make this work (assuming the IL is valid)
            StackValueKind kind;

            if (op1.Kind > op2.Kind)
            {
                kind = op1.Kind;
            }
            else
            {
                kind = op2.Kind;
            }

            PushTemp(StackValueKind.Int32);

            string op = null;
            bool unsigned = false;
            bool inverted = false;
            switch (opcode)
            {
                case ILOpcode.ceq: op = "=="; break;
                case ILOpcode.cgt: op = ">"; break;
                case ILOpcode.clt: op = "<"; break;
                case ILOpcode.cgt_un:
                    if (kind == StackValueKind.Float)
                    {
                        op = "<="; inverted = true;
                    }
                    else
                    {
                        op = ">";
                        if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
                            unsigned = true;
                    }
                    break;
                case ILOpcode.clt_un:
                    if (kind == StackValueKind.Float)
                    {
                        op = ">="; inverted = true;
                    }
                    else
                    {
                        op = "<";
                        if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
                            unsigned = true;
                    }
                    break;
            }

            if (kind == StackValueKind.ByRef)
                unsigned = false;

            if (inverted)
            {
                Append("!(");
            }
            if (unsigned)
            {
                Append("(u");
                Append(GetStackValueKindCPPTypeName(kind));
                Append(")");
            }
            Append(op2);
            Append(" ");
            Append(op);
            Append(" ");
            if (unsigned)
            {
                Append("(u");
                Append(GetStackValueKindCPPTypeName(kind));
                Append(")");
            }
            Append(op1);
            if (inverted)
            {
                Append(")");
            }
            AppendSemicolon();
        }
Example #35
0
        private void ImportBasicBlock(BasicBlock basicBlock)
        {
            _currentBasicBlock = basicBlock;
            _currentOffset     = basicBlock.StartOffset;

            for (;;)
            {
                StartImportingInstruction();

                ILOpcode opCode = (ILOpcode)ReadILByte();

again:
                switch (opCode)
                {
                case ILOpcode.nop:
                    ImportNop();
                    break;

                case ILOpcode.break_:
                    ImportBreak();
                    break;

                case ILOpcode.ldarg_0:
                case ILOpcode.ldarg_1:
                case ILOpcode.ldarg_2:
                case ILOpcode.ldarg_3:
                    ImportLoadVar(opCode - ILOpcode.ldarg_0, true);
                    break;

                case ILOpcode.ldloc_0:
                case ILOpcode.ldloc_1:
                case ILOpcode.ldloc_2:
                case ILOpcode.ldloc_3:
                    ImportLoadVar(opCode - ILOpcode.ldloc_0, false);
                    break;

                case ILOpcode.stloc_0:
                case ILOpcode.stloc_1:
                case ILOpcode.stloc_2:
                case ILOpcode.stloc_3:
                    ImportStoreVar(opCode - ILOpcode.stloc_0, false);
                    break;

                case ILOpcode.ldarg_s:
                    ImportLoadVar(ReadILByte(), true);
                    break;

                case ILOpcode.ldarga_s:
                    ImportAddressOfVar(ReadILByte(), true);
                    break;

                case ILOpcode.starg_s:
                    ImportStoreVar(ReadILByte(), true);
                    break;

                case ILOpcode.ldloc_s:
                    ImportLoadVar(ReadILByte(), false);
                    break;

                case ILOpcode.ldloca_s:
                    ImportAddressOfVar(ReadILByte(), false);
                    break;

                case ILOpcode.stloc_s:
                    ImportStoreVar(ReadILByte(), false);
                    break;

                case ILOpcode.ldnull:
                    ImportLoadNull();
                    break;

                case ILOpcode.ldc_i4_m1:
                    ImportLoadInt(-1, StackValueKind.Int32);
                    break;

                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:
                    ImportLoadInt(opCode - ILOpcode.ldc_i4_0, StackValueKind.Int32);
                    break;

                case ILOpcode.ldc_i4_s:
                    ImportLoadInt((sbyte)ReadILByte(), StackValueKind.Int32);
                    break;

                case ILOpcode.ldc_i4:
                    ImportLoadInt((int)ReadILUInt32(), StackValueKind.Int32);
                    break;

                case ILOpcode.ldc_i8:
                    ImportLoadInt((long)ReadILUInt64(), StackValueKind.Int64);
                    break;

                case ILOpcode.ldc_r4:
                    ImportLoadFloat(ReadILFloat());
                    break;

                case ILOpcode.ldc_r8:
                    ImportLoadFloat(ReadILDouble());
                    break;

                case ILOpcode.dup:
                    ImportDup();
                    break;

                case ILOpcode.pop:
                    ImportPop();
                    break;

                case ILOpcode.jmp:
                    ImportJmp(ReadILToken());
                    EndImportingInstruction();
                    return;

                case ILOpcode.call:
                    ImportCall(opCode, ReadILToken());
                    break;

                case ILOpcode.calli:
                    ImportCalli(ReadILToken());
                    break;

                case ILOpcode.ret:
                    ImportReturn();
                    EndImportingInstruction();
                    return;

                case ILOpcode.br_s:
                case ILOpcode.brfalse_s:
                case ILOpcode.brtrue_s:
                case ILOpcode.beq_s:
                case ILOpcode.bge_s:
                case ILOpcode.bgt_s:
                case ILOpcode.ble_s:
                case ILOpcode.blt_s:
                case ILOpcode.bne_un_s:
                case ILOpcode.bge_un_s:
                case ILOpcode.bgt_un_s:
                case ILOpcode.ble_un_s:
                case ILOpcode.blt_un_s:
                {
                    int delta = (sbyte)ReadILByte();
                    ImportBranch(opCode + (ILOpcode.br - ILOpcode.br_s),
                                 _basicBlocks[_currentOffset + delta], (opCode != ILOpcode.br_s) ? _basicBlocks[_currentOffset] : null);
                }
                    EndImportingInstruction();
                    return;

                case ILOpcode.br:
                case ILOpcode.brfalse:
                case ILOpcode.brtrue:
                case ILOpcode.beq:
                case ILOpcode.bge:
                case ILOpcode.bgt:
                case ILOpcode.ble:
                case ILOpcode.blt:
                case ILOpcode.bne_un:
                case ILOpcode.bge_un:
                case ILOpcode.bgt_un:
                case ILOpcode.ble_un:
                case ILOpcode.blt_un:
                {
                    int delta = (int)ReadILUInt32();
                    ImportBranch(opCode,
                                 _basicBlocks[_currentOffset + delta], (opCode != ILOpcode.br) ? _basicBlocks[_currentOffset] : null);
                }
                    EndImportingInstruction();
                    return;

                case ILOpcode.switch_:
                {
                    uint  count    = ReadILUInt32();
                    int   jmpBase  = _currentOffset + (int)(4 * count);
                    int[] jmpDelta = new int[count];
                    for (uint i = 0; i < count; i++)
                    {
                        jmpDelta[i] = (int)ReadILUInt32();
                    }

                    ImportSwitchJump(jmpBase, jmpDelta, _basicBlocks[_currentOffset]);
                }
                    EndImportingInstruction();
                    return;

                case ILOpcode.ldind_i1:
                    ImportLoadIndirect(WellKnownType.SByte);
                    break;

                case ILOpcode.ldind_u1:
                    ImportLoadIndirect(WellKnownType.Byte);
                    break;

                case ILOpcode.ldind_i2:
                    ImportLoadIndirect(WellKnownType.Int16);
                    break;

                case ILOpcode.ldind_u2:
                    ImportLoadIndirect(WellKnownType.UInt16);
                    break;

                case ILOpcode.ldind_i4:
                    ImportLoadIndirect(WellKnownType.Int32);
                    break;

                case ILOpcode.ldind_u4:
                    ImportLoadIndirect(WellKnownType.UInt32);
                    break;

                case ILOpcode.ldind_i8:
                    ImportLoadIndirect(WellKnownType.Int64);
                    break;

                case ILOpcode.ldind_i:
                    ImportLoadIndirect(WellKnownType.IntPtr);
                    break;

                case ILOpcode.ldind_r4:
                    ImportLoadIndirect(WellKnownType.Single);
                    break;

                case ILOpcode.ldind_r8:
                    ImportLoadIndirect(WellKnownType.Double);
                    break;

                case ILOpcode.ldind_ref:
                    ImportLoadIndirect(null);
                    break;

                case ILOpcode.stind_ref:
                    ImportStoreIndirect(null);
                    break;

                case ILOpcode.stind_i1:
                    ImportStoreIndirect(WellKnownType.SByte);
                    break;

                case ILOpcode.stind_i2:
                    ImportStoreIndirect(WellKnownType.Int16);
                    break;

                case ILOpcode.stind_i4:
                    ImportStoreIndirect(WellKnownType.Int32);
                    break;

                case ILOpcode.stind_i8:
                    ImportStoreIndirect(WellKnownType.Int64);
                    break;

                case ILOpcode.stind_r4:
                    ImportStoreIndirect(WellKnownType.Single);
                    break;

                case ILOpcode.stind_r8:
                    ImportStoreIndirect(WellKnownType.Double);
                    break;

                case ILOpcode.add:
                case ILOpcode.sub:
                case ILOpcode.mul:
                case ILOpcode.div:
                case ILOpcode.div_un:
                case ILOpcode.rem:
                case ILOpcode.rem_un:
                case ILOpcode.and:
                case ILOpcode.or:
                case ILOpcode.xor:
                    ImportBinaryOperation(opCode);
                    break;

                case ILOpcode.shl:
                case ILOpcode.shr:
                case ILOpcode.shr_un:
                    ImportShiftOperation(opCode);
                    break;

                case ILOpcode.neg:
                case ILOpcode.not:
                    ImportUnaryOperation(opCode);
                    break;

                case ILOpcode.conv_i1:
                    ImportConvert(WellKnownType.SByte, false, false);
                    break;

                case ILOpcode.conv_i2:
                    ImportConvert(WellKnownType.Int16, false, false);
                    break;

                case ILOpcode.conv_i4:
                    ImportConvert(WellKnownType.Int32, false, false);
                    break;

                case ILOpcode.conv_i8:
                    ImportConvert(WellKnownType.Int64, false, false);
                    break;

                case ILOpcode.conv_r4:
                    ImportConvert(WellKnownType.Single, false, false);
                    break;

                case ILOpcode.conv_r8:
                    ImportConvert(WellKnownType.Double, false, false);
                    break;

                case ILOpcode.conv_u4:
                    ImportConvert(WellKnownType.UInt32, false, false);
                    break;

                case ILOpcode.conv_u8:
                    ImportConvert(WellKnownType.UInt64, false, true);
                    break;

                case ILOpcode.callvirt:
                    ImportCall(opCode, ReadILToken());
                    break;

                case ILOpcode.cpobj:
                    ImportCpOpj(ReadILToken());
                    break;

                case ILOpcode.ldobj:
                    ImportLoadIndirect(ReadILToken());
                    break;

                case ILOpcode.ldstr:
                    ImportLoadString(ReadILToken());
                    break;

                case ILOpcode.newobj:
                    ImportCall(opCode, ReadILToken());
                    break;

                case ILOpcode.castclass:
                case ILOpcode.isinst:
                    ImportCasting(opCode, ReadILToken());
                    break;

                case ILOpcode.conv_r_un:
                    ImportConvert(WellKnownType.Double, false, true);
                    break;

                case ILOpcode.unbox:
                    ImportUnbox(ReadILToken(), opCode);
                    break;

                case ILOpcode.throw_:
                    ImportThrow();
                    EndImportingInstruction();
                    return;

                case ILOpcode.ldfld:
                    ImportLoadField(ReadILToken(), false);
                    break;

                case ILOpcode.ldflda:
                    ImportAddressOfField(ReadILToken(), false);
                    break;

                case ILOpcode.stfld:
                    ImportStoreField(ReadILToken(), false);
                    break;

                case ILOpcode.ldsfld:
                    ImportLoadField(ReadILToken(), true);
                    break;

                case ILOpcode.ldsflda:
                    ImportAddressOfField(ReadILToken(), true);
                    break;

                case ILOpcode.stsfld:
                    ImportStoreField(ReadILToken(), true);
                    break;

                case ILOpcode.stobj:
                    ImportStoreIndirect(ReadILToken());
                    break;

                case ILOpcode.conv_ovf_i1_un:
                    ImportConvert(WellKnownType.SByte, true, true);
                    break;

                case ILOpcode.conv_ovf_i2_un:
                    ImportConvert(WellKnownType.Int16, true, true);
                    break;

                case ILOpcode.conv_ovf_i4_un:
                    ImportConvert(WellKnownType.Int32, true, true);
                    break;

                case ILOpcode.conv_ovf_i8_un:
                    ImportConvert(WellKnownType.Int64, true, true);
                    break;

                case ILOpcode.conv_ovf_u1_un:
                    ImportConvert(WellKnownType.Byte, true, true);
                    break;

                case ILOpcode.conv_ovf_u2_un:
                    ImportConvert(WellKnownType.UInt16, true, true);
                    break;

                case ILOpcode.conv_ovf_u4_un:
                    ImportConvert(WellKnownType.UInt32, true, true);
                    break;

                case ILOpcode.conv_ovf_u8_un:
                    ImportConvert(WellKnownType.UInt64, true, true);
                    break;

                case ILOpcode.conv_ovf_i_un:
                    ImportConvert(WellKnownType.IntPtr, true, true);
                    break;

                case ILOpcode.conv_ovf_u_un:
                    ImportConvert(WellKnownType.UIntPtr, true, true);
                    break;

                case ILOpcode.box:
                    ImportBox(ReadILToken());
                    break;

                case ILOpcode.newarr:
                    ImportNewArray(ReadILToken());
                    break;

                case ILOpcode.ldlen:
                    ImportLoadLength();
                    break;

                case ILOpcode.ldelema:
                    ImportAddressOfElement(ReadILToken());
                    break;

                case ILOpcode.ldelem_i1:
                    ImportLoadElement(WellKnownType.SByte);
                    break;

                case ILOpcode.ldelem_u1:
                    ImportLoadElement(WellKnownType.Byte);
                    break;

                case ILOpcode.ldelem_i2:
                    ImportLoadElement(WellKnownType.Int16);
                    break;

                case ILOpcode.ldelem_u2:
                    ImportLoadElement(WellKnownType.UInt16);
                    break;

                case ILOpcode.ldelem_i4:
                    ImportLoadElement(WellKnownType.Int32);
                    break;

                case ILOpcode.ldelem_u4:
                    ImportLoadElement(WellKnownType.UInt32);
                    break;

                case ILOpcode.ldelem_i8:
                    ImportLoadElement(WellKnownType.Int64);
                    break;

                case ILOpcode.ldelem_i:
                    ImportLoadElement(WellKnownType.IntPtr);
                    break;

                case ILOpcode.ldelem_r4:
                    ImportLoadElement(WellKnownType.Single);
                    break;

                case ILOpcode.ldelem_r8:
                    ImportLoadElement(WellKnownType.Double);
                    break;

                case ILOpcode.ldelem_ref:
                    ImportLoadElement(null);
                    break;

                case ILOpcode.stelem_i:
                    ImportStoreElement(WellKnownType.IntPtr);
                    break;

                case ILOpcode.stelem_i1:
                    ImportStoreElement(WellKnownType.SByte);
                    break;

                case ILOpcode.stelem_i2:
                    ImportStoreElement(WellKnownType.Int16);
                    break;

                case ILOpcode.stelem_i4:
                    ImportStoreElement(WellKnownType.Int32);
                    break;

                case ILOpcode.stelem_i8:
                    ImportStoreElement(WellKnownType.Int64);
                    break;

                case ILOpcode.stelem_r4:
                    ImportStoreElement(WellKnownType.Single);
                    break;

                case ILOpcode.stelem_r8:
                    ImportStoreElement(WellKnownType.Double);
                    break;

                case ILOpcode.stelem_ref:
                    ImportStoreElement(null);
                    break;

                case ILOpcode.ldelem:
                    ImportLoadElement(ReadILToken());
                    break;

                case ILOpcode.stelem:
                    ImportStoreElement(ReadILToken());
                    break;

                case ILOpcode.unbox_any:
                    ImportUnbox(ReadILToken(), opCode);
                    break;

                case ILOpcode.conv_ovf_i1:
                    ImportConvert(WellKnownType.SByte, true, false);
                    break;

                case ILOpcode.conv_ovf_u1:
                    ImportConvert(WellKnownType.Byte, true, false);
                    break;

                case ILOpcode.conv_ovf_i2:
                    ImportConvert(WellKnownType.Int16, true, false);
                    break;

                case ILOpcode.conv_ovf_u2:
                    ImportConvert(WellKnownType.UInt16, true, false);
                    break;

                case ILOpcode.conv_ovf_i4:
                    ImportConvert(WellKnownType.Int32, true, false);
                    break;

                case ILOpcode.conv_ovf_u4:
                    ImportConvert(WellKnownType.UInt32, true, false);
                    break;

                case ILOpcode.conv_ovf_i8:
                    ImportConvert(WellKnownType.Int64, true, false);
                    break;

                case ILOpcode.conv_ovf_u8:
                    ImportConvert(WellKnownType.UInt64, true, false);
                    break;

                case ILOpcode.refanyval:
                    ImportRefAnyVal(ReadILToken());
                    break;

                case ILOpcode.ckfinite:
                    ImportCkFinite();
                    break;

                case ILOpcode.mkrefany:
                    ImportMkRefAny(ReadILToken());
                    break;

                case ILOpcode.ldtoken:
                    ImportLdToken(ReadILToken());
                    break;

                case ILOpcode.conv_u2:
                    ImportConvert(WellKnownType.UInt16, false, false);
                    break;

                case ILOpcode.conv_u1:
                    ImportConvert(WellKnownType.Byte, false, false);
                    break;

                case ILOpcode.conv_i:
                    ImportConvert(WellKnownType.IntPtr, false, false);
                    break;

                case ILOpcode.conv_ovf_i:
                    ImportConvert(WellKnownType.IntPtr, true, false);
                    break;

                case ILOpcode.conv_ovf_u:
                    ImportConvert(WellKnownType.UIntPtr, true, false);
                    break;

                case ILOpcode.add_ovf:
                case ILOpcode.add_ovf_un:
                case ILOpcode.mul_ovf:
                case ILOpcode.mul_ovf_un:
                case ILOpcode.sub_ovf:
                case ILOpcode.sub_ovf_un:
                    ImportBinaryOperation(opCode);
                    break;

                case ILOpcode.endfinally:     //both endfinally and endfault
                    ImportEndFinally();
                    EndImportingInstruction();
                    return;

                case ILOpcode.leave:
                {
                    int delta = (int)ReadILUInt32();
                    ImportLeave(_basicBlocks[_currentOffset + delta]);
                }
                    EndImportingInstruction();
                    return;

                case ILOpcode.leave_s:
                {
                    int delta = (sbyte)ReadILByte();
                    ImportLeave(_basicBlocks[_currentOffset + delta]);
                }
                    EndImportingInstruction();
                    return;

                case ILOpcode.stind_i:
                    ImportStoreIndirect(WellKnownType.IntPtr);
                    break;

                case ILOpcode.conv_u:
                    ImportConvert(WellKnownType.UIntPtr, false, false);
                    break;

                case ILOpcode.prefix1:
                    opCode = (ILOpcode)(0x100 + ReadILByte());
                    goto again;

                case ILOpcode.arglist:
                    ImportArgList();
                    break;

                case ILOpcode.ceq:
                case ILOpcode.cgt:
                case ILOpcode.cgt_un:
                case ILOpcode.clt:
                case ILOpcode.clt_un:
                    ImportCompareOperation(opCode);
                    break;

                case ILOpcode.ldftn:
                case ILOpcode.ldvirtftn:
                    ImportLdFtn(ReadILToken(), opCode);
                    break;

                case ILOpcode.ldarg:
                    ImportLoadVar(ReadILUInt16(), true);
                    break;

                case ILOpcode.ldarga:
                    ImportAddressOfVar(ReadILUInt16(), true);
                    break;

                case ILOpcode.starg:
                    ImportStoreVar(ReadILUInt16(), true);
                    break;

                case ILOpcode.ldloc:
                    ImportLoadVar(ReadILUInt16(), false);
                    break;

                case ILOpcode.ldloca:
                    ImportAddressOfVar(ReadILUInt16(), false);
                    break;

                case ILOpcode.stloc:
                    ImportStoreVar(ReadILUInt16(), false);
                    break;

                case ILOpcode.localloc:
                    ImportLocalAlloc();
                    break;

                case ILOpcode.endfilter:
                    ImportEndFilter();
                    EndImportingInstruction();
                    return;

                case ILOpcode.unaligned:
                    ImportUnalignedPrefix(ReadILByte());
                    continue;

                case ILOpcode.volatile_:
                    ImportVolatilePrefix();
                    continue;

                case ILOpcode.tail:
                    ImportTailPrefix();
                    continue;

                case ILOpcode.initobj:
                    ImportInitObj(ReadILToken());
                    break;

                case ILOpcode.constrained:
                    ImportConstrainedPrefix(ReadILToken());
                    continue;

                case ILOpcode.cpblk:
                    ImportCpBlk();
                    break;

                case ILOpcode.initblk:
                    ImportInitBlk();
                    break;

                case ILOpcode.no:
                    ImportNoPrefix(ReadILByte());
                    continue;

                case ILOpcode.rethrow:
                    ImportRethrow();
                    EndImportingInstruction();
                    return;

                case ILOpcode.sizeof_:
                    ImportSizeOf(ReadILToken());
                    break;

                case ILOpcode.refanytype:
                    ImportRefAnyType();
                    break;

                case ILOpcode.readonly_:
                    ImportReadOnlyPrefix();
                    continue;

                default:
                    ReportInvalidInstruction(opCode);
                    EndImportingInstruction();
                    return;
                }

                EndImportingInstruction();

                // Check if control falls through the end of method.
                if (_currentOffset == _basicBlocks.Length)
                {
                    ReportFallthroughAtEndOfMethod();
                    return;
                }

                BasicBlock nextBasicBlock = _basicBlocks[_currentOffset];
                if (nextBasicBlock != null)
                {
                    ImportFallthrough(nextBasicBlock);
                    return;
                }
            }
        }
        /// <summary>
        /// Parse MIbcGroup method and return enumerable of MethodProfileData
        ///
        /// Like the AssemblyDictionary method, data is encoded via IL instructions. The format is
        ///
        /// ldtoken methodInProfileData
        /// Any series of instructions that does not include pop. Expansion data is encoded via ldstr "id"
        /// followed by a expansion specific sequence of il opcodes.
        /// pop
        /// {Repeat N times for N methods described}
        ///
        /// Extensions supported with current parser:
        ///
        /// ldstr "ExclusiveWeight"
        /// Any ldc.i4 or ldc.r4 or ldc.r8 instruction to indicate the exclusive weight
        ///
        /// ldstr "WeightedCallData"
        /// ldc.i4 <Count of methods called>
        /// Repeat <Count of methods called times>
        ///  ldtoken <Method called from this method>
        ///  ldc.i4 <Weight associated with calling the <Method called from this method>>
        ///
        /// This format is designed to be extensible to hold more data as we add new per method profile data without breaking existing parsers.
        /// </summary>
        static IEnumerable <MethodProfileData> ReadMIbcGroup(TypeSystemContext tsc, EcmaMethod method)
        {
            EcmaMethodIL             ilBody         = EcmaMethodIL.Create(method);
            MetadataLoaderForPgoData metadataLoader = new MetadataLoaderForPgoData(ilBody);

            byte[] ilBytes                       = ilBody.GetILBytes();
            int    currentOffset                 = 0;
            object methodInProgress              = null;
            object metadataNotResolvable         = new object();
            object metadataObject                = null;
            MibcGroupParseState state            = MibcGroupParseState.LookingForNextMethod;
            int    intValue                      = 0;
            int    weightedCallGraphSize         = 0;
            int    profileEntryFound             = 0;
            double exclusiveWeight               = 0;
            Dictionary <MethodDesc, int> weights = null;
            bool        processIntValue          = false;
            List <long> instrumentationDataLongs = null;

            PgoSchemaElem[] pgoSchemaData = null;

            while (currentOffset < ilBytes.Length)
            {
                ILOpcode opcode = (ILOpcode)ilBytes[currentOffset];
                if (opcode == ILOpcode.prefix1)
                {
                    opcode = 0x100 + (ILOpcode)ilBytes[currentOffset + 1];
                }
                processIntValue = false;
                switch (opcode)
                {
                case ILOpcode.ldtoken:
                {
                    uint token = BitConverter.ToUInt32(ilBytes.AsSpan(currentOffset + 1, 4));
                    if (state == MibcGroupParseState.ProcessingInstrumentationData)
                    {
                        instrumentationDataLongs.Add(token);
                    }
                    else
                    {
                        metadataObject = null;
                        try
                        {
                            metadataObject = ilBody.GetObject((int)token);
                        }
                        catch (TypeSystemException)
                        {
                            // The method being referred to may be missing. In that situation,
                            // use the metadataNotResolvable sentinel to indicate that this record should be ignored
                            metadataObject = metadataNotResolvable;
                        }
                        switch (state)
                        {
                        case MibcGroupParseState.ProcessingCallgraphToken:
                            state = MibcGroupParseState.ProcessingCallgraphWeight;
                            break;

                        case MibcGroupParseState.LookingForNextMethod:
                            methodInProgress = metadataObject;
                            state            = MibcGroupParseState.LookingForOptionalData;
                            break;

                        default:
                            state = MibcGroupParseState.LookingForOptionalData;
                            break;
                        }
                    }
                }
                break;

                case ILOpcode.ldc_r4:
                {
                    float fltValue = BitConverter.ToSingle(ilBytes.AsSpan(currentOffset + 1, 4));

                    switch (state)
                    {
                    case MibcGroupParseState.ProcessingExclusiveWeight:
                        exclusiveWeight = fltValue;
                        state           = MibcGroupParseState.LookingForOptionalData;
                        break;

                    default:
                        state = MibcGroupParseState.LookingForOptionalData;
                        break;
                    }

                    break;
                }

                case ILOpcode.ldc_r8:
                {
                    double dblValue = BitConverter.ToDouble(ilBytes.AsSpan(currentOffset + 1, 8));

                    switch (state)
                    {
                    case MibcGroupParseState.ProcessingExclusiveWeight:
                        exclusiveWeight = dblValue;
                        state           = MibcGroupParseState.LookingForOptionalData;
                        break;

                    default:
                        state = MibcGroupParseState.LookingForOptionalData;
                        break;
                    }
                    break;
                }

                case ILOpcode.ldc_i4_0:
                    intValue        = 0;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_1:
                    intValue        = 1;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_2:
                    intValue        = 2;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_3:
                    intValue        = 3;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_4:
                    intValue        = 4;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_5:
                    intValue        = 5;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_6:
                    intValue        = 6;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_7:
                    intValue        = 7;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_8:
                    intValue        = 8;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_m1:
                    intValue        = -1;
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4_s:
                    intValue        = (sbyte)ilBytes[currentOffset + 1];
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i4:
                    intValue        = BitConverter.ToInt32(ilBytes.AsSpan(currentOffset + 1, 4));
                    processIntValue = true;
                    break;

                case ILOpcode.ldc_i8:
                    if (state == MibcGroupParseState.ProcessingInstrumentationData)
                    {
                        instrumentationDataLongs.Add(BitConverter.ToInt64(ilBytes.AsSpan(currentOffset + 1, 8)));
                    }
                    break;

                case ILOpcode.ldstr:
                {
                    UInt32 userStringToken  = BitConverter.ToUInt32(ilBytes.AsSpan(currentOffset + 1, 4));
                    string optionalDataName = (string)ilBody.GetObject((int)userStringToken);
                    switch (optionalDataName)
                    {
                    case "ExclusiveWeight":
                        state = MibcGroupParseState.ProcessingExclusiveWeight;
                        break;

                    case "WeightedCallData":
                        state = MibcGroupParseState.ProcessingCallgraphCount;
                        break;

                    case "InstrumentationDataStart":
                        state = MibcGroupParseState.ProcessingInstrumentationData;
                        instrumentationDataLongs = new List <long>();
                        break;

                    case "InstrumentationDataEnd":
                        if (instrumentationDataLongs != null)
                        {
                            instrumentationDataLongs.Add(2);             // MarshalMask 2 (Type)
                            instrumentationDataLongs.Add(0);             // PgoInstrumentationKind.Done (0)
                            pgoSchemaData = PgoProcessor.ParsePgoData <TypeSystemEntityOrUnknown>(metadataLoader, instrumentationDataLongs, false).ToArray();
                        }
                        state = MibcGroupParseState.LookingForOptionalData;
                        break;

                    default:
                        state = MibcGroupParseState.LookingForOptionalData;
                        break;
                    }
                }
                break;

                case ILOpcode.pop:
                    if (methodInProgress != metadataNotResolvable)
                    {
                        profileEntryFound++;
                        if (exclusiveWeight == 0)
                        {
                            // If no exclusive weight is found assign a non zero value that assumes the order in the pgo file is significant.
                            exclusiveWeight = Math.Min(1000000.0 - profileEntryFound, 0.0) / 1000000.0;
                        }
                        MethodProfileData mibcData = new MethodProfileData((MethodDesc)methodInProgress, MethodProfilingDataFlags.ReadMethodCode, exclusiveWeight, weights, 0xFFFFFFFF, pgoSchemaData);
                        state                    = MibcGroupParseState.LookingForNextMethod;
                        exclusiveWeight          = 0;
                        weights                  = null;
                        instrumentationDataLongs = null;
                        pgoSchemaData            = null;
                        yield return(mibcData);
                    }
                    methodInProgress = null;
                    break;

                default:
                    state = MibcGroupParseState.LookingForOptionalData;
                    break;
                }

                if (processIntValue)
                {
                    switch (state)
                    {
                    case MibcGroupParseState.ProcessingExclusiveWeight:
                        exclusiveWeight = intValue;
                        state           = MibcGroupParseState.LookingForOptionalData;
                        break;

                    case MibcGroupParseState.ProcessingCallgraphCount:
                        weightedCallGraphSize = intValue;
                        weights = new Dictionary <MethodDesc, int>();
                        if (weightedCallGraphSize > 0)
                        {
                            state = MibcGroupParseState.ProcessingCallgraphToken;
                        }
                        else
                        {
                            state = MibcGroupParseState.LookingForOptionalData;
                        }
                        break;

                    case MibcGroupParseState.ProcessingCallgraphWeight:
                        if (metadataObject != metadataNotResolvable)
                        {
                            weights.Add((MethodDesc)metadataObject, intValue);
                        }
                        weightedCallGraphSize--;
                        if (weightedCallGraphSize > 0)
                        {
                            state = MibcGroupParseState.ProcessingCallgraphToken;
                        }
                        else
                        {
                            state = MibcGroupParseState.LookingForOptionalData;
                        }
                        break;

                    case MibcGroupParseState.ProcessingInstrumentationData:
                        instrumentationDataLongs.Add(intValue);
                        break;

                    default:
                        state = MibcGroupParseState.LookingForOptionalData;
                        instrumentationDataLongs = null;
                        break;
                    }
                }

                // This isn't correct if there is a switch opcode, but since we won't do that, its ok
                currentOffset += opcode.GetSize();
            }
        }
Example #37
0
        private void ImportLdFtn(int token, ILOpcode opCode)
        {
            MethodDesc method = (MethodDesc)_methodIL.GetObject(token);

            if (opCode == ILOpcode.ldvirtftn)
            {
                if (method.IsVirtual)
                    throw new NotImplementedException();
            }

            AddMethodReference(method);

            var entry = new LdTokenEntry<MethodDesc>(StackValueKind.NativeInt, NewTempName(), method);
            PushTemp(entry);
            Append("(intptr_t)&");
            Append(_writer.GetCppTypeName(method.OwningType));
            Append("::");
            Append(_writer.GetCppMethodName(method));

            AppendSemicolon();
        }
Example #38
0
        private void ImportLdFtn(int token, ILOpcode opCode)
        {
            MethodDesc method = (MethodDesc)_methodIL.GetObject(token);

            if (opCode == ILOpcode.ldvirtftn)
            {
                if (method.IsVirtual)
                    throw new NotImplementedException();
            }

            _compilation.AddMethod(method);

            PushTemp(StackValueKind.NativeInt);
            Append("(intptr_t)&");
            Append(_writer.GetCppTypeName(method.OwningType));
            Append("::");
            Append(_writer.GetCppMethodName(method));

            _stack[_stackTop - 1].Value.Aux = method;

            Finish();
        }
Example #39
0
        private void ImportCall(ILOpcode opcode, int token)
        {
            bool callViaSlot = false;
            bool delegateInvoke = false;
            DelegateInfo delegateInfo = null;
            bool mdArrayCreate = false;

            MethodDesc method = (MethodDesc)_methodIL.GetObject(token);

            var intrinsicClassification = IntrinsicMethods.GetIntrinsicMethodClassification(method);
            if (intrinsicClassification != IntrinsicMethodKind.None)
            {
                ImportIntrinsicCall(intrinsicClassification);
                return;
            }

            if (opcode == ILOpcode.calli)
                throw new NotImplementedException();

            TypeDesc constrained = null;
            if (opcode != ILOpcode.newobj)
            {
                if ((_pendingPrefix & Prefix.Constrained) != 0 && opcode == ILOpcode.callvirt)
                {
                    _pendingPrefix &= ~Prefix.Constrained;
                    constrained = _constrained;

                    // TODO:
                    throw new NotImplementedException();
                }
            }

            TypeDesc retType = null;

            {
                TypeDesc owningType = method.OwningType;
                if (opcode == ILOpcode.newobj)
                    retType = owningType;

                if (opcode == ILOpcode.newobj)
                {
                    if (owningType.IsString)
                    {
                        // String constructors actually look like regular method calls
                        method = IntrinsicMethods.GetStringInitializer(method);
                        opcode = ILOpcode.call;

                        // WORKAROUND: the static method expects an extra arg
                        // Annoyingly, it needs to be before all the others
                        if (_stackTop >= _stack.Length)
                            Array.Resize(ref _stack, 2 * _stackTop + 3);
                        for (int i = _stackTop - 1; i > _stackTop - method.Signature.Length; i--)
                            _stack[i + 1] = _stack[i];
                        _stackTop++;
                        _stack[_stackTop - method.Signature.Length] =
                            new StackValue { Kind = StackValueKind.ObjRef, Value = new Value("0") };
                    }
                    else if (owningType.IsArray)
                    {
                        mdArrayCreate = true;
                    }
                    else if (owningType.IsDelegate)
                    {
                        delegateInfo = _compilation.GetDelegateCtor((MethodDesc)_stack[_stackTop - 1].Value.Aux);
                        method = delegateInfo.Ctor;
                    }
                }
                else
                if (owningType.IsDelegate)
                {
                    if (method.Name == "Invoke")
                    {
                        opcode = ILOpcode.call;
                        delegateInvoke = true;
                    }
                }
            }

            if (opcode == ILOpcode.callvirt)
            {
                // TODO: Null checks

                if (method.IsVirtual)
                {
                    // TODO: Full resolution of virtual methods
                    if (!method.IsNewSlot)
                        throw new NotImplementedException();

                    // TODO: Interface calls
                    if (method.OwningType.IsInterface)
                        throw new NotImplementedException();

                    _compilation.AddVirtualSlot(method);

                    callViaSlot = true;
                }
            }

            if (!callViaSlot && !delegateInvoke && !mdArrayCreate)
                _compilation.AddMethod(method);

            if (opcode == ILOpcode.newobj)
                _compilation.MarkAsConstructed(retType);

            var methodSignature = method.Signature;

            if (retType == null)
                retType = methodSignature.ReturnType;

            string temp = null;
            StackValueKind retKind = StackValueKind.Unknown;

            if (!retType.IsVoid)
            {
                retKind = GetStackValueKind(retType);
                temp = NewTempName();

                Append(GetStackValueKindCPPTypeName(retKind, retType));
                Append(" ");
                Append(temp);
                if (retType.IsValueType && opcode == ILOpcode.newobj)
                {
                    Append(";");
                }
                else
                {
                    Append("=");

                    if (retType.IsPointer)
                    {
                        Append("(intptr_t)");
                    }
                }
            }

            if (opcode == ILOpcode.newobj && !mdArrayCreate)
            {
                if (!retType.IsValueType)
                {
                    _compilation.AddType(retType);

                    Append("__allocate_object(");
                    Append(_writer.GetCppTypeName(retType));
                    Append("::__getMethodTable())");
                    Finish();

                    if (delegateInfo != null && delegateInfo.ShuffleThunk != null)
                    {
                        _stack[_stackTop - 2].Value.Name = temp;

                        StringBuilder sb = new StringBuilder();
                        sb.Append("(intptr_t)&");
                        sb.Append(_writer.GetCppTypeName(delegateInfo.ShuffleThunk.OwningType));
                        sb.Append("::");
                        sb.Append(_writer.GetCppMethodName(delegateInfo.ShuffleThunk));

                        Push(StackValueKind.NativeInt, new Value(sb.ToString()), null);
                    }
                }
            }

            if (callViaSlot || delegateInvoke)
            {
                Append("(*");
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::");
                Append(delegateInvoke ? "__invoke__" : "__getslot__");
                Append(_writer.GetCppMethodName(method));
                Append("(");
                Append(_stack[_stackTop - (methodSignature.Length + 1)].Value.Name);
                Append("))");

                if (delegateInvoke)
                {
                    _stack[_stackTop - (methodSignature.Length + 1)].Value.Name =
                        "((" + _writer.GetCppSignatureTypeName(GetWellKnownType(WellKnownType.MulticastDelegate)) + ")" +
                            _stack[_stackTop - (methodSignature.Length + 1)].Value.Name + ")->m_firstParameter";
                }
            }
            else if (mdArrayCreate)
            {
                _compilation.AddType(method.OwningType);
                Append("RhNewMDArray");
            }
            else
            {
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::");
                Append(_writer.GetCppMethodName(method));
            }


            Append("(");
            int count = methodSignature.Length;
            bool hasThis = !methodSignature.IsStatic;
            if (hasThis)
                count++;
            if (mdArrayCreate)
            {
                Append(_writer.GetCppTypeName(method.OwningType));
                Append("::__getMethodTable(), ");
                Append(((ArrayType)method.OwningType).Rank.ToString());
                Append(", ");
                count--;
            }
            else if (opcode == ILOpcode.newobj)
            {
                Append("(");
                if (retType.IsValueType)
                {
                    Append(_writer.GetCppSignatureTypeName(retType.MakeByRefType()));
                    Append(")");
                    Append("&" + temp);
                }
                else
                {
                    Append(_writer.GetCppSignatureTypeName(retType));
                    Append(")");
                    Append(temp);
                }
                count--;
                if (count > 0)
                    Append(", ");
            }
            for (int i = 0; i < count; i++)
            {
                var op = _stack[_stackTop - count + i];
                int argIndex = methodSignature.Length - (count - i);
                TypeDesc argType;
                if (argIndex == -1)
                {
                    argType = method.OwningType;
                    if (argType.IsValueType)
                        argType = argType.MakeByRefType();
                }
                else
                {
                    argType = methodSignature[argIndex];
                }
                AppendCastIfNecessary(argType, op.Kind);
                Append(op.Value.Name);
                if (i != count - 1)
                    Append(", ");
            }
            _stackTop -= count;
            Append(")");

            if (temp != null)
                Push(retKind, new Value(temp), retType);
            Finish();
        }
Example #40
0
        private void ImportUnaryOperation(ILOpcode opCode)
        {
            var argument = _stack.Pop();

            PushTemp(argument.Kind, argument.Type);

            Debug.Assert((opCode == ILOpcode.neg) || (opCode == ILOpcode.not));
            Append((opCode == ILOpcode.neg) ? "-" : "~");
            Append(argument);

            AppendSemicolon();
        }
Example #41
0
        private void ImportUnaryOperation(ILOpcode opCode)
        {
            var argument = _stack.Pop();

            if (argument.Kind == StackValueKind.Float)
                throw new NotImplementedException();

            PushTemp(argument.Kind, argument.Type);

            Append((opCode == ILOpcode.neg) ? "~" : "!");
            Append(argument);

            AppendSemicolon();
        }
Example #42
0
        private void ImportBranch(ILOpcode opcode, BasicBlock target, BasicBlock fallthrough)
        {
            AppendLine();
            if (opcode != ILOpcode.br)
            {
                Append("if (");
                if (opcode == ILOpcode.brfalse || opcode == ILOpcode.brtrue)
                {
                    var op = _stack.Pop();
                    Append(op);
                    Append((opcode == ILOpcode.brtrue) ? " != 0" : " == 0");
                }
                else
                {
                    var op1 = _stack.Pop();
                    var op2 = _stack.Pop();

                    // StackValueKind is carefully ordered to make this work (assuming the IL is valid)
                    StackValueKind kind;

                    if (op1.Kind > op2.Kind)
                    {
                        kind = op1.Kind;
                    }
                    else
                    {
                        kind = op2.Kind;
                    }

                    string op = null;
                    bool unsigned = false;
                    bool inverted = false;
                    switch (opcode)
                    {
                        case ILOpcode.beq: op = "=="; break;
                        case ILOpcode.bge: op = ">="; break;
                        case ILOpcode.bgt: op = ">"; break;
                        case ILOpcode.ble: op = "<="; break;
                        case ILOpcode.blt: op = "<"; break;
                        case ILOpcode.bne_un: op = "!="; break;
                        case ILOpcode.bge_un:
                            if (kind == StackValueKind.Float)
                            {
                                op = "<"; inverted = true;
                            }
                            else
                            {
                                op = ">=";
                            }
                            if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
                                unsigned = true;
                            break;
                        case ILOpcode.bgt_un:
                            if (kind == StackValueKind.Float)
                            {
                                op = "<="; inverted = true;
                            }
                            else
                            {
                                op = ">";
                            }
                            if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
                                unsigned = true;
                            break;
                        case ILOpcode.ble_un:
                            if (kind == StackValueKind.Float)
                            {
                                op = ">"; inverted = true;
                            }
                            else
                            {
                                op = "<=";
                            }
                            if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
                                unsigned = true;
                            break;
                        case ILOpcode.blt_un:
                            if (kind == StackValueKind.Float)
                            {
                                op = ">="; inverted = true;
                            }
                            else
                            {
                                op = "<";
                            }
                            if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
                                unsigned = true;
                            break;
                    }

                    if (kind == StackValueKind.ByRef)
                        unsigned = false;

                    if (inverted)
                    {
                        Append("!(");
                    }
                    if (unsigned)
                    {
                        Append("(u");
                        Append(GetStackValueKindCPPTypeName(kind));
                        Append(")");
                    }
                    Append(op2);
                    Append(" ");
                    Append(op);
                    Append(" ");
                    if (unsigned)
                    {
                        Append("(u");
                        Append(GetStackValueKindCPPTypeName(kind));
                        Append(")");
                    }
                    Append(op1);
                    if (inverted)
                    {
                        Append(")");
                    }
                }
                Append(") ");
            }
            Append("{");
            Indent();
            ImportFallthrough(target);
            AppendLine();
            Append("goto _bb");
            Append(target.StartOffset.ToStringInvariant());
            AppendSemicolon();
            Exdent();
            AppendLine();
            Append("}");

            if (fallthrough != null)
                ImportFallthrough(fallthrough);
        }
Example #43
0
        void ImportShiftOperation(ILOpcode opcode)
        {
            var shiftAmount = Pop();
            var op = Pop();

            PushTemp(op.Kind, op.Type);

            if (opcode == ILOpcode.shr_un)
            {
                Append("(u");
                Append(GetStackValueKindCPPTypeName(op.Kind));
                Append(")");
            }
            Append(op.Value.Name);

            Append((opcode == ILOpcode.shl) ? "<<" : ">>");

            Append(shiftAmount.Value.Name);
            Finish();
        }
Example #44
0
 public void Emit(ILOpcode opcode, int token)
 {
     Emit(opcode);
     EmitUInt32(token);
 }
Example #45
0
        private void ImportBinaryOperation(ILOpcode opcode)
        {
            var op1 = _stack.Pop();
            var op2 = _stack.Pop();

            // StackValueKind is carefully ordered to make this work (assuming the IL is valid)
            StackValueKind kind;
            TypeDesc type;

            if (op1.Kind > op2.Kind)
            {
                kind = op1.Kind;
                type = op1.Type;
            }
            else
            {
                kind = op2.Kind;
                type = op2.Type;
            }

            // The one exception from the above rule
            if ((kind == StackValueKind.ByRef) &&
                    (opcode == ILOpcode.sub || opcode == ILOpcode.sub_ovf || opcode == ILOpcode.sub_ovf_un))
            {
                kind = StackValueKind.NativeInt;
                type = null;
            }

            PushTemp(kind, type);

            string op = null;
            bool unsigned = false;
            switch (opcode)
            {
                case ILOpcode.add: op = "+"; break;
                case ILOpcode.sub: op = "-"; break;
                case ILOpcode.mul: op = "*"; break;
                case ILOpcode.div: op = "/"; break;
                case ILOpcode.div_un: op = "/"; unsigned = true; break;
                case ILOpcode.rem: op = "%"; break;
                case ILOpcode.rem_un: op = "%"; unsigned = true; break;
                case ILOpcode.and: op = "&"; break;
                case ILOpcode.or: op = "|"; break;
                case ILOpcode.xor: op = "^"; break;

                // TODO: Overflow checks
                case ILOpcode.add_ovf: op = "+"; break;
                case ILOpcode.add_ovf_un: op = "+"; unsigned = true; break;
                case ILOpcode.sub_ovf: op = "-"; break;
                case ILOpcode.sub_ovf_un: op = "-"; unsigned = true; break;
                case ILOpcode.mul_ovf: op = "*"; break;
                case ILOpcode.mul_ovf_un: op = "*"; unsigned = true; break;

                default: Debug.Assert(false, "Unexpected opcode"); break;
            }

            if (unsigned)
            {
                Append("(u");
                Append(GetStackValueKindCPPTypeName(kind));
                Append(")");
            }
            Append(op2);
            Append(" ");
            Append(op);
            Append(" ");
            if (unsigned)
            {
                Append("(u");
                Append(GetStackValueKindCPPTypeName(kind));
                Append(")");
            }
            Append(op1);

            AppendSemicolon();
        }
Example #46
0
 public void Emit(ILOpcode opcode)
 {
     if ((int)opcode > 0x100)
         EmitByte((byte)ILOpcode.prefix1);
     EmitByte((byte)opcode);
 }
Example #47
0
        private void ImportShiftOperation(ILOpcode opcode)
        {
            var shiftAmount = _stack.Pop();
            var op = _stack.Pop();

            PushTemp(op.Kind, op.Type);

            if (opcode == ILOpcode.shr_un)
            {
                Append("(u");
                Append(GetStackValueKindCPPTypeName(op.Kind));
                Append(")");
            }
            Append(op);

            Append((opcode == ILOpcode.shl) ? " << " : " >> ");

            Append(shiftAmount);
            AppendSemicolon();
        }
Example #48
0
        private void FindJumpTargets()
        {
            _currentOffset = 0;

            while (_currentOffset < _ilBytes.Length)
            {
                MarkInstructionBoundary();

                ILOpcode opCode = (ILOpcode)ReadILByte();

again:
                switch (opCode)
                {
                case ILOpcode.ldarg_s:
                case ILOpcode.ldarga_s:
                case ILOpcode.starg_s:
                case ILOpcode.ldloc_s:
                case ILOpcode.ldloca_s:
                case ILOpcode.stloc_s:
                case ILOpcode.ldc_i4_s:
                case ILOpcode.unaligned:
                case ILOpcode.no:
                    SkipIL(1);
                    break;

                case ILOpcode.ldarg:
                case ILOpcode.ldarga:
                case ILOpcode.starg:
                case ILOpcode.ldloc:
                case ILOpcode.ldloca:
                case ILOpcode.stloc:
                    SkipIL(2);
                    break;

                case ILOpcode.ldc_i4:
                case ILOpcode.ldc_r4:
                    SkipIL(4);
                    break;

                case ILOpcode.ldc_i8:
                case ILOpcode.ldc_r8:
                    SkipIL(8);
                    break;

                case ILOpcode.jmp:
                case ILOpcode.call:
                case ILOpcode.calli:
                case ILOpcode.callvirt:
                case ILOpcode.cpobj:
                case ILOpcode.ldobj:
                case ILOpcode.ldstr:
                case ILOpcode.newobj:
                case ILOpcode.castclass:
                case ILOpcode.isinst:
                case ILOpcode.unbox:
                case ILOpcode.ldfld:
                case ILOpcode.ldflda:
                case ILOpcode.stfld:
                case ILOpcode.ldsfld:
                case ILOpcode.ldsflda:
                case ILOpcode.stsfld:
                case ILOpcode.stobj:
                case ILOpcode.box:
                case ILOpcode.newarr:
                case ILOpcode.ldelema:
                case ILOpcode.ldelem:
                case ILOpcode.stelem:
                case ILOpcode.unbox_any:
                case ILOpcode.refanyval:
                case ILOpcode.mkrefany:
                case ILOpcode.ldtoken:
                case ILOpcode.ldftn:
                case ILOpcode.ldvirtftn:
                case ILOpcode.initobj:
                case ILOpcode.constrained:
                case ILOpcode.sizeof_:
                    SkipIL(4);
                    break;

                case ILOpcode.prefix1:
                    opCode = (ILOpcode)(0x100 + ReadILByte());
                    goto again;

                case ILOpcode.br_s:
                case ILOpcode.leave_s:
                {
                    int delta  = (sbyte)ReadILByte();
                    int target = _currentOffset + delta;
                    if ((uint)target < (uint)_basicBlocks.Length)
                    {
                        CreateBasicBlock(target);
                    }
                    else
                    {
                        ReportInvalidBranchTarget(target);
                    }
                }
                break;

                case ILOpcode.brfalse_s:
                case ILOpcode.brtrue_s:
                case ILOpcode.beq_s:
                case ILOpcode.bge_s:
                case ILOpcode.bgt_s:
                case ILOpcode.ble_s:
                case ILOpcode.blt_s:
                case ILOpcode.bne_un_s:
                case ILOpcode.bge_un_s:
                case ILOpcode.bgt_un_s:
                case ILOpcode.ble_un_s:
                case ILOpcode.blt_un_s:
                {
                    int delta  = (sbyte)ReadILByte();
                    int target = _currentOffset + delta;
                    if ((uint)target < (uint)_basicBlocks.Length)
                    {
                        CreateBasicBlock(target);
                    }
                    else
                    {
                        ReportInvalidBranchTarget(target);
                    }
                    CreateBasicBlock(_currentOffset);
                }
                break;

                case ILOpcode.br:
                case ILOpcode.leave:
                {
                    int delta  = (int)ReadILUInt32();
                    int target = _currentOffset + delta;
                    if ((uint)target < (uint)_basicBlocks.Length)
                    {
                        CreateBasicBlock(target);
                    }
                    else
                    {
                        ReportInvalidBranchTarget(target);
                    }
                }
                break;

                case ILOpcode.brfalse:
                case ILOpcode.brtrue:
                case ILOpcode.beq:
                case ILOpcode.bge:
                case ILOpcode.bgt:
                case ILOpcode.ble:
                case ILOpcode.blt:
                case ILOpcode.bne_un:
                case ILOpcode.bge_un:
                case ILOpcode.bgt_un:
                case ILOpcode.ble_un:
                case ILOpcode.blt_un:
                {
                    int delta  = (int)ReadILUInt32();
                    int target = _currentOffset + delta;
                    if ((uint)target < (uint)_basicBlocks.Length)
                    {
                        CreateBasicBlock(target);
                    }
                    else
                    {
                        ReportInvalidBranchTarget(target);
                    }
                    CreateBasicBlock(_currentOffset);
                }
                break;

                case ILOpcode.switch_:
                {
                    uint count   = ReadILUInt32();
                    int  jmpBase = _currentOffset + (int)(4 * count);
                    for (uint i = 0; i < count; i++)
                    {
                        int delta  = (int)ReadILUInt32();
                        int target = jmpBase + delta;
                        if ((uint)target < (uint)_basicBlocks.Length)
                        {
                            CreateBasicBlock(target);
                        }
                        else
                        {
                            ReportInvalidBranchTarget(target);
                        }
                    }
                    CreateBasicBlock(_currentOffset);
                }
                break;

                default:
                    continue;
                }
            }
        }
Example #49
0
 public void Emit(ILOpcode opcode, ILToken token)
 {
     Emit(opcode);
     EmitUInt32((int)token);
 }
Example #50
0
        bool IsBinaryComparable(StackValue src, StackValue dst, ILOpcode op)
        {
            if (src.Kind == dst.Kind && src.Type == dst.Type)
            {
                return(true);
            }

            switch (src.Kind)
            {
            case StackValueKind.ObjRef:
                switch (dst.Kind)
                {
                case StackValueKind.ObjRef:
                    // ECMA-335 III.1.5 Operand type table, P. 303:
                    // __cgt.un__ is allowed and verifiable on ObjectRefs (O). This is commonly used when
                    // comparing an ObjectRef with null(there is no "compare - not - equal" instruction, which
                    // would otherwise be a more obvious solution)
                    return(op == ILOpcode.beq || op == ILOpcode.beq_s ||
                           op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
                           op == ILOpcode.ceq || op == ILOpcode.cgt_un);

                default:
                    return(false);
                }

            case StackValueKind.ValueType:
                return(false);

            case StackValueKind.ByRef:
                switch (dst.Kind)
                {
                case StackValueKind.ByRef:
                    return(true);

                case StackValueKind.NativeInt:
                    return(op == ILOpcode.beq || op == ILOpcode.beq_s ||
                           op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
                           op == ILOpcode.ceq);

                default:
                    return(false);
                }

            case StackValueKind.Int32:
                return(dst.Kind == StackValueKind.Int64 || dst.Kind == StackValueKind.NativeInt);

            case StackValueKind.Int64:
                return(dst.Kind == StackValueKind.Int64);

            case StackValueKind.NativeInt:
                switch (dst.Kind)
                {
                case StackValueKind.Int32:
                case StackValueKind.NativeInt:
                    return(true);

                case StackValueKind.ByRef:
                    return(op == ILOpcode.beq || op == ILOpcode.beq_s ||
                           op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
                           op == ILOpcode.ceq);

                default:
                    return(false);
                }

            case StackValueKind.Float:
                return(dst.Kind == StackValueKind.Float);

            default:
                throw new NotImplementedException();
            }
        }
Example #51
0
        private void ImportUnaryOperation(ILOpcode opCode)
        {
            var argument = Pop();

            PushTemp(argument.Kind, argument.Type);

            Append((opCode == ILOpcode.neg) ? "~" : "!");
            Append(argument.Value.Name);

            Finish();
        }