[dotnet-linker] Add a StoreAttributesStep to store attributes that are removed by the linker.

Add a StoreAttributesStep to store attributes that are removed by the linker, but
that the static registrar needs.

In particular, in .NET 6 the linker removes the System.Runtime.CompilerServices.ExtensionAttribute,
which the static registrar needs to handle category methods properly.

This involved copying and slightly modifying the RemoveAttributesBase code.
This commit is contained in:
Rolf Bjarne Kvinge 2020-11-06 16:13:37 +01:00
Родитель 8f0ca7508a
Коммит 831f55796e
5 изменённых файлов: 143 добавлений и 17 удалений

Просмотреть файл

@ -80,6 +80,7 @@ namespace Xamarin {
prelink_substeps.Add (new MarkNSObjects ()); prelink_substeps.Add (new MarkNSObjects ());
prelink_substeps.Add (new PreserveSmartEnumConversionsSubStep ()); prelink_substeps.Add (new PreserveSmartEnumConversionsSubStep ());
prelink_substeps.Add (new CollectUnmarkedMembersSubStep ()); prelink_substeps.Add (new CollectUnmarkedMembersSubStep ());
prelink_substeps.Add (new StoreAttributesStep ());
post_sweep_substeps.Add (new RemoveAttributesStep ()); post_sweep_substeps.Add (new RemoveAttributesStep ());
} }

Просмотреть файл

@ -0,0 +1,104 @@
using System;
using System.Collections;
using Mono.Linker;
using Mono.Linker.Steps;
using Mono.Cecil;
using Xamarin.Tuner;
namespace Xamarin.Linker.Steps {
public abstract class AttributeIteratorBaseStep : BaseSubStep {
protected DerivedLinkContext LinkContext {
get {
return LinkerConfiguration.GetInstance (Context).DerivedLinkContext;
}
}
public override SubStepTargets Targets {
get {
return SubStepTargets.Assembly
| SubStepTargets.Type
| SubStepTargets.Field
| SubStepTargets.Method
| SubStepTargets.Property
| SubStepTargets.Event;
}
}
public override bool IsActiveFor (AssemblyDefinition assembly)
{
return Annotations.GetAction (assembly) == AssemblyAction.Link;
}
public override void ProcessAssembly (AssemblyDefinition assembly)
{
ProcessAttributeProvider (assembly);
ProcessAttributeProvider (assembly.MainModule);
}
public override void ProcessType (TypeDefinition type)
{
ProcessAttributeProvider (type);
if (type.HasGenericParameters)
ProcessAttributeProviderCollection (type.GenericParameters);
}
void ProcessAttributeProviderCollection (IList list)
{
for (int i = 0; i < list.Count; i++)
ProcessAttributeProvider ((ICustomAttributeProvider) list [i]);
}
public override void ProcessField (FieldDefinition field)
{
ProcessAttributeProvider (field);
}
public override void ProcessMethod (MethodDefinition method)
{
ProcessMethodAttributeProvider (method);
}
void ProcessMethodAttributeProvider (MethodDefinition method)
{
ProcessAttributeProvider (method);
ProcessAttributeProvider (method.MethodReturnType);
if (method.HasParameters)
ProcessAttributeProviderCollection (method.Parameters);
if (method.HasGenericParameters)
ProcessAttributeProviderCollection (method.GenericParameters);
}
public override void ProcessProperty (PropertyDefinition property)
{
ProcessAttributeProvider (property);
}
public override void ProcessEvent (EventDefinition @event)
{
ProcessAttributeProvider (@event);
}
void ProcessAttributeProvider (ICustomAttributeProvider provider)
{
if (!provider.HasCustomAttributes)
return;
for (int i = 0; i < provider.CustomAttributes.Count; i++) {
var attrib = provider.CustomAttributes [i];
ProcessAttribute (provider, attrib, out var remove);
if (remove)
provider.CustomAttributes.RemoveAt (i--);
}
}
protected abstract void ProcessAttribute (ICustomAttributeProvider provider, CustomAttribute attribute, out bool remove);
}
}

Просмотреть файл

@ -1,8 +1,6 @@
using System; using System;
using Mono.Cecil; using Mono.Cecil;
using Mono.Tuner;
using Xamarin.Tuner;
namespace Xamarin.Linker.Steps { namespace Xamarin.Linker.Steps {
// The .NET linker comes with a way to remove attributes (by passing '--link-attributes // The .NET linker comes with a way to remove attributes (by passing '--link-attributes
@ -22,14 +20,16 @@ namespace Xamarin.Linker.Steps {
// //
// The end result is that a custom step is the best solution for now. // The end result is that a custom step is the best solution for now.
public class RemoveAttributesStep : RemoveAttributesBase { public class RemoveAttributesStep : AttributeIteratorBaseStep {
protected DerivedLinkContext LinkContext { protected override void ProcessAttribute (ICustomAttributeProvider provider, CustomAttribute attribute, out bool remove)
get { {
return LinkerConfiguration.GetInstance (Context).DerivedLinkContext; remove = IsRemovedAttribute (attribute);
}
if (remove)
LinkContext.StoreCustomAttribute (provider, attribute);
} }
protected override bool IsRemovedAttribute (CustomAttribute attribute) bool IsRemovedAttribute (CustomAttribute attribute)
{ {
// this avoids calling FullName (which allocates a string) // this avoids calling FullName (which allocates a string)
var attr_type = attribute.Constructor.DeclaringType; var attr_type = attribute.Constructor.DeclaringType;
@ -51,11 +51,5 @@ namespace Xamarin.Linker.Steps {
return false; return false;
} }
} }
protected override void WillRemoveAttribute (ICustomAttributeProvider provider, CustomAttribute attribute)
{
LinkContext.StoreCustomAttribute (provider, attribute);
base.WillRemoveAttribute (provider, attribute);
}
} }
} }

Просмотреть файл

@ -0,0 +1,30 @@
using System;
using Mono.Cecil;
namespace Xamarin.Linker.Steps {
// The registrar needs some of the system attributes that the linker might remove, so store those elsewhere for the static registrar's use.
public class StoreAttributesStep : AttributeIteratorBaseStep {
protected override void ProcessAttribute (ICustomAttributeProvider provider, CustomAttribute attribute, out bool remove)
{
// don't remove any of these
remove = false;
// this avoids calling FullName (which allocates a string)
var attr_type = attribute.Constructor.DeclaringType;
var store = false;
switch (attr_type.Namespace) {
case "System.Runtime.CompilerServices":
switch (attr_type.Name) {
case "ExtensionAttribute":
store = true;
break;
}
break;
}
if (store)
LinkContext.StoreCustomAttribute (provider, attribute);
}
}
}

Просмотреть файл

@ -176,9 +176,6 @@
<Compile Include="..\..\builds\mono-ios-sdk-destdir\ios-sources\external\linker\src\tuner\Mono.Tuner\CecilRocks.cs"> <Compile Include="..\..\builds\mono-ios-sdk-destdir\ios-sources\external\linker\src\tuner\Mono.Tuner\CecilRocks.cs">
<Link>external\mono-archive\Mono.Tuner\CecilRocks.cs</Link> <Link>external\mono-archive\Mono.Tuner\CecilRocks.cs</Link>
</Compile> </Compile>
<Compile Include="..\..\builds\mono-ios-sdk-destdir\ios-sources\external\linker\src\tuner\Mono.Tuner\RemoveAttributesBase.cs">
<Link>external\mono-archive\Mono.Tuner\RemoveAttributesBase.cs</Link>
</Compile>
<Compile Include="..\..\external\Xamarin.MacDev\Xamarin.MacDev\PListObject.cs"> <Compile Include="..\..\external\Xamarin.MacDev\Xamarin.MacDev\PListObject.cs">
<Link>external\Xamarin.MacDev\Xamarin.MacDev\PListObject.cs</Link> <Link>external\Xamarin.MacDev\Xamarin.MacDev\PListObject.cs</Link>
</Compile> </Compile>