Skip to content

Commit 4157348

Browse files
Add support for exported types in illink XML formats (#102487)
Addresses the TODO in the native AOT port. Ran into inability of rooting things from mscorlib with the illink XML format on native AOT so decided to fix the TODO. (It was possible to work around with `Type.GetType` (that's a supported pattern) or rd.xml, but this should work with the descriptors too.)
1 parent 48c49a3 commit 4157348

File tree

10 files changed

+66
-4
lines changed

10 files changed

+66
-4
lines changed

src/coreclr/tools/Common/Compiler/ProcessLinkerXmlBase.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,10 @@ protected virtual void ProcessTypes(ModuleDesc assembly, XPathNavigator nav, boo
217217
continue;
218218
}
219219

220-
// TODO: Process exported types
220+
MetadataType? type = CecilCompatibleTypeParser.GetType(assembly, fullname);
221221

222-
TypeDesc? type = CecilCompatibleTypeParser.GetType(assembly, fullname);
222+
if (type != null && type.Module != assembly)
223+
type = ProcessExportedType(type, assembly, typeNav);
223224

224225
if (type == null)
225226
{
@@ -234,6 +235,8 @@ protected virtual void ProcessTypes(ModuleDesc assembly, XPathNavigator nav, boo
234235
}
235236
}
236237

238+
protected virtual MetadataType? ProcessExportedType(MetadataType exported, ModuleDesc assembly, XPathNavigator nav) => exported;
239+
237240
private void MatchType(TypeDesc type, Regex regex, XPathNavigator nav)
238241
{
239242
StringBuilder sb = new StringBuilder();
@@ -759,7 +762,7 @@ public bool TryConvertValue(string value, TypeDesc type, out object? result)
759762

760763
public class CecilCompatibleTypeParser
761764
{
762-
public static TypeDesc? GetType(ModuleDesc assembly, string fullName)
765+
public static MetadataType? GetType(ModuleDesc assembly, string fullName)
763766
{
764767
Debug.Assert(!string.IsNullOrEmpty(fullName));
765768
var position = fullName.IndexOf('/');

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ protected override void ProcessAssembly(ModuleDesc assembly, XPathNavigator nav,
4040
ProcessTypes(assembly, nav, warnOnUnresolvedTypes);
4141
}
4242

43-
// protected override TypeDesc? ProcessExportedType(ExportedType exported, ModuleDesc assembly, XPathNavigator nav) => null;
43+
protected override MetadataType ProcessExportedType(MetadataType exported, ModuleDesc assembly, XPathNavigator nav) => null;
4444

4545
protected override bool ProcessTypePattern(string fullname, ModuleDesc assembly, XPathNavigator nav) => false;
4646

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DescriptorMarker.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,14 @@ private void MarkAndPreserve(TypeDesc type, XPathNavigator nav, TypePreserve pre
162162
}
163163
#endif
164164

165+
protected override MetadataType? ProcessExportedType(MetadataType exported, ModuleDesc assembly, XPathNavigator nav)
166+
{
167+
// Rooting module metadata roots type forwarder metadata for all types in the module that are reflection visible.
168+
// (We don't track individual type forwarders right now.)
169+
_dependencies.Add(_factory.ModuleMetadata(assembly), "Type used through forwarder");
170+
return base.ProcessExportedType(exported, assembly, nav);
171+
}
172+
165173
protected override void ProcessType(TypeDesc type, XPathNavigator nav)
166174
{
167175
Debug.Assert(ShouldProcessElement(nav));

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public static int Run()
1717
ThrowIfMemberNotPresent(typeof(ILLinkDescriptor), nameof(PropertyKeptViaDescriptor));
1818
ThrowIfMemberNotPresent(typeof(ILLinkDescriptor), nameof(EventKeptViaDescriptor));
1919
ThrowIfTypeNotPresent(typeof(ILLinkDescriptor), nameof(NestedTypeKeptViaDescriptor));
20+
ThrowIfTypeNotPresent("LibraryClass, ShimLibrary");
2021
ThrowIfTypePresent(typeof(ILLinkDescriptor), nameof(NestedTypeNonKept));
2122
return 100;
2223
}
@@ -51,6 +52,10 @@ class NestedTypeNonKept
5152
Justification = "That's the point")]
5253
private static bool IsTypePresent(Type testType, string typeName) => testType.GetNestedType(typeName, BindingFlags.NonPublic | BindingFlags.Public) != null;
5354

55+
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2057:UnrecognizedReflectionPattern",
56+
Justification = "That's the point")]
57+
private static bool IsTypePresent(string typeName) => Type.GetType(typeName) != null;
58+
5459
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
5560
Justification = "That's the point")]
5661
private static bool IsMemberPresent(Type testType, string memberName) {
@@ -70,6 +75,14 @@ private static void ThrowIfTypeNotPresent(Type testType, string typeName)
7075
}
7176
}
7277

78+
private static void ThrowIfTypeNotPresent(string typeName)
79+
{
80+
if (!IsTypePresent(typeName))
81+
{
82+
throw new Exception(typeName);
83+
}
84+
}
85+
7386
private static void ThrowIfTypePresent(Type testType, string typeName)
7487
{
7588
if (IsTypePresent(testType, typeName))
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
public class LibraryClass { }
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Library</OutputType>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<Compile Include="Library.cs" />
7+
</ItemGroup>
8+
</Project>

src/tests/nativeaot/SmokeTests/TrimmingBehaviors/NonEmbedded.ILLink.Descriptor.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@
44
<method name="methodKeptViaStandaloneDescriptor"/>
55
</type>
66
</assembly>
7+
8+
<assembly fullname="ShimLibrary">
9+
<type fullname="LibraryClass" />
10+
</assembly>
711
</linker>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Runtime.CompilerServices;
5+
6+
[assembly: TypeForwardedTo(typeof(LibraryClass))]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Library</OutputType>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<Compile Include="ShimLibrary.cs" />
7+
</ItemGroup>
8+
<ItemGroup>
9+
<ProjectReference Include="Library.csproj" />
10+
</ItemGroup>
11+
</Project>

src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
<!-- We don't run the scanner in optimized builds -->
99
<CLRTestTargetUnsupported Condition="'$(IlcMultiModule)' == 'true'">true</CLRTestTargetUnsupported>
1010
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<ProjectReference Include="ShimLibrary.csproj" />
14+
</ItemGroup>
15+
1116
<ItemGroup>
1217
<Compile Include="Dataflow.cs" />
1318
<Compile Include="DeadCodeElimination.cs" />

0 commit comments

Comments
 (0)