Welcome to mirror list, hosted at ThFree Co, Russian Federation.

InterproceduralState.cs « Linker.Dataflow « linker « src - github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bfb5cf5730d476927eeb8814ae786d1ba7e00493 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// 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;
using System.Collections.Generic;
using System.Diagnostics;
using ILLink.Shared.DataFlow;
using Mono.Cecil;
using Mono.Cecil.Cil;
using HoistedLocalState = ILLink.Shared.DataFlow.DefaultValueDictionary<
	Mono.Linker.Dataflow.HoistedLocalKey,
	ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>>;
using MultiValue = ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>;

namespace Mono.Linker.Dataflow
{
	// Tracks the set of methods which get analyzer together during interprocedural analysis,
	// and the possible states of hoisted locals in state machine methods and lambdas/local functions.
	struct InterproceduralState : IEquatable<InterproceduralState>
	{
		public ValueSet<MethodIL> MethodBodies;
		public HoistedLocalState HoistedLocals;
		readonly InterproceduralStateLattice lattice;

		public InterproceduralState (ValueSet<MethodIL> methodBodies, HoistedLocalState hoistedLocals, InterproceduralStateLattice lattice)
			=> (MethodBodies, HoistedLocals, this.lattice) = (methodBodies, hoistedLocals, lattice);

		public bool Equals (InterproceduralState other)
			=> MethodBodies.Equals (other.MethodBodies) && HoistedLocals.Equals (other.HoistedLocals);

		public override bool Equals (object? obj)
			=> obj is InterproceduralState state && Equals (state);

		public override int GetHashCode () => base.GetHashCode ();

		public InterproceduralState Clone ()
			=> new (MethodBodies.Clone (), HoistedLocals.Clone (), lattice);

		public void TrackMethod (MethodDefinition method)
		{
			if (method.Body is not MethodBody methodBody)
				return;

			TrackMethod (methodBody);
		}

		public void TrackMethod (MethodBody methodBody)
		{
			TrackMethod (lattice.Context.GetMethodIL (methodBody));
		}

		public void TrackMethod (MethodIL methodIL)
		{
			// Work around the fact that ValueSet is readonly
			var methodsList = new List<MethodIL> (MethodBodies);
			methodsList.Add (methodIL);

			// For state machine methods, also scan the state machine members.
			// Simplification: assume that all generated methods of the state machine type are
			// reached at the point where the state machine method is reached.
			if (CompilerGeneratedState.TryGetStateMachineType (methodIL.Method, out TypeDefinition? stateMachineType)) {
				foreach (var stateMachineMethod in stateMachineType.Methods) {
					Debug.Assert (!CompilerGeneratedNames.IsLambdaOrLocalFunction (stateMachineMethod.Name));
					if (stateMachineMethod.Body is MethodBody stateMachineMethodBody)
						methodsList.Add (lattice.Context.GetMethodIL (stateMachineMethodBody));
				}
			}

			MethodBodies = new ValueSet<MethodIL> (methodsList);
		}

		public void SetHoistedLocal (HoistedLocalKey key, MultiValue value)
		{
			// For hoisted locals, we track the entire set of assigned values seen
			// in the closure of a method, so setting a hoisted local value meets
			// it with any existing value.
			HoistedLocals.Set (key,
				lattice.HoistedLocalsLattice.ValueLattice.Meet (
					HoistedLocals.Get (key), value));
		}

		public MultiValue GetHoistedLocal (HoistedLocalKey key)
			=> HoistedLocals.Get (key);
	}

	readonly struct InterproceduralStateLattice : ILattice<InterproceduralState>
	{
		public readonly ValueSetLattice<MethodIL> MethodBodyLattice;
		public readonly DictionaryLattice<HoistedLocalKey, MultiValue, ValueSetLattice<SingleValue>> HoistedLocalsLattice;
		public readonly LinkContext Context;

		public InterproceduralStateLattice (
			ValueSetLattice<MethodIL> methodBodyLattice,
			DictionaryLattice<HoistedLocalKey, MultiValue, ValueSetLattice<SingleValue>> hoistedLocalsLattice,
			LinkContext context)
			=> (MethodBodyLattice, HoistedLocalsLattice, Context) = (methodBodyLattice, hoistedLocalsLattice, context);

		public InterproceduralState Top => new InterproceduralState (MethodBodyLattice.Top, HoistedLocalsLattice.Top, this);

		public InterproceduralState Meet (InterproceduralState left, InterproceduralState right)
			=> new (
				MethodBodyLattice.Meet (left.MethodBodies, right.MethodBodies),
				HoistedLocalsLattice.Meet (left.HoistedLocals, right.HoistedLocals),
				this);
	}
}