Skip to content

Commit 02e2bb9

Browse files
authored
ILLink: Allow TypePreserve info to be applied multiple times (#103140)
Allows TypePreserve info to be applied multiple times. Pending preserve items may not be processed when the preserve info is applied, and the preserve info may be applied twice (in ProcessMarkedPending and ProcessType). If the preserve has already been applied in these cases, we will just return early rather than throwing an exception. Adds a test that applies a preserve on an otherwise unreferenced type.
1 parent 5f91817 commit 02e2bb9

File tree

5 files changed

+50
-16
lines changed

5 files changed

+50
-16
lines changed

src/tools/illink/src/linker/Linker.Steps/MarkStep.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,6 @@ bool ProcessMarkedPending ()
477477

478478
foreach (var type in Annotations.GetPendingPreserve ()) {
479479
marked = true;
480-
Debug.Assert (Annotations.IsProcessed (type));
481480
ApplyPreserveInfo (type);
482481
}
483482

@@ -2785,7 +2784,7 @@ void ApplyPreserveInfo (TypeDefinition type)
27852784

27862785
if (Annotations.TryGetPreserve (type, out TypePreserve preserve)) {
27872786
if (!Annotations.SetAppliedPreserve (type, preserve))
2788-
throw new InternalErrorException ($"Type {type} already has applied {preserve}.");
2787+
return;
27892788

27902789
var di = new DependencyInfo (DependencyKind.TypePreserve, type);
27912790

src/tools/illink/src/linker/Linker/Annotations.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
using System.Diagnostics;
3535
using System.Diagnostics.CodeAnalysis;
3636
using System.Linq;
37-
using System.Reflection.Metadata.Ecma335;
3837
using ILLink.Shared.TrimAnalysis;
3938
using Mono.Cecil;
4039
using Mono.Cecil.Cil;
@@ -303,25 +302,12 @@ public bool SetAppliedPreserve (TypeDefinition type, TypePreserve preserve)
303302
return true;
304303
}
305304

306-
public bool HasAppliedPreserve (TypeDefinition type, TypePreserve preserve)
307-
{
308-
if (!preserved_types.TryGetValue (type, out (TypePreserve preserve, bool applied) existing))
309-
throw new InternalErrorException ($"Type {type} must have a TypePreserve before it can be applied.");
310-
311-
if (preserve != existing.preserve)
312-
throw new InternalErrorException ($"Type {type} does not have {preserve}. The TypePreserve may have changed before the call to {nameof (HasAppliedPreserve)}.");
313-
314-
return existing.applied;
315-
}
316-
317305
public void SetPreserve (TypeDefinition type, TypePreserve preserve)
318306
{
319307
Debug.Assert (preserve != TypePreserve.Nothing);
320308
if (!preserved_types.TryGetValue (type, out (TypePreserve preserve, bool applied) existing)) {
321309
preserved_types.Add (type, (preserve, false));
322310
if (IsProcessed (type)) {
323-
// Required to track preserve for marked types where the existing preserve
324-
// was Nothing (since these aren't explicitly tracked.)
325311
var addedPending = pending_preserve.Add (type);
326312
Debug.Assert (addedPending);
327313
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using Mono.Linker.Tests.Cases.Expectations.Assertions;
3+
using Mono.Linker.Tests.Cases.Expectations.Metadata;
4+
5+
namespace Mono.Linker.Tests.Cases.CommandLine
6+
{
7+
[SetupCompileBefore ("CustomApplyPreserveStep.dll", new[] { "Dependencies/CustomApplyPreserveStep.cs" }, new[] { "illink.dll", "Mono.Cecil.dll" }, addAsReference: false)]
8+
[SetupLinkerArgument ("--custom-step", "-MarkStep:CustomStep.CustomApplyPreserveStep,CustomApplyPreserveStep.dll")]
9+
[SetupLinkerArgument ("--verbose")]
10+
public class CustomStepApplyPreserve
11+
{
12+
[Kept]
13+
public class HasPreserveApplied
14+
{
15+
[Kept]
16+
public int Field;
17+
18+
[Kept]
19+
public HasPreserveApplied () { }
20+
21+
[Kept]
22+
public void Method ()
23+
{
24+
}
25+
26+
public class Nested { }
27+
}
28+
29+
[Kept]
30+
public static void Main ()
31+
{
32+
Console.WriteLine (typeof (HasPreserveApplied).FullName);
33+
}
34+
}
35+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace CustomStep
2+
{
3+
public class CustomApplyPreserveStep : Mono.Linker.Steps.IStep
4+
{
5+
public void Process(Mono.Linker.LinkContext context)
6+
{
7+
var myType = context.GetType("Mono.Linker.Tests.Cases.CommandLine.CustomStepApplyPreserve/HasPreserveApplied");
8+
context.Annotations.SetPreserve(myType, Mono.Linker.TypePreserve.Methods);
9+
// Make sure we can set preserve multiple times
10+
context.Annotations.SetPreserve(myType, Mono.Linker.TypePreserve.All);
11+
}
12+
}
13+
}

src/tools/illink/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<Compile Remove="TypeForwarding\Dependencies\TypeForwardersRewriteForwarders.cs" />
2323
<Compile Remove="CommandLine\Dependencies\CustomStepDummy.cs" />
2424
<Compile Remove="CommandLine\Dependencies\CustomStepUser.cs" />
25+
<Compile Remove="CommandLine\Dependencies\CustomApplyPreserveStep.cs" />
2526
<Compile Remove="Logging\Dependencies\LogStep.cs" />
2627
<Compile Remove="Extensibility\Dependencies\*.cs" />
2728
<Compile Remove="DynamicDependencies\Dependencies\FacadeAssembly.cs" />

0 commit comments

Comments
 (0)