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