Skip to content

Commit fbb67a6

Browse files
Begin transition to dependency framework in illink (#101277)
Recreates the Process() loop in MarkStep with node that depends on a new copy of itself when the loop needs to be rerun. Within the loop, the new Method and Type nodes are added to the dependency framework analyzer as roots when MarkMethod and MarkType are called, which leads to the OnMarked methods to be called, which forwards to the ProcessType/Method method in MarkStep. The dependency analyzer doesn't do anything interesting yet. In a follow-up I'll move dependencies from the MarkX and ProcessX methods to the DependencyNode types. Makes ILCompiler.DependencyAnalysisFramework output path independent of target architecture. Removes TargetArchitecture and TargetOS from ILLink.Tasks project references. --------- Co-authored-by: vitek-karas <10670590+vitek-karas@users.noreply.github.com>
1 parent 1eb888b commit fbb67a6

12 files changed

+302
-48
lines changed

eng/liveILLink.targets

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@
3030

3131
<ItemGroup Condition="'$(_RequiresLiveILLink)' == 'true'">
3232
<!-- The assembly shouldn't be referenced, nor promoted to a package dependency, nor copied to the output directory. -->
33+
<!-- ILLink.Tasks is architecture independent, so TargetArch and TargetOS should not be specified -->
3334
<ProjectReference Include="$(_ILLinkTasksSourceDir)ILLink.Tasks.csproj"
3435
ReferenceOutputAssembly="false"
3536
PrivateAssets="all"
3637
Private="false"
37-
SetConfiguration="Configuration=$(ToolsConfiguration)">
38+
SetConfiguration="Configuration=$(ToolsConfiguration)"
39+
GlobalPropertiesToRemove="TargetArchitecture;TargetOS" >
3840
<!-- Keep TFMs in sync with ILLink.Tasks.csproj -->
3941
<SetTargetFramework Condition="'$(MSBuildRuntimeType)' == 'Core'">TargetFramework=$(NetCoreAppToolCurrent)</SetTargetFramework>
4042
<SetTargetFramework Condition="'$(MSBuildRuntimeType)' != 'Core'">TargetFramework=$(NetFrameworkToolCurrent)</SetTargetFramework>

src/coreclr/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<InferPlatformFromTargetArchitecture>true</InferPlatformFromTargetArchitecture>
3+
<InferPlatformFromTargetArchitecture Condition="'$(InferPlatformFromTargetArchitecture)' == ''">true</InferPlatformFromTargetArchitecture>
44

55
<!-- TODO: Clean-up casing and remove __BuildType to remove this block. -->
66
<Configuration Condition="'$(Configuration)' == ''">$(__BuildType)</Configuration>

src/coreclr/tools/aot/ILCompiler.DependencyAnalysisFramework/ILCompiler.DependencyAnalysisFramework.csproj

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project>
2+
<PropertyGroup>
3+
<PlatformName>AnyCPU</PlatformName>
4+
</PropertyGroup>
5+
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
26
<PropertyGroup>
37
<OutputType>Library</OutputType>
48
<RootNamespace>ILCompiler.DependencyAnalysisFramework</RootNamespace>
@@ -8,6 +12,10 @@
812
<Platforms>x64;x86</Platforms>
913
<PlatformTarget>AnyCPU</PlatformTarget>
1014
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
15+
<!-- Workaround for circular dependency (this => trim analyzers in illink.Tasks => Mono.Linker => this)-->
16+
<_RequiresLiveILLink>false</_RequiresLiveILLink>
17+
<!-- Mono.Linker requires the assembly to be signed -->
18+
<SignAssembly>true</SignAssembly>
1119

1220
<!-- We're binplacing these into an existing publish layout so that F5 build in VS updates
1321
the same bits tests expect to see in artifacts/crossgen2. That way we never need to wonder which
@@ -50,4 +58,5 @@
5058
<Link>Sorting\MergeSortCore.cs</Link>
5159
</Compile>
5260
</ItemGroup>
61+
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
5362
</Project>

src/tools/illink/src/linker/Linker.Steps/MarkScopeStack.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,6 @@ internal LocalScope PushLocalScope (in Scope scope)
8888
return new LocalScope (scope, this);
8989
}
9090

91-
internal ParentScope PopToParentScope ()
92-
{
93-
return new ParentScope (this);
94-
}
95-
9691
public IDisposable PushScope (in MessageOrigin origin)
9792
{
9893
return new LocalScope (origin, this);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using ILCompiler.DependencyAnalysisFramework;
7+
using Mono.Cecil;
8+
9+
namespace Mono.Linker.Steps
10+
{
11+
public partial class MarkStep
12+
{
13+
internal sealed class MethodDefinitionNode : DependencyNodeCore<NodeFactory>
14+
{
15+
readonly MethodDefinition method;
16+
readonly DependencyInfo reason;
17+
18+
public MethodDefinitionNode (MethodDefinition method, DependencyInfo reason)
19+
{
20+
this.method = method;
21+
this.reason = reason;
22+
}
23+
24+
public override bool InterestingForDynamicDependencyAnalysis => false;
25+
26+
public override bool HasDynamicDependencies => false;
27+
28+
public override bool HasConditionalStaticDependencies => false;
29+
30+
public override bool StaticDependenciesAreComputed => true;
31+
32+
public override IEnumerable<DependencyListEntry>? GetStaticDependencies (NodeFactory context)
33+
{
34+
context.MarkStep.ProcessMethod (method, reason);
35+
return null;
36+
}
37+
38+
public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (NodeFactory context) => null;
39+
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
40+
protected override string GetName (NodeFactory context) => method.GetDisplayName();
41+
}
42+
}
43+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Collections.Concurrent;
6+
using System.Collections.Generic;
7+
using Mono.Cecil;
8+
9+
namespace Mono.Linker.Steps
10+
{
11+
public partial class MarkStep
12+
{
13+
internal sealed class NodeFactory (MarkStep markStep)
14+
{
15+
public MarkStep MarkStep { get; } = markStep;
16+
readonly NodeCache<TypeDefinition, TypeDefinitionNode> _typeNodes = new (static t => new TypeDefinitionNode(t));
17+
readonly NodeCache<MethodDefinition, MethodDefinitionNode> _methodNodes = new (static _ => throw new InvalidOperationException ("Creation of node requires more than the key."));
18+
readonly NodeCache<TypeDefinition, TypeIsRelevantToVariantCastingNode> _typeIsRelevantToVariantCastingNodes = new (static (t) => new TypeIsRelevantToVariantCastingNode (t));
19+
20+
internal TypeDefinitionNode GetTypeNode (TypeDefinition definition)
21+
{
22+
return _typeNodes.GetOrAdd (definition);
23+
}
24+
25+
internal MethodDefinitionNode GetMethodDefinitionNode (MethodDefinition method, DependencyInfo reason)
26+
{
27+
return _methodNodes.GetOrAdd (method, (k) => new MethodDefinitionNode (k, reason));
28+
}
29+
30+
internal TypeIsRelevantToVariantCastingNode GetTypeIsRelevantToVariantCastingNode (TypeDefinition type)
31+
{
32+
return _typeIsRelevantToVariantCastingNodes.GetOrAdd (type);
33+
}
34+
35+
struct NodeCache<TKey, TValue> where TKey : notnull
36+
{
37+
// Change to concurrent dictionary if/when multithreaded marking is enabled
38+
readonly Dictionary<TKey, TValue> _cache;
39+
readonly Func<TKey, TValue> _creator;
40+
41+
public NodeCache (Func<TKey, TValue> creator, IEqualityComparer<TKey> comparer)
42+
{
43+
_creator = creator;
44+
_cache = new (comparer);
45+
}
46+
47+
public NodeCache (Func<TKey, TValue> creator)
48+
{
49+
_creator = creator;
50+
_cache = new ();
51+
}
52+
53+
public TValue GetOrAdd (TKey key)
54+
{
55+
return _cache.GetOrAdd (key, _creator);
56+
}
57+
58+
public TValue GetOrAdd (TKey key, Func<TKey, TValue> creator)
59+
{
60+
return _cache.GetOrAdd (key, creator);
61+
}
62+
}
63+
}
64+
}
65+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using ILCompiler.DependencyAnalysisFramework;
7+
8+
namespace Mono.Linker.Steps
9+
{
10+
public partial class MarkStep
11+
{
12+
sealed class ProcessCallbackNode : DependencyNodeCore<NodeFactory>
13+
{
14+
Func<bool> _processAction;
15+
DependencyList? _dependencies;
16+
17+
public ProcessCallbackNode (Func<bool> action) => _processAction = action;
18+
19+
public void Process ()
20+
{
21+
_dependencies = new DependencyList ();
22+
if (_processAction ()) {
23+
_dependencies.Add (new ProcessCallbackNode (_processAction), "Some processing was done, continuation required");
24+
}
25+
}
26+
27+
public override bool InterestingForDynamicDependencyAnalysis => false;
28+
29+
public override bool HasDynamicDependencies => false;
30+
31+
public override bool HasConditionalStaticDependencies => false;
32+
33+
public override bool StaticDependenciesAreComputed => _dependencies != null;
34+
35+
public override IEnumerable<DependencyListEntry>? GetStaticDependencies (NodeFactory context) => _dependencies;
36+
37+
public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (NodeFactory context) => null;
38+
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
39+
protected override string GetName (NodeFactory context) => "Process";
40+
}
41+
}
42+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Collections.Generic;
5+
using ILCompiler.DependencyAnalysisFramework;
6+
using Mono.Cecil;
7+
8+
namespace Mono.Linker.Steps
9+
{
10+
public partial class MarkStep
11+
{
12+
internal sealed class TypeDefinitionNode : DependencyNodeCore<NodeFactory>
13+
{
14+
readonly TypeDefinition type;
15+
16+
public TypeDefinitionNode (TypeDefinition type)
17+
{
18+
this.type = type;
19+
}
20+
21+
public override bool InterestingForDynamicDependencyAnalysis => false;
22+
23+
public override bool HasDynamicDependencies => false;
24+
25+
public override bool HasConditionalStaticDependencies => false;
26+
27+
public override bool StaticDependenciesAreComputed => true;
28+
29+
public override IEnumerable<DependencyListEntry>? GetStaticDependencies (NodeFactory context)
30+
{
31+
context.MarkStep.ProcessType (type);
32+
return null;
33+
}
34+
35+
public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (NodeFactory context) => null;
36+
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
37+
protected override string GetName (NodeFactory context) => type.GetDisplayName();
38+
}
39+
}
40+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Collections.Generic;
5+
using ILCompiler.DependencyAnalysisFramework;
6+
using Mono.Cecil;
7+
8+
namespace Mono.Linker.Steps
9+
{
10+
public partial class MarkStep
11+
{
12+
internal sealed class TypeIsRelevantToVariantCastingNode : DependencyNodeCore<NodeFactory>
13+
{
14+
TypeDefinition type;
15+
public TypeIsRelevantToVariantCastingNode (TypeDefinition type) => this.type = type;
16+
17+
public override bool InterestingForDynamicDependencyAnalysis => false;
18+
19+
public override bool HasDynamicDependencies => false;
20+
21+
public override bool HasConditionalStaticDependencies => false;
22+
23+
public override bool StaticDependenciesAreComputed => true;
24+
25+
public override IEnumerable<DependencyListEntry>? GetStaticDependencies (NodeFactory context)
26+
{
27+
yield break;
28+
}
29+
30+
public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (NodeFactory context) => null;
31+
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
32+
protected override string GetName (NodeFactory context) => $"{type.GetDisplayName()} is relevant to variant casting";
33+
protected override void OnMarked (NodeFactory context)
34+
{
35+
context.MarkStep.Annotations.MarkRelevantToVariantCasting (type);
36+
}
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)