private void WriteMethodTableRvas(NodeFactory factory, ref ObjectDataBuilder builder, ref BlobReader reader)
        {
            MetadataReader metadataReader = _sourceModule.MetadataReader;
            var            tableIndex     = TableIndex.MethodDef;
            int            rowCount       = metadataReader.GetTableRowCount(tableIndex);
            int            rowSize        = metadataReader.GetTableRowSize(tableIndex);

            for (int i = 1; i <= rowCount; i++)
            {
                Debug.Assert(builder.CountBytes == reader.Offset);

                int inputRva = reader.ReadInt32();

                if (inputRva == 0)
                {
                    // Don't fix up 0 Rvas (abstract methods in the methodDef table)
                    builder.EmitInt(0);
                }
                else
                {
                    var        methodDefHandle = MetadataTokens.EntityHandle(TableIndex.MethodDef, i);
                    EcmaMethod method          = _sourceModule.GetMethod(methodDefHandle) as EcmaMethod;
                    builder.EmitReloc(((ReadyToRunCodegenNodeFactory)factory).CopiedMethodIL(method), RelocType.IMAGE_REL_BASED_ADDR32NB);
                }

                // Skip the rest of the row
                int remainingBytes = rowSize - sizeof(int);
                builder.EmitBytes(reader.ReadBytes(remainingBytes));
            }
        }
Example #2
0
        static IEnumerable <MIbcData> ReadMIbcGroup(TypeSystemContext tsc, EcmaMethod method)
        {
            EcmaMethodIL ilBody = EcmaMethodIL.Create((EcmaMethod)method);

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

            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));
                    metadataObject = ilBody.GetObject((int)token);
                    break;

                case ILOpcode.pop:
                    MIbcData mibcData = new MIbcData();
                    mibcData.MetadataObject = metadataObject;
                    yield return(mibcData);

                    break;
                }

                // This isn't correct if there is a switch opcode, but since we won't do that, its ok
                currentOffset += opcode.GetSize();
            }
        }
Example #3
0
        private static void PrintMethod(EcmaMethod method)
        {
            Write(method.Name);
            Write("(");
            try
            {
                if (method.Signature.Length > 0)
                {
                    bool first = true;
                    for (int i = 0; i < method.Signature.Length; i++)
                    {
                        Internal.TypeSystem.TypeDesc parameter = method.Signature[i];
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            Write(", ");
                        }

                        Write(parameter.ToString());
                    }
                }
            }
            catch
            {
                Write("Error while getting method signature");
            }
            Write(")");
        }
Example #4
0
        private static void PrintMethod(EcmaMethod method)
        {
            Write(method.Name);
            Write("(");

            if (method.Signature._parameters != null && method.Signature._parameters.Length > 0)
            {
                bool first = true;
                foreach (Internal.TypeSystem.TypeDesc parameter in method.Signature._parameters)
                {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        Write(", ");
                    }

                    Write(parameter.ToString());
                }
            }

            Write(")");
        }
Example #5
0
        public IEnumerable <MethodInfo> EnumerateMethods()
        {
            DebugNameFormatter   nameFormatter     = new DebugNameFormatter();
            TypeNameFormatter    typeNameFormatter = new TypeString();
            HashSet <MethodDesc> emittedMethods    = new HashSet <MethodDesc>();

            foreach (KeyValuePair <ISymbolDefinitionNode, MethodWithGCInfo> symbolMethodPair in _methodSymbolMap)
            {
                EcmaMethod ecmaMethod = symbolMethodPair.Value.Method.GetTypicalMethodDefinition() as EcmaMethod;
                if (ecmaMethod != null && emittedMethods.Add(ecmaMethod))
                {
                    MethodInfo methodInfo = new MethodInfo();
                    methodInfo.MethodToken  = (uint)MetadataTokens.GetToken(ecmaMethod.Handle);
                    methodInfo.AssemblyName = ecmaMethod.Module.Assembly.GetName().Name;
                    methodInfo.Name         = FormatMethodName(symbolMethodPair.Value.Method, typeNameFormatter);
                    OutputNode node    = _nodeSymbolMap[symbolMethodPair.Key];
                    Section    section = _sections[node.SectionIndex];
                    methodInfo.HotRVA     = (uint)(section.RVAWhenPlaced + node.Offset);
                    methodInfo.HotLength  = (uint)node.Length;
                    methodInfo.ColdRVA    = 0;
                    methodInfo.ColdLength = 0;
                    yield return(methodInfo);
                }
            }
        }
Example #6
0
        public void AddCompilationRoots(IRootingServiceProvider rootProvider)
        {
            foreach (var type in _module.GetAllTypes())
            {
                foreach (var method in type.GetMethods())
                {
                    EcmaMethod ecmaMethod = (EcmaMethod)method;

                    if (ecmaMethod.IsRuntimeExport)
                    {
                        string runtimeExportName = ecmaMethod.GetRuntimeExportName();
                        if (runtimeExportName != null)
                        {
                            rootProvider.AddCompilationRoot(method, "Runtime export", runtimeExportName);
                        }
                    }

                    if (ecmaMethod.IsNativeCallable)
                    {
                        string nativeCallableExportName = ecmaMethod.GetNativeCallableExportName();
                        if (nativeCallableExportName != null)
                        {
                            rootProvider.AddCompilationRoot(method, "Native callable", nativeCallableExportName);
                        }
                    }
                }
            }
        }
Example #7
0
        public static string GetRuntimeExportName(this EcmaMethod This)
        {
            var decoded = This.GetDecodedCustomAttribute("System.Runtime", "RuntimeExportAttribute");

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

            var decodedValue = decoded.Value;

            if (decodedValue.FixedArguments.Length != 0)
            {
                return((string)decodedValue.FixedArguments[0].Value);
            }

            foreach (var argument in decodedValue.NamedArguments)
            {
                if (argument.Name == "EntryPoint")
                {
                    return((string)argument.Value);
                }
            }

            return(null);
        }
Example #8
0
        protected void AddCompilationRootsForExports(EcmaModule module)
        {
            foreach (var type in module.GetAllTypes())
            {
                foreach (var method in type.GetMethods())
                {
                    EcmaMethod ecmaMethod = (EcmaMethod)method;

                    if (ecmaMethod.IsRuntimeExport)
                    {
                        string runtimeExportName = ecmaMethod.GetRuntimeExportName();
                        if (runtimeExportName != null)
                        {
                            _rootProvider.AddCompilationRoot(method, "Runtime export", runtimeExportName);
                        }
                    }

                    if (ecmaMethod.IsNativeCallable)
                    {
                        string nativeCallableExportName = ecmaMethod.GetNativeCallableExportName();
                        if (nativeCallableExportName != null)
                        {
                            _rootProvider.AddCompilationRoot(method, "Native callable", nativeCallableExportName);
                        }
                    }
                }
            }
        }
Example #9
0
        public static byte[] BuildSignatureForMethodDefinedInModule(MethodDesc method, NodeFactory factory)
        {
            EcmaMethod typicalMethod = (EcmaMethod)method.GetTypicalMethodDefinition();

            ModuleToken moduleToken;

            if (factory.CompilationModuleGroup.VersionsWithMethodBody(typicalMethod))
            {
                moduleToken = new ModuleToken(typicalMethod.Module, typicalMethod.Handle);
            }
            else
            {
                MutableModule manifestMetadata = factory.ManifestMetadataTable._mutableModule;
                var           handle           = manifestMetadata.TryGetExistingEntityHandle(method.GetTypicalMethodDefinition());
                Debug.Assert(handle.HasValue);
                moduleToken = new ModuleToken(factory.ManifestMetadataTable._mutableModule, handle.Value);
            }

            ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();

            signatureBuilder.EmitMethodSignature(
                new MethodWithToken(method, moduleToken, constrainedType: null, unboxing: false, context: null),
                enforceDefEncoding: true,
                enforceOwningType: moduleToken.Module is EcmaModule ? factory.CompilationModuleGroup.EnforceOwningType((EcmaModule)moduleToken.Module) : true,
                factory.SignatureContext,
                isInstantiatingStub: false);

            return(signatureBuilder.ToArray());
        }
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, Array.Empty <ISymbolDefinitionNode>()));
            }

            PgoValueEmitter pgoEmitter      = new PgoValueEmitter(_factory.CompilationModuleGroup, _symbolNodeFactory, true);
            NativeWriter    hashtableWriter = new NativeWriter();

            Section         hashtableSection = hashtableWriter.NewSection();
            VertexHashtable vertexHashtable  = new VertexHashtable();

            hashtableSection.Place(vertexHashtable);

            Dictionary <byte[], BlobVertex> uniqueInstrumentationData = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);

            foreach (MethodDesc method in _instrumentationDataMethods)
            {
                pgoEmitter.Clear();
                PgoProcessor.EncodePgoData(_profileDataManager[method].SchemaData, pgoEmitter, false);

                // In composite R2R format, always enforce owning type to let us share generic instantiations among modules
                EcmaMethod  typicalMethod = (EcmaMethod)method.GetTypicalMethodDefinition();
                ModuleToken moduleToken   = new ModuleToken(typicalMethod.Module, typicalMethod.Handle);

                ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();
                signatureBuilder.EmitMethodSignature(
                    new MethodWithToken(method, moduleToken, constrainedType: null, unboxing: false, context: null),
                    enforceDefEncoding: true,
                    enforceOwningType: _factory.CompilationModuleGroup.EnforceOwningType(moduleToken.Module),
                    factory.SignatureContext,
                    isInstantiatingStub: false);
                byte[]     signature     = signatureBuilder.ToArray();
                BlobVertex signatureBlob = new BlobVertex(signature);

                byte[]     encodedInstrumentationData = pgoEmitter.ToByteArray();
                BlobVertex instrumentationDataBlob    = null;
                if (!uniqueInstrumentationData.TryGetValue(encodedInstrumentationData, out instrumentationDataBlob))
                {
                    instrumentationDataBlob = new BlobVertex(encodedInstrumentationData);
                    hashtableSection.Place(instrumentationDataBlob);
                    uniqueInstrumentationData.Add(encodedInstrumentationData, instrumentationDataBlob);
                }

                PgoInstrumentedDataWithSignatureBlobVertex pgoDataVertex = new PgoInstrumentedDataWithSignatureBlobVertex(signatureBlob, 0, instrumentationDataBlob);
                hashtableSection.Place(pgoDataVertex);
                vertexHashtable.Append(unchecked ((uint)ReadyToRunHashCode.MethodHashCode(method)), pgoDataVertex);
            }

            MemoryStream hashtableContent = new MemoryStream();

            hashtableWriter.Save(hashtableContent);
            return(new ObjectData(
                       data: hashtableContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
Example #11
0
        private EcmaMethodIL(EcmaMethod method, int rva, bool clearInitLocals)
        {
            _method     = method;
            _module     = method.Module;
            _methodBody = _module.PEReader.GetMethodBody(rva);

            _clearInitLocals = clearInitLocals;
        }
Example #12
0
        private uint LookupIbcMethodToken(MetadataType methodMetadataType, uint ibcToken, Dictionary <IBCBlobKey, BlobEntry> blobs)
        {
            var methodEntry    = (BlobEntry.ExternalMethodEntry)blobs[new IBCBlobKey(ibcToken, BlobType.ExternalMethodDef)];
            var signatureEntry = (BlobEntry.ExternalSignatureEntry)blobs[new IBCBlobKey(methodEntry.SignatureToken, BlobType.ExternalSignatureDef)];

            string methodName = Encoding.UTF8.GetString(methodEntry.Name);


            var ecmaType = (EcmaType)methodMetadataType.GetTypeDefinition();

            EcmaModule ecmaModule = ecmaType.EcmaModule;
            var        lookupClassTokenTypeDef = (int)LookupIbcTypeToken(ref ecmaModule, methodEntry.ClassToken, blobs);

            if (lookupClassTokenTypeDef != ecmaType.MetadataReader.GetToken(ecmaType.Handle))
            {
                throw new Exception($"Ibc MethodToken {ibcToken:x} incosistent classToken '{ibcToken:x}' with specified exact type '{ecmaType}'");
            }

            foreach (MethodDesc method in ecmaType.GetMethods())
            {
                if (method.Name == methodName)
                {
                    EcmaMethod ecmaCandidateMethod = method as EcmaMethod;
                    if (method == null)
                    {
                        continue;
                    }

                    MetadataReader metadataReader  = ecmaCandidateMethod.MetadataReader;
                    BlobReader     signatureReader = metadataReader.GetBlobReader(metadataReader.GetMethodDefinition(ecmaCandidateMethod.Handle).Signature);

                    // Compare for equality
                    if (signatureReader.RemainingBytes != signatureEntry.Signature.Length)
                    {
                        continue;
                    }
                    for (int i = 0; i < signatureEntry.Signature.Length; i++)
                    {
                        if (signatureReader.ReadByte() != signatureEntry.Signature[i])
                        {
                            continue;
                        }
                    }

                    // TODO, consider implementing the fuzzy matching that CrossGen implements
                    // It will be necessary for handling version tolerant ibc parsing of generics

                    // Exact match
                    return((uint)MetadataTokens.GetToken(ecmaCandidateMethod.Handle));
                }
            }

            if (_logger.IsVerbose)
            {
                _logger.Writer.WriteLine("Warning: Unable to find exact match for candidate external method");
            }
            return(0);
        }
Example #13
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 #14
0
        public static string GetRuntimeImportEntryPointName(this EcmaMethod This)
        {
            var metadataReader = This.MetadataReader;

            foreach (var attributeHandle in metadataReader.GetMethodDefinition(This.Handle).GetCustomAttributes())
            {
                EntityHandle attributeType, attributeCtor;
                if (!metadataReader.GetAttributeTypeAndConstructor(attributeHandle,
                                                                   out attributeType, out attributeCtor))
                {
                    continue;
                }

                StringHandle namespaceHandle, nameHandle;
                if (!metadataReader.GetAttributeTypeNamespaceAndName(attributeType,
                                                                     out namespaceHandle, out nameHandle))
                {
                    continue;
                }

                if (metadataReader.StringComparer.Equals(namespaceHandle, "System.Runtime") &&
                    metadataReader.StringComparer.Equals(nameHandle, "RuntimeImportAttribute"))
                {
                    var constructor = This.Module.GetMethod(attributeCtor);

                    if (constructor.Signature.Length != 1 && constructor.Signature.Length != 2)
                    {
                        throw new BadImageFormatException();
                    }

                    for (int i = 0; i < constructor.Signature.Length; i++)
                    {
                        if (constructor.Signature[i] != This.Context.GetWellKnownType(WellKnownType.String))
                        {
                            throw new BadImageFormatException();
                        }
                    }

                    var attributeBlob = metadataReader.GetBlobReader(metadataReader.GetCustomAttribute(attributeHandle).Value);
                    if (attributeBlob.ReadInt16() != 1)
                    {
                        throw new BadImageFormatException();
                    }

                    // Skip module name if present
                    if (constructor.Signature.Length == 2)
                    {
                        attributeBlob.ReadSerializedString();
                    }

                    return(attributeBlob.ReadSerializedString());
                }
            }

            return(null);
        }
Example #15
0
 public bool NeedsCrossModuleInlineableTokens(EcmaMethod method)
 {
     if (!_compilationModuleGroup.VersionsWithMethodBody(method) &&
         _compilationModuleGroup.CrossModuleInlineable(method) &&
         !_manifestModuleWrappedMethods.ContainsKey(method))
     {
         return(true);
     }
     return(false);
 }
Example #16
0
        static public EcmaMethodIL Create(EcmaMethod method)
        {
            var rva = method.MetadataReader.GetMethodDefinition(method.Handle).RelativeVirtualAddress;

            if (rva == 0)
            {
                return(null);
            }
            return(new EcmaMethodIL(method.Module, method.Module.PEReader.GetMethodBody(rva)));
        }
Example #17
0
        public static EcmaMethodIL Create(EcmaMethod method, bool clearInitLocals = false)
        {
            var rva = method.MetadataReader.GetMethodDefinition(method.Handle).RelativeVirtualAddress;

            if (rva == 0)
            {
                return(null);
            }
            return(new EcmaMethodIL(method, rva, clearInitLocals));
        }
        public void TestDependencyGraphInvariants(EcmaMethod method)
        {
            //
            // Scan the input method
            //

            var context = (CompilerTypeSystemContext)method.Context;
            CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup(context);

            CompilationBuilder builder = new RyuJitCompilationBuilder(context, compilationGroup);
            IILScanner         scanner = builder.GetILScannerBuilder()
                                         .UseCompilationRoots(new ICompilationRootProvider[] { new SingleMethodRootProvider(method) })
                                         .ToILScanner();

            ILScanResults results = scanner.Scan();

            //
            // Check invariants
            //

            const string assetsNamespace       = "ILCompiler.Compiler.Tests.Assets";
            bool         foundSomethingToCheck = false;

            foreach (var attr in method.GetDecodedCustomAttributes(assetsNamespace, "GeneratesConstructedEETypeAttribute"))
            {
                foundSomethingToCheck = true;
                Assert.Contains((TypeDesc)attr.FixedArguments[0].Value, results.ConstructedEETypes);
            }

            foreach (var attr in method.GetDecodedCustomAttributes(assetsNamespace, "NoConstructedEETypeAttribute"))
            {
                foundSomethingToCheck = true;
                Assert.DoesNotContain((TypeDesc)attr.FixedArguments[0].Value, results.ConstructedEETypes);
            }

            foreach (var attr in method.GetDecodedCustomAttributes(assetsNamespace, "GeneratesMethodBodyAttribute"))
            {
                foundSomethingToCheck = true;
                MethodDesc methodToCheck = GetMethodFromAttribute(attr);
                Assert.Contains(methodToCheck.GetCanonMethodTarget(CanonicalFormKind.Specific), results.CompiledMethodBodies);
            }

            foreach (var attr in method.GetDecodedCustomAttributes(assetsNamespace, "NoMethodBodyAttribute"))
            {
                foundSomethingToCheck = true;
                MethodDesc methodToCheck = GetMethodFromAttribute(attr);
                Assert.DoesNotContain(methodToCheck.GetCanonMethodTarget(CanonicalFormKind.Specific), results.CompiledMethodBodies);
            }

            //
            // Make sure we checked something
            //

            Assert.True(foundSomethingToCheck, "No invariants to check?");
        }
Example #19
0
        public CopiedMethodILNode CopiedMethodIL(EcmaMethod method)
        {
            CopiedMethodILNode result;

            if (!_copiedMethodIL.TryGetValue(method, out result))
            {
                result = new CopiedMethodILNode(method);
                _copiedMethodIL.Add(method, result);
            }

            return(result);
        }
Example #20
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 #21
0
        string CompileSpecialMethod(MethodDesc method, SpecialMethodKind kind)
        {
            StringBuilder builder = new StringBuilder();

            switch (kind)
            {
            case SpecialMethodKind.PInvoke:
            case SpecialMethodKind.RuntimeImport:
            {
                EcmaMethod ecmaMethod = method as EcmaMethod;

                string importName = kind == SpecialMethodKind.PInvoke ?
                                    method.GetPInvokeMethodMetadata().Name : ecmaMethod.GetRuntimeImportEntryPointName();

                if (importName == null)
                {
                    importName = method.Name;
                }

                // TODO: hacky special-case
                if (importName != "memmove" && importName != "malloc")         // some methods are already declared by the CRT headers
                {
                    builder.AppendLine(GetCppMethodDeclaration(method, false, importName));
                }
                builder.AppendLine(GetCppMethodDeclaration(method, true));
                builder.AppendLine("{");
                builder.Append("    ");
                if (GetCppSignatureTypeName(method.Signature.ReturnType) != "void")
                {
                    builder.Append("return ");
                }

                builder.AppendLine("::" + importName + "(" + GetCppMethodCallParamList(method) + ");");
                builder.AppendLine("}");

                return(builder.ToString());
            }

            default:
                // TODO: hacky special-case
                if (method.Name == "BlockCopy")
                {
                    return(null);
                }

                return(GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine);
            }
        }
Example #22
0
            private void LookForVirtualOverrides(EcmaMethod method)
            {
                // We don't currently attempt to handle this for non-generics.
                if (!method.HasInstantiation)
                {
                    return;
                }

                // If this is a generic virtual method, add an edge from each of the generic parameters
                // of the implementation to the generic parameters of the declaration - any call to the
                // declaration will be modeled as if the declaration was calling into the implementation.

                var decl = (EcmaMethod)MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method).GetTypicalMethodDefinition();

                if (decl != method)
                {
                    RecordBinding(this, decl.Instantiation, method.Instantiation);
                }
                else
                {
                    TypeDesc methodOwningType = method.OwningType;

                    // This is the slot definition. Does it implement an interface?
                    // (This has obvious holes. They haven't show up as issues so far.)
                    foreach (DefType interfaceType in methodOwningType.RuntimeInterfaces)
                    {
                        foreach (MethodDesc interfaceMethod in interfaceType.GetVirtualMethods())
                        {
                            // Trivially reject looking at interface methods that for sure can't be implemented by
                            // the method we're looking at.
                            if (!interfaceMethod.IsVirtual ||
                                interfaceMethod.Instantiation.Length != method.Instantiation.Length ||
                                interfaceMethod.Signature.Length != method.Signature.Length ||
                                interfaceMethod.Signature.IsStatic != method.Signature.IsStatic)
                            {
                                continue;
                            }

                            MethodDesc impl = methodOwningType.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod)?.GetMethodDefinition();
                            if (impl == method)
                            {
                                RecordBinding(this, interfaceMethod.Instantiation, method.Instantiation);
                                // Continue the loop in case this method implements multiple interfaces
                            }
                        }
                    }
                }
Example #23
0
        // Create the cross module inlineable tokens for a method
        // This method is order dependent, and must be called during the single threaded portion of compilation
        public void CreateCrossModuleInlineableTokensForILBody(EcmaMethod method)
        {
            Debug.Assert(_manifestMutableModule != null);
            Debug.Assert(!_compilationModuleGroup.VersionsWithMethodBody(method) &&
                         _compilationModuleGroup.CrossModuleInlineable(method));
            var wrappedMethodIL = new ManifestModuleWrappedMethodIL();

            if (!wrappedMethodIL.Initialize(_manifestMutableModule, EcmaMethodIL.Create(method)))
            {
                // If we could not initialize the wrapped method IL, we should store a null.
                // That will result in the IL code for the method being unavailable for use in
                // the compilation, which is version safe.
                wrappedMethodIL = null;
            }
            _manifestModuleWrappedMethods.Add(method, wrappedMethodIL);
            IncrementVersion();
        }
            private int MethodToInt(TypeSystemEntityOrUnknown handle)
            {
                if (handle.IsNull || (handle.AsMethod == null && handle.AsUnknown == 0))
                {
                    return(0);
                }

                if (_methodConversions.TryGetValue(handle, out int computedInt))
                {
                    return(computedInt);
                }
                if (handle.AsMethod != null && _compilationGroup.VersionsWithMethodBody(handle.AsMethod))
                {
                    EcmaMethod  typicalMethod = (EcmaMethod)handle.AsMethod.GetTypicalMethodDefinition();
                    ModuleToken moduleToken   = new ModuleToken(typicalMethod.Module, typicalMethod.Handle);

                    MethodWithToken tok = new MethodWithToken(handle.AsMethod, moduleToken, constrainedType: null, unboxing: false, context: null);
                    Import          methodHandleImport = (Import)_symbolFactory.CreateReadyToRunHelper(ReadyToRunHelperId.MethodHandle, tok);
                    _imports.Add(methodHandleImport);

                    if (_actuallyCaptureOutput)
                    {
                        if (methodHandleImport.Table.IndexFromBeginningOfArray >= 0xF)
                        {
                            // The current implementation of this table only allows for 15 different
                            // import tables to be used. This is probably enough for long term
                            // but this code will throw if we use more import tables and attempt
                            // to encode pgo data
                            throw new Exception("Unexpected high index for table import");
                        }

                        computedInt = (methodHandleImport.IndexFromBeginningOfArray << 4) | methodHandleImport.Table.IndexFromBeginningOfArray;
                    }
                    else
                    {
                        computedInt = _imports.Count << 1;
                    }
                }
                else
                {
                    computedInt = ((++_unknownMethodsFound) << 4) | 0xF;
                }
                _methodConversions.Add(handle, computedInt);
                return(computedInt);
            }
Example #25
0
        private ArraySignatureBuilder BuildSignatureForMethod(MethodWithGCInfo method, NodeFactory factory)
        {
            // In composite R2R format, always enforce owning type to let us share generic instantiations among modules

            EcmaMethod  typicalMethod = (EcmaMethod)method.Method.GetTypicalMethodDefinition();
            ModuleToken moduleToken   = new ModuleToken(typicalMethod.Module, typicalMethod.Handle);

            ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();

            signatureBuilder.EmitMethodSignature(
                new MethodWithToken(method.Method, moduleToken, constrainedType: null, unboxing: false, context: null),
                enforceDefEncoding: true,
                enforceOwningType: _factory.CompilationModuleGroup.EnforceOwningType(moduleToken.Module),
                factory.SignatureContext,
                isInstantiatingStub: false);

            return(signatureBuilder);
        }
        public IEnumerable <LocalVariable> GetLocalVariableNamesForMethod(MethodDesc method)
        {
            EcmaMethod ecmaMethod = method.GetTypicalMethodDefinition() as EcmaMethod;

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

            ModuleData moduleData = _moduleData[ecmaMethod.Module];

            if (moduleData.PdbReader == null)
            {
                return(null);
            }

            return(_pdbSymbolProvider.GetLocalVariableNamesForMethod(moduleData.PdbReader, MetadataTokens.GetToken(ecmaMethod.Handle)));
        }
Example #27
0
        public static string GetRuntimeImportDllName(this EcmaMethod This)
        {
            var decoded = This.GetDecodedCustomAttribute("System.Runtime", "RuntimeImportAttribute");

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

            var decodedValue = decoded.Value;

            if (decodedValue.FixedArguments.Length == 2)
            {
                return((string)decodedValue.FixedArguments[0].Value);
            }

            return(null);
        }
Example #28
0
        public void TestGenericNameFormatting()
        {
            MetadataType testClass  = _testModule.GetType("ILDisassembler", "TestGenericClass`1");
            EcmaMethod   testMethod = (EcmaMethod)testClass.GetMethod("TestMethod", null);
            EcmaMethodIL methodIL   = EcmaMethodIL.Create(testMethod);

            Dictionary <int, string> interestingLines = new Dictionary <int, string>
            {
                { 4, "IL_0003:  ldstr       \"Hello \\\"World\\\"!\\n\"" },
                { 9, "IL_000D:  call        instance void class ILDisassembler.TestGenericClass`1<!TClassParam>::VoidGenericMethod<string, valuetype ILDisassembler.TestStruct>(!!0, int32, native int, class ILDisassembler.TestClass&)" },
                { 14, "IL_0017:  initobj     !TClassParam" },
                { 16, "IL_001E:  call        !!0 class ILDisassembler.TestGenericClass`1<!TClassParam>::MethodParamGenericMethod<class ILDisassembler.TestClass>(class ILDisassembler.TestGenericClass`1<!!0>, class ILDisassembler.TestGenericClass`1/Nested<!0>, valuetype ILDisassembler.TestStruct*[], !0)" },
                { 24, "IL_0030:  call        !!0 class ILDisassembler.TestGenericClass`1<!TClassParam>::MethodParamGenericMethod<!0>(class ILDisassembler.TestGenericClass`1<!!0>, class ILDisassembler.TestGenericClass`1/Nested<!0>, valuetype ILDisassembler.TestStruct*[], !0)" },
                { 26, "IL_0036:  ldtoken     !TClassParam" },
                { 28, "IL_003C:  ldtoken     valuetype [CoreTestAssembly]System.Nullable`1<int32>" },
                { 31, "IL_0043:  ldc.r8      3.14" },
                { 32, "IL_004C:  ldc.r4      1.68" },
                { 34, "IL_0053:  call        instance valuetype ILDisassembler.TestStruct class ILDisassembler.TestGenericClass`1<!TClassParam>::NonGenericMethod(float64, float32, int16)" },
                { 37, "IL_005A:  ldflda      !0 class ILDisassembler.TestGenericClass`1<!TClassParam>::somefield" },
                { 41, "IL_0067:  stfld       class ILDisassembler.TestClass class ILDisassembler.TestGenericClass`1<!TClassParam>::otherfield" },
                { 44, "IL_006E:  stfld       class ILDisassembler.TestGenericClass`1<class ILDisassembler.TestGenericClass`1<class ILDisassembler.TestClass>> class ILDisassembler.TestGenericClass`1<!TClassParam>::genericfield" },
                { 47, "IL_0075:  stfld       !0[] class ILDisassembler.TestGenericClass`1<!TClassParam>::arrayfield" },
                { 48, "IL_007A:  call        void ILDisassembler.TestClass::NonGenericMethod()" },
                { 49, "IL_007F:  ldsflda     valuetype ILDisassembler.TestStruct ILDisassembler.TestClass::somefield" },
                { 50, "IL_0084:  initobj     ILDisassembler.TestStruct" }
            };

            ILDisassembler disasm = new ILDisassembler(methodIL);

            int numLines = 1;

            while (disasm.HasNextInstruction)
            {
                string line = disasm.GetNextInstruction();
                string expectedLine;
                if (interestingLines.TryGetValue(numLines, out expectedLine))
                {
                    Assert.Equal(expectedLine, line);
                }
                numLines++;
            }

            Assert.Equal(52, numLines);
        }
Example #29
0
        public IEnumerable <ILLocalVariable> GetLocalVariableNamesForMethod(MethodDesc method)
        {
            EcmaMethod ecmaMethod = method.GetTypicalMethodDefinition() as EcmaMethod;

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

            ModuleData moduleData;

            _moduleHashtable.TryGetValue(ecmaMethod.Module, out moduleData);
            Debug.Assert(moduleData != null);

            if (moduleData.PdbReader == null)
            {
                return(null);
            }

            return(moduleData.PdbReader.GetLocalVariableNamesForMethod(MetadataTokens.GetToken(ecmaMethod.Handle)));
        }
Example #30
0
        public static string GetNativeCallableExportName(this EcmaMethod This)
        {
            var decoded = This.GetDecodedCustomAttribute("System.Runtime.InteropServices", "NativeCallableAttribute");

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

            var decodedValue = decoded.Value;

            foreach (var argument in decodedValue.NamedArguments)
            {
                if (argument.Name == "EntryPoint")
                {
                    return((string)argument.Value);
                }
            }

            return(null);
        }