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

RuntimeNoMetadataType.cs « TypeSystem « Internal « src « System.Private.TypeLoader « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 3e6b79244ddab32bc61cea304870658cf1af180e (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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
// 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.Text;
using System.Reflection.Runtime.General;
using Internal.NativeFormat;
using Internal.TypeSystem;
using Internal.Runtime;
using Internal.Runtime.Augments;
using Internal.Runtime.TypeLoader;
using Internal.Metadata.NativeFormat;

using Debug = System.Diagnostics.Debug;

namespace Internal.TypeSystem.NoMetadata
{
    /// <summary>
    /// Type that once had metadata, but that metadata is not available
    /// for the lifetime of the TypeSystemContext. Directly correlates
    /// to a RuntimeTypeHandle useable in the current environment.
    /// This type replaces the placeholder NoMetadataType that comes
    /// with the common type system codebase
    /// </summary>
    internal class NoMetadataType : DefType
    {
        private TypeSystemContext _context;
        private int _hashcode;
        private RuntimeTypeHandle _genericTypeDefinition;
        private DefType _genericTypeDefinitionAsDefType;
        private Instantiation _instantiation;

        // "_baseType == this" means "base type was not initialized yet"
        private DefType _baseType;

        public NoMetadataType(TypeSystemContext context, RuntimeTypeHandle genericTypeDefinition, DefType genericTypeDefinitionAsDefType, Instantiation instantiation, int hashcode)
        {
            _hashcode = hashcode;
            _context = context;
            _genericTypeDefinition = genericTypeDefinition;
            _genericTypeDefinitionAsDefType = genericTypeDefinitionAsDefType;
            if (_genericTypeDefinitionAsDefType == null)
                _genericTypeDefinitionAsDefType = this;
            _instantiation = instantiation;

            // Instantiation must either be:
            // Something valid (if the type is generic, or a generic type definition)
            // or Empty (if the type isn't a generic of any form)
            unsafe
            {
                Debug.Assert(((_instantiation.Length > 0) && _genericTypeDefinition.ToEETypePtr()->IsGenericTypeDefinition) ||
                             ((_instantiation.Length == 0) && !_genericTypeDefinition.ToEETypePtr()->IsGenericTypeDefinition));
            }

            // Base type is not initialized
            _baseType = this;
        }

        public override int GetHashCode()
        {
            return _hashcode;
        }

        public override TypeSystemContext Context
        {
            get
            {
                return _context;
            }
        }

        public override DefType BaseType
        {
            get
            {
                // _baseType == this means we didn't initialize it yet
                if (_baseType != this)
                    return _baseType;

                if (RetrieveRuntimeTypeHandleIfPossible())
                {
                    RuntimeTypeHandle baseTypeHandle;
                    if (!RuntimeAugments.TryGetBaseType(RuntimeTypeHandle, out baseTypeHandle))
                    {
                        Debug.Assert(false);
                    }

                    DefType baseType = !baseTypeHandle.IsNull() ? (DefType)Context.ResolveRuntimeTypeHandle(baseTypeHandle) : null;
                    SetBaseType(baseType);

                    return baseType;
                }
                else
                {
                    // Parsing of the base type has not yet happened. Perform that part of native layout parsing
                    // just-in-time
                    TypeBuilderState state = GetOrCreateTypeBuilderState();

                    ComputeTemplate();
                    NativeParser typeInfoParser = state.GetParserForNativeLayoutInfo();
                    NativeParser baseTypeParser = typeInfoParser.GetParserForBagElementKind(BagElementKind.BaseType);

                    ParseBaseType(state.NativeLayoutInfo.LoadContext, baseTypeParser);
                    Debug.Assert(_baseType != this);
                    return _baseType;
                }
            }
        }

        internal override void ParseBaseType(NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser baseTypeParser)
        {
            if (!baseTypeParser.IsNull)
            {
                // If the base type is available from the native layout info use it if the type we have is a NoMetadataType
                SetBaseType((DefType)nativeLayoutInfoLoadContext.GetType(ref baseTypeParser));
            }
            else
            {
                // Set the base type for no metadata types, if we reach this point, and there isn't a parser, then we simply use the value from the template
                SetBaseType(ComputeTemplate().BaseType);
            }
        }

        /// <summary>
        /// This is used to set base type for generic types without metadata
        /// </summary>
        public void SetBaseType(DefType baseType)
        {
            Debug.Assert(_baseType == this || _baseType == baseType);
            _baseType = baseType;
        }

        protected override TypeFlags ComputeTypeFlags(TypeFlags mask)
        {
            TypeFlags flags = 0;

            if ((mask & TypeFlags.CategoryMask) != 0)
            {
                unsafe
                {
                    EEType* eetype = _genericTypeDefinition.ToEETypePtr();
                    if (eetype->IsValueType)
                    {
                        if (eetype->CorElementType == 0)
                        {
                            flags |= TypeFlags.ValueType;
                        }
                        else
                        {
                            if (eetype->BaseType == typeof(System.Enum).TypeHandle.ToEETypePtr())
                            {
                                flags |= TypeFlags.Enum;
                            }
                            else
                            {
                                // Primitive type.
                                if (eetype->CorElementType <= CorElementType.ELEMENT_TYPE_U8)
                                {
                                    flags |= (TypeFlags)eetype->CorElementType;
                                }
                                else
                                {
                                    switch (eetype->CorElementType)
                                    {
                                        case CorElementType.ELEMENT_TYPE_I:
                                            flags |= TypeFlags.IntPtr;
                                            break;

                                        case CorElementType.ELEMENT_TYPE_U:
                                            flags |= TypeFlags.UIntPtr;
                                            break;

                                        case CorElementType.ELEMENT_TYPE_R4:
                                            flags |= TypeFlags.Single;
                                            break;

                                        case CorElementType.ELEMENT_TYPE_R8:
                                            flags |= TypeFlags.Double;
                                            break;

                                        default:
                                            throw new BadImageFormatException();
                                    }
                                }
                            }
                        }
                    }
                    else if (eetype->IsInterface)
                    {
                        flags |= TypeFlags.Interface;
                    }
                    else
                    {
                        flags |= TypeFlags.Class;
                    }
                }
            }

            if ((mask & TypeFlags.AttributeCacheComputed) != 0)
            {
                flags |= TypeFlags.AttributeCacheComputed;

                unsafe
                {
                    EEType* eetype = _genericTypeDefinition.ToEETypePtr();
                    if (eetype->IsByRefLike)
                    {
                        flags |= TypeFlags.IsByRefLike;
                    }
                }
            }

            return flags;
        }

        // Canonicalization handling

        public override bool IsCanonicalSubtype(CanonicalFormKind policy)
        {
            foreach (TypeDesc t in Instantiation)
            {
                if (t.IsCanonicalSubtype(policy))
                {
                    return true;
                }
            }

            return false;
        }

        protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind)
        {
            bool needsChange;
            Instantiation canonInstantiation = Context.ConvertInstantiationToCanonForm(Instantiation, kind, out needsChange);
            if (needsChange)
            {
                TypeDesc openType = GetTypeDefinition();
                return openType.InstantiateSignature(canonInstantiation, new Instantiation());
            }

            return this;
        }

        public override TypeDesc GetTypeDefinition()
        {
            if (_genericTypeDefinitionAsDefType != null)
                return _genericTypeDefinitionAsDefType;
            else
                return this;
        }

        public override TypeDesc InstantiateSignature(Instantiation typeInstantiation, Instantiation methodInstantiation)
        {
            TypeDesc[] clone = null;

            for (int i = 0; i < _instantiation.Length; i++)
            {
                TypeDesc uninst = _instantiation[i];
                TypeDesc inst = uninst.InstantiateSignature(typeInstantiation, methodInstantiation);
                if (inst != uninst)
                {
                    if (clone == null)
                    {
                        clone = new TypeDesc[_instantiation.Length];
                        for (int j = 0; j < clone.Length; j++)
                        {
                            clone[j] = _instantiation[j];
                        }
                    }
                    clone[i] = inst;
                }
            }

            return (clone == null) ? this : _genericTypeDefinitionAsDefType.Context.ResolveGenericInstantiation(_genericTypeDefinitionAsDefType, new Instantiation(clone));
        }

        public override Instantiation Instantiation
        {
            get
            {
                return _instantiation;
            }
        }

        public override TypeDesc UnderlyingType
        {
            get
            {
                if (!this.IsEnum)
                    return this;

                unsafe
                {
                    CorElementType corElementType = RuntimeTypeHandle.ToEETypePtr()->CorElementType;

                    return Context.GetTypeFromCorElementType(corElementType);
                }
            }
        }

        private void GetTypeNameHelper(out string name, out string nsName, out string assemblyName)
        {
            TypeReferenceHandle typeRefHandle;
            QTypeDefinition qTypeDefinition;
            MetadataReader reader;

            RuntimeTypeHandle genericDefinitionHandle = GetTypeDefinition().GetRuntimeTypeHandle();
            Debug.Assert(!genericDefinitionHandle.IsNull());

            string enclosingDummy;

            // Try to get the name from metadata
            if (TypeLoaderEnvironment.Instance.TryGetMetadataForNamedType(genericDefinitionHandle, out qTypeDefinition))
            {
                TypeDefinitionHandle typeDefHandle = qTypeDefinition.NativeFormatHandle;
                typeDefHandle.GetFullName(qTypeDefinition.NativeFormatReader, out name, out enclosingDummy, out nsName);
                assemblyName = typeDefHandle.GetContainingModuleName(qTypeDefinition.NativeFormatReader);
            }
            // Try to get the name from diagnostic metadata
            else if (TypeLoaderEnvironment.TryGetTypeReferenceForNamedType(genericDefinitionHandle, out reader, out typeRefHandle))
            {
                typeRefHandle.GetFullName(reader, out name, out enclosingDummy, out nsName);
                assemblyName = typeRefHandle.GetContainingModuleName(reader);
            }
            else
            {
                name = genericDefinitionHandle.LowLevelToStringRawEETypeAddress();
                nsName = "";
                assemblyName = "?";
            }
        }

        public string DiagnosticNamespace
        {
            get
            {
                string name, nsName, assemblyName;
                GetTypeNameHelper(out name, out nsName, out assemblyName);
                return nsName;
            }
        }

        public string DiagnosticName
        {
            get
            {
                string name, nsName, assemblyName;
                GetTypeNameHelper(out name, out nsName, out assemblyName);
                return name;
            }
        }

        public string DiagnosticModuleName
        {
            get
            {
                string name, nsName, assemblyName;
                GetTypeNameHelper(out name, out nsName, out assemblyName);
                return assemblyName;
            }
        }

#if DEBUG
        private string _cachedToString = null;

        public override string ToString()
        {
            if (_cachedToString != null)
                return _cachedToString;

            StringBuilder sb = new StringBuilder();

            if (!_genericTypeDefinition.IsNull())
                sb.Append(_genericTypeDefinition.LowLevelToString());
            else if (!RuntimeTypeHandle.IsNull())
                sb.Append(RuntimeTypeHandle.LowLevelToString());

            if (!Instantiation.IsNull)
            {
                for (int i = 0; i < Instantiation.Length; i++)
                {
                    sb.Append(i == 0 ? "[" : ", ");
                    sb.Append(Instantiation[i].ToString());
                }
                if (Instantiation.Length > 0) sb.Append("]");
            }

            _cachedToString = sb.ToString();

            return _cachedToString;
        }
#endif
    }
}