File: Linker.Dataflow\TrimAnalysisMethodCallPattern.cs
Web Access
Project: src\src\tools\illink\src\linker\Mono.Linker.csproj (illink)
// 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);
		}
	}
}