/// <summary> /// Get the GC layout of a type when used as a field. /// NOTE: if the fieldtype is a reference type, this function will return GCLayout.None /// Consumers of the api must handle that special case. /// </summary> private unsafe TypeBuilder.GCLayout GetFieldGCLayout(TypeDesc fieldType) { if (!fieldType.IsValueType) { if (fieldType.IsPointer) return TypeBuilder.GCLayout.None; else return TypeBuilder.GCLayout.SingleReference; } // Is this a type that already exists? If so, get its gclayout from the EEType directly if (fieldType.RetrieveRuntimeTypeHandleIfPossible()) { return new TypeBuilder.GCLayout(fieldType.RuntimeTypeHandle); } // The type of the field must be a valuetype that is dynamically being constructed if (fieldType.IsTemplateCanonical()) { // Pull the GC Desc from the canonical instantiation TypeDesc templateType = fieldType.ComputeTemplate(); bool success = templateType.RetrieveRuntimeTypeHandleIfPossible(); Debug.Assert(success); return new TypeBuilder.GCLayout(templateType.RuntimeTypeHandle); } else { // Use the type builder state's computed InstanceGCLayout var instanceGCLayout = fieldType.GetOrCreateTypeBuilderState().InstanceGCLayout; if (instanceGCLayout == null) return TypeBuilder.GCLayout.None; return new TypeBuilder.GCLayout(instanceGCLayout, false /* Always represents a valuetype as the reference type case is handled above with the GCLayout.SingleReference return */); } }
// Get the GC layout of a type. Handles pre-created, universal template, and non-universal template cases // Only to be used for getting the instance layout of non-valuetypes. /// <summary> /// Get the GC layout of a type. Handles pre-created, universal template, and non-universal template cases /// Only to be used for getting the instance layout of non-valuetypes that are used as base types /// </summary> /// <param name="type"></param> /// <returns></returns> private unsafe TypeBuilder.GCLayout GetInstanceGCLayout(TypeDesc type) { Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Any)); Debug.Assert(!type.IsValueType); if (type.RetrieveRuntimeTypeHandleIfPossible()) { return new TypeBuilder.GCLayout(type.RuntimeTypeHandle); } if (type.IsTemplateCanonical()) { var templateType = type.ComputeTemplate(); bool success = templateType.RetrieveRuntimeTypeHandleIfPossible(); Debug.Assert(success && !templateType.RuntimeTypeHandle.IsNull()); return new TypeBuilder.GCLayout(templateType.RuntimeTypeHandle); } else { TypeBuilderState state = type.GetOrCreateTypeBuilderState(); if (state.InstanceGCLayout == null) return TypeBuilder.GCLayout.None; else return new TypeBuilder.GCLayout(state.InstanceGCLayout, true); } }