Skip to content
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
121 changes: 121 additions & 0 deletions src/linker/Linker.Dataflow/ArrayValue.cs
Original file line number Diff line number Diff line change
@@ -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 ();
}
}
}
41 changes: 41 additions & 0 deletions src/linker/Linker.Dataflow/FieldValue.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
35 changes: 35 additions & 0 deletions src/linker/Linker.Dataflow/GenericParameterValue.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
49 changes: 49 additions & 0 deletions src/linker/Linker.Dataflow/MethodParameterValue.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
39 changes: 39 additions & 0 deletions src/linker/Linker.Dataflow/MethodReturnValue.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
40 changes: 40 additions & 0 deletions src/linker/Linker.Dataflow/MethodThisParameterValue.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
2 changes: 0 additions & 2 deletions src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
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
Expand Down
24 changes: 24 additions & 0 deletions src/linker/Linker.Dataflow/RuntimeMethodHandleValue.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading