Skip to content

Commit 1a31bf6

Browse files
Fix generation of type forwarders (#67570)
These need to be interned to account for nested forwarders. We were erroneously generating multiple containing forwarders whenever there's a nested one.
1 parent c585bd7 commit 1a31bf6

File tree

1 file changed

+31
-18
lines changed

1 file changed

+31
-18
lines changed

src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.TypeForwarders.cs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5+
using System.Collections.Generic;
56

67
using Internal.Metadata.NativeFormat.Writer;
78

@@ -18,6 +19,10 @@ namespace ILCompiler.Metadata
1819
{
1920
partial class Transform<TPolicy>
2021
{
22+
private EntityMap<ForwarderKey, TypeForwarder> _forwarders = new EntityMap<ForwarderKey, TypeForwarder>(EqualityComparer<ForwarderKey>.Default);
23+
24+
private Action<ForwarderKey, TypeForwarder> _initForwarder;
25+
2126
private void HandleTypeForwarders(Cts.Ecma.EcmaModule module)
2227
{
2328
foreach (var exportedTypeHandle in module.MetadataReader.ExportedTypes)
@@ -30,7 +35,7 @@ private void HandleTypeForwarders(Cts.Ecma.EcmaModule module)
3035
Ecma.ExportedType exportedType = module.MetadataReader.GetExportedType(exportedTypeHandle);
3136
if (exportedType.IsForwarder || exportedType.Implementation.Kind == Ecma.HandleKind.ExportedType)
3237
{
33-
HandleTypeForwarder(module, exportedType);
38+
HandleTypeForwarder(module, exportedTypeHandle);
3439
}
3540
else
3641
{
@@ -39,11 +44,18 @@ private void HandleTypeForwarders(Cts.Ecma.EcmaModule module)
3944
}
4045
}
4146

42-
private TypeForwarder HandleTypeForwarder(Cts.Ecma.EcmaModule module, Ecma.ExportedType exportedType)
47+
private TypeForwarder HandleTypeForwarder(Cts.Ecma.EcmaModule module, Ecma.ExportedTypeHandle handle)
48+
{
49+
return _forwarders.GetOrCreate(new ForwarderKey(module, handle), _initForwarder ?? (_initForwarder = InitializeTypeForwarder));
50+
}
51+
52+
private void InitializeTypeForwarder(ForwarderKey key, TypeForwarder record)
4353
{
54+
Cts.Ecma.EcmaModule module = key.Module;
4455
Ecma.MetadataReader reader = module.MetadataReader;
45-
string name = reader.GetString(exportedType.Name);
46-
TypeForwarder result;
56+
Ecma.ExportedType exportedType = reader.GetExportedType(key.ExportedType);
57+
58+
record.Name = HandleString(reader.GetString(exportedType.Name));
4759

4860
switch (exportedType.Implementation.Kind)
4961
{
@@ -67,35 +79,36 @@ private TypeForwarder HandleTypeForwarder(Cts.Ecma.EcmaModule module, Ecma.Expor
6779
else
6880
refName.SetPublicKeyToken(reader.GetBlobBytes(assemblyRef.PublicKeyOrToken));
6981

70-
result = new TypeForwarder
71-
{
72-
Name = HandleString(name),
73-
Scope = HandleScopeReference(refName),
74-
};
82+
record.Scope = HandleScopeReference(refName);
7583

76-
namespaceDefinition.TypeForwarders.Add(result);
84+
namespaceDefinition.TypeForwarders.Add(record);
7785
}
7886
break;
7987

8088
case Ecma.HandleKind.ExportedType:
8189
{
82-
TypeForwarder scope = HandleTypeForwarder(module, reader.GetExportedType((Ecma.ExportedTypeHandle)exportedType.Implementation));
90+
TypeForwarder scope = HandleTypeForwarder(module, (Ecma.ExportedTypeHandle)exportedType.Implementation);
8391

84-
result = new TypeForwarder
85-
{
86-
Name = HandleString(name),
87-
Scope = scope.Scope,
88-
};
92+
record.Scope = scope.Scope;
8993

90-
scope.NestedTypes.Add(result);
94+
scope.NestedTypes.Add(record);
9195
}
9296
break;
9397

9498
default:
9599
throw new BadImageFormatException();
96100
}
101+
}
102+
103+
private readonly struct ForwarderKey : IEquatable<ForwarderKey>
104+
{
105+
public readonly Cts.Ecma.EcmaModule Module;
106+
public readonly Ecma.ExportedTypeHandle ExportedType;
107+
public ForwarderKey(Cts.Ecma.EcmaModule module, Ecma.ExportedTypeHandle exportedType)
108+
=> (Module, ExportedType) = (module, exportedType);
97109

98-
return result;
110+
public bool Equals(ForwarderKey other) => Module == other.Module && ExportedType == other.ExportedType;
111+
public override int GetHashCode() => HashCode.Combine(Module.GetHashCode(), ExportedType.GetHashCode());
99112
}
100113
}
101114
}

0 commit comments

Comments
 (0)