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
