File: src\System\Reflection\Emit\RuntimeTypeBuilder.cs
Web Access
Project: src\src\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj (System.Private.CoreLib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using CultureInfo = System.Globalization.CultureInfo;
 
namespace System.Reflection.Emit
{
    internal sealed partial class RuntimeTypeBuilder : TypeBuilder
    {
        public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo)
        {
            if (typeInfo == null) return false;
            return IsAssignableFrom(typeInfo.AsType());
        }
 
        #region Declarations
        private sealed class CustAttr
        {
            private readonly ConstructorInfo? m_con;
            private readonly byte[]? m_binaryAttribute;
            private readonly CustomAttributeBuilder? m_customBuilder;
 
            public CustAttr(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
            {
                ArgumentNullException.ThrowIfNull(con);
 
                m_con = con;
                m_binaryAttribute = binaryAttribute.ToArray();
            }
 
            public CustAttr(CustomAttributeBuilder customBuilder)
            {
                ArgumentNullException.ThrowIfNull(customBuilder);
 
                m_customBuilder = customBuilder;
            }
 
            public void Bake(RuntimeModuleBuilder module, int token)
            {
                if (m_customBuilder == null)
                {
                    Debug.Assert(m_con != null);
                    DefineCustomAttribute(module, token, module.GetMethodMetadataToken(m_con),
                        m_binaryAttribute);
                }
                else
                {
                    m_customBuilder.CreateCustomAttribute(module, token);
                }
            }
        }
        #endregion
 
        #region Private Static FCalls
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_SetParentType")]
        private static partial void SetParentType(QCallModule module, int tdTypeDef, int tkParent);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_AddInterfaceImpl")]
        private static partial void AddInterfaceImpl(QCallModule module, int tdTypeDef, int tkInterface);
        #endregion
 
        #region Internal Static FCalls
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineMethod", StringMarshalling = StringMarshalling.Utf16)]
        internal static partial int DefineMethod(QCallModule module, int tkParent, string name, byte[] signature, int sigLength,
            MethodAttributes attributes);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineMethodSpec")]
        internal static partial int DefineMethodSpec(QCallModule module, int tkParent, byte[] signature, int sigLength);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineField", StringMarshalling = StringMarshalling.Utf16)]
        internal static partial int DefineField(QCallModule module, int tkParent, string name, byte[] signature, int sigLength,
            FieldAttributes attributes);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_SetMethodIL")]
        private static partial void SetMethodIL(QCallModule module, int tk, [MarshalAs(UnmanagedType.Bool)] bool isInitLocals,
            byte[]? body, int bodyLength,
            byte[] LocalSig, int sigLength,
            int maxStackSize,
            ExceptionHandler[]? exceptions, int numExceptions,
            int[]? tokenFixups, int numTokenFixups);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineCustomAttribute")]
        private static partial void DefineCustomAttribute(QCallModule module, int tkAssociate, int tkConstructor,
            ReadOnlySpan<byte> attr, int attrLength);
 
        internal static void DefineCustomAttribute(RuntimeModuleBuilder module, int tkAssociate, int tkConstructor,
            ReadOnlySpan<byte> attr)
        {
            DefineCustomAttribute(new QCallModule(ref module), tkAssociate, tkConstructor,
                attr, attr.Length);
        }
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineProperty", StringMarshalling = StringMarshalling.Utf16)]
        internal static partial int DefineProperty(QCallModule module, int tkParent, string name, PropertyAttributes attributes,
            byte[] signature, int sigLength);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineEvent", StringMarshalling = StringMarshalling.Utf16)]
        internal static partial int DefineEvent(QCallModule module, int tkParent, string name, EventAttributes attributes, int tkEventType);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineMethodSemantics")]
        internal static partial void DefineMethodSemantics(QCallModule module, int tkAssociation,
            MethodSemanticsAttributes semantics, int tkMethod);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineMethodImpl")]
        internal static partial void DefineMethodImpl(QCallModule module, int tkType, int tkBody, int tkDecl);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_SetMethodImpl")]
        internal static partial void SetMethodImpl(QCallModule module, int tkMethod, MethodImplAttributes MethodImplAttributes);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_SetParamInfo", StringMarshalling = StringMarshalling.Utf16)]
        internal static partial int SetParamInfo(QCallModule module, int tkMethod, int iSequence,
            ParameterAttributes iParamAttributes, string? strParamName);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_GetTokenFromSig")]
        internal static partial int GetTokenFromSig(QCallModule module, byte[] signature, int sigLength);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_SetFieldLayoutOffset")]
        internal static partial void SetFieldLayoutOffset(QCallModule module, int fdToken, int iOffset);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_SetClassLayout")]
        internal static partial void SetClassLayout(QCallModule module, int tk, PackingSize iPackingSize, int iTypeSize);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_SetConstantValue")]
        private static unsafe partial void SetConstantValue(QCallModule module, int tk, int corType, void* pValue);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_SetPInvokeData", StringMarshalling = StringMarshalling.Utf16)]
        private static partial void SetPInvokeData(QCallModule module, string DllName, string name, int token, int linkFlags);
 
        #endregion
        #region Internal\Private Static Members
 
        internal static bool IsTypeEqual(Type? t1, Type? t2)
        {
            // Maybe we are lucky that they are equal in the first place
            if (t1 == t2)
                return true;
            RuntimeTypeBuilder? tb1 = null;
            RuntimeTypeBuilder? tb2 = null;
            Type? runtimeType1;
            Type? runtimeType2;
 
            // set up the runtimeType and TypeBuilder type corresponding to t1 and t2
            if (t1 is RuntimeTypeBuilder rtb1)
            {
                tb1 = rtb1;
                // This will be null if it is not baked.
                runtimeType1 = tb1.m_bakedRuntimeType;
            }
            else
            {
                runtimeType1 = t1;
            }
 
            if (t2 is RuntimeTypeBuilder rtb2)
            {
                tb2 = rtb2;
                // This will be null if it is not baked.
                runtimeType2 = tb2.m_bakedRuntimeType;
            }
            else
            {
                runtimeType2 = t2;
            }
 
            // If the type builder view is equal then it is equal
            if (tb1 != null && tb2 != null && ReferenceEquals(tb1, tb2))
                return true;
 
            // if the runtimetype view is eqaul than it is equal
            if (runtimeType1 != null && runtimeType2 != null && runtimeType1 == runtimeType2)
                return true;
 
            return false;
        }
 
        internal static unsafe void SetConstantValue(RuntimeModuleBuilder module, int tk, Type destType, object? value)
        {
            // This is a helper function that is used by ParameterBuilder, PropertyBuilder,
            // and FieldBuilder to validate a default value and save it in the meta-data.
 
            if (value != null)
            {
                Type type = value.GetType();
 
                // We should allow setting a constant value on a ByRef parameter
                if (destType.IsByRef)
                    destType = destType.GetElementType()!;
 
                // Convert nullable types to their underlying type.
                // This is necessary for nullable enum types to pass the IsEnum check that's coming next.
                destType = Nullable.GetUnderlyingType(destType) ?? destType;
 
                if (destType.IsEnum)
                {
                    // |                                   |  UnderlyingSystemType     |  Enum.GetUnderlyingType() |  IsEnum
                    // |-----------------------------------|---------------------------|---------------------------|---------
                    // | runtime Enum Type                 |  self                     |  underlying type of enum  |  TRUE
                    // | EnumBuilder                       |  underlying type of enum  |  underlying type of enum* |  TRUE
                    // | TypeBuilder of enum types**       |  underlying type of enum  |  Exception                |  TRUE
                    // | TypeBuilder of enum types (baked) |  runtime enum type        |  Exception                |  TRUE
 
                    // *: the behavior of Enum.GetUnderlyingType(EnumBuilder) might change in the future
                    //     so let's not depend on it.
                    // **: created with System.Enum as the parent type.
 
                    // The above behaviors might not be the most consistent but we have to live with them.
 
                    Type? underlyingType;
                    if (destType is RuntimeEnumBuilder enumBldr)
                    {
                        underlyingType = enumBldr.GetEnumUnderlyingType();
 
                        // The constant value supplied should match either the baked enum type or its underlying type
                        // we don't need to compare it with the EnumBuilder itself because you can never have an object of that type
                        if (type != enumBldr.m_typeBuilder.m_bakedRuntimeType && type != underlyingType)
                            throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
                    }
                    else if (destType is RuntimeTypeBuilder typeBldr)
                    {
                        underlyingType = typeBldr.m_enumUnderlyingType;
 
                        // The constant value supplied should match either the baked enum type or its underlying type
                        // typeBldr.m_enumUnderlyingType is null if the user hasn't created a "value__" field on the enum
                        if (underlyingType == null || (type != typeBldr.UnderlyingSystemType && type != underlyingType))
                            throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
                    }
                    else // must be a runtime Enum Type
                    {
                        Debug.Assert(destType is RuntimeType, "destType is not a runtime type, an EnumBuilder, or a TypeBuilder.");
 
                        underlyingType = Enum.GetUnderlyingType(destType);
 
                        // The constant value supplied should match either the enum itself or its underlying type
                        if (type != destType && type != underlyingType)
                            throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
                    }
 
                    type = underlyingType;
                }
                else
                {
                    // Note that it is non CLS compliant if destType != type. But RefEmit never guarantees CLS-Compliance.
                    if (!destType.IsAssignableFrom(type))
                        throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
                }
 
                CorElementType corType = RuntimeTypeHandle.GetCorElementType((RuntimeType)type);
 
                switch (corType)
                {
                    case CorElementType.ELEMENT_TYPE_I1:
                    case CorElementType.ELEMENT_TYPE_U1:
                    case CorElementType.ELEMENT_TYPE_BOOLEAN:
                    case CorElementType.ELEMENT_TYPE_I2:
                    case CorElementType.ELEMENT_TYPE_U2:
                    case CorElementType.ELEMENT_TYPE_CHAR:
                    case CorElementType.ELEMENT_TYPE_I4:
                    case CorElementType.ELEMENT_TYPE_U4:
                    case CorElementType.ELEMENT_TYPE_R4:
                    case CorElementType.ELEMENT_TYPE_I8:
                    case CorElementType.ELEMENT_TYPE_U8:
                    case CorElementType.ELEMENT_TYPE_R8:
                        fixed (byte* pData = &value.GetRawData())
                            SetConstantValue(new QCallModule(ref module), tk, (int)corType, pData);
                        break;
 
                    default:
                        if (type == typeof(string))
                        {
                            fixed (char* pString = (string)value)
                                SetConstantValue(new QCallModule(ref module), tk, (int)CorElementType.ELEMENT_TYPE_STRING, pString);
                        }
                        else if (type == typeof(DateTime))
                        {
                            // date is a I8 representation
                            long ticks = ((DateTime)value).Ticks;
                            SetConstantValue(new QCallModule(ref module), tk, (int)CorElementType.ELEMENT_TYPE_I8, &ticks);
                        }
                        else
                        {
                            throw new ArgumentException(SR.Format(SR.Argument_ConstantNotSupported, type));
                        }
                        break;
                }
            }
            else
            {
                // A null default value in metadata is permissible even for non-nullable value types.
                // (See ECMA-335 II.15.4.1.4 "The .param directive" and II.22.9 "Constant" for details.)
                // This is how the Roslyn compilers generally encode `default(TValueType)` default values.
 
                SetConstantValue(new QCallModule(ref module), tk, (int)CorElementType.ELEMENT_TYPE_CLASS, null);
            }
        }
 
        #endregion
 
        #region Private Data Members
        private List<CustAttr>? m_ca;
        private int m_tdType;
        private readonly RuntimeModuleBuilder m_module;
        private readonly string? m_strName;
        private readonly string? m_strNameSpace;
        private string? m_strFullQualName;
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
        private Type? m_typeParent;
 
        private List<Type>? m_typeInterfaces;
        private readonly TypeAttributes m_iAttr;
        private GenericParameterAttributes m_genParamAttributes;
        internal List<RuntimeMethodBuilder>? m_listMethods;
        internal int m_lastTokenizedMethod;
        private int m_constructorCount;
        private readonly int m_iTypeSize;
        private readonly PackingSize m_iPackingSize;
        private readonly RuntimeTypeBuilder? m_DeclaringType;
 
        // We cannot store this on EnumBuilder because users can define enum types manually using TypeBuilder.
        private Type? m_enumUnderlyingType;
        internal bool m_isHiddenGlobalType;
        private bool m_hasBeenCreated;
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
        private RuntimeType m_bakedRuntimeType = null!;
 
        private readonly int m_genParamPos;
        private RuntimeGenericTypeParameterBuilder[]? m_inst;
        private readonly bool m_bIsGenParam;
        private readonly RuntimeMethodBuilder? m_declMeth;
        private readonly RuntimeTypeBuilder? m_genTypeDef;
        #endregion
 
        #region Constructor
        // ctor for the global (module) type
        internal RuntimeTypeBuilder(RuntimeModuleBuilder module)
        {
            m_tdType = ((int)MetadataTokenType.TypeDef);
            m_isHiddenGlobalType = true;
            m_module = module;
            m_listMethods = new List<RuntimeMethodBuilder>();
            // No token has been created so let's initialize it to -1
            // The first time we call MethodBuilder.GetToken this will incremented.
            m_lastTokenizedMethod = -1;
        }
 
        // ctor for generic method parameter
        internal RuntimeTypeBuilder(string szName, int genParamPos, RuntimeMethodBuilder declMeth)
        {
            m_strName = szName;
            m_genParamPos = genParamPos;
            m_bIsGenParam = true;
            m_typeInterfaces = new List<Type>();
 
            Debug.Assert(declMeth != null);
            m_declMeth = declMeth;
            m_DeclaringType = m_declMeth.GetTypeBuilder();
            m_module = declMeth.GetModuleBuilder();
        }
 
        // ctor for generic type parameter
        private RuntimeTypeBuilder(string szName, int genParamPos, RuntimeTypeBuilder declType)
        {
            m_strName = szName;
            m_genParamPos = genParamPos;
            m_bIsGenParam = true;
            m_typeInterfaces = new List<Type>();
 
            Debug.Assert(declType != null);
            m_DeclaringType = declType;
            m_module = declType.GetModuleBuilder();
        }
 
        internal RuntimeTypeBuilder(
            string name, TypeAttributes attr, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, RuntimeModuleBuilder module,
            PackingSize iPackingSize, int iTypeSize, RuntimeTypeBuilder? enclosingType)
        {
            if (name[0] == '\0')
                throw new ArgumentException(SR.Argument_IllegalName, nameof(name));
 
            if (name.Length > 1023)
                throw new ArgumentException(SR.Argument_TypeNameTooLong, nameof(name));
 
            int i;
            m_module = module;
            m_DeclaringType = enclosingType;
            RuntimeAssemblyBuilder containingAssem = m_module.ContainingAssemblyBuilder;
 
            // cannot have two types within the same assembly of the same name
            containingAssem.CheckTypeNameConflict(name, enclosingType);
 
            if (enclosingType != null)
            {
                // Nested Type should have nested attribute set.
                // If we are renumbering TypeAttributes' bit, we need to change the logic here.
                if (((attr & TypeAttributes.VisibilityMask) == TypeAttributes.Public) || ((attr & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic))
                    throw new ArgumentException(SR.Argument_BadNestedTypeFlags, nameof(attr));
            }
 
            int[]? interfaceTokens = null;
            if (interfaces != null)
            {
                interfaceTokens = new int[interfaces.Length + 1];
                for (i = 0; i < interfaces.Length; i++)
                {
                    // cannot contain null in the interface list
                    ArgumentNullException.ThrowIfNull(interfaces[i], nameof(interfaces));
                    interfaceTokens[i] = m_module.GetTypeTokenInternal(interfaces[i]);
                }
            }
 
            int iLast = name.LastIndexOf('.');
            if (iLast <= 0)
            {
                // no name space
                m_strNameSpace = string.Empty;
                m_strName = name;
            }
            else
            {
                // split the name space
                m_strNameSpace = name.Substring(0, iLast);
                m_strName = name.Substring(iLast + 1);
            }
 
            VerifyTypeAttributes(attr);
 
            m_iAttr = attr;
 
            SetParent(parent);
 
            m_listMethods = new List<RuntimeMethodBuilder>();
            m_lastTokenizedMethod = -1;
 
            SetInterfaces(interfaces);
 
            int tkParent = 0;
            if (m_typeParent != null)
                tkParent = m_module.GetTypeTokenInternal(m_typeParent);
 
            int tkEnclosingType = 0;
            if (enclosingType != null)
            {
                tkEnclosingType = enclosingType.m_tdType;
            }
 
            m_tdType = DefineType(new QCallModule(ref module),
                name, tkParent, m_iAttr, tkEnclosingType, interfaceTokens!);
 
            m_iPackingSize = iPackingSize;
            m_iTypeSize = iTypeSize;
            if ((m_iPackingSize != 0) || (m_iTypeSize != 0))
                SetClassLayout(new QCallModule(ref module), m_tdType, m_iPackingSize, m_iTypeSize);
 
            m_module.AddType(FullName!, this);
        }
 
        #endregion
        #region Private Members
        private FieldBuilder DefineDataHelper(string name, byte[]? data, int size, FieldAttributes attributes)
        {
            string strValueClassName;
            TypeBuilder? valueClassType;
            FieldBuilder fdBuilder;
            TypeAttributes typeAttributes;
 
            ArgumentException.ThrowIfNullOrEmpty(name);
 
            if (size <= 0 || size >= 0x003f0000)
                throw new ArgumentException(SR.Argument_BadSizeForData);
 
            ThrowIfCreated();
 
            // form the value class name
            strValueClassName = $"$ArrayType${size}";
 
            // Is this already defined in this module?
            Type? temp = m_module.FindTypeBuilderWithName(strValueClassName, false);
            valueClassType = temp as TypeBuilder;
 
            if (valueClassType == null)
            {
                typeAttributes = TypeAttributes.Public | TypeAttributes.ExplicitLayout | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass;
 
                // Define the backing value class
                valueClassType = m_module.DefineType(strValueClassName, typeAttributes, typeof(ValueType), PackingSize.Size1, size);
                valueClassType.CreateType();
            }
 
            fdBuilder = DefineField(name, valueClassType, attributes | FieldAttributes.Static);
 
            // now we need to set the RVA
            ((RuntimeFieldBuilder)fdBuilder).SetData(data, size);
            return fdBuilder;
        }
 
        private void VerifyTypeAttributes(TypeAttributes attr)
        {
            // Verify attr consistency for Nesting or otherwise.
            if (DeclaringType == null)
            {
                // Not a nested class.
                if (((attr & TypeAttributes.VisibilityMask) != TypeAttributes.NotPublic) && ((attr & TypeAttributes.VisibilityMask) != TypeAttributes.Public))
                {
                    throw new ArgumentException(SR.Argument_BadTypeAttrNestedVisibilityOnNonNestedType);
                }
            }
            else
            {
                // Nested class.
                if (((attr & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic) || ((attr & TypeAttributes.VisibilityMask) == TypeAttributes.Public))
                {
                    throw new ArgumentException(SR.Argument_BadTypeAttrNonNestedVisibilityNestedType);
                }
            }
 
            // Verify that the layout mask is valid.
            if (((attr & TypeAttributes.LayoutMask) != TypeAttributes.AutoLayout) && ((attr & TypeAttributes.LayoutMask) != TypeAttributes.SequentialLayout) && ((attr & TypeAttributes.LayoutMask) != TypeAttributes.ExplicitLayout))
            {
                throw new ArgumentException(SR.Argument_BadTypeAttrInvalidLayout);
            }
 
            // Check if the user attempted to set any reserved bits.
            if ((attr & TypeAttributes.ReservedMask) != 0)
            {
                throw new ArgumentException(SR.Argument_BadTypeAttrReservedBitsSet);
            }
        }
 
        protected override bool IsCreatedCore()
        {
            return m_hasBeenCreated;
        }
        #endregion
 
        #region FCalls
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineType", StringMarshalling = StringMarshalling.Utf16)]
        private static partial int DefineType(QCallModule module,
            string fullname, int tkParent, TypeAttributes attributes, int tkEnclosingType, int[] interfaceTokens);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineGenericParam", StringMarshalling = StringMarshalling.Utf16)]
        private static partial int DefineGenericParam(QCallModule module,
            string name, int tkParent, GenericParameterAttributes attributes, int position, int[] constraints);
 
        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_TermCreateClass")]
        private static partial void TermCreateClass(QCallModule module, int tk, ObjectHandleOnStack type);
        #endregion
 
        #region Internal Methods
        internal void ThrowIfCreated()
        {
            if (IsCreated())
                throw new InvalidOperationException(SR.InvalidOperation_TypeHasBeenCreated);
        }
 
        internal object SyncRoot => m_module.SyncRoot;
 
        internal RuntimeModuleBuilder GetModuleBuilder()
        {
            return m_module;
        }
 
        internal RuntimeType BakedRuntimeType => m_bakedRuntimeType;
 
        internal void SetGenParamAttributes(GenericParameterAttributes genericParameterAttributes)
        {
            m_genParamAttributes = genericParameterAttributes;
        }
 
        internal void SetGenParamCustomAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
        {
            CustAttr ca = new CustAttr(con, binaryAttribute);
 
            lock (SyncRoot)
            {
                SetGenParamCustomAttributeNoLock(ca);
            }
        }
 
        internal void SetGenParamCustomAttribute(CustomAttributeBuilder customBuilder)
        {
            CustAttr ca = new CustAttr(customBuilder);
 
            lock (SyncRoot)
            {
                SetGenParamCustomAttributeNoLock(ca);
            }
        }
 
        private void SetGenParamCustomAttributeNoLock(CustAttr ca)
        {
            m_ca ??= new List<CustAttr>();
            m_ca.Add(ca);
        }
        #endregion
 
        #region Object Overrides
        public override string ToString()
        {
            return TypeNameBuilder.ToString(this, TypeNameBuilder.Format.ToString)!;
        }
 
        #endregion
 
        #region MemberInfo Overrides
        public override Type? DeclaringType => m_DeclaringType;
 
        public override Type? ReflectedType => m_DeclaringType;
 
        public override string Name =>
                // one of the constructors allows this to be null but it is only used internally without accessing Name
                m_strName!;
 
        public override Module Module => GetModuleBuilder();
 
        public override bool IsByRefLike => false;
 
        public override int MetadataToken => m_tdType;
 
        #endregion
 
        #region Type Overrides
        public override Guid GUID
        {
            get
            {
                if (!IsCreated())
                    throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
                return m_bakedRuntimeType.GUID;
            }
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
        public override object? InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target,
            object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
        }
 
        public override Assembly Assembly => m_module.Assembly;
 
        public override RuntimeTypeHandle TypeHandle => throw new NotSupportedException(SR.NotSupported_DynamicModule);
 
        public override string? FullName => m_strFullQualName ??= TypeNameBuilder.ToString(this, TypeNameBuilder.Format.FullName);
 
        public override string? Namespace => m_strNameSpace;
 
        public override string? AssemblyQualifiedName => TypeNameBuilder.ToString(this, TypeNameBuilder.Format.AssemblyQualifiedName);
 
        public override Type? BaseType => m_typeParent;
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
        protected override ConstructorInfo? GetConstructorImpl(BindingFlags bindingAttr, Binder? binder,
                CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetConstructor(bindingAttr, binder, callConvention, types, modifiers);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
        public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetConstructors(bindingAttr);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
        protected override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder,
                CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            if (types == null)
            {
                return m_bakedRuntimeType.GetMethod(name, bindingAttr);
            }
            else
            {
                return m_bakedRuntimeType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
            }
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
        public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetMethods(bindingAttr);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
        public override FieldInfo? GetField(string name, BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetField(name, bindingAttr);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
        public override FieldInfo[] GetFields(BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetFields(bindingAttr);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
        public override Type? GetInterface(string name, bool ignoreCase)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetInterface(name, ignoreCase);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
        public override Type[] GetInterfaces()
        {
            if (m_bakedRuntimeType != null)
            {
                return m_bakedRuntimeType.GetInterfaces();
            }
 
            if (m_typeInterfaces == null)
            {
                return EmptyTypes;
            }
 
            return m_typeInterfaces.ToArray();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
        public override EventInfo? GetEvent(string name, BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetEvent(name, bindingAttr);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)]
        public override EventInfo[] GetEvents()
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetEvents();
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
        protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder,
                Type? returnType, Type[]? types, ParameterModifier[]? modifiers)
        {
            throw new NotSupportedException(SR.NotSupported_DynamicModule);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
        public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetProperties(bindingAttr);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
        public override Type[] GetNestedTypes(BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetNestedTypes(bindingAttr);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
        public override Type? GetNestedType(string name, BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetNestedType(name, bindingAttr);
        }
 
        [DynamicallyAccessedMembers(GetAllMembers)]
        public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetMember(name, type, bindingAttr);
        }
 
        public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type interfaceType)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetInterfaceMap(interfaceType);
        }
 
        [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
        public override EventInfo[] GetEvents(BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetEvents(bindingAttr);
        }
 
        [DynamicallyAccessedMembers(GetAllMembers)]
        public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return m_bakedRuntimeType.GetMembers(bindingAttr);
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
            Justification = "The GetInterfaces technically requires all interfaces to be preserved" +
                "But in this case it acts only on TypeBuilder which is never trimmed (as it's runtime created).")]
        public override bool IsAssignableFrom([NotNullWhen(true)] Type? c)
        {
            if (IsTypeEqual(c, this))
                return true;
 
            Type? fromRuntimeType;
            RuntimeTypeBuilder? fromTypeBuilder = c as RuntimeTypeBuilder;
 
            if (fromTypeBuilder != null)
                fromRuntimeType = fromTypeBuilder.m_bakedRuntimeType;
            else
                fromRuntimeType = c;
 
            if (fromRuntimeType != null && fromRuntimeType is RuntimeType)
            {
                // fromType is baked. So if this type is not baked, it cannot be assignable to!
                if (m_bakedRuntimeType == null)
                    return false;
 
                // since toType is also baked, delegate to the base
                return m_bakedRuntimeType.IsAssignableFrom(fromRuntimeType);
            }
 
            // So if c is not a runtimeType nor TypeBuilder. We don't know how to deal with it.
            // return false then.
            if (fromTypeBuilder == null)
                return false;
 
            // If fromTypeBuilder is a subclass of this class, then c can be cast to this type.
            if (fromTypeBuilder.IsSubclassOf(this))
                return true;
 
            if (!IsInterface)
                return false;
 
            // now is This type a base type on one of the interface impl?
            Type[] interfaces = fromTypeBuilder.GetInterfaces();
            for (int i = 0; i < interfaces.Length; i++)
            {
                // unfortunately, IsSubclassOf does not cover the case when they are the same type.
                if (IsTypeEqual(interfaces[i], this))
                    return true;
 
                if (interfaces[i].IsSubclassOf(this))
                    return true;
            }
            return false;
        }
 
        protected override TypeAttributes GetAttributeFlagsImpl()
        {
            return m_iAttr;
        }
 
        public override bool IsTypeDefinition => true;
 
        public override bool IsSZArray => false;
 
        protected override bool IsArrayImpl()
        {
            return false;
        }
        protected override bool IsByRefImpl()
        {
            return false;
        }
        protected override bool IsPointerImpl()
        {
            return false;
        }
        protected override bool IsPrimitiveImpl()
        {
            return false;
        }
 
        protected override bool IsCOMObjectImpl()
        {
            return ((GetAttributeFlagsImpl() & TypeAttributes.Import) != 0) ? true : false;
        }
 
        public override Type GetElementType()
        {
            // You will never have to deal with a TypeBuilder if you are just referring to arrays.
            throw new NotSupportedException(SR.NotSupported_DynamicModule);
        }
 
        protected override bool HasElementTypeImpl()
        {
            return false;
        }
 
        public override bool IsSecurityCritical => true;
 
        public override bool IsSecuritySafeCritical => false;
 
        public override bool IsSecurityTransparent => false;
 
        public override bool IsSubclassOf(Type c)
        {
            Type? p = this;
 
            if (IsTypeEqual(p, c))
                return false;
 
            p = p.BaseType;
 
            while (p != null)
            {
                if (IsTypeEqual(p, c))
                    return true;
 
                p = p.BaseType;
            }
 
            return false;
        }
 
        public override Type UnderlyingSystemType
        {
            get
            {
                if (m_bakedRuntimeType != null)
                    return m_bakedRuntimeType;
 
                if (IsEnum)
                {
                    if (m_enumUnderlyingType == null)
                        throw new InvalidOperationException(SR.InvalidOperation_NoUnderlyingTypeOnEnum);
 
                    return m_enumUnderlyingType;
                }
                else
                {
                    return this;
                }
            }
        }
 
        #endregion
 
        #region ICustomAttributeProvider Implementation
        public override object[] GetCustomAttributes(bool inherit)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            return CustomAttribute.GetCustomAttributes(m_bakedRuntimeType, (typeof(object) as RuntimeType)!, inherit);
        }
 
        public override object[] GetCustomAttributes(Type attributeType, bool inherit)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            ArgumentNullException.ThrowIfNull(attributeType);
 
            if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType)
                throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType));
 
            return CustomAttribute.GetCustomAttributes(m_bakedRuntimeType, attributeRuntimeType, inherit);
        }
 
        public override bool IsDefined(Type attributeType, bool inherit)
        {
            if (!IsCreated())
                throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated);
 
            ArgumentNullException.ThrowIfNull(attributeType);
 
            if (attributeType.UnderlyingSystemType is not RuntimeType attributeRuntimeType)
                throw new ArgumentException(SR.Arg_MustBeType, nameof(attributeType));
 
            return CustomAttribute.IsDefined(m_bakedRuntimeType, attributeRuntimeType, inherit);
        }
 
        #endregion
 
        #region Public Member
 
        #region DefineType
        public override GenericParameterAttributes GenericParameterAttributes => m_genParamAttributes;
 
        internal void SetInterfaces(params Type[]? interfaces)
        {
            ThrowIfCreated();
 
            m_typeInterfaces = new List<Type>();
            if (interfaces != null)
            {
                m_typeInterfaces.AddRange(interfaces);
            }
        }
 
        protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names)
        {
            if (m_inst != null)
            {
                throw new InvalidOperationException();
            }
 
            m_inst = new RuntimeGenericTypeParameterBuilder[names.Length];
            for (int i = 0; i < names.Length; i++)
            {
                string name = names[i];
                ArgumentNullException.ThrowIfNull(name, nameof(names));
                m_inst[i] = new RuntimeGenericTypeParameterBuilder(new RuntimeTypeBuilder(name, i, this));
            }
 
            return m_inst;
        }
 
        public override Type[] GetGenericArguments() => m_inst ?? EmptyTypes;
 
        // If a TypeBuilder is generic, it must be a generic type definition
        // All instantiated generic types are TypeBuilderInstantiation.
        public override bool IsGenericTypeDefinition => IsGenericType;
        public override bool IsGenericType => m_inst != null;
        public override bool IsGenericParameter => m_bIsGenParam;
        public override bool IsConstructedGenericType => false;
 
        public override int GenericParameterPosition => m_genParamPos;
        public override MethodBase? DeclaringMethod => m_declMeth;
        public override Type GetGenericTypeDefinition() { if (IsGenericTypeDefinition) return this; if (m_genTypeDef == null) throw new InvalidOperationException(); return m_genTypeDef; }
        #endregion
 
        #region Define Method
        protected override void DefineMethodOverrideCore(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration)
        {
            lock (SyncRoot)
            {
                ThrowIfCreated();
 
                if (!ReferenceEquals(methodInfoBody.DeclaringType, this))
                    // Loader restriction: body method has to be from this class
                    throw new ArgumentException(SR.ArgumentException_BadMethodImplBody);
 
                int tkBody = m_module.GetMethodMetadataToken(methodInfoBody);
                int tkDecl = m_module.GetMethodMetadataToken(methodInfoDeclaration);
 
                RuntimeModuleBuilder module = m_module;
                DefineMethodImpl(new QCallModule(ref module), m_tdType, tkBody, tkDecl);
            }
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2082:UnrecognizedReflectionPattern",
            Justification = "Reflection.Emit is not subject to trimming")]
        protected override MethodBuilder DefineMethodCore(string name, MethodAttributes attributes, CallingConventions callingConvention,
            Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers,
            Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers)
        {
            lock (SyncRoot)
            {
                ThrowIfCreated();
 
                // pass in Method attributes
                RuntimeMethodBuilder method = new RuntimeMethodBuilder(
                    name, attributes, callingConvention,
                    returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
                    parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers,
                    m_module, this);
 
                if (!m_isHiddenGlobalType)
                {
                    // If this method is declared to be a constructor, increment our constructor count.
                    if ((method.Attributes & MethodAttributes.SpecialName) != 0 && method.Name.Equals(ConstructorInfo.ConstructorName))
                    {
                        m_constructorCount++;
                    }
                }
 
                m_listMethods!.Add(method);
 
                return method;
            }
        }
 
        [RequiresUnreferencedCode("P/Invoke marshalling may dynamically access members that could be trimmed.")]
        protected override MethodBuilder DefinePInvokeMethodCore(string name, string dllName, string entryName, MethodAttributes attributes,
            CallingConventions callingConvention,
            Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers,
            Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers,
            CallingConvention nativeCallConv, CharSet nativeCharSet)
        {
            lock (SyncRoot)
            {
                if ((attributes & MethodAttributes.Abstract) != 0)
                    throw new ArgumentException(SR.Argument_BadPInvokeMethod);
 
                if ((m_iAttr & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
                    throw new ArgumentException(SR.Argument_BadPInvokeOnInterface);
 
                ThrowIfCreated();
 
                attributes |= MethodAttributes.PinvokeImpl;
                RuntimeMethodBuilder method = new RuntimeMethodBuilder(name, attributes, callingConvention,
                    returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
                    parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers,
                    m_module, this);
 
                // The signature grabbing code has to be up here or the signature won't be finished
                // and our equals check won't work.
                _ = method.GetMethodSignature().InternalGetSignature(out _);
 
                if (m_listMethods!.Contains(method))
                {
                    throw new ArgumentException(SR.Argument_MethodRedefined);
                }
                m_listMethods.Add(method);
 
                int token = method.MetadataToken;
 
                int linkFlags = 0;
                switch (nativeCallConv)
                {
                    case CallingConvention.Winapi:
                        linkFlags = (int)PInvokeAttributes.CallConvWinapi;
                        break;
                    case CallingConvention.Cdecl:
                        linkFlags = (int)PInvokeAttributes.CallConvCdecl;
                        break;
                    case CallingConvention.StdCall:
                        linkFlags = (int)PInvokeAttributes.CallConvStdcall;
                        break;
                    case CallingConvention.ThisCall:
                        linkFlags = (int)PInvokeAttributes.CallConvThiscall;
                        break;
                    case CallingConvention.FastCall:
                        linkFlags = (int)PInvokeAttributes.CallConvFastcall;
                        break;
                }
                switch (nativeCharSet)
                {
                    case CharSet.None:
                        linkFlags |= (int)PInvokeAttributes.CharSetNotSpec;
                        break;
                    case CharSet.Ansi:
                        linkFlags |= (int)PInvokeAttributes.CharSetAnsi;
                        break;
                    case CharSet.Unicode:
                        linkFlags |= (int)PInvokeAttributes.CharSetUnicode;
                        break;
                    case CharSet.Auto:
                        linkFlags |= (int)PInvokeAttributes.CharSetAuto;
                        break;
                }
 
                RuntimeModuleBuilder module = m_module;
                SetPInvokeData(new QCallModule(ref module),
                    dllName,
                    entryName,
                    token,
                    linkFlags);
 
                method.SetToken(token);
 
                return method;
            }
        }
        #endregion
 
        #region Define Constructor
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2082:UnrecognizedReflectionPattern",
            Justification = "Reflection.Emit is not subject to trimming")]
        protected override ConstructorBuilder DefineTypeInitializerCore()
        {
            lock (SyncRoot)
            {
                ThrowIfCreated();
 
                // change the attributes and the class constructor's name
                const MethodAttributes attr = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName;
 
                ConstructorBuilder constBuilder = new RuntimeConstructorBuilder(
                    ConstructorInfo.TypeConstructorName, attr, CallingConventions.Standard, null, m_module, this);
 
                return constBuilder;
            }
        }
 
        protected override ConstructorBuilder DefineDefaultConstructorCore(MethodAttributes attributes)
        {
            if ((m_iAttr & TypeAttributes.Interface) == TypeAttributes.Interface)
            {
                throw new InvalidOperationException(SR.InvalidOperation_ConstructorNotAllowedOnInterface);
            }
 
            lock (SyncRoot)
            {
                return DefineDefaultConstructorNoLock(attributes);
            }
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern",
            Justification = "MakeGenericType is only called on a TypeBuilderInstantiation which is not subject to trimming")]
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
            Justification = "GetConstructor is only called on a TypeBuilderInstantiation which is not subject to trimming")]
        private RuntimeConstructorBuilder DefineDefaultConstructorNoLock(MethodAttributes attributes)
        {
            RuntimeConstructorBuilder constBuilder;
 
            // get the parent class's default constructor
            // We really don't want(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic) here.  We really want
            // constructors visible from the subclass, but that is not currently
            // available in BindingFlags.  This more open binding is open to
            // runtime binding failures(like if we resolve to a private
            // constructor).
            ConstructorInfo? con = null;
 
            if (m_typeParent is TypeBuilderInstantiation)
            {
                Type? genericTypeDefinition = m_typeParent.GetGenericTypeDefinition();
 
                if (genericTypeDefinition is RuntimeTypeBuilder rtBuilder)
                    genericTypeDefinition = rtBuilder.m_bakedRuntimeType;
 
                if (genericTypeDefinition == null)
                    throw new NotSupportedException(SR.NotSupported_DynamicModule);
 
                Type inst = genericTypeDefinition.MakeGenericType(m_typeParent.GetGenericArguments());
 
                if (inst is TypeBuilderInstantiation)
                    con = GetConstructor(inst, genericTypeDefinition.GetConstructor(
                        BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, EmptyTypes, null)!);
                else
                    con = inst.GetConstructor(
                        BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, EmptyTypes, null);
            }
 
            con ??= m_typeParent!.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, EmptyTypes, null);
 
            if (con == null)
                throw new NotSupportedException(SR.NotSupported_NoParentDefaultConstructor);
 
            // Define the constructor Builder
            constBuilder = (RuntimeConstructorBuilder)DefineConstructor(attributes, CallingConventions.Standard, null);
 
            // generate the code to call the parent's default constructor
            ILGenerator il = constBuilder.GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, con);
            il.Emit(OpCodes.Ret);
 
            constBuilder.m_isDefaultConstructor = true;
            return constBuilder;
        }
 
        protected override ConstructorBuilder DefineConstructorCore(MethodAttributes attributes, CallingConventions callingConvention,
            Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers)
        {
            if ((m_iAttr & TypeAttributes.Interface) == TypeAttributes.Interface && (attributes & MethodAttributes.Static) != MethodAttributes.Static)
            {
                throw new InvalidOperationException(SR.InvalidOperation_ConstructorNotAllowedOnInterface);
            }
 
            lock (SyncRoot)
            {
                return DefineConstructorNoLock(attributes, callingConvention, parameterTypes, requiredCustomModifiers, optionalCustomModifiers);
            }
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2082:UnrecognizedReflectionPattern",
            Justification = "Reflection.Emit is not subject to trimming")]
        private ConstructorBuilder DefineConstructorNoLock(MethodAttributes attributes, CallingConventions callingConvention,
            Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers)
        {
            ThrowIfCreated();
 
            string name;
 
            if ((attributes & MethodAttributes.Static) == 0)
            {
                name = ConstructorInfo.ConstructorName;
            }
            else
            {
                name = ConstructorInfo.TypeConstructorName;
            }
 
            attributes |= MethodAttributes.SpecialName;
 
            ConstructorBuilder constBuilder =
                new RuntimeConstructorBuilder(name, attributes, callingConvention,
                    parameterTypes, requiredCustomModifiers, optionalCustomModifiers, m_module, this);
 
            m_constructorCount++;
 
            return constBuilder;
        }
 
        #endregion
 
        #region Define Nested Type
        protected override TypeBuilder DefineNestedTypeCore(string name, TypeAttributes attr, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, PackingSize packSize, int typeSize)
        {
            lock (SyncRoot)
            {
                return new RuntimeTypeBuilder(name, attr, parent, interfaces, m_module, packSize, typeSize, this);
            }
        }
 
        #endregion
 
        #region Define Field
        protected override FieldBuilder DefineFieldCore(string fieldName, Type type, Type[]? requiredCustomModifiers,
            Type[]? optionalCustomModifiers, FieldAttributes attributes)
        {
            lock (SyncRoot)
            {
                ThrowIfCreated();
 
                if (m_enumUnderlyingType == null && IsEnum)
                {
                    if ((attributes & FieldAttributes.Static) == 0)
                    {
                        // remember the underlying type for enum type
                        m_enumUnderlyingType = type;
                    }
                }
 
                return new RuntimeFieldBuilder(this, fieldName, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
            }
        }
 
        protected override FieldBuilder DefineInitializedDataCore(string name, byte[] data, FieldAttributes attributes)
        {
            lock (SyncRoot)
            {
                // This method will define an initialized Data in .sdata.
                // We will create a fake TypeDef to represent the data with size. This TypeDef
                // will be the signature for the Field.
 
                return DefineDataHelper(name, data, data.Length, attributes);
            }
        }
 
        protected override FieldBuilder DefineUninitializedDataCore(string name, int size, FieldAttributes attributes)
        {
            lock (SyncRoot)
            {
                // This method will define an uninitialized Data in .sdata.
                // We will create a fake TypeDef to represent the data with size. This TypeDef
                // will be the signature for the Field.
                return DefineDataHelper(name, null, size, attributes);
            }
        }
 
        #endregion
 
        #region Define Properties and Events
 
        protected override PropertyBuilder DefinePropertyCore(string name, PropertyAttributes attributes, CallingConventions callingConvention,
            Type returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers,
            Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers)
        {
            lock (SyncRoot)
            {
                SignatureHelper sigHelper;
                byte[] sigBytes;
 
                ThrowIfCreated();
 
                // get the signature in SignatureHelper form
                sigHelper = SignatureHelper.GetPropertySigHelper(
                    m_module, callingConvention,
                    returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
                    parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
 
                // get the signature in byte form
                sigBytes = sigHelper.InternalGetSignature(out int sigLength);
 
                RuntimeModuleBuilder module = m_module;
 
                int prToken = DefineProperty(
                    new QCallModule(ref module),
                    m_tdType,
                    name,
                    attributes,
                    sigBytes,
                    sigLength);
 
                // create the property builder now.
                return new RuntimePropertyBuilder(
                        m_module,
                        name,
                        attributes,
                        returnType,
                        prToken,
                        this);
            }
        }
 
        protected override EventBuilder DefineEventCore(string name, EventAttributes attributes, Type eventtype)
        {
            if (name[0] == '\0')
            {
                throw new ArgumentException(SR.Argument_IllegalName, nameof(name));
            }
 
            lock (SyncRoot)
            {
                int tkType;
                int evToken;
 
                ThrowIfCreated();
 
                tkType = m_module.GetTypeTokenInternal(eventtype);
 
                // Internal helpers to define property records
                RuntimeModuleBuilder module = m_module;
                evToken = DefineEvent(
                    new QCallModule(ref module),
                    m_tdType,
                    name,
                    attributes,
                    tkType);
 
                // create the property builder now.
                return new RuntimeEventBuilder(
                        m_module,
                        name,
                        attributes,
                        this,
                        evToken);
            }
        }
 
        #endregion
 
        #region Create Type
 
        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
        protected override TypeInfo CreateTypeInfoCore()
        {
            TypeInfo? typeInfo = CreateTypeInfoImpl();
            Debug.Assert(m_isHiddenGlobalType || typeInfo != null);
            return typeInfo!;
        }
 
        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
        internal TypeInfo? CreateTypeInfoImpl()
        {
            lock (SyncRoot)
            {
                return CreateTypeNoLock();
            }
        }
 
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2083:UnrecognizedReflectionPattern",
            Justification = "Reflection.Emit is not subject to trimming")]
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2068:UnrecognizedReflectionPattern",
            Justification = "Reflection.Emit is not subject to trimming")]
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2069:UnrecognizedReflectionPattern",
            Justification = "Reflection.Emit is not subject to trimming")]
        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
        private TypeInfo? CreateTypeNoLock()
        {
            if (IsCreated())
                return m_bakedRuntimeType;
 
            m_typeInterfaces ??= new List<Type>();
 
            int[] interfaceTokens = new int[m_typeInterfaces.Count];
            for (int i = 0; i < m_typeInterfaces.Count; i++)
            {
                interfaceTokens[i] = m_module.GetTypeTokenInternal(m_typeInterfaces[i]);
            }
 
            int tkParent = 0;
            if (m_typeParent != null)
            {
                tkParent = m_module.GetTypeTokenInternal(m_typeParent);
            }
 
            RuntimeModuleBuilder module = m_module;
 
            if (IsGenericParameter)
            {
                int[] constraints; // Array of token constrains terminated by null token
 
                if (m_typeParent != null)
                {
                    constraints = new int[m_typeInterfaces.Count + 2];
                    constraints[^2] = tkParent;
                }
                else
                {
                    constraints = new int[m_typeInterfaces.Count + 1];
                }
 
                for (int i = 0; i < m_typeInterfaces.Count; i++)
                {
                    constraints[i] = m_module.GetTypeTokenInternal(m_typeInterfaces[i]);
                }
 
                int declMember = m_declMeth == null ? m_DeclaringType!.m_tdType : m_declMeth.MetadataToken;
                m_tdType = DefineGenericParam(new QCallModule(ref module),
                    m_strName!, declMember, m_genParamAttributes, m_genParamPos, constraints);
 
                if (m_ca != null)
                {
                    foreach (CustAttr ca in m_ca)
                        ca.Bake(m_module, MetadataToken);
                }
 
                m_hasBeenCreated = true;
 
                // Baking a generic parameter does not put sufficient information into the metadata to actually be able to load it as a type,
                // the associated generic type/method needs to be baked first. So we return this rather than the baked type.
                return this;
            }
            else
            {
                // Check for global typebuilder
                if (((m_tdType & 0x00FFFFFF) != 0) && ((tkParent & 0x00FFFFFF) != 0))
                {
                    SetParentType(new QCallModule(ref module), m_tdType, tkParent);
                }
 
                if (m_inst != null)
                {
                    foreach (RuntimeGenericTypeParameterBuilder tb in m_inst)
                    {
                        tb.m_type.CreateType();
                    }
                }
            }
 
            if (!m_isHiddenGlobalType)
            {
                // create a public default constructor if this class has no constructor.
                // except if the type is Interface, ValueType, Enum, or a static class.
                if (m_constructorCount == 0 && ((m_iAttr & TypeAttributes.Interface) == 0) && !IsValueType && ((m_iAttr & (TypeAttributes.Abstract | TypeAttributes.Sealed)) != (TypeAttributes.Abstract | TypeAttributes.Sealed)))
                {
                    DefineDefaultConstructor(MethodAttributes.Public);
                }
            }
 
            int size = m_listMethods!.Count;
 
            for (int i = 0; i < size; i++)
            {
                RuntimeMethodBuilder meth = m_listMethods[i];
 
                if (meth.IsGenericMethodDefinition)
                {
                    _ = meth.MetadataToken; // Doubles as "CreateMethod" for MethodBuilder -- analogous to CreateType()
                }
 
                MethodAttributes methodAttrs = meth.Attributes;
 
                // Any of these flags in the implementation flags is set, we will not attach the IL method body
                if (((meth.GetMethodImplementationFlags() & (MethodImplAttributes.CodeTypeMask | MethodImplAttributes.PreserveSig | MethodImplAttributes.Unmanaged)) != MethodImplAttributes.IL) ||
                    ((methodAttrs & MethodAttributes.PinvokeImpl) != (MethodAttributes)0))
                {
                    continue;
                }
 
                byte[] localSig = meth.GetLocalSignature(out int sigLength);
 
                // Check that they haven't declared an abstract method on a non-abstract class
                if (((methodAttrs & MethodAttributes.Abstract) != 0) && ((m_iAttr & TypeAttributes.Abstract) == 0))
                {
                    throw new InvalidOperationException(SR.InvalidOperation_BadTypeAttributesNotAbstract);
                }
 
                byte[]? body = meth.GetBody();
 
                // If this is an abstract method or an interface, we don't need to set the IL.
 
                if ((methodAttrs & MethodAttributes.Abstract) != 0)
                {
                    // We won't check on Interface because we can have class static initializer on interface.
                    // We will just let EE or validator to catch the problem.
 
                    // ((m_iAttr & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface))
 
                    if (body != null)
                        throw new InvalidOperationException(SR.Format(SR.InvalidOperation_BadMethodBody, meth.Name));
                }
                else if (body == null || body.Length == 0)
                {
                    // If it's not an abstract or an interface, set the IL.
                    if (meth.m_ilGenerator != null)
                    {
                        // we need to bake the method here.
                        meth.CreateMethodBodyHelper(((RuntimeILGenerator)meth.GetILGenerator()));
                    }
 
                    body = meth.GetBody();
 
                    if ((body == null || body.Length == 0) && !meth.m_canBeRuntimeImpl)
                        throw new InvalidOperationException(
                            SR.Format(SR.InvalidOperation_BadEmptyMethodBody, meth.Name));
                }
 
                int maxStack = meth.GetMaxStack();
 
                ExceptionHandler[]? exceptions = meth.GetExceptionHandlers();
                int[]? tokenFixups = meth.GetTokenFixups();
 
                SetMethodIL(new QCallModule(ref module), meth.MetadataToken, meth.InitLocals,
                    body, (body != null) ? body.Length : 0,
                    localSig, sigLength, maxStack,
                    exceptions, (exceptions != null) ? exceptions.Length : 0,
                    tokenFixups, (tokenFixups != null) ? tokenFixups.Length : 0);
 
                if (m_module.ContainingAssemblyBuilder._access == AssemblyBuilderAccess.Run)
                {
                    // if we don't need the data structures to build the method any more
                    // throw them away.
                    meth.ReleaseBakedStructures();
                }
            }
 
            m_hasBeenCreated = true;
 
            // Terminate the process.
            RuntimeType? cls = null;
            TermCreateClass(new QCallModule(ref module), m_tdType, ObjectHandleOnStack.Create(ref cls));
 
            if (!m_isHiddenGlobalType)
            {
                m_bakedRuntimeType = cls!;
 
                // if this type is a nested type, we need to invalidate the cached nested runtime type on the nesting type
                if (m_DeclaringType != null && m_DeclaringType.m_bakedRuntimeType != null)
                {
                    m_DeclaringType.m_bakedRuntimeType.InvalidateCachedNestedType();
                }
 
                return cls;
            }
            else
            {
                return null;
            }
        }
 
        #endregion
 
        #region Misc
        protected override int SizeCore => m_iTypeSize;
 
        protected override PackingSize PackingSizeCore => m_iPackingSize;
 
        protected override void SetParentCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent)
        {
            ThrowIfCreated();
 
            if (parent != null)
            {
                if (parent.IsInterface)
                    throw new ArgumentException(SR.Argument_CannotSetParentToInterface);
 
                m_typeParent = parent;
            }
            else
            {
                if ((m_iAttr & TypeAttributes.Interface) != TypeAttributes.Interface)
                {
                    m_typeParent = typeof(object);
                }
                else
                {
                    if ((m_iAttr & TypeAttributes.Abstract) == 0)
                        throw new InvalidOperationException(SR.InvalidOperation_BadInterfaceNotAbstract);
 
                    // there is no extends for interface class
                    m_typeParent = null;
                }
            }
        }
 
        protected override void AddInterfaceImplementationCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type interfaceType)
        {
            ThrowIfCreated();
 
            int tkInterface = m_module.GetTypeTokenInternal(interfaceType);
            RuntimeModuleBuilder module = m_module;
            AddInterfaceImpl(new QCallModule(ref module), m_tdType, tkInterface);
 
            m_typeInterfaces!.Add(interfaceType);
        }
 
        internal int TypeToken
        {
            get
            {
                if (IsGenericParameter)
                    ThrowIfCreated();
 
                return m_tdType;
            }
        }
 
        internal void SetCustomAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
        {
            SetCustomAttributeCore(con, binaryAttribute);
        }
 
        protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
        {
            DefineCustomAttribute(m_module, m_tdType, m_module.GetMethodMetadataToken(con), binaryAttribute);
        }
 
        #endregion
 
        #endregion
    }
}