Welcome to mirror list, hosted at ThFree Co, Russian Federation.

GenericTypesTemplateMap.cs « DependencyAnalysis « Compiler « src « ILCompiler.Compiler « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c01bfae12976e832f8093633fe212750ad09fa50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;

using Internal.Text;
using ILCompiler.DependencyAnalysisFramework;
using Internal.TypeSystem;
using Internal.NativeFormat;

namespace ILCompiler.DependencyAnalysis
{
    /// <summary>
    /// Hashtable of all generic type templates used by the TypeLoader at runtime
    /// </summary>
    public sealed class GenericTypesTemplateMap : ObjectNode, ISymbolDefinitionNode
    {
        private ObjectAndOffsetSymbolNode _endSymbol;
        private ExternalReferencesTableNode _externalReferences;

        public GenericTypesTemplateMap(ExternalReferencesTableNode externalReferences)
        {
            _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__GenericTypesTemplateMap_End", true);
            _externalReferences = externalReferences;
        }

        public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(nameMangler.CompilationUnitPrefix).Append("__GenericTypesTemplateMap");
        }

        public ISymbolNode EndSymbol => _endSymbol;
        public int Offset => 0;
        public override bool IsShareable => false;
        public override ObjectNodeSection Section => _externalReferences.Section;
        public override bool StaticDependenciesAreComputed => true;
        protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);

        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // Dependencies for this node are tracked by the method code nodes
            if (relocsOnly)
                return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });

            // Ensure the native layout data has been saved, in order to get valid Vertex offsets for the signature Vertices
            factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory);

            NativeWriter nativeWriter = new NativeWriter();
            VertexHashtable hashtable = new VertexHashtable();
            Section nativeSection = nativeWriter.NewSection();
            nativeSection.Place(hashtable);

            foreach (TypeDesc type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                if (!IsEligibleToHaveATemplate(type))
                    continue;

                if ((factory.Target.Abi == TargetAbi.ProjectN) && !ProjectNDependencyBehavior.EnableFullAnalysis)
                {
                    // If the type does not have fully constructed type, don't track its dependencies.
                    // TODO: Remove the workaround once we stop using the STS dependency analysis.
                    IDependencyNode node = factory.MaximallyConstructableType(type);

                    if (!node.Marked)
                        continue;
                }

                // Type's native layout info
                NativeLayoutTemplateTypeLayoutVertexNode templateNode = factory.NativeLayout.TemplateTypeLayout(type);

                // If this template isn't considered necessary, don't emit it.
                if (!templateNode.Marked)
                    continue;
                Vertex nativeLayout = templateNode.SavedVertex;

                // Hashtable Entry
                Vertex entry = nativeWriter.GetTuple(
                    nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(type))),
                    nativeWriter.GetUnsignedConstant((uint)nativeLayout.VertexOffset));

                // Add to the hash table, hashed by the containing type's hashcode
                uint hashCode = (uint)type.GetHashCode();
                hashtable.Append(hashCode, nativeSection.Place(entry));
            }

            byte[] streamBytes = nativeWriter.Save();

            _endSymbol.SetSymbolOffset(streamBytes.Length);

            return new ObjectData(streamBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol });
        }
        
        public static void GetTemplateTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
        {
            if (!factory.MetadataManager.SupportsReflection)
                return;

            TypeDesc templateType = ConvertArrayOfTToRegularArray(factory, type);

            if (!IsEligibleToHaveATemplate(templateType))
                return;

            if ((factory.Target.Abi == TargetAbi.ProjectN) && !ProjectNDependencyBehavior.EnableFullAnalysis)
            {
                // If the type does not have fully constructed type, don't track its dependencies.
                // TODO: Remove the workaround once we stop using the STS dependency analysis.
                IDependencyNode node = factory.MaximallyConstructableType(templateType);

                if (!node.Marked)
                    return;
            }

            dependencies = dependencies ?? new DependencyList();
            dependencies.Add(new DependencyListEntry(factory.NecessaryTypeSymbol(templateType), "Template type"));
            dependencies.Add(new DependencyListEntry(factory.NativeLayout.TemplateTypeLayout(templateType), "Template Type Layout"));
        }

        /// <summary>
        /// Array&lt;T&gt; should not get an EEType in our system. All templates should replace
        /// references to Array&lt;T&gt; types with regular arrays.
        /// </summary>
        public static TypeDesc ConvertArrayOfTToRegularArray(NodeFactory factory, TypeDesc type)
        {
            if (type.HasSameTypeDefinition(factory.ArrayOfTClass))
            {
                Debug.Assert(type.Instantiation.Length == 1);
                return factory.TypeSystemContext.GetArrayType(type.Instantiation[0]);
            }

            return type;
        }

        public static bool IsArrayTypeEligibleForTemplate(TypeDesc type)
        {
            if (!type.IsSzArray)
                return false;

            // Unmanaged Pointer and Function pointer arrays can't use the array template
            ArrayType arrayType = (ArrayType)type;
            TypeDesc elementType = arrayType.ElementType;

            return !elementType.IsPointer && !elementType.IsFunctionPointer;
        }

        public static bool IsEligibleToHaveATemplate(TypeDesc type)
        {
            if (!type.HasInstantiation && !IsArrayTypeEligibleForTemplate(type))
                return false;

            if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
            {
                // Must be fully canonical
                Debug.Assert(type == type.ConvertToCanonForm(CanonicalFormKind.Specific));
                return true;
            }

            return false;
        }

        protected internal override int Phase => (int)ObjectNodePhase.Ordered;
        public override int ClassCode => (int)ObjectNodeOrder.GenericTypesTemplateMap;
    }
}