diff options
author | Jackson Schuster <36744439+jtschuster@users.noreply.github.com> | 2022-04-01 20:41:17 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-01 20:41:17 +0300 |
commit | 987a86e2e96a06e01f5d84c416c3c5f70e7ecbd6 (patch) | |
tree | 1b7785d4e155a5ac0302221c6080f72b96375484 | |
parent | 4f0d349e43a71d44ef71339293701fcfc2da997e (diff) |
Break up ValueNode.cs so each Value has it's own file (#2713)
* Break up ValueNode.cs so each Value has it's own file
* Update ValueNode.cs namespace
-rw-r--r-- | src/linker/Linker.Dataflow/ArrayValue.cs | 121 | ||||
-rw-r--r-- | src/linker/Linker.Dataflow/FieldValue.cs | 41 | ||||
-rw-r--r-- | src/linker/Linker.Dataflow/GenericParameterValue.cs | 35 | ||||
-rw-r--r-- | src/linker/Linker.Dataflow/MethodParameterValue.cs | 49 | ||||
-rw-r--r-- | src/linker/Linker.Dataflow/MethodReturnValue.cs | 39 | ||||
-rw-r--r-- | src/linker/Linker.Dataflow/MethodThisParameterValue.cs | 40 | ||||
-rw-r--r-- | src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs | 2 | ||||
-rw-r--r-- | src/linker/Linker.Dataflow/RuntimeMethodHandleValue.cs | 24 | ||||
-rw-r--r-- | src/linker/Linker.Dataflow/SingleValueExtensions.cs | 87 | ||||
-rw-r--r-- | src/linker/Linker.Dataflow/ValueNode.cs | 348 |
10 files changed, 437 insertions, 349 deletions
diff --git a/src/linker/Linker.Dataflow/ArrayValue.cs b/src/linker/Linker.Dataflow/ArrayValue.cs new file mode 100644 index 000000000..884e5cd7e --- /dev/null +++ b/src/linker/Linker.Dataflow/ArrayValue.cs @@ -0,0 +1,121 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Text; +using ILLink.Shared.DataFlow; +using Mono.Cecil; +using Mono.Linker.Dataflow; +using MultiValue = ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>; + + +namespace ILLink.Shared.TrimAnalysis +{ + partial record ArrayValue + { + public static MultiValue Create (MultiValue size, TypeReference elementType) + { + MultiValue result = MultiValueLattice.Top; + foreach (var sizeValue in size) { + result = MultiValueLattice.Meet (result, new MultiValue (new ArrayValue (sizeValue, elementType))); + } + + return result; + } + + public static MultiValue Create (int size, TypeReference elementType) + { + return new MultiValue (new ArrayValue (new ConstIntValue (size), elementType)); + } + + /// <summary> + /// Constructs an array value of the given size + /// </summary> + ArrayValue (SingleValue size, TypeReference elementType) + { + Size = size; + ElementType = elementType; + IndexValues = new Dictionary<int, ValueBasicBlockPair> (); + } + + public TypeReference ElementType { get; } + public Dictionary<int, ValueBasicBlockPair> IndexValues { get; } + + public partial bool TryGetValueByIndex (int index, out MultiValue value) + { + if (IndexValues.TryGetValue (index, out var valuePair)) { + value = valuePair.Value; + return true; + } + + value = default; + return false; + } + + public override int GetHashCode () + { + return HashCode.Combine (GetType ().GetHashCode (), Size); + } + + public bool Equals (ArrayValue? otherArr) + { + if (otherArr == null) + return false; + + bool equals = Size.Equals (otherArr.Size); + equals &= IndexValues.Count == otherArr.IndexValues.Count; + if (!equals) + return false; + + // If both sets T and O are the same size and "T intersect O" is empty, then T == O. + HashSet<KeyValuePair<int, ValueBasicBlockPair>> thisValueSet = new (IndexValues); + HashSet<KeyValuePair<int, ValueBasicBlockPair>> otherValueSet = new (otherArr.IndexValues); + thisValueSet.ExceptWith (otherValueSet); + return thisValueSet.Count == 0; + } + + public override SingleValue DeepCopy () + { + var newValue = new ArrayValue (Size.DeepCopy (), ElementType); + foreach (var kvp in IndexValues) { + newValue.IndexValues.Add (kvp.Key, new ValueBasicBlockPair (kvp.Value.Value.Clone (), kvp.Value.BasicBlockIndex)); + } + + return newValue; + } + + public override string ToString () + { + StringBuilder result = new (); + result.Append ("Array Size:"); + result.Append (this.ValueToString (Size)); + + result.Append (", Values:("); + bool first = true; + foreach (var element in IndexValues) { + if (!first) { + result.Append (","); + first = false; + } + + result.Append ("("); + result.Append (element.Key); + result.Append (",("); + bool firstValue = true; + foreach (var v in element.Value.Value) { + if (firstValue) { + result.Append (","); + firstValue = false; + } + + result.Append (v.ToString ()); + } + result.Append ("))"); + } + result.Append (')'); + + return result.ToString (); + } + } +}
\ No newline at end of file diff --git a/src/linker/Linker.Dataflow/FieldValue.cs b/src/linker/Linker.Dataflow/FieldValue.cs new file mode 100644 index 000000000..416315128 --- /dev/null +++ b/src/linker/Linker.Dataflow/FieldValue.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using ILLink.Shared.DataFlow; +using Mono.Linker; +using Mono.Linker.Dataflow; +using FieldDefinition = Mono.Cecil.FieldDefinition; +using TypeDefinition = Mono.Cecil.TypeDefinition; + + +namespace ILLink.Shared.TrimAnalysis +{ + + /// <summary> + /// A representation of a field. Typically a result of ldfld. + /// </summary> + sealed partial record FieldValue : IValueWithStaticType + { + public FieldValue (TypeDefinition? staticType, FieldDefinition fieldToLoad, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + { + StaticType = staticType; + Field = fieldToLoad; + DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; + } + + public readonly FieldDefinition Field; + + public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } + + public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () + => new string[] { Field.GetDisplayName () }; + + public TypeDefinition? StaticType { get; } + + public override SingleValue DeepCopy () => this; // This value is immutable + + public override string ToString () => this.ValueToString (Field, DynamicallyAccessedMemberTypes); + } +}
\ No newline at end of file diff --git a/src/linker/Linker.Dataflow/GenericParameterValue.cs b/src/linker/Linker.Dataflow/GenericParameterValue.cs new file mode 100644 index 000000000..7f6e104b1 --- /dev/null +++ b/src/linker/Linker.Dataflow/GenericParameterValue.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using ILLink.Shared.DataFlow; +using Mono.Linker.Dataflow; +using GenericParameter = Mono.Cecil.GenericParameter; + +namespace ILLink.Shared.TrimAnalysis +{ + /// <summary> + /// This is a System.Type value which represents generic parameter (basically result of typeof(T)) + /// Its actual type is unknown, but it can have annotations. + /// </summary> + partial record GenericParameterValue + { + public GenericParameterValue (GenericParameter genericParameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + { + GenericParameter = new (genericParameter); + DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; + } + + public partial bool HasDefaultConstructorConstraint () => GenericParameter.GenericParameter.HasDefaultConstructorConstraint; + + public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } + + public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () + => new string[] { GenericParameter.GenericParameter.Name, DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName (GenericParameter.GenericParameter) }; + + public override SingleValue DeepCopy () => this; // This value is immutable + + public override string ToString () => this.ValueToString (GenericParameter, DynamicallyAccessedMemberTypes); + } +}
\ No newline at end of file diff --git a/src/linker/Linker.Dataflow/MethodParameterValue.cs b/src/linker/Linker.Dataflow/MethodParameterValue.cs new file mode 100644 index 000000000..020857223 --- /dev/null +++ b/src/linker/Linker.Dataflow/MethodParameterValue.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using ILLink.Shared.DataFlow; +using Mono.Cecil; +using Mono.Linker.Dataflow; +using TypeDefinition = Mono.Cecil.TypeDefinition; + + +namespace ILLink.Shared.TrimAnalysis +{ + + /// <summary> + /// A value that came from a method parameter - such as the result of a ldarg. + /// </summary> + partial record MethodParameterValue : IValueWithStaticType + { + public MethodParameterValue (TypeDefinition? staticType, MethodDefinition method, int parameterIndex, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + { + StaticType = staticType; + Method = method; + ParameterIndex = parameterIndex; + DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; + } + + public readonly MethodDefinition Method; + + /// <summary> + /// This is the index of non-implicit parameter - so the index into MethodDefinition.Parameters array. + /// It's NOT the IL parameter index which could be offset by 1 if the method has an implicit this. + /// </summary> + public readonly int ParameterIndex; + + public ParameterDefinition ParameterDefinition => Method.Parameters[ParameterIndex]; + + public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } + + public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () + => new string[] { DiagnosticUtilities.GetParameterNameForErrorMessage (ParameterDefinition), DiagnosticUtilities.GetMethodSignatureDisplayName (Method) }; + + public TypeDefinition? StaticType { get; } + + public override SingleValue DeepCopy () => this; // This value is immutable + + public override string ToString () => this.ValueToString (Method, ParameterIndex, DynamicallyAccessedMemberTypes); + } +}
\ No newline at end of file diff --git a/src/linker/Linker.Dataflow/MethodReturnValue.cs b/src/linker/Linker.Dataflow/MethodReturnValue.cs new file mode 100644 index 000000000..10414a670 --- /dev/null +++ b/src/linker/Linker.Dataflow/MethodReturnValue.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using ILLink.Shared.DataFlow; +using Mono.Cecil; +using Mono.Linker.Dataflow; +using TypeDefinition = Mono.Cecil.TypeDefinition; + + +namespace ILLink.Shared.TrimAnalysis +{ + /// <summary> + /// Return value from a method + /// </summary> + partial record MethodReturnValue : IValueWithStaticType + { + public MethodReturnValue (TypeDefinition? staticType, MethodDefinition method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + { + StaticType = staticType; + Method = method; + DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; + } + + public readonly MethodDefinition Method; + + public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } + + public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () + => new string[] { DiagnosticUtilities.GetMethodSignatureDisplayName (Method) }; + + public TypeDefinition? StaticType { get; } + + public override SingleValue DeepCopy () => this; // This value is immutable + + public override string ToString () => this.ValueToString (Method, DynamicallyAccessedMemberTypes); + } +}
\ No newline at end of file diff --git a/src/linker/Linker.Dataflow/MethodThisParameterValue.cs b/src/linker/Linker.Dataflow/MethodThisParameterValue.cs new file mode 100644 index 000000000..e9ded179b --- /dev/null +++ b/src/linker/Linker.Dataflow/MethodThisParameterValue.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using ILLink.Shared.DataFlow; +using Mono.Cecil; +using Mono.Linker; +using Mono.Linker.Dataflow; +using TypeDefinition = Mono.Cecil.TypeDefinition; + + +namespace ILLink.Shared.TrimAnalysis +{ + + /// <summary> + /// A value that came from the implicit this parameter of a method + /// </summary> + partial record MethodThisParameterValue : IValueWithStaticType + { + public MethodThisParameterValue (MethodDefinition method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) + { + Method = method; + DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; + } + + public readonly MethodDefinition Method; + + public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } + + public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () + => new string[] { Method.GetDisplayName () }; + + public TypeDefinition? StaticType => Method.DeclaringType; + + public override SingleValue DeepCopy () => this; // This value is immutable + + public override string ToString () => this.ValueToString (Method, DynamicallyAccessedMemberTypes); + } +}
\ No newline at end of file diff --git a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs index 992e6f62b..aa58d484f 100644 --- a/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs @@ -14,9 +14,7 @@ using ILLink.Shared.TypeSystemProxy; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Linker.Steps; - using BindingFlags = System.Reflection.BindingFlags; - using MultiValue = ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>; namespace Mono.Linker.Dataflow diff --git a/src/linker/Linker.Dataflow/RuntimeMethodHandleValue.cs b/src/linker/Linker.Dataflow/RuntimeMethodHandleValue.cs new file mode 100644 index 000000000..7197b5491 --- /dev/null +++ b/src/linker/Linker.Dataflow/RuntimeMethodHandleValue.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using ILLink.Shared.DataFlow; +using Mono.Cecil; + + +namespace ILLink.Shared.TrimAnalysis +{ + + /// <summary> + /// This is the System.RuntimeMethodHandle equivalent to a <see cref="SystemReflectionMethodBaseValue"/> node. + /// </summary> + partial record RuntimeMethodHandleValue + { + public RuntimeMethodHandleValue (MethodDefinition methodRepresented) => MethodRepresented = methodRepresented; + + public readonly MethodDefinition MethodRepresented; + + public override SingleValue DeepCopy () => this; // This value is immutable + + public override string ToString () => this.ValueToString (MethodRepresented); + } +}
\ No newline at end of file diff --git a/src/linker/Linker.Dataflow/SingleValueExtensions.cs b/src/linker/Linker.Dataflow/SingleValueExtensions.cs new file mode 100644 index 000000000..b136c9fef --- /dev/null +++ b/src/linker/Linker.Dataflow/SingleValueExtensions.cs @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using ILLink.Shared.DataFlow; +using Mono.Linker.Dataflow; + +namespace ILLink.Shared.TrimAnalysis +{ + // These are extension methods because we want to allow the use of them on null 'this' pointers. + internal static class SingleValueExtensions + { + /// <summary> + /// Returns true if a ValueNode graph contains a cycle + /// </summary> + /// <param name="node">Node to evaluate</param> + /// <param name="seenNodes">Set of nodes previously seen on the current arc. Callers may pass a non-empty set + /// to test whether adding that set to this node would create a cycle. Contents will be modified by the walk + /// and should not be used by the caller after returning</param> + /// <param name="allNodesSeen">Optional. The set of all nodes encountered during a walk after DetectCycle returns</param> + /// <returns></returns> + public static bool DetectCycle (this SingleValue node, HashSet<SingleValue> seenNodes, HashSet<SingleValue>? allNodesSeen) + { + if (node == null) + return false; + + if (seenNodes.Contains (node)) + return true; + + seenNodes.Add (node); + + if (allNodesSeen != null) { + allNodesSeen.Add (node); + } + + bool foundCycle = false; + switch (node) { + // + // Leaf nodes + // + case UnknownValue: + case NullValue: + case SystemTypeValue: + case RuntimeTypeHandleValue: + case KnownStringValue: + case ConstIntValue: + case MethodParameterValue: + case MethodThisParameterValue: + case MethodReturnValue: + case GenericParameterValue: + case RuntimeTypeHandleForGenericParameterValue: + case SystemReflectionMethodBaseValue: + case RuntimeMethodHandleValue: + case FieldValue: + break; + + // + // Nodes with children + // + case ArrayValue: + ArrayValue av = (ArrayValue) node; + foundCycle = av.Size.DetectCycle (seenNodes, allNodesSeen); + foreach (ValueBasicBlockPair pair in av.IndexValues.Values) { + foreach (var v in pair.Value) { + foundCycle |= v.DetectCycle (seenNodes, allNodesSeen); + } + } + break; + + case RuntimeTypeHandleForNullableValueWithDynamicallyAccessedMembers value: + foundCycle = value.UnderlyingTypeValue.DetectCycle (seenNodes, allNodesSeen); + break; + + case NullableValueWithDynamicallyAccessedMembers value: + foundCycle = value.UnderlyingTypeValue.DetectCycle (seenNodes, allNodesSeen); + break; + + default: + throw new Exception (String.Format ("Unknown node type: {0}", node.GetType ().Name)); + } + seenNodes.Remove (node); + + return foundCycle; + } + } +}
\ No newline at end of file diff --git a/src/linker/Linker.Dataflow/ValueNode.cs b/src/linker/Linker.Dataflow/ValueNode.cs index 1cdac92b3..5a0df8f34 100644 --- a/src/linker/Linker.Dataflow/ValueNode.cs +++ b/src/linker/Linker.Dataflow/ValueNode.cs @@ -3,354 +3,10 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Text; -using ILLink.Shared.DataFlow; -using Mono.Cecil; -using Mono.Linker; -using Mono.Linker.Dataflow; -using FieldDefinition = Mono.Cecil.FieldDefinition; -using GenericParameter = Mono.Cecil.GenericParameter; using MultiValue = ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>; -using TypeDefinition = Mono.Cecil.TypeDefinition; -namespace ILLink.Shared.TrimAnalysis +namespace Mono.Linker.Dataflow { - // These are extension methods because we want to allow the use of them on null 'this' pointers. - internal static class SingleValueExtensions - { - /// <summary> - /// Returns true if a ValueNode graph contains a cycle - /// </summary> - /// <param name="node">Node to evaluate</param> - /// <param name="seenNodes">Set of nodes previously seen on the current arc. Callers may pass a non-empty set - /// to test whether adding that set to this node would create a cycle. Contents will be modified by the walk - /// and should not be used by the caller after returning</param> - /// <param name="allNodesSeen">Optional. The set of all nodes encountered during a walk after DetectCycle returns</param> - /// <returns></returns> - public static bool DetectCycle (this SingleValue node, HashSet<SingleValue> seenNodes, HashSet<SingleValue>? allNodesSeen) - { - if (node == null) - return false; - - if (seenNodes.Contains (node)) - return true; - - seenNodes.Add (node); - - if (allNodesSeen != null) { - allNodesSeen.Add (node); - } - - bool foundCycle = false; - switch (node) { - // - // Leaf nodes - // - case UnknownValue: - case NullValue: - case SystemTypeValue: - case RuntimeTypeHandleValue: - case KnownStringValue: - case ConstIntValue: - case MethodParameterValue: - case MethodThisParameterValue: - case MethodReturnValue: - case GenericParameterValue: - case RuntimeTypeHandleForGenericParameterValue: - case SystemReflectionMethodBaseValue: - case RuntimeMethodHandleValue: - case FieldValue: - break; - - // - // Nodes with children - // - case ArrayValue: - ArrayValue av = (ArrayValue) node; - foundCycle = av.Size.DetectCycle (seenNodes, allNodesSeen); - foreach (ValueBasicBlockPair pair in av.IndexValues.Values) { - foreach (var v in pair.Value) { - foundCycle |= v.DetectCycle (seenNodes, allNodesSeen); - } - } - break; - - case RuntimeTypeHandleForNullableValueWithDynamicallyAccessedMembers value: - foundCycle = value.UnderlyingTypeValue.DetectCycle (seenNodes, allNodesSeen); - break; - - case NullableValueWithDynamicallyAccessedMembers value: - foundCycle = value.UnderlyingTypeValue.DetectCycle (seenNodes, allNodesSeen); - break; - - default: - throw new Exception (String.Format ("Unknown node type: {0}", node.GetType ().Name)); - } - seenNodes.Remove (node); - - return foundCycle; - } - } - - /// <summary> - /// This is a System.Type value which represents generic parameter (basically result of typeof(T)) - /// Its actual type is unknown, but it can have annotations. - /// </summary> - partial record GenericParameterValue - { - public GenericParameterValue (GenericParameter genericParameter, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) - { - GenericParameter = new (genericParameter); - DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; - } - - public partial bool HasDefaultConstructorConstraint () => GenericParameter.GenericParameter.HasDefaultConstructorConstraint; - - public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } - - public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () - => new string[] { GenericParameter.GenericParameter.Name, DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName (GenericParameter.GenericParameter) }; - - public override SingleValue DeepCopy () => this; // This value is immutable - - public override string ToString () => this.ValueToString (GenericParameter, DynamicallyAccessedMemberTypes); - } - - /// <summary> - /// This is the System.RuntimeMethodHandle equivalent to a <see cref="SystemReflectionMethodBaseValue"/> node. - /// </summary> - partial record RuntimeMethodHandleValue - { - public RuntimeMethodHandleValue (MethodDefinition methodRepresented) => MethodRepresented = methodRepresented; - - public readonly MethodDefinition MethodRepresented; - - public override SingleValue DeepCopy () => this; // This value is immutable - - public override string ToString () => this.ValueToString (MethodRepresented); - } - - /// <summary> - /// A value that came from a method parameter - such as the result of a ldarg. - /// </summary> - partial record MethodParameterValue : IValueWithStaticType - { - public MethodParameterValue (TypeDefinition? staticType, MethodDefinition method, int parameterIndex, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) - { - StaticType = staticType; - Method = method; - ParameterIndex = parameterIndex; - DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; - } - - public readonly MethodDefinition Method; - - /// <summary> - /// This is the index of non-implicit parameter - so the index into MethodDefinition.Parameters array. - /// It's NOT the IL parameter index which could be offset by 1 if the method has an implicit this. - /// </summary> - public readonly int ParameterIndex; - - public ParameterDefinition ParameterDefinition => Method.Parameters[ParameterIndex]; - - public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } - - public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () - => new string[] { DiagnosticUtilities.GetParameterNameForErrorMessage (ParameterDefinition), DiagnosticUtilities.GetMethodSignatureDisplayName (Method) }; - - public TypeDefinition? StaticType { get; } - - public override SingleValue DeepCopy () => this; // This value is immutable - - public override string ToString () => this.ValueToString (Method, ParameterIndex, DynamicallyAccessedMemberTypes); - } - - /// <summary> - /// A value that came from the implicit this parameter of a method - /// </summary> - partial record MethodThisParameterValue : IValueWithStaticType - { - public MethodThisParameterValue (MethodDefinition method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) - { - Method = method; - DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; - } - - public readonly MethodDefinition Method; - - public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } - - public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () - => new string[] { Method.GetDisplayName () }; - - public TypeDefinition? StaticType => Method.DeclaringType; - - public override SingleValue DeepCopy () => this; // This value is immutable - - public override string ToString () => this.ValueToString (Method, DynamicallyAccessedMemberTypes); - } - - /// <summary> - /// Return value from a method - /// </summary> - partial record MethodReturnValue : IValueWithStaticType - { - public MethodReturnValue (TypeDefinition? staticType, MethodDefinition method, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) - { - StaticType = staticType; - Method = method; - DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; - } - - public readonly MethodDefinition Method; - - public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } - - public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () - => new string[] { DiagnosticUtilities.GetMethodSignatureDisplayName (Method) }; - - public TypeDefinition? StaticType { get; } - - public override SingleValue DeepCopy () => this; // This value is immutable - - public override string ToString () => this.ValueToString (Method, DynamicallyAccessedMemberTypes); - } - - /// <summary> - /// A representation of a field. Typically a result of ldfld. - /// </summary> - partial record FieldValue : IValueWithStaticType - { - public FieldValue (TypeDefinition? staticType, FieldDefinition fieldToLoad, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes) - { - StaticType = staticType; - Field = fieldToLoad; - DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes; - } - - public readonly FieldDefinition Field; - - public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; } - - public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch () - => new string[] { Field.GetDisplayName () }; - - public TypeDefinition? StaticType { get; } - - public override SingleValue DeepCopy () => this; // This value is immutable - - public override string ToString () => this.ValueToString (Field, DynamicallyAccessedMemberTypes); - } - - partial record ArrayValue - { - public static MultiValue Create (MultiValue size, TypeReference elementType) - { - MultiValue result = MultiValueLattice.Top; - foreach (var sizeValue in size) { - result = MultiValueLattice.Meet (result, new MultiValue (new ArrayValue (sizeValue, elementType))); - } - - return result; - } - - public static MultiValue Create (int size, TypeReference elementType) - { - return new MultiValue (new ArrayValue (new ConstIntValue (size), elementType)); - } - - /// <summary> - /// Constructs an array value of the given size - /// </summary> - ArrayValue (SingleValue size, TypeReference elementType) - { - Size = size; - ElementType = elementType; - IndexValues = new Dictionary<int, ValueBasicBlockPair> (); - } - - public TypeReference ElementType { get; } - public Dictionary<int, ValueBasicBlockPair> IndexValues { get; } - - public partial bool TryGetValueByIndex (int index, out MultiValue value) - { - if (IndexValues.TryGetValue (index, out var valuePair)) { - value = valuePair.Value; - return true; - } - - value = default; - return false; - } - - public override int GetHashCode () - { - return HashCode.Combine (GetType ().GetHashCode (), Size); - } - - public bool Equals (ArrayValue? otherArr) - { - if (otherArr == null) - return false; - - bool equals = Size.Equals (otherArr.Size); - equals &= IndexValues.Count == otherArr.IndexValues.Count; - if (!equals) - return false; - - // If both sets T and O are the same size and "T intersect O" is empty, then T == O. - HashSet<KeyValuePair<int, ValueBasicBlockPair>> thisValueSet = new (IndexValues); - HashSet<KeyValuePair<int, ValueBasicBlockPair>> otherValueSet = new (otherArr.IndexValues); - thisValueSet.ExceptWith (otherValueSet); - return thisValueSet.Count == 0; - } - - public override SingleValue DeepCopy () - { - var newValue = new ArrayValue (Size.DeepCopy (), ElementType); - foreach (var kvp in IndexValues) { - newValue.IndexValues.Add (kvp.Key, new ValueBasicBlockPair (kvp.Value.Value.Clone (), kvp.Value.BasicBlockIndex)); - } - - return newValue; - } - - public override string ToString () - { - StringBuilder result = new (); - result.Append ("Array Size:"); - result.Append (this.ValueToString (Size)); - - result.Append (", Values:("); - bool first = true; - foreach (var element in IndexValues) { - if (!first) { - result.Append (","); - first = false; - } - - result.Append ("("); - result.Append (element.Key); - result.Append (",("); - bool firstValue = true; - foreach (var v in element.Value.Value) { - if (firstValue) { - result.Append (","); - firstValue = false; - } - - result.Append (v.ToString ()); - } - result.Append ("))"); - } - result.Append (')'); - - return result.ToString (); - } - } - - #region ValueNode Collections public class ValueNodeList : List<MultiValue> { public ValueNodeList () @@ -390,8 +46,6 @@ namespace ILLink.Shared.TrimAnalysis return true; } } - #endregion - public struct ValueBasicBlockPair { |