From d29392edce6bee3fb178ea6275222cc2ae69b18f Mon Sep 17 00:00:00 2001
From: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Date: Fri, 27 Mar 2026 12:40:14 +0000
Subject: [PATCH 1/5] Migrate remaining tools to modern commandline
---
eng/build.yml | 2 +-
src/AnalyzeAsm/AnalyzeAsm.csproj | 1 -
src/Directory.Build.props | 15 ++
src/cijobs/CIJobsRootCommand.cs | 33 ++--
src/cijobs/Program.cs | 12 +-
src/cijobs/cijobs.csproj | 3 -
.../instructions-retired-explorer.csproj | 3 -
src/jit-analyze/Program.cs | 7 +-
src/jit-analyze/jit-analyze.csproj | 3 -
src/jit-dasm-pmi/Program.cs | 7 +-
src/jit-dasm-pmi/jit-dasm-pmi.csproj | 3 -
src/jit-dasm/Program.cs | 7 +-
src/jit-dasm/jit-dasm.csproj | 3 -
.../jit-decisions-analyze.csproj | 3 -
src/jit-diff/JitDiffRootCommand.cs | 149 ++++++++++++++++
src/jit-diff/jit-diff.cs | 168 ++++++++----------
src/jit-diff/jit-diff.csproj | 3 -
src/jit-format/JitFormatRootCommand.cs | 65 +++++++
src/jit-format/jit-format.cs | 58 +++---
src/jit-format/jit-format.csproj | 3 -
src/jit-include.props | 11 --
src/jit-rl-cse/MLCSE.csproj | 3 -
src/jit-tp-analyze/Program.cs | 7 +-
src/jit-tp-analyze/jit-tp-analyze.csproj | 3 -
src/mutate-test/MutateTestRootCommand.cs | 32 ++--
src/mutate-test/Program.cs | 12 +-
src/mutate-test/mutate-test.csproj | 3 -
.../performance-explorer.csproj | 3 -
src/pmi/pmi.csproj | 2 -
src/superpmi/superpmicollect.csproj | 2 -
src/target-framework.props | 9 -
src/wasm-spmi-filter/wasm-spmi-filter.csproj | 1 -
32 files changed, 399 insertions(+), 237 deletions(-)
create mode 100644 src/Directory.Build.props
create mode 100644 src/jit-diff/JitDiffRootCommand.cs
create mode 100644 src/jit-format/JitFormatRootCommand.cs
delete mode 100644 src/jit-include.props
delete mode 100644 src/target-framework.props
diff --git a/eng/build.yml b/eng/build.yml
index 9f7588ae..ba3779bb 100644
--- a/eng/build.yml
+++ b/eng/build.yml
@@ -13,7 +13,7 @@ jobs:
displayName: 'Install .NET Core SDK'
inputs:
packageType: sdk
- version: 8.x
+ version: 10.x
installationPath: $(Agent.ToolsDirectory)/dotnet
- ${{ if eq(parameters.agentOs, 'Windows_NT') }}:
diff --git a/src/AnalyzeAsm/AnalyzeAsm.csproj b/src/AnalyzeAsm/AnalyzeAsm.csproj
index 74954604..6a70a1ab 100644
--- a/src/AnalyzeAsm/AnalyzeAsm.csproj
+++ b/src/AnalyzeAsm/AnalyzeAsm.csproj
@@ -2,7 +2,6 @@
Exe
- net6.0
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 00000000..0422e1b6
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,15 @@
+
+
+
+ net10.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/cijobs/CIJobsRootCommand.cs b/src/cijobs/CIJobsRootCommand.cs
index e566a403..df9c44af 100644
--- a/src/cijobs/CIJobsRootCommand.cs
+++ b/src/cijobs/CIJobsRootCommand.cs
@@ -5,38 +5,37 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
-using System.CommandLine.Invocation;
using System.Threading.Tasks;
namespace ManagedCodeGen
{
- internal sealed class CIJobsRootCommand : CliRootCommand
+ internal sealed class CIJobsRootCommand : RootCommand
{
- public CliOption Server { get; } =
+ public Option Server { get; } =
new("--server", "-s") { Description = "Url of the server. Defaults to https://ci.dot.net/" };
- public CliOption JobName { get; } =
+ public Option JobName { get; } =
new("--job", "-j") { Description = "Name of the job." };
- public CliOption BranchName { get; } =
+ public Option BranchName { get; } =
new("--branch", "-b") { DefaultValueFactory = _ => "master", Description = "Name of the branch." };
- public CliOption RepoName { get; } =
+ public Option RepoName { get; } =
new("--repo", "-r") { DefaultValueFactory = _ => "dotnet_coreclr", Description = "Name of the repo (e.g. dotnet_corefx or dotnet_coreclr)." };
- public CliOption MatchPattern { get; } =
+ public Option MatchPattern { get; } =
new("--match", "-m") { Description = "Regex pattern used to select jobs output." };
- public CliOption JobNumber { get; } =
+ public Option JobNumber { get; } =
new("--number", "-n") { Description = "Job number." };
- public CliOption ShowLastSuccessful { get; } =
+ public Option ShowLastSuccessful { get; } =
new("--last-successful", "-l") { Description = "Show last successful build." };
- public CliOption Commit { get; } =
+ public Option Commit { get; } =
new("--commit", "-c") { Description = "List build at this commit." };
- public CliOption ShowArtifacts { get; } =
+ public Option ShowArtifacts { get; } =
new("--artifacts", "-a") { Description = "Show job artifacts on server." };
- public CliOption OutputPath { get; } =
+ public Option OutputPath { get; } =
new("--output", "-o") { Description = "The path where output will be placed." };
- public CliOption OutputRoot { get; } =
+ public Option OutputRoot { get; } =
new("--output-root") { Description = "The root directory where output will be placed. A subdirectory named by job and build number will be created within this to store the output." };
- public CliOption Unzip { get; } =
+ public Option Unzip { get; } =
new("--unzip", "-u") { Description = "Unzip copied artifacts" };
- public CliOption ContentPath { get; } =
+ public Option ContentPath { get; } =
new("--ContentPath", "-p") { Description = "Relative product zip path. Default is artifact/bin/Product/*zip*/Product.zip" };
public ParseResult Result;
@@ -45,7 +44,7 @@ public CIJobsRootCommand(string[] args) : base("Continuous integration build job
{
List errors = new();
- CliCommand listCommand = new("list", "List jobs on ci.dot.net for the repo.")
+ Command listCommand = new("list", "List jobs on ci.dot.net for the repo.")
{
Server,
JobName,
@@ -104,7 +103,7 @@ public CIJobsRootCommand(string[] args) : base("Continuous integration build job
Subcommands.Add(listCommand);
- CliCommand copyCommand = new("copy", @"Copies job artifacts from ci.dot.net. This
+ Command copyCommand = new("copy", @"Copies job artifacts from ci.dot.net. This
command copies a zip of artifacts from a repo (defaulted to
dotnet_coreclr). The default location of the zips is the
Product sub-directory, though that can be changed using the
diff --git a/src/cijobs/Program.cs b/src/cijobs/Program.cs
index 73b01e18..24626b0e 100755
--- a/src/cijobs/Program.cs
+++ b/src/cijobs/Program.cs
@@ -69,13 +69,13 @@ public async Task RunAsync(string name)
return await CopyAsync(cic);
}
- private T Get(CliOption option) => _command.Result.GetValue(option);
+ private T Get(Option option) => _command.Result.GetValue(option);
- private static Task Main(string[] args) =>
- new CliConfiguration(new CIJobsRootCommand(args).UseVersion())
- {
- EnableParseErrorReporting = true
- }.InvokeAsync(args);
+ private static Task Main(string[] args)
+ {
+ var command = new CIJobsRootCommand(args).UseVersion();
+ return command.Parse(args).InvokeAsync();
+ }
// List jobs and their details from the given project on .NETCI Jenkins instance.
// List functionality:
diff --git a/src/cijobs/cijobs.csproj b/src/cijobs/cijobs.csproj
index 036eb0f1..87773400 100644
--- a/src/cijobs/cijobs.csproj
+++ b/src/cijobs/cijobs.csproj
@@ -1,8 +1,5 @@
-
-
-
Exe
diff --git a/src/instructions-retired-explorer/instructions-retired-explorer.csproj b/src/instructions-retired-explorer/instructions-retired-explorer.csproj
index 4539b1d1..fc32fc7d 100644
--- a/src/instructions-retired-explorer/instructions-retired-explorer.csproj
+++ b/src/instructions-retired-explorer/instructions-retired-explorer.csproj
@@ -1,8 +1,5 @@
-
-
-
Exe
diff --git a/src/jit-analyze/Program.cs b/src/jit-analyze/Program.cs
index 2d334f85..cc791ca9 100644
--- a/src/jit-analyze/Program.cs
+++ b/src/jit-analyze/Program.cs
@@ -908,8 +908,11 @@ public static Dictionary DiffInText(string diffPath, string basePat
private T Get(Option option) => _command.Result.GetValue(option);
- private static int Main(string[] args) =>
- new CommandLineConfiguration(new JitAnalyzeRootCommand(args).UseVersion()).Invoke(args);
+ private static int Main(string[] args)
+ {
+ var command = new JitAnalyzeRootCommand(args).UseVersion();
+ return command.Parse(args).Invoke();
+ }
public int Run()
{
diff --git a/src/jit-analyze/jit-analyze.csproj b/src/jit-analyze/jit-analyze.csproj
index 036eb0f1..87773400 100644
--- a/src/jit-analyze/jit-analyze.csproj
+++ b/src/jit-analyze/jit-analyze.csproj
@@ -1,8 +1,5 @@
-
-
-
Exe
diff --git a/src/jit-dasm-pmi/Program.cs b/src/jit-dasm-pmi/Program.cs
index 16cf6c50..904bbba3 100644
--- a/src/jit-dasm-pmi/Program.cs
+++ b/src/jit-dasm-pmi/Program.cs
@@ -75,8 +75,11 @@ public int Run()
private T Get(Option option) => _command.Result.GetValue(option);
private T Get(Argument arg) => _command.Result.GetValue(arg);
- private static int Main(string[] args) =>
- new CommandLineConfiguration(new JitDasmPmiRootCommand(args).UseVersion()).Invoke(args);
+ private static int Main(string[] args)
+ {
+ var command = new JitDasmPmiRootCommand(args).UseVersion();
+ return command.Parse(args).Invoke();
+ }
public List GenerateAssemblyWorklist()
{
diff --git a/src/jit-dasm-pmi/jit-dasm-pmi.csproj b/src/jit-dasm-pmi/jit-dasm-pmi.csproj
index 036eb0f1..87773400 100644
--- a/src/jit-dasm-pmi/jit-dasm-pmi.csproj
+++ b/src/jit-dasm-pmi/jit-dasm-pmi.csproj
@@ -1,8 +1,5 @@
-
-
-
Exe
diff --git a/src/jit-dasm/Program.cs b/src/jit-dasm/Program.cs
index dc24baa8..77755cd1 100644
--- a/src/jit-dasm/Program.cs
+++ b/src/jit-dasm/Program.cs
@@ -84,8 +84,11 @@ public int Run()
private T Get(Option option) => _command.Result.GetValue(option);
private T Get(Argument arg) => _command.Result.GetValue(arg);
- private static int Main(string[] args) =>
- new CommandLineConfiguration(new JitDasmRootCommand(args).UseVersion()).Invoke(args);
+ private static int Main(string[] args)
+ {
+ var command = new JitDasmRootCommand(args).UseVersion();
+ return command.Parse(args).Invoke();
+ }
public List GenerateAssemblyWorklist()
{
diff --git a/src/jit-dasm/jit-dasm.csproj b/src/jit-dasm/jit-dasm.csproj
index 036eb0f1..87773400 100644
--- a/src/jit-dasm/jit-dasm.csproj
+++ b/src/jit-dasm/jit-dasm.csproj
@@ -1,8 +1,5 @@
-
-
-
Exe
diff --git a/src/jit-decisions-analyze/jit-decisions-analyze.csproj b/src/jit-decisions-analyze/jit-decisions-analyze.csproj
index 036eb0f1..87773400 100644
--- a/src/jit-decisions-analyze/jit-decisions-analyze.csproj
+++ b/src/jit-decisions-analyze/jit-decisions-analyze.csproj
@@ -1,8 +1,5 @@
-
-
-
Exe
diff --git a/src/jit-diff/JitDiffRootCommand.cs b/src/jit-diff/JitDiffRootCommand.cs
new file mode 100644
index 00000000..9048517e
--- /dev/null
+++ b/src/jit-diff/JitDiffRootCommand.cs
@@ -0,0 +1,149 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.CommandLine;
+using System.CommandLine.Parsing;
+
+namespace ManagedCodeGen
+{
+ internal sealed class JitDiffRootCommand : RootCommand
+ {
+ public Option BasePath { get; } =
+ new("--base", "-b") { Description = "The base compiler directory or tag. Will use crossgen, corerun, or clrjit from this directory.", Arity = ArgumentArity.ZeroOrOne };
+ public Option DiffPath { get; } =
+ new("--diff", "-d") { Description = "The diff compiler directory or tag. Will use crossgen, corerun, or clrjit from this directory.", Arity = ArgumentArity.ZeroOrOne };
+ public Option CrossgenExe { get; } =
+ new("--crossgen") { Description = "The crossgen or crossgen2 compiler exe. When this is specified, will use clrjit from the --base and --diff directories with this crossgen." };
+ public Option OutputPath { get; } =
+ new("--output", "-o") { Description = "The output path." };
+ public Option NoAnalyze { get; } =
+ new("--noanalyze") { Description = "Do not analyze resulting base, diff dasm directories. (By default, the directories are analyzed for diffs.)" };
+ public Option Sequential { get; } =
+ new("--sequential", "-s") { Description = "Run sequentially; don't do parallel compiles." };
+ public Option Tag { get; } =
+ new("--tag", "-t") { Description = "Name of root in output directory. Allows for many sets of output." };
+ public Option CoreLib { get; } =
+ new("--corelib", "-c") { Description = "Diff System.Private.CoreLib.dll." };
+ public Option Frameworks { get; } =
+ new("--frameworks", "-f") { Description = "Diff frameworks." };
+ public Option Metric { get; } =
+ new("--metrics", "-m") { Description = "Comma-separated metric to use for diff computations. Available metrics: CodeSize(default), PerfScore, PrologSize, InstrCount, AllocSize, ExtraAllocBytes, DebugClauseCount, DebugVarCount" };
+ public Option Benchmarks { get; } =
+ new("--benchmarks") { Description = "Diff core benchmarks." };
+ public Option Tests { get; } =
+ new("--tests") { Description = "Diff all tests." };
+ public Option GCInfo { get; } =
+ new("--gcinfo") { Description = "Add GC info to the disasm output." };
+ public Option DebugInfo { get; } =
+ new("--debuginfo") { Description = "Add Debug info to the disasm output." };
+ public Option Verbose { get; } =
+ new("--verbose", "-v") { Description = "Enable verbose output." };
+ public Option NoDiffable { get; } =
+ new("--nodiffable") { Description = "Generate non-diffable asm (pointer values will be left in output)." };
+ public Option CoreRoot { get; } =
+ new("--core_root") { Description = "Path to test CORE_ROOT." };
+ public Option TestRoot { get; } =
+ new("--test_root") { Description = "Path to test tree. Use with --benchmarks or --tests." };
+ public Option BaseRoot { get; } =
+ new("--base_root") { Description = "Path to root of base dotnet/runtime repo." };
+ public Option DiffRoot { get; } =
+ new("--diff_root") { Description = "Path to root of diff dotnet/runtime repo." };
+ public Option Arch { get; } =
+ new("--arch") { Description = "Architecture to diff (x86, x64)." };
+ public Option Build { get; } =
+ new("--build") { Description = "Build flavor to diff (Checked, Debug)." };
+ public Option AltJit { get; } =
+ new("--altjit") { Description = "If set, the name of the altjit to use (e.g., clrjit_win_arm64_x64.dll)." };
+ public Option Pmi { get; } =
+ new("--pmi") { Description = "Run asm diffs via pmi." };
+ public Option Cctors { get; } =
+ new("--cctors") { Description = "With --pmi, jit and run cctors before jitting other methods" };
+ public Option> AssemblyList { get; } =
+ new("--assembly") { Description = "Run asm diffs on a given set of assemblies. An individual item can be an assembly or a directory tree containing assemblies." };
+ public Option Tsv { get; } =
+ new("--tsv") { Description = "Dump analysis data to diffs.tsv in output directory." };
+ public Option Tier0 { get; } =
+ new("--tier0") { Description = "Diff tier0 codegen where possible." };
+ public Option Count { get; } =
+ new("--count") { Description = "Provide the count parameter to jit-analyze (default 20)." };
+
+ public Option JobName { get; } =
+ new("--job", "-j") { Description = "Name of the job." };
+ public Option Number { get; } =
+ new("--number", "-n") { Description = "Job number." };
+ public Option LastSuccessful { get; } =
+ new("--last_successful", "-l") { Description = "Last successful build." };
+ public Option BranchName { get; } =
+ new("--branch", "-b") { Description = "Name of branch." };
+
+ public ParseResult Result { get; private set; }
+ public jitdiff.Commands SelectedCommand { get; private set; }
+
+ public JitDiffRootCommand(string[] args) : base("Managed codegen diff orchestrator")
+ {
+ Command diffCommand = new("diff", "Run asm diffs via crossgen.")
+ {
+ BasePath, DiffPath, CrossgenExe, OutputPath, NoAnalyze, Sequential, Tag, CoreLib, Frameworks, Metric,
+ Benchmarks, Tests, GCInfo, DebugInfo, Verbose, NoDiffable, CoreRoot, TestRoot, BaseRoot, DiffRoot,
+ Arch, Build, AltJit, Pmi, Cctors, AssemblyList, Tsv, Tier0, Count
+ };
+ diffCommand.SetAction(result => Execute(result, jitdiff.Commands.Diff));
+ Subcommands.Add(diffCommand);
+
+ Command listCommand = new("list", "List defaults and available tools in config.json.")
+ {
+ Verbose
+ };
+ listCommand.SetAction(result => Execute(result, jitdiff.Commands.List));
+ Subcommands.Add(listCommand);
+
+ Command installCommand = new("install", "Install tool in config.json.")
+ {
+ JobName, Number, LastSuccessful, BranchName, Verbose
+ };
+ installCommand.SetAction(result => Execute(result, jitdiff.Commands.Install));
+ Subcommands.Add(installCommand);
+
+ Command uninstallCommand = new("uninstall", "Uninstall tool from config.json.")
+ {
+ Tag
+ };
+ uninstallCommand.SetAction(result => Execute(result, jitdiff.Commands.Uninstall));
+ Subcommands.Add(uninstallCommand);
+ }
+
+ private int Execute(ParseResult result, jitdiff.Commands command)
+ {
+ Result = result;
+ SelectedCommand = command;
+
+ try
+ {
+ jitdiff.Config config = new(this);
+ return config.DoCommand switch
+ {
+ jitdiff.Commands.Diff => jitdiff.DiffTool.DiffCommand(config),
+ jitdiff.Commands.PmiDiff => jitdiff.DiffTool.DiffCommand(config),
+ jitdiff.Commands.List => config.ListCommand(),
+ jitdiff.Commands.Install => jitdiff.InstallCommand(config),
+ jitdiff.Commands.Uninstall => jitdiff.UninstallCommand(config),
+ _ => 1,
+ };
+ }
+ catch (Exception e)
+ {
+ Console.ResetColor();
+ Console.ForegroundColor = ConsoleColor.Red;
+
+ Console.Error.WriteLine("Error: " + e.Message);
+ Console.Error.WriteLine(e.ToString());
+
+ Console.ResetColor();
+ return 1;
+ }
+ }
+ }
+}
diff --git a/src/jit-diff/jit-diff.cs b/src/jit-diff/jit-diff.cs
index 9430d637..c395c112 100755
--- a/src/jit-diff/jit-diff.cs
+++ b/src/jit-diff/jit-diff.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
+using System.CommandLine.Parsing;
using System.IO;
using System.Linq;
using System.Text.Json;
@@ -113,7 +114,6 @@ private static string GetConfigurationArtifactDir(string platformMoniker, string
public class Config
{
- private ArgumentSyntax _syntaxResult;
private Commands _command = Commands.Diff;
private bool _baseSpecified = false; // True if user specified "--base" or "--base " or "--base "
private bool _diffSpecified = false; // True if user specified "--diff" or "--diff " or "--diff "
@@ -158,77 +158,80 @@ public class Config
private bool _noJitUtilsRoot = false;
private bool _validationError = false;
- public Config(string[] args)
+ internal Config(JitDiffRootCommand command)
{
- // Get configuration values from JIT_UTILS_ROOT/config.json
+ // Get configuration values from JIT_UTILS_ROOT/config.json.
LoadFileConfig();
- _syntaxResult = ArgumentSyntax.Parse(args, syntax =>
+ ParseResult result = command.Result;
+ _command = command.SelectedCommand;
+
+ bool IsSpecified(Option option) => result.GetResult(option) != null;
+ T Get(Option option) => result.GetValue(option);
+
+ if (_command == Commands.Diff)
{
- // Diff command section.
- syntax.DefineCommand("diff", ref _command, Commands.Diff, "Run asm diffs via crossgen.");
-
- var baseOption = syntax.DefineOption("b|base", ref _basePath, false,
- "The base compiler directory or tag. Will use crossgen, corerun, or clrjit from this directory.");
- var diffOption = syntax.DefineOption("d|diff", ref _diffPath, false,
- "The diff compiler directory or tag. Will use crossgen, corerun, or clrjit from this directory.");
- syntax.DefineOption("crossgen", ref _crossgenExe,
- "The crossgen or crossgen2 compiler exe. When this is specified, will use clrjit from the --base and " +
- "--diff directories with this crossgen.");
- syntax.DefineOption("o|output", ref _outputPath, "The output path.");
- syntax.DefineOption("noanalyze", ref _noanalyze, "Do not analyze resulting base, diff dasm directories. (By default, the directories are analyzed for diffs.)");
- syntax.DefineOption("s|sequential", ref _sequential, "Run sequentially; don't do parallel compiles.");
- syntax.DefineOption("t|tag", ref _tag, "Name of root in output directory. Allows for many sets of output.");
- syntax.DefineOption("c|corelib", ref _corelib, "Diff System.Private.CoreLib.dll.");
- syntax.DefineOption("f|frameworks", ref _frameworks, "Diff frameworks.");
- syntax.DefineOption("m|metrics", ref _metric, false, "Comma-separated metric to use for diff computations. Available metrics: CodeSize(default), PerfScore, PrologSize, InstrCount, AllocSize, ExtraAllocBytes, DebugClauseCount, DebugVarCount");
- syntax.DefineOption("benchmarks", ref _benchmarks, "Diff core benchmarks.");
- syntax.DefineOption("tests", ref _tests, "Diff all tests.");
- syntax.DefineOption("gcinfo", ref _gcinfo, "Add GC info to the disasm output.");
- syntax.DefineOption("debuginfo", ref _debuginfo, "Add Debug info to the disasm output.");
- syntax.DefineOption("v|verbose", ref _verbose, "Enable verbose output.");
- syntax.DefineOption("nodiffable", ref _noDiffable, "Generate non-diffable asm (pointer values will be left in output).");
- syntax.DefineOption("core_root", ref _platformPath, "Path to test CORE_ROOT.");
- syntax.DefineOption("test_root", ref _testPath, "Path to test tree. Use with --benchmarks or --tests.");
- syntax.DefineOption("base_root", ref _baseRoot, "Path to root of base dotnet/runtime repo.");
- syntax.DefineOption("diff_root", ref _diffRoot, "Path to root of diff dotnet/runtime repo.");
- syntax.DefineOption("arch", ref _arch, "Architecture to diff (x86, x64).");
- syntax.DefineOption("build", ref _build, "Build flavor to diff (Checked, Debug).");
- syntax.DefineOption("altjit", ref _altjit, "If set, the name of the altjit to use (e.g., clrjit_win_arm64_x64.dll).");
- var pmiOption = syntax.DefineOption("pmi", ref _pmi, "Run asm diffs via pmi.");
- syntax.DefineOption("cctors", ref _cctors, "With --pmi, jit and run cctors before jitting other methods");
- syntax.DefineOptionList("assembly", ref _assemblyList, "Run asm diffs on a given set of assemblies. An individual item can be an assembly or a directory tree containing assemblies.");
- syntax.DefineOption("tsv", ref _tsv, "Dump analysis data to diffs.tsv in output directory.");
- syntax.DefineOption("tier0", ref _tier0, "Diff tier0 codegen where possible.");
-
- // used by jit-analyze
- syntax.DefineOption("count", ref _count, "provide the count parameter to jit-analyze (default 20)");
-
- // List command section.
- syntax.DefineCommand("list", ref _command, Commands.List,
- "List defaults and available tools in " + s_configFileName + ".");
- syntax.DefineOption("v|verbose", ref _verbose, "Enable verbose output.");
-
- // Install command section.
- syntax.DefineCommand("install", ref _command, Commands.Install, "Install tool in " + s_configFileName + ".");
- syntax.DefineOption("j|job", ref _jobName, "Name of the job.");
- syntax.DefineOption("n|number", ref _number, "Job number.");
- syntax.DefineOption("l|last_successful", ref _lastSuccessful, "Last successful build.");
- syntax.DefineOption("b|branch", ref _branchName, "Name of branch.");
- syntax.DefineOption("v|verbose", ref _verbose, "Enable verbose output.");
-
- // Uninstall command section.s
- syntax.DefineCommand("uninstall", ref _command, Commands.Uninstall, "Uninstall tool from " + s_configFileName + ".");
- syntax.DefineOption("t|tag", ref _tag, "Name of tool tag in config file.");
-
- _baseSpecified = baseOption.IsSpecified;
- _diffSpecified = diffOption.IsSpecified;
-
- if (pmiOption.IsSpecified)
+ _baseSpecified = IsSpecified(command.BasePath);
+ if (_baseSpecified)
+ {
+ _basePath = Get(command.BasePath);
+ }
+
+ _diffSpecified = IsSpecified(command.DiffPath);
+ if (_diffSpecified)
+ {
+ _diffPath = Get(command.DiffPath);
+ }
+
+ if (IsSpecified(command.CrossgenExe)) _crossgenExe = Get(command.CrossgenExe);
+ if (IsSpecified(command.OutputPath)) _outputPath = Get(command.OutputPath);
+ if (IsSpecified(command.NoAnalyze)) _noanalyze = Get(command.NoAnalyze);
+ if (IsSpecified(command.Sequential)) _sequential = Get(command.Sequential);
+ if (IsSpecified(command.Tag)) _tag = Get(command.Tag);
+ if (IsSpecified(command.CoreLib)) _corelib = Get(command.CoreLib);
+ if (IsSpecified(command.Frameworks)) _frameworks = Get(command.Frameworks);
+ if (IsSpecified(command.Metric)) _metric = Get(command.Metric);
+ if (IsSpecified(command.Benchmarks)) _benchmarks = Get(command.Benchmarks);
+ if (IsSpecified(command.Tests)) _tests = Get(command.Tests);
+ if (IsSpecified(command.GCInfo)) _gcinfo = Get(command.GCInfo);
+ if (IsSpecified(command.DebugInfo)) _debuginfo = Get(command.DebugInfo);
+ if (IsSpecified(command.Verbose)) _verbose = Get(command.Verbose);
+ if (IsSpecified(command.NoDiffable)) _noDiffable = Get(command.NoDiffable);
+ if (IsSpecified(command.CoreRoot)) _platformPath = Get(command.CoreRoot);
+ if (IsSpecified(command.TestRoot)) _testPath = Get(command.TestRoot);
+ if (IsSpecified(command.BaseRoot)) _baseRoot = Get(command.BaseRoot);
+ if (IsSpecified(command.DiffRoot)) _diffRoot = Get(command.DiffRoot);
+ if (IsSpecified(command.Arch)) _arch = Get(command.Arch);
+ if (IsSpecified(command.Build)) _build = Get(command.Build);
+ if (IsSpecified(command.AltJit)) _altjit = Get(command.AltJit);
+ if (IsSpecified(command.Pmi)) _pmi = Get(command.Pmi);
+ if (IsSpecified(command.Cctors)) _cctors = Get(command.Cctors);
+ if (IsSpecified(command.AssemblyList)) _assemblyList = Get(command.AssemblyList);
+ if (IsSpecified(command.Tsv)) _tsv = Get(command.Tsv);
+ if (IsSpecified(command.Tier0)) _tier0 = Get(command.Tier0);
+ if (IsSpecified(command.Count)) _count = Get(command.Count);
+
+ if (_pmi)
{
_command = Commands.PmiDiff;
}
- });
+ }
+ else if (_command == Commands.List)
+ {
+ if (IsSpecified(command.Verbose)) _verbose = Get(command.Verbose);
+ }
+ else if (_command == Commands.Install)
+ {
+ if (IsSpecified(command.JobName)) _jobName = Get(command.JobName);
+ if (IsSpecified(command.Number)) _number = Get(command.Number);
+ if (IsSpecified(command.LastSuccessful)) _lastSuccessful = Get(command.LastSuccessful);
+ if (IsSpecified(command.BranchName)) _branchName = Get(command.BranchName);
+ if (IsSpecified(command.Verbose)) _verbose = Get(command.Verbose);
+ }
+ else if (_command == Commands.Uninstall)
+ {
+ if (IsSpecified(command.Tag)) _tag = Get(command.Tag);
+ }
SetRID();
@@ -776,7 +779,8 @@ private void Validate()
private void DisplayUsageMessage()
{
Console.Error.WriteLine("");
- Console.Error.Write(_syntaxResult.GetHelpText(100));
+ Console.Error.WriteLine("Usage: jit-diff [options]");
+ Console.Error.WriteLine("Run 'jit-diff --help' for command-specific options.");
if (_command == Commands.Diff)
{
@@ -1348,36 +1352,8 @@ public int ListCommand()
public static int Main(string[] args)
{
- Config config = new Config(args);
- int ret = 0;
-
- switch (config.DoCommand)
- {
- case Commands.Diff:
- case Commands.PmiDiff:
- {
- ret = DiffTool.DiffCommand(config);
- }
- break;
- case Commands.List:
- {
- // List command: list loaded configuration
- ret = config.ListCommand();
- }
- break;
- case Commands.Install:
- {
- ret = InstallCommand(config);
- }
- break;
- case Commands.Uninstall:
- {
- ret = UninstallCommand(config);
- }
- break;
- }
-
- return ret;
+ var command = new JitDiffRootCommand(args).UseVersion();
+ return command.Parse(args).Invoke();
}
}
}
diff --git a/src/jit-diff/jit-diff.csproj b/src/jit-diff/jit-diff.csproj
index 7c7b258e..87773400 100644
--- a/src/jit-diff/jit-diff.csproj
+++ b/src/jit-diff/jit-diff.csproj
@@ -1,14 +1,11 @@
-
-
Exe
-
diff --git a/src/jit-format/JitFormatRootCommand.cs b/src/jit-format/JitFormatRootCommand.cs
new file mode 100644
index 00000000..2d3c4d3d
--- /dev/null
+++ b/src/jit-format/JitFormatRootCommand.cs
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.CommandLine;
+using System.CommandLine.Parsing;
+
+namespace ManagedCodeGen
+{
+ internal sealed class JitFormatRootCommand : RootCommand
+ {
+ public Option Arch { get; } =
+ new("--arch", "-a") { Description = "The architecture of the build (options: arm64, x64, x86)" };
+ public Option OS { get; } =
+ new("--os", "-o") { Description = "The operating system of the build (options: windows, osx, linux, etc.)" };
+ public Option Build { get; } =
+ new("--build", "-b") { Description = "The build type of the build (options: Release, Checked, Debug)" };
+ public Option RuntimePath { get; } =
+ new("--runtime", "-r") { Description = "Full path to runtime directory" };
+ public Option CompileCommands { get; } =
+ new("--compile-commands") { Description = "Full path to compile_commands.json" };
+ public Option Verbose { get; } =
+ new("--verbose") { Description = "Enable verbose output." };
+ public Option Untidy { get; } =
+ new("--untidy") { Description = "Do not run clang-tidy" };
+ public Option NoFormat { get; } =
+ new("--noformat") { Description = "Do not run clang-format" };
+ public Option Cross { get; } =
+ new("--cross") { Description = "If on Linux, run the configure build as a cross build." };
+ public Option Fix { get; } =
+ new("--fix", "-f") { Description = "Fix formatting errors discovered by clang-format and clang-tidy." };
+ public Option IgnoreErrors { get; } =
+ new("--ignore-errors", "-i") { Description = "Ignore clang-tidy errors" };
+ public Option> Projects { get; } =
+ new("--projects") { Description = "List of build projects clang-tidy should consider (e.g. dll, standalone, protojit, etc.). Default: dll" };
+ public Argument> Filenames { get; } =
+ new("filenames") { Description = "Optional list of files that should be formatted." };
+
+ public ParseResult Result { get; private set; }
+
+ public JitFormatRootCommand(string[] args) : base("JIT formatting tool")
+ {
+ Options.Add(Arch);
+ Options.Add(OS);
+ Options.Add(Build);
+ Options.Add(RuntimePath);
+ Options.Add(CompileCommands);
+ Options.Add(Verbose);
+ Options.Add(Untidy);
+ Options.Add(NoFormat);
+ Options.Add(Cross);
+ Options.Add(Fix);
+ Options.Add(IgnoreErrors);
+ Options.Add(Projects);
+ Arguments.Add(Filenames);
+
+ SetAction(result =>
+ {
+ Result = result;
+ return jitformat.Execute(this);
+ });
+ }
+ }
+}
diff --git a/src/jit-format/jit-format.cs b/src/jit-format/jit-format.cs
index 104017e8..4d7ca752 100644
--- a/src/jit-format/jit-format.cs
+++ b/src/jit-format/jit-format.cs
@@ -10,6 +10,7 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
+using System.CommandLine.Parsing;
using System.Diagnostics;
using System.IO;
using System.Linq;
@@ -30,7 +31,6 @@ public class Config
private static string s_configFileName = "config.json";
private static string s_configFileRootKey = "format";
- private ArgumentSyntax _syntaxResult;
private string _arch = null;
private string _os = null;
private string _build = null;
@@ -51,27 +51,29 @@ public class Config
private JsonObject _jObj;
private string _jitUtilsRoot = null;
- public Config(string[] args)
+ internal Config(JitFormatRootCommand command)
{
LoadFileConfig();
- _syntaxResult = ArgumentSyntax.Parse(args, syntax =>
- {
- syntax.DefineOption("a|arch", ref _arch, "The architecture of the build (options: arm64, x64, x86)");
- syntax.DefineOption("o|os", ref _os, "The operating system of the build (options: windows, osx, linux, etc.)");
- syntax.DefineOption("b|build", ref _build, "The build type of the build (options: Release, Checked, Debug)");
- syntax.DefineOption("r|runtime", ref _runtimePath, "Full path to runtime directory");
- syntax.DefineOption("compile-commands", ref _compileCommands, "Full path to compile_commands.json");
- syntax.DefineOption("v|verbose", ref _verbose, "Enable verbose output.");
- syntax.DefineOption("untidy", ref _untidy, "Do not run clang-tidy");
- syntax.DefineOption("noformat", ref _noformat, "Do not run clang-format");
- syntax.DefineOption("cross", ref _cross, "If on Linux, run the configure build as a cross build.");
- syntax.DefineOption("f|fix", ref _fix, "Fix formatting errors discovered by clang-format and clang-tidy.");
- syntax.DefineOption("i|ignore-errors", ref _ignoreErrors, "Ignore clang-tidy errors");
- syntax.DefineOptionList("projects", ref _projects, "List of build projects clang-tidy should consider (e.g. dll, standalone, protojit, etc.). Default: dll");
-
- syntax.DefineParameterList("filenames", ref _filenames, "Optional list of files that should be formatted.");
- });
+ ParseResult result = command.Result;
+
+ bool IsSpecified(Option option) => result.GetResult(option) != null;
+ T Get(Option option) => result.GetValue(option);
+ List GetArgument(Argument> arg) => result.GetValue(arg);
+
+ if (IsSpecified(command.Arch)) _arch = Get(command.Arch);
+ if (IsSpecified(command.OS)) _os = Get(command.OS);
+ if (IsSpecified(command.Build)) _build = Get(command.Build);
+ if (IsSpecified(command.RuntimePath)) _runtimePath = Get(command.RuntimePath);
+ if (IsSpecified(command.CompileCommands)) _compileCommands = Get(command.CompileCommands);
+ if (IsSpecified(command.Verbose)) _verbose = Get(command.Verbose);
+ if (IsSpecified(command.Untidy)) _untidy = Get(command.Untidy);
+ if (IsSpecified(command.NoFormat)) _noformat = Get(command.NoFormat);
+ if (IsSpecified(command.Cross)) _cross = Get(command.Cross);
+ if (IsSpecified(command.Fix)) _fix = Get(command.Fix);
+ if (IsSpecified(command.IgnoreErrors)) _ignoreErrors = Get(command.IgnoreErrors);
+ if (IsSpecified(command.Projects)) _projects = Get(command.Projects);
+ _filenames = GetArgument(command.Filenames);
// Run validation code on parsed input to ensure we have a sensible scenario.
@@ -241,7 +243,7 @@ private void validate()
if (!_untidy && ((_arch == null) || (_os == null) || (_build == null)))
{
- _syntaxResult.ReportError("Specify --arch, --os, and --build for clang-tidy run.");
+ throw new Exception("Specify --arch, --os, and --build for clang-tidy run.");
}
if (_runtimePath == null)
@@ -253,7 +255,7 @@ private void validate()
_runtimePath = Utility.GetRepoRoot(_verbose);
if (_runtimePath == null)
{
- _syntaxResult.ReportError("Specify --runtime");
+ throw new Exception("Specify --runtime");
}
else
{
@@ -265,12 +267,12 @@ private void validate()
if (!Directory.Exists(_coreclrPath))
{
// If _coreclrPath doesn't exist, it is an invalid path
- _syntaxResult.ReportError("Invalid path to runtime directory. Specify with --runtime");
+ throw new Exception("Invalid path to runtime directory. Specify with --runtime");
}
else if (!File.Exists(Path.Combine(_coreclrPath, "build-runtime.cmd")) || !File.Exists(Path.Combine(_coreclrPath, "build-runtime.sh")) || !File.Exists(Path.Combine(_coreclrPath, "clr.featuredefines.props")))
{
// Doesn't look like the coreclr directory.
- _syntaxResult.ReportError("Invalid path to coreclr directory. Specify with --runtime");
+ throw new Exception("Invalid path to coreclr directory. Specify with --runtime");
}
// Check that we can find compile_commands.json on windows
@@ -491,10 +493,10 @@ public CompileCommand(string dir, string cmd, string filename)
}
}
- public static int Main(string[] args)
+ internal static int Execute(JitFormatRootCommand command)
{
// Parse and store comand line options.
- var config = new Config(args);
+ var config = new Config(command);
int returncode = 0;
bool verbose = config.DoVerboseOutput;
@@ -625,6 +627,12 @@ public static int Main(string[] args)
return returncode;
}
+ public static int Main(string[] args)
+ {
+ var command = new JitFormatRootCommand(args).UseVersion();
+ return command.Parse(args).Invoke();
+ }
+
// This method reads in a compile_command.json file, and writes a new json file with only the entries
// commands for files found in the project specified. For example, if project is dll, it will write a
// new compile_commands file (called compile_commands_dll.json) with only the entries whose directory
diff --git a/src/jit-format/jit-format.csproj b/src/jit-format/jit-format.csproj
index 7c7b258e..87773400 100644
--- a/src/jit-format/jit-format.csproj
+++ b/src/jit-format/jit-format.csproj
@@ -1,14 +1,11 @@
-
-
Exe
-
diff --git a/src/jit-include.props b/src/jit-include.props
deleted file mode 100644
index e4a0fd5d..00000000
--- a/src/jit-include.props
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/jit-rl-cse/MLCSE.csproj b/src/jit-rl-cse/MLCSE.csproj
index c5357bb9..65779695 100644
--- a/src/jit-rl-cse/MLCSE.csproj
+++ b/src/jit-rl-cse/MLCSE.csproj
@@ -1,8 +1,5 @@
-
-
-
Exe
enable
diff --git a/src/jit-tp-analyze/Program.cs b/src/jit-tp-analyze/Program.cs
index ae9acac5..2fdc5fae 100644
--- a/src/jit-tp-analyze/Program.cs
+++ b/src/jit-tp-analyze/Program.cs
@@ -124,8 +124,11 @@ private static double GetPercentageDiff(double baseValue, double diffValue) =>
private static string FormatPercentageDiff(double value, string precision = "00") =>
(value > 0 ? "+" : "") + value.ToString($"0.{precision}") + "%";
- private static void Main(string[] args) =>
- new CommandLineConfiguration(new JitTpAnalyzeRootCommand().UseVersion()).Invoke(args);
+ private static void Main(string[] args)
+ {
+ var command = new JitTpAnalyzeRootCommand().UseVersion();
+ command.Parse(args).Invoke();
+ }
private struct FunctionDiff
{
diff --git a/src/jit-tp-analyze/jit-tp-analyze.csproj b/src/jit-tp-analyze/jit-tp-analyze.csproj
index fe8dbbe8..6a70a1ab 100644
--- a/src/jit-tp-analyze/jit-tp-analyze.csproj
+++ b/src/jit-tp-analyze/jit-tp-analyze.csproj
@@ -1,8 +1,5 @@
-
-
-
Exe
diff --git a/src/mutate-test/MutateTestRootCommand.cs b/src/mutate-test/MutateTestRootCommand.cs
index e6ed26b5..bb14301c 100644
--- a/src/mutate-test/MutateTestRootCommand.cs
+++ b/src/mutate-test/MutateTestRootCommand.cs
@@ -7,35 +7,35 @@
namespace MutateTest
{
- internal sealed class MutateTestRootCommand : CliRootCommand
+ internal sealed class MutateTestRootCommand : RootCommand
{
- public CliArgument InputFilePath { get; } =
- new("input-test-case") { Description = "Input test case file or directory (for --recursive)", Arity = ArgumentArity.OneOrMore };
- public CliOption EHStress { get; } =
+ public Argument InputFilePath { get; } =
+ new("input-test-case") { Description = "Input test case file or directory (for --recursive)", Arity = ArgumentArity.ExactlyOne };
+ public Option EHStress { get; } =
new("--ehStress") { Description = "Add EH to methods" };
- public CliOption StructStress { get; } =
+ public Option StructStress { get; } =
new("--structStress") { Description = "Replace locals with structs" };
- public CliOption ShowResults { get; } =
+ public Option ShowResults { get; } =
new("--showResults") { Description = "Add EH to methods" };
- public CliOption Verbose { get; } =
+ public Option Verbose { get; } =
new("--verbose") { Description = "Describe each transformation" };
- public CliOption Quiet { get; } =
+ public Option Quiet { get; } =
new("--quiet") { Description = "Produce minimal output" };
- public CliOption Recursive { get; } =
+ public Option Recursive { get; } =
new("--recursive") { Description = "Process each file recursively" };
- public CliOption Seed { get; } =
+ public Option Seed { get; } =
new("--seed") { DefaultValueFactory = _ => 42, Description = "Random seed" };
- public CliOption StopAtFirstFailure { get; } =
+ public Option StopAtFirstFailure { get; } =
new("--stopAtFirstFailure") { Description = "Stop each test at first failure" };
- public CliOption EmptyBlocks { get; } =
+ public Option EmptyBlocks { get; } =
new("--emptyBlocks") { Description = "Transform empty blocks" };
- public CliOption SizeLimit { get; } =
+ public Option SizeLimit { get; } =
new("--sizeLimit") { DefaultValueFactory = _ => 10000, Description = "Don't process programs larger than this size" };
- public CliOption TimeLimit { get; } =
+ public Option TimeLimit { get; } =
new("--timeLimit") { DefaultValueFactory = _ => 10000, Description = "Don't stress programs where compile + run takes more than this many milliseconds" };
- public CliOption Projects { get; } =
+ public Option Projects { get; } =
new("--projects") { Description = "Look for .csproj files instead of .cs files when doing recursive exploration" };
- public CliOption OnlyFailures { get; } =
+ public Option OnlyFailures { get; } =
new("--onlyFailures") { Description = "Only emit output for cases that fail at runtime" };
public ParseResult Result { get; private set; }
diff --git a/src/mutate-test/Program.cs b/src/mutate-test/Program.cs
index 212a8ba1..6006e466 100644
--- a/src/mutate-test/Program.cs
+++ b/src/mutate-test/Program.cs
@@ -232,13 +232,13 @@ public Program(MutateTestRootCommand command)
private static bool isFirstRun = true;
- private T Get(CliOption option) => _command.Result.GetValue(option);
+ private T Get(Option option) => _command.Result.GetValue(option);
- private static int Main(string[] args) =>
- new CliConfiguration(new MutateTestRootCommand(args).UseVersion())
- {
- EnableParseErrorReporting = true
- }.Invoke(args);
+ private static int Main(string[] args)
+ {
+ var command = new MutateTestRootCommand(args).UseVersion();
+ return command.Parse(args).Invoke();
+ }
public int Run()
{
diff --git a/src/mutate-test/mutate-test.csproj b/src/mutate-test/mutate-test.csproj
index bd600f3a..c09eb2da 100644
--- a/src/mutate-test/mutate-test.csproj
+++ b/src/mutate-test/mutate-test.csproj
@@ -1,10 +1,7 @@
-
-
Exe
- net6.0
Mutate
Mutate
diff --git a/src/performance-explorer/performance-explorer.csproj b/src/performance-explorer/performance-explorer.csproj
index 036eb0f1..87773400 100644
--- a/src/performance-explorer/performance-explorer.csproj
+++ b/src/performance-explorer/performance-explorer.csproj
@@ -1,8 +1,5 @@
-
-
-
Exe
diff --git a/src/pmi/pmi.csproj b/src/pmi/pmi.csproj
index 344ce4c0..89ff5527 100644
--- a/src/pmi/pmi.csproj
+++ b/src/pmi/pmi.csproj
@@ -4,8 +4,6 @@
Exe
-
-
diff --git a/src/superpmi/superpmicollect.csproj b/src/superpmi/superpmicollect.csproj
index 95fdbc0d..52e6553d 100644
--- a/src/superpmi/superpmicollect.csproj
+++ b/src/superpmi/superpmicollect.csproj
@@ -4,6 +4,4 @@
Exe
-
-
diff --git a/src/target-framework.props b/src/target-framework.props
deleted file mode 100644
index c5a6fefa..00000000
--- a/src/target-framework.props
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
- net8.0
-
-
-
diff --git a/src/wasm-spmi-filter/wasm-spmi-filter.csproj b/src/wasm-spmi-filter/wasm-spmi-filter.csproj
index 19d1338a..553d71b4 100644
--- a/src/wasm-spmi-filter/wasm-spmi-filter.csproj
+++ b/src/wasm-spmi-filter/wasm-spmi-filter.csproj
@@ -2,7 +2,6 @@
Exe
- net10.0
wasm_spmi_filter
enable
enable
From 4c1ec85dd84e16cc4df69a5357804e203f9ac5cf Mon Sep 17 00:00:00 2001
From: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Date: Tue, 12 May 2026 12:43:21 +0000
Subject: [PATCH 2/5] Consolidate extended help for diff subcommand
---
src/jit-diff/diff.cs | 6 +-
src/jit-diff/jit-diff.cs | 133 ++++++++++++++++-----------------
src/jit-format/jit-format.cs | 9 +--
src/util/CommandLineHelpers.cs | 45 +++++++++++
4 files changed, 116 insertions(+), 77 deletions(-)
diff --git a/src/jit-diff/diff.cs b/src/jit-diff/diff.cs
index e9cd749c..7a671de8 100644
--- a/src/jit-diff/diff.cs
+++ b/src/jit-diff/diff.cs
@@ -432,14 +432,14 @@ private static int CompareFrameworkAssemblies(AssemblyInfo assemblyInfo1, Assemb
{
string assembly1 = assemblyInfo1.Path;
- if (assembly1 == s_CoreLibAssembly)
+ if (assembly1 == CoreLibAssemblyName)
{
return -1;
}
string assembly2 = assemblyInfo2.Path;
- if (assembly2 == s_CoreLibAssembly)
+ if (assembly2 == CoreLibAssemblyName)
{
return 1;
}
@@ -497,7 +497,7 @@ public static List GenerateAssemblyWorklist(Config config)
if (config.CoreLib || config.DoFrameworks)
{
const bool recursive = false;
- string searchPattern = config.DoFrameworks ? "*" : s_CoreLibAssembly;
+ string searchPattern = config.DoFrameworks ? "*" : CoreLibAssemblyName;
List directoryAssemblyInfoList = IdentifyAssemblies(config.CoreRoot, config.CoreRoot, config, recursive, searchPattern);
directoryAssemblyInfoList.Sort(CompareFrameworkAssemblies);
diff --git a/src/jit-diff/jit-diff.cs b/src/jit-diff/jit-diff.cs
index c395c112..a8fa8b7e 100755
--- a/src/jit-diff/jit-diff.cs
+++ b/src/jit-diff/jit-diff.cs
@@ -5,13 +5,10 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
-using System.CommandLine.Parsing;
using System.IO;
-using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
-using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace ManagedCodeGen
@@ -148,7 +145,7 @@ public class Config
private string _platformName = null;
private string _branchName = null;
private bool _pmi = false;
- private IReadOnlyList _assemblyList = Array.Empty();
+ private IReadOnlyList _assemblyList = [];
private bool _tsv;
private bool _cctors;
private int _count = 20;
@@ -771,65 +768,11 @@ private void Validate()
if (_validationError)
{
- DisplayUsageMessage();
+ jitdiff.DisplayCommandHelp(_command);
Environment.Exit(-1);
}
}
- private void DisplayUsageMessage()
- {
- Console.Error.WriteLine("");
- Console.Error.WriteLine("Usage: jit-diff [options]");
- Console.Error.WriteLine("Run 'jit-diff --help' for command-specific options.");
-
- if (_command == Commands.Diff)
- {
- string[] diffExampleText = {
- @"Examples:",
- @"",
- @" jit-diff diff --output c:\diffs --corelib --core_root c:\runtime\artifacts\tests\coreclr\windows.x64.Release\Tests\Core_Root --base c:\runtime_base\artifacts\bin\coreclr\windows.x64.Checked --diff c:\runtime\artifacts\bin\coreclr\windows.x86.Checked",
- @" Generate diffs of prejitted code for System.Private.CoreLib.dll by specifying baseline and",
- @" diff compiler directories explicitly.",
- @"",
- @" jit-diff diff --output c:\diffs --base c:\runtime_base\artifacts\bin\coreclr\windows.x64.Checked --diff",
- @" If run within the c:\runtime git clone of dotnet/runtime, does the same",
- @" as the prevous example, using defaults.",
- @"",
- @" jit-diff diff --output c:\diffs --base --base_root c:\runtime_base --diff",
- @" Does the same as the prevous example, using -base_root to find the base",
- @" directory (if run from c:\runtime tree).",
- @"",
- @" jit-diff diff --base --diff",
- @" Does the same as the prevous example (if run from c:\runtime tree), but uses",
- @" default c:\runtime\artifacts\diffs output directory, and `base_root` must be specified",
- @" in the config.json file in the directory pointed to by the JIT_UTILS_ROOT",
- @" environment variable.",
- @"",
- @" jit-diff diff --base --diff --pmi",
- @" Does the same as the prevous example (if run from c:\runtime tree)",
- @" but shows diffs for jitted code, via PMI",
- @"",
- @" jit-diff diff --diff",
- @" Only generates asm using the diff JIT -- does not generate asm from a baseline compiler --",
- @" using all computed defaults.",
- @"",
- @" jit-diff diff --diff --pmi --assembly test.exe",
- @" Generates asm using the diff JIT, showing jitted code for all methods",
- @" in the assembly test.exe",
- @"",
- @" jit-diff diff --diff --arch x86",
- @" Generate diffs, but for x86, even if there is an x64 compiler available.",
- @"",
- @" jit-diff diff --diff --build Debug",
- @" Generate diffs, but using a Debug build, even if there is a Checked build available."
- };
- foreach (var line in diffExampleText)
- {
- Console.Error.WriteLine(line);
- }
- }
- }
-
private void DisplayErrorMessage(string error)
{
Console.Error.WriteLine("error: {0}", error);
@@ -976,11 +919,18 @@ public string GetToolPath(string tool, out bool found)
// Extract set value for tool and see if we can find it
// in the installed tools.
var tools = (JsonArray)_jObj[s_configFileRootKey]["tools"];
- var path = tools.Where(x => (string)x["tag"] == tag)
- .Select(x => (string)x["path"]);
- // If the tag resolves to a tool return it, otherwise just return it
- // as a posible path.
- return path.Any() ? path.First() : tag;
+ foreach (JsonNode installedTool in tools)
+ {
+ if ((string)installedTool["tag"] == tag)
+ {
+ // If the tag resolves to a tool, return the resolved path.
+ return (string)installedTool["path"];
+ }
+ }
+
+ // If the tag doesn't resolve to an installed tool, return it as
+ // a possible path.
+ return tag;
}
found = false;
@@ -1348,13 +1298,62 @@ public int ListCommand()
"V8"
};
- private static string s_CoreLibAssembly = "System.Private.CoreLib.dll";
+ private const string CoreLibAssemblyName = "System.Private.CoreLib.dll";
+
+ private static RootCommand CreateRootCommand(string[] args) =>
+ new JitDiffRootCommand(args)
+ .UseVersion()
+ .UseExtendedHelp(PrintExtendedHelp);
+
+ internal static void DisplayCommandHelp(Commands command)
+ {
+ string[] helpArgs = command switch
+ {
+ Commands.Diff or Commands.PmiDiff => ["diff", "--help"],
+ Commands.List => ["list", "--help"],
+ Commands.Install => ["install", "--help"],
+ Commands.Uninstall => ["uninstall", "--help"],
+ _ => ["--help"]
+ };
+
+ CreateRootCommand([]).Parse(helpArgs).Invoke();
+ }
+
+ public static void PrintExtendedHelp(ParseResult parseResult)
+ {
+ if (!string.Equals(parseResult.CommandResult.Command.Name, "diff", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+
+ Console.WriteLine("""
+
+ Examples:
+
+ jit-diff diff --output c:\diffs --corelib --core_root c:\runtime\artifacts\tests\coreclr\windows.x64.Release\Tests\Core_Root --base c:\runtime_base\artifacts\bin\coreclr\windows.x64.Checked --diff c:\runtime\artifacts\bin\coreclr\windows.x64.Checked
+ Generate corelib prejit diffs by specifying explicit baseline and diff compiler directories.
+
+ jit-diff diff --output c:\diffs --base --base_root c:\runtime_base --diff
+ If run from a dotnet/runtime clone, infer the remaining paths and architecture/build defaults.
+
+ jit-diff diff --base --diff
+ Same as above, but use the default output directory under artifacts\diffs.
+
+ jit-diff diff --base --diff --pmi
+ Diff jitted code via PMI instead of prejitting with crossgen.
+
+ jit-diff diff --diff --pmi --assembly test.exe
+ Diff all jitted methods for a specific assembly.
+
+ jit-diff diff --diff --arch x86
+ Force x86 diffs even when x64 defaults are available.
+ """);
+ }
public static int Main(string[] args)
{
- var command = new JitDiffRootCommand(args).UseVersion();
+ var command = CreateRootCommand(args);
return command.Parse(args).Invoke();
}
}
}
-
diff --git a/src/jit-format/jit-format.cs b/src/jit-format/jit-format.cs
index 4d7ca752..bf508d43 100644
--- a/src/jit-format/jit-format.cs
+++ b/src/jit-format/jit-format.cs
@@ -2,11 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-///////////////////////////////////////////////////////////////////////////////
-//
-// jit-format -
-//
-
using System;
using System.Collections.Generic;
using System.CommandLine;
@@ -36,8 +31,8 @@ public class Config
private string _build = null;
private string _runtimePath = null;
private string _coreclrPath = null;
- private IReadOnlyList _filenames = Array.Empty();
- private IReadOnlyList _projects = Array.Empty();
+ private IReadOnlyList _filenames = [];
+ private IReadOnlyList _projects = [];
private string _srcDirectory = null;
private bool _untidy = false;
private bool _noformat = false;
diff --git a/src/util/CommandLineHelpers.cs b/src/util/CommandLineHelpers.cs
index fd1793e5..d661cb15 100644
--- a/src/util/CommandLineHelpers.cs
+++ b/src/util/CommandLineHelpers.cs
@@ -2,7 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using System.CommandLine;
+using System.CommandLine.Help;
+using System.CommandLine.Invocation;
using System.CommandLine.Parsing;
using System.IO;
@@ -22,6 +25,48 @@ public static RootCommand UseVersion(this RootCommand command)
return command;
}
+ public static RootCommand UseExtendedHelp(this RootCommand command, Action customizer)
+ {
+ ConfigureHelp(command, customizer);
+ return command;
+ }
+
+ private static void ConfigureHelp(Command command, Action customizer)
+ {
+ foreach (Option option in command.Options)
+ {
+ if (option is HelpOption helpOption)
+ {
+ helpOption.Action = new CustomizedHelpAction(helpOption, customizer);
+ break;
+ }
+ }
+
+ foreach (Command subcommand in command.Subcommands)
+ {
+ ConfigureHelp(subcommand, customizer);
+ }
+ }
+
+ private sealed class CustomizedHelpAction : SynchronousCommandLineAction
+ {
+ private readonly HelpAction _helpAction;
+ private readonly Action _customizer;
+
+ public CustomizedHelpAction(HelpOption helpOption, Action customizer)
+ {
+ _helpAction = (HelpAction)helpOption.Action;
+ _customizer = customizer;
+ }
+
+ public override int Invoke(ParseResult parseResult)
+ {
+ int result = _helpAction.Invoke(parseResult);
+ _customizer(parseResult);
+ return result;
+ }
+ }
+
#nullable enable
public static string? GetResolvedPath(ArgumentResult result) =>
result.Tokens.Count > 0 ? Path.GetFullPath(result.Tokens[0].Value) : null;
From 699d906aca6f63307f97df38582520fa685e2068 Mon Sep 17 00:00:00 2001
From: Adeel <3840695+am11@users.noreply.github.com>
Date: Fri, 5 Jun 2026 02:02:28 +0300
Subject: [PATCH 3/5] Update Antigen to the same plan
---
NuGet.Config | 1 -
src/Antigen/Antigen/Antigen.cs | 38 ++++++----------
src/Antigen/Antigen/Antigen.csproj | 14 +-----
src/Antigen/Antigen/AntigenRootCommand.cs | 37 ++++++++++++++++
src/Antigen/Antigen/Config/RunOptions.cs | 16 +++++--
.../ExecutionEngine/DynamicAssemblyLoader.cs | 2 +-
.../ExecutionEngine/ExecutionEngine.csproj | 5 ---
src/Antigen/ExecutionEngine/Program.cs | 19 ++++----
.../Rewriters/Statements/SyntaxRewriter.cs | 4 +-
src/Antigen/Trimmer/TestTrimmer.cs | 25 +++++++----
src/Antigen/Trimmer/Trimmer.csproj | 4 +-
src/Antigen/Trimmer/TrimmerRootCommand.cs | 43 +++++++++++++++++++
.../Utilities/Compilation/CompileResult.cs | 12 +++---
src/Antigen/Utilities/Compilation/Compiler.cs | 6 +--
src/Antigen/Utilities/Execution/EEDriver.cs | 4 +-
src/Antigen/Utilities/Execution/EEProxy.cs | 10 +++--
.../Utilities/Execution/ExecuteResult.cs | 16 +++----
src/Antigen/Utilities/RequestResponse.cs | 6 +--
src/Antigen/Utilities/RslnUtilities.cs | 2 +-
src/Antigen/Utilities/TestRunner.cs | 6 +--
src/Antigen/Utilities/Utilities.csproj | 6 +--
src/mutate-test/mutate-test.csproj | 9 ++--
src/util/CommandLineHelpers.cs | 4 +-
23 files changed, 179 insertions(+), 110 deletions(-)
create mode 100644 src/Antigen/Antigen/AntigenRootCommand.cs
create mode 100644 src/Antigen/Trimmer/TrimmerRootCommand.cs
diff --git a/NuGet.Config b/NuGet.Config
index 1c5a35f1..3f9f7ab4 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -3,7 +3,6 @@
-
diff --git a/src/Antigen/Antigen/Antigen.cs b/src/Antigen/Antigen/Antigen.cs
index e87a8d57..e45bdc72 100644
--- a/src/Antigen/Antigen/Antigen.cs
+++ b/src/Antigen/Antigen/Antigen.cs
@@ -4,7 +4,8 @@
using System.IO;
using System.Threading.Tasks;
using Antigen.Config;
-using CommandLine;
+using System.CommandLine;
+using System.CommandLine.Parsing;
using Utils;
using System.Linq;
using System.Runtime.CompilerServices;
@@ -38,23 +39,27 @@ class Program
static int Main(string[] args)
{
- return Parser.Default.ParseArguments(args).MapResult(Run, err => 1);
+ var command = new AntigenRootCommand(args).UseVersion();
+ return command.Parse(args).Invoke();
}
- private static int Run(CommandLineOptions opts)
+ internal static int Run(AntigenRootCommand command)
{
try
{
+ ParseResult result = command.Result;
PRNG.Initialize(s_runOptions.Seed);
- s_runOptions.CoreRun = opts.CoreRunPath;
- s_runOptions.OutputDirectory = opts.IssuesFolder;
- if (opts.RunDuration > 0)
+ s_runOptions.CoreRun = result.GetValue(command.CoreRunPath);
+ s_runOptions.OutputDirectory = result.GetValue(command.IssuesFolder);
+ int runDuration = result.GetValue(command.RunDuration);
+ if (runDuration > 0)
{
- s_runOptions.RunDuration = opts.RunDuration;
+ s_runOptions.RunDuration = runDuration;
}
- if (opts.NumTestCases > 0)
+ int numTestCases = result.GetValue(command.NumTestCases);
+ if (numTestCases > 0)
{
- s_runOptions.NumTestCases = opts.NumTestCases;
+ s_runOptions.NumTestCases = numTestCases;
}
if (s_runOptions.RunDuration != -1)
@@ -295,19 +300,4 @@ static void RunTest()
}
}
}
-
- public class CommandLineOptions
- {
- [Option(shortName: 'c', longName: "CoreRun", Required = true, HelpText = "Full path to CoreRun/CoreRun.exe.")]
- public string CoreRunPath { get; set; }
-
- [Option(shortName: 'o', longName: "IssuesFolder", Required = true, HelpText = "Full path to folder where issues will be copied.")]
- public string IssuesFolder { get; set; }
-
- [Option(shortName: 'n', longName: "NumTestCases", Required = false, HelpText = "Number of test cases to execute. By default, 1000.")]
- public int NumTestCases { get; set; }
-
- [Option(shortName: 'd', longName: "RunDuration", Required = false, HelpText = "Duration in minutes to run. By default until NumTestCases, but if Duration is given, will override the NumTestCases.")]
- public int RunDuration { get; set; }
- }
}
diff --git a/src/Antigen/Antigen/Antigen.csproj b/src/Antigen/Antigen/Antigen.csproj
index a2aee0a9..c72d3a78 100644
--- a/src/Antigen/Antigen/Antigen.csproj
+++ b/src/Antigen/Antigen/Antigen.csproj
@@ -2,30 +2,20 @@
Exe
- net9.0
Antigen
ab71806a-3bd8-4fb1-b0e2-9450aec41a9f
True
-
-
-
-
+
+
-
- false
-
- https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json
-
-
-
diff --git a/src/Antigen/Antigen/AntigenRootCommand.cs b/src/Antigen/Antigen/AntigenRootCommand.cs
new file mode 100644
index 00000000..74b0b285
--- /dev/null
+++ b/src/Antigen/Antigen/AntigenRootCommand.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+
+namespace Antigen
+{
+ internal sealed class AntigenRootCommand : RootCommand
+ {
+ public Option CoreRunPath { get; } =
+ new("--CoreRun", "-c") { Description = "Full path to CoreRun/CoreRun.exe.", Required = true };
+ public Option IssuesFolder { get; } =
+ new("--IssuesFolder", "-o") { Description = "Full path to folder where issues will be copied.", Required = true };
+ public Option NumTestCases { get; } =
+ new("--NumTestCases", "-n") { Description = "Number of test cases to execute. By default, 1000." };
+ public Option RunDuration { get; } =
+ new("--RunDuration", "-d") { Description = "Duration in minutes to run. By default until NumTestCases, but if Duration is given, will override the NumTestCases." };
+
+ public ParseResult Result { get; private set; }
+
+ public AntigenRootCommand(string[] args) : base("Antigen JIT fuzzer")
+ {
+ Options.Add(CoreRunPath);
+ Options.Add(IssuesFolder);
+ Options.Add(NumTestCases);
+ Options.Add(RunDuration);
+
+ SetAction(result =>
+ {
+ Result = result;
+ return Program.Run(this);
+ });
+ }
+ }
+}
diff --git a/src/Antigen/Antigen/Config/RunOptions.cs b/src/Antigen/Antigen/Config/RunOptions.cs
index 537bad2a..298c424d 100644
--- a/src/Antigen/Antigen/Config/RunOptions.cs
+++ b/src/Antigen/Antigen/Config/RunOptions.cs
@@ -4,7 +4,8 @@
using System.IO;
using System.Reflection;
using System.Runtime.Intrinsics;
-using Newtonsoft.Json;
+using System.Text.Json;
+using System.Text.Json.Serialization;
namespace Antigen.Config
{
@@ -25,7 +26,7 @@ public class RunOptions
// Percent of time to execute baseline
public double ExecuteBaseline;
- [NonSerialized()]
+ [JsonIgnore]
public string CoreRun = null;
public List Configs;
@@ -40,7 +41,16 @@ internal static RunOptions Initialize()
string antiGenConfig = Path.Combine(currentDirectory, "Config", "antigen.json");
Debug.Assert(File.Exists(antiGenConfig));
- var runOption = JsonConvert.DeserializeObject(File.ReadAllText(antiGenConfig));
+ JsonSerializerOptions options = new()
+ {
+ IncludeFields = true,
+ PropertyNameCaseInsensitive = true,
+ ReadCommentHandling = JsonCommentHandling.Skip,
+ AllowTrailingCommas = true,
+ NumberHandling = JsonNumberHandling.AllowReadingFromString,
+ };
+
+ var runOption = JsonSerializer.Deserialize(File.ReadAllText(antiGenConfig), options);
EnvVarOptions.Initialize(runOption.BaselineEnvVars, runOption.TestEnvVars);
return runOption;
diff --git a/src/Antigen/ExecutionEngine/DynamicAssemblyLoader.cs b/src/Antigen/ExecutionEngine/DynamicAssemblyLoader.cs
index 739ae469..f472bc51 100644
--- a/src/Antigen/ExecutionEngine/DynamicAssemblyLoader.cs
+++ b/src/Antigen/ExecutionEngine/DynamicAssemblyLoader.cs
@@ -21,7 +21,7 @@ public Assembly LoadFromBytes(byte[] assemblyBytes)
return LoadFromStream(new MemoryStream(assemblyBytes));
}
- protected override Assembly Load(AssemblyName assemblyName)
+ protected override Assembly? Load(AssemblyName assemblyName)
{
// Default implementation does nothing.
return null;
diff --git a/src/Antigen/ExecutionEngine/ExecutionEngine.csproj b/src/Antigen/ExecutionEngine/ExecutionEngine.csproj
index 6a3b4868..a76f3d0a 100644
--- a/src/Antigen/ExecutionEngine/ExecutionEngine.csproj
+++ b/src/Antigen/ExecutionEngine/ExecutionEngine.csproj
@@ -2,15 +2,10 @@
Exe
- net9.0
enable
enable
-
-
-
-
diff --git a/src/Antigen/ExecutionEngine/Program.cs b/src/Antigen/ExecutionEngine/Program.cs
index 2afb3fd3..76e15dc9 100644
--- a/src/Antigen/ExecutionEngine/Program.cs
+++ b/src/Antigen/ExecutionEngine/Program.cs
@@ -8,8 +8,7 @@
using System.Reflection.Metadata;
using System.Runtime.ExceptionServices;
using System.Threading;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
+using System.Text.Json;
namespace ExecutionEngine
{
@@ -38,7 +37,7 @@ static async Task Main(string[] args)
{
continue;
}
- Request? request = JsonConvert.DeserializeObject(lines);
+ Request? request = JsonSerializer.Deserialize(lines);
if (request == null)
{
continue;
@@ -61,7 +60,7 @@ static async Task Main(string[] args)
response.IsJitAssert = true;
}
- var json = JsonConvert.SerializeObject(response);
+ var json = JsonSerializer.Serialize(response);
Console.WriteLine(json);
Console.Out.Flush();
Console.WriteLine("Done");
@@ -86,13 +85,13 @@ private static RunResult Run(byte[] assemblyBytes)
{
int hashCode;
var assembly = s_loader.LoadFromBytes(assemblyBytes);
- var methodInfo = assembly.GetType("TestClass").GetMethod("Main");
- var methodExec = methodInfo.CreateDelegate>();
+ var methodInfo = assembly.GetType("TestClass")!.GetMethod("Main");
+ var methodExec = methodInfo!.CreateDelegate>();
// Adopted from Jakob's Fuzzlyn
int threadID = Environment.CurrentManagedThreadId;
- List exceptions = null;
- void FirstChanceExceptionHandler(object sender, FirstChanceExceptionEventArgs args)
+ List? exceptions = null;
+ void FirstChanceExceptionHandler(object? sender, FirstChanceExceptionEventArgs args)
{
if (Environment.CurrentManagedThreadId == threadID)
{
@@ -104,7 +103,7 @@ void FirstChanceExceptionHandler(object sender, FirstChanceExceptionEventArgs ar
try
{
- hashCode = methodExec(null);
+ hashCode = methodExec(null!);
}
catch
{
@@ -123,7 +122,7 @@ void FirstChanceExceptionHandler(object sender, FirstChanceExceptionEventArgs ar
// }
// We are interested in the JIT assert that was hit, and not the OverflowException
// thrown because value = 1 did not get to run.
- Exception ex = exceptions[0];
+ Exception ex = exceptions![0];
if (ex is TypeInitializationException && ex.InnerException != null)
{
diff --git a/src/Antigen/Trimmer/Rewriters/Statements/SyntaxRewriter.cs b/src/Antigen/Trimmer/Rewriters/Statements/SyntaxRewriter.cs
index b9dcd76e..2e5fe0b5 100644
--- a/src/Antigen/Trimmer/Rewriters/Statements/SyntaxRewriter.cs
+++ b/src/Antigen/Trimmer/Rewriters/Statements/SyntaxRewriter.cs
@@ -44,8 +44,8 @@ public void UpdateId(int newId)
public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
{
- if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia ||
- trivia.Kind() == SyntaxKind.MultiLineCommentTrivia)
+ if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) ||
+ trivia.IsKind(SyntaxKind.MultiLineCommentTrivia))
{
return default(SyntaxTrivia);
}
diff --git a/src/Antigen/Trimmer/TestTrimmer.cs b/src/Antigen/Trimmer/TestTrimmer.cs
index ee3db30b..2d863409 100644
--- a/src/Antigen/Trimmer/TestTrimmer.cs
+++ b/src/Antigen/Trimmer/TestTrimmer.cs
@@ -7,11 +7,12 @@
using Antigen.Trimmer.Rewriters;
using Antigen.Trimmer.Rewriters.Expressions;
using Antigen.Trimmer.Rewriters.Statements;
-using CommandLine;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System;
using System.Collections.Generic;
+using System.CommandLine;
+using System.CommandLine.Parsing;
using System.Diagnostics;
using System.IO;
using System.Linq;
@@ -52,11 +53,23 @@ public class TestTrimmer
static int Main(string[] args)
{
- return Parser.Default.ParseArguments(args).MapResult(Run, err => 1);
+ var command = new TrimmerRootCommand(args).UseVersion();
+ return command.Parse(args).Invoke();
}
- private static int Run(CommandLineOptions opts)
+ internal static int Run(TrimmerRootCommand command)
{
+ ParseResult result = command.Result;
+ CommandLineOptions opts = new()
+ {
+ CoreRunPath = result.GetValue(command.CoreRunPath),
+ ParentPid = result.GetValue(command.ParentPid),
+ IssuesFolder = result.GetValue(command.IssuesFolder),
+ ReproFile = result.GetValue(command.ReproFile),
+ AltJitName = result.GetValue(command.AltJitName),
+ AltJitMethodName = result.GetValue(command.AltJitMethodName),
+ };
+
int.TryParse(opts.ParentPid, out s_parentProcessId);
Task monitorTask = Task.Run(() => MonitorParentProcess());
@@ -615,22 +628,16 @@ private static void MonitorParentProcess()
public class CommandLineOptions
{
- [Option(shortName: 'c', longName: "CoreRun", Required = true, HelpText = "Path to CoreRun/CoreRun.exe.")]
public string CoreRunPath { get; set; }
- [Option(shortName: 'p', longName: "ParentPid", Required = false, HelpText = "Antigen process id")]
public string ParentPid { get; set; }
- [Option(shortName: 'o', longName: "IssuesFolder", Required = false, HelpText = "Path to folder where trimmed issue will be copied.")]
public string IssuesFolder { get; set; }
- [Option(shortName: 'f', longName: "ReproFile", Required = false, HelpText = "Full path of the repro file.")]
public string ReproFile { get; set; }
- [Option(shortName: 'j', longName: "AltJitName", Required = false, HelpText = "Name of altjit. By default, current OS/arch.")]
public string AltJitName { get; set; }
- [Option(shortName: 'm', longName: "AltJitMethodName", Required = false, HelpText = "Name of method for altjit. By default, current OS/arch.")]
public string AltJitMethodName { get; set; }
}
}
diff --git a/src/Antigen/Trimmer/Trimmer.csproj b/src/Antigen/Trimmer/Trimmer.csproj
index 4c6a9edd..05cd19b4 100644
--- a/src/Antigen/Trimmer/Trimmer.csproj
+++ b/src/Antigen/Trimmer/Trimmer.csproj
@@ -2,13 +2,11 @@
Exe
- net9.0
True
-
-
+
diff --git a/src/Antigen/Trimmer/TrimmerRootCommand.cs b/src/Antigen/Trimmer/TrimmerRootCommand.cs
new file mode 100644
index 00000000..3508cd1f
--- /dev/null
+++ b/src/Antigen/Trimmer/TrimmerRootCommand.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.CommandLine;
+using System.CommandLine.Parsing;
+
+namespace Trimmer
+{
+ internal sealed class TrimmerRootCommand : RootCommand
+ {
+ public Option CoreRunPath { get; } =
+ new("--CoreRun", "-c") { Description = "Path to CoreRun/CoreRun.exe.", Required = true };
+ public Option ParentPid { get; } =
+ new("--ParentPid", "-p") { Description = "Antigen process id" };
+ public Option IssuesFolder { get; } =
+ new("--IssuesFolder", "-o") { Description = "Path to folder where trimmed issue will be copied." };
+ public Option ReproFile { get; } =
+ new("--ReproFile", "-f") { Description = "Full path of the repro file." };
+ public Option AltJitName { get; } =
+ new("--AltJitName", "-j") { Description = "Name of altjit. By default, current OS/arch." };
+ public Option AltJitMethodName { get; } =
+ new("--AltJitMethodName", "-m") { Description = "Name of method for altjit. By default, current OS/arch." };
+
+ public ParseResult Result { get; private set; }
+
+ public TrimmerRootCommand(string[] args) : base("Antigen test case trimmer")
+ {
+ Options.Add(CoreRunPath);
+ Options.Add(ParentPid);
+ Options.Add(IssuesFolder);
+ Options.Add(ReproFile);
+ Options.Add(AltJitName);
+ Options.Add(AltJitMethodName);
+
+ SetAction(result =>
+ {
+ Result = result;
+ return TestTrimmer.Run(this);
+ });
+ }
+ }
+}
diff --git a/src/Antigen/Utilities/Compilation/CompileResult.cs b/src/Antigen/Utilities/Compilation/CompileResult.cs
index cc5c2248..c0916160 100644
--- a/src/Antigen/Utilities/Compilation/CompileResult.cs
+++ b/src/Antigen/Utilities/Compilation/CompileResult.cs
@@ -19,7 +19,7 @@ public CompileResult(IEnumerable diagnostics)
CompileWarnings = diagnostics.Where(diag => diag.Severity == DiagnosticSeverity.Warning);
}
- public CompileResult(string assemblyName, string assemblyFullPath, byte[]? debugMs, byte[]? releaseMs)
+ public CompileResult(string assemblyName, string? assemblyFullPath, byte[]? debugMs, byte[]? releaseMs)
{
AssemblyName = assemblyName;
AssemblyFullPath = assemblyFullPath;
@@ -32,11 +32,11 @@ public CompileResult(Exception roslynException)
RoslynException = roslynException;
}
- public string AssemblyName { get; }
- public Exception RoslynException { get; }
- public IEnumerable CompileErrors { get; }
- public IEnumerable CompileWarnings { get; }
- public string AssemblyFullPath { get; }
+ public string? AssemblyName { get; }
+ public Exception? RoslynException { get; }
+ public IEnumerable? CompileErrors { get; }
+ public IEnumerable? CompileWarnings { get; }
+ public string? AssemblyFullPath { get; }
public byte[]? DebugAssembly { get; }
public byte[]? ReleaseAssembly { get; }
}
diff --git a/src/Antigen/Utilities/Compilation/Compiler.cs b/src/Antigen/Utilities/Compilation/Compiler.cs
index 645e310e..ded1ce22 100644
--- a/src/Antigen/Utilities/Compilation/Compiler.cs
+++ b/src/Antigen/Utilities/Compilation/Compiler.cs
@@ -39,8 +39,8 @@ public class Compiler
private static readonly MetadataReference[] s_references =
{
MetadataReference.CreateFromFile(s_corelibPath),
- MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath), "System.Console.dll")),
- MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath), "System.Runtime.dll")),
+ MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath)!, "System.Console.dll")),
+ MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath)!, "System.Runtime.dll")),
MetadataReference.CreateFromFile(typeof(SyntaxTree).Assembly.Location),
MetadataReference.CreateFromFile(typeof(CSharpSyntaxTree).Assembly.Location),
};
@@ -63,7 +63,7 @@ public CompileResult Compile(SyntaxTree programTree, string assemblyName)
return new CompileResult(assemblyName, null, debugBytes, releaseBytes);
}
- private byte[] CompileAndGetBytes(SyntaxTree programTree, string assemblyName, CSharpCompilationOptions options)
+ private byte[]? CompileAndGetBytes(SyntaxTree programTree, string assemblyName, CSharpCompilationOptions options)
{
string tag = options.OptimizationLevel == OptimizationLevel.Debug ? "Debug" : "Release";
var cc = CSharpCompilation.Create($"{assemblyName}-{tag}.exe", new SyntaxTree[] { programTree }, s_references, options);
diff --git a/src/Antigen/Utilities/Execution/EEDriver.cs b/src/Antigen/Utilities/Execution/EEDriver.cs
index 155d4988..4a2fb57e 100644
--- a/src/Antigen/Utilities/Execution/EEDriver.cs
+++ b/src/Antigen/Utilities/Execution/EEDriver.cs
@@ -97,9 +97,9 @@ private void Return(EEProxy proxy)
///
///
///
- internal Response Execute(Request request)
+ internal Response? Execute(Request request)
{
- EEProxy proxy = null;
+ EEProxy? proxy = null;
try
{
proxy = Get();
diff --git a/src/Antigen/Utilities/Execution/EEProxy.cs b/src/Antigen/Utilities/Execution/EEProxy.cs
index c9f9fced..5083e358 100644
--- a/src/Antigen/Utilities/Execution/EEProxy.cs
+++ b/src/Antigen/Utilities/Execution/EEProxy.cs
@@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
@@ -14,7 +15,7 @@
using System.Threading.Tasks;
//using Antigen.Config;
using ExecutionEngine;
-using Newtonsoft.Json;
+using System.Text.Json;
using Utils;
namespace Antigen.Execution
@@ -54,6 +55,7 @@ private EEProxy(string host, string executionEngine, Dictionary
_testCaseExecutionCount = 0;
}
+ [MemberNotNull(nameof(_envVars), nameof(_envVarsList))]
private void SetEnvironmentVariables(ProcessStartInfo startInfo, Dictionary envVars)
{
envVars["DOTNET_TieredCompilation"] = "0";
@@ -96,7 +98,7 @@ public static EEProxy GetInstance(string host, string executionEngine, Dictionar
public Response Execute(Request request)
{
- _process.StandardInput.WriteLine(JsonConvert.SerializeObject(request));
+ _process.StandardInput.WriteLine(JsonSerializer.Serialize(request));
bool killed = false;
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(TimeoutInSeconds));
@@ -104,7 +106,7 @@ public Response Execute(Request request)
StringBuilder responseReader = new StringBuilder();
while (true)
{
- string line = _process.StandardOutput.ReadLine();
+ string? line = _process.StandardOutput.ReadLine();
if ((line == null) || (line == "Done"))
{
break;
@@ -124,7 +126,7 @@ public Response Execute(Request request)
try
{
- return JsonConvert.DeserializeObject(responseReader.ToString());
+ return JsonSerializer.Deserialize(responseReader.ToString()) ?? new() { HasCrashed = true };
}
catch (JsonException)
{
diff --git a/src/Antigen/Utilities/Execution/ExecuteResult.cs b/src/Antigen/Utilities/Execution/ExecuteResult.cs
index 7655a785..174ad69a 100644
--- a/src/Antigen/Utilities/Execution/ExecuteResult.cs
+++ b/src/Antigen/Utilities/Execution/ExecuteResult.cs
@@ -23,18 +23,18 @@ public enum RunOutcome
public struct ExecuteResult
{
- public string OtherErrorMessage { get; private set; }
- public string AssertionMessage { get; private set; }
- public string ShortAssertionText { get; private set; }
+ public string? OtherErrorMessage { get; private set; }
+ public string? AssertionMessage { get; private set; }
+ public string? ShortAssertionText { get; private set; }
public RunOutcome Result { get; private set; }
- public IReadOnlyList> EnvVars { get; private set; }
+ public IReadOnlyList>? EnvVars { get; private set; }
public static ExecuteResult GetSuccessResult()
{
return new ExecuteResult(RunOutcome.Success, null);
}
- public static ExecuteResult GetOtherErrorResult(string errorMessage, IReadOnlyList> envVars)
+ public static ExecuteResult GetOtherErrorResult(string? errorMessage, IReadOnlyList>? envVars)
{
return new ExecuteResult(RunOutcome.OtherError, null, errorMessage, envVars);
}
@@ -44,14 +44,14 @@ public static ExecuteResult GetTimeoutResult()
return new ExecuteResult(RunOutcome.Timeout, null);
}
- public static ExecuteResult GetAssertionFailureResult(string assertionMessage, IReadOnlyList> envVars)
+ public static ExecuteResult GetAssertionFailureResult(string assertionMessage, IReadOnlyList>? envVars)
{
var result = new ExecuteResult(RunOutcome.AssertionFailure, assertionMessage, null, envVars);
result.ShortAssertionText = RslnUtilities.ParseAssertionError(assertionMessage);
return result;
}
- public static ExecuteResult GetOutputMismatchResult(string outputDiff, IReadOnlyList> envVars)
+ public static ExecuteResult GetOutputMismatchResult(string outputDiff, IReadOnlyList>? envVars)
{
return new ExecuteResult(RunOutcome.OutputMismatch, null, outputDiff, envVars);
}
@@ -61,7 +61,7 @@ public static ExecuteResult GetCompilationError()
return new ExecuteResult(RunOutcome.CompilationError, null);
}
- private ExecuteResult(RunOutcome result, string assertionMessage, string errorMessage = null, IReadOnlyList> envVars = null)
+ private ExecuteResult(RunOutcome result, string? assertionMessage, string? errorMessage = null, IReadOnlyList>? envVars = null)
{
Result = result;
AssertionMessage = assertionMessage;
diff --git a/src/Antigen/Utilities/RequestResponse.cs b/src/Antigen/Utilities/RequestResponse.cs
index 598bb6be..045f13d6 100644
--- a/src/Antigen/Utilities/RequestResponse.cs
+++ b/src/Antigen/Utilities/RequestResponse.cs
@@ -13,8 +13,8 @@ namespace ExecutionEngine
{
public class Request
{
- public byte[] Debug { get; set; }
- public byte[] Release { get; set; }
+ public byte[] Debug { get; set; } = [];
+ public byte[] Release { get; set; } = [];
}
public class Response
@@ -26,6 +26,6 @@ public class Response
public bool IsTimeout { get; set; }
public bool IsJitAssert { get; set; }
public bool HasCrashed { get; set; }
- public IReadOnlyList> EnvironmentVariables { get; set; }
+ public IReadOnlyList>? EnvironmentVariables { get; set; }
}
}
diff --git a/src/Antigen/Utilities/RslnUtilities.cs b/src/Antigen/Utilities/RslnUtilities.cs
index bc4be7a8..5ce49f28 100644
--- a/src/Antigen/Utilities/RslnUtilities.cs
+++ b/src/Antigen/Utilities/RslnUtilities.cs
@@ -73,7 +73,7 @@ private static void FindTreeDiff(SyntaxNode expected, SyntaxNode actual)
///
///
///
- public static string ParseAssertionError(string output)
+ public static string? ParseAssertionError(string output)
{
if (string.IsNullOrEmpty(output))
{
diff --git a/src/Antigen/Utilities/TestRunner.cs b/src/Antigen/Utilities/TestRunner.cs
index ab611f41..495dc7f1 100644
--- a/src/Antigen/Utilities/TestRunner.cs
+++ b/src/Antigen/Utilities/TestRunner.cs
@@ -35,7 +35,7 @@ public enum TestResult
public class TestRunner
{
- private static TestRunner _testRunner;
+ private static TestRunner? _testRunner;
private readonly string _coreRun;
private readonly EEDriver _driver;
@@ -43,8 +43,8 @@ public class TestRunner
private static readonly MetadataReference[] s_references =
{
MetadataReference.CreateFromFile(s_corelibPath),
- MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath), "System.Console.dll")),
- MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath), "System.Runtime.dll")),
+ MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath)!, "System.Console.dll")),
+ MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath)!, "System.Runtime.dll")),
MetadataReference.CreateFromFile(typeof(SyntaxTree).Assembly.Location),
MetadataReference.CreateFromFile(typeof(CSharpSyntaxTree).Assembly.Location),
};
diff --git a/src/Antigen/Utilities/Utilities.csproj b/src/Antigen/Utilities/Utilities.csproj
index 74528279..7de5e0e0 100644
--- a/src/Antigen/Utilities/Utilities.csproj
+++ b/src/Antigen/Utilities/Utilities.csproj
@@ -1,16 +1,12 @@
- net9.0
enable
enable
-
-
-
+
-
diff --git a/src/mutate-test/mutate-test.csproj b/src/mutate-test/mutate-test.csproj
index c09eb2da..f1c92093 100644
--- a/src/mutate-test/mutate-test.csproj
+++ b/src/mutate-test/mutate-test.csproj
@@ -7,9 +7,12 @@
-
-
-
+
+
+
+
+
diff --git a/src/util/CommandLineHelpers.cs b/src/util/CommandLineHelpers.cs
index d661cb15..0384a3da 100644
--- a/src/util/CommandLineHelpers.cs
+++ b/src/util/CommandLineHelpers.cs
@@ -9,7 +9,7 @@
using System.CommandLine.Parsing;
using System.IO;
-public static class Helpers
+internal static class Helpers
{
public static RootCommand UseVersion(this RootCommand command)
{
@@ -55,7 +55,7 @@ private sealed class CustomizedHelpAction : SynchronousCommandLineAction
public CustomizedHelpAction(HelpOption helpOption, Action customizer)
{
- _helpAction = (HelpAction)helpOption.Action;
+ _helpAction = (HelpAction)helpOption.Action!;
_customizer = customizer;
}
From 468c938f47c320f24b71a9ae97be797c0cdb957f Mon Sep 17 00:00:00 2001
From: Adeel <3840695+am11@users.noreply.github.com>
Date: Fri, 5 Jun 2026 02:06:26 +0300
Subject: [PATCH 4/5] Add Antigen to build.sh
---
build.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/build.sh b/build.sh
index f5813c2b..e39fa05e 100755
--- a/build.sh
+++ b/build.sh
@@ -48,7 +48,7 @@ while getopts "hpb:" opt; do
done
# declare the array of projects
-declare -a projects=(jit-dasm jit-diff jit-analyze jit-tp-analyze jit-format pmi jit-dasm-pmi jit-decisions-analyze performance-explorer instructions-retired-explorer)
+declare -a projects=(Antigen jit-dasm jit-diff jit-analyze jit-tp-analyze jit-format pmi jit-dasm-pmi jit-decisions-analyze performance-explorer instructions-retired-explorer)
# for each project either build or publish
for proj in "${projects[@]}"
From 0ebe2fbcb0b5a4e11cbe0c3a4c1c471fe7240cd7 Mon Sep 17 00:00:00 2001
From: Adeel <3840695+am11@users.noreply.github.com>
Date: Fri, 5 Jun 2026 04:53:00 +0300
Subject: [PATCH 5/5] Update scripts
---
build.cmd | 5 ++++-
build.sh | 2 ++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/build.cmd b/build.cmd
index 02badd00..5abe72c3 100644
--- a/build.cmd
+++ b/build.cmd
@@ -44,7 +44,7 @@ REM Do as many builds as possible; don't stop on first failure (if any).
set __ExitCode=0
REM Declare the list of projects
-set projects=jit-diff jit-dasm jit-analyze jit-tp-analyze jit-format pmi jit-dasm-pmi jit-decisions-analyze performance-explorer instructions-retired-explorer
+set projects=Antigen jit-diff jit-dasm jit-analyze jit-tp-analyze jit-format pmi jit-dasm-pmi jit-decisions-analyze performance-explorer instructions-retired-explorer
REM Build each project
for %%p in (%projects%) do (
@@ -52,6 +52,9 @@ for %%p in (%projects%) do (
REM Publish src/pmi project without single-file, so it can be executed with a custom build of the runtime/JIT
if "%%p"=="pmi" (
dotnet publish -c %buildType% -o %appInstallDir% .\src\%%p
+ ) else if "%%p"=="Antigen" (
+ REM Publish Antigen without single-file; it resolves corelib/Roslyn reference assemblies by path for compilation
+ dotnet publish -c %buildType% -o %appInstallDir% .\src\%%p
) else (
dotnet publish -c %buildType% -o %appInstallDir% .\src\%%p --self-contained -r:%rid% -p:PublishSingleFile=true
)
diff --git a/build.sh b/build.sh
index e39fa05e..19d070d6 100755
--- a/build.sh
+++ b/build.sh
@@ -57,6 +57,8 @@ do
case "$proj" in
# Publish src/pmi project without single-file, so it can be executed with a custom build of the runtime/JIT
pmi) dotnet publish -c "$buildType" -o "$appInstallDir" ./src/"$proj" ;;
+ # Publish Antigen without single-file; it locates reference assemblies (corelib, Roslyn) by path for Roslyn compilation
+ Antigen) dotnet publish -c "$buildType" -o "$appInstallDir" ./src/"$proj" ;;
*) dotnet publish -c "$buildType" -o "$appInstallDir" ./src/"$proj" --self-contained -r $rid -p:PublishSingleFile=true ;;
esac
exit_code=$?