Skip to content

Commit fce2e6a

Browse files
Use MetadataTypeSymbol in interop type maps (#118776)
We guarantee the type can be found but not that it can be passed to e.g. `RuntimeHelpers.GetUninitializedObject`. The `MetadataTypeSymbol` node didn't exist when interop type map was added.
1 parent d1691e1 commit fce2e6a

File tree

5 files changed

+74
-11
lines changed

5 files changed

+74
-11
lines changed

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedExternalTypeMapNode.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section se
2121
foreach ((string key, TypeDesc type) in entries)
2222
{
2323
Vertex keyVertex = writer.GetStringConstant(key);
24-
Vertex valueVertex = writer.GetUnsignedConstant(externalReferences.GetIndex(factory.MaximallyConstructableType(type)));
24+
Vertex valueVertex = writer.GetUnsignedConstant(externalReferences.GetIndex(factory.MetadataTypeSymbol(type)));
2525
Vertex entry = writer.GetTuple(keyVertex, valueVertex);
2626
typeMapHashTable.Append((uint)TypeHashingAlgorithms.ComputeNameHashCode(key), section.Place(entry));
2727
}
@@ -37,7 +37,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
3737
{
3838
foreach (TypeDesc targetType in entries.Values)
3939
{
40-
yield return new DependencyListEntry(context.MaximallyConstructableType(targetType), "Analyzed external type map entry target type");
40+
yield return new DependencyListEntry(context.MetadataTypeSymbol(targetType), "Analyzed external type map entry target type");
4141
}
4242
}
4343
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => [];

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedProxyTypeMapNode.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section se
2121
foreach ((TypeDesc key, TypeDesc type) in entries)
2222
{
2323
Vertex keyVertex = writer.GetUnsignedConstant(externalReferences.GetIndex(factory.MaximallyConstructableType(key)));
24-
Vertex valueVertex = writer.GetUnsignedConstant(externalReferences.GetIndex(factory.MaximallyConstructableType(type)));
24+
Vertex valueVertex = writer.GetUnsignedConstant(externalReferences.GetIndex(factory.MetadataTypeSymbol(type)));
2525
Vertex entry = writer.GetTuple(keyVertex, valueVertex);
2626
typeMapHashTable.Append((uint)key.GetHashCode(), section.Place(entry));
2727
}
@@ -38,7 +38,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
3838
foreach (var (sourceType, proxyType) in entries)
3939
{
4040
yield return new DependencyListEntry(context.MaximallyConstructableType(sourceType), "Analyzed proxy type map entry source type");
41-
yield return new DependencyListEntry(context.MaximallyConstructableType(proxyType), "Analyzed proxy type map entry proxy type");
41+
yield return new DependencyListEntry(context.MetadataTypeSymbol(proxyType), "Analyzed proxy type map entry proxy type");
4242
}
4343
}
4444
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => [];

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapNode.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDep
3939
if (trimmingTargetType is not null)
4040
{
4141
yield return new CombinedDependencyListEntry(
42-
context.MaximallyConstructableType(targetType),
42+
context.MetadataTypeSymbol(targetType),
4343
context.NecessaryTypeSymbol(trimmingTargetType),
4444
"Type in external type map is cast target");
4545
}
@@ -54,7 +54,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
5454
if (trimmingTargetType is null)
5555
{
5656
yield return new DependencyListEntry(
57-
context.MaximallyConstructableType(targetType),
57+
context.MetadataTypeSymbol(targetType),
5858
"External type map entry target type");
5959
}
6060
}
@@ -80,7 +80,7 @@ public int CompareToImpl(ISortableNode other, CompilerComparer comparer)
8080
if (trimmingTargetType is null
8181
|| factory.NecessaryTypeSymbol(trimmingTargetType).Marked)
8282
{
83-
IEETypeNode targetNode = factory.MaximallyConstructableType(targetType);
83+
IEETypeNode targetNode = factory.MetadataTypeSymbol(targetType);
8484
Debug.Assert(targetNode.Marked);
8585
yield return (entry.Key, targetNode);
8686
}

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapNode.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDep
4343
foreach (var (key, value) in _mapEntries)
4444
{
4545
yield return new CombinedDependencyListEntry(
46-
context.MaximallyConstructableType(value),
46+
context.MetadataTypeSymbol(value),
4747
context.MaximallyConstructableType(key),
4848
"Proxy type map entry");
4949
}
@@ -60,7 +60,7 @@ public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDep
6060
IEETypeNode keyNode = factory.MaximallyConstructableType(key);
6161
if (keyNode.Marked)
6262
{
63-
IEETypeNode valueNode = factory.MaximallyConstructableType(value);
63+
IEETypeNode valueNode = factory.MetadataTypeSymbol(value);
6464
Debug.Assert(valueNode.Marked);
6565
yield return (keyNode, valueNode);
6666
}

src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
using System.Runtime.CompilerServices;
88
using System.Runtime.InteropServices;
99

10+
[assembly: TypeMap<DeadCodeElimination.TestInteropMapTrimming.Universe>("Foo", typeof(DeadCodeElimination.TestInteropMapTrimming.ConditionalTypeMapEntry), typeof(DeadCodeElimination.TestInteropMapTrimming.TypeMapTrimTarget))]
11+
[assembly: TypeMap<DeadCodeElimination.TestInteropMapTrimming.Universe>("Bar", typeof(DeadCodeElimination.TestInteropMapTrimming.UnconditionalTypeMapEntry))]
12+
[assembly: TypeMapAssociation<DeadCodeElimination.TestInteropMapTrimming.Universe>(typeof(DeadCodeElimination.TestInteropMapTrimming.SourceType), typeof(DeadCodeElimination.TestInteropMapTrimming.ProxyType))]
13+
1014
class DeadCodeElimination
1115
{
1216
public static int Run()
@@ -36,6 +40,7 @@ public static int Run()
3640
TestInvisibleGenericsTrimming.Run();
3741
TestTypeHandlesInGenericDictionaries.Run();
3842
TestMetadataMethodTables.Run();
43+
TestInteropMapTrimming.Run();
3944

4045
return 100;
4146
}
@@ -1267,6 +1272,59 @@ public static void Run()
12671272
}
12681273
}
12691274

1275+
internal class TestInteropMapTrimming
1276+
{
1277+
internal class Universe;
1278+
1279+
internal class ConditionalTypeMapEntry;
1280+
internal class UnconditionalTypeMapEntry;
1281+
internal class TypeMapTrimTarget;
1282+
1283+
internal class SourceType;
1284+
internal class ProxyType;
1285+
1286+
[MethodImpl(MethodImplOptions.NoInlining)]
1287+
static object GetUnknown() => null;
1288+
1289+
[MethodImpl(MethodImplOptions.NoInlining)]
1290+
static void Consume(object o) { }
1291+
1292+
public static void Run()
1293+
{
1294+
var map = TypeMapping.GetOrCreateExternalTypeMapping<Universe>();
1295+
1296+
{
1297+
if (GetUnknown() is TypeMapTrimTarget)
1298+
{
1299+
Console.WriteLine("Unexpected!");
1300+
}
1301+
1302+
var mappedType = map["Foo"];
1303+
ThrowIfUsableMethodTable(mappedType);
1304+
if (mappedType.Name != nameof(ConditionalTypeMapEntry))
1305+
throw new Exception();
1306+
}
1307+
1308+
{
1309+
var mappedType = map["Bar"];
1310+
ThrowIfUsableMethodTable(mappedType);
1311+
if (mappedType.Name != nameof(UnconditionalTypeMapEntry))
1312+
throw new Exception();
1313+
}
1314+
1315+
var proxyMap = TypeMapping.GetOrCreateProxyTypeMapping<Universe>();
1316+
1317+
{
1318+
Consume(new SourceType());
1319+
1320+
var mappedType = proxyMap[typeof(SourceType)];
1321+
ThrowIfUsableMethodTable(mappedType);
1322+
if (mappedType.Name != nameof(ProxyType))
1323+
throw new Exception();
1324+
}
1325+
}
1326+
}
1327+
12701328
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
12711329
Justification = "That's the point")]
12721330
private static Type GetTypeSecretly(Type testType, string typeName) => testType.GetNestedType(typeName, BindingFlags.NonPublic | BindingFlags.Public);
@@ -1279,14 +1337,19 @@ private static void ThrowIfPresent(Type testType, string typeName)
12791337
}
12801338
}
12811339

1282-
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:UnrecognizedReflectionPattern",
1283-
Justification = "That's the point")]
12841340
private static void ThrowIfPresentWithUsableMethodTable(Type testType, string typeName)
12851341
{
12861342
Type t = GetTypeSecretly(testType, typeName);
12871343
if (t == null)
12881344
return;
12891345

1346+
ThrowIfUsableMethodTable(t);
1347+
}
1348+
1349+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern",
1350+
Justification = "That's the point")]
1351+
private static void ThrowIfUsableMethodTable(Type t)
1352+
{
12901353
try
12911354
{
12921355
RuntimeHelpers.GetUninitializedObject(t);

0 commit comments

Comments
 (0)