| File: ILCompiler\Metadata\Transform.TypeForwarders.cs | Web Access |
| Project: 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; 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); Cts.ModuleDesc targetModule = (Cts.ModuleDesc)module.GetObject(exportedType.Implementation); record.Namespace = HandleNamespaceReference(targetModule, ns); HandleScopeDefinition(module).TypeForwarders.Add(record); } break; case Ecma.HandleKind.ExportedType: { TypeForwarder scope = HandleTypeForwarder(module, (Ecma.ExportedTypeHandle)exportedType.Implementation); record.Namespace = scope.Namespace; 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()); } } }