98452c58e0c721dfbffa44428e4232ff9c30bd88
[platform/upstream/dotnet/runtime.git] /
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 using System.Diagnostics;
7
8 using Internal.JitInterface;
9 using Internal.Text;
10 using Internal.TypeSystem;
11 using Internal.TypeSystem.Ecma;
12
13 namespace ILCompiler.DependencyAnalysis.ReadyToRun
14 {
15     public class GenericLookupSignature : Signature
16     {
17         private readonly CORINFO_RUNTIME_LOOKUP_KIND _runtimeLookupKind;
18
19         private readonly ReadyToRunFixupKind _fixupKind;
20
21         private readonly TypeDesc _typeArgument;
22
23         private readonly MethodWithToken _methodArgument;
24
25         private readonly FieldDesc _fieldArgument;
26
27         private readonly GenericContext _methodContext;
28
29         private readonly SignatureContext _signatureContext;
30
31         public GenericLookupSignature(
32             CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind,
33             ReadyToRunFixupKind fixupKind,
34             TypeDesc typeArgument,
35             MethodWithToken methodArgument,
36             FieldDesc fieldArgument,
37             GenericContext methodContext,
38             SignatureContext signatureContext)
39         {
40             Debug.Assert(typeArgument != null || methodArgument != null || fieldArgument != null);
41             _runtimeLookupKind = runtimeLookupKind;
42             _fixupKind = fixupKind;
43             _typeArgument = typeArgument;
44             _methodArgument = methodArgument;
45             _fieldArgument = fieldArgument;
46             _methodContext = methodContext;
47             _signatureContext = signatureContext;
48         }
49
50         public override int ClassCode => 258608008;
51
52         public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
53         {
54             if (relocsOnly)
55             {
56                 return new ObjectData(Array.Empty<byte>(), null, 1, null);
57             }
58
59             ReadyToRunCodegenNodeFactory r2rFactory = (ReadyToRunCodegenNodeFactory)factory;
60
61             // Determine the need for module override
62             EcmaModule targetModule;
63             if (_methodArgument != null)
64             {
65                 targetModule = _methodArgument.Token.Module;
66             }
67             else if (_typeArgument != null)
68             {
69                 targetModule = _signatureContext.GetTargetModule(_typeArgument);
70             }
71             else if (_fieldArgument != null)
72             {
73                 targetModule = _signatureContext.GetTargetModule(_fieldArgument);
74             }
75             else
76             {
77                 throw new NotImplementedException();
78             }
79
80             ReadyToRunFixupKind fixupToEmit;
81             TypeDesc contextTypeToEmit = null;
82
83             switch (_runtimeLookupKind)
84             {
85                 case CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_CLASSPARAM:
86                     fixupToEmit = ReadyToRunFixupKind.READYTORUN_FIXUP_TypeDictionaryLookup;
87                     break;
88
89                 case CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_METHODPARAM:
90                     fixupToEmit = ReadyToRunFixupKind.READYTORUN_FIXUP_MethodDictionaryLookup;
91                     break;
92
93                 case CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ:
94                     fixupToEmit = ReadyToRunFixupKind.READYTORUN_FIXUP_ThisObjDictionaryLookup;
95                     contextTypeToEmit = _methodContext.ContextType;
96                     break;
97
98                 default:
99                     throw new NotImplementedException();
100             }
101
102             ObjectDataSignatureBuilder dataBuilder = new ObjectDataSignatureBuilder();
103             dataBuilder.AddSymbol(this);
104
105             SignatureContext innerContext = dataBuilder.EmitFixup(r2rFactory, fixupToEmit, targetModule, _signatureContext);
106             if (contextTypeToEmit != null)
107             {
108                 dataBuilder.EmitTypeSignature(contextTypeToEmit, innerContext);
109             }
110
111             dataBuilder.EmitByte((byte)_fixupKind);
112             if (_methodArgument != null)
113             {
114                 dataBuilder.EmitMethodSignature(
115                     _methodArgument,
116                     enforceDefEncoding: false,
117                     enforceOwningType: false,
118                     context: innerContext,
119                     isUnboxingStub: false,
120                     isInstantiatingStub: true);
121             }
122             else if (_typeArgument != null)
123             {
124                 dataBuilder.EmitTypeSignature(_typeArgument, innerContext);
125             }
126             else if (_fieldArgument != null)
127             {
128                 dataBuilder.EmitFieldSignature(_fieldArgument, innerContext);
129             }
130             else
131             {
132                 throw new NotImplementedException();
133             }
134
135             return dataBuilder.ToObjectData();
136         }
137
138         public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
139         {
140             sb.Append(nameMangler.CompilationUnitPrefix);
141             sb.Append("GenericLookupSignature(");
142             sb.Append(_runtimeLookupKind.ToString());
143             sb.Append(" / ");
144             sb.Append(_fixupKind.ToString());
145             sb.Append(": ");
146             if (_methodArgument != null)
147             {
148                 sb.Append(nameMangler.GetMangledMethodName(_methodArgument.Method));
149                 if (!_methodArgument.Token.IsNull)
150                 {
151                     sb.Append(" [");
152                     sb.Append(_methodArgument.Token.MetadataReader.GetString(_methodArgument.Token.MetadataReader.GetAssemblyDefinition().Name));
153                     sb.Append(":"); ;
154                     sb.Append(((uint)_methodArgument.Token.Token).ToString("X8"));
155                     sb.Append("]");
156                 }
157             }
158             if (_typeArgument != null)
159             {
160                 sb.Append(nameMangler.GetMangledTypeName(_typeArgument));
161             }
162             if (_fieldArgument != null)
163             {
164                 sb.Append(nameMangler.GetMangledFieldName(_fieldArgument));
165             }
166             sb.Append(" (");
167             _methodContext.AppendMangledName(nameMangler, sb);
168             sb.Append(")");
169         }
170
171         public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
172         {
173             GenericLookupSignature otherNode = (GenericLookupSignature)other;
174             int result = _runtimeLookupKind.CompareTo(otherNode._runtimeLookupKind);
175             if (result != 0)
176                 return result;
177
178             result = _fixupKind.CompareTo(otherNode._fixupKind);
179             if (result != 0)
180                 return result;
181
182             if (_typeArgument != null || otherNode._typeArgument != null)
183             {
184                 if (_typeArgument == null)
185                     return -1;
186                 if (otherNode._typeArgument == null)
187                     return 1;
188
189                 result = comparer.Compare(_typeArgument, otherNode._typeArgument);
190                 if (result != 0)
191                     return result;
192             }
193
194             if (_fieldArgument != null || otherNode._fieldArgument != null)
195             {
196                 if (_fieldArgument == null)
197                     return -1;
198                 if (otherNode._fieldArgument == null)
199                     return 1;
200
201                 result = comparer.Compare(_fieldArgument, otherNode._fieldArgument);
202                 if (result != 0)
203                     return result;
204             }
205
206             if (_methodArgument != null || otherNode._methodArgument != null)
207             {
208                 if (_methodArgument == null)
209                     return -1;
210                 if (otherNode._methodArgument == null)
211                     return 1;
212
213                 result = _methodArgument.CompareTo(otherNode._methodArgument, comparer);
214                 if (result != 0)
215                     return result;
216             }
217
218             result = comparer.Compare(_methodContext.ContextMethod, otherNode._methodContext.ContextMethod);
219             if (result != 0)
220                 return result;
221
222             return _signatureContext.CompareTo(otherNode._signatureContext, comparer);
223         }
224
225         protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
226         {
227             DependencyList dependencies = new DependencyList();
228             if (_typeArgument != null && !_typeArgument.IsRuntimeDeterminedSubtype)
229             {
230                 dependencies.Add(factory.NecessaryTypeSymbol(_typeArgument), "Type referenced in a generic lookup signature");
231             }
232             return dependencies;
233         }
234     }
235 }