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)); } }
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(); } }
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(")"); }
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(")"); }
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); } } }
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); } } } } }
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); }
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); } } } } }
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 })); }
private EcmaMethodIL(EcmaMethod method, int rva, bool clearInitLocals) { _method = method; _module = method.Module; _methodBody = _module.PEReader.GetMethodBody(rva); _clearInitLocals = clearInitLocals; }
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); }
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)); }
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); }
public bool NeedsCrossModuleInlineableTokens(EcmaMethod method) { if (!_compilationModuleGroup.VersionsWithMethodBody(method) && _compilationModuleGroup.CrossModuleInlineable(method) && !_manifestModuleWrappedMethods.ContainsKey(method)) { return(true); } return(false); }
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))); }
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?"); }
public CopiedMethodILNode CopiedMethodIL(EcmaMethod method) { CopiedMethodILNode result; if (!_copiedMethodIL.TryGetValue(method, out result)) { result = new CopiedMethodILNode(method); _copiedMethodIL.Add(method, result); } return(result); }
/// <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(); } }
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); } }
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 } } } }
// 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); }
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))); }
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); }
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); }
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))); }
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); }