You've already forked linux-packaging-mono
Imported Upstream version 5.10.0.47
Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
parent
88ff76fe28
commit
e46a49ecf1
120
external/linker/linker/Linker.Steps/AddBypassNGenStep.cs
vendored
Normal file
120
external/linker/linker/Linker.Steps/AddBypassNGenStep.cs
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// AddBypassNGenStep.cs
|
||||
//
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Collections.Generic;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
namespace Mono.Linker.Steps {
|
||||
|
||||
public class AddBypassNGenStep : BaseStep{
|
||||
|
||||
AssemblyDefinition coreLibAssembly;
|
||||
CustomAttribute bypassNGenAttribute;
|
||||
|
||||
protected override void ProcessAssembly (AssemblyDefinition assembly)
|
||||
{
|
||||
if (Annotations.GetAction (assembly) == AssemblyAction.AddBypassNGen) {
|
||||
coreLibAssembly = Context.Resolve (assembly.MainModule.TypeSystem.CoreLibrary);
|
||||
bypassNGenAttribute = null;
|
||||
if (assembly == coreLibAssembly) {
|
||||
EnsureBypassNGenAttribute (assembly.MainModule);
|
||||
}
|
||||
|
||||
foreach (var type in assembly.MainModule.Types)
|
||||
ProcessType (type);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessType (TypeDefinition type)
|
||||
{
|
||||
if (type.HasMethods)
|
||||
ProcessMethods (type.Methods, type.Module);
|
||||
|
||||
if (type.HasNestedTypes)
|
||||
ProcessNestedTypes (type);
|
||||
}
|
||||
|
||||
void ProcessMethods (Collection<MethodDefinition> methods, ModuleDefinition module)
|
||||
{
|
||||
foreach (var method in methods)
|
||||
if (!Annotations.IsMarked (method)) {
|
||||
EnsureBypassNGenAttribute (module);
|
||||
method.CustomAttributes.Add (bypassNGenAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessNestedTypes (TypeDefinition type)
|
||||
{
|
||||
for (int i = 0; i < type.NestedTypes.Count; i++) {
|
||||
var nested = type.NestedTypes [i];
|
||||
ProcessType (nested);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureBypassNGenAttribute (ModuleDefinition targetModule)
|
||||
{
|
||||
if (bypassNGenAttribute != null) {
|
||||
return;
|
||||
}
|
||||
ModuleDefinition corelibMainModule = coreLibAssembly.MainModule;
|
||||
TypeReference bypassNGenAttributeRef = new TypeReference ("System.Runtime", "BypassNGenAttribute", corelibMainModule, targetModule.TypeSystem.CoreLibrary);
|
||||
TypeDefinition bypassNGenAttributeDef = corelibMainModule.MetadataResolver.Resolve (bypassNGenAttributeRef);
|
||||
MethodDefinition bypassNGenAttributeDefaultConstructor = null;
|
||||
|
||||
if (bypassNGenAttributeDef == null) {
|
||||
// System.Runtime.BypassNGenAttribute is not found in corelib. Add it.
|
||||
TypeReference systemAttributeRef = new TypeReference ("System", "Attribute", corelibMainModule, targetModule.TypeSystem.CoreLibrary);
|
||||
TypeReference systemAttribute = corelibMainModule.MetadataResolver.Resolve (systemAttributeRef);
|
||||
systemAttribute = corelibMainModule.ImportReference (systemAttribute);
|
||||
|
||||
if (systemAttribute == null)
|
||||
throw new System.ApplicationException ("System.Attribute is not found in " + targetModule.TypeSystem.CoreLibrary.Name);
|
||||
|
||||
MethodReference systemAttributeDefaultConstructorRef = new MethodReference (".ctor", corelibMainModule.TypeSystem.Void, systemAttributeRef);
|
||||
MethodReference systemAttributeDefaultConstructor = corelibMainModule.MetadataResolver.Resolve (systemAttributeDefaultConstructorRef);
|
||||
systemAttributeDefaultConstructor = corelibMainModule.ImportReference (systemAttributeDefaultConstructor);
|
||||
|
||||
if (systemAttributeDefaultConstructor == null)
|
||||
throw new System.ApplicationException ("System.Attribute has no default constructor");
|
||||
|
||||
bypassNGenAttributeDef = new TypeDefinition ("System.Runtime", "BypassNGenAttribute", TypeAttributes.NotPublic | TypeAttributes.Sealed, systemAttribute);
|
||||
|
||||
coreLibAssembly.MainModule.Types.Add (bypassNGenAttributeDef);
|
||||
|
||||
if (Annotations.GetAction (coreLibAssembly) == AssemblyAction.Copy) {
|
||||
Annotations.SetAction (coreLibAssembly, AssemblyAction.Save);
|
||||
}
|
||||
|
||||
const MethodAttributes ctorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
|
||||
bypassNGenAttributeDefaultConstructor = new MethodDefinition (".ctor", ctorAttributes, coreLibAssembly.MainModule.TypeSystem.Void);
|
||||
var instructions = bypassNGenAttributeDefaultConstructor.Body.Instructions;
|
||||
instructions.Add (Instruction.Create (OpCodes.Ldarg_0));
|
||||
instructions.Add (Instruction.Create (OpCodes.Call, systemAttributeDefaultConstructor));
|
||||
instructions.Add (Instruction.Create (OpCodes.Ret));
|
||||
|
||||
bypassNGenAttributeDef.Methods.Add (bypassNGenAttributeDefaultConstructor);
|
||||
}
|
||||
else {
|
||||
foreach (MethodDefinition method in bypassNGenAttributeDef.Methods) {
|
||||
if (method.IsConstructor && !method.IsStatic && !method.HasParameters) {
|
||||
bypassNGenAttributeDefaultConstructor = method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bypassNGenAttributeDefaultConstructor == null) {
|
||||
throw new System.ApplicationException ("System.Runtime.BypassNGenAttribute has no default constructor");
|
||||
}
|
||||
}
|
||||
|
||||
MethodReference defaultConstructorReference = targetModule.ImportReference (bypassNGenAttributeDefaultConstructor);
|
||||
bypassNGenAttribute = new CustomAttribute (defaultConstructorReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,12 @@ namespace Mono.Linker.Steps {
|
||||
get { return _context.Annotations; }
|
||||
}
|
||||
|
||||
public Tracer Tracer {
|
||||
get { return _context.Tracer; }
|
||||
}
|
||||
|
||||
public MarkingHelpers MarkingHelpers => _context.MarkingHelpers;
|
||||
|
||||
public void Process (LinkContext context)
|
||||
{
|
||||
_context = context;
|
||||
@@ -51,6 +51,12 @@ namespace Mono.Linker.Steps {
|
||||
get { return _context.Annotations; }
|
||||
}
|
||||
|
||||
public Tracer Tracer {
|
||||
get { return _context.Tracer; }
|
||||
}
|
||||
|
||||
private MarkingHelpers MarkingHelpers => _context.MarkingHelpers;
|
||||
|
||||
public MarkStep ()
|
||||
{
|
||||
_methods = new Queue<MethodDefinition> ();
|
||||
@@ -77,14 +83,14 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
protected virtual void InitializeAssembly (AssemblyDefinition assembly)
|
||||
{
|
||||
Annotations.Push (assembly);
|
||||
Tracer.Push (assembly);
|
||||
try {
|
||||
MarkAssembly (assembly);
|
||||
|
||||
foreach (TypeDefinition type in assembly.MainModule.Types)
|
||||
InitializeType (type);
|
||||
} finally {
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,13 +131,7 @@ namespace Mono.Linker.Steps {
|
||||
if (QueueIsEmpty ())
|
||||
throw new InvalidOperationException ("No entry methods");
|
||||
|
||||
ProcessEntireQueue ();
|
||||
|
||||
// After all types have been processed then we can process the lazily marked attributes
|
||||
ProcessLazyAttributes ();
|
||||
|
||||
// We need to process the queue again in case marking the attributes enqueued more work
|
||||
ProcessEntireQueue ();
|
||||
while (ProcessPrimaryQueue () || ProcessLazyAttributes ())
|
||||
|
||||
// deal with [TypeForwardedTo] pseudo-attributes
|
||||
foreach (AssemblyDefinition assembly in _context.GetAssemblies ()) {
|
||||
@@ -157,39 +157,41 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
if (!Annotations.IsMarked (type))
|
||||
continue;
|
||||
Annotations.Push (type);
|
||||
Tracer.Push (type);
|
||||
try {
|
||||
Annotations.Mark (exported);
|
||||
if (_context.KeepTypeForwarderOnlyAssemblies) {
|
||||
Annotations.Mark (assembly.MainModule);
|
||||
}
|
||||
MarkingHelpers.MarkExportedType (exported, assembly.MainModule);
|
||||
} finally {
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessEntireQueue ()
|
||||
bool ProcessPrimaryQueue ()
|
||||
{
|
||||
if (QueueIsEmpty ())
|
||||
return false;
|
||||
|
||||
while (!QueueIsEmpty ()) {
|
||||
ProcessQueue ();
|
||||
ProcessVirtualMethods ();
|
||||
DoAdditionalProcessing ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProcessQueue ()
|
||||
{
|
||||
while (!QueueIsEmpty ()) {
|
||||
MethodDefinition method = _methods.Dequeue ();
|
||||
Annotations.Push (method);
|
||||
Tracer.Push (method);
|
||||
try {
|
||||
ProcessMethod (method);
|
||||
} catch (Exception e) {
|
||||
throw new MarkException (string.Format ("Error processing method: '{0}' in assembly: '{1}'", method.FullName, method.Module.Name), e, method);
|
||||
} finally {
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,9 +209,9 @@ namespace Mono.Linker.Steps {
|
||||
void ProcessVirtualMethods ()
|
||||
{
|
||||
foreach (MethodDefinition method in _virtual_methods) {
|
||||
Annotations.Push (method);
|
||||
Tracer.Push (method);
|
||||
ProcessVirtualMethod (method);
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,12 +257,16 @@ namespace Mono.Linker.Steps {
|
||||
if (!provider.HasCustomAttributes)
|
||||
return;
|
||||
|
||||
Annotations.Push (provider);
|
||||
Tracer.Push (provider);
|
||||
try {
|
||||
foreach (CustomAttribute ca in provider.CustomAttributes)
|
||||
foreach (CustomAttribute ca in provider.CustomAttributes) {
|
||||
if (!ShouldMarkCustomAttribute (ca))
|
||||
continue;
|
||||
|
||||
MarkCustomAttribute (ca);
|
||||
}
|
||||
} finally {
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,8 +281,9 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
protected virtual void MarkCustomAttribute (CustomAttribute ca)
|
||||
{
|
||||
Annotations.Push ((object)ca.AttributeType ?? (object)ca);
|
||||
Tracer.Push ((object)ca.AttributeType ?? (object)ca);
|
||||
try {
|
||||
Annotations.Mark (ca);
|
||||
MarkMethod (ca.Constructor);
|
||||
|
||||
MarkCustomAttributeArguments (ca);
|
||||
@@ -292,10 +299,25 @@ namespace Mono.Linker.Steps {
|
||||
MarkCustomAttributeProperties (ca, type);
|
||||
MarkCustomAttributeFields (ca, type);
|
||||
} finally {
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool ShouldMarkCustomAttribute (CustomAttribute ca)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual bool ShouldMarkTopLevelCustomAttribute (CustomAttribute ca, MethodDefinition resolvedConstructor)
|
||||
{
|
||||
// If an attribute's module has not been marked after processing all types in all assemblies and the attribute itself has not been marked,
|
||||
// then surely nothing is using this attribute and there is no need to mark it
|
||||
if (!Annotations.IsMarked (resolvedConstructor.Module) && !Annotations.IsMarked (ca.AttributeType))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider)
|
||||
{
|
||||
// most security declarations are removed (if linked) but user code might still have some
|
||||
@@ -358,12 +380,12 @@ namespace Mono.Linker.Steps {
|
||||
protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute)
|
||||
{
|
||||
PropertyDefinition property = GetProperty (attribute, namedArgument.Name);
|
||||
Annotations.Push (property);
|
||||
Tracer.Push (property);
|
||||
if (property != null)
|
||||
MarkMethod (property.SetMethod);
|
||||
|
||||
MarkIfType (namedArgument.Argument);
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
|
||||
PropertyDefinition GetProperty (TypeDefinition type, string propertyname)
|
||||
@@ -518,24 +540,38 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessLazyAttributes ()
|
||||
bool ProcessLazyAttributes ()
|
||||
{
|
||||
var startingQueueCount = _topLevelAttributes.Count;
|
||||
if (startingQueueCount == 0)
|
||||
return false;
|
||||
|
||||
var skippedItems = new List<CustomAttribute> ();
|
||||
var markOccurred = false;
|
||||
|
||||
while (_topLevelAttributes.Count != 0) {
|
||||
var customAttribute = _topLevelAttributes.Dequeue ();
|
||||
|
||||
var resolved = customAttribute.AttributeType.Resolve ();
|
||||
var resolved = customAttribute.Constructor.Resolve ();
|
||||
if (resolved == null) {
|
||||
HandleUnresolvedType (customAttribute.AttributeType);
|
||||
HandleUnresolvedMethod (customAttribute.Constructor);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If an attribute's module has not been marked after processing all types in all assemblies and the attribute itself has not been marked,
|
||||
// then surely nothing is using this attribute and there is no need to mark it
|
||||
if (!Annotations.IsMarked (resolved.Module) && !Annotations.IsMarked (customAttribute.AttributeType))
|
||||
if (!ShouldMarkTopLevelCustomAttribute (customAttribute, resolved)) {
|
||||
skippedItems.Add (customAttribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
markOccurred = true;
|
||||
MarkCustomAttribute (customAttribute);
|
||||
}
|
||||
|
||||
// requeue the items we skipped in case we need to make another pass
|
||||
foreach (var item in skippedItems)
|
||||
_topLevelAttributes.Enqueue (item);
|
||||
|
||||
return markOccurred;
|
||||
}
|
||||
|
||||
protected void MarkField (FieldReference reference)
|
||||
@@ -618,7 +654,7 @@ namespace Mono.Linker.Steps {
|
||||
if (CheckProcessed (type))
|
||||
return null;
|
||||
|
||||
Annotations.Push (type);
|
||||
Tracer.Push (type);
|
||||
|
||||
MarkScope (type.Scope);
|
||||
MarkType (type.BaseType);
|
||||
@@ -659,7 +695,7 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
DoAdditionalTypeProcessing (type);
|
||||
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
|
||||
Annotations.Mark (type);
|
||||
|
||||
@@ -926,10 +962,10 @@ namespace Mono.Linker.Steps {
|
||||
if (property.Name != property_name)
|
||||
continue;
|
||||
|
||||
Annotations.Push (property);
|
||||
Tracer.Push (property);
|
||||
MarkMethod (property.GetMethod);
|
||||
MarkMethod (property.SetMethod);
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1215,7 +1251,7 @@ namespace Mono.Linker.Steps {
|
||||
if (!includeStatic && field.IsStatic)
|
||||
continue;
|
||||
|
||||
if (markBackingFieldsOnlyIfPropertyMarked && field.Name.EndsWith (">k__BackingField")) {
|
||||
if (markBackingFieldsOnlyIfPropertyMarked && field.Name.EndsWith (">k__BackingField", StringComparison.Ordinal)) {
|
||||
// We can't reliably construct the expected property name from the backing field name for all compilers
|
||||
// because csc shortens the name of the backing field in some cases
|
||||
// For example:
|
||||
@@ -1234,8 +1270,12 @@ namespace Mono.Linker.Steps {
|
||||
static PropertyDefinition SearchPropertiesForMatchingFieldDefinition (FieldDefinition field)
|
||||
{
|
||||
foreach (var property in field.DeclaringType.Properties) {
|
||||
foreach (var ins in property.GetMethod.Body.Instructions) {
|
||||
if (ins.Operand != null && ins.Operand == field)
|
||||
var instr = property.GetMethod?.Body?.Instructions;
|
||||
if (instr == null)
|
||||
continue;
|
||||
|
||||
foreach (var ins in instr) {
|
||||
if (ins?.Operand == field)
|
||||
return property;
|
||||
}
|
||||
}
|
||||
@@ -1273,7 +1313,7 @@ namespace Mono.Linker.Steps {
|
||||
if (reference.DeclaringType is ArrayType)
|
||||
return null;
|
||||
|
||||
Annotations.Push (reference);
|
||||
Tracer.Push (reference);
|
||||
if (reference.DeclaringType is GenericInstanceType)
|
||||
MarkType (reference.DeclaringType);
|
||||
|
||||
@@ -1293,9 +1333,9 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
EnqueueMethod (method);
|
||||
} finally {
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
Annotations.AddDependency (method);
|
||||
Tracer.AddDependency (method);
|
||||
|
||||
return method;
|
||||
}
|
||||
@@ -1334,7 +1374,7 @@ namespace Mono.Linker.Steps {
|
||||
if (CheckProcessed (method))
|
||||
return;
|
||||
|
||||
Annotations.Push (method);
|
||||
Tracer.Push (method);
|
||||
MarkType (method.DeclaringType);
|
||||
MarkCustomAttributes (method);
|
||||
MarkSecurityDeclarations (method);
|
||||
@@ -1382,7 +1422,7 @@ namespace Mono.Linker.Steps {
|
||||
Annotations.Mark (method);
|
||||
|
||||
ApplyPreserveMethods (method);
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
|
||||
// Allow subclassers to mark additional things when marking a method
|
||||
@@ -1433,7 +1473,7 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
}
|
||||
|
||||
bool ShouldParseMethodBody (MethodDefinition method)
|
||||
protected virtual bool ShouldParseMethodBody (MethodDefinition method)
|
||||
{
|
||||
if (!method.HasBody)
|
||||
return false;
|
||||
@@ -1447,6 +1487,8 @@ namespace Mono.Linker.Steps {
|
||||
case AssemblyAction.Link:
|
||||
case AssemblyAction.Copy:
|
||||
case AssemblyAction.CopyUsed:
|
||||
case AssemblyAction.AddBypassNGen:
|
||||
case AssemblyAction.AddBypassNGenUsed:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -71,7 +71,7 @@ namespace Mono.Linker.Steps {
|
||||
protected override void Process ()
|
||||
{
|
||||
CheckOutputDirectory ();
|
||||
Annotations.SaveDependencies ();
|
||||
Tracer.Finish ();
|
||||
}
|
||||
|
||||
void CheckOutputDirectory ()
|
||||
@@ -113,14 +113,18 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
CopyConfigFileIfNeeded (assembly, directory);
|
||||
|
||||
switch (Annotations.GetAction (assembly)) {
|
||||
var action = Annotations.GetAction (assembly);
|
||||
Context.LogMessage (MessageImportance.Low, $"Output action: {action,8} assembly: {assembly}");
|
||||
|
||||
switch (action) {
|
||||
case AssemblyAction.Save:
|
||||
case AssemblyAction.Link:
|
||||
Context.Annotations.AddDependency (assembly);
|
||||
case AssemblyAction.AddBypassNGen:
|
||||
Context.Tracer.AddDependency (assembly);
|
||||
WriteAssembly (assembly, directory);
|
||||
break;
|
||||
case AssemblyAction.Copy:
|
||||
Context.Annotations.AddDependency (assembly);
|
||||
Context.Tracer.AddDependency (assembly);
|
||||
CloseSymbols (assembly);
|
||||
CopyAssembly (GetOriginalAssemblyFileInfo (assembly), directory, Context.LinkSymbols);
|
||||
break;
|
||||
@@ -101,7 +101,7 @@ namespace Mono.Linker.Steps
|
||||
var action = rootVisibility == RootVisibility.Any ? AssemblyAction.Copy : AssemblyAction.Link;
|
||||
SetAction (context, assembly, action);
|
||||
|
||||
context.Annotations.Push (assembly);
|
||||
context.Tracer.Push (assembly);
|
||||
|
||||
foreach (TypeDefinition type in assembly.MainModule.Types)
|
||||
MarkType (context, type, rootVisibility);
|
||||
@@ -144,14 +144,11 @@ namespace Mono.Linker.Steps
|
||||
|
||||
context.Resolve (resolvedExportedType.Scope);
|
||||
MarkType (context, resolvedExportedType, rootVisibility);
|
||||
context.Annotations.Mark (exported);
|
||||
if (context.KeepTypeForwarderOnlyAssemblies) {
|
||||
context.Annotations.Mark (assembly.MainModule);
|
||||
}
|
||||
context.MarkingHelpers.MarkExportedType (exported, assembly.MainModule);
|
||||
}
|
||||
}
|
||||
|
||||
context.Annotations.Pop ();
|
||||
context.Tracer.Pop ();
|
||||
}
|
||||
|
||||
static void MarkType (LinkContext context, TypeDefinition type, RootVisibility rootVisibility)
|
||||
@@ -175,9 +172,7 @@ namespace Mono.Linker.Steps
|
||||
return;
|
||||
}
|
||||
|
||||
context.Annotations.Mark (type);
|
||||
|
||||
context.Annotations.Push (type);
|
||||
context.Annotations.MarkAndPush (type);
|
||||
|
||||
if (type.HasFields)
|
||||
MarkFields (context, type.Fields, rootVisibility);
|
||||
@@ -187,20 +182,20 @@ namespace Mono.Linker.Steps
|
||||
foreach (var nested in type.NestedTypes)
|
||||
MarkType (context, nested, rootVisibility);
|
||||
|
||||
context.Annotations.Pop ();
|
||||
context.Tracer.Pop ();
|
||||
}
|
||||
|
||||
void ProcessExecutable (AssemblyDefinition assembly)
|
||||
{
|
||||
SetAction (Context, assembly, AssemblyAction.Link);
|
||||
|
||||
Annotations.Push (assembly);
|
||||
Tracer.Push (assembly);
|
||||
|
||||
Annotations.Mark (assembly.EntryPoint.DeclaringType);
|
||||
|
||||
MarkMethod (Context, assembly.EntryPoint, MethodAction.Parse, RootVisibility.Any);
|
||||
|
||||
Annotations.Pop ();
|
||||
Tracer.Pop ();
|
||||
}
|
||||
|
||||
static void MarkFields (LinkContext context, Collection<FieldDefinition> fields, RootVisibility rootVisibility)
|
||||
@@ -95,25 +95,32 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
if (!string.IsNullOrEmpty (_resourceName))
|
||||
Context.Annotations.AddResourceToRemove (_resourceAssembly, _resourceName);
|
||||
} catch (Exception ex) {
|
||||
} catch (Exception ex) when (!(ex is XmlResolutionException)) {
|
||||
throw new XmlResolutionException (string.Format ("Failed to process XML description: {0}", _xmlDocumentLocation), ex);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessAssemblies (LinkContext context, XPathNodeIterator iterator)
|
||||
protected virtual void ProcessAssemblies (LinkContext context, XPathNodeIterator iterator)
|
||||
{
|
||||
while (iterator.MoveNext ()) {
|
||||
AssemblyDefinition assembly = GetAssembly (context, GetFullName (iterator.Current));
|
||||
if (GetTypePreserve (iterator.Current) == TypePreserve.All) {
|
||||
foreach (var type in assembly.MainModule.Types)
|
||||
MarkAndPreserveAll (type);
|
||||
} else {
|
||||
ProcessTypes (assembly, iterator.Current.SelectChildren ("type", _ns));
|
||||
ProcessNamespaces (assembly, iterator.Current.SelectChildren ("namespace", _ns));
|
||||
}
|
||||
AssemblyDefinition assembly = GetAssembly (context, GetAssemblyName (iterator.Current));
|
||||
ProcessAssembly (assembly, iterator);
|
||||
}
|
||||
}
|
||||
|
||||
protected void ProcessAssembly (AssemblyDefinition assembly, XPathNodeIterator iterator)
|
||||
{
|
||||
Tracer.Push (assembly);
|
||||
if (GetTypePreserve (iterator.Current) == TypePreserve.All) {
|
||||
foreach (var type in assembly.MainModule.Types)
|
||||
MarkAndPreserveAll (type);
|
||||
} else {
|
||||
ProcessTypes (assembly, iterator.Current.SelectChildren ("type", _ns));
|
||||
ProcessNamespaces (assembly, iterator.Current.SelectChildren ("namespace", _ns));
|
||||
}
|
||||
Tracer.Pop ();
|
||||
}
|
||||
|
||||
void ProcessNamespaces (AssemblyDefinition assembly, XPathNodeIterator iterator)
|
||||
{
|
||||
while (iterator.MoveNext ()) {
|
||||
@@ -129,14 +136,18 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
void MarkAndPreserveAll (TypeDefinition type)
|
||||
{
|
||||
Annotations.Mark (type);
|
||||
Annotations.MarkAndPush (type);
|
||||
Annotations.SetPreserve (type, TypePreserve.All);
|
||||
|
||||
if (!type.HasNestedTypes)
|
||||
if (!type.HasNestedTypes) {
|
||||
Tracer.Pop ();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (TypeDefinition nested in type.NestedTypes)
|
||||
MarkAndPreserveAll (nested);
|
||||
|
||||
Tracer.Pop ();
|
||||
}
|
||||
|
||||
void ProcessTypes (AssemblyDefinition assembly, XPathNodeIterator iterator)
|
||||
@@ -156,9 +167,10 @@ namespace Mono.Linker.Steps {
|
||||
if (assembly.MainModule.HasExportedTypes) {
|
||||
foreach (var exported in assembly.MainModule.ExportedTypes) {
|
||||
if (fullname == exported.FullName) {
|
||||
Annotations.Mark (exported);
|
||||
Annotations.Mark (assembly.MainModule);
|
||||
Tracer.Push (exported);
|
||||
MarkingHelpers.MarkExportedType (exported, assembly.MainModule);
|
||||
var resolvedExternal = exported.Resolve ();
|
||||
Tracer.Pop ();
|
||||
if (resolvedExternal != null) {
|
||||
type = resolvedExternal;
|
||||
break;
|
||||
@@ -200,8 +212,7 @@ namespace Mono.Linker.Steps {
|
||||
void MatchExportedType (ExportedType exportedType, ModuleDefinition module, Regex regex, XPathNavigator nav)
|
||||
{
|
||||
if (regex.Match (exportedType.FullName).Success) {
|
||||
Annotations.Mark (exportedType);
|
||||
Annotations.Mark (module);
|
||||
MarkingHelpers.MarkExportedType (exportedType, module);
|
||||
TypeDefinition type = null;
|
||||
try {
|
||||
type = exportedType.Resolve ();
|
||||
@@ -239,7 +250,8 @@ namespace Mono.Linker.Steps {
|
||||
return;
|
||||
}
|
||||
|
||||
Annotations.Mark (type);
|
||||
Annotations.MarkAndPush (type);
|
||||
Tracer.AddDirectDependency (this, type);
|
||||
|
||||
if (type.IsNested) {
|
||||
var parent = type;
|
||||
@@ -258,6 +270,7 @@ namespace Mono.Linker.Steps {
|
||||
MarkSelectedEvents (nav, type);
|
||||
MarkSelectedProperties (nav, type);
|
||||
}
|
||||
Tracer.Pop ();
|
||||
}
|
||||
|
||||
void MarkSelectedFields (XPathNavigator nav, TypeDefinition type)
|
||||
@@ -302,11 +315,10 @@ namespace Mono.Linker.Steps {
|
||||
if (attribute == null || attribute.Length == 0)
|
||||
return nav.HasChildren ? TypePreserve.Nothing : TypePreserve.All;
|
||||
|
||||
try {
|
||||
return (TypePreserve) Enum.Parse (typeof (TypePreserve), attribute, true);
|
||||
} catch {
|
||||
return TypePreserve.Nothing;
|
||||
}
|
||||
TypePreserve result;
|
||||
if (Enum.TryParse (attribute, true, out result))
|
||||
return result;
|
||||
return TypePreserve.Nothing;
|
||||
}
|
||||
|
||||
void ProcessFields (TypeDefinition type, XPathNodeIterator iterator)
|
||||
@@ -363,17 +375,21 @@ namespace Mono.Linker.Steps {
|
||||
return field.FieldType.FullName + " " + field.Name;
|
||||
}
|
||||
|
||||
void ProcessMethods (TypeDefinition type, XPathNodeIterator iterator)
|
||||
protected virtual void ProcessMethods (TypeDefinition type, XPathNodeIterator iterator)
|
||||
{
|
||||
while (iterator.MoveNext ()) {
|
||||
string value = GetSignature (iterator.Current);
|
||||
if (!String.IsNullOrEmpty (value))
|
||||
ProcessMethodSignature (type, value);
|
||||
while (iterator.MoveNext ())
|
||||
ProcessMethod (type, iterator);
|
||||
}
|
||||
|
||||
value = GetAttribute (iterator.Current, "name");
|
||||
if (!String.IsNullOrEmpty (value))
|
||||
ProcessMethodName (type, value);
|
||||
}
|
||||
protected void ProcessMethod(TypeDefinition type, XPathNodeIterator iterator)
|
||||
{
|
||||
string value = GetSignature (iterator.Current);
|
||||
if (!String.IsNullOrEmpty (value))
|
||||
ProcessMethodSignature (type, value);
|
||||
|
||||
value = GetAttribute (iterator.Current, "name");
|
||||
if (!String.IsNullOrEmpty (value))
|
||||
ProcessMethodName (type, value);
|
||||
}
|
||||
|
||||
void ProcessMethodSignature (TypeDefinition type, string signature)
|
||||
@@ -393,6 +409,7 @@ namespace Mono.Linker.Steps {
|
||||
void MarkMethod (MethodDefinition method)
|
||||
{
|
||||
Annotations.Mark (method);
|
||||
Tracer.AddDirectDependency (this, method);
|
||||
Annotations.SetAction (method, MethodAction.Parse);
|
||||
}
|
||||
|
||||
@@ -414,7 +431,7 @@ namespace Mono.Linker.Steps {
|
||||
MarkMethod (type, method, name);
|
||||
}
|
||||
|
||||
static MethodDefinition GetMethod (TypeDefinition type, string signature)
|
||||
protected static MethodDefinition GetMethod (TypeDefinition type, string signature)
|
||||
{
|
||||
if (type.HasMethods)
|
||||
foreach (MethodDefinition meth in type.Methods)
|
||||
@@ -578,17 +595,18 @@ namespace Mono.Linker.Steps {
|
||||
return property.PropertyType.FullName + " " + property.Name;
|
||||
}
|
||||
|
||||
static AssemblyDefinition GetAssembly (LinkContext context, string assemblyName)
|
||||
protected AssemblyDefinition GetAssembly (LinkContext context, AssemblyNameReference assemblyName)
|
||||
{
|
||||
AssemblyNameReference reference = AssemblyNameReference.Parse (assemblyName);
|
||||
AssemblyDefinition assembly;
|
||||
|
||||
assembly = context.Resolve (reference);
|
||||
|
||||
var assembly = context.Resolve (assemblyName);
|
||||
ProcessReferences (assembly, context);
|
||||
return assembly;
|
||||
}
|
||||
|
||||
protected virtual AssemblyNameReference GetAssemblyName (XPathNavigator nav)
|
||||
{
|
||||
return AssemblyNameReference.Parse (GetFullName (nav));
|
||||
}
|
||||
|
||||
static void ProcessReferences (AssemblyDefinition assembly, LinkContext context)
|
||||
{
|
||||
context.ResolveReferences (assembly);
|
||||
@@ -600,19 +618,13 @@ namespace Mono.Linker.Steps {
|
||||
if (attribute == null || attribute.Length == 0)
|
||||
return true;
|
||||
|
||||
return TryParseBool (attribute);
|
||||
bool result;
|
||||
if (bool.TryParse (attribute, out result))
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool TryParseBool (string s)
|
||||
{
|
||||
try {
|
||||
return bool.Parse (s);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static string GetSignature (XPathNavigator nav)
|
||||
protected static string GetSignature (XPathNavigator nav)
|
||||
{
|
||||
return GetAttribute (nav, _signature);
|
||||
}
|
||||
@@ -640,7 +652,7 @@ namespace Mono.Linker.Steps {
|
||||
return _accessorsAll;
|
||||
}
|
||||
|
||||
static string GetAttribute (XPathNavigator nav, string attribute)
|
||||
protected static string GetAttribute (XPathNavigator nav, string attribute)
|
||||
{
|
||||
return nav.GetAttribute (attribute, _ns);
|
||||
}
|
||||
@@ -61,14 +61,14 @@ namespace Mono.Linker.Steps {
|
||||
Annotations.SetAction (assembly, AssemblyAction.Save);
|
||||
}
|
||||
|
||||
AssemblyAction currentAction = Annotations.GetAction(assembly);
|
||||
AssemblyAction currentAction = Annotations.GetAction (assembly);
|
||||
|
||||
if ((currentAction == AssemblyAction.Link) || (currentAction == AssemblyAction.Save)) {
|
||||
// if we save (only or by linking) then unmarked exports (e.g. forwarders) must be cleaned
|
||||
// or they can point to nothing which will break later (e.g. when re-loading for stripping IL)
|
||||
// reference: https://bugzilla.xamarin.com/show_bug.cgi?id=36577
|
||||
if (assembly.MainModule.HasExportedTypes)
|
||||
SweepCollection(assembly.MainModule.ExportedTypes);
|
||||
SweepCollectionNonAttributable (assembly.MainModule.ExportedTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,14 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
break;
|
||||
|
||||
case AssemblyAction.AddBypassNGenUsed:
|
||||
if (!IsMarkedAssembly (assembly)) {
|
||||
RemoveAssembly (assembly);
|
||||
} else {
|
||||
Annotations.SetAction (assembly, AssemblyAction.AddBypassNGen);
|
||||
}
|
||||
return;
|
||||
|
||||
case AssemblyAction.CopyUsed:
|
||||
if (!IsMarkedAssembly (assembly)) {
|
||||
RemoveAssembly (assembly);
|
||||
@@ -115,6 +123,7 @@ namespace Mono.Linker.Steps {
|
||||
assembly.MainModule.Types.Add (type);
|
||||
|
||||
SweepResources (assembly);
|
||||
SweepCustomAttributes (assembly);
|
||||
}
|
||||
|
||||
bool IsMarkedAssembly (AssemblyDefinition assembly)
|
||||
@@ -184,8 +193,17 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
break;
|
||||
|
||||
case AssemblyAction.CopyUsed:
|
||||
if (IsMarkedAssembly (assembly) && !Context.KeepTypeForwarderOnlyAssemblies) {
|
||||
Annotations.SetAction (assembly, AssemblyAction.Save);
|
||||
ResolveAllTypeReferences (assembly);
|
||||
}
|
||||
break;
|
||||
|
||||
case AssemblyAction.Save:
|
||||
case AssemblyAction.Link:
|
||||
case AssemblyAction.AddBypassNGen:
|
||||
case AssemblyAction.AddBypassNGenUsed:
|
||||
if (!Context.KeepTypeForwarderOnlyAssemblies) {
|
||||
ResolveAllTypeReferences (assembly);
|
||||
}
|
||||
@@ -258,6 +276,12 @@ namespace Mono.Linker.Steps {
|
||||
|
||||
if (type.HasInterfaces)
|
||||
SweepInterfaces (type);
|
||||
|
||||
if (type.HasCustomAttributes)
|
||||
SweepCustomAttributes (type);
|
||||
|
||||
if (type.HasProperties)
|
||||
SweepCustomAttributeCollection (type.Properties);
|
||||
}
|
||||
|
||||
protected void SweepNestedTypes (TypeDefinition type)
|
||||
@@ -284,7 +308,24 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
}
|
||||
|
||||
void SweepMethods (Collection<MethodDefinition> methods)
|
||||
protected void SweepCustomAttributes (ICustomAttributeProvider provider)
|
||||
{
|
||||
for (int i = provider.CustomAttributes.Count - 1; i >= 0; i--) {
|
||||
var attribute = provider.CustomAttributes [i];
|
||||
if (!Annotations.IsMarked (attribute)) {
|
||||
CustomAttributeUsageRemoved (provider, attribute);
|
||||
provider.CustomAttributes.RemoveAt (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void SweepCustomAttributeCollection<T> (Collection<T> providers) where T : ICustomAttributeProvider
|
||||
{
|
||||
foreach (var provider in providers)
|
||||
SweepCustomAttributes (provider);
|
||||
}
|
||||
|
||||
protected virtual void SweepMethods (Collection<MethodDefinition> methods)
|
||||
{
|
||||
SweepCollection (methods);
|
||||
if (sweepSymbols)
|
||||
@@ -336,15 +377,31 @@ namespace Mono.Linker.Steps {
|
||||
}
|
||||
}
|
||||
|
||||
protected void SweepCollection<T> (IList<T> list) where T : IMetadataTokenProvider
|
||||
protected void SweepCollection<T> (IList<T> list) where T : ICustomAttributeProvider
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
if (!Annotations.IsMarked (list [i])) {
|
||||
if (ShouldRemove (list [i])) {
|
||||
ElementRemoved (list [i]);
|
||||
list.RemoveAt (i--);
|
||||
} else {
|
||||
SweepCustomAttributes (list [i]);
|
||||
}
|
||||
}
|
||||
|
||||
protected void SweepCollectionNonAttributable<T> (IList<T> list) where T : IMetadataTokenProvider
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
if (ShouldRemove (list [i])) {
|
||||
ElementRemoved (list [i]);
|
||||
list.RemoveAt (i--);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool ShouldRemove<T> (T element) where T : IMetadataTokenProvider
|
||||
{
|
||||
return !Annotations.IsMarked (element);
|
||||
}
|
||||
|
||||
static bool AreSameReference (AssemblyNameReference a, AssemblyNameReference b)
|
||||
{
|
||||
if (a == b)
|
||||
@@ -370,5 +427,9 @@ namespace Mono.Linker.Steps {
|
||||
protected virtual void InterfaceRemoved (TypeDefinition type, InterfaceImplementation iface)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void CustomAttributeUsageRemoved (ICustomAttributeProvider provider, CustomAttribute attribute)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
@@ -38,6 +36,8 @@ namespace Mono.Linker {
|
||||
|
||||
public class AnnotationStore {
|
||||
|
||||
protected readonly LinkContext context;
|
||||
|
||||
readonly Dictionary<AssemblyDefinition, AssemblyAction> assembly_actions = new Dictionary<AssemblyDefinition, AssemblyAction> ();
|
||||
readonly Dictionary<MethodDefinition, MethodAction> method_actions = new Dictionary<MethodDefinition, MethodAction> ();
|
||||
readonly HashSet<IMetadataTokenProvider> marked = new HashSet<IMetadataTokenProvider> ();
|
||||
@@ -51,31 +51,27 @@ namespace Mono.Linker {
|
||||
|
||||
readonly Dictionary<object, Dictionary<IMetadataTokenProvider, object>> custom_annotations = new Dictionary<object, Dictionary<IMetadataTokenProvider, object>> ();
|
||||
readonly Dictionary<AssemblyDefinition, HashSet<string>> resources_to_remove = new Dictionary<AssemblyDefinition, HashSet<string>> ();
|
||||
readonly HashSet<CustomAttribute> marked_attributes = new HashSet<CustomAttribute> ();
|
||||
|
||||
Stack<object> dependency_stack;
|
||||
System.Xml.XmlWriter writer;
|
||||
GZipStream zipStream;
|
||||
public AnnotationStore (LinkContext context) => this.context = context;
|
||||
|
||||
public void PrepareDependenciesDump ()
|
||||
{
|
||||
PrepareDependenciesDump ("linker-dependencies.xml.gz");
|
||||
protected Tracer Tracer {
|
||||
get {
|
||||
return context.Tracer;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete ("Use Tracer in LinkContext directly")]
|
||||
public void PrepareDependenciesDump ()
|
||||
{
|
||||
Tracer.Start ();
|
||||
}
|
||||
|
||||
[Obsolete ("Use Tracer in LinkContext directly")]
|
||||
public void PrepareDependenciesDump (string filename)
|
||||
{
|
||||
dependency_stack = new Stack<object> ();
|
||||
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
|
||||
settings.Indent = true;
|
||||
settings.IndentChars = "\t";
|
||||
var depsFile = File.OpenWrite (filename);
|
||||
zipStream = new GZipStream (depsFile, CompressionMode.Compress);
|
||||
|
||||
writer = System.Xml.XmlWriter.Create (zipStream, settings);
|
||||
writer.WriteStartDocument ();
|
||||
writer.WriteStartElement ("dependencies");
|
||||
writer.WriteStartAttribute ("version");
|
||||
writer.WriteString ("1.0");
|
||||
writer.WriteEndAttribute ();
|
||||
Tracer.DependenciesFileName = filename;
|
||||
Tracer.Start ();
|
||||
}
|
||||
|
||||
public ICollection<AssemblyDefinition> GetAssemblies ()
|
||||
@@ -119,7 +115,18 @@ namespace Mono.Linker {
|
||||
public void Mark (IMetadataTokenProvider provider)
|
||||
{
|
||||
marked.Add (provider);
|
||||
AddDependency (provider);
|
||||
Tracer.AddDependency (provider, true);
|
||||
}
|
||||
|
||||
public void Mark (CustomAttribute attribute)
|
||||
{
|
||||
marked_attributes.Add (attribute);
|
||||
}
|
||||
|
||||
public void MarkAndPush (IMetadataTokenProvider provider)
|
||||
{
|
||||
Mark (provider);
|
||||
Tracer.Push (provider, false);
|
||||
}
|
||||
|
||||
public bool IsMarked (IMetadataTokenProvider provider)
|
||||
@@ -127,6 +134,11 @@ namespace Mono.Linker {
|
||||
return marked.Contains (provider);
|
||||
}
|
||||
|
||||
public bool IsMarked (CustomAttribute attribute)
|
||||
{
|
||||
return marked_attributes.Contains (attribute);
|
||||
}
|
||||
|
||||
public void Processed (IMetadataTokenProvider provider)
|
||||
{
|
||||
processed.Add (provider);
|
||||
@@ -315,64 +327,5 @@ namespace Mono.Linker {
|
||||
custom_annotations.Add (key, slots);
|
||||
return slots;
|
||||
}
|
||||
|
||||
public void AddDependency (object o)
|
||||
{
|
||||
if (writer == null)
|
||||
return;
|
||||
|
||||
KeyValuePair<object, object> pair = new KeyValuePair<object, object> (dependency_stack.Count > 0 ? dependency_stack.Peek () : null, o);
|
||||
if (pair.Key != pair.Value)
|
||||
{
|
||||
writer.WriteStartElement ("edge");
|
||||
writer.WriteAttributeString ("b", TokenString (pair.Key));
|
||||
writer.WriteAttributeString ("e", TokenString (pair.Value));
|
||||
writer.WriteEndElement ();
|
||||
}
|
||||
}
|
||||
|
||||
public void Push (object o)
|
||||
{
|
||||
if (writer == null)
|
||||
return;
|
||||
|
||||
if (dependency_stack.Count > 0)
|
||||
AddDependency (o);
|
||||
dependency_stack.Push (o);
|
||||
}
|
||||
|
||||
public void Pop ()
|
||||
{
|
||||
if (writer == null)
|
||||
return;
|
||||
|
||||
dependency_stack.Pop ();
|
||||
}
|
||||
|
||||
string TokenString (object o)
|
||||
{
|
||||
if (o == null)
|
||||
return "N:null";
|
||||
|
||||
if (o is IMetadataTokenProvider)
|
||||
return (o as IMetadataTokenProvider).MetadataToken.TokenType + ":" + o;
|
||||
|
||||
return "Other:" + o;
|
||||
}
|
||||
|
||||
public void SaveDependencies ()
|
||||
{
|
||||
if (writer == null)
|
||||
return;
|
||||
|
||||
writer.WriteEndElement ();
|
||||
writer.WriteEndDocument ();
|
||||
writer.Flush ();
|
||||
writer.Dispose ();
|
||||
zipStream.Dispose ();
|
||||
writer = null;
|
||||
zipStream = null;
|
||||
dependency_stack = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,11 @@ namespace Mono.Linker {
|
||||
// Save the assembly/symbols in memory without linking it.
|
||||
// E.g. useful to remove unneeded assembly references (as done in SweepStep),
|
||||
// resolving [TypeForwardedTo] attributes (like PCL) to their final location
|
||||
Save
|
||||
Save,
|
||||
// Keep all types, methods, and fields but add System.Runtime.BypassNGenAttribute to unmarked methods.
|
||||
AddBypassNGen,
|
||||
// Keep all types, methods, and fields in marked assemblies but add System.Runtime.BypassNGenAttribute to unmarked methods.
|
||||
// Delete unmarked assemblies.
|
||||
AddBypassNGenUsed
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user