| File: ILCompiler\Metadata\Transform.TypeForwarders.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.MetadataTransform\ILCompiler.MetadataTransform.csproj (ILCompiler.MetadataTransform) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using Internal.Metadata.NativeFormat.Writer; using Cts = Internal.TypeSystem; using Ecma = System.Reflection.Metadata; using Debug = System.Diagnostics.Debug; using AssemblyNameInfo = System.Reflection.Metadata.AssemblyNameInfo; using AssemblyContentType = System.Reflection.AssemblyContentType; using AssemblyNameFlags = System.Reflection.AssemblyNameFlags; using AssemblyFlags = System.Reflection.AssemblyFlags; namespace ILCompiler.Metadata { internal partial class Transform<TPolicy> { private EntityMap<ForwarderKey, TypeForwarder> _forwarders = new EntityMap<ForwarderKey, TypeForwarder>(EqualityComparer<ForwarderKey>.Default); private Action<ForwarderKey, TypeForwarder> _initForwarder; private void HandleTypeForwarders(Cts.Ecma.EcmaModule module) { foreach (var exportedTypeHandle in module.MetadataReader.ExportedTypes) { if (!_policy.GeneratesMetadata(module, exportedTypeHandle)) { continue; } Ecma.ExportedType exportedType = module.MetadataReader.GetExportedType(exportedTypeHandle); if (exportedType.IsForwarder || exportedType.Implementation.Kind == Ecma.HandleKind.ExportedType) { HandleTypeForwarder(module, exportedTypeHandle); } else { Debug.Fail("Multi-module assemblies"); } } } private TypeForwarder HandleTypeForwarder(Cts.Ecma.EcmaModule module, Ecma.ExportedTypeHandle handle) { return _forwarders.GetOrCreate(new ForwarderKey(module, handle), _initForwarder ??= InitializeTypeForwarder); } private void InitializeTypeForwarder(ForwarderKey key, TypeForwarder record) { Cts.Ecma.EcmaModule module = key.Module; Ecma.MetadataReader reader = module.MetadataReader; Ecma.ExportedType exportedType = reader.GetExportedType(key.ExportedType); record.Name = HandleString(reader.GetString(exportedType.Name)); switch (exportedType.Implementation.Kind) { case Ecma.HandleKind.AssemblyReference: { string ns = reader.GetString(exportedType.Namespace); NamespaceDefinition namespaceDefinition = HandleNamespaceDefinition(module, ns); Ecma.AssemblyReference assemblyRef = reader.GetAssemblyReference((Ecma.AssemblyReferenceHandle)exportedType.Implementation); AssemblyNameInfo refName = new AssemblyNameInfo ( name: reader.GetString(assemblyRef.Name), version: assemblyRef.Version, cultureName: reader.GetString(assemblyRef.Culture), flags: (AssemblyNameFlags)assemblyRef.Flags, publicKeyOrToken: reader.GetBlobContent(assemblyRef.PublicKeyOrToken) ); record.Scope = HandleScopeReference(refName); namespaceDefinition.TypeForwarders.Add(record); } break; case Ecma.HandleKind.ExportedType: { TypeForwarder scope = HandleTypeForwarder(module, (Ecma.ExportedTypeHandle)exportedType.Implementation); record.Scope = scope.Scope; scope.NestedTypes.Add(record); } break; default: throw new BadImageFormatException(); } } #pragma warning disable CA1067 // Override Object.Equals(object) when implementing IEquatable<T> private readonly struct ForwarderKey : IEquatable<ForwarderKey> #pragma warning restore CA1067 // Override Object.Equals(object) when implementing IEquatable<T> { public readonly Cts.Ecma.EcmaModule Module; public readonly Ecma.ExportedTypeHandle ExportedType; public ForwarderKey(Cts.Ecma.EcmaModule module, Ecma.ExportedTypeHandle exportedType) => (Module, ExportedType) = (module, exportedType); public bool Equals(ForwarderKey other) => Module == other.Module && ExportedType == other.ExportedType; public override int GetHashCode() => HashCode.Combine(Module.GetHashCode(), ExportedType.GetHashCode()); } } }