1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 7 using Internal.NativeFormat; 8 using Internal.Text; 9 using Internal.TypeSystem; 10 11 namespace ILCompiler.DependencyAnalysis 12 { 13 /// <summary> 14 /// Represents a map between EETypes and metadata records within the <see cref="MetadataNode"/>. 15 /// </summary> 16 internal sealed class TypeMetadataMapNode : ObjectNode, ISymbolDefinitionNode 17 { 18 private ObjectAndOffsetSymbolNode _endSymbol; 19 private ExternalReferencesTableNode _externalReferences; 20 TypeMetadataMapNode(ExternalReferencesTableNode externalReferences)21 public TypeMetadataMapNode(ExternalReferencesTableNode externalReferences) 22 { 23 _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__type_to_metadata_map_End", true); 24 _externalReferences = externalReferences; 25 } 26 27 public ISymbolNode EndSymbol => _endSymbol; 28 AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)29 public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) 30 { 31 sb.Append(nameMangler.CompilationUnitPrefix).Append("__type_to_metadata_map"); 32 } 33 public int Offset => 0; 34 public override bool IsShareable => false; 35 36 public override ObjectNodeSection Section => _externalReferences.Section; 37 38 public override bool StaticDependenciesAreComputed => true; 39 40 public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => !factory.MetadataManager.SupportsReflection; 41 42 protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); 43 GetData(NodeFactory factory, bool relocsOnly = false)44 public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) 45 { 46 // This node does not trigger generation of other nodes. 47 if (relocsOnly) 48 return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this }); 49 50 var writer = new NativeWriter(); 51 var typeMapHashTable = new VertexHashtable(); 52 53 Section hashTableSection = writer.NewSection(); 54 hashTableSection.Place(typeMapHashTable); 55 56 foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping(factory)) 57 { 58 if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity)) 59 continue; 60 61 // Types that don't have EETypes don't need mapping table entries because there's no risk of them 62 // not unifying to the same System.Type at runtime. 63 if (!factory.MetadataManager.TypeGeneratesEEType(mappingEntry.Entity)) 64 continue; 65 66 // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted. 67 IEETypeNode typeSymbol = factory.NecessaryTypeSymbol(mappingEntry.Entity); 68 69 Vertex vertex = writer.GetTuple( 70 writer.GetUnsignedConstant(_externalReferences.GetIndex(typeSymbol)), 71 writer.GetUnsignedConstant((uint)mappingEntry.MetadataHandle) 72 ); 73 74 int hashCode = typeSymbol.Type.GetHashCode(); 75 typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); 76 } 77 78 byte[] hashTableBytes = writer.Save(); 79 80 _endSymbol.SetSymbolOffset(hashTableBytes.Length); 81 82 return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); 83 } 84 85 protected internal override int Phase => (int)ObjectNodePhase.Ordered; 86 87 protected internal override int ClassCode => (int)ObjectNodeOrder.TypeMetadataMapNode; 88 } 89 } 90