Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linker dependency framework #101277

Merged
merged 42 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
afe8990
MarkStep runs inside dependency framework
vitek-karas Sep 13, 2023
4a92aaf
Merge branch 'main' of https://github.com/dotnet/runtime into LinkerD…
jtschuster Apr 19, 2024
76fe923
Put MarkType into DependencyFramework
jtschuster Apr 19, 2024
b3ccd66
Leave MarkType in MarkStep, use captured MarkStep to call it
jtschuster Apr 19, 2024
eb5e333
Format
jtschuster Apr 19, 2024
e1270bb
Use DF for TypeDefinition and MethodDefinition
jtschuster Apr 19, 2024
2d12ade
Rename MarkTypeImpl to ProcessType and clean up code
jtschuster Apr 20, 2024
1dc80db
Clean up code a bit more
jtschuster Apr 20, 2024
991f7a0
Use ProjectReference for DAF, and undo method moves
jtschuster Apr 22, 2024
069f47b
Merge branch 'main' of https://github.com/dotnet/runtime into LinkerD…
jtschuster Apr 22, 2024
c1670eb
Don't have additional virtualmethods processing
jtschuster Apr 22, 2024
8382e68
Merge branch 'main' of https://github.com/dotnet/runtime into LinkerD…
jtschuster Apr 22, 2024
5bf5ece
Remove old header comment copied from MarkStep
jtschuster Apr 22, 2024
e6edbce
Remove nullable directives from ilc files
jtschuster Apr 22, 2024
10a5c57
Sign DAF instead of nowarn on trimmer
jtschuster Apr 22, 2024
166d2d5
Re-add doc comment; Make types internal
jtschuster Apr 22, 2024
01f3a79
Undo Queue changes, fix visibility issues
jtschuster Apr 23, 2024
098f7bc
Rename TypeDefinitionDependencyNode file to match class
jtschuster Apr 23, 2024
25ec8ce
PR feedback:
jtschuster Apr 23, 2024
9ef1343
PR Feedback:
jtschuster Apr 25, 2024
d50d70c
Use static lambda for TypeDefinitionNode creation
jtschuster Apr 25, 2024
dfe51f2
Only warn on duplicate members within a single descriptors file
jtschuster Apr 25, 2024
afedfb7
Only warn on duplicate members within a single descriptors file
jtschuster Apr 25, 2024
a600348
Make duplicate preserve an info message
jtschuster Apr 26, 2024
8d642a5
Merge branch 'main' of https://github.com/dotnet/runtime into LinkerD…
jtschuster Apr 26, 2024
a0ea640
Merge branch 'main' of https://github.com/dotnet/runtime into ILLinkD…
jtschuster Apr 26, 2024
2bb99d7
Merge branch 'ILLinkDescriptionDuplicatePreserve' into LinkerDependen…
jtschuster Apr 26, 2024
b27bc04
Update expectations in xml warnings tests
jtschuster Apr 26, 2024
3394758
Merge branch 'ILLinkDescriptionDuplicatePreserve' into LinkerDependen…
jtschuster Apr 26, 2024
1abe4b3
Make method internal for API compat
jtschuster Apr 27, 2024
8cbedd1
Merge branch 'ILLinkDescriptionDuplicatePreserve' into LinkerDependen…
jtschuster Apr 27, 2024
df7a522
Merge branch 'main' into LinkerDependencyFramework
jtschuster Apr 30, 2024
28bf0be
Merge branch 'main' into LinkerDependencyFramework
jtschuster May 1, 2024
3ca9f9a
PR Feedback:
jtschuster May 2, 2024
830f23e
Merge branch 'LinkerDependencyFramework' of https://github.com/jtschu…
jtschuster May 2, 2024
3001124
Add space before method call parentheses
jtschuster May 2, 2024
f003f74
Don't pass TargetOS and TargetArch to ILLink.Tasks when using live il…
jtschuster May 3, 2024
a0f6861
Merge branch 'main' into LinkerDependencyFramework
jtschuster May 3, 2024
d358b42
Update comment in liveILLink.targets
jtschuster May 3, 2024
0fab4e3
Merge branch 'LinkerDependencyFramework' of https://github.com/jtschu…
jtschuster May 3, 2024
5e124b5
Don't append platform to output dirs
jtschuster May 3, 2024
855b109
Merge branch 'main' into LinkerDependencyFramework
jtschuster May 6, 2024
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
4 changes: 3 additions & 1 deletion eng/liveILLink.targets
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@

<ItemGroup Condition="'$(_RequiresLiveILLink)' == 'true'">
<!-- The assembly shouldn't be referenced, nor promoted to a package dependency, nor copied to the output directory. -->
<!-- ILLink.Tasks is architecture independent, so TargetArch and TargetOS should not be specified -->
<ProjectReference Include="$(_ILLinkTasksSourceDir)ILLink.Tasks.csproj"
ReferenceOutputAssembly="false"
PrivateAssets="all"
Private="false"
SetConfiguration="Configuration=$(ToolsConfiguration)">
SetConfiguration="Configuration=$(ToolsConfiguration)"
GlobalPropertiesToRemove="TargetArchitecture;TargetOS" >
<!-- Keep TFMs in sync with ILLink.Tasks.csproj -->
<SetTargetFramework Condition="'$(MSBuildRuntimeType)' == 'Core'">TargetFramework=$(NetCoreAppToolCurrent)</SetTargetFramework>
<SetTargetFramework Condition="'$(MSBuildRuntimeType)' != 'Core'">TargetFramework=$(NetFrameworkToolCurrent)</SetTargetFramework>
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<InferPlatformFromTargetArchitecture>true</InferPlatformFromTargetArchitecture>
<InferPlatformFromTargetArchitecture Condition="'$(InferPlatformFromTargetArchitecture)' == ''">true</InferPlatformFromTargetArchitecture>

<!-- TODO: Clean-up casing and remove __BuildType to remove this block. -->
<Configuration Condition="'$(Configuration)' == ''">$(__BuildType)</Configuration>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project>
<PropertyGroup>
<PlatformName>AnyCPU</PlatformName>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>ILCompiler.DependencyAnalysisFramework</RootNamespace>
Expand All @@ -8,6 +12,10 @@
<Platforms>x64;x86</Platforms>
<PlatformTarget>AnyCPU</PlatformTarget>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<!-- Workaround for circular dependency (this => trim analyzers in illink.Tasks => Mono.Linker => this)-->
<_RequiresLiveILLink>false</_RequiresLiveILLink>
<!-- Mono.Linker requires the assembly to be signed -->
<SignAssembly>true</SignAssembly>

<!-- We're binplacing these into an existing publish layout so that F5 build in VS updates
the same bits tests expect to see in artifacts/crossgen2. That way we never need to wonder which
Expand Down Expand Up @@ -50,4 +58,5 @@
<Link>Sorting\MergeSortCore.cs</Link>
</Compile>
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>
5 changes: 0 additions & 5 deletions src/tools/illink/src/linker/Linker.Steps/MarkScopeStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@ internal LocalScope PushLocalScope (in Scope scope)
return new LocalScope (scope, this);
}

internal ParentScope PopToParentScope ()
{
return new ParentScope (this);
}

public IDisposable PushScope (in MessageOrigin origin)
{
return new LocalScope (origin, this);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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 ILCompiler.DependencyAnalysisFramework;
using Mono.Cecil;

namespace Mono.Linker.Steps
{
public partial class MarkStep
{
internal sealed class MethodDefinitionNode : DependencyNodeCore<NodeFactory>
{
readonly MethodDefinition method;
readonly DependencyInfo reason;

public MethodDefinitionNode (MethodDefinition method, DependencyInfo reason)
{
this.method = method;
this.reason = reason;
}

public override bool InterestingForDynamicDependencyAnalysis => false;

public override bool HasDynamicDependencies => false;

public override bool HasConditionalStaticDependencies => false;

public override bool StaticDependenciesAreComputed => true;

public override IEnumerable<DependencyListEntry>? GetStaticDependencies (NodeFactory context)
{
context.MarkStep.ProcessMethod (method, reason);
return null;
}

public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (NodeFactory context) => null;
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
protected override string GetName (NodeFactory context) => method.GetDisplayName();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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.Concurrent;
using System.Collections.Generic;
using Mono.Cecil;

namespace Mono.Linker.Steps
{
public partial class MarkStep
{
internal sealed class NodeFactory (MarkStep markStep)
{
public MarkStep MarkStep { get; } = markStep;
readonly NodeCache<TypeDefinition, TypeDefinitionNode> _typeNodes = new (static t => new TypeDefinitionNode(t));
readonly NodeCache<MethodDefinition, MethodDefinitionNode> _methodNodes = new (static _ => throw new InvalidOperationException ("Creation of node requires more than the key."));
readonly NodeCache<TypeDefinition, TypeIsRelevantToVariantCastingNode> _typeIsRelevantToVariantCastingNodes = new (static (t) => new TypeIsRelevantToVariantCastingNode (t));

internal TypeDefinitionNode GetTypeNode (TypeDefinition definition)
{
return _typeNodes.GetOrAdd (definition);
}

internal MethodDefinitionNode GetMethodDefinitionNode (MethodDefinition method, DependencyInfo reason)
{
return _methodNodes.GetOrAdd (method, (k) => new MethodDefinitionNode (k, reason));
}

internal TypeIsRelevantToVariantCastingNode GetTypeIsRelevantToVariantCastingNode (TypeDefinition type)
{
return _typeIsRelevantToVariantCastingNodes.GetOrAdd (type);
}

struct NodeCache<TKey, TValue> where TKey : notnull
{
// Change to concurrent dictionary if/when multithreaded marking is enabled
readonly Dictionary<TKey, TValue> _cache;
readonly Func<TKey, TValue> _creator;

public NodeCache (Func<TKey, TValue> creator, IEqualityComparer<TKey> comparer)
{
_creator = creator;
_cache = new (comparer);
}

public NodeCache (Func<TKey, TValue> creator)
{
_creator = creator;
_cache = new ();
}

public TValue GetOrAdd (TKey key)
{
return _cache.GetOrAdd (key, _creator);
}

public TValue GetOrAdd (TKey key, Func<TKey, TValue> creator)
{
return _cache.GetOrAdd (key, creator);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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 ILCompiler.DependencyAnalysisFramework;

namespace Mono.Linker.Steps
{
public partial class MarkStep
{
sealed class ProcessCallbackNode : DependencyNodeCore<NodeFactory>
{
Func<bool> _processAction;
DependencyList? _dependencies;

public ProcessCallbackNode (Func<bool> action) => _processAction = action;

public void Process ()
{
_dependencies = new DependencyList ();
if (_processAction ()) {
_dependencies.Add (new ProcessCallbackNode (_processAction), "Some processing was done, continuation required");
}
}

public override bool InterestingForDynamicDependencyAnalysis => false;

public override bool HasDynamicDependencies => false;

public override bool HasConditionalStaticDependencies => false;

public override bool StaticDependenciesAreComputed => _dependencies != null;

public override IEnumerable<DependencyListEntry>? GetStaticDependencies (NodeFactory context) => _dependencies;

public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (NodeFactory context) => null;
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
protected override string GetName (NodeFactory context) => "Process";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.Collections.Generic;
using ILCompiler.DependencyAnalysisFramework;
using Mono.Cecil;

namespace Mono.Linker.Steps
{
public partial class MarkStep
{
internal sealed class TypeDefinitionNode : DependencyNodeCore<NodeFactory>
{
readonly TypeDefinition type;

public TypeDefinitionNode (TypeDefinition type)
{
this.type = type;
}

public override bool InterestingForDynamicDependencyAnalysis => false;

public override bool HasDynamicDependencies => false;

public override bool HasConditionalStaticDependencies => false;

public override bool StaticDependenciesAreComputed => true;

public override IEnumerable<DependencyListEntry>? GetStaticDependencies (NodeFactory context)
{
context.MarkStep.ProcessType (type);
return null;
}

public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (NodeFactory context) => null;
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
protected override string GetName (NodeFactory context) => type.GetDisplayName();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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.Collections.Generic;
using ILCompiler.DependencyAnalysisFramework;
using Mono.Cecil;

namespace Mono.Linker.Steps
{
public partial class MarkStep
{
internal sealed class TypeIsRelevantToVariantCastingNode : DependencyNodeCore<NodeFactory>
{
TypeDefinition type;
public TypeIsRelevantToVariantCastingNode (TypeDefinition type) => this.type = type;

public override bool InterestingForDynamicDependencyAnalysis => false;

public override bool HasDynamicDependencies => false;

public override bool HasConditionalStaticDependencies => false;

public override bool StaticDependenciesAreComputed => true;

public override IEnumerable<DependencyListEntry>? GetStaticDependencies (NodeFactory context)
{
yield break;
}

public override IEnumerable<CombinedDependencyListEntry>? GetConditionalStaticDependencies (NodeFactory context) => null;
public override IEnumerable<CombinedDependencyListEntry>? SearchDynamicDependencies (List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
protected override string GetName (NodeFactory context) => $"{type.GetDisplayName()} is relevant to variant casting";
protected override void OnMarked (NodeFactory context)
{
context.MarkStep.Annotations.MarkRelevantToVariantCasting (type);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When do we use OnMarked vs GetStaticDependencies?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just used OnMarked arbitrarily for this since there aren't any dependencies. It looks like OnMarked will do work up front when the node is returned from another GetStaticDependencies, then it's added to a stack to later call GetStaticDependencies.

}
}
}
}
Loading
Loading