Skip to content

Commit 174c23e

Browse files
authored
Update shared code from linker (#70204)
This brings in relatively recent version of the shared code from the dotnet/linker repo. Main changes: * ValueNode -> SingleValue - and the partial classes implementation for the values * Adapt MethodBodyScanner to the SingleValue/MultiValue * Includes some fixes around array handling and unknown values * Removal of ReflectionPatternContext * Partially replaced by DiagnosticContext * Partially removed (the checks that everything reports something are nto needed anymore) * Use HandleCallAction and RequireDynamicallyAccessedMembersAction - this replaces most of the functionality in ReflectionMethodBodyScanner. Formatting: The files which are shared exactly from linker are kept as is (so tabs and so on) The files which are AOT specific should follow the formatting of AOT projects Testing: Passes smoke tests and some additional validation done via linker tests which is not part of this change Note: This is not up-to-date with linker but it's getting us much closer. Known "TODOs": * CompilerGeneratedState - linker has a much newer and much more capable version. Port of that will come later (as it was in heavy development while I was doing this port, and it's not strictly necessary for current functionality) * Type hierarchy marking - this needs work on the linker side as it's not yet part of the shared codebase * Correctly handle RUC/RDC for all "reflection accesses" to methods - some of the change improve on this, but it's nowhere near where it needs to be. Future work item.
1 parent 7532658 commit 174c23e

File tree

110 files changed

+7394
-8585
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+7394
-8585
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Linker port settings:
2+
# A newline ending every file
3+
# Use tabs as indentation
4+
[ILLink.Shared/**.cs]
5+
indent_style = tab
6+
indent_size = 4
7+
csharp_new_line_before_open_brace = types,methods
8+
csharp_new_line_before_else = false
9+
csharp_new_line_before_catch = false
10+
csharp_new_line_before_finally = false
11+
csharp_new_line_before_members_in_object_initializers = true
12+
csharp_new_line_before_members_in_anonymous_types = true
13+
csharp_new_line_between_query_expression_clauses = true
14+
15+
csharp_space_after_keywords_in_control_flow_statements = true
16+
csharp_space_between_method_declaration_name_and_open_parenthesis = true
17+
csharp_space_between_method_call_name_and_opening_parenthesis = true
18+
csharp_space_before_open_square_brackets = false
19+
csharp_space_after_cast = true
20+
21+
csharp_indent_switch_labels = false
22+
23+
# Sort using and Import directives with System.* appearing first
24+
dotnet_sort_system_directives_first = true
25+
26+
# Prefer property-like constructs to have an expression-body
27+
csharp_style_expression_bodied_properties = true:none
28+
csharp_style_expression_bodied_indexers = true:none
29+
csharp_style_expression_bodied_accessors = true:none

src/coreclr/tools/aot/ILCompiler.Compiler.Tests/DependencyGraphTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public void TestDependencyGraphInvariants(EcmaMethod method)
7171
UsageBasedMetadataManager metadataManager = new UsageBasedMetadataManager(compilationGroup, context,
7272
new FullyBlockedMetadataBlockingPolicy(), new FullyBlockedManifestResourceBlockingPolicy(),
7373
null, new NoStackTraceEmissionPolicy(), new NoDynamicInvokeThunkGenerationPolicy(),
74-
new Dataflow.FlowAnnotations(Logger.Null, ilProvider), UsageBasedMetadataGenerationOptions.None,
74+
new ILLink.Shared.TrimAnalysis.FlowAnnotations(Logger.Null, ilProvider), UsageBasedMetadataGenerationOptions.None,
7575
Logger.Null, Array.Empty<KeyValuePair<string, bool>>(), Array.Empty<string>(), Array.Empty<string>());
7676

7777
CompilationBuilder builder = new RyuJitCompilationBuilder(context, compilationGroup)
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Text;
7+
using ILCompiler.Dataflow;
8+
using ILLink.Shared.DataFlow;
9+
using Internal.TypeSystem;
10+
11+
using MultiValue = ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>;
12+
13+
#nullable enable
14+
15+
namespace ILLink.Shared.TrimAnalysis
16+
{
17+
partial record ArrayValue
18+
{
19+
public static MultiValue Create(MultiValue size, TypeDesc elementType)
20+
{
21+
MultiValue result = MultiValueLattice.Top;
22+
foreach (var sizeValue in size)
23+
{
24+
result = MultiValueLattice.Meet(result, new MultiValue(new ArrayValue(sizeValue, elementType)));
25+
}
26+
27+
return result;
28+
}
29+
30+
public static MultiValue Create(int size, TypeDesc elementType)
31+
{
32+
return new MultiValue(new ArrayValue(new ConstIntValue(size), elementType));
33+
}
34+
35+
/// <summary>
36+
/// Constructs an array value of the given size
37+
/// </summary>
38+
ArrayValue(SingleValue size, TypeDesc elementType)
39+
{
40+
Size = size;
41+
ElementType = elementType;
42+
IndexValues = new Dictionary<int, ValueBasicBlockPair>();
43+
}
44+
45+
public TypeDesc ElementType { get; }
46+
public Dictionary<int, ValueBasicBlockPair> IndexValues { get; }
47+
48+
public partial bool TryGetValueByIndex(int index, out MultiValue value)
49+
{
50+
if (IndexValues.TryGetValue(index, out var valuePair))
51+
{
52+
value = valuePair.Value;
53+
return true;
54+
}
55+
56+
value = default;
57+
return false;
58+
}
59+
60+
public override int GetHashCode()
61+
{
62+
return HashCode.Combine(GetType().GetHashCode(), Size);
63+
}
64+
65+
public bool Equals(ArrayValue? otherArr)
66+
{
67+
if (otherArr == null)
68+
return false;
69+
70+
bool equals = Size.Equals(otherArr.Size);
71+
equals &= IndexValues.Count == otherArr.IndexValues.Count;
72+
if (!equals)
73+
return false;
74+
75+
// If both sets T and O are the same size and "T intersect O" is empty, then T == O.
76+
HashSet<KeyValuePair<int, ValueBasicBlockPair>> thisValueSet = new(IndexValues);
77+
HashSet<KeyValuePair<int, ValueBasicBlockPair>> otherValueSet = new(otherArr.IndexValues);
78+
thisValueSet.ExceptWith(otherValueSet);
79+
return thisValueSet.Count == 0;
80+
}
81+
82+
public override SingleValue DeepCopy()
83+
{
84+
var newValue = new ArrayValue(Size.DeepCopy(), ElementType);
85+
foreach (var kvp in IndexValues)
86+
{
87+
newValue.IndexValues.Add(kvp.Key, new ValueBasicBlockPair(kvp.Value.Value.Clone(), kvp.Value.BasicBlockIndex));
88+
}
89+
90+
return newValue;
91+
}
92+
93+
public override string ToString()
94+
{
95+
StringBuilder result = new();
96+
result.Append("Array Size:");
97+
result.Append(this.ValueToString(Size));
98+
99+
result.Append(", Values:(");
100+
bool first = true;
101+
foreach (var element in IndexValues)
102+
{
103+
if (!first)
104+
{
105+
result.Append(",");
106+
first = false;
107+
}
108+
109+
result.Append("(");
110+
result.Append(element.Key);
111+
result.Append(",(");
112+
bool firstValue = true;
113+
foreach (var v in element.Value.Value)
114+
{
115+
if (firstValue)
116+
{
117+
result.Append(",");
118+
firstValue = false;
119+
}
120+
121+
result.Append(v.ToString());
122+
}
123+
result.Append("))");
124+
}
125+
result.Append(')');
126+
127+
return result.ToString();
128+
}
129+
}
130+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using ILCompiler;
5+
using ILCompiler.Logging;
6+
7+
#nullable enable
8+
9+
namespace ILLink.Shared.TrimAnalysis
10+
{
11+
readonly partial struct DiagnosticContext
12+
{
13+
public readonly MessageOrigin Origin;
14+
public readonly bool DiagnosticsEnabled;
15+
readonly Logger _logger;
16+
17+
public DiagnosticContext(in MessageOrigin origin, bool diagnosticsEnabled, Logger logger)
18+
=> (Origin, DiagnosticsEnabled, _logger) = (origin, diagnosticsEnabled, logger);
19+
20+
public partial void AddDiagnostic(DiagnosticId id, params string[] args)
21+
{
22+
if (DiagnosticsEnabled)
23+
_logger.LogWarning(Origin, id, args);
24+
}
25+
}
26+
}

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DiagnosticUtilities.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,12 @@ internal static bool IsInRequiresScope(this MethodDesc method, string requiresAt
131131
method.IsInRequiresScope(requiresAttribute, true);
132132

133133
/// <summary>
134-
/// True if member of a call is considered to be annotated with the Requires... attribute.
135-
/// Doesn't check the associated symbol for overrides and virtual methods because we should warn on mismatched between the property AND the accessors
136-
/// </summary>
137-
/// <param name="method">
138-
/// MethodDesc that is either an overriding member or an overriden/virtual member
139-
/// </param>
134+
/// True if member of a call is considered to be annotated with the Requires... attribute.
135+
/// Doesn't check the associated symbol for overrides and virtual methods because we should warn on mismatched between the property AND the accessors
136+
/// </summary>
137+
/// <param name="method">
138+
/// MethodDesc that is either an overriding member or an overriden/virtual member
139+
/// </param>
140140
internal static bool IsOverrideInRequiresScope(this MethodDesc method, string requiresAttribute) =>
141141
method.IsInRequiresScope(requiresAttribute, false);
142142

@@ -185,10 +185,10 @@ internal static bool DoesPropertyRequire(this PropertyPseudoDesc property, strin
185185
TryGetRequiresAttribute(property, requiresAttribute, out attribute);
186186

187187
/// <summary>
188-
/// Determines if member requires (and thus any usage of such method should be warned about).
189-
/// </summary>
190-
/// <remarks>Unlike <see cref="IsInRequiresScope(MethodDesc, string)"/> only static methods
191-
/// and .ctors are reported as requires when the declaring type has Requires on it.</remarks>
188+
/// Determines if member requires (and thus any usage of such method should be warned about).
189+
/// </summary>
190+
/// <remarks>Unlike <see cref="IsInRequiresScope(MethodDesc, string)"/> only static methods
191+
/// and .ctors are reported as requires when the declaring type has Requires on it.</remarks>
192192
internal static bool DoesMemberRequire(this TypeSystemEntity member, string requiresAttribute, [NotNullWhen(returnValue: true)] out CustomAttributeValue<TypeDesc>? attribute)
193193
{
194194
attribute = null;

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DynamicallyAccessedMembersBinder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ public static IEnumerable<EventPseudoDesc> GetEventsOnTypeHierarchy(this TypeDes
352352
type = type.BaseType;
353353
onBaseType = true;
354354
}
355-
355+
356356
while (type != null)
357357
{
358358
if (type.GetTypeDefinition() is not EcmaType ecmaType)

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/EcmaExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static bool IsPublic(this MethodDesc method)
2222
public static bool IsPublic(this FieldDesc field)
2323
{
2424
return field.GetTypicalFieldDefinition() is EcmaField ecmaField
25-
&& (ecmaField.Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public;
25+
&& (ecmaField.Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public;
2626
}
2727

2828
public static bool IsPrivate(this MethodDesc method)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Collections.Generic;
5+
using System.Diagnostics.CodeAnalysis;
6+
using ILCompiler;
7+
using ILCompiler.Dataflow;
8+
using ILLink.Shared.DataFlow;
9+
using Internal.TypeSystem;
10+
11+
#nullable enable
12+
13+
namespace ILLink.Shared.TrimAnalysis
14+
{
15+
16+
/// <summary>
17+
/// A representation of a field. Typically a result of ldfld.
18+
/// </summary>
19+
sealed partial record FieldValue : IValueWithStaticType
20+
{
21+
public FieldValue(FieldDesc field, DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes)
22+
{
23+
StaticType = field.FieldType;
24+
Field = field;
25+
DynamicallyAccessedMemberTypes = dynamicallyAccessedMemberTypes;
26+
}
27+
28+
public readonly FieldDesc Field;
29+
30+
public override DynamicallyAccessedMemberTypes DynamicallyAccessedMemberTypes { get; }
31+
32+
public override IEnumerable<string> GetDiagnosticArgumentsForAnnotationMismatch()
33+
=> new string[] { Field.GetDisplayName() };
34+
35+
public TypeDesc? StaticType { get; }
36+
37+
public override SingleValue DeepCopy() => this; // This value is immutable
38+
39+
public override string ToString() => this.ValueToString(Field, DynamicallyAccessedMemberTypes);
40+
}
41+
}

0 commit comments

Comments
 (0)