diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index fddfffe7523d9..207e4c3e6722c 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -458,20 +458,6 @@ llvm::ArrayRef ArgStripper::rulesFor(llvm::StringRef Arg) { PrevAlias[Self] = T; NextAlias[T] = Self; }; - // Also grab prefixes for each option, these are not fully exposed. - llvm::ArrayRef Prefixes[DriverID::LastOption]; - -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); -#define OPTION(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, \ - FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ - METAVAR, VALUES) \ - Prefixes[DriverID::OPT_##ID] = PREFIX; -#include "clang/Driver/Options.inc" -#undef OPTION -#undef PREFIX struct { DriverID ID; @@ -498,7 +484,9 @@ llvm::ArrayRef ArgStripper::rulesFor(llvm::StringRef Arg) { llvm::SmallVector Rules; // Iterate over each alias, to add rules for parsing it. for (unsigned A = ID; A != DriverID::OPT_INVALID; A = NextAlias[A]) { - if (!Prefixes[A].size()) // option groups. + llvm::SmallVector Prefixes; + DriverTable.appendOptionPrefixes(A, Prefixes); + if (Prefixes.empty()) // option groups. continue; auto Opt = DriverTable.getOption(A); // Exclude - and -foo pseudo-options. @@ -507,7 +495,7 @@ llvm::ArrayRef ArgStripper::rulesFor(llvm::StringRef Arg) { auto Modes = getModes(Opt); std::pair ArgCount = getArgCount(Opt); // Iterate over each spelling of the alias, e.g. -foo vs --foo. - for (StringRef Prefix : Prefixes[A]) { + for (StringRef Prefix : Prefixes) { llvm::SmallString<64> Buf(Prefix); Buf.append(Opt.getName()); llvm::StringRef Spelling = Result->try_emplace(Buf).first->getKey(); diff --git a/clang/lib/Driver/DriverOptions.cpp b/clang/lib/Driver/DriverOptions.cpp index 053e7f1c6404f..cde1f8989935b 100644 --- a/clang/lib/Driver/DriverOptions.cpp +++ b/clang/lib/Driver/DriverOptions.cpp @@ -14,24 +14,21 @@ using namespace clang::driver; using namespace clang::driver::options; using namespace llvm::opt; +#define OPTTABLE_STR_TABLE_CODE +#include "clang/Driver/Options.inc" +#undef OPTTABLE_STR_TABLE_CODE + #define OPTTABLE_VALUES_CODE #include "clang/Driver/Options.inc" #undef OPTTABLE_VALUES_CODE -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "clang/Driver/Options.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE -static constexpr const llvm::StringLiteral PrefixTable_init[] = -#define PREFIX_UNION(VALUES) VALUES +#define OPTTABLE_PREFIXES_UNION_CODE #include "clang/Driver/Options.inc" -#undef PREFIX_UNION - ; -static constexpr const llvm::ArrayRef - PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1); +#undef OPTTABLE_PREFIXES_UNION_CODE static constexpr OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -43,7 +40,9 @@ namespace { class DriverOptTable : public PrecomputedOptTable { public: - DriverOptTable() : PrecomputedOptTable(InfoTable, PrefixTable) {} + DriverOptTable() + : PrecomputedOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + OptionPrefixesUnion) {} }; } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 98136b7a455d9..23906d5c06d38 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -277,6 +277,14 @@ CowCompilerInvocation::getMutPreprocessorOutputOpts() { using ArgumentConsumer = CompilerInvocation::ArgumentConsumer; +#define OPTTABLE_STR_TABLE_CODE +#include "clang/Driver/Options.inc" +#undef OPTTABLE_STR_TABLE_CODE + +static llvm::StringRef lookupStrInTable(unsigned Offset) { + return &OptionStrTable[Offset]; +} + #define SIMPLE_ENUM_VALUE_TABLE #include "clang/Driver/Options.inc" #undef SIMPLE_ENUM_VALUE_TABLE @@ -303,6 +311,11 @@ static std::optional normalizeSimpleNegativeFlag(OptSpecifier Opt, /// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with /// unnecessary template instantiations and just ignore it with a variadic /// argument. +static void denormalizeSimpleFlag(ArgumentConsumer Consumer, + unsigned SpellingOffset, Option::OptionClass, + unsigned, /*T*/...) { + Consumer(lookupStrInTable(SpellingOffset)); +} static void denormalizeSimpleFlag(ArgumentConsumer Consumer, const Twine &Spelling, Option::OptionClass, unsigned, /*T*/...) { @@ -343,10 +356,10 @@ static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue, } static auto makeBooleanOptionDenormalizer(bool Value) { - return [Value](ArgumentConsumer Consumer, const Twine &Spelling, + return [Value](ArgumentConsumer Consumer, unsigned SpellingOffset, Option::OptionClass, unsigned, bool KeyPath) { if (KeyPath == Value) - Consumer(Spelling); + Consumer(lookupStrInTable(SpellingOffset)); }; } @@ -371,6 +384,14 @@ static void denormalizeStringImpl(ArgumentConsumer Consumer, } } +template +static void +denormalizeString(ArgumentConsumer Consumer, unsigned SpellingOffset, + Option::OptionClass OptClass, unsigned TableIndex, T Value) { + denormalizeStringImpl(Consumer, lookupStrInTable(SpellingOffset), OptClass, + TableIndex, Twine(Value)); +} + template static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling, Option::OptionClass OptClass, unsigned TableIndex, @@ -417,14 +438,14 @@ static std::optional normalizeSimpleEnum(OptSpecifier Opt, } static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer, - const Twine &Spelling, + unsigned SpellingOffset, Option::OptionClass OptClass, unsigned TableIndex, unsigned Value) { assert(TableIndex < SimpleEnumValueTablesSize); const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex]; if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) { - denormalizeString(Consumer, Spelling, OptClass, TableIndex, - MaybeEnumVal->Name); + denormalizeString(Consumer, lookupStrInTable(SpellingOffset), OptClass, + TableIndex, MaybeEnumVal->Name); } else { llvm_unreachable("The simple enum value was not correctly defined in " "the tablegen option description"); @@ -433,11 +454,11 @@ static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer, template static void denormalizeSimpleEnum(ArgumentConsumer Consumer, - const Twine &Spelling, + unsigned SpellingOffset, Option::OptionClass OptClass, unsigned TableIndex, T Value) { - return denormalizeSimpleEnumImpl(Consumer, Spelling, OptClass, TableIndex, - static_cast(Value)); + return denormalizeSimpleEnumImpl(Consumer, SpellingOffset, OptClass, + TableIndex, static_cast(Value)); } static std::optional normalizeString(OptSpecifier Opt, @@ -473,7 +494,7 @@ normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args, } static void denormalizeStringVector(ArgumentConsumer Consumer, - const Twine &Spelling, + unsigned SpellingOffset, Option::OptionClass OptClass, unsigned TableIndex, const std::vector &Values) { @@ -487,15 +508,16 @@ static void denormalizeStringVector(ArgumentConsumer Consumer, CommaJoinedValue.append(Value); } } - denormalizeString(Consumer, Spelling, Option::OptionClass::JoinedClass, - TableIndex, CommaJoinedValue); + denormalizeString(Consumer, SpellingOffset, + Option::OptionClass::JoinedClass, TableIndex, + CommaJoinedValue); break; } case Option::JoinedClass: case Option::SeparateClass: case Option::JoinedOrSeparateClass: for (const std::string &Value : Values) - denormalizeString(Consumer, Spelling, OptClass, TableIndex, Value); + denormalizeString(Consumer, SpellingOffset, OptClass, TableIndex, Value); break; default: llvm_unreachable("Cannot denormalize an option with option class " @@ -532,10 +554,11 @@ static T extractMaskValue(T KeyPath) { } #define PARSE_OPTION_WITH_MARSHALLING( \ - ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, \ - FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \ - SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \ - IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ + ARGS, DIAGS, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS, \ + ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ + METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \ + IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, \ + TABLE_INDEX) \ if ((VISIBILITY) & options::CC1Option) { \ KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \ if (IMPLIED_CHECK) \ @@ -549,8 +572,8 @@ static T extractMaskValue(T KeyPath) { // Capture the extracted value as a lambda argument to avoid potential issues // with lifetime extension of the reference. #define GENERATE_OPTION_WITH_MARSHALLING( \ - CONSUMER, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ - VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \ + CONSUMER, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \ + FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \ SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \ IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ if ((VISIBILITY) & options::CC1Option) { \ @@ -559,8 +582,8 @@ static T extractMaskValue(T KeyPath) { (Extracted != \ static_cast((IMPLIED_CHECK) ? (IMPLIED_VALUE) \ : (DEFAULT_VALUE)))) \ - DENORMALIZER(CONSUMER, SPELLING, Option::KIND##Class, TABLE_INDEX, \ - Extracted); \ + DENORMALIZER(CONSUMER, SPELLING_OFFSET, Option::KIND##Class, \ + TABLE_INDEX, Extracted); \ }(EXTRACTOR(KEYPATH)); \ } diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index 3fa79636de5d7..8a2c3463189fa 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -31,41 +31,21 @@ namespace drv = clang::driver::options; namespace clang { namespace installapi { -/// Create prefix string literals used in InstallAPIOpts.td. -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "InstallAPIOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE -static constexpr const llvm::StringLiteral PrefixTable_init[] = -#define PREFIX_UNION(VALUES) VALUES +#define OPTTABLE_PREFIXES_TABLE_CODE #include "InstallAPIOpts.inc" -#undef PREFIX_UNION - ; -static constexpr const ArrayRef - PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1); +#undef OPTTABLE_PREFIXES_TABLE_CODE + +#define OPTTABLE_PREFIXES_UNION_CODE +#include "InstallAPIOpts.inc" +#undef OPTTABLE_PREFIXES_UNION_CODE /// Create table mapping all options defined in InstallAPIOpts.td. static constexpr OptTable::Info InfoTable[] = { -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ - VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, \ - VALUES) \ - {PREFIX, \ - NAME, \ - HELPTEXT, \ - HELPTEXTSFORVARIANTS, \ - METAVAR, \ - OPT_##ID, \ - Option::KIND##Class, \ - PARAM, \ - FLAGS, \ - VISIBILITY, \ - OPT_##GROUP, \ - OPT_##ALIAS, \ - ALIASARGS, \ - VALUES}, +#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), #include "InstallAPIOpts.inc" #undef OPTION }; @@ -75,7 +55,9 @@ namespace { /// \brief Create OptTable class for parsing actual command line arguments. class DriverOptTable : public opt::PrecomputedOptTable { public: - DriverOptTable() : PrecomputedOptTable(InfoTable, PrefixTable) {} + DriverOptTable() + : PrecomputedOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + OptionPrefixesUnion) {} }; } // end anonymous namespace. diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index ebafd7eb7774e..fae32a3503c18 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -174,12 +174,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "LinkerWrapperOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "LinkerWrapperOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -189,7 +190,8 @@ static constexpr OptTable::Info InfoTable[] = { class WrapperOptTable : public opt::GenericOptTable { public: - WrapperOptTable() : opt::GenericOptTable(InfoTable) {} + WrapperOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; const OptTable &getOptTable() { diff --git a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp index bc191afdca739..faf73a7c2f193 100644 --- a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp +++ b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp @@ -109,12 +109,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "NVLinkOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "NVLinkOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -124,7 +125,8 @@ static constexpr OptTable::Info InfoTable[] = { class WrapperOptTable : public opt::GenericOptTable { public: - WrapperOptTable() : opt::GenericOptTable(InfoTable) {} + WrapperOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; const OptTable &getOptTable() { diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index 58b56dcfd3bec..bd36181fca3f3 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -50,12 +50,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE const llvm::opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -65,7 +66,8 @@ const llvm::opt::OptTable::Info InfoTable[] = { class ScanDepsOptTable : public llvm::opt::GenericOptTable { public: - ScanDepsOptTable() : GenericOptTable(InfoTable) { + ScanDepsOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp index 076458a275d98..2bcb3757d49d0 100644 --- a/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp +++ b/clang/tools/clang-sycl-linker/ClangSYCLLinker.cpp @@ -88,12 +88,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "SYCLLinkOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "SYCLLinkOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -103,7 +104,8 @@ static constexpr OptTable::Info InfoTable[] = { class LinkerOptTable : public opt::GenericOptTable { public: - LinkerOptTable() : opt::GenericOptTable(InfoTable) {} + LinkerOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; const OptTable &getOptTable() { diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index c1b3272a1f49e..1148be09fb10c 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -845,13 +845,14 @@ MemoryBufferRef LinkerDriver::convertResToCOFF(ArrayRef mbs, // Create OptTable +#define OPTTABLE_STR_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_STR_TABLE_CODE + // Create prefix string literals used in Options.td -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE // Create table mapping all options defined in Options.td static constexpr llvm::opt::OptTable::Info infoTable[] = { @@ -860,7 +861,8 @@ static constexpr llvm::opt::OptTable::Info infoTable[] = { #undef OPTION }; -COFFOptTable::COFFOptTable() : GenericOptTable(infoTable, true) {} +COFFOptTable::COFFOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, infoTable, 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 4c88723f090d0..6d027c529c19e 100644 --- a/lld/ELF/DriverUtils.cpp +++ b/lld/ELF/DriverUtils.cpp @@ -33,13 +33,14 @@ using namespace lld::elf; // Create OptTable +#define OPTTABLE_STR_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_STR_TABLE_CODE + // Create prefix string literals used in Options.td -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE // Create table mapping all options defined in Options.td static constexpr opt::OptTable::Info optInfo[] = { @@ -48,7 +49,8 @@ static constexpr opt::OptTable::Info optInfo[] = { #undef OPTION }; -ELFOptTable::ELFOptTable() : GenericOptTable(optInfo) {} +ELFOptTable::ELFOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, optInfo) {} // 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 308c5eaf8c317..69d023c23b3c7 100644 --- a/lld/MachO/DriverUtils.cpp +++ b/lld/MachO/DriverUtils.cpp @@ -34,13 +34,14 @@ using namespace llvm::sys; using namespace lld; using namespace lld::macho; +#define OPTTABLE_STR_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_STR_TABLE_CODE + // Create prefix string literals used in Options.td -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE // Create table mapping all options defined in Options.td static constexpr OptTable::Info optInfo[] = { @@ -65,7 +66,8 @@ static constexpr OptTable::Info optInfo[] = { #undef OPTION }; -MachOOptTable::MachOOptTable() : GenericOptTable(optInfo) {} +MachOOptTable::MachOOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, optInfo) {} // 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 b4371b5b2240d..a77d86b443a6c 100644 --- a/lld/MinGW/Driver.cpp +++ b/lld/MinGW/Driver.cpp @@ -58,13 +58,13 @@ enum { #undef OPTION }; -// Create prefix string literals used in Options.td -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE // Create table mapping all options defined in Options.td static constexpr opt::OptTable::Info infoTable[] = { @@ -92,7 +92,9 @@ static constexpr opt::OptTable::Info infoTable[] = { namespace { class MinGWOptTable : public opt::GenericOptTable { public: - MinGWOptTable() : opt::GenericOptTable(infoTable, false) {} + MinGWOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, infoTable, + false) {} opt::InputArgList parse(ArrayRef argv); }; } // namespace diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index 37a0156c728f6..00b5c82d9c777 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -139,13 +139,13 @@ bool link(ArrayRef args, llvm::raw_ostream &stdoutOS, return errorCount() == 0; } -// Create prefix string literals used in Options.td -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE // Create table mapping all options defined in Options.td static constexpr opt::OptTable::Info optInfo[] = { @@ -173,7 +173,8 @@ static constexpr opt::OptTable::Info optInfo[] = { namespace { class WasmOptTable : public opt::GenericOptTable { public: - WasmOptTable() : opt::GenericOptTable(optInfo) {} + WasmOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, optInfo) {} opt::InputArgList parse(ArrayRef argv); }; } // namespace diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index 8baf3a8d60c37..2a36f95c94d0c 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -54,6 +54,10 @@ using namespace lldb; using namespace lldb_private; +#define OPTTABLE_STR_TABLE_CODE +#include "clang/Driver/Options.inc" +#undef OPTTABLE_STR_TABLE_CODE + static Status ExceptionMaskValidator(const char *string, void *unused) { Status error; llvm::StringRef str_ref(string); @@ -1078,8 +1082,8 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( // clang has no version-min clang flag for XROS. if (!version.empty() && sdk_type != XcodeSDK::Type::Linux && sdk_type != XcodeSDK::Type::XROS) { -#define OPTION(PREFIX, NAME, VAR, ...) \ - llvm::StringRef opt_##VAR = NAME; \ +#define OPTION(PREFIX_OFFSET, NAME_OFFSET, VAR, ...) \ + llvm::StringRef opt_##VAR = &OptionStrTable[NAME_OFFSET]; \ (void)opt_##VAR; #include "clang/Driver/Options.inc" #undef OPTION diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index afb1a1ff95c3a..98c3643f75c97 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -61,12 +61,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -76,7 +77,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class LLDBOptTable : public opt::GenericOptTable { public: - LLDBOptTable() : opt::GenericOptTable(InfoTable) {} + LLDBOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // namespace diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 3bfc578806021..7e8f7b5f6df67 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -92,12 +92,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr llvm::opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -106,7 +107,9 @@ static constexpr llvm::opt::OptTable::Info InfoTable[] = { }; class LLDBDAPOptTable : public llvm::opt::GenericOptTable { public: - LLDBDAPOptTable() : llvm::opt::GenericOptTable(InfoTable, true) {} + LLDBDAPOptTable() + : llvm::opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, + InfoTable, true) {} }; typedef void (*RequestCallback)(const llvm::json::Object &command); diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp index ed10c161b6b2f..fec868b1fa9a1 100644 --- a/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -291,12 +291,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "LLGSOptions.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "LLGSOptions.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -306,7 +307,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class LLGSOptTable : public opt::GenericOptTable { public: - LLGSOptTable() : opt::GenericOptTable(InfoTable) {} + LLGSOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} void PrintHelp(llvm::StringRef Name) { std::string Usage = diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h index 8fabc78d81aed..decb6cb5455eb 100644 --- a/llvm/include/llvm/Option/OptTable.h +++ b/llvm/include/llvm/Option/OptTable.h @@ -53,10 +53,8 @@ class OptTable { public: /// Entry for a single option instance in the option data table. struct Info { - /// A null terminated array of prefix strings to apply to name while - /// matching. - ArrayRef Prefixes; - StringLiteral PrefixedName; + unsigned PrefixesOffset; + unsigned PrefixedNameOffset; const char *HelpText; // Help text for specific visibilities. A list of pairs, where each pair // is a list of visibilities and a specific help string for those @@ -80,15 +78,56 @@ class OptTable { const char *AliasArgs; const char *Values; - StringRef getName() const { - unsigned PrefixLength = Prefixes.empty() ? 0 : Prefixes[0].size(); - return PrefixedName.drop_front(PrefixLength); + bool hasNoPrefix() const { return PrefixesOffset == 0; } + + unsigned getNumPrefixes(ArrayRef PrefixesTable) const { + return PrefixesTable[PrefixesOffset]; + } + + ArrayRef + getPrefixOffsets(ArrayRef PrefixesTable) const { + return hasNoPrefix() ? ArrayRef() + : PrefixesTable.slice(PrefixesOffset + 1, + getNumPrefixes(PrefixesTable)); + } + + void appendPrefixes(const char *StrTable, ArrayRef PrefixesTable, + SmallVectorImpl &Prefixes) const { + for (unsigned PrefixOffset : getPrefixOffsets(PrefixesTable)) + Prefixes.push_back(&StrTable[PrefixOffset]); + } + + StringRef getPrefix(const char *StrTable, ArrayRef PrefixesTable, + unsigned PrefixIndex) const { + return &StrTable[getPrefixOffsets(PrefixesTable)[PrefixIndex]]; + } + + StringRef getPrefixedName(const char *StrTable) const { + return &StrTable[PrefixedNameOffset]; + } + + StringRef getName(const char *StrTable, + ArrayRef PrefixesTable) const { + unsigned PrefixLength = + hasNoPrefix() ? 0 : getPrefix(StrTable, PrefixesTable, 0).size(); + return getPrefixedName(StrTable).drop_front(PrefixLength); } }; private: + // A unified string table for these options. Individual strings are stored as + // null terminated C-strings at offsets within this table. + const char *StrTable; + + // A table of different sets of prefixes. Each set starts with the number of + // prefixes in that set followed by that many offsets into the string table + // for each of the prefix strings. This is essentially a Pascal-string style + // encoding. + ArrayRef PrefixesTable; + /// The option information table. ArrayRef OptionInfos; + bool IgnoreCase; bool GroupedShortOptions = false; bool DashDashParsing = false; @@ -102,12 +141,12 @@ class OptTable { /// special option like 'input' or 'unknown', and is not an option group). unsigned FirstSearchableIndex = 0; - /// The union of the first element of all option prefixes. - SmallString<8> PrefixChars; - /// The union of all option prefixes. If an argument does not begin with /// one of these, it is an input. - virtual ArrayRef getPrefixesUnion() const = 0; + SmallVector PrefixesUnion; + + /// The union of the first element of all option prefixes. + SmallString<8> PrefixChars; private: const Info &getInfo(OptSpecifier Opt) const { @@ -122,7 +161,8 @@ class OptTable { protected: /// Initialize OptTable using Tablegen'ed OptionInfos. Child class must /// manually call \c buildPrefixChars once they are fully constructed. - OptTable(ArrayRef OptionInfos, bool IgnoreCase = false); + OptTable(const char *StrTable, ArrayRef PrefixesTable, + ArrayRef OptionInfos, bool IgnoreCase = false); /// Build (or rebuild) the PrefixChars member. void buildPrefixChars(); @@ -130,6 +170,12 @@ class OptTable { public: virtual ~OptTable(); + /// Return the string table used for option names. + const char *getStrTable() const { return StrTable; } + + /// Return the prefixes table used for option names. + ArrayRef getPrefixesTable() const { return PrefixesTable; } + /// Return the total number of option classes. unsigned getNumOptions() const { return OptionInfos.size(); } @@ -141,7 +187,25 @@ class OptTable { /// Lookup the name of the given option. StringRef getOptionName(OptSpecifier id) const { - return getInfo(id).getName(); + return getInfo(id).getName(StrTable, PrefixesTable); + } + + /// Lookup the prefix of the given option. + StringRef getOptionPrefix(OptSpecifier id) const { + const Info &I = getInfo(id); + return I.hasNoPrefix() ? StringRef() + : I.getPrefix(StrTable, PrefixesTable, 0); + } + + void appendOptionPrefixes(OptSpecifier id, + SmallVectorImpl &Prefixes) const { + const Info &I = getInfo(id); + I.appendPrefixes(StrTable, PrefixesTable, Prefixes); + } + + /// Lookup the prefixed name of the given option. + StringRef getOptionPrefixedName(OptSpecifier id) const { + return getInfo(id).getPrefixedName(StrTable); } /// Get the kind of the given option. @@ -353,28 +417,22 @@ class OptTable { /// Specialization of OptTable class GenericOptTable : public OptTable { - SmallVector PrefixesUnionBuffer; - protected: - GenericOptTable(ArrayRef OptionInfos, bool IgnoreCase = false); - ArrayRef getPrefixesUnion() const final { - return PrefixesUnionBuffer; - } + GenericOptTable(const char *StrTable, ArrayRef PrefixesTable, + ArrayRef OptionInfos, bool IgnoreCase = false); }; class PrecomputedOptTable : public OptTable { - ArrayRef PrefixesUnion; - protected: - PrecomputedOptTable(ArrayRef OptionInfos, - ArrayRef PrefixesTable, + PrecomputedOptTable(const char *StrTable, ArrayRef PrefixesTable, + ArrayRef OptionInfos, + ArrayRef PrefixesUnionOffsets, bool IgnoreCase = false) - : OptTable(OptionInfos, IgnoreCase), PrefixesUnion(PrefixesTable) { + : OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase) { + for (unsigned PrefixOffset : PrefixesUnionOffsets) + PrefixesUnion.push_back(&StrTable[PrefixOffset]); buildPrefixChars(); } - ArrayRef getPrefixesUnion() const final { - return PrefixesUnion; - } }; } // end namespace opt @@ -382,31 +440,35 @@ class PrecomputedOptTable : public OptTable { } // end namespace llvm #define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX( \ - ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, \ - FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ + ID_PREFIX, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ + ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ + METAVAR, VALUES) \ ID_PREFIX##ID -#define LLVM_MAKE_OPT_ID(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, \ - ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, \ - HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ - LLVM_MAKE_OPT_ID_WITH_ID_PREFIX( \ - OPT_, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ - VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUE) +#define LLVM_MAKE_OPT_ID(PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, \ + GROUP, ALIAS, ALIASARGS, FLAGS, VISIBILITY, PARAM, \ + HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ + LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OPT_, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, \ + ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ + VISIBILITY, PARAM, HELPTEXT, \ + HELPTEXTSFORVARIANTS, METAVAR, VALUE) #define LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX( \ - ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, \ - FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ + ID_PREFIX, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ + ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ + METAVAR, VALUES) \ llvm::opt::OptTable::Info { \ - PREFIX, PREFIXED_NAME, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, \ - ID_PREFIX##ID, llvm::opt::Option::KIND##Class, PARAM, FLAGS, \ + PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, HELPTEXT, HELPTEXTSFORVARIANTS, \ + METAVAR, ID_PREFIX##ID, llvm::opt::Option::KIND##Class, PARAM, FLAGS, \ VISIBILITY, ID_PREFIX##GROUP, ID_PREFIX##ALIAS, ALIASARGS, VALUES \ } -#define LLVM_CONSTRUCT_OPT_INFO(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, \ - ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, \ - HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ +#define LLVM_CONSTRUCT_OPT_INFO( \ + PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \ + FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX( \ - OPT_, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ - VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) + OPT_, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ + ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ + METAVAR, VALUES) #endif // LLVM_OPTION_OPTTABLE_H diff --git a/llvm/include/llvm/Option/Option.h b/llvm/include/llvm/Option/Option.h index 5d16fbdb6b77c..a0563da15c8ed 100644 --- a/llvm/include/llvm/Option/Option.h +++ b/llvm/include/llvm/Option/Option.h @@ -100,7 +100,8 @@ class Option { /// Get the name of this option without any prefix. StringRef getName() const { assert(Info && "Must have a valid info!"); - return Info->getName(); + assert(Owner && "Must have a valid owner!"); + return Owner->getOptionName(Info->ID); } const Option getGroup() const { @@ -127,15 +128,16 @@ class Option { /// Get the default prefix for this option. StringRef getPrefix() const { - return Info->Prefixes.empty() - ? StringRef() - : static_cast(Info->Prefixes[0]); + assert(Info && "Must have a valid info!"); + assert(Owner && "Must have a valid owner!"); + return Owner->getOptionPrefix(Info->ID); } /// Get the name of this option with the default prefix. - StringLiteral getPrefixedName() const { + StringRef getPrefixedName() const { assert(Info && "Must have a valid info!"); - return Info->PrefixedName; + assert(Owner && "Must have a valid owner!"); + return Owner->getOptionPrefixedName(Info->ID); } /// Get the help text for this option. diff --git a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp index f23f3ed9406bd..ecf5c0e519cae 100644 --- a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp @@ -19,21 +19,17 @@ using namespace jitlink; #define DEBUG_TYPE "jitlink" -// Create prefix string literals used in Options.td -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "COFFOptions.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE -static constexpr const StringLiteral PrefixTable_init[] = -#define PREFIX_UNION(VALUES) VALUES +#define OPTTABLE_PREFIXES_TABLE_CODE #include "COFFOptions.inc" -#undef PREFIX_UNION - ; -static constexpr const ArrayRef - PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1); +#undef OPTTABLE_PREFIXES_TABLE_CODE + +#define OPTTABLE_PREFIXES_UNION_CODE +#include "COFFOptions.inc" +#undef OPTTABLE_PREFIXES_UNION_CODE // Create table mapping all options defined in COFFOptions.td using namespace llvm::opt; @@ -46,7 +42,9 @@ static constexpr opt::OptTable::Info infoTable[] = { class COFFOptTable : public opt::PrecomputedOptTable { public: - COFFOptTable() : PrecomputedOptTable(infoTable, PrefixTable, true) {} + COFFOptTable() + : PrecomputedOptTable(OptionStrTable, OptionPrefixesTable, infoTable, + OptionPrefixesUnion, true) {} }; static COFFOptTable optTable; diff --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp index 9fdafed39b8b6..87e6f1f12364c 100644 --- a/llvm/lib/Option/OptTable.cpp +++ b/llvm/lib/Option/OptTable.cpp @@ -31,46 +31,55 @@ using namespace llvm; using namespace llvm::opt; -namespace llvm::opt { +namespace { +struct OptNameLess { + const char *StrTable; + ArrayRef PrefixesTable; + + explicit OptNameLess(const char *StrTable, ArrayRef PrefixesTable) + : StrTable(StrTable), PrefixesTable(PrefixesTable) {} + #ifndef NDEBUG -static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) { - if (&A == &B) - return false; - - if (int Cmp = StrCmpOptionName(A.getName(), B.getName())) - return Cmp < 0; - - // Note: we are converting ArrayRef to ArrayRef. - // In general, ArrayRef cannot be safely viewed as ArrayRef - // since sizeof(SubClass) may not be same as sizeof(Base). However in this - // case, sizeof(StringLiteral) is same as sizeof(StringRef), so this - // conversion is safe. - static_assert(sizeof(StringRef) == sizeof(StringLiteral)); - ArrayRef APrefixes(A.Prefixes.data(), A.Prefixes.size()); - ArrayRef BPrefixes(B.Prefixes.data(), B.Prefixes.size()); - - if (int Cmp = StrCmpOptionPrefixes(APrefixes, BPrefixes)) - return Cmp < 0; - - // Names are the same, check that classes are in order; exactly one - // should be joined, and it should succeed the other. - assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) && - "Unexpected classes for options with same name."); - return B.Kind == Option::JoinedClass; -} + inline bool operator()(const OptTable::Info &A, + const OptTable::Info &B) const { + if (&A == &B) + return false; + + if (int Cmp = StrCmpOptionName(A.getName(StrTable, PrefixesTable), + B.getName(StrTable, PrefixesTable))) + return Cmp < 0; + + SmallVector APrefixes, BPrefixes; + A.appendPrefixes(StrTable, PrefixesTable, APrefixes); + B.appendPrefixes(StrTable, PrefixesTable, BPrefixes); + + if (int Cmp = StrCmpOptionPrefixes(APrefixes, BPrefixes)) + return Cmp < 0; + + // Names are the same, check that classes are in order; exactly one + // should be joined, and it should succeed the other. + assert( + ((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) && + "Unexpected classes for options with same name."); + return B.Kind == Option::JoinedClass; + } #endif -// Support lower_bound between info and an option name. -static inline bool operator<(const OptTable::Info &I, StringRef Name) { - // Do not fallback to case sensitive comparison. - return StrCmpOptionName(I.getName(), Name, false) < 0; -} -} // namespace llvm::opt + // Support lower_bound between info and an option name. + inline bool operator()(const OptTable::Info &I, StringRef Name) const { + // Do not fallback to case sensitive comparison. + return StrCmpOptionName(I.getName(StrTable, PrefixesTable), Name, false) < + 0; + } +}; +} // namespace OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {} -OptTable::OptTable(ArrayRef OptionInfos, bool IgnoreCase) - : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase) { +OptTable::OptTable(const char *StrTable, ArrayRef PrefixesTable, + ArrayRef OptionInfos, bool IgnoreCase) + : StrTable(StrTable), PrefixesTable(PrefixesTable), + OptionInfos(OptionInfos), IgnoreCase(IgnoreCase) { // Explicitly zero initialize the error to work around a bug in array // value-initialization on MinGW with gcc 4.3.5. @@ -102,7 +111,7 @@ OptTable::OptTable(ArrayRef OptionInfos, bool IgnoreCase) // Check that options are in order. for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions(); i != e; ++i){ - if (!(getInfo(i) < getInfo(i + 1))) { + if (!(OptNameLess(StrTable, PrefixesTable)(getInfo(i), getInfo(i + 1)))) { getOption(i).dump(); getOption(i + 1).dump(); llvm_unreachable("Options are not in order!"); @@ -115,7 +124,7 @@ void OptTable::buildPrefixChars() { assert(PrefixChars.empty() && "rebuilding a non-empty prefix char"); // Build prefix chars. - for (const StringLiteral &Prefix : getPrefixesUnion()) { + for (StringRef Prefix : PrefixesUnion) { for (char C : Prefix) if (!is_contained(PrefixChars, C)) PrefixChars.push_back(C); @@ -132,7 +141,7 @@ const Option OptTable::getOption(OptSpecifier Opt) const { return Option(&getInfo(id), this); } -static bool isInput(const ArrayRef &Prefixes, StringRef Arg) { +static bool isInput(const ArrayRef &Prefixes, StringRef Arg) { if (Arg == "-") return true; for (const StringRef &Prefix : Prefixes) @@ -142,25 +151,32 @@ static bool isInput(const ArrayRef &Prefixes, StringRef Arg) { } /// \returns Matched size. 0 means no match. -static unsigned matchOption(const OptTable::Info *I, StringRef Str, +static unsigned matchOption(const char *StrTable, + ArrayRef PrefixesTable, + const OptTable::Info *I, StringRef Str, bool IgnoreCase) { - for (auto Prefix : I->Prefixes) { + StringRef Name = I->getName(StrTable, PrefixesTable); + for (unsigned PrefixOffset : I->getPrefixOffsets(PrefixesTable)) { + StringRef Prefix = &StrTable[PrefixOffset]; if (Str.starts_with(Prefix)) { StringRef Rest = Str.substr(Prefix.size()); - bool Matched = IgnoreCase ? Rest.starts_with_insensitive(I->getName()) - : Rest.starts_with(I->getName()); + bool Matched = IgnoreCase ? Rest.starts_with_insensitive(Name) + : Rest.starts_with(Name); if (Matched) - return Prefix.size() + StringRef(I->getName()).size(); + return Prefix.size() + Name.size(); } } return 0; } // Returns true if one of the Prefixes + In.Names matches Option -static bool optionMatches(const OptTable::Info &In, StringRef Option) { - for (auto Prefix : In.Prefixes) - if (Option.ends_with(In.getName())) - if (Option.slice(0, Option.size() - In.getName().size()) == Prefix) +static bool optionMatches(const char *StrTable, + ArrayRef PrefixesTable, + const OptTable::Info &In, StringRef Option) { + StringRef Name = In.getName(StrTable, PrefixesTable); + if (Option.consume_back(Name)) + for (unsigned PrefixOffset : In.getPrefixOffsets(PrefixesTable)) + if (Option == &StrTable[PrefixOffset]) return true; return false; } @@ -173,7 +189,7 @@ OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const { // Search all options and return possible values. for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) { const Info &In = OptionInfos[I]; - if (!In.Values || !optionMatches(In, Option)) + if (!In.Values || !optionMatches(StrTable, PrefixesTable, In, Option)) continue; SmallVector Candidates; @@ -194,15 +210,17 @@ OptTable::findByPrefix(StringRef Cur, Visibility VisibilityMask, std::vector Ret; for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) { const Info &In = OptionInfos[I]; - if (In.Prefixes.empty() || (!In.HelpText && !In.GroupID)) + if (In.hasNoPrefix() || (!In.HelpText && !In.GroupID)) continue; if (!(In.Visibility & VisibilityMask)) continue; if (In.Flags & DisableFlags) continue; - for (auto Prefix : In.Prefixes) { - std::string S = (Prefix + In.getName() + "\t").str(); + StringRef Name = In.getName(StrTable, PrefixesTable); + for (unsigned PrefixOffset : In.getPrefixOffsets(PrefixesTable)) { + StringRef Prefix = &StrTable[PrefixOffset]; + std::string S = (Twine(Prefix) + Name + "\t").str(); if (In.HelpText) S += In.HelpText; if (StringRef(S).starts_with(Cur) && S != std::string(Cur) + "\t") @@ -253,7 +271,7 @@ unsigned OptTable::internalFindNearest( for (const Info &CandidateInfo : ArrayRef(OptionInfos).drop_front(FirstSearchableIndex)) { - StringRef CandidateName = CandidateInfo.getName(); + StringRef CandidateName = CandidateInfo.getName(StrTable, PrefixesTable); // We can eliminate some option prefix/name pairs as candidates right away: // * Ignore option candidates with empty names, such as "--", or names @@ -267,7 +285,7 @@ unsigned OptTable::internalFindNearest( // * Ignore positional argument option candidates (which do not // have prefixes). - if (CandidateInfo.Prefixes.empty()) + if (CandidateInfo.hasNoPrefix()) continue; // Now check if the candidate ends with a character commonly used when @@ -286,7 +304,9 @@ unsigned OptTable::internalFindNearest( // Consider each possible prefix for each candidate to find the most // appropriate one. For example, if a user asks for "--helm", suggest // "--help" over "-help". - for (auto CandidatePrefix : CandidateInfo.Prefixes) { + for (unsigned CandidatePrefixOffset : + CandidateInfo.getPrefixOffsets(PrefixesTable)) { + StringRef CandidatePrefix = &StrTable[CandidatePrefixOffset]; // If Candidate and NormalizedName have more than 'BestDistance' // characters of difference, no need to compute the edit distance, it's // going to be greater than BestDistance. Don't bother computing Candidate @@ -332,19 +352,21 @@ std::unique_ptr OptTable::parseOneArgGrouped(InputArgList &Args, // itself. const char *CStr = Args.getArgString(Index); StringRef Str(CStr); - if (isInput(getPrefixesUnion(), Str)) + if (isInput(PrefixesUnion, Str)) return std::make_unique(getOption(InputOptionID), Str, Index++, CStr); const Info *End = OptionInfos.data() + OptionInfos.size(); StringRef Name = Str.ltrim(PrefixChars); const Info *Start = - std::lower_bound(OptionInfos.data() + FirstSearchableIndex, End, Name); + std::lower_bound(OptionInfos.data() + FirstSearchableIndex, End, Name, + OptNameLess(StrTable, PrefixesTable)); const Info *Fallback = nullptr; unsigned Prev = Index; // Search for the option which matches Str. for (; Start != End; ++Start) { - unsigned ArgSize = matchOption(Start, Str, IgnoreCase); + unsigned ArgSize = + matchOption(StrTable, PrefixesTable, Start, Str, IgnoreCase); if (!ArgSize) continue; @@ -417,7 +439,7 @@ std::unique_ptr OptTable::internalParseOneArg( // Anything that doesn't start with PrefixesUnion is an input, as is '-' // itself. - if (isInput(getPrefixesUnion(), Str)) + if (isInput(PrefixesUnion, Str)) return std::make_unique(getOption(InputOptionID), Str, Index++, Str.data()); @@ -426,7 +448,8 @@ std::unique_ptr OptTable::internalParseOneArg( StringRef Name = Str.ltrim(PrefixChars); // Search for the first next option which could be a prefix. - Start = std::lower_bound(Start, End, Name); + Start = + std::lower_bound(Start, End, Name, OptNameLess(StrTable, PrefixesTable)); // Options are stored in sorted order, with '\0' at the end of the // alphabet. Since the only options which can accept a string must @@ -440,7 +463,8 @@ std::unique_ptr OptTable::internalParseOneArg( unsigned ArgSize = 0; // Scan for first option which is a proper prefix. for (; Start != End; ++Start) - if ((ArgSize = matchOption(Start, Str, IgnoreCase))) + if ((ArgSize = + matchOption(StrTable, PrefixesTable, Start, Str, IgnoreCase))) break; if (Start == End) break; @@ -763,12 +787,15 @@ void OptTable::internalPrintHelp( OS.flush(); } -GenericOptTable::GenericOptTable(ArrayRef OptionInfos, bool IgnoreCase) - : OptTable(OptionInfos, IgnoreCase) { +GenericOptTable::GenericOptTable(const char *StrTable, + ArrayRef PrefixesTable, + ArrayRef OptionInfos, bool IgnoreCase) + : OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase) { - std::set TmpPrefixesUnion; + std::set TmpPrefixesUnion; for (auto const &Info : OptionInfos.drop_front(FirstSearchableIndex)) - TmpPrefixesUnion.insert(Info.Prefixes.begin(), Info.Prefixes.end()); - PrefixesUnionBuffer.append(TmpPrefixesUnion.begin(), TmpPrefixesUnion.end()); + for (unsigned PrefixOffset : Info.getPrefixOffsets(PrefixesTable)) + TmpPrefixesUnion.insert(StringRef(&StrTable[PrefixOffset])); + PrefixesUnion.append(TmpPrefixesUnion.begin(), TmpPrefixesUnion.end()); buildPrefixChars(); } diff --git a/llvm/lib/Option/Option.cpp b/llvm/lib/Option/Option.cpp index ecb3e84b1da8b..738f75bb41e68 100644 --- a/llvm/lib/Option/Option.cpp +++ b/llvm/lib/Option/Option.cpp @@ -57,10 +57,13 @@ void Option::print(raw_ostream &O, bool AddNewLine) const { #undef P } - if (!Info->Prefixes.empty()) { + if (!Info->hasNoPrefix()) { O << " Prefixes:["; - for (size_t I = 0, N = Info->Prefixes.size(); I != N; ++I) - O << '"' << Info->Prefixes[I] << (I == N - 1 ? "\"" : "\", "); + for (size_t I = 0, N = Info->getNumPrefixes(Owner->getPrefixesTable()); + I != N; ++I) + O << '"' + << Info->getPrefix(Owner->getStrTable(), Owner->getPrefixesTable(), I) + << (I == N - 1 ? "\"" : "\", "); O << ']'; } diff --git a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp index b3dcc0f986684..58ff720516f38 100644 --- a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp +++ b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp @@ -31,6 +31,10 @@ using namespace llvm::COFF; namespace { +#define OPTTABLE_STR_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_STR_TABLE_CODE + enum { OPT_INVALID = 0, #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__), @@ -38,12 +42,9 @@ enum { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -54,7 +55,9 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DllOptTable : public opt::GenericOptTable { public: - DllOptTable() : opt::GenericOptTable(InfoTable, false) {} + DllOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + 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 2e0841ba02b54..319aebffdbbba 100644 --- a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp +++ b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp @@ -37,6 +37,10 @@ using namespace llvm::object; namespace { +#define OPTTABLE_STR_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_STR_TABLE_CODE + enum { OPT_INVALID = 0, #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__), @@ -44,12 +48,9 @@ enum { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -60,7 +61,9 @@ static constexpr opt::OptTable::Info InfoTable[] = { class LibOptTable : public opt::GenericOptTable { public: - LibOptTable() : opt::GenericOptTable(InfoTable, true) {} + LibOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + true) {} }; } // namespace diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp index 594b52326871d..913077eb0b06d 100644 --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -64,12 +64,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -80,7 +81,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DsymutilOptTable : public opt::GenericOptTable { public: - DsymutilOptTable() : opt::GenericOptTable(InfoTable) {} + DsymutilOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // namespace diff --git a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp index d33459b194c9a..9e3800f5bfbbc 100644 --- a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp +++ b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp @@ -51,12 +51,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -67,7 +68,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class CGDataOptTable : public opt::GenericOptTable { public: - CGDataOptTable() : GenericOptTable(InfoTable) {} + CGDataOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp index 0c10769a9488e..8ef8d6e239cfe 100644 --- a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp +++ b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp @@ -42,12 +42,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -58,7 +59,9 @@ static constexpr opt::OptTable::Info InfoTable[] = { class CvtResOptTable : public opt::GenericOptTable { public: - CvtResOptTable() : opt::GenericOptTable(InfoTable, true) {} + CvtResOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + true) {} }; } diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp index 41b379e8fd396..1467093e78c0b 100644 --- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -31,12 +31,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -47,7 +48,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class CxxfiltOptTable : public opt::GenericOptTable { public: - CxxfiltOptTable() : opt::GenericOptTable(InfoTable) { + CxxfiltOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { 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 77862737bccd2..934833bf6fe42 100644 --- a/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp +++ b/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp @@ -37,12 +37,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -53,7 +54,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DebuginfodFindOptTable : public opt::GenericOptTable { public: - DebuginfodFindOptTable() : GenericOptTable(InfoTable) {} + DebuginfodFindOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp index 44d656148a4e2..2859a36c80b0b 100644 --- a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp +++ b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp @@ -36,12 +36,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -52,7 +53,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DebuginfodOptTable : public opt::GenericOptTable { public: - DebuginfodOptTable() : GenericOptTable(InfoTable) {} + DebuginfodOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp index 7b777b1845f8a..0180abb834f9d 100644 --- a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp +++ b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp @@ -38,12 +38,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Options.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Options.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -54,7 +55,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DwarfutilOptTable : public opt::GenericOptTable { public: - DwarfutilOptTable() : opt::GenericOptTable(InfoTable) {} + DwarfutilOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // namespace diff --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp index 60a89cb13c57a..e34fcadfde5fc 100644 --- a/llvm/tools/llvm-dwp/llvm-dwp.cpp +++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -47,12 +47,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -63,7 +64,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class DwpOptTable : public opt::GenericOptTable { public: - DwpOptTable() : GenericOptTable(InfoTable) {} + DwpOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp index 4d441465c47fb..42900159ce966 100644 --- a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp +++ b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp @@ -64,12 +64,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE const opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -79,7 +80,8 @@ const opt::OptTable::Info InfoTable[] = { class GSYMUtilOptTable : public llvm::opt::GenericOptTable { public: - GSYMUtilOptTable() : GenericOptTable(InfoTable) { + GSYMUtilOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-ifs/llvm-ifs.cpp b/llvm/tools/llvm-ifs/llvm-ifs.cpp index b76ea8dec0c98..e12016c51e906 100644 --- a/llvm/tools/llvm-ifs/llvm-ifs.cpp +++ b/llvm/tools/llvm-ifs/llvm-ifs.cpp @@ -59,12 +59,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -74,7 +75,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class IFSOptTable : public opt::GenericOptTable { public: - IFSOptTable() : opt::GenericOptTable(InfoTable) { + IFSOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp index 3d3f3f0af4b7a..94247118dc4eb 100644 --- a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp +++ b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp @@ -48,12 +48,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -63,7 +64,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class LibtoolDarwinOptTable : public opt::GenericOptTable { public: - LibtoolDarwinOptTable() : GenericOptTable(InfoTable) {} + LibtoolDarwinOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/llvm-lipo/llvm-lipo.cpp b/llvm/tools/llvm-lipo/llvm-lipo.cpp index 711a9185e155f..3c0197e8b7bac 100644 --- a/llvm/tools/llvm-lipo/llvm-lipo.cpp +++ b/llvm/tools/llvm-lipo/llvm-lipo.cpp @@ -72,12 +72,13 @@ enum LipoID { }; namespace lipo { -#define PREFIX(NAME, VALUE) \ - static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ - static constexpr llvm::ArrayRef NAME( \ - NAME##_init, std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "LipoOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "LipoOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info LipoInfoTable[] = { @@ -89,7 +90,9 @@ static constexpr opt::OptTable::Info LipoInfoTable[] = { class LipoOptTable : public opt::GenericOptTable { public: - LipoOptTable() : opt::GenericOptTable(lipo::LipoInfoTable) {} + LipoOptTable() + : opt::GenericOptTable(lipo::OptionStrTable, lipo::OptionPrefixesTable, + lipo::LipoInfoTable) {} }; enum class LipoAction { diff --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp index db69109e2d1fa..1aa41096002ee 100644 --- a/llvm/tools/llvm-ml/llvm-ml.cpp +++ b/llvm/tools/llvm-ml/llvm-ml.cpp @@ -58,12 +58,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -73,7 +74,9 @@ static constexpr opt::OptTable::Info InfoTable[] = { class MLOptTable : public opt::GenericOptTable { public: - MLOptTable() : opt::GenericOptTable(InfoTable, /*IgnoreCase=*/false) {} + MLOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + /*IgnoreCase=*/false) {} }; } // namespace diff --git a/llvm/tools/llvm-mt/llvm-mt.cpp b/llvm/tools/llvm-mt/llvm-mt.cpp index 8b793b877642c..3bd1bc786f86d 100644 --- a/llvm/tools/llvm-mt/llvm-mt.cpp +++ b/llvm/tools/llvm-mt/llvm-mt.cpp @@ -40,12 +40,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -56,7 +57,9 @@ static constexpr opt::OptTable::Info InfoTable[] = { class CvtResOptTable : public opt::GenericOptTable { public: - CvtResOptTable() : opt::GenericOptTable(InfoTable, true) {} + CvtResOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + true) {} }; } // namespace diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index d3e8d4c5ed987..e7c3e36dd38d2 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -65,12 +65,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -80,7 +81,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class NmOptTable : public opt::GenericOptTable { public: - NmOptTable() : opt::GenericOptTable(InfoTable) { + NmOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index 104d802b1e1ee..0925fc55317f7 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -39,12 +39,13 @@ enum ObjcopyID { }; namespace objcopy_opt { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "ObjcopyOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "ObjcopyOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info ObjcopyInfoTable[] = { #define OPTION(...) \ @@ -56,7 +57,10 @@ static constexpr opt::OptTable::Info ObjcopyInfoTable[] = { class ObjcopyOptTable : public opt::GenericOptTable { public: - ObjcopyOptTable() : opt::GenericOptTable(objcopy_opt::ObjcopyInfoTable) { + ObjcopyOptTable() + : opt::GenericOptTable(objcopy_opt::OptionStrTable, + objcopy_opt::OptionPrefixesTable, + objcopy_opt::ObjcopyInfoTable) { setGroupedShortOptions(true); setDashDashParsing(true); } @@ -71,13 +75,13 @@ enum InstallNameToolID { }; namespace install_name_tool { +#define OPTTABLE_STR_TABLE_CODE +#include "InstallNameToolOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "InstallNameToolOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = { #define OPTION(...) \ @@ -90,7 +94,9 @@ static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = { class InstallNameToolOptTable : public opt::GenericOptTable { public: InstallNameToolOptTable() - : GenericOptTable(install_name_tool::InstallNameToolInfoTable) {} + : GenericOptTable(install_name_tool::OptionStrTable, + install_name_tool::OptionPrefixesTable, + install_name_tool::InstallNameToolInfoTable) {} }; enum BitcodeStripID { @@ -102,13 +108,13 @@ enum BitcodeStripID { }; namespace bitcode_strip { +#define OPTTABLE_STR_TABLE_CODE +#include "BitcodeStripOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "BitcodeStripOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = { #define OPTION(...) \ @@ -121,7 +127,9 @@ static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = { class BitcodeStripOptTable : public opt::GenericOptTable { public: BitcodeStripOptTable() - : opt::GenericOptTable(bitcode_strip::BitcodeStripInfoTable) {} + : opt::GenericOptTable(bitcode_strip::OptionStrTable, + bitcode_strip::OptionPrefixesTable, + bitcode_strip::BitcodeStripInfoTable) {} }; enum StripID { @@ -132,12 +140,13 @@ enum StripID { }; namespace strip { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE +#include "StripOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE #include "StripOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info StripInfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__), @@ -148,7 +157,9 @@ static constexpr opt::OptTable::Info StripInfoTable[] = { class StripOptTable : public opt::GenericOptTable { public: - StripOptTable() : GenericOptTable(strip::StripInfoTable) { + StripOptTable() + : GenericOptTable(strip::OptionStrTable, strip::OptionPrefixesTable, + strip::StripInfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 246d5cfa05818..1e74cb80b2118 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -99,10 +99,11 @@ namespace { class CommonOptTable : public opt::GenericOptTable { public: - CommonOptTable(ArrayRef OptionInfos, const char *Usage, + CommonOptTable(const char *StrTable, ArrayRef PrefixesTable, + ArrayRef OptionInfos, const char *Usage, const char *Description) - : opt::GenericOptTable(OptionInfos), Usage(Usage), - Description(Description) { + : opt::GenericOptTable(StrTable, PrefixesTable, OptionInfos), + Usage(Usage), Description(Description) { setGroupedShortOptions(true); } @@ -121,12 +122,13 @@ class CommonOptTable : public opt::GenericOptTable { // ObjdumpOptID is in ObjdumpOptID.h namespace objdump_opt { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "ObjdumpOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "ObjdumpOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info ObjdumpInfoTable[] = { #define OPTION(...) \ @@ -139,9 +141,10 @@ static constexpr opt::OptTable::Info ObjdumpInfoTable[] = { class ObjdumpOptTable : public CommonOptTable { public: ObjdumpOptTable() - : CommonOptTable(objdump_opt::ObjdumpInfoTable, - " [options] ", - "llvm object file dumper") {} + : CommonOptTable( + objdump_opt::OptionStrTable, objdump_opt::OptionPrefixesTable, + objdump_opt::ObjdumpInfoTable, " [options] ", + "llvm object file dumper") {} }; enum OtoolOptID { @@ -152,12 +155,13 @@ enum OtoolOptID { }; namespace otool { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE +#include "OtoolOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE #include "OtoolOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info OtoolInfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__), @@ -169,7 +173,8 @@ static constexpr opt::OptTable::Info OtoolInfoTable[] = { class OtoolOptTable : public CommonOptTable { public: OtoolOptTable() - : CommonOptTable(otool::OtoolInfoTable, " [option...] [file...]", + : CommonOptTable(otool::OptionStrTable, otool::OptionPrefixesTable, + otool::OtoolInfoTable, " [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 4bc9d90095575..a77188c462afe 100644 --- a/llvm/tools/llvm-rc/llvm-rc.cpp +++ b/llvm/tools/llvm-rc/llvm-rc.cpp @@ -57,12 +57,13 @@ enum ID { }; namespace rc_opt { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -73,7 +74,10 @@ static constexpr opt::OptTable::Info InfoTable[] = { class RcOptTable : public opt::GenericOptTable { public: - RcOptTable() : GenericOptTable(rc_opt::InfoTable, /* IgnoreCase = */ true) {} + RcOptTable() + : GenericOptTable(rc_opt::OptionStrTable, rc_opt::OptionPrefixesTable, + rc_opt::InfoTable, + /* IgnoreCase = */ true) {} }; enum Windres_ID { @@ -84,12 +88,13 @@ enum Windres_ID { }; namespace windres_opt { -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE +#include "WindresOpts.inc" +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE #include "WindresOpts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) \ @@ -102,7 +107,10 @@ static constexpr opt::OptTable::Info InfoTable[] = { class WindresOptTable : public opt::GenericOptTable { public: WindresOptTable() - : GenericOptTable(windres_opt::InfoTable, /* IgnoreCase = */ false) {} + : GenericOptTable(windres_opt::OptionStrTable, + windres_opt::OptionPrefixesTable, + windres_opt::InfoTable, + /* IgnoreCase = */ false) {} }; static ExitOnError ExitOnErr; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index 3e76cda2dd433..2f77e5d350553 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -59,12 +59,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -74,7 +75,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class ReadobjOptTable : public opt::GenericOptTable { public: - ReadobjOptTable() : opt::GenericOptTable(InfoTable) { + ReadobjOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-readtapi/llvm-readtapi.cpp b/llvm/tools/llvm-readtapi/llvm-readtapi.cpp index 04282d3e4877c..b5574ea41e332 100644 --- a/llvm/tools/llvm-readtapi/llvm-readtapi.cpp +++ b/llvm/tools/llvm-readtapi/llvm-readtapi.cpp @@ -45,12 +45,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "TapiOpts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "TapiOpts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -60,7 +61,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class TAPIOptTable : public opt::GenericOptTable { public: - TAPIOptTable() : opt::GenericOptTable(InfoTable) { + TAPIOptTable() + : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); } }; diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp index 4a1b0e879036c..0d7bf24832670 100644 --- a/llvm/tools/llvm-size/llvm-size.cpp +++ b/llvm/tools/llvm-size/llvm-size.cpp @@ -45,12 +45,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -60,7 +61,10 @@ static constexpr opt::OptTable::Info InfoTable[] = { class SizeOptTable : public opt::GenericOptTable { public: - SizeOptTable() : GenericOptTable(InfoTable) { setGroupedShortOptions(true); } + SizeOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { + 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 d4305096b60a0..9979b93de8427 100644 --- a/llvm/tools/llvm-strings/llvm-strings.cpp +++ b/llvm/tools/llvm-strings/llvm-strings.cpp @@ -38,12 +38,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -54,7 +55,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class StringsOptTable : public opt::GenericOptTable { public: - StringsOptTable() : GenericOptTable(InfoTable) { + StringsOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { setGroupedShortOptions(true); setDashDashParsing(true); } diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp index 3e41a85d64695..3ba7f59d5b847 100644 --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -56,12 +56,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -72,7 +73,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class SymbolizerOptTable : public opt::GenericOptTable { public: - SymbolizerOptTable() : GenericOptTable(InfoTable) { + SymbolizerOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) { 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 a091e37ff4026..ca0b424722196 100644 --- a/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp +++ b/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp @@ -33,12 +33,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE using namespace llvm::opt; static constexpr opt::OptTable::Info InfoTable[] = { @@ -49,7 +50,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class TLICheckerOptTable : public opt::GenericOptTable { public: - TLICheckerOptTable() : GenericOptTable(InfoTable) {} + TLICheckerOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // end anonymous namespace diff --git a/llvm/tools/sancov/sancov.cpp b/llvm/tools/sancov/sancov.cpp index 39feff62391fe..727b94b8477cc 100644 --- a/llvm/tools/sancov/sancov.cpp +++ b/llvm/tools/sancov/sancov.cpp @@ -67,12 +67,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_STR_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_STR_TABLE_CODE + +#define OPTTABLE_PREFIXES_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_PREFIXES_TABLE_CODE static constexpr opt::OptTable::Info InfoTable[] = { #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), @@ -82,7 +83,8 @@ static constexpr opt::OptTable::Info InfoTable[] = { class SancovOptTable : public opt::GenericOptTable { public: - SancovOptTable() : GenericOptTable(InfoTable) {} + SancovOptTable() + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {} }; } // namespace diff --git a/llvm/unittests/Option/OptionMarshallingTest.cpp b/llvm/unittests/Option/OptionMarshallingTest.cpp index 2ec422f1a0984..08c3b019689f8 100644 --- a/llvm/unittests/Option/OptionMarshallingTest.cpp +++ b/llvm/unittests/Option/OptionMarshallingTest.cpp @@ -9,29 +9,37 @@ #include "llvm/ADT/StringRef.h" #include "gtest/gtest.h" +#define OPTTABLE_STR_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_STR_TABLE_CODE + struct OptionWithMarshallingInfo { - llvm::StringLiteral PrefixedName; + int PrefixedNameOffset; const char *KeyPath; const char *ImpliedCheck; const char *ImpliedValue; + + llvm::StringRef getPrefixedName() const { + return &OptionStrTable[PrefixedNameOffset]; + } }; static const OptionWithMarshallingInfo MarshallingTable[] = { #define OPTION_WITH_MARSHALLING( \ - PREFIX_TYPE, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ - VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \ + PREFIX_TYPE, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \ + FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \ SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \ IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ - {PREFIXED_NAME, #KEYPATH, #IMPLIED_CHECK, #IMPLIED_VALUE}, + {PREFIXED_NAME_OFFSET, #KEYPATH, #IMPLIED_CHECK, #IMPLIED_VALUE}, #include "Opts.inc" #undef OPTION_WITH_MARSHALLING }; TEST(OptionMarshalling, EmittedOrderSameAsDefinitionOrder) { - ASSERT_EQ(MarshallingTable[0].PrefixedName, "-marshalled-flag-d"); - ASSERT_EQ(MarshallingTable[1].PrefixedName, "-marshalled-flag-c"); - ASSERT_EQ(MarshallingTable[2].PrefixedName, "-marshalled-flag-b"); - ASSERT_EQ(MarshallingTable[3].PrefixedName, "-marshalled-flag-a"); + ASSERT_EQ(MarshallingTable[0].getPrefixedName(), "-marshalled-flag-d"); + ASSERT_EQ(MarshallingTable[1].getPrefixedName(), "-marshalled-flag-c"); + ASSERT_EQ(MarshallingTable[2].getPrefixedName(), "-marshalled-flag-b"); + ASSERT_EQ(MarshallingTable[3].getPrefixedName(), "-marshalled-flag-a"); } TEST(OptionMarshalling, EmittedSpecifiedKeyPath) { diff --git a/llvm/unittests/Option/OptionParsingTest.cpp b/llvm/unittests/Option/OptionParsingTest.cpp index cd8743e49d4fd..3da015e343eb9 100644 --- a/llvm/unittests/Option/OptionParsingTest.cpp +++ b/llvm/unittests/Option/OptionParsingTest.cpp @@ -20,6 +20,10 @@ using namespace llvm::opt; #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif +#define OPTTABLE_STR_TABLE_CODE +#include "Opts.inc" +#undef OPTTABLE_STR_TABLE_CODE + enum ID { OPT_INVALID = 0, // This is not an option ID. #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__), @@ -28,20 +32,13 @@ enum ID { #undef OPTION }; -#define PREFIX(NAME, VALUE) \ - static constexpr StringLiteral NAME##_init[] = VALUE; \ - static constexpr ArrayRef NAME(NAME##_init, \ - std::size(NAME##_init) - 1); +#define OPTTABLE_PREFIXES_TABLE_CODE #include "Opts.inc" -#undef PREFIX +#undef OPTTABLE_PREFIXES_TABLE_CODE -static constexpr const StringLiteral PrefixTable_init[] = -#define PREFIX_UNION(VALUES) VALUES +#define OPTTABLE_PREFIXES_UNION_CODE #include "Opts.inc" -#undef PREFIX_UNION - ; -static constexpr const ArrayRef - PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1); +#undef OPTTABLE_PREFIXES_UNION_CODE enum OptionFlags { OptFlag1 = (1 << 4), @@ -64,13 +61,15 @@ namespace { class TestOptTable : public GenericOptTable { public: TestOptTable(bool IgnoreCase = false) - : GenericOptTable(InfoTable, IgnoreCase) {} + : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + IgnoreCase) {} }; class TestPrecomputedOptTable : public PrecomputedOptTable { public: TestPrecomputedOptTable(bool IgnoreCase = false) - : PrecomputedOptTable(InfoTable, PrefixTable, IgnoreCase) {} + : PrecomputedOptTable(OptionStrTable, OptionPrefixesTable, InfoTable, + OptionPrefixesUnion, IgnoreCase) {} }; } diff --git a/llvm/utils/TableGen/OptionParserEmitter.cpp b/llvm/utils/TableGen/OptionParserEmitter.cpp index 48f5818938ae8..eca828cad5f4d 100644 --- a/llvm/utils/TableGen/OptionParserEmitter.cpp +++ b/llvm/utils/TableGen/OptionParserEmitter.cpp @@ -9,9 +9,11 @@ #include "Common/OptEmitter.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/StringToOffsetTable.h" #include "llvm/TableGen/TableGenBackend.h" #include #include @@ -26,6 +28,15 @@ static std::string getOptionName(const Record &R) { return std::string(R.getValueAsString("EnumName")); } +static raw_ostream &writeStrTableOffset(raw_ostream &OS, + const StringToOffsetTable &Table, + llvm::StringRef Str) { + OS << Table.GetStringOffset(Str) << " /* "; + OS.write_escaped(Str); + OS << " */"; + return OS; +} + static raw_ostream &writeCstring(raw_ostream &OS, llvm::StringRef Str) { OS << '"'; OS.write_escaped(Str); @@ -260,59 +271,84 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { // Generate prefix groups. typedef SmallVector, 2> PrefixKeyT; - typedef std::map PrefixesT; + typedef std::map PrefixesT; PrefixesT Prefixes; - Prefixes.insert(std::pair(PrefixKeyT(), "prefix_0")); - unsigned CurPrefix = 0; + Prefixes.insert({PrefixKeyT(), 0}); for (const Record &R : llvm::make_pointee_range(Opts)) { std::vector RPrefixes = R.getValueAsListOfStrings("Prefixes"); PrefixKeyT PrefixKey(RPrefixes.begin(), RPrefixes.end()); - unsigned NewPrefix = CurPrefix + 1; - std::string Prefix = (Twine("prefix_") + Twine(NewPrefix)).str(); - if (Prefixes.insert(std::pair(PrefixKey, Prefix)).second) - CurPrefix = NewPrefix; + Prefixes.insert({PrefixKey, 0}); } DenseSet PrefixesUnionSet; - for (const auto &Prefix : Prefixes) - PrefixesUnionSet.insert(Prefix.first.begin(), Prefix.first.end()); + for (const auto &[Prefix, _] : Prefixes) + PrefixesUnionSet.insert(Prefix.begin(), Prefix.end()); SmallVector PrefixesUnion(PrefixesUnionSet.begin(), PrefixesUnionSet.end()); array_pod_sort(PrefixesUnion.begin(), PrefixesUnion.end()); + llvm::StringToOffsetTable Table; + // Make sure the empty string is the zero-th one in the table. This both makes + // it easy to check for empty strings (zero offset == empty) and makes + // initialization cheaper for empty strings. + Table.GetOrAddStringOffset(""); + // We can add all the prefixes via the union. + for (const auto &Prefix : PrefixesUnion) + Table.GetOrAddStringOffset(Prefix); + for (const Record &R : llvm::make_pointee_range(Groups)) + Table.GetOrAddStringOffset(R.getValueAsString("Name")); + for (const Record &R : llvm::make_pointee_range(Opts)) + Table.GetOrAddStringOffset(getOptionPrefixedName(R)); + + // Dump string table. + OS << "/////////\n"; + OS << "// String table\n\n"; + OS << "#ifdef OPTTABLE_STR_TABLE_CODE\n"; + Table.EmitStringLiteralDef(OS, "static constexpr char OptionStrTable[]", + /*Indent=*/""); + OS << "#endif // OPTTABLE_STR_TABLE_CODE\n\n"; + // Dump prefixes. OS << "/////////\n"; OS << "// Prefixes\n\n"; - OS << "#ifdef PREFIX\n"; - OS << "#define COMMA ,\n"; - for (const auto &Prefix : Prefixes) { - OS << "PREFIX("; - - // Prefix name. - OS << Prefix.second; - - // Prefix values. - OS << ", {"; - for (const auto &PrefixKey : Prefix.first) - OS << "llvm::StringLiteral(\"" << PrefixKey << "\") COMMA "; - // Append an empty element to avoid ending up with an empty array. - OS << "llvm::StringLiteral(\"\")})\n"; + OS << "#ifdef OPTTABLE_PREFIXES_TABLE_CODE\n"; + OS << "static constexpr unsigned OptionPrefixesTable[] = {\n"; + { + // Ensure the first prefix set is always empty. + assert(!Prefixes.empty() && + "We should always emit an empty set of prefixes"); + assert(Prefixes.begin()->first.empty() && + "First prefix set should always be empty"); + llvm::ListSeparator Sep(",\n"); + unsigned CurIndex = 0; + for (auto &[Prefix, PrefixIndex] : Prefixes) { + // First emit the number of prefix strings in this list of prefixes. + OS << Sep << " " << Prefix.size() << " /* prefixes */"; + PrefixIndex = CurIndex; + assert((CurIndex == 0 || !Prefix.empty()) && + "Only first prefix set should be empty!"); + for (const auto &PrefixKey : Prefix) + OS << ", " << *Table.GetStringOffset(PrefixKey) << " /* '" << PrefixKey + << "' */"; + CurIndex += Prefix.size() + 1; + } } - OS << "#undef COMMA\n"; - OS << "#endif // PREFIX\n\n"; + OS << "\n};\n"; + OS << "#endif // OPTTABLE_PREFIXES_TABLE_CODE\n\n"; - // Dump prefix unions. + // Dump prefixes union. OS << "/////////\n"; OS << "// Prefix Union\n\n"; - OS << "#ifdef PREFIX_UNION\n"; - OS << "#define COMMA ,\n"; - OS << "PREFIX_UNION({\n"; - for (const auto &Prefix : PrefixesUnion) { - OS << "llvm::StringLiteral(\"" << Prefix << "\") COMMA "; + OS << "#ifdef OPTTABLE_PREFIXES_UNION_CODE\n"; + OS << "static constexpr unsigned OptionPrefixesUnion[] = {\n"; + { + llvm::ListSeparator Sep(", "); + for (auto Prefix : PrefixesUnion) + OS << Sep << " " << *Table.GetStringOffset(Prefix) << " /* '" << Prefix + << "' */"; } - OS << "llvm::StringLiteral(\"\")})\n"; - OS << "#undef COMMA\n"; - OS << "#endif // PREFIX_UNION\n\n"; + OS << "\n};\n"; + OS << "#endif // OPTTABLE_PREFIXES_UNION_CODE\n\n"; // Dump groups. OS << "/////////\n"; @@ -337,11 +373,12 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { // Start a single option entry. OS << "OPTION("; - // The option prefix; - OS << "llvm::ArrayRef()"; + // A zero prefix offset corresponds to an empty set of prefixes. + OS << "0 /* no prefixes */"; - // The option string. - OS << ", \"" << R.getValueAsString("Name") << '"'; + // The option string offset. + OS << ", "; + writeStrTableOffset(OS, Table, R.getValueAsString("Name")); // The option identifier name. OS << ", " << getOptionName(R); @@ -387,7 +424,7 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) { OS << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())] << ", "; // The option prefixed name. - writeCstring(OS, getOptionPrefixedName(R)); + writeStrTableOffset(OS, Table, getOptionPrefixedName(R)); // The option identifier name. OS << ", " << getOptionName(R);