|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Immutable;
using System.Diagnostics;
using ILLink.Shared.DataFlow;
using ILLink.Shared.TrimAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Linker.Steps;
using MultiValue = ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>;
namespace Mono.Linker.Dataflow
{
public readonly record struct TrimAnalysisMethodCallPattern
{
public readonly Instruction Operation;
public readonly MethodReference CalledMethod;
public readonly MultiValue Instance;
public readonly ImmutableArray<MultiValue> Arguments;
public readonly MessageOrigin Origin;
public TrimAnalysisMethodCallPattern (
Instruction operation,
MethodReference calledMethod,
MultiValue instance,
ImmutableArray<MultiValue> arguments,
MessageOrigin origin)
{
Debug.Assert (origin.Provider is MethodDefinition);
Operation = operation;
CalledMethod = calledMethod;
Instance = instance.DeepCopy ();
if (arguments.IsEmpty) {
Arguments = ImmutableArray<MultiValue>.Empty;
} else {
var builder = ImmutableArray.CreateBuilder<MultiValue> ();
foreach (var argument in arguments)
builder.Add (argument.DeepCopy ());
Arguments = builder.ToImmutableArray ();
}
Origin = origin;
}
public TrimAnalysisMethodCallPattern Merge (ValueSetLattice<SingleValue> lattice, TrimAnalysisMethodCallPattern other)
{
Debug.Assert (Operation == other.Operation);
Debug.Assert (Origin == other.Origin);
Debug.Assert (CalledMethod == other.CalledMethod);
Debug.Assert (Arguments.Length == other.Arguments.Length);
var argumentsBuilder = ImmutableArray.CreateBuilder<MultiValue> ();
for (int i = 0; i < Arguments.Length; i++)
argumentsBuilder.Add (lattice.Meet (Arguments[i], other.Arguments[i]));
return new TrimAnalysisMethodCallPattern (
Operation,
CalledMethod,
lattice.Meet (Instance, other.Instance),
argumentsBuilder.ToImmutable (),
Origin);
}
public void MarkAndProduceDiagnostics (ReflectionMarker reflectionMarker, MarkStep markStep, LinkContext context)
{
bool diagnosticsEnabled = !context.Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (Origin.Provider, out _);
var diagnosticContext = new DiagnosticContext (Origin, diagnosticsEnabled, context);
ReflectionMethodBodyScanner.HandleCall (Operation, CalledMethod, Instance, Arguments,
diagnosticContext,
reflectionMarker,
context,
markStep);
}
}
}
|