https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/224807
>From 8fccb784f2883bf9c65eacafb954b40fb8dfe078 Mon Sep 17 00:00:00 2001 From: Fangrui Song <[email protected]> Date: Fri, 18 Sep 2026 19:48:57 -0700 Subject: [PATCH 1/2] [Option] Replace the OptionTables object with a function. NFC The generated aggregate holds seven addresses, so it needs a relocation per pointer and lives in .data.rel.ro (dynamic relocations in PIE and shared library builds): ``` static constexpr llvm::opt::OptTable::Tables OptionTables = { OptionStrTable, OptionPrefixesTable, OptionPrefixesUnion, ...}; ... FooOptTable() : OptTable(OptionTables) {} ``` Emit a function instead. The caller builds the aggregate on the stack from PC-relative addresses, which the linker resolves: ``` static constexpr llvm::opt::OptTable::Tables optionTables() { return {OptionStrTable, OptionPrefixesTable, OptionInfoTable, ...}; } ... FooOptTable() : OptTable(optionTables()) {} ``` Derive the prefix union from the prefix table in the constructor and drop the emitted OptionPrefixesUnion. Drop the redundant `static` on the emitted tables: a namespace-scope const object has internal linkage. Aided by Opus 5 --- clang/lib/Options/DriverOptions.cpp | 2 +- clang/tools/clang-installapi/Options.cpp | 2 +- .../ClangLinkerWrapper.cpp | 2 +- .../ClangNVLinkWrapper.cpp | 2 +- clang/tools/clang-scan-deps/ClangScanDeps.cpp | 4 +- .../clang-sycl-linker/ClangSYCLLinker.cpp | 2 +- lld/COFF/DriverUtils.cpp | 2 +- lld/ELF/DriverUtils.cpp | 2 +- lld/MachO/DriverUtils.cpp | 2 +- lld/MinGW/Driver.cpp | 2 +- lld/wasm/Driver.cpp | 2 +- lldb/tools/driver/Driver.cpp | 2 +- lldb/tools/lldb-dap/tool/lldb-dap.cpp | 2 +- lldb/tools/lldb-server/lldb-gdbserver.cpp | 2 +- lldb/tools/lldb-server/lldb-platform.cpp | 2 +- .../examples/OptSubcommand/llvm-hello-sub.cpp | 2 +- llvm/include/llvm/Option/OptTable.h | 4 +- .../JITLink/COFFDirectiveParser.cpp | 3 +- llvm/lib/Option/OptTable.cpp | 18 +++++--- .../llvm-dlltool/DlltoolDriver.cpp | 2 +- llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp | 2 +- llvm/tools/dsymutil/dsymutil.cpp | 2 +- llvm/tools/llvm-cas/llvm-cas.cpp | 2 +- llvm/tools/llvm-cgdata/llvm-cgdata.cpp | 2 +- llvm/tools/llvm-cvtres/llvm-cvtres.cpp | 2 +- llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp | 2 +- .../llvm-debuginfod-find.cpp | 2 +- .../tools/llvm-debuginfod/llvm-debuginfod.cpp | 2 +- llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp | 2 +- llvm/tools/llvm-dwp/llvm-dwp.cpp | 2 +- llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp | 4 +- llvm/tools/llvm-ifs/llvm-ifs.cpp | 4 +- .../llvm-libtool-darwin.cpp | 2 +- llvm/tools/llvm-lipo/llvm-lipo.cpp | 2 +- llvm/tools/llvm-ml/llvm-ml.cpp | 2 +- llvm/tools/llvm-mt/llvm-mt.cpp | 2 +- llvm/tools/llvm-nm/llvm-nm.cpp | 2 +- llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 11 +++-- llvm/tools/llvm-objdump/llvm-objdump.cpp | 4 +- llvm/tools/llvm-rc/llvm-rc.cpp | 4 +- llvm/tools/llvm-readobj/llvm-readobj.cpp | 2 +- llvm/tools/llvm-readtapi/llvm-readtapi.cpp | 4 +- llvm/tools/llvm-size/llvm-size.cpp | 2 +- llvm/tools/llvm-strings/llvm-strings.cpp | 2 +- .../tools/llvm-symbolizer/llvm-symbolizer.cpp | 2 +- .../llvm-tli-checker/llvm-tli-checker.cpp | 2 +- llvm/tools/sancov/sancov.cpp | 2 +- llvm/unittests/Option/OptionParsingTest.cpp | 2 +- .../Option/OptionSubCommandsTest.cpp | 2 +- llvm/utils/TableGen/OptionParserEmitter.cpp | 46 ++++++------------- 50 files changed, 88 insertions(+), 96 deletions(-) diff --git a/clang/lib/Options/DriverOptions.cpp b/clang/lib/Options/DriverOptions.cpp index 50158f13a9653..4a1684cd3ce8c 100644 --- a/clang/lib/Options/DriverOptions.cpp +++ b/clang/lib/Options/DriverOptions.cpp @@ -23,7 +23,7 @@ namespace { class DriverOptTable : public OptTable { public: - DriverOptTable() : OptTable(OptionTables) { + DriverOptTable() : OptTable(optionTables()) { setValuesCodeFn(getOptionValuesCode); } }; diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index c3bd0b14ce65a..8c9d1142d1510 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -38,7 +38,7 @@ namespace { /// \brief Create OptTable class for parsing actual command line arguments. class DriverOptTable : public opt::OptTable { public: - DriverOptTable() : OptTable(OptionTables) {} + DriverOptTable() : OptTable(optionTables()) {} }; } // end anonymous namespace. diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 2e178aee196b6..0e71d0020c071 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -179,7 +179,7 @@ enum ID { class WrapperOptTable : public opt::OptTable { public: - WrapperOptTable() : opt::OptTable(OptionTables) {} + WrapperOptTable() : opt::OptTable(optionTables()) {} }; const OptTable &getOptTable() { diff --git a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp index 6df0af65e292b..84a3561fb9725 100644 --- a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp +++ b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp @@ -116,7 +116,7 @@ enum ID { class WrapperOptTable : public opt::OptTable { public: - WrapperOptTable() : opt::OptTable(OptionTables) {} + WrapperOptTable() : opt::OptTable(optionTables()) {} }; const OptTable &getOptTable() { diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index 0cbc115f910df..778f73909665d 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -59,7 +59,9 @@ enum ID { class ScanDepsOptTable : public llvm::opt::OptTable { public: - ScanDepsOptTable() : OptTable(OptionTables) { setGroupedShortOptions(true); } + ScanDepsOptTable() : OptTable(optionTables()) { + setGroupedShortOptions(true); + } }; enum ResourceDirRecipeKind { diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 84e0ead680d2b..b568c7e87ce7c 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -103,7 +103,7 @@ enum ID { class LinkerOptTable : public opt::OptTable { public: - LinkerOptTable() : opt::OptTable(OptionTables) {} + LinkerOptTable() : opt::OptTable(optionTables()) {} }; } // namespace diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index 75530b405c692..265ddee6d8557 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -751,7 +751,7 @@ MemoryBufferRef LinkerDriver::convertResToCOFF(ArrayRef<MemoryBufferRef> mbs, #define OPTTABLE_CODE #include "Options.inc" -COFFOptTable::COFFOptTable() : OptTable(OptionTables, true) {} +COFFOptTable::COFFOptTable() : OptTable(optionTables(), true) {} // Set color diagnostics according to --color-diagnostics={auto,always,never} // or --no-color-diagnostics flags. diff --git a/lld/ELF/DriverUtils.cpp b/lld/ELF/DriverUtils.cpp index b2c760eeaf3ec..7bee46d8534bf 100644 --- a/lld/ELF/DriverUtils.cpp +++ b/lld/ELF/DriverUtils.cpp @@ -36,7 +36,7 @@ using namespace lld::elf; #define OPTTABLE_CODE #include "Options.inc" -ELFOptTable::ELFOptTable() : OptTable(OptionTables) {} +ELFOptTable::ELFOptTable() : OptTable(optionTables()) {} // Set color diagnostics according to --color-diagnostics={auto,always,never} // or --no-color-diagnostics flags. diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp index 9b0f820634ad6..e097d2ce302c3 100644 --- a/lld/MachO/DriverUtils.cpp +++ b/lld/MachO/DriverUtils.cpp @@ -35,7 +35,7 @@ using namespace lld::macho; #define OPTTABLE_CODE #include "Options.inc" -MachOOptTable::MachOOptTable() : OptTable(OptionTables) {} +MachOOptTable::MachOOptTable() : OptTable(optionTables()) {} // Set color diagnostics according to --color-diagnostics={auto,always,never} // or --no-color-diagnostics flags. diff --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp index b15d06b82146a..53cce5b5c0277 100644 --- a/lld/MinGW/Driver.cpp +++ b/lld/MinGW/Driver.cpp @@ -64,7 +64,7 @@ enum { namespace { class MinGWOptTable : public opt::OptTable { public: - MinGWOptTable() : opt::OptTable(OptionTables, false) {} + MinGWOptTable() : opt::OptTable(optionTables(), false) {} opt::InputArgList parse(ArrayRef<const char *> argv); }; } // namespace diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index a15c5cf0ad7ed..1de9851d5ed3e 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -151,7 +151,7 @@ bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS, namespace { class WasmOptTable : public opt::OptTable { public: - WasmOptTable() : opt::OptTable(OptionTables) {} + WasmOptTable() : opt::OptTable(optionTables()) {} opt::InputArgList parse(ArrayRef<const char *> argv); }; } // namespace diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index 69894370c07e8..529ec309445cf 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -84,7 +84,7 @@ enum ID { class LLDBOptTable : public opt::OptTable { public: - LLDBOptTable() : opt::OptTable(OptionTables) {} + LLDBOptTable() : opt::OptTable(optionTables()) {} }; } // namespace diff --git a/lldb/tools/lldb-dap/tool/lldb-dap.cpp b/lldb/tools/lldb-dap/tool/lldb-dap.cpp index 7dc367af45199..9444f77ae31ca 100644 --- a/lldb/tools/lldb-dap/tool/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/tool/lldb-dap.cpp @@ -114,7 +114,7 @@ enum ID { #include "Options.inc" class LLDBDAPOptTable : public llvm::opt::OptTable { public: - LLDBDAPOptTable() : llvm::opt::OptTable(OptionTables, true) {} + LLDBDAPOptTable() : llvm::opt::OptTable(optionTables(), true) {} }; } // anonymous namespace diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp index 853aee10ac4ec..98a79dedf65c0 100644 --- a/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -307,7 +307,7 @@ enum ID { class LLGSOptTable : public opt::OptTable { public: - LLGSOptTable() : opt::OptTable(OptionTables) {} + LLGSOptTable() : opt::OptTable(optionTables()) {} void PrintHelp(llvm::StringRef Name) { std::string Usage = diff --git a/lldb/tools/lldb-server/lldb-platform.cpp b/lldb/tools/lldb-server/lldb-platform.cpp index 8a1e273435d92..29f065c33f409 100644 --- a/lldb/tools/lldb-server/lldb-platform.cpp +++ b/lldb/tools/lldb-server/lldb-platform.cpp @@ -73,7 +73,7 @@ enum ID { class PlatformOptTable : public opt::OptTable { public: - PlatformOptTable() : opt::OptTable(OptionTables) {} + PlatformOptTable() : opt::OptTable(optionTables()) {} void PrintHelp(llvm::StringRef Name) { std::string Usage = diff --git a/llvm/examples/OptSubcommand/llvm-hello-sub.cpp b/llvm/examples/OptSubcommand/llvm-hello-sub.cpp index 485a3bfe89907..bc057002a4b36 100644 --- a/llvm/examples/OptSubcommand/llvm-hello-sub.cpp +++ b/llvm/examples/OptSubcommand/llvm-hello-sub.cpp @@ -24,7 +24,7 @@ enum ID { class HelloSubOptTable : public OptTable { public: - HelloSubOptTable() : OptTable(OptionTables) {}; + HelloSubOptTable() : OptTable(optionTables()) {}; }; } // namespace diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h index 1532f18b105bd..611cfe826a99f 100644 --- a/llvm/include/llvm/Option/OptTable.h +++ b/llvm/include/llvm/Option/OptTable.h @@ -159,7 +159,6 @@ class LLVM_ABI OptTable { struct Tables { const StringTable &StrTable; ArrayRef<StringTable::Offset> PrefixesTable; - ArrayRef<StringTable::Offset> PrefixesUnion; ArrayRef<Info> Infos; ArrayRef<HelpTextVariant> HelpTextVariants; ArrayRef<SubCommand> SubCommands; @@ -252,11 +251,10 @@ class LLVM_ABI OptTable { unsigned &Index) const; protected: - OptTable(const Tables &Tables, bool IgnoreCase = false); - void setValuesCodeFn(ValuesCodeFnTy Fn) { ValuesCodeFn = Fn; } public: + OptTable(const Tables &T, bool IgnoreCase = false); virtual ~OptTable(); /// Return the string table used for option names. diff --git a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp index 624ead6a8ea78..6300cfa56f133 100644 --- a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp @@ -17,14 +17,13 @@ using namespace jitlink; #define DEBUG_TYPE "jitlink" -// Create table mapping all options defined in COFFOptions.td using namespace llvm::opt; #define OPTTABLE_CODE #include "COFFOptions.inc" class COFFOptTable : public opt::OptTable { public: - COFFOptTable() : OptTable(OptionTables, true) {} + COFFOptTable() : OptTable(optionTables(), true) {} }; static COFFOptTable optTable; diff --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp index c444235076586..87487d625f7e4 100644 --- a/llvm/lib/Option/OptTable.cpp +++ b/llvm/lib/Option/OptTable.cpp @@ -78,12 +78,18 @@ OptTable::OptTable(const Tables &T, bool IgnoreCase) OptionInfos(T.Infos), IgnoreCase(IgnoreCase), SubCommands(T.SubCommands), SubCommandIDsTable(T.SubCommandIDs), HelpTextVariantsTable(T.HelpTextVariants) { - for (StringTable::Offset PrefixOffset : T.PrefixesUnion) { - StringRef Prefix = (*StrTable)[PrefixOffset]; - PrefixesUnion.push_back(Prefix); - for (char C : Prefix) - if (!is_contained(PrefixChars, C)) - PrefixChars.push_back(C); + // Each prefix set in PrefixesTable starts with its size. + for (unsigned I = 0, E = PrefixesTable.size(); I != E;) { + unsigned Size = PrefixesTable[I++].value(); + for (unsigned J = 0; J != Size; ++J) { + StringRef Prefix = (*StrTable)[PrefixesTable[I++]]; + if (is_contained(PrefixesUnion, Prefix)) + continue; + PrefixesUnion.push_back(Prefix); + for (char C : Prefix) + if (!is_contained(PrefixChars, C)) + PrefixChars.push_back(C); + } } // Find start of normal options. diff --git a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp index cef8f5af611d8..d914b49747c32 100644 --- a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp +++ b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp @@ -45,7 +45,7 @@ using namespace llvm::opt; class DllOptTable : public opt::OptTable { public: - DllOptTable() : opt::OptTable(OptionTables, false) {} + DllOptTable() : opt::OptTable(optionTables(), false) {} }; // Opens a file. Path has to be resolved already. diff --git a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp index 0cae27d4c2765..55e59aa6ac12d 100644 --- a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp +++ b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp @@ -50,7 +50,7 @@ using namespace llvm::opt; class LibOptTable : public opt::OptTable { public: - LibOptTable() : opt::OptTable(OptionTables, true) {} + LibOptTable() : opt::OptTable(optionTables(), true) {} }; } // namespace diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp index 9adf846d1e1a3..0b30d3512d8d2 100644 --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -74,7 +74,7 @@ using namespace llvm::opt; class DsymutilOptTable : public opt::OptTable { public: - DsymutilOptTable() : opt::OptTable(OptionTables) {} + DsymutilOptTable() : opt::OptTable(optionTables()) {} }; } // namespace diff --git a/llvm/tools/llvm-cas/llvm-cas.cpp b/llvm/tools/llvm-cas/llvm-cas.cpp index 7ed4f4fc0846a..d4d79336b5d75 100644 --- a/llvm/tools/llvm-cas/llvm-cas.cpp +++ b/llvm/tools/llvm-cas/llvm-cas.cpp @@ -39,7 +39,7 @@ using namespace llvm::opt; class LLVMCASOptTable : public opt::OptTable { public: - LLVMCASOptTable() : opt::OptTable(OptionTables) {} + LLVMCASOptTable() : opt::OptTable(optionTables()) {} }; enum class CommandKind { diff --git a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp index 472805ec06053..f06119a24e6ff 100644 --- a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp +++ b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp @@ -57,7 +57,7 @@ using namespace llvm::opt; class CGDataOptTable : public opt::OptTable { public: - CGDataOptTable() : OptTable(OptionTables) {} + CGDataOptTable() : OptTable(optionTables()) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp index a6f1d42f433e9..e13c66c9ab1a7 100644 --- a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp +++ b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp @@ -48,7 +48,7 @@ using namespace llvm::opt; class CvtResOptTable : public opt::OptTable { public: - CvtResOptTable() : opt::OptTable(OptionTables, true) {} + CvtResOptTable() : opt::OptTable(optionTables(), true) {} }; } diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp index 6584da5f9f41f..457623561e241 100644 --- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -37,7 +37,7 @@ using namespace llvm::opt; class CxxfiltOptTable : public opt::OptTable { public: - CxxfiltOptTable() : opt::OptTable(OptionTables) { + CxxfiltOptTable() : opt::OptTable(optionTables()) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp b/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp index 447038f1601d7..483b14a841083 100644 --- a/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp +++ b/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp @@ -43,7 +43,7 @@ using namespace llvm::opt; class DebuginfodFindOptTable : public opt::OptTable { public: - DebuginfodFindOptTable() : OptTable(OptionTables) {} + DebuginfodFindOptTable() : OptTable(optionTables()) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp index 60c4ba164bc82..1ecb6e8c4bd3d 100644 --- a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp +++ b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp @@ -42,7 +42,7 @@ using namespace llvm::opt; class DebuginfodOptTable : public opt::OptTable { public: - DebuginfodOptTable() : OptTable(OptionTables) {} + DebuginfodOptTable() : OptTable(optionTables()) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp index 0d40bb7d75b79..2176db14f06f4 100644 --- a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp +++ b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp @@ -45,7 +45,7 @@ using namespace llvm::opt; class DwarfutilOptTable : public opt::OptTable { public: - DwarfutilOptTable() : opt::OptTable(OptionTables) {} + DwarfutilOptTable() : opt::OptTable(optionTables()) {} }; } // namespace diff --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp index c24164e3846e2..fac0051aa76e9 100644 --- a/llvm/tools/llvm-dwp/llvm-dwp.cpp +++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -40,7 +40,7 @@ using namespace llvm::opt; class DwpOptTable : public opt::OptTable { public: - DwpOptTable() : OptTable(OptionTables) {} + DwpOptTable() : OptTable(optionTables()) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp index 386af5186077e..e168c8141def9 100644 --- a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp +++ b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp @@ -75,7 +75,9 @@ enum ID { class GSYMUtilOptTable : public llvm::opt::OptTable { public: - GSYMUtilOptTable() : OptTable(OptionTables) { setGroupedShortOptions(true); } + GSYMUtilOptTable() : OptTable(optionTables()) { + setGroupedShortOptions(true); + } }; static bool Verbose; diff --git a/llvm/tools/llvm-ifs/llvm-ifs.cpp b/llvm/tools/llvm-ifs/llvm-ifs.cpp index 35f08b62ebacc..575a1117363fe 100644 --- a/llvm/tools/llvm-ifs/llvm-ifs.cpp +++ b/llvm/tools/llvm-ifs/llvm-ifs.cpp @@ -63,7 +63,9 @@ enum ID { class IFSOptTable : public opt::OptTable { public: - IFSOptTable() : opt::OptTable(OptionTables) { setGroupedShortOptions(true); } + IFSOptTable() : opt::OptTable(optionTables()) { + setGroupedShortOptions(true); + } }; struct DriverConfig { diff --git a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp index ad3af47de7dde..b2e02173ee3b4 100644 --- a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp +++ b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp @@ -53,7 +53,7 @@ enum ID { class LibtoolDarwinOptTable : public opt::OptTable { public: - LibtoolDarwinOptTable() : OptTable(OptionTables) {} + LibtoolDarwinOptTable() : OptTable(optionTables()) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-lipo/llvm-lipo.cpp b/llvm/tools/llvm-lipo/llvm-lipo.cpp index 486321657c3af..c5dd60d1107ad 100644 --- a/llvm/tools/llvm-lipo/llvm-lipo.cpp +++ b/llvm/tools/llvm-lipo/llvm-lipo.cpp @@ -77,7 +77,7 @@ using namespace llvm::opt; class LipoOptTable : public opt::OptTable { public: - LipoOptTable() : opt::OptTable(lipo::OptionTables) {} + LipoOptTable() : opt::OptTable(lipo::optionTables()) {} }; enum class LipoAction { diff --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp index c6ce99cfc4da7..2a4e0537579d3 100644 --- a/llvm/tools/llvm-ml/llvm-ml.cpp +++ b/llvm/tools/llvm-ml/llvm-ml.cpp @@ -64,7 +64,7 @@ enum ID { class MLOptTable : public opt::OptTable { public: - MLOptTable() : opt::OptTable(OptionTables, /*IgnoreCase=*/false) {} + MLOptTable() : opt::OptTable(optionTables(), /*IgnoreCase=*/false) {} }; } // namespace diff --git a/llvm/tools/llvm-mt/llvm-mt.cpp b/llvm/tools/llvm-mt/llvm-mt.cpp index 3e651cf56e719..9e781ad2fedb3 100644 --- a/llvm/tools/llvm-mt/llvm-mt.cpp +++ b/llvm/tools/llvm-mt/llvm-mt.cpp @@ -46,7 +46,7 @@ using namespace llvm::opt; class CvtResOptTable : public opt::OptTable { public: - CvtResOptTable() : opt::OptTable(OptionTables, true) {} + CvtResOptTable() : opt::OptTable(optionTables(), true) {} }; } // namespace diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index 2e9f865675234..e4e4dc6c83083 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -72,7 +72,7 @@ enum ID { class NmOptTable : public opt::OptTable { public: - NmOptTable() : opt::OptTable(OptionTables) { setGroupedShortOptions(true); } + NmOptTable() : opt::OptTable(optionTables()) { setGroupedShortOptions(true); } }; enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols }; diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index 0bbaf95660329..4c0f9d1d09daf 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -46,7 +46,7 @@ namespace objcopy_opt { class ObjcopyOptTable : public opt::OptTable { public: - ObjcopyOptTable() : opt::OptTable(objcopy_opt::OptionTables) { + ObjcopyOptTable() : opt::OptTable(objcopy_opt::optionTables()) { setGroupedShortOptions(true); setDashDashParsing(true); } @@ -67,7 +67,7 @@ namespace install_name_tool { class InstallNameToolOptTable : public opt::OptTable { public: - InstallNameToolOptTable() : OptTable(install_name_tool::OptionTables) {} + InstallNameToolOptTable() : OptTable(install_name_tool::optionTables()) {} }; enum BitcodeStripID { @@ -85,7 +85,7 @@ namespace bitcode_strip { class BitcodeStripOptTable : public opt::OptTable { public: - BitcodeStripOptTable() : opt::OptTable(bitcode_strip::OptionTables) {} + BitcodeStripOptTable() : opt::OptTable(bitcode_strip::optionTables()) {} }; enum StripID { @@ -102,7 +102,7 @@ namespace strip { class StripOptTable : public opt::OptTable { public: - StripOptTable() : OptTable(strip::OptionTables) { + StripOptTable() : OptTable(strip::optionTables()) { setGroupedShortOptions(true); } }; @@ -122,7 +122,8 @@ namespace extract_bundle_entry { class ExtractBundleEntryOptTable : public opt::OptTable { public: - ExtractBundleEntryOptTable() : OptTable(extract_bundle_entry::OptionTables) { + ExtractBundleEntryOptTable() + : OptTable(extract_bundle_entry::optionTables()) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 77aac37506d4f..ed45af32fbd8f 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -121,7 +121,7 @@ namespace objdump_opt { class ObjdumpOptTable : public CommonOptTable { public: ObjdumpOptTable() - : CommonOptTable(objdump_opt::OptionTables, + : CommonOptTable(objdump_opt::optionTables(), " [options] <input object files>", "llvm object file dumper") {} }; @@ -141,7 +141,7 @@ namespace otool { class OtoolOptTable : public CommonOptTable { public: OtoolOptTable() - : CommonOptTable(otool::OptionTables, " [option...] [file...]", + : CommonOptTable(otool::optionTables(), " [option...] [file...]", "Mach-O object file displaying tool") {} }; diff --git a/llvm/tools/llvm-rc/llvm-rc.cpp b/llvm/tools/llvm-rc/llvm-rc.cpp index a091ae5ec6b5b..7be5b16dce3ba 100644 --- a/llvm/tools/llvm-rc/llvm-rc.cpp +++ b/llvm/tools/llvm-rc/llvm-rc.cpp @@ -63,7 +63,7 @@ namespace rc_opt { class RcOptTable : public opt::OptTable { public: - RcOptTable() : OptTable(rc_opt::OptionTables, /* IgnoreCase = */ true) {} + RcOptTable() : OptTable(rc_opt::optionTables(), /* IgnoreCase = */ true) {} }; enum Windres_ID { @@ -81,7 +81,7 @@ namespace windres_opt { class WindresOptTable : public opt::OptTable { public: WindresOptTable() - : OptTable(windres_opt::OptionTables, /* IgnoreCase = */ false) {} + : OptTable(windres_opt::optionTables(), /* IgnoreCase = */ false) {} }; static ExitOnError ExitOnErr; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index 51f2fb326863f..6ec0563d6d327 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -64,7 +64,7 @@ enum ID { class ReadobjOptTable : public opt::OptTable { public: - ReadobjOptTable() : opt::OptTable(OptionTables) { + ReadobjOptTable() : opt::OptTable(optionTables()) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-readtapi/llvm-readtapi.cpp b/llvm/tools/llvm-readtapi/llvm-readtapi.cpp index aea79e3c0872e..f032e90401d10 100644 --- a/llvm/tools/llvm-readtapi/llvm-readtapi.cpp +++ b/llvm/tools/llvm-readtapi/llvm-readtapi.cpp @@ -50,7 +50,9 @@ enum ID { class TAPIOptTable : public opt::OptTable { public: - TAPIOptTable() : opt::OptTable(OptionTables) { setGroupedShortOptions(true); } + TAPIOptTable() : opt::OptTable(optionTables()) { + setGroupedShortOptions(true); + } }; struct StubOptions { diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp index b58306c780f82..66195fdbe4f56 100644 --- a/llvm/tools/llvm-size/llvm-size.cpp +++ b/llvm/tools/llvm-size/llvm-size.cpp @@ -50,7 +50,7 @@ enum ID { class SizeOptTable : public opt::OptTable { public: - SizeOptTable() : OptTable(OptionTables) { setGroupedShortOptions(true); } + SizeOptTable() : OptTable(optionTables()) { setGroupedShortOptions(true); } }; enum OutputFormatTy { berkeley, sysv, darwin }; diff --git a/llvm/tools/llvm-strings/llvm-strings.cpp b/llvm/tools/llvm-strings/llvm-strings.cpp index 04c0f3a16454b..f2abd1c3271a8 100644 --- a/llvm/tools/llvm-strings/llvm-strings.cpp +++ b/llvm/tools/llvm-strings/llvm-strings.cpp @@ -44,7 +44,7 @@ using namespace llvm::opt; class StringsOptTable : public opt::OptTable { public: - StringsOptTable() : OptTable(OptionTables) { + StringsOptTable() : OptTable(optionTables()) { setGroupedShortOptions(true); setDashDashParsing(true); } diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp index a820126cf265c..c82cb11ade1ca 100644 --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -62,7 +62,7 @@ using namespace llvm::opt; class SymbolizerOptTable : public opt::OptTable { public: - SymbolizerOptTable() : OptTable(OptionTables) { + SymbolizerOptTable() : OptTable(optionTables()) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp b/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp index 1b045d7291cf3..8e67d1a087d22 100644 --- a/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp +++ b/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp @@ -39,7 +39,7 @@ using namespace llvm::opt; class TLICheckerOptTable : public opt::OptTable { public: - TLICheckerOptTable() : OptTable(OptionTables) {} + TLICheckerOptTable() : OptTable(optionTables()) {} }; } // end anonymous namespace diff --git a/llvm/tools/sancov/sancov.cpp b/llvm/tools/sancov/sancov.cpp index 0d91ffb798bcb..2d20caee8355a 100644 --- a/llvm/tools/sancov/sancov.cpp +++ b/llvm/tools/sancov/sancov.cpp @@ -73,7 +73,7 @@ enum ID { class SancovOptTable : public opt::OptTable { public: - SancovOptTable() : OptTable(OptionTables) {} + SancovOptTable() : OptTable(optionTables()) {} }; } // namespace diff --git a/llvm/unittests/Option/OptionParsingTest.cpp b/llvm/unittests/Option/OptionParsingTest.cpp index 382de8ee7a195..6b45ea5ea8aa7 100644 --- a/llvm/unittests/Option/OptionParsingTest.cpp +++ b/llvm/unittests/Option/OptionParsingTest.cpp @@ -48,7 +48,7 @@ enum OptionVisibility { namespace { class TestOptTable : public OptTable { public: - TestOptTable(bool IgnoreCase = false) : OptTable(OptionTables, IgnoreCase) { + TestOptTable(bool IgnoreCase = false) : OptTable(optionTables(), IgnoreCase) { setValuesCodeFn(getOptionValuesCode); } }; diff --git a/llvm/unittests/Option/OptionSubCommandsTest.cpp b/llvm/unittests/Option/OptionSubCommandsTest.cpp index 8885ee2f83668..27405beeec0ef 100644 --- a/llvm/unittests/Option/OptionSubCommandsTest.cpp +++ b/llvm/unittests/Option/OptionSubCommandsTest.cpp @@ -37,7 +37,7 @@ enum ID { class TestOptSubCommandTable : public OptTable { public: TestOptSubCommandTable(bool IgnoreCase = false) - : OptTable(OptionTables, IgnoreCase) {} + : OptTable(optionTables(), IgnoreCase) {} }; // Test fixture diff --git a/llvm/utils/TableGen/OptionParserEmitter.cpp b/llvm/utils/TableGen/OptionParserEmitter.cpp index e4a3313e67a42..59a681ff2dd52 100644 --- a/llvm/utils/TableGen/OptionParserEmitter.cpp +++ b/llvm/utils/TableGen/OptionParserEmitter.cpp @@ -282,17 +282,10 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { SubCommandIDs.try_emplace(SubCommandKey, 0); } - DenseSet<StringRef> PrefixesUnionSet; - for (const auto &[Prefix, _] : Prefixes) - PrefixesUnionSet.insert_range(Prefix); - SmallVector<StringRef> PrefixesUnion(PrefixesUnionSet.begin(), - PrefixesUnionSet.end()); - array_pod_sort(PrefixesUnion.begin(), PrefixesUnion.end()); - llvm::StringToOffsetTable Table; - // We can add all the prefixes via the union. - for (const auto &Prefix : PrefixesUnion) - Table.GetOrAddStringOffset(Prefix); + for (const auto &[PrefixSet, _] : Prefixes) + for (const auto &Prefix : PrefixSet) + Table.GetOrAddStringOffset(Prefix); for (const Record &R : llvm::make_pointee_range(Groups)) { Table.GetOrAddStringOffset(R.getValueAsString("Name")); Table.GetOrAddStringOffset(getHelpText(R)); @@ -346,8 +339,7 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { OS << "#ifdef OPTTABLE_CODE\n"; // Dump prefixes. - OS << "static constexpr llvm::StringTable::Offset OptionPrefixesTable[] = " - "{\n"; + OS << "constexpr llvm::StringTable::Offset OptionPrefixesTable[] = {\n"; { // Ensure the first prefix set is always empty. assert(!Prefixes.empty() && @@ -370,20 +362,9 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { } OS << "\n};\n\n"; - // Dump prefixes union. - if (!PrefixesUnion.empty()) { - OS << "static constexpr llvm::StringTable::Offset OptionPrefixesUnion[] = " - "{\n"; - llvm::ListSeparator Sep(", "); - for (auto Prefix : PrefixesUnion) - OS << Sep << " " << *Table.GetStringOffset(Prefix) << " /* '" << Prefix - << "' */"; - OS << "\n};\n\n"; - } - // Dump help text variants. Each option's variants form a run ended by a zero // row; offset 0 is the empty run. - OS << "static constexpr llvm::opt::OptTable::HelpTextVariant " + OS << "constexpr llvm::opt::OptTable::HelpTextVariant " "OptionHelpTextVariantsTable[] = {\n"; DenseMap<const Record *, unsigned> HelpTextVariantsOffset; unsigned NumVariantRows = 1; @@ -413,8 +394,7 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { // Dump subcommands. if (!SubCommands.empty()) { - OS << "static constexpr llvm::opt::OptTable::SubCommand " - "OptionSubCommands[] = {\n"; + OS << "constexpr llvm::opt::OptTable::SubCommand OptionSubCommands[] = {\n"; for (const Record *SubCommand : SubCommands) { OS << " { \"" << SubCommand->getValueAsString("Name") << "\", "; OS << "\"" << SubCommand->getValueAsString("HelpText") << "\", "; @@ -424,7 +404,7 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { } // Dump subcommand IDs. - OS << "static constexpr unsigned OptionSubCommandIDsTable[] = {\n"; + OS << "constexpr unsigned OptionSubCommandIDsTable[] = {\n"; { // Ensure the first subcommand set is always empty. assert(!SubCommandIDs.empty() && @@ -454,7 +434,7 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { OS << "\n};\n\n"; // Dump the option table in OptTable::Info field order. - OS << "static constexpr llvm::opt::OptTable::Info OptionInfoTable[] = {\n"; + OS << "constexpr llvm::opt::OptTable::Info OptionInfoTable[] = {\n"; for (const Record &R : llvm::make_pointee_range(Groups)) { OS << " {"; writeStrTableOffset(OS, Table, R.getValueAsString("Name"), @@ -489,13 +469,13 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { } OS << "};\n\n"; - OS << "static constexpr llvm::opt::OptTable::Tables OptionTables = {\n"; - OS << " OptionStrTable, OptionPrefixesTable, " - << (PrefixesUnion.empty() ? "{}" : "OptionPrefixesUnion") - << ", OptionInfoTable,\n"; - OS << " OptionHelpTextVariantsTable, " + // A function rather than an object: the object needs relocations. + OS << "static constexpr llvm::opt::OptTable::Tables optionTables() {\n"; + OS << " return {OptionStrTable, OptionPrefixesTable, OptionInfoTable,\n"; + OS << " OptionHelpTextVariantsTable, " << (SubCommands.empty() ? "{}" : "OptionSubCommands") << ", OptionSubCommandIDsTable};\n"; + OS << "}\n"; OS << "#undef OPTTABLE_CODE\n"; OS << "#endif // OPTTABLE_CODE\n\n"; >From 080cc8090d9efaf54b2bd775b3e40d2f5b04b7ee Mon Sep 17 00:00:00 2001 From: Fangrui Song <[email protected]> Date: Fri, 18 Sep 2026 19:49:07 -0700 Subject: [PATCH 2/2] [Option] Shrink Info from 40 to 24 bytes Few options set MetaVar, AliasArgs, Values, help text variants, or subcommands (12%, 4%, 4%, 0.1%, 0.06% of 6955 options), yet every entry carries all five. Move them to a deduplicated InfoExtra side table reached by a 16-bit offset; row 0 serves options that set none. Narrow Visibility to 16 bits; clang uses seven. clang's table shrinks from 155 KB to 93 KB plus 4 KB of extras. Aided by Opus 5 --- llvm/include/llvm/Option/OptTable.h | 78 ++++++++++++--------- llvm/include/llvm/Option/Option.h | 9 +-- llvm/lib/Option/OptTable.cpp | 6 +- llvm/utils/TableGen/OptionParserEmitter.cpp | 72 ++++++++++--------- 4 files changed, 85 insertions(+), 80 deletions(-) diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h index 611cfe826a99f..6f8f9500f8fa6 100644 --- a/llvm/include/llvm/Option/OptTable.h +++ b/llvm/include/llvm/Option/OptTable.h @@ -73,6 +73,20 @@ class LLVM_ABI OptTable { StringTable::Offset HelpTextOffset; }; + /// Fields few options set. Row 0 is all zero and serves the options that set + /// none. + struct InfoExtra { + StringTable::Offset MetaVarOffset; + StringTable::Offset AliasArgsOffset; + /// The possible values as a comma separated list, empty for an option whose + /// values only getOptionValuesCode() knows. + StringTable::Offset ValuesOffset; + // Offset into OptTable's HelpTextVariantsTable; 0 for none. + unsigned short HelpTextVariantsOffset; + // Offset into OptTable's SubCommandIDsTable. + unsigned short SubCommandIDsOffset; + }; + /// Entry for a single option instance in the option data table. An option's /// ID is its 1-based position in the table. struct Info { @@ -80,21 +94,14 @@ class LLVM_ABI OptTable { /// Offset 0 means the .td supplied no HelpText. A HelpText<""> maps to a /// distinct empty string, marking the option deliberately undocumented. StringTable::Offset HelpTextOffset; - StringTable::Offset MetaVarOffset; - StringTable::Offset AliasArgsOffset; - /// The possible values as a comma separated list, empty for an option whose - /// values only getOptionValuesCode() knows. - StringTable::Offset ValuesOffset; unsigned Flags; - unsigned Visibility; + unsigned short Visibility; // Offset into OptTable's PrefixesTable. unsigned short PrefixesOffset; unsigned short GroupID; unsigned short AliasID; - // Offset into OptTable's HelpTextVariantsTable; 0 for none. - unsigned short HelpTextVariantsOffset; - // Offset into OptTable's SubCommandIDsTable. - unsigned short SubCommandIDsOffset; + // Offset into OptTable's InfoExtrasTable. + unsigned short ExtraOffset; unsigned char Kind; unsigned char Param; @@ -113,22 +120,6 @@ class LLVM_ABI OptTable { } bool hasHelpText() const { return HelpTextOffset.value() != 0; } - bool hasAliasArgs() const { return AliasArgsOffset.value() != 0; } - - bool hasSubCommands() const { return SubCommandIDsOffset != 0; } - - unsigned getNumSubCommandIDs(ArrayRef<unsigned> SubCommandIDsTable) const { - // We embed the number of subcommand IDs in the value of the first offset. - return SubCommandIDsTable[SubCommandIDsOffset]; - } - - ArrayRef<unsigned> - getSubCommandIDs(ArrayRef<unsigned> SubCommandIDsTable) const { - return hasSubCommands() ? SubCommandIDsTable.slice( - SubCommandIDsOffset + 1, - getNumSubCommandIDs(SubCommandIDsTable)) - : ArrayRef<unsigned>(); - } void appendPrefixes(const StringTable &StrTable, ArrayRef<StringTable::Offset> PrefixesTable, @@ -160,6 +151,7 @@ class LLVM_ABI OptTable { const StringTable &StrTable; ArrayRef<StringTable::Offset> PrefixesTable; ArrayRef<Info> Infos; + ArrayRef<InfoExtra> InfoExtras; ArrayRef<HelpTextVariant> HelpTextVariants; ArrayRef<SubCommand> SubCommands; ArrayRef<unsigned> SubCommandIDs; @@ -174,7 +166,7 @@ class LLVM_ABI OptTable { SubCommands, [&](const auto &C) { return SubCommand == C.Name; }); assert(SCIT != SubCommands.end() && "This helper is only for valid registered subcommands."); - auto SubCommandIDs = CandidateInfo->getSubCommandIDs(SubCommandIDsTable); + auto SubCommandIDs = getSubCommandIDs(*CandidateInfo); unsigned CurrentSubCommandID = SCIT - &SubCommands[0]; return llvm::is_contained(SubCommandIDs, CurrentSubCommandID); } @@ -193,6 +185,8 @@ class LLVM_ABI OptTable { /// The option information table. ArrayRef<Info> OptionInfos; + ArrayRef<InfoExtra> InfoExtrasTable; + bool IgnoreCase; /// The subcommand information table. @@ -229,24 +223,33 @@ class LLVM_ABI OptTable { return OptionInfos[id - 1]; } + const InfoExtra &getExtra(const Info &I) const { + return InfoExtrasTable[I.ExtraOffset]; + } + StringTable::Offset getHelpTextOffset(const Info &I, Visibility VisibilityMask) const { - if (I.HelpTextVariantsOffset) - for (const HelpTextVariant *V = - &HelpTextVariantsTable[I.HelpTextVariantsOffset]; - V->Visibility; ++V) - if (VisibilityMask & V->Visibility) - return V->HelpTextOffset; + for (const HelpTextVariant *V = + &HelpTextVariantsTable[getExtra(I).HelpTextVariantsOffset]; + V->Visibility; ++V) + if (VisibilityMask & V->Visibility) + return V->HelpTextOffset; return I.HelpTextOffset; } StringRef getOptionValues(const Info &I) const { - StringRef Values = (*StrTable)[I.ValuesOffset]; + StringRef Values = (*StrTable)[getExtra(I).ValuesOffset]; if (Values.empty() && ValuesCodeFn) Values = ValuesCodeFn(getOptionID(I)); return Values; } + ArrayRef<unsigned> getSubCommandIDs(const Info &I) const { + // A set starts with its size. + unsigned Offset = getExtra(I).SubCommandIDsOffset; + return SubCommandIDsTable.slice(Offset + 1, SubCommandIDsTable[Offset]); + } + std::unique_ptr<Arg> parseOneArgGrouped(InputArgList &Args, unsigned &Index) const; @@ -329,7 +332,12 @@ class LLVM_ABI OptTable { /// Get the meta-variable name to use when describing /// this options values in the help text. StringRef getOptionMetaVar(OptSpecifier id) const { - return (*StrTable)[getInfo(id).MetaVarOffset]; + return (*StrTable)[getExtra(getInfo(id)).MetaVarOffset]; + } + + /// Get the alias arguments as a \0 separated list, e.g. "foo\0bar\0". + const char *getOptionAliasArgs(OptSpecifier id) const { + return StrTable->getCString(getExtra(getInfo(id)).AliasArgsOffset); } /// Specify the environment variable where initial options should be read. diff --git a/llvm/include/llvm/Option/Option.h b/llvm/include/llvm/Option/Option.h index 1233ca5a42228..dd91be2e4c527 100644 --- a/llvm/include/llvm/Option/Option.h +++ b/llvm/include/llvm/Option/Option.h @@ -117,15 +117,10 @@ class Option { /// Get the alias arguments as a \0 separated list. /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0". const char *getAliasArgs() const { - assert(Info && "Must have a valid info!"); - assert(Owner && "Must have a valid owner!"); - return Owner->getStrTable().getCString(Info->AliasArgsOffset); + return Owner->getOptionAliasArgs(getID()); } - bool hasAliasArgs() const { - assert(Info && "Must have a valid info!"); - return Info->hasAliasArgs(); - } + bool hasAliasArgs() const { return *getAliasArgs() != '\0'; } /// Get the default prefix for this option. StringRef getPrefix() const { return Owner->getOptionPrefix(getID()); } diff --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp index 87487d625f7e4..ad7db113aa6e9 100644 --- a/llvm/lib/Option/OptTable.cpp +++ b/llvm/lib/Option/OptTable.cpp @@ -75,7 +75,8 @@ OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {} OptTable::OptTable(const Tables &T, bool IgnoreCase) : StrTable(&T.StrTable), PrefixesTable(T.PrefixesTable), - OptionInfos(T.Infos), IgnoreCase(IgnoreCase), SubCommands(T.SubCommands), + OptionInfos(T.Infos), InfoExtrasTable(T.InfoExtras), + IgnoreCase(IgnoreCase), SubCommands(T.SubCommands), SubCommandIDsTable(T.SubCommandIDs), HelpTextVariantsTable(T.HelpTextVariants) { // Each prefix set in PrefixesTable starts with its size. @@ -770,8 +771,7 @@ void OptTable::internalPrintHelp( auto DoesOptionBelongToSubcommand = [&](const Info &CandidateInfo) { // Retrieve the SubCommandIDs registered to the given current CandidateInfo // Option. - ArrayRef<unsigned> SubCommandIDs = - CandidateInfo.getSubCommandIDs(SubCommandIDsTable); + ArrayRef<unsigned> SubCommandIDs = getSubCommandIDs(CandidateInfo); // If no registered subcommands, then only global options are to be printed. // If no valid SubCommand (empty) in commandline then print the current diff --git a/llvm/utils/TableGen/OptionParserEmitter.cpp b/llvm/utils/TableGen/OptionParserEmitter.cpp index 59a681ff2dd52..ddc7e9f0f4ef4 100644 --- a/llvm/utils/TableGen/OptionParserEmitter.cpp +++ b/llvm/utils/TableGen/OptionParserEmitter.cpp @@ -18,6 +18,7 @@ #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringToOffsetTable.h" #include "llvm/TableGen/TableGenBackend.h" +#include <array> #include <cstring> #include <map> @@ -258,18 +259,11 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { using SubCommandIDsT = std::map<SubCommandKeyT, unsigned>; SubCommandIDsT SubCommandIDs; - auto PrintSubCommandIdsOffset = [&SubCommandIDs, &OS](const Record &R) { - if (R.getValue("SubCommands") != nullptr) { - std::vector<const Record *> SubCommands = - R.getValueAsListOfDefs("SubCommands"); - SubCommandKeyT SubCommandKey; - for (const auto &SubCommand : SubCommands) - SubCommandKey.push_back(SubCommand->getName()); - OS << SubCommandIDs[SubCommandKey]; - } else { - // The option SubCommandIDsOffset (for default top level toolname is 0). - OS << '0'; - } + auto GetSubCommandIDsOffset = [&SubCommandIDs](const Record &R) { + SubCommandKeyT SubCommandKey; + for (const Record *SubCommand : R.getValueAsListOfDefs("SubCommands")) + SubCommandKey.push_back(SubCommand->getName()); + return SubCommandIDs[SubCommandKey]; }; SubCommandIDs.try_emplace(SubCommandKeyT(), 0); @@ -433,6 +427,29 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { } OS << "\n};\n\n"; + // Rarely set fields, in OptTable::InfoExtra order. Options with equal values + // share a row; row 0 is all zero. + OS << "constexpr llvm::opt::OptTable::InfoExtra OptionInfoExtrasTable[] = " + "{\n {0, 0, 0, 0, 0},\n"; + std::map<std::array<unsigned, 5>, unsigned> ExtraRows; + ExtraRows.try_emplace({}, 0); + DenseMap<const Record *, unsigned> ExtraOffset; + for (const Record &R : llvm::make_pointee_range(Opts)) { + std::array<unsigned, 5> Row = { + *Table.GetStringOffset(getOptionalString(R, "MetaVarName")), + *Table.GetStringOffset(getAliasArgsBlob(R)), + *Table.GetStringOffset(getOptionalString(R, "Values")), + HelpTextVariantsOffset.lookup(&R), GetSubCommandIDsOffset(R)}; + auto [It, Inserted] = ExtraRows.try_emplace(Row, ExtraRows.size()); + if (Inserted) { + OS << " {"; + interleaveComma(Row, OS); + OS << "},\n"; + } + ExtraOffset[&R] = It->second; + } + OS << "};\n\n"; + // Dump the option table in OptTable::Info field order. OS << "constexpr llvm::opt::OptTable::Info OptionInfoTable[] = {\n"; for (const Record &R : llvm::make_pointee_range(Groups)) { @@ -441,9 +458,8 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { /*EmitComment=*/true); OS << ", "; writeStrTableOffset(OS, Table, getHelpText(R)); - OS << ", 0, 0, 0, 0, 0, 0, " << GetRefID(R, "Group") << ", 0, 0, "; - PrintSubCommandIdsOffset(R); - OS << ", llvm::opt::Option::GroupClass, 0},\n"; + OS << ", 0, 0, 0, " << GetRefID(R, "Group") + << ", 0, 0, llvm::opt::Option::GroupClass, 0},\n"; } for (const Record &R : llvm::make_pointee_range(Opts)) { OS << " {"; @@ -451,28 +467,20 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { /*EmitComment=*/true); OS << ", "; writeStrTableOffset(OS, Table, getHelpText(R)); - OS << ", "; - writeStrTableOffset(OS, Table, getOptionalString(R, "MetaVarName")); - OS << ", "; - writeStrTableOffset(OS, Table, getAliasArgsBlob(R)); - OS << ", "; - writeStrTableOffset(OS, Table, getOptionalString(R, "Values")); OS << ", " << GetMask(R, "Flags") << ", " << GetMask(R, "Visibility"); std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes"); OS << ", " << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())]; OS << ", " << GetRefID(R, "Group") << ", " << GetRefID(R, "Alias"); - OS << ", " << HelpTextVariantsOffset.lookup(&R) << ", "; - PrintSubCommandIdsOffset(R); - OS << ", llvm::opt::Option::" + OS << ", " << ExtraOffset.lookup(&R) << ", llvm::opt::Option::" << R.getValueAsDef("Kind")->getValueAsString("Name") << "Class, " << R.getValueAsInt("NumArgs") << "},\n"; } OS << "};\n\n"; - // A function rather than an object: the object needs relocations. + // A function rather than an object: the object needs dynamic relocations. OS << "static constexpr llvm::opt::OptTable::Tables optionTables() {\n"; OS << " return {OptionStrTable, OptionPrefixesTable, OptionInfoTable,\n"; - OS << " OptionHelpTextVariantsTable, " + OS << " OptionInfoExtrasTable, OptionHelpTextVariantsTable, " << (SubCommands.empty() ? "{}" : "OptionSubCommands") << ", OptionSubCommandIDsTable};\n"; OS << "}\n"; @@ -548,13 +556,8 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { // The option meta-variable name (unused). OS << ", 0"; - // The option Values (unused for groups). - OS << ", 0"; - - // The option SubCommandIDsOffset. - OS << ", "; - PrintSubCommandIdsOffset(R); - OS << ")\n"; + // The option Values and SubCommandIDsOffset (unused for groups). + OS << ", 0, 0)\n"; } OS << "\n"; @@ -619,8 +622,7 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { writeStrTableOffset(OS, Table, getOptionalString(R, "Values")); // The option SubCommandIDsOffset. - OS << ", "; - PrintSubCommandIdsOffset(R); + OS << ", " << GetSubCommandIDsOffset(R); }; auto IsMarshallingOption = [](const Record &R) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
