diff --git a/src/libraries/System.Reflection.Emit/System.Reflection.Emit.sln b/src/libraries/System.Reflection.Emit/System.Reflection.Emit.sln index d71e15aa37b804..b4fa6af73eaece 100644 --- a/src/libraries/System.Reflection.Emit/System.Reflection.Emit.sln +++ b/src/libraries/System.Reflection.Emit/System.Reflection.Emit.sln @@ -43,8 +43,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reflection.Metadata" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime", "..\System.Runtime\src\System.Runtime.csproj", "{BB96A2BA-44E9-43FA-91B1-CCEE212C6A8A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CodeDom", "..\System.CodeDom\src\System.CodeDom.csproj", "{D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reflection.MetadataLoadContext", "..\System.Reflection.MetadataLoadContext\src\System.Reflection.MetadataLoadContext.csproj", "{9F3970FF-F138-4F23-A2F8-2387858E723D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Collections.Immutable", "..\System.Collections.Immutable\src\System.Collections.Immutable.csproj", "{C2FF5BC7-825E-437E-92C3-F505EB6D1D40}" @@ -53,8 +51,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Collections.Immutabl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reflection.MetadataLoadContext", "..\System.Reflection.MetadataLoadContext\ref\System.Reflection.MetadataLoadContext.csproj", "{B2FAA0B4-2976-4742-B186-9C4928BCF9AF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CodeDom", "..\System.CodeDom\ref\System.CodeDom.csproj", "{501C1EA6-F7DB-4D3E-A212-F06689A831CD}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reflection.Metadata", "..\System.Reflection.Metadata\ref\System.Reflection.Metadata.csproj", "{E468274C-8F7E-49FC-BC2A-82C8B9E5B026}" EndProject Global @@ -319,24 +315,6 @@ Global {BB96A2BA-44E9-43FA-91B1-CCEE212C6A8A}.Release|x64.Build.0 = Release|Any CPU {BB96A2BA-44E9-43FA-91B1-CCEE212C6A8A}.Release|x86.ActiveCfg = Release|Any CPU {BB96A2BA-44E9-43FA-91B1-CCEE212C6A8A}.Release|x86.Build.0 = Release|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Checked|Any CPU.Build.0 = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Checked|x64.ActiveCfg = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Checked|x64.Build.0 = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Checked|x86.ActiveCfg = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Checked|x86.Build.0 = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Debug|x64.ActiveCfg = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Debug|x64.Build.0 = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Debug|x86.ActiveCfg = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Debug|x86.Build.0 = Debug|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Release|Any CPU.Build.0 = Release|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Release|x64.ActiveCfg = Release|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Release|x64.Build.0 = Release|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Release|x86.ActiveCfg = Release|Any CPU - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E}.Release|x86.Build.0 = Release|Any CPU {9F3970FF-F138-4F23-A2F8-2387858E723D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU {9F3970FF-F138-4F23-A2F8-2387858E723D}.Checked|Any CPU.Build.0 = Debug|Any CPU {9F3970FF-F138-4F23-A2F8-2387858E723D}.Checked|x64.ActiveCfg = Debug|Any CPU @@ -409,24 +387,6 @@ Global {B2FAA0B4-2976-4742-B186-9C4928BCF9AF}.Release|x64.Build.0 = Release|Any CPU {B2FAA0B4-2976-4742-B186-9C4928BCF9AF}.Release|x86.ActiveCfg = Release|Any CPU {B2FAA0B4-2976-4742-B186-9C4928BCF9AF}.Release|x86.Build.0 = Release|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Checked|Any CPU.Build.0 = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Checked|x64.ActiveCfg = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Checked|x64.Build.0 = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Checked|x86.ActiveCfg = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Checked|x86.Build.0 = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Debug|x64.ActiveCfg = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Debug|x64.Build.0 = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Debug|x86.ActiveCfg = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Debug|x86.Build.0 = Debug|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Release|Any CPU.Build.0 = Release|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Release|x64.ActiveCfg = Release|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Release|x64.Build.0 = Release|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Release|x86.ActiveCfg = Release|Any CPU - {501C1EA6-F7DB-4D3E-A212-F06689A831CD}.Release|x86.Build.0 = Release|Any CPU {E468274C-8F7E-49FC-BC2A-82C8B9E5B026}.Checked|Any CPU.ActiveCfg = Debug|Any CPU {E468274C-8F7E-49FC-BC2A-82C8B9E5B026}.Checked|Any CPU.Build.0 = Debug|Any CPU {E468274C-8F7E-49FC-BC2A-82C8B9E5B026}.Checked|x64.ActiveCfg = Debug|Any CPU @@ -466,12 +426,10 @@ Global {613C42F2-847A-42B3-9F5E-F5A670356BF7} = {C36D185D-9B3D-42E5-985F-E21B3BAF3B6D} {F33093A8-FF33-4F95-B256-F2AB712C956A} = {74F4AB97-3DBC-48FB-A2EA-2B4141749800} {BB96A2BA-44E9-43FA-91B1-CCEE212C6A8A} = {74F4AB97-3DBC-48FB-A2EA-2B4141749800} - {D13E80A9-A4E9-4399-A2C2-3008DA1C3B4E} = {2FC35C2F-76DB-4D84-B421-9700BEA4D161} {9F3970FF-F138-4F23-A2F8-2387858E723D} = {2FC35C2F-76DB-4D84-B421-9700BEA4D161} {C2FF5BC7-825E-437E-92C3-F505EB6D1D40} = {74F4AB97-3DBC-48FB-A2EA-2B4141749800} {DE04D45B-7E15-409D-A176-985D814A6AEB} = {C36D185D-9B3D-42E5-985F-E21B3BAF3B6D} {B2FAA0B4-2976-4742-B186-9C4928BCF9AF} = {C36D185D-9B3D-42E5-985F-E21B3BAF3B6D} - {501C1EA6-F7DB-4D3E-A212-F06689A831CD} = {C36D185D-9B3D-42E5-985F-E21B3BAF3B6D} {E468274C-8F7E-49FC-BC2A-82C8B9E5B026} = {C36D185D-9B3D-42E5-985F-E21B3BAF3B6D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj b/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj index 7da2c955d52e60..bc290ba0b8cf39 100644 --- a/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj +++ b/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj @@ -5,7 +5,6 @@ true - diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/AssemblyBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/AssemblyBuilderImpl.cs index ea7ec68d9d7e1d..d8543a23602b99 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/AssemblyBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/AssemblyBuilderImpl.cs @@ -11,10 +11,11 @@ namespace System.Reflection.Emit { internal sealed class AssemblyBuilderImpl : AssemblyBuilder { - private bool _previouslySaved; private readonly AssemblyName _assemblyName; private readonly Assembly _coreAssembly; + private readonly MetadataBuilder _metadataBuilder; private ModuleBuilderImpl? _module; + private bool _previouslySaved; internal AssemblyBuilderImpl(AssemblyName name, Assembly coreAssembly, IEnumerable? assemblyAttributes) { @@ -29,6 +30,7 @@ internal AssemblyBuilderImpl(AssemblyName name, Assembly coreAssembly, IEnumerab _assemblyName = name; _coreAssembly = coreAssembly; + _metadataBuilder = new MetadataBuilder(); if (assemblyAttributes != null) { @@ -42,7 +44,7 @@ internal AssemblyBuilderImpl(AssemblyName name, Assembly coreAssembly, IEnumerab internal static AssemblyBuilderImpl DefinePersistedAssembly(AssemblyName name, Assembly coreAssembly, IEnumerable? assemblyAttributes) => new AssemblyBuilderImpl(name, coreAssembly, assemblyAttributes); - private static void WritePEImage(Stream peStream, MetadataBuilder metadataBuilder, BlobBuilder ilBuilder) + private void WritePEImage(Stream peStream, BlobBuilder ilBuilder) { // Create executable with the managed metadata from the specified MetadataBuilder. var peHeaderBuilder = new PEHeaderBuilder( @@ -51,7 +53,7 @@ private static void WritePEImage(Stream peStream, MetadataBuilder metadataBuilde var peBuilder = new ManagedPEBuilder( peHeaderBuilder, - new MetadataRootBuilder(metadataBuilder), + new MetadataRootBuilder(_metadataBuilder), ilBuilder); // Write executable into the specified stream. @@ -75,13 +77,11 @@ internal void Save(Stream stream) } // Add assembly metadata - var metadata = new MetadataBuilder(); - - metadata.AddAssembly( - metadata.GetOrAddString(value: _assemblyName.Name!), + _metadataBuilder.AddAssembly( + _metadataBuilder.GetOrAddString(value: _assemblyName.Name!), version: _assemblyName.Version ?? new Version(0, 0, 0, 0), - culture: _assemblyName.CultureName == null ? default : metadata.GetOrAddString(value: _assemblyName.CultureName), - publicKey: _assemblyName.GetPublicKey() is byte[] publicKey ? metadata.GetOrAddBlob(value: publicKey) : default, + culture: _assemblyName.CultureName == null ? default : _metadataBuilder.GetOrAddString(value: _assemblyName.CultureName), + publicKey: _assemblyName.GetPublicKey() is byte[] publicKey ? _metadataBuilder.GetOrAddBlob(value: publicKey) : default, flags: AddContentType((AssemblyFlags)_assemblyName.Flags, _assemblyName.ContentType), #pragma warning disable SYSLIB0037 // Type or member is obsolete hashAlgorithm: (AssemblyHashAlgorithm)_assemblyName.HashAlgorithm @@ -89,10 +89,10 @@ internal void Save(Stream stream) ); // Add module's metadata - _module.AppendMetadata(metadata); + _module.AppendMetadata(); var ilBuilder = new BlobBuilder(); - WritePEImage(stream, metadata, ilBuilder); + WritePEImage(stream, ilBuilder); _previouslySaved = true; } @@ -114,7 +114,7 @@ protected override ModuleBuilder DefineDynamicModuleCore(string name) throw new InvalidOperationException(SR.InvalidOperation_NoMultiModuleAssembly); } - _module = new ModuleBuilderImpl(name, _coreAssembly); + _module = new ModuleBuilderImpl(name, _coreAssembly, _metadataBuilder); return _module; } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MetadataHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MetadataHelper.cs deleted file mode 100644 index 869c5ef3f11130..00000000000000 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MetadataHelper.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; - -namespace System.Reflection.Emit -{ - // This static helper class adds common entities to a MetadataBuilder. - internal static class MetadataHelper - { - internal static AssemblyReferenceHandle AddAssemblyReference(Assembly assembly, MetadataBuilder metadata) - { - AssemblyName assemblyName = assembly.GetName(); - - return AddAssemblyReference(metadata, assemblyName.Name!, assemblyName.Version, assemblyName.CultureName, - assemblyName.GetPublicKeyToken(), assemblyName.Flags, assemblyName.ContentType); - } - - internal static AssemblyReferenceHandle AddAssemblyReference(MetadataBuilder metadata, string name, Version? version, - string? culture, byte[]? publicKeyToken, AssemblyNameFlags flags, AssemblyContentType contentType) - { - return metadata.AddAssemblyReference( - name: metadata.GetOrAddString(name), - version: version ?? new Version(0, 0, 0, 0), - culture: (culture == null) ? default : metadata.GetOrAddString(value: culture), - publicKeyOrToken: (publicKeyToken == null) ? default : metadata.GetOrAddBlob(publicKeyToken), // reference has token, not full public key - flags: (AssemblyFlags)((int)contentType << 9) | ((flags & AssemblyNameFlags.Retargetable) != 0 ? AssemblyFlags.Retargetable : 0), - hashValue: default); // .file directive assemblies not supported, no need to handle this value. - } - - internal static TypeDefinitionHandle AddTypeDefinition(MetadataBuilder metadata, TypeBuilderImpl typeBuilder, EntityHandle baseType, int methodToken, int fieldToken) - { - // Add type metadata - return metadata.AddTypeDefinition( - attributes: typeBuilder.Attributes, - @namespace: (typeBuilder.Namespace == null) ? default : metadata.GetOrAddString(typeBuilder.Namespace), - name: metadata.GetOrAddString(typeBuilder.Name), - baseType: baseType, - fieldList: MetadataTokens.FieldDefinitionHandle(fieldToken), - methodList: MetadataTokens.MethodDefinitionHandle(methodToken)); - } - - internal static TypeReferenceHandle AddTypeReference(MetadataBuilder metadata, Type type, AssemblyReferenceHandle parent) - { - return AddTypeReference(metadata, parent, type.Name, type.Namespace); - } - - internal static TypeReferenceHandle AddTypeReference(MetadataBuilder metadata, AssemblyReferenceHandle parent, string name, string? nameSpace) - { - return metadata.AddTypeReference( - resolutionScope: parent, - @namespace: (nameSpace == null) ? default : metadata.GetOrAddString(nameSpace), - name: metadata.GetOrAddString(name) - ); - } - - internal static MethodDefinitionHandle AddMethodDefinition(MetadataBuilder metadata, MethodBuilderImpl methodBuilder, BlobBuilder methodSignatureBlob) - { - return metadata.AddMethodDefinition( - attributes: methodBuilder.Attributes, - implAttributes: MethodImplAttributes.IL, - name: metadata.GetOrAddString(methodBuilder.Name), - signature: metadata.GetOrAddBlob(methodSignatureBlob), - bodyOffset: -1, // No body supported yet - parameterList: MetadataTokens.ParameterHandle(1) - ); - } - - internal static FieldDefinitionHandle AddFieldDefinition(MetadataBuilder metadata, FieldInfo field, BlobBuilder fieldSignatureBlob) - { - return metadata.AddFieldDefinition( - attributes: field.Attributes, - name: metadata.GetOrAddString(field.Name), - signature: metadata.GetOrAddBlob(fieldSignatureBlob)); - } - } -} diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs index c63e4c26e5d47c..1262ae599fc39c 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs @@ -38,7 +38,7 @@ internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConv } internal BlobBuilder GetMethodSignatureBlob() => - MetadataSignatureHelper.MethodSignatureEncoder(_module, _parameterTypes, ReturnType, IsStatic); + MetadataSignatureHelper.MethodSignatureEncoder(_module, _parameterTypes, ReturnType, !IsStatic); protected override bool InitLocalsCore { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names) => throw new NotImplementedException(); diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 07dde6a0746ee6..8c17b6794c4126 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -2,6 +2,7 @@ // 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.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -13,20 +14,23 @@ internal sealed class ModuleBuilderImpl : ModuleBuilder { private readonly Assembly _coreAssembly; private readonly string _name; - private Type?[]? _coreTypes; - private readonly Dictionary _assemblyRefStore = new(); - private readonly Dictionary _typeRefStore = new(); - private readonly List _typeDefStore = new(); + private readonly MetadataBuilder _metadataBuilder; + private readonly Dictionary _assemblyReferences = new(); + private readonly Dictionary _typeReferences = new(); + private readonly List _typeDefinitions = new(); + private int _nextTypeDefRowId = 1; private int _nextMethodDefRowId = 1; private int _nextFieldDefRowId = 1; - private bool _coreTypesFullPopulated; + private bool _coreTypesFullyPopulated; + private Type?[]? _coreTypes; private static readonly Type[] s_coreTypes = { typeof(void), typeof(object), typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), - typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(string), typeof(nint), typeof(nuint) }; + typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(string), typeof(nint), typeof(nuint), typeof(TypedReference) }; - internal ModuleBuilderImpl(string name, Assembly coreAssembly) + internal ModuleBuilderImpl(string name, Assembly coreAssembly, MetadataBuilder builder) { _coreAssembly = coreAssembly; _name = name; + _metadataBuilder = builder; } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Types are preserved via s_coreTypes")] @@ -38,7 +42,7 @@ internal Type GetTypeFromCoreAssembly(CoreTypeId typeId) if (_coreAssembly == typeof(object).Assembly) { _coreTypes = s_coreTypes; - _coreTypesFullPopulated = true; + _coreTypesFullyPopulated = true; } else { @@ -59,7 +63,7 @@ internal Type GetTypeFromCoreAssembly(CoreTypeId typeId) if (_coreAssembly == typeof(object).Assembly) { _coreTypes = s_coreTypes; - _coreTypesFullPopulated = true; + _coreTypesFullyPopulated = true; } else { @@ -67,7 +71,7 @@ internal Type GetTypeFromCoreAssembly(CoreTypeId typeId) } } - if (!_coreTypesFullPopulated) + if (!_coreTypesFullyPopulated) { for (int i = 0; i < _coreTypes.Length; i++) { @@ -76,7 +80,7 @@ internal Type GetTypeFromCoreAssembly(CoreTypeId typeId) _coreTypes[i] = _coreAssembly.GetType(s_coreTypes[i].FullName!, throwOnError: false)!; } } - _coreTypesFullPopulated = true; + _coreTypesFullyPopulated = true; } for (int i = 0; i < _coreTypes.Length; i++) @@ -90,72 +94,127 @@ internal Type GetTypeFromCoreAssembly(CoreTypeId typeId) return null; } - internal void AppendMetadata(MetadataBuilder metadata) + internal void AppendMetadata() { // Add module metadata - metadata.AddModule( + _metadataBuilder.AddModule( generation: 0, - moduleName: metadata.GetOrAddString(_name), - mvid: metadata.GetOrAddGuid(Guid.NewGuid()), + moduleName: _metadataBuilder.GetOrAddString(_name), + mvid: _metadataBuilder.GetOrAddGuid(Guid.NewGuid()), encId: default, encBaseId: default); // Create type definition for the special type that holds global functions - metadata.AddTypeDefinition( + _metadataBuilder.AddTypeDefinition( attributes: default, @namespace: default, - name: metadata.GetOrAddString(""), + name: _metadataBuilder.GetOrAddString(""), baseType: default, fieldList: MetadataTokens.FieldDefinitionHandle(1), methodList: MetadataTokens.MethodDefinitionHandle(1)); ; // Add each type definition to metadata table. - foreach (TypeBuilderImpl typeBuilder in _typeDefStore) + foreach (TypeBuilderImpl typeBuilder in _typeDefinitions) { - TypeReferenceHandle parent = default; + EntityHandle parent = default; if (typeBuilder.BaseType is not null) { - // TODO: need to handle the case when the base is from same assembly - parent = GetTypeReference(metadata, typeBuilder.BaseType); + parent = GetTypeHandle(typeBuilder.BaseType); } - TypeDefinitionHandle typeDefinitionHandle = MetadataHelper.AddTypeDefinition(metadata, typeBuilder, parent, _nextMethodDefRowId, _nextFieldDefRowId); + TypeDefinitionHandle typeDefinitionHandle = AddTypeDefinition(typeBuilder, parent, _nextMethodDefRowId, _nextFieldDefRowId); + Debug.Assert(typeBuilder._handle.Equals(typeDefinitionHandle)); // Add each method definition to metadata table. foreach (MethodBuilderImpl method in typeBuilder._methodDefStore) { - MetadataHelper.AddMethodDefinition(metadata, method, method.GetMethodSignatureBlob()); + AddMethodDefinition(method, method.GetMethodSignatureBlob()); _nextMethodDefRowId++; } foreach (FieldBuilderImpl field in typeBuilder._fieldDefStore) { - MetadataHelper.AddFieldDefinition(metadata, field, MetadataSignatureHelper.FieldSignatureEncoder(field.FieldType, this)); + AddFieldDefinition(field, MetadataSignatureHelper.FieldSignatureEncoder(field.FieldType, this)); _nextFieldDefRowId++; } } } - private TypeReferenceHandle GetTypeReference(MetadataBuilder metadata, Type type) + private FieldDefinitionHandle AddFieldDefinition(FieldBuilderImpl field, BlobBuilder fieldSignature) => + _metadataBuilder.AddFieldDefinition( + attributes: field.Attributes, + name: _metadataBuilder.GetOrAddString(field.Name), + signature: _metadataBuilder.GetOrAddBlob(fieldSignature)); + + private TypeDefinitionHandle AddTypeDefinition(TypeBuilderImpl type, EntityHandle parent, int methodToken, int fieldToken) => + _metadataBuilder.AddTypeDefinition( + attributes: type.Attributes, + @namespace: (type.Namespace == null) ? default : _metadataBuilder.GetOrAddString(type.Namespace), + name: _metadataBuilder.GetOrAddString(type.Name), + baseType: parent, + fieldList: MetadataTokens.FieldDefinitionHandle(fieldToken), + methodList: MetadataTokens.MethodDefinitionHandle(methodToken)); + + private MethodDefinitionHandle AddMethodDefinition(MethodBuilderImpl method, BlobBuilder methodSignature) => + _metadataBuilder.AddMethodDefinition( + attributes: method.Attributes, + implAttributes: MethodImplAttributes.IL, + name: _metadataBuilder.GetOrAddString(method.Name), + signature: _metadataBuilder.GetOrAddBlob(methodSignature), + bodyOffset: -1, // No body supported yet + parameterList: MetadataTokens.ParameterHandle(1) + ); + + private TypeReferenceHandle AddTypeReference(Type type, AssemblyReferenceHandle parent) => + _metadataBuilder.AddTypeReference( + resolutionScope: parent, + @namespace: (type.Namespace == null) ? default : _metadataBuilder.GetOrAddString(type.Namespace), + name: _metadataBuilder.GetOrAddString(type.Name) + ); + + private TypeReferenceHandle GetTypeReference(Type type) { - if (!_typeRefStore.TryGetValue(type, out var parentHandle)) + if (!_typeReferences.TryGetValue(type, out var parentHandle)) { - parentHandle = MetadataHelper.AddTypeReference(metadata, type, - GetAssemblyReference(type.Assembly, metadata)); + parentHandle = AddTypeReference(type, GetAssemblyReference(type.Assembly)); + _typeReferences.Add(type, parentHandle); } return parentHandle; } - private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly, MetadataBuilder metadata) + private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly) { - if (_assemblyRefStore.TryGetValue(assembly, out var handle)) + if (!_assemblyReferences.TryGetValue(assembly, out var handle)) { - return handle; + AssemblyName aName = assembly.GetName(); + handle = AddAssemblyReference(aName.Name!, aName.Version, aName.CultureName, aName.GetPublicKeyToken(), aName.Flags, aName.ContentType); + _assemblyReferences.Add(assembly, handle); } - return MetadataHelper.AddAssemblyReference(assembly, metadata); + return handle; } + + private AssemblyReferenceHandle AddAssemblyReference(string name, Version? version, + string? culture, byte[]? publicKeyToken, AssemblyNameFlags flags, AssemblyContentType contentType) => + _metadataBuilder.AddAssemblyReference( + name: _metadataBuilder.GetOrAddString(name), + version: version ?? new Version(0, 0, 0, 0), + culture: (culture == null) ? default : _metadataBuilder.GetOrAddString(value: culture), + publicKeyOrToken: (publicKeyToken == null) ? default : _metadataBuilder.GetOrAddBlob(publicKeyToken), // reference has token, not full public key + flags: (AssemblyFlags)((int)contentType << 9) | ((flags & AssemblyNameFlags.Retargetable) != 0 ? AssemblyFlags.Retargetable : 0), + hashValue: default); // .file directive assemblies not supported, no need to handle this value. + + internal EntityHandle GetTypeHandle(Type type) + { + if (type is TypeBuilderImpl tb && Equals(tb.Module)) + { + return tb._handle; + } + + return GetTypeReference(type); + } + [RequiresAssemblyFiles("Returns for modules with no file path")] public override string Name => ""; public override string ScopeName => _name; @@ -173,8 +232,9 @@ private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly, Metadata protected override MethodBuilder DefinePInvokeMethodCore(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) => throw new NotImplementedException(); protected override TypeBuilder DefineTypeCore(string name, TypeAttributes attr, [DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] Type? parent, Type[]? interfaces, PackingSize packingSize, int typesize) { - TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this); - _typeDefStore.Add(_type); + TypeDefinitionHandle typeHandle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId); + TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, typeHandle); + _typeDefinitions.Add(_type); return _type; } protected override FieldBuilder DefineUninitializedDataCore(string name, int size, FieldAttributes attributes) => throw new NotImplementedException(); diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs index ad950b15152ac3..ad1701c35ecb97 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs @@ -7,14 +7,14 @@ namespace System.Reflection.Emit { - // TODO: Only support simple signatures. More complex signatures will be added. + // TODO: Only support simple signatures. More complex signatures (generics, array, byref, pointers etc) will be added. internal static class MetadataSignatureHelper { internal static BlobBuilder FieldSignatureEncoder(Type fieldType, ModuleBuilderImpl module) { BlobBuilder fieldSignature = new(); - WriteSignatureTypeForReflectionType(new BlobEncoder(fieldSignature).FieldSignature(), fieldType, module); + WriteSignatureForType(new BlobEncoder(fieldSignature).FieldSignature(), fieldType, module); return fieldSignature; } @@ -33,7 +33,7 @@ internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl module, Typ if (returnType != null && returnType != module.GetTypeFromCoreAssembly(CoreTypeId.Void)) { - WriteSignatureTypeForReflectionType(retEncoder.Type(), returnType, module); + WriteSignatureForType(retEncoder.Type(), returnType, module); } else // If null mark ReturnTypeEncoder as void { @@ -44,71 +44,74 @@ internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl module, Typ { foreach (Type parameter in parameters) { - WriteSignatureTypeForReflectionType(parEncoder.AddParameter().Type(), parameter, module); + WriteSignatureForType(parEncoder.AddParameter().Type(), parameter, module); } } return methodSignature; } - private static void WriteSignatureTypeForReflectionType(SignatureTypeEncoder signature, Type type, ModuleBuilderImpl module) + private static void WriteSignatureForType(SignatureTypeEncoder signature, Type type, ModuleBuilderImpl module) { CoreTypeId? typeId = module.GetTypeIdFromCoreTypes(type); - // We need to translate from Reflection.Type to SignatureTypeEncoder. switch (typeId) { case CoreTypeId.Boolean: signature.Boolean(); - break; + return; case CoreTypeId.Byte: signature.Byte(); - break; + return; case CoreTypeId.SByte: signature.SByte(); - break; + return; case CoreTypeId.Char: signature.Char(); - break; + return; case CoreTypeId.Int16: signature.Int16(); - break; + return; case CoreTypeId.UInt16: signature.UInt16(); - break; + return; case CoreTypeId.Int32: signature.Int32(); - break; + return; case CoreTypeId.UInt32: signature.UInt32(); - break; + return; case CoreTypeId.Int64: signature.Int64(); - break; + return; case CoreTypeId.UInt64: signature.UInt64(); - break; + return; case CoreTypeId.Single: signature.Single(); - break; + return; case CoreTypeId.Double: signature.Double(); - break; + return; case CoreTypeId.IntPtr: signature.IntPtr(); - break; + return; case CoreTypeId.UIntPtr: signature.UIntPtr(); - break; + return; case CoreTypeId.Object: signature.Object(); - break; + return; case CoreTypeId.String: signature.String(); - break; - default: - throw new NotSupportedException(SR.Format(SR.NotSupported_Signature, type.FullName)); + return; + case CoreTypeId.TypedReference: + signature.Builder.WriteByte((byte)SignatureTypeCode.TypedReference); + return; } + + EntityHandle typeHandle = module.GetTypeHandle(type); + signature.Type(typeHandle, type.IsValueType); } } @@ -131,5 +134,6 @@ internal enum CoreTypeId String, IntPtr, UIntPtr, + TypedReference, } } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs index 71548abab22ef7..16558aa05ceef4 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs @@ -5,6 +5,8 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Globalization; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; namespace System.Reflection.Emit { @@ -15,17 +17,19 @@ internal sealed class TypeBuilderImpl : TypeBuilder private readonly ModuleBuilderImpl _module; private readonly string _name; private readonly string? _namespace; + internal readonly TypeDefinitionHandle _handle; [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private Type? _typeParent; private TypeAttributes _attributes; internal TypeBuilderImpl(string fullName, TypeAttributes typeAttributes, - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, ModuleBuilderImpl module) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, ModuleBuilderImpl module, TypeDefinitionHandle handle) { _name = fullName; _module = module; _attributes = typeAttributes; SetParent(parent); + _handle = handle; // Extract namespace from fullName int idx = _name.LastIndexOf('.'); @@ -112,10 +116,10 @@ protected override void SetParentCore([DynamicallyAccessedMembers(DynamicallyAcc public override string? Namespace => _namespace; public override Assembly Assembly => _module.Assembly; public override Module Module => _module; - public override Type UnderlyingSystemType => throw new NotSupportedException(); + public override Type UnderlyingSystemType => this; public override Guid GUID => throw new NotSupportedException(); public override Type? BaseType => _typeParent; - + public override int MetadataToken => MetadataTokens.GetToken(_handle); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public override object? InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target, object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters) => throw new NotSupportedException(); diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTestsWithVariousTypes.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTestsWithVariousTypes.cs index c459a9be15a56c..22b85bc9693d96 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTestsWithVariousTypes.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTestsWithVariousTypes.cs @@ -56,14 +56,13 @@ public static IEnumerable VariousInterfacesStructsTestData() { yield return new object[] { new Type[] { typeof(INoMethod) } }; yield return new object[] { new Type[] { typeof(IMultipleMethod) } }; - yield return new object[] { new Type[] { typeof(INoMethod), typeof(INoMethod2) } }; yield return new object[] { new Type[] { typeof(INoMethod), typeof(IOneMethod) } }; - yield return new object[] { new Type[] { typeof(IMultipleMethod), typeof(INoMethod2) } }; - yield return new object[] { new Type[] { typeof(IMultipleMethod), typeof(INoMethod2), typeof(IAccess), typeof(IOneMethod), typeof(INoMethod) } }; + yield return new object[] { new Type[] { typeof(IMultipleMethod), typeof(EmptyTestClass) } }; + yield return new object[] { new Type[] { typeof(IMultipleMethod), typeof(EmptyTestClass), typeof(IAccess), typeof(IOneMethod), typeof(INoMethod) } }; yield return new object[] { new Type[] { typeof(EmptyStruct) } }; - yield return new object[] { new Type[] { typeof(StructWithField) } }; - yield return new object[] { new Type[] { typeof(StructWithField), typeof(EmptyStruct) } }; - yield return new object[] { new Type[] { typeof(IMultipleMethod), typeof(EmptyStruct), typeof(INoMethod2), typeof(StructWithField) } }; + yield return new object[] { new Type[] { typeof(StructWithFields) } }; + yield return new object[] { new Type[] { typeof(StructWithFields), typeof(EmptyStruct) } }; + yield return new object[] { new Type[] { typeof(IMultipleMethod), typeof(StructWithFields), typeof(ClassWithFields), typeof(EmptyTestClass) } }; } [Theory] @@ -177,40 +176,47 @@ public void CreateMembersThatUsesTypeLoadedFromCoreAssemblyTest() } } - // Test Interfaces + // Test Types public interface INoMethod { } - public interface INoMethod2 - { - } - public interface IMultipleMethod { string Func(); - bool MoreFunc(); - double DoIExist(); + IOneMethod MoreFunc(); + StructWithFields DoIExist(); void BuildAPerpetualMotionMachine(); } internal interface IAccess { - public int BuildAI(); + public Version BuildAI(); public int DisableRogueAI(); } public interface IOneMethod { - string Func(); + object Func(); } public struct EmptyStruct { } - public struct StructWithField + public struct StructWithFields + { + public int field1; + public string field2; + } + + public class EmptyTestClass + { + } + + public class ClassWithFields : EmptyTestClass { - public int field; + public EmptyTestClass field1; + public byte field2; } } diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblyTools.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblyTools.cs index 16d16ff84d7ec4..b07c04b2ea755b 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblyTools.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblyTools.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices; namespace System.Reflection.Emit.Tests { @@ -88,6 +87,7 @@ internal static Assembly LoadAssemblyFromStream(Stream stream) => internal sealed class CoreMetadataAssemblyResolver : MetadataAssemblyResolver { public static Assembly s_coreAssembly = typeof(object).Assembly; + public static Assembly s_emitAssembly = typeof(AssemblyTools).Assembly; public CoreMetadataAssemblyResolver() { } public override Assembly Resolve(MetadataLoadContext context, AssemblyName assemblyName) @@ -109,12 +109,26 @@ public override Assembly Resolve(MetadataLoadContext context, AssemblyName assem return _coreAssembly; } + if (name.Equals("System.Reflection.Emit.Tests", StringComparison.OrdinalIgnoreCase)) + { + if (_emitAssembly == null) + { + _emitAssembly = context.LoadFromStream(CreateStreamForEmitAssembly()); + } + + return _emitAssembly; + } + return null; } + private Assembly _emitAssembly; private Assembly _coreAssembly; - public static Stream CreateStreamForCoreAssembly() + private Stream CreateStreamForEmitAssembly() => + File.OpenRead(AssemblyPathHelper.GetAssemblyLocation(s_emitAssembly)); + + private static Stream CreateStreamForCoreAssembly() { // We need a core assembly in IL form. Since this version of this code is for Jitted platforms, the System.Private.Corelib // of the underlying runtime will do just fine.