private static NativeLayoutFieldDesc[] ParseFieldLayout(DefType owningType, NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser fieldLayoutParser) { if (fieldLayoutParser.IsNull) { return(Empty <NativeLayoutFieldDesc> .Array); } uint numFields = fieldLayoutParser.GetUnsigned(); var fields = new NativeLayoutFieldDesc[numFields]; for (int i = 0; i < numFields; i++) { TypeDesc fieldType = nativeLayoutInfoLoadContext.GetType(ref fieldLayoutParser); NativeFormat.FieldStorage storage = (NativeFormat.FieldStorage)fieldLayoutParser.GetUnsigned(); fields[i] = new NativeLayoutFieldDesc(owningType, fieldType, storage); } return(fields); }
public static void RegisterDebugDataForType(TypeBuilder typeBuilder, DefType defType, TypeBuilderState state) { if (!defType.IsGeneric()) { RegisterDebugDataForNativeFormatType(typeBuilder, defType, state); return; } if (defType.IsGenericDefinition) { // We don't yet have an encoding for open generic types // TODO! fill this in return; } NativePrimitiveEncoder encoder = new NativePrimitiveEncoder(); encoder.Init(); IntPtr gcStaticFieldData = TypeLoaderEnvironment.Instance.TryGetGcStaticFieldData(typeBuilder.GetRuntimeTypeHandle(defType)); IntPtr nonGcStaticFieldData = TypeLoaderEnvironment.Instance.TryGetNonGcStaticFieldData(typeBuilder.GetRuntimeTypeHandle(defType)); bool isUniversalGenericType = state.TemplateType != null && state.TemplateType.IsCanonicalSubtype(CanonicalFormKind.Universal); bool embeddedTypeSizeAndFieldOffsets = isUniversalGenericType || (state.TemplateType == null); uint instanceFieldCount = 0; uint staticFieldCount = 0; // GetDiagnosticFields only returns the fields that are of interest for diagnostic reporting. So it doesn't // return a meaningful list for non-universal canonical templates IEnumerable <FieldDesc> diagnosticFields = defType.GetDiagnosticFields(); foreach (var f in diagnosticFields) { if (f.IsLiteral) { continue; } if (f.IsStatic) { ++staticFieldCount; } else { ++instanceFieldCount; } } SharedTypeFlags sharedTypeFlags = 0; if (gcStaticFieldData != IntPtr.Zero) { sharedTypeFlags |= SharedTypeFlags.HasGCStaticFieldRegion; } if (nonGcStaticFieldData != IntPtr.Zero) { sharedTypeFlags |= SharedTypeFlags.HasNonGCStaticFieldRegion; } if (state.ThreadDataSize != 0) { sharedTypeFlags |= SharedTypeFlags.HasThreadStaticFieldRegion; } if (embeddedTypeSizeAndFieldOffsets) { sharedTypeFlags |= SerializedDebugData.SharedTypeFlags.HasTypeSize; if (instanceFieldCount > 0) { sharedTypeFlags |= SerializedDebugData.SharedTypeFlags.HasInstanceFields; } if (staticFieldCount > 0) { sharedTypeFlags |= SerializedDebugData.SharedTypeFlags.HasStaticFields; } } SerializeDataBlobTypeAndFlags(ref encoder, SerializedDataBlobKind.SharedType, (byte)sharedTypeFlags); // // The order of these writes is a contract shared between the runtime and debugger engine. // Changes here must also be updated in the debugger reader code // encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(defType).ToIntPtr().ToInt64()); encoder.WriteUnsigned((uint)defType.Instantiation.Length); foreach (var instParam in defType.Instantiation) { encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(instParam).ToIntPtr().ToInt64()); } if (gcStaticFieldData != IntPtr.Zero) { encoder.WriteUnsignedLong((ulong)gcStaticFieldData.ToInt64()); } if (nonGcStaticFieldData != IntPtr.Zero) { encoder.WriteUnsignedLong((ulong)nonGcStaticFieldData.ToInt64()); } // Write the TLS offset into the native thread's TLS buffer. That index de-referenced is the thread static // data region for this type if (state.ThreadDataSize != 0) { encoder.WriteUnsigned(state.ThreadStaticOffset); } // Collect information debugger only requires for universal generics and dynamically loaded types if (embeddedTypeSizeAndFieldOffsets) { Debug.Assert(state.TypeSize != null); encoder.WriteUnsigned((uint)state.TypeSize); if (instanceFieldCount > 0) { encoder.WriteUnsigned(instanceFieldCount); uint i = 0; foreach (FieldDesc f in diagnosticFields) { if (f.IsLiteral) { continue; } if (f.IsStatic) { continue; } encoder.WriteUnsigned(i); encoder.WriteUnsigned((uint)f.Offset.AsInt); i++; } } if (staticFieldCount > 0) { encoder.WriteUnsigned(staticFieldCount); uint i = 0; foreach (FieldDesc f in diagnosticFields) { if (f.IsLiteral) { continue; } if (!f.IsStatic) { continue; } NativeLayoutFieldDesc nlfd = f as NativeLayoutFieldDesc; FieldStorage fieldStorage; if (nlfd != null) { // NativeLayoutFieldDesc's have the field storage information directly embedded in them fieldStorage = nlfd.FieldStorage; } else { // Metadata based types do not, but the api's to get the info are available if (f.IsThreadStatic) { fieldStorage = FieldStorage.TLSStatic; } else if (f.HasGCStaticBase) { fieldStorage = FieldStorage.GCStatic; } else { fieldStorage = FieldStorage.NonGCStatic; } } encoder.WriteUnsigned(i); encoder.WriteUnsigned((uint)fieldStorage); encoder.WriteUnsigned((uint)f.Offset.AsInt); i++; } } } Instance.ThreadSafeWriteBytes(encoder.GetBytes()); }
private static NativeLayoutFieldDesc[] ParseFieldLayout(DefType owningType, NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser fieldLayoutParser) { if (fieldLayoutParser.IsNull) return Empty<NativeLayoutFieldDesc>.Array; uint numFields = fieldLayoutParser.GetUnsigned(); var fields = new NativeLayoutFieldDesc[numFields]; for (int i = 0; i < numFields; i++) { TypeDesc fieldType = nativeLayoutInfoLoadContext.GetType(ref fieldLayoutParser); NativeFormat.FieldStorage storage = (NativeFormat.FieldStorage)fieldLayoutParser.GetUnsigned(); fields[i] = new NativeLayoutFieldDesc(owningType, fieldType, storage); } return fields; }