https://github.com/MaskRay created 
https://github.com/llvm/llvm-project/pull/224964

yaml2obj is one of three tools that parse with
cl::ParseCommandLineOptions(LongOptionsUseDoubleDash=true). Parse its
options with an OptTable instead, so that the mode can be removed from
cl::. Spellings follow the other migrated tools: -D<macro>=<v> and
-D <macro>=<v>, -o<file> and -o <file>, --docnum=<n> and --docnum <n>,
--max-size likewise, -E, -h/--help and --version. `-o=<file>` is no
longer accepted; the tests that used it are updated. `--help` lists
only yaml2obj's options.

LLM-aided

>From d8b08e10da9d3fd934cf5934901aa937b4b67537 Mon Sep 17 00:00:00 2001
From: Fangrui Song <[email protected]>
Date: Sun, 20 Sep 2026 12:28:10 -0700
Subject: [PATCH] [yaml2obj] Migrate to OptTable

yaml2obj is one of three tools that parse with
cl::ParseCommandLineOptions(LongOptionsUseDoubleDash=true). Parse its
options with an OptTable instead, so that the mode can be removed from
cl::. Spellings follow the other migrated tools: -D<macro>=<v> and
-D <macro>=<v>, -o<file> and -o <file>, --docnum=<n> and --docnum <n>,
--max-size likewise, -E, -h/--help and --version. `-o=<file>` is no
longer accepted; the tests that used it are updated. `--help` lists
only yaml2obj's options.

LLM-aided
---
 .../InstallAPI/exclusive-passes-platform.test |   2 +-
 .../export_trie_lc_dyld_exports_trie.yaml     |   2 +-
 .../MachO/export_trie_lc_dyld_info_only.yaml  |   2 +-
 .../ObjectYAML/MachO/function_starts.yaml     |   2 +-
 .../COFF/codeview-merging-ghash.test          |   2 +-
 llvm/test/tools/llvm-tli-checker/ifuncs.yaml  |   2 +-
 .../tools/llvm-tli-checker/ps4-tli-check.yaml |   4 +-
 llvm/test/tools/yaml2obj/help.test            |   9 +-
 llvm/tools/yaml2obj/CMakeLists.txt            |   7 ++
 llvm/tools/yaml2obj/Opts.td                   |  18 ++++
 llvm/tools/yaml2obj/yaml2obj.cpp              | 101 +++++++++++-------
 .../gn/secondary/llvm/tools/yaml2obj/BUILD.gn |   9 ++
 .../llvm-project-overlay/llvm/BUILD.bazel     |  11 ++
 13 files changed, 121 insertions(+), 50 deletions(-)
 create mode 100644 llvm/tools/yaml2obj/Opts.td

diff --git a/clang/test/InstallAPI/exclusive-passes-platform.test 
b/clang/test/InstallAPI/exclusive-passes-platform.test
index c5a79cf9a30d16..2428b5d54679c6 100644
--- a/clang/test/InstallAPI/exclusive-passes-platform.test
+++ b/clang/test/InstallAPI/exclusive-passes-platform.test
@@ -1,7 +1,7 @@
 ; RUN: rm -rf %t
 ; RUN: split-file %s %t
 ; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json
-; RUN: yaml2obj %t/Xplatform.yaml -o=%t/Xplatform
+; RUN: yaml2obj %t/Xplatform.yaml -o %t/Xplatform
 
 // Check that in zippered mode, a successful pass runs in both macos & 
maccatalyst.
 ; RUN: clang-installapi %t/inputs.json \
diff --git a/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_exports_trie.yaml 
b/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_exports_trie.yaml
index 4710bca2996514..d5857c8acbfed0 100644
--- a/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_exports_trie.yaml
+++ b/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_exports_trie.yaml
@@ -1,4 +1,4 @@
-# RUN: yaml2obj %s -o=%t
+# RUN: yaml2obj %s -o %t
 # RUN: obj2yaml %t | FileCheck %s
 # RUN: llvm-objdump --macho --exports-trie %t | FileCheck %s 
--check-prefix=OBJDUMP-VERIFY
 
diff --git a/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_info_only.yaml 
b/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_info_only.yaml
index 9c359db6b90d6a..1612295be1ce1c 100644
--- a/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_info_only.yaml
+++ b/llvm/test/ObjectYAML/MachO/export_trie_lc_dyld_info_only.yaml
@@ -1,4 +1,4 @@
-# RUN: yaml2obj %s -o=%t
+# RUN: yaml2obj %s -o %t
 # RUN: obj2yaml %t | FileCheck %s
 # RUN: llvm-objdump --macho --exports-trie %t | FileCheck %s 
--check-prefix=OBJDUMP-VERIFY
 
diff --git a/llvm/test/ObjectYAML/MachO/function_starts.yaml 
b/llvm/test/ObjectYAML/MachO/function_starts.yaml
index 0cdd6665dcfb9c..2331049ccee423 100644
--- a/llvm/test/ObjectYAML/MachO/function_starts.yaml
+++ b/llvm/test/ObjectYAML/MachO/function_starts.yaml
@@ -176,7 +176,7 @@ LinkEditData:
   FunctionStarts:  [ 0x3F80, 0x3F84 ]
 ...
 
-# RUN: yaml2obj %s -o=%t
+# RUN: yaml2obj %s -o %t
 # RUN: obj2yaml %t | FileCheck %s
 # CHECK: FunctionStarts:  [ 0x3F80, 0x3F84 ]
 
diff --git a/llvm/test/tools/llvm-readobj/COFF/codeview-merging-ghash.test 
b/llvm/test/tools/llvm-readobj/COFF/codeview-merging-ghash.test
index 7c57cf0b5dc81f..31139c4cb3aad0 100644
--- a/llvm/test/tools/llvm-readobj/COFF/codeview-merging-ghash.test
+++ b/llvm/test/tools/llvm-readobj/COFF/codeview-merging-ghash.test
@@ -1,4 +1,4 @@
-# RUN: yaml2obj %s -o=%t.obj
+# RUN: yaml2obj %s -o %t.obj
 # RUN: llvm-readobj --codeview-merged-types %t.obj | FileCheck %s 
--check-prefix=MERGED
 # RUN: llvm-readobj --codeview-merged-types --codeview-ghash %t.obj | 
FileCheck %s --check-prefix=MERGED
 
diff --git a/llvm/test/tools/llvm-tli-checker/ifuncs.yaml 
b/llvm/test/tools/llvm-tli-checker/ifuncs.yaml
index 4eae66c3051a7f..dd76269dbe14df 100644
--- a/llvm/test/tools/llvm-tli-checker/ifuncs.yaml
+++ b/llvm/test/tools/llvm-tli-checker/ifuncs.yaml
@@ -4,7 +4,7 @@
 # llvm-tli-checker won't be able to find it unless it knows how to check 
ifuncs.
 # This test makes sure that llvm-tli-checker supports processing ifuncs.
 #
-# RUN: yaml2obj %s -o=%t1
+# RUN: yaml2obj %s -o %t1
 # RUN: llvm-tli-checker --triple=x86_64-unknown-freebsd %t1 | FileCheck %s
 #
 # CHECK: == Total TLI yes SDK yes: 1
diff --git a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml 
b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
index 63520a0b98089e..70a44a3aab775a 100644
--- a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
+++ b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
@@ -1,12 +1,12 @@
 # REQUIRES: x86-registered-target
 #
 ## This produces a static object that matches expectations for PS4/PS5.
-# RUN: yaml2obj %s -DTYPE=ET_REL -DLABEL=Symbols -DZDAPV=_ZdaPv -o=%t1
+# RUN: yaml2obj %s -DTYPE=ET_REL -DLABEL=Symbols -DZDAPV=_ZdaPv -o %t1
 # RUN: llvm-tli-checker --triple=x86_64-scei-ps4 %t1 | FileCheck %s
 # RUN: llvm-tli-checker --triple=x86_64-sie-ps5 %t1 | FileCheck %s
 #
 ## This produces a dynamic object that has _ZdaPvj instead of _ZdaPv.
-# RUN: yaml2obj %s -DTYPE=ET_DYN -DLABEL=DynamicSymbols -DZDAPV=_ZdaPvj -o=%t2
+# RUN: yaml2obj %s -DTYPE=ET_DYN -DLABEL=DynamicSymbols -DZDAPV=_ZdaPvj -o %t2
 # RUN: llvm-tli-checker --triple x86_64-scei-ps4 %t2 | \
 # RUN:     FileCheck %s --check-prefixes=WRONG_SUMMARY,WRONG_DETAIL \
 # RUN:    --implicit-check-not="==" --implicit-check-not="<<" 
--implicit-check-not=">>"
diff --git a/llvm/test/tools/yaml2obj/help.test 
b/llvm/test/tools/yaml2obj/help.test
index 2e82c1278c4340..95564c47bc97ec 100644
--- a/llvm/test/tools/yaml2obj/help.test
+++ b/llvm/test/tools/yaml2obj/help.test
@@ -1,11 +1,8 @@
 ## Show that help text is printed correctly when requested.
 
-# RUN: yaml2obj -h | FileCheck %s --check-prefixes=CHECK,CATEG 
--implicit-check-not=Options:
-# RUN: yaml2obj --help | FileCheck %s --check-prefixes=CHECK,CATEG 
--implicit-check-not=Options:
-# RUN: yaml2obj --help-list | FileCheck %s --implicit-check-not=Options:
+# RUN: yaml2obj -h | FileCheck %s
+# RUN: yaml2obj --help | FileCheck %s
 
 # CHECK: OVERVIEW: Create an object file from a YAML description
-# CHECK: USAGE: yaml2obj{{(.exe)?}} [options] <input file>{{$}}
+# CHECK: USAGE: yaml2obj [options] <input file>{{$}}
 # CHECK: OPTIONS:
-# CATEG: Generic Options:
-# CATEG: yaml2obj Options:
diff --git a/llvm/tools/yaml2obj/CMakeLists.txt 
b/llvm/tools/yaml2obj/CMakeLists.txt
index ad413405255c66..d9d1796c555c65 100644
--- a/llvm/tools/yaml2obj/CMakeLists.txt
+++ b/llvm/tools/yaml2obj/CMakeLists.txt
@@ -1,10 +1,17 @@
 set(LLVM_LINK_COMPONENTS
   Object
   ObjectYAML
+  Option
   ProfileData
   Support
   )
 
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(Yaml2ObjOptsTableGen)
+
 add_llvm_utility(yaml2obj
   yaml2obj.cpp
+  DEPENDS
+  Yaml2ObjOptsTableGen
   )
diff --git a/llvm/tools/yaml2obj/Opts.td b/llvm/tools/yaml2obj/Opts.td
new file mode 100644
index 00000000000000..02a7934c38b2fc
--- /dev/null
+++ b/llvm/tools/yaml2obj/Opts.td
@@ -0,0 +1,18 @@
+include "llvm/Option/OptParser.td"
+
+class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
+class FF<string name, string help> : Flag<["--"], name>, HelpText<help>;
+
+multiclass Eq<string name, string help> {
+  def NAME #_EQ : Joined<["--"], name #"=">, HelpText<help>;
+  def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+def D : JoinedOrSeparate<["-"], "D">, HelpText<"Define the specified macro to 
the specified definition">, MetaVarName<"<macro>=<definition>">;
+defm docnum : Eq<"docnum", "Read the specified document from the input 
(default = 1)">, MetaVarName<"<n>">;
+def E : F<"E", "Just print the preprocessed file">;
+def help : FF<"help", "Display this help">;
+def : F<"h", "Alias for --help">, Alias<help>;
+defm max_size : Eq<"max-size", "Set the maximum allowed output size (0 means 
no limit) [ELF and COFF only]">, MetaVarName<"<bytes>">;
+def o : JoinedOrSeparate<["-"], "o">, HelpText<"Output filename">, 
MetaVarName<"<filename>">;
+def version : FF<"version", "Display the version">;
diff --git a/llvm/tools/yaml2obj/yaml2obj.cpp b/llvm/tools/yaml2obj/yaml2obj.cpp
index 0cb3d5d61b126d..8fb5b0af0d3ab4 100644
--- a/llvm/tools/yaml2obj/yaml2obj.cpp
+++ b/llvm/tools/yaml2obj/yaml2obj.cpp
@@ -16,10 +16,14 @@
 #include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ObjectYAML/ObjectYAML.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/StringSaver.h"
 #include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/YAMLTraits.h"
@@ -30,37 +34,25 @@
 using namespace llvm;
 
 namespace {
-cl::OptionCategory Cat("yaml2obj Options");
-
-cl::opt<std::string> Input(cl::Positional, cl::desc("<input file>"),
-                           cl::init("-"), cl::cat(Cat));
-
-static cl::list<std::string>
-    D("D", cl::Prefix,
-      cl::desc("Defined the specified macros to their specified "
-               "definition. The syntax is <macro>=<definition>"),
-      cl::cat(Cat));
-
-cl::opt<bool> PreprocessOnly("E", cl::desc("Just print the preprocessed file"),
-                             cl::cat(Cat));
-
-cl::opt<unsigned>
-    DocNum("docnum", cl::init(1),
-           cl::desc("Read specified document from input (default = 1)"),
-           cl::cat(Cat));
-
-static cl::opt<uint64_t>
-    MaxSize("max-size", cl::init(10 * 1024 * 1024),
-            cl::desc("Sets the maximum allowed output size (0 means no limit) "
-                     "[ELF and COFF only]"),
-            cl::cat(Cat));
-
-cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
-                                    cl::value_desc("filename"), cl::init("-"),
-                                    cl::Prefix, cl::cat(Cat));
+enum ID {
+  OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
+#include "Opts.inc"
+#undef OPTION
+};
+
+using namespace llvm::opt;
+#define OPTTABLE_CODE
+#include "Opts.inc"
+
+class Yaml2ObjOptTable : public opt::OptTable {
+public:
+  Yaml2ObjOptTable() : OptTable(optionTables()) { setDashDashParsing(true); }
+};
 } // namespace
 
 static std::optional<std::string> preprocess(StringRef Buf,
+                                             ArrayRef<std::string> D,
                                              yaml::ErrorHandler ErrHandler) {
   DenseMap<StringRef, StringRef> Defines;
   for (StringRef Define : D) {
@@ -110,18 +102,55 @@ static std::optional<std::string> preprocess(StringRef 
Buf,
   return Preprocessed;
 }
 
+template <class T>
+static void parseIntArg(const opt::InputArgList &Args, int ID, T &Value,
+                        yaml::ErrorHandler ErrHandler) {
+  if (const opt::Arg *A = Args.getLastArg(ID)) {
+    StringRef V(A->getValue());
+    if (!to_integer(V, Value, 0)) {
+      ErrHandler("expected an integer, but got '" + V + "'");
+      exit(1);
+    }
+  }
+}
+
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
-  cl::HideUnrelatedOptions(Cat);
-  cl::ParseCommandLineOptions(
-      argc, argv, "Create an object file from a YAML description", nullptr,
-      nullptr, nullptr, /*LongOptionsUseDoubleDash=*/true);
-
   constexpr StringRef ProgName = "yaml2obj";
   auto ErrHandler = [&](const Twine &Msg) {
     WithColor::error(errs(), ProgName) << Msg << "\n";
   };
 
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  Yaml2ObjOptTable Tbl;
+  opt::InputArgList Args =
+      Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
+        ErrHandler(Msg);
+        exit(1);
+      });
+  if (Args.hasArg(OPT_help)) {
+    Tbl.printHelp(outs(), "yaml2obj [options] <input file>",
+                  "Create an object file from a YAML description");
+    return 0;
+  }
+  if (Args.hasArg(OPT_version)) {
+    cl::PrintVersionMessage();
+    return 0;
+  }
+
+  std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
+  if (Inputs.size() > 1) {
+    ErrHandler("too many input files");
+    return 1;
+  }
+  StringRef Input = Inputs.empty() ? StringRef("-") : StringRef(Inputs[0]);
+  StringRef OutputFilename = Args.getLastArgValue(OPT_o, "-");
+  unsigned DocNum = 1;
+  parseIntArg(Args, OPT_docnum_EQ, DocNum, ErrHandler);
+  uint64_t MaxSize = 10 * 1024 * 1024;
+  parseIntArg(Args, OPT_max_size_EQ, MaxSize, ErrHandler);
+
   std::error_code EC;
   std::unique_ptr<ToolOutputFile> Out(
       new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));
@@ -137,12 +166,12 @@ int main(int argc, char **argv) {
     return 1;
   }
 
-  std::optional<std::string> Buffer =
-      preprocess(Buf.get()->getBuffer(), ErrHandler);
+  std::optional<std::string> Buffer = preprocess(
+      Buf.get()->getBuffer(), Args.getAllArgValues(OPT_D), ErrHandler);
   if (!Buffer)
     return 1;
 
-  if (PreprocessOnly) {
+  if (Args.hasArg(OPT_E)) {
     Out->os() << Buffer;
   } else {
     yaml::Input YIn(*Buffer);
diff --git a/llvm/utils/gn/secondary/llvm/tools/yaml2obj/BUILD.gn 
b/llvm/utils/gn/secondary/llvm/tools/yaml2obj/BUILD.gn
index 7e4ba3be0d4799..47e45c9cca3dc4 100644
--- a/llvm/utils/gn/secondary/llvm/tools/yaml2obj/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/tools/yaml2obj/BUILD.gn
@@ -1,6 +1,15 @@
+import("//llvm/utils/TableGen/tablegen.gni")
+
+tablegen("Opts") {
+  visibility = [ ":yaml2obj" ]
+  args = [ "-gen-opt-parser-defs" ]
+}
+
 executable("yaml2obj") {
   deps = [
+    ":Opts",
     "//llvm/lib/ObjectYAML",
+    "//llvm/lib/Option",
     "//llvm/lib/Support",
   ]
   sources = [ "yaml2obj.cpp" ]
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel 
b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index b7765075c72fb0..279d2d2cb37ce3 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -7183,6 +7183,15 @@ cc_binary(
     ],
 )
 
+gentbl_cc_library(
+    name = "Yaml2ObjOptsTableGen",
+    strip_include_prefix = "tools/yaml2obj",
+    tbl_outs = {"tools/yaml2obj/Opts.inc": ["-gen-opt-parser-defs"]},
+    tblgen = ":llvm-tblgen",
+    td_file = "tools/yaml2obj/Opts.td",
+    deps = [":OptParserTdFiles"],
+)
+
 cc_binary(
     name = "yaml2obj",
     testonly = True,
@@ -7197,7 +7206,9 @@ cc_binary(
         ":MC",
         ":Object",
         ":ObjectYAML",
+        ":Option",
         ":Support",
+        ":Yaml2ObjOptsTableGen",
     ],
 )
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to