Skip to content

Commit 4655a1a

Browse files
committed
[dotnet-linker] Use [DynamicDependency] attributes instead of manual marking when marking static registrar methods.
This makes it easier to move this code out of a custom linker step in the future. Contributes towards #17693.
1 parent 9639042 commit 4655a1a

4 files changed

Lines changed: 73 additions & 0 deletions

File tree

dotnet/targets/Xamarin.Shared.Sdk.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@
553553
<_UseDynamicDependenciesForGeneratedCodeOptimizations Condition="'$(_UseDynamicDependenciesForGeneratedCodeOptimizations)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForGeneratedCodeOptimizations>
554554
<_UseLinkDescriptionForApplyPreserveAttribute Condition="'$(_UseLinkDescriptionForApplyPreserveAttribute)' == '' And '$(_XamarinRuntime)' == 'NativeAOT'">true</_UseLinkDescriptionForApplyPreserveAttribute>
555555
<_UseLinkDescriptionForApplyPreserveAttribute Condition="'$(_UseLinkDescriptionForApplyPreserveAttribute)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseLinkDescriptionForApplyPreserveAttribute>
556+
<_UseDynamicDependenciesForMarkStaticRegistrar Condition="'$(_UseDynamicDependenciesForMarkStaticRegistrar)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForMarkStaticRegistrar>
556557
</PropertyGroup>
557558

558559
<PropertyGroup>
@@ -759,6 +760,7 @@
759760
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.PreserveBlockCodeStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForBlockCodePreservation)' == 'true'" />
760761
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.OptimizeGeneratedCodeStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForGeneratedCodeOptimizations)' == 'true'" />
761762
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.ApplyPreserveAttributeStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseLinkDescriptionForApplyPreserveAttribute)' == 'true'" />
763+
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.MarkForStaticRegistrarStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForMarkStaticRegistrar)' == 'true'" />
762764
<!-- The final decision to remove/keep the dynamic registrar must be done before the linking step -->
763765
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="MonoTouch.Tuner.RegistrarRemovalTrackingStep" />
764766
<!-- TODO: these steps should probably run after mark. -->

tools/common/DerivedLinkContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public class DerivedLinkContext : LinkContext {
4949
Dictionary<TypeDefinition, LinkedAwayTypeReference> LinkedAwayTypeMap = new Dictionary<TypeDefinition, LinkedAwayTypeReference> ();
5050

5151
public bool DidRunApplyPreserveAttributeStep { get; set; }
52+
public bool DidRunMarkForStaticRegistrarStep { get; set; }
5253

5354
public DerivedLinkContext (LinkerConfiguration configuration, Application app)
5455
#if !LEGACY_TOOLS

tools/dotnet-linker/MarkForStaticRegistrar.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ public class MarkForStaticRegistrar : ConfigurationAwareSubStep {
2323

2424
public override bool IsActiveFor (AssemblyDefinition assembly)
2525
{
26+
// It's either this step, or MarkForStaticRegistrarStep. If MarkForStaticRegistrarStep already ran, then we shouldn't run this step.
27+
if (Configuration.DerivedLinkContext.DidRunMarkForStaticRegistrarStep)
28+
return false;
29+
2630
if (Configuration.Application.Optimizations.OptimizeBlockLiteralSetupBlock != true)
2731
return false;
2832

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System.Linq;
5+
6+
using Mono.Cecil;
7+
using Mono.Linker;
8+
using Registrar;
9+
using Xamarin.Bundler;
10+
11+
#nullable enable
12+
13+
namespace Xamarin.Linker.Steps {
14+
15+
// This class marks APIs referenced by the native code generated by the static registrar.
16+
public class MarkForStaticRegistrarStep : AssemblyModifierStep {
17+
protected override string Name { get => "Mark For Static Registrar"; }
18+
19+
protected override int ErrorCode { get => 2460; }
20+
21+
protected override bool IsActiveFor (AssemblyDefinition assembly)
22+
{
23+
if (Configuration.Application.Optimizations.OptimizeBlockLiteralSetupBlock != true)
24+
return false;
25+
26+
if (Configuration.Application.Registrar != RegistrarMode.Static)
27+
return false;
28+
29+
return Annotations.GetAction (assembly) == AssemblyAction.Link;
30+
}
31+
32+
protected override void TryProcess ()
33+
{
34+
DerivedLinkContext.DidRunMarkForStaticRegistrarStep = true;
35+
base.TryProcess ();
36+
}
37+
38+
protected override bool ProcessType (TypeDefinition type)
39+
{
40+
return base.ProcessMethods (type);
41+
}
42+
43+
protected override bool ProcessMethod (MethodDefinition method)
44+
{
45+
return ProcessDelegateProxyAttribute (method);
46+
}
47+
48+
// Mark the Invoke method in the type pointed to by the DelegateProxy attribute,
49+
// because it may only be referenced from native code when using the static registrar.
50+
bool ProcessDelegateProxyAttribute (MethodDefinition method)
51+
{
52+
if (!StaticRegistrar.IsDelegate (method.ReturnType.Resolve ()))
53+
return false;
54+
55+
var getDelegateProxyType = DerivedLinkContext.StaticRegistrar.GetDelegateProxyType (method);
56+
if (getDelegateProxyType is null)
57+
return false;
58+
59+
var invokeMethod = getDelegateProxyType.Methods.SingleOrDefault (m => m.Name == "Invoke");
60+
if (invokeMethod is null)
61+
return false;
62+
63+
return abr.AddDynamicDependencyAttribute (method, invokeMethod);
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)