Skip to content

Refresh code shared with IL Linker #703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Sources taken from https://github.com/mono/linker/tree/1d02cb5bd77aff898b85cf1d8438067b899fedad/src/linker/Linker.Dataflow.
Sources taken from https://github.com/mono/linker/tree/2cb420dbabb4ec86d41a1b431696e58f45f031cd/src/linker/Linker.Dataflow.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// 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.

Expand Down Expand Up @@ -513,8 +513,12 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c
return false;

var callingMethodDefinition = callingMethodBody.Method;
bool shouldEnableReflectionWarnings = ShouldEnableReflectionPatternReporting (callingMethodDefinition);
var reflectionContext = new ReflectionPatternContext (_context, shouldEnableReflectionWarnings, callingMethodDefinition, calledMethod.Resolve (), operation);
var reflectionContext = new ReflectionPatternContext (
_context,
ShouldEnableReflectionPatternReporting (callingMethodDefinition),
callingMethodDefinition,
calledMethod.Resolve (),
operation);

DynamicallyAccessedMemberTypes returnValueDynamicallyAccessedMemberTypes = 0;

Expand Down Expand Up @@ -820,9 +824,8 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c
reflectionContext.AnalyzingPattern ();

var parameters = calledMethod.Parameters;
if ((parameters.Count == 3 && (methodParams[2].Kind == ValueNodeKind.MethodReturn || methodParams[2].Kind == ValueNodeKind.ConstInt || methodParams[2].Kind == ValueNodeKind.LoadField)
&& (methodParams[2].AsConstInt () == null || methodParams[2].AsConstInt () != 0)) ||
(parameters.Count == 5 && (methodParams[4].AsConstInt () == null || methodParams[4].AsConstInt () != 0))) {
if ((parameters.Count == 3 && parameters[2].ParameterType.MetadataType == MetadataType.Boolean && methodParams[2].AsConstInt () != 0) ||
(parameters.Count == 5 && methodParams[4].AsConstInt () != 0)) {
reflectionContext.RecordUnrecognizedPattern (2096, $"Call to '{calledMethod.GetDisplayName ()}' can perform case insensitive lookup of the type, currently ILLink can not guarantee presence of all the matching types");
break;
}
Expand Down Expand Up @@ -1331,18 +1334,7 @@ methodParams[argsParam] is ArrayValue arrayValue &&
reflectionContext.RecordHandledPattern ();
}

if (shouldEnableReflectionWarnings &&
_context.Annotations.TryGetLinkerAttribute (calledMethodDefinition, out RequiresUnreferencedCodeAttribute requiresUnreferencedCode)) {
string message =
$"Calling '{calledMethodDefinition.GetDisplayName ()}' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. " +
$"{requiresUnreferencedCode.Message}.";

if (requiresUnreferencedCode.Url != null) {
message += " " + requiresUnreferencedCode.Url;
}

_context.LogWarning (message, 2026, callingMethodDefinition, operation.Offset, MessageSubCategory.TrimAnalysis);
}
_markStep.CheckAndReportRequiresUnreferencedCode (calledMethodDefinition, new MessageOrigin (callingMethodDefinition, operation.Offset));

// To get good reporting of errors we need to track the origin of the value for all method calls
// but except Newobj as those are special.
Expand Down Expand Up @@ -1405,7 +1397,7 @@ void ProcessCreateInstanceByName (ref ReflectionPatternContext reflectionContext
if (assemblyNameValue is KnownStringValue assemblyNameStringValue) {
foreach (var typeNameValue in methodParams[methodParamsOffset + 1].UniqueValues ()) {
if (typeNameValue is KnownStringValue typeNameStringValue) {
var resolvedAssembly = _context.GetLoadedAssembly (assemblyNameStringValue.Contents);
var resolvedAssembly = _context.TryResolve (assemblyNameStringValue.Contents);
if (resolvedAssembly == null) {
reflectionContext.RecordUnrecognizedPattern (2061, $"The assembly name '{assemblyNameStringValue.Contents}' passed to method '{calledMethod.GetDisplayName ()}' references assembly which is not available.");
continue;
Expand Down Expand Up @@ -1712,23 +1704,23 @@ void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflect
foreach (var member in typeDefinition.GetDynamicallyAccessedMembers (requiredMemberTypes)) {
switch (member) {
case MethodDefinition method:
MarkMethod (ref reflectionContext, method);
MarkMethod (ref reflectionContext, method, DependencyKind.DynamicallyAccessedMember);
break;
case FieldDefinition field:
MarkField (ref reflectionContext, field);
MarkField (ref reflectionContext, field, DependencyKind.DynamicallyAccessedMember);
break;
case TypeDefinition nestedType:
MarkNestedType (ref reflectionContext, nestedType);
MarkNestedType (ref reflectionContext, nestedType, DependencyKind.DynamicallyAccessedMember);
break;
case PropertyDefinition property:
MarkProperty (ref reflectionContext, property);
MarkProperty (ref reflectionContext, property, DependencyKind.DynamicallyAccessedMember);
break;
case EventDefinition @event:
MarkEvent (ref reflectionContext, @event);
MarkEvent (ref reflectionContext, @event, DependencyKind.DynamicallyAccessedMember);
break;
case null:
var source = reflectionContext.Source;
reflectionContext.RecordRecognizedPattern (typeDefinition, () => _markStep.MarkEntireType (typeDefinition, includeBaseTypes: true, new DependencyInfo (DependencyKind.AccessedViaReflection, source), source));
reflectionContext.RecordRecognizedPattern (typeDefinition, () => _markStep.MarkEntireType (typeDefinition, includeBaseTypes: true, includeInterfaceTypes: true, new DependencyInfo (DependencyKind.DynamicallyAccessedMember, source), source));
break;
}
}
Expand All @@ -1740,28 +1732,29 @@ void MarkType (ref ReflectionPatternContext reflectionContext, TypeReference typ
reflectionContext.RecordRecognizedPattern (typeReference?.Resolve (), () => _markStep.MarkTypeVisibleToReflection (typeReference, new DependencyInfo (DependencyKind.AccessedViaReflection, source), source));
}

void MarkMethod (ref ReflectionPatternContext reflectionContext, MethodDefinition method)
void MarkMethod (ref ReflectionPatternContext reflectionContext, MethodDefinition method, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection)
{
var source = reflectionContext.Source;
reflectionContext.RecordRecognizedPattern (method, () => _markStep.MarkIndirectlyCalledMethod (method, new DependencyInfo (DependencyKind.AccessedViaReflection, source), source));
var offset = reflectionContext.Instruction?.Offset;
reflectionContext.RecordRecognizedPattern (method, () => _markStep.MarkIndirectlyCalledMethod (method, new DependencyInfo (dependencyKind, source), new MessageOrigin (source, offset)));
}

void MarkNestedType (ref ReflectionPatternContext reflectionContext, TypeDefinition nestedType)
void MarkNestedType (ref ReflectionPatternContext reflectionContext, TypeDefinition nestedType, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection)
{
var source = reflectionContext.Source;
reflectionContext.RecordRecognizedPattern (nestedType, () => _markStep.MarkTypeVisibleToReflection (nestedType, new DependencyInfo (DependencyKind.AccessedViaReflection, source), source));
reflectionContext.RecordRecognizedPattern (nestedType, () => _markStep.MarkTypeVisibleToReflection (nestedType, new DependencyInfo (dependencyKind, source), source));
}

void MarkField (ref ReflectionPatternContext reflectionContext, FieldDefinition field)
void MarkField (ref ReflectionPatternContext reflectionContext, FieldDefinition field, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection)
{
var source = reflectionContext.Source;
reflectionContext.RecordRecognizedPattern (field, () => _markStep.MarkField (field, new DependencyInfo (DependencyKind.AccessedViaReflection, source)));
reflectionContext.RecordRecognizedPattern (field, () => _markStep.MarkField (field, new DependencyInfo (dependencyKind, source)));
}

void MarkProperty (ref ReflectionPatternContext reflectionContext, PropertyDefinition property)
void MarkProperty (ref ReflectionPatternContext reflectionContext, PropertyDefinition property, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection)
{
var source = reflectionContext.Source;
var dependencyInfo = new DependencyInfo (DependencyKind.AccessedViaReflection, source);
var dependencyInfo = new DependencyInfo (dependencyKind, source);
reflectionContext.RecordRecognizedPattern (property, () => {
// Marking the property itself actually doesn't keep it (it only marks its attributes and records the dependency), we have to mark the methods on it
_markStep.MarkProperty (property, dependencyInfo);
Expand All @@ -1774,10 +1767,10 @@ void MarkProperty (ref ReflectionPatternContext reflectionContext, PropertyDefin
});
}

void MarkEvent (ref ReflectionPatternContext reflectionContext, EventDefinition @event)
void MarkEvent (ref ReflectionPatternContext reflectionContext, EventDefinition @event, DependencyKind dependencyKind = DependencyKind.AccessedViaReflection)
{
var source = reflectionContext.Source;
var dependencyInfo = new DependencyInfo (DependencyKind.AccessedViaReflection, reflectionContext.Source);
var dependencyInfo = new DependencyInfo (dependencyKind, reflectionContext.Source);
reflectionContext.RecordRecognizedPattern (@event, () => {
// MarkEvent actually marks the add/remove/invoke methods as well, so no need to mark those explicitly
_markStep.MarkEvent (@event, dependencyInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1096,9 +1096,8 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet
reflectionContext.AnalyzingPattern();

var parameters = calledMethod.Signature;
if ((parameters.Length == 3 && (methodParams[2].Kind == ValueNodeKind.MethodReturn || methodParams[2].Kind == ValueNodeKind.ConstInt || methodParams[2].Kind == ValueNodeKind.LoadField)
&& (methodParams[2].AsConstInt() == null || methodParams[2].AsConstInt() != 0)) ||
(parameters.Length == 5 && (methodParams[4].AsConstInt() == null || methodParams[4].AsConstInt() != 0)))
if ((parameters.Length == 3 && parameters[2].IsWellKnownType(WellKnownType.Boolean) && methodParams[2].AsConstInt() != 0) ||
(parameters.Length == 5 && methodParams[4].AsConstInt() != 0))
{
reflectionContext.RecordUnrecognizedPattern(2096, $"Call to '{calledMethod.GetDisplayName()}' can perform case insensitive lookup of the type, currently ILLink can not guarantee presence of all the matching types");
break;
Expand Down Expand Up @@ -1713,7 +1712,7 @@ methodParams[argsParam] is ArrayValue arrayValue &&
attributeMessage += '.';

string message =
$"Calling '{calledMethod.GetDisplayName()}' which has `RequiresUnreferencedCodeAttribute` can break functionality when trimming application code. {attributeMessage}";
$"Using method '{calledMethod.GetDisplayName()}' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. {attributeMessage}";

//if (requiresUnreferencedCode.Url != null)
//{
Expand Down