Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1606998
Add cross-module R2R reference resolution tests
jtschuster Mar 31, 2026
1493728
Add runtime-async method variants to cross-module resolution tests
jtschuster Mar 31, 2026
70ad8f0
Add R2R validation tool for cross-module resolution tests
jtschuster Mar 31, 2026
1575e66
Extract crossgen2 precommands into shared .targets file
jtschuster Mar 31, 2026
ee26040
Refactor crossgen2 orchestration into C# console app
jtschuster Mar 31, 2026
67ffdd6
Output runcrossgen to CORE_ROOT/runcrossgen/
jtschuster Mar 31, 2026
d5b2d3a
Use host SDK RID for runcrossgen build-time tool
jtschuster Mar 31, 2026
8029183
WIP: Add ILCompiler.ReadyToRun.Tests project
jtschuster Apr 1, 2026
3e1a6c8
Fix R2R test validation and remove opt-async-methods
jtschuster Apr 1, 2026
183262c
Add runtime-async functional tests for R2R
jtschuster Apr 1, 2026
7bb35e5
Refactor R2R test model: rename DependencyInfo to CompiledAssembly, a…
jtschuster Apr 1, 2026
804ec55
Replace R2RExpectations with Action<ReadyToRunReader> validation call…
jtschuster Apr 1, 2026
25ee0be
Fix R2R test runner: --opt-cross-module args and composite output naming
jtschuster Apr 2, 2026
b2e0f5b
Add InliningInfo2 structured parsing and method-targeted assertions
jtschuster Apr 2, 2026
c8c6a35
Add 10 new R2R cross-module/async/composite test cases
jtschuster Apr 2, 2026
805f042
Add test source files for new R2R test cases
jtschuster Apr 2, 2026
d90a6cd
Fix composite tests: add --optimize flag and cross-assembly inline as…
jtschuster Apr 2, 2026
67e8d19
Fix code review issues: parser bug, deadlock, file handle leak
jtschuster Apr 2, 2026
2ab55e0
Add CrossModuleGenericMultiInliner test for cross-module inliner parsing
jtschuster Apr 2, 2026
03d71ec
Validate resolved inliner names in HasCrossModuleInliners
jtschuster Apr 2, 2026
22e55bd
Remove unused Utility.GetName() from CrossModuleGenericLib test
jtschuster Apr 2, 2026
b6d5227
Remove session state and planning files from tracking
jtschuster Apr 2, 2026
61ea4a9
Remove crossmoduleresolution tests from src/tests/readytorun
jtschuster Apr 2, 2026
537cd1b
Fix stale and inaccurate comments across R2R test files
jtschuster Apr 2, 2026
32b6ce8
Use ActiveIssue instead of Fact(Skip) for composite async tests
jtschuster Apr 2, 2026
de94dba
Use self-contained crossgen2_inbuild for R2R tests
jtschuster Apr 3, 2026
262a295
Log crossgen2 command line in test output for reproducibility
jtschuster Apr 3, 2026
19b97d2
Merge branch 'main' into RuntimeAsyncComposite
jtschuster Apr 8, 2026
041e4a1
Fix R2R inlining info parser correctness and test build issues
jtschuster Apr 13, 2026
28a7932
Fix SPCL reference path resolution in R2R tests
jtschuster Apr 15, 2026
46dddbd
Add clr.corelib+clr.nativecorelib to CLR_Tools_Tests build
jtschuster Apr 15, 2026
b6f6156
Fall back to CoreCLR artifacts dir when SPCL not in runtime pack nati…
jtschuster Apr 15, 2026
af54482
InliningInfoSection2 is per assembly in composite mode
jtschuster Apr 16, 2026
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
11 changes: 10 additions & 1 deletion docs/design/coreclr/botr/readytorun-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ The following section types are defined and described later in this document:
| ProfileDataInfo | 111 | Image (added in V2.2)
| ManifestMetadata | 112 | Image (added in V2.3)
| AttributePresence | 113 | Assembly (added in V3.1)
| InliningInfo2 | 114 | Image (added in V4.1)
| InliningInfo2 | 114 | Image (non-composite, added in V4.1), Assembly (composite, added in V6.3)
| ComponentAssemblies | 115 | Image (added in V4.1)
| OwnerCompositeExecutable | 116 | Image (added in V4.1)
| PgoInstrumentationData | 117 | Image (added in V5.2)
Expand Down Expand Up @@ -589,6 +589,15 @@ The entry of the hashtable is a counted sequence of compressed unsigned integers

Foreign RIDs are only present if a fragile inlining was allowed at compile time.

**Note:** In single-file (non-composite) R2R files, this section is image-wide and is
referenced directly by the main R2R header. In composite R2R files (v6.3+), this section
is instead emitted per component assembly and is referenced by the
`READYTORUN_SECTION_ASSEMBLIES_ENTRY` core header of each component; inlinee/inliner RIDs
without a module override flag refer to methods in the owning component assembly. The
image-wide [`CrossModuleInlineInfo`](#readytorunsectiontypecrossmoduleinlineinfo-v63)
section supersedes the image-wide use of `InliningInfo2` for cross-module inlines in
composite images and may be emitted alongside the per-assembly `InliningInfo2` sections.

**TODO:** It remains to be seen whether `DelayLoadMethodCallThunks` and / or
`InliningInfo` also require changes specific to the composite R2R file format.

Expand Down
2 changes: 2 additions & 0 deletions eng/Subsets.props
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@
Test="true" Category="clr" Condition="'$(DotNetBuildSourceOnly)' != 'true' and '$(NativeAotSupported)' == 'true'"/>
<ProjectToBuild Include="$(CoreClrProjectRoot)tools\aot\ILCompiler.Trimming.Tests\ILCompiler.Trimming.Tests.csproj"
Test="true" Category="clr" Condition="'$(DotNetBuildSourceOnly)' != 'true' and '$(NativeAotSupported)' == 'true'"/>
<ProjectToBuild Include="$(CoreClrProjectRoot)tools\aot\ILCompiler.ReadyToRun.Tests\ILCompiler.ReadyToRun.Tests.csproj"
Test="true" Category="clr" Condition="'$(DotNetBuildSourceOnly)' != 'true' and '$(NativeAotSupported)' == 'true'"/>
<ProjectToBuild Include="$(CoreClrProjectRoot)tools\ILVerification.Tests\ILVerification.Tests.csproj"
Test="true" Category="clr" Condition="'$(DotNetBuildSourceOnly)' != 'true'"/>
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ extends:
jobParameters:
timeoutInMinutes: 120
nameSuffix: CLR_Tools_Tests
buildArgs: -s clr.aot+clr.iltools+libs.sfx+clr.toolstests+tools.cdac+tools.cdactests -c $(_BuildConfig) -test
buildArgs: -s clr.aot+clr.iltools+clr.corelib+clr.nativecorelib+libs.sfx+clr.toolstests+tools.cdac+tools.cdactests -c $(_BuildConfig) -test
enablePublishTestResults: true
testResultsFormat: 'xunit'
# We want to run AOT tests when illink changes because there's share code and tests from illink which are used by AOT
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<AssemblyName>ILCompiler.ReadyToRun.Tests</AssemblyName>
<TargetFramework>$(NetCoreAppToolCurrent)</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>x64;x86</Platforms>
<PlatformTarget>AnyCPU</PlatformTarget>
<RuntimeIdentifiers>linux-x64;win-x64;osx-x64</RuntimeIdentifiers>
<Configurations>Debug;Release;Checked</Configurations>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<TestRunnerAdditionalArguments>-notrait category=failing</TestRunnerAdditionalArguments>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(MicrosoftCodeAnalysisCSharpVersion)" />
<PackageReference Include="Microsoft.DotNet.XUnitExtensions" Version="$(MicrosoftDotNetXUnitExtensionsVersion)" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj" />
</ItemGroup>

<!-- Test case source files are embedded as resources so we can compile them with Roslyn at test time.
Exclude subdirectory sources from compilation since they are compiled in-memory by R2RTestCaseCompiler. -->
<ItemGroup>
Comment thread
jtschuster marked this conversation as resolved.
<Compile Remove="TestCases/*/**/*.cs" />
<EmbeddedResource Include="TestCases/**/*.cs" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>

<!-- Pass build-time paths to test runtime via RuntimeHostConfigurationOption -->
<ItemGroup>
<RuntimeHostConfigurationOption Include="R2RTest.Crossgen2Dir">
<Value>$(RuntimeBinDir)/$(BuildArchitecture)/crossgen2</Value>
</RuntimeHostConfigurationOption>
<RuntimeHostConfigurationOption Include="R2RTest.RuntimePackDir">
<Value>$(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)</Value>
</RuntimeHostConfigurationOption>
<RuntimeHostConfigurationOption Include="R2RTest.RuntimePackNativeDir">
<Value>$(MicrosoftNetCoreAppRuntimePackNativeDir)</Value>
</RuntimeHostConfigurationOption>
<RuntimeHostConfigurationOption Include="R2RTest.RefPackDir">
<Value>$(MicrosoftNetCoreAppRefPackRefDir)</Value>
</RuntimeHostConfigurationOption>
<RuntimeHostConfigurationOption Include="R2RTest.CoreCLRArtifactsDir">
<Value>$(CoreCLRArtifactsPath)</Value>
</RuntimeHostConfigurationOption>
<RuntimeHostConfigurationOption Include="R2RTest.TargetArchitecture">
<Value>$(TargetArchitecture)</Value>
</RuntimeHostConfigurationOption>
<RuntimeHostConfigurationOption Include="R2RTest.TargetOS">
<Value>$(TargetOS)</Value>
</RuntimeHostConfigurationOption>
<RuntimeHostConfigurationOption Include="R2RTest.Configuration">
<Value>$(Configuration)</Value>
</RuntimeHostConfigurationOption>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Test: Cross-module inlining of async methods
// Validates that async methods from AsyncInlineableLib are cross-module
// inlined into this assembly with CHECK_IL_BODY fixups.
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

public static class AsyncMethods
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static async Task<int> TestAsyncInline()
{
return await AsyncInlineableLib.GetValueAsync();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static async Task<string> TestAsyncStringInline()
{
return await AsyncInlineableLib.GetStringAsync();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static int TestSyncFromAsyncLib()
{
return AsyncInlineableLib.GetValueSync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Test: Basic cross-module inlining
// Validates that crossgen2 with --opt-cross-module produces CHECK_IL_BODY fixups
// for methods inlined from InlineableLib into this main assembly.
using System;
using System.Runtime.CompilerServices;

public static class BasicInlining
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static int TestGetValue()
{
return InlineableLib.GetValue();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static string TestGetString()
{
return InlineableLib.GetString();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static int TestAdd()
{
return InlineableLib.Add(10, 32);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Test: Composite mode with runtime-async methods across assemblies.
// Validates that async methods produce [ASYNC] variants in composite output.
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

public static class CompositeAsyncMain
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static async Task<int> CallCompositeAsync()
{
return await AsyncCompositeLib.GetValueAsync();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static async Task<string> CallCompositeStringAsync()
{
return await AsyncCompositeLib.GetStringAsync();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static int CallCompositeSync()
{
return AsyncCompositeLib.GetValueSync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Test: Composite mode basic compilation
// Validates that composite mode R2R compilation with multiple assemblies
// produces correct manifest references and component assembly entries.
using System;
using System.Runtime.CompilerServices;

public static class CompositeBasic
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static int TestCompositeCall()
{
return CompositeLib.GetCompositeValue();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static object TestCompositeTypeCreation()
{
return new CompositeLib.CompositeType();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Dependency library for composite async tests.
// Contains runtime-async methods called from another assembly in composite mode.
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

public static class AsyncCompositeLib
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<int> GetValueAsync()
{
await Task.Yield();
return 42;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<string> GetStringAsync()
{
await Task.Yield();
return "composite_async";
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetValueSync() => 99;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

public static class AsyncInlineableLib
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<int> GetValueAsync() => 42;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<string> GetStringAsync() => "Hello from async";

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetValueSync() => 42;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

public static class CompositeLib
{
public static int GetCompositeValue() => 100;

public class CompositeType
{
public string Name { get; set; } = "Composite";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Runtime.CompilerServices;

/// <summary>
/// Library with two generic types that each inline the same utility method.
/// When compiled via CrossModuleCompileable generics, each type's InvokeGetValue()
/// becomes a distinct cross-module inliner MethodDef for the same inlinee (Utility.GetValue),
/// producing multiple cross-module inliner entries in the CrossModuleInlineInfo section.
/// </summary>
public static class Utility
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetValue() => 42;
}

public class GenericWrapperA<T>
{
private T _value;

public GenericWrapperA(T value) => _value = value;

[MethodImpl(MethodImplOptions.NoInlining)]
public virtual int InvokeGetValue()
{
return Utility.GetValue();
}
}

public class GenericWrapperB<T>
{
private T _value;

public GenericWrapperB(T value) => _value = value;

[MethodImpl(MethodImplOptions.NoInlining)]
public virtual int InvokeGetValue()
{
return Utility.GetValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

public static class ExternalLib
{
public static int ExternalValue => 99;

public class ExternalType
{
public int Value { get; set; }
}

public class Outer
{
public class Inner
{
public static int NestedValue => 77;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Runtime.CompilerServices;

public static class InlineableLib
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetValue() => 42;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetString() => "Hello from InlineableLib";

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Add(int a, int b) => a + b;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Runtime.CompilerServices;

public static class InlineableLibTransitive
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetExternalValue() => ExternalLib.ExternalValue;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetNestedValue() => ExternalLib.Outer.Inner.NestedValue;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ExternalLib.ExternalType CreateExternal() => new ExternalLib.ExternalType { Value = 42 };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Dependency library for multi-step compilation tests.
// Contains sync inlineable methods used in both composite and non-composite steps.
using System;
using System.Runtime.CompilerServices;

public static class MultiStepLibA
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetValue() => 42;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetLabel() => "LibA";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Second library for multi-step composite compilation.
// Compiled together with MultiStepLibA as a composite in step 1.
using System;
using System.Runtime.CompilerServices;

public static class MultiStepLibB
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetCompositeValue() => MultiStepLibA.GetValue() + 1;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetCompositeLabel() => MultiStepLibA.GetLabel() + "_B";
}
Loading
Loading