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.Collections.Generic;
7 using Debug = System.Diagnostics.Debug;
8 
9 namespace Internal.TypeSystem.Interop
10 {
11     public partial class NativeStructType : MetadataType
12     {
13         // The managed struct that this type will imitate
14         public MetadataType ManagedStructType
15         {
16             get;
17         }
18 
19         public override ModuleDesc Module
20         {
21             get;
22         }
23 
24         public override string Name
25         {
26             get
27             {
28                 return "__NativeType__" + ManagedStructType.Name;
29             }
30         }
31 
32         public override string Namespace
33         {
34             get
35             {
36                 return "Internal.CompilerGenerated";
37             }
38         }
39 
40         public override Instantiation Instantiation
41         {
42             get
43             {
44                 return ManagedStructType.Instantiation;
45             }
46         }
47 
48         public override PInvokeStringFormat PInvokeStringFormat
49         {
50             get
51             {
52                 return ManagedStructType.PInvokeStringFormat;
53             }
54         }
55 
56         public override bool IsExplicitLayout
57         {
58             get
59             {
60                 return ManagedStructType.IsExplicitLayout;
61             }
62         }
63 
64         public override bool IsSequentialLayout
65         {
66             get
67             {
68                 return ManagedStructType.IsSequentialLayout;
69             }
70         }
71 
72         public override bool IsBeforeFieldInit
73         {
74             get
75             {
76                 return ManagedStructType.IsBeforeFieldInit;
77             }
78         }
79 
80         public override MetadataType MetadataBaseType
81         {
82             get
83             {
84                 return (MetadataType)Context.GetWellKnownType(WellKnownType.ValueType);
85             }
86         }
87 
88         public override bool IsSealed
89         {
90             get
91             {
92                 return true;
93             }
94         }
95 
96         public override bool IsAbstract
97         {
98             get
99             {
100                 return false;
101             }
102         }
103 
104         public override DefType ContainingType
105         {
106             get
107             {
108                 return null;
109             }
110         }
111 
112         public override DefType[] ExplicitlyImplementedInterfaces
113         {
114             get
115             {
116                 return Array.Empty<DefType>();
117             }
118         }
119 
120         public override TypeSystemContext Context
121         {
122             get
123             {
124                 return ManagedStructType.Context;
125             }
126         }
127 
128         private NativeStructField[] _fields;
129         private InteropStateManager _interopStateManager;
130         private bool _hasInvalidLayout;
131 
132         public bool HasInvalidLayout
133         {
134             get
135             {
136                 return _hasInvalidLayout;
137             }
138         }
139 
140         public FieldDesc[] Fields
141         {
142             get
143             {
144                 return _fields;
145             }
146         }
147 
NativeStructType(ModuleDesc owningModule, MetadataType managedStructType, InteropStateManager interopStateManager)148         public NativeStructType(ModuleDesc owningModule, MetadataType managedStructType, InteropStateManager interopStateManager)
149         {
150             Debug.Assert(managedStructType.IsTypeDefinition);
151             Debug.Assert(managedStructType.IsValueType);
152             Debug.Assert(!managedStructType.IsGenericDefinition);
153 
154             Module = owningModule;
155             ManagedStructType = managedStructType;
156             _interopStateManager = interopStateManager;
157             _hasInvalidLayout = false;
158             CalculateFields();
159         }
160 
CalculateFields()161         private void CalculateFields()
162         {
163             bool isSequential = ManagedStructType.IsSequentialLayout;
164             MarshalAsDescriptor[] marshalAsDescriptors = ManagedStructType.GetFieldMarshalAsDescriptors();
165             bool isAnsi = ((MetadataType)ManagedStructType).PInvokeStringFormat == PInvokeStringFormat.AnsiClass;
166 
167             int numFields = 0;
168             foreach (FieldDesc field in ManagedStructType.GetFields())
169             {
170                 if (field.IsStatic)
171                 {
172                     continue;
173                 }
174                 numFields++;
175             }
176 
177             _fields = new NativeStructField[numFields];
178 
179             int index = 0;
180             foreach (FieldDesc field in ManagedStructType.GetFields())
181             {
182                 if (field.IsStatic)
183                 {
184                     continue;
185                 }
186 
187                 var managedType = field.FieldType;
188 
189                 TypeDesc nativeType;
190                 try
191                 {
192                     nativeType = MarshalHelpers.GetNativeStructFieldType(managedType, marshalAsDescriptors[index], _interopStateManager, isAnsi);
193                 }
194                 catch (NotSupportedException)
195                 {
196                     // if marshalling is not supported for this type the generated stubs will emit appropriate
197                     // error message. We just set native type to be same as managedtype
198                     nativeType = managedType;
199                     _hasInvalidLayout = true;
200                 }
201 
202                 _fields[index++] = new NativeStructField(nativeType, this, field);
203             }
204         }
205 
GetClassLayout()206         public override ClassLayoutMetadata GetClassLayout()
207         {
208             ClassLayoutMetadata layout = ManagedStructType.GetClassLayout();
209 
210             ClassLayoutMetadata result;
211             result.PackingSize = layout.PackingSize;
212             result.Size = layout.Size;
213 
214             if (IsExplicitLayout)
215             {
216                 result.Offsets = new FieldAndOffset[layout.Offsets.Length];
217 
218                 Debug.Assert(layout.Offsets.Length <= _fields.Length);
219 
220                 int layoutIndex = 0;
221                 for (int index = 0; index < _fields.Length; index++)
222                 {
223                     if (_fields[index].Name == layout.Offsets[layoutIndex].Field.Name)
224                     {
225                         result.Offsets[layoutIndex] = new FieldAndOffset(_fields[index], layout.Offsets[layoutIndex].Offset);
226                         layoutIndex++;
227                     }
228                 }
229 
230                 Debug.Assert(layoutIndex == layout.Offsets.Length);
231             }
232             else
233             {
234                 result.Offsets = null;
235             }
236 
237             return result;
238         }
239 
HasCustomAttribute(string attributeNamespace, string attributeName)240         public override bool HasCustomAttribute(string attributeNamespace, string attributeName)
241         {
242             return false;
243         }
244 
GetNestedTypes()245         public override IEnumerable<MetadataType> GetNestedTypes()
246         {
247             return Array.Empty<MetadataType>();
248         }
249 
GetNestedType(string name)250         public override MetadataType GetNestedType(string name)
251         {
252             return null;
253         }
254 
ComputeVirtualMethodImplsForType()255         protected override MethodImplRecord[] ComputeVirtualMethodImplsForType()
256         {
257             return Array.Empty<MethodImplRecord>();
258         }
259 
FindMethodsImplWithMatchingDeclName(string name)260         public override MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string name)
261         {
262             return Array.Empty<MethodImplRecord>();
263         }
264 
265         private int _hashCode;
266 
InitializeHashCode()267         private void InitializeHashCode()
268         {
269             var hashCodeBuilder = new Internal.NativeFormat.TypeHashingAlgorithms.HashCodeBuilder(Namespace);
270 
271             if (Namespace.Length > 0)
272             {
273                 hashCodeBuilder.Append(".");
274             }
275 
276             hashCodeBuilder.Append(Name);
277             _hashCode = hashCodeBuilder.ToHashCode();
278         }
279 
GetHashCode()280         public override int GetHashCode()
281         {
282             if (_hashCode == 0)
283             {
284                 InitializeHashCode();
285             }
286             return _hashCode;
287         }
288 
ComputeTypeFlags(TypeFlags mask)289         protected override TypeFlags ComputeTypeFlags(TypeFlags mask)
290         {
291             TypeFlags flags = 0;
292 
293             if ((mask & TypeFlags.HasGenericVarianceComputed) != 0)
294             {
295                 flags |= TypeFlags.HasGenericVarianceComputed;
296             }
297 
298             if ((mask & TypeFlags.CategoryMask) != 0)
299             {
300                 flags |= TypeFlags.ValueType;
301             }
302 
303             flags |= TypeFlags.HasFinalizerComputed;
304             flags |= TypeFlags.IsByRefLikeComputed;
305 
306             return flags;
307         }
308 
GetFields()309         public override IEnumerable<FieldDesc> GetFields()
310         {
311             return _fields;
312         }
313 
314         /// <summary>
315         /// Synthetic field on <see cref="NativeStructType"/>.
316         /// </summary>
317         private partial class NativeStructField : FieldDesc
318         {
319             private TypeDesc _fieldType;
320             private MetadataType _owningType;
321             private FieldDesc _managedField;
322 
323             public override TypeSystemContext Context
324             {
325                 get
326                 {
327                     return _owningType.Context;
328                 }
329             }
330 
331             public override TypeDesc FieldType
332             {
333                 get
334                 {
335                     return _fieldType;
336                 }
337             }
338 
339             public override bool HasRva
340             {
341                 get
342                 {
343                     return false;
344                 }
345             }
346 
347 
348             public override bool IsInitOnly
349             {
350                 get
351                 {
352                     return false;
353                 }
354             }
355 
356             public override bool IsLiteral
357             {
358                 get
359                 {
360                     return false;
361                 }
362             }
363 
364             public override bool IsStatic
365             {
366                 get
367                 {
368                     return false;
369                 }
370             }
371 
372             public override bool IsThreadStatic
373             {
374                 get
375                 {
376                     return false;
377                 }
378             }
379 
380             public override DefType OwningType
381             {
382                 get
383                 {
384                     return _owningType;
385                 }
386             }
387 
HasCustomAttribute(string attributeNamespace, string attributeName)388             public override bool HasCustomAttribute(string attributeNamespace, string attributeName)
389             {
390                 return false;
391             }
392 
393             public override string Name
394             {
395                 get
396                 {
397                     return _managedField.Name;
398                 }
399             }
400 
NativeStructField(TypeDesc nativeType, MetadataType owningType, FieldDesc managedField)401             public NativeStructField(TypeDesc nativeType, MetadataType owningType, FieldDesc managedField)
402             {
403                 _fieldType = nativeType;
404                 _owningType = owningType;
405                 _managedField = managedField;
406             }
407         }
408 
409     }
410 }
411