Skip to content

Rework the Option library to reduce dynamic relocations #119198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 4 additions & 16 deletions clang-tools-extra/clangd/CompileCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,20 +458,6 @@ llvm::ArrayRef<ArgStripper::Rule> ArgStripper::rulesFor(llvm::StringRef Arg) {
PrevAlias[Self] = T;
NextAlias[T] = Self;
};
// Also grab prefixes for each option, these are not fully exposed.
llvm::ArrayRef<llvm::StringLiteral> Prefixes[DriverID::LastOption];

#define PREFIX(NAME, VALUE) \
static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \
static constexpr llvm::ArrayRef<llvm::StringLiteral> 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;
Expand All @@ -498,7 +484,9 @@ llvm::ArrayRef<ArgStripper::Rule> ArgStripper::rulesFor(llvm::StringRef Arg) {
llvm::SmallVector<Rule> 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<llvm::StringRef, 4> Prefixes;
DriverTable.appendOptionPrefixes(A, Prefixes);
if (Prefixes.empty()) // option groups.
continue;
auto Opt = DriverTable.getOption(A);
// Exclude - and -foo pseudo-options.
Expand All @@ -507,7 +495,7 @@ llvm::ArrayRef<ArgStripper::Rule> ArgStripper::rulesFor(llvm::StringRef Arg) {
auto Modes = getModes(Opt);
std::pair<unsigned, unsigned> 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();
Expand Down
23 changes: 11 additions & 12 deletions clang/lib/Driver/DriverOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<llvm::StringLiteral> 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<llvm::StringLiteral>
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__),
Expand All @@ -43,7 +40,9 @@ namespace {

class DriverOptTable : public PrecomputedOptTable {
public:
DriverOptTable() : PrecomputedOptTable(InfoTable, PrefixTable) {}
DriverOptTable()
: PrecomputedOptTable(OptionStrTable, OptionPrefixesTable, InfoTable,
OptionPrefixesUnion) {}
};
}

Expand Down
63 changes: 43 additions & 20 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -303,6 +311,11 @@ static std::optional<bool> 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*/...) {
Expand Down Expand Up @@ -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));
};
}

Expand All @@ -371,6 +384,14 @@ static void denormalizeStringImpl(ArgumentConsumer Consumer,
}
}

template <typename T>
static void
denormalizeString(ArgumentConsumer Consumer, unsigned SpellingOffset,
Option::OptionClass OptClass, unsigned TableIndex, T Value) {
denormalizeStringImpl(Consumer, lookupStrInTable(SpellingOffset), OptClass,
TableIndex, Twine(Value));
}

template <typename T>
static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling,
Option::OptionClass OptClass, unsigned TableIndex,
Expand Down Expand Up @@ -417,14 +438,14 @@ static std::optional<unsigned> 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");
Expand All @@ -433,11 +454,11 @@ static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer,

template <typename T>
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<unsigned>(Value));
return denormalizeSimpleEnumImpl(Consumer, SpellingOffset, OptClass,
TableIndex, static_cast<unsigned>(Value));
}

static std::optional<std::string> normalizeString(OptSpecifier Opt,
Expand Down Expand Up @@ -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<std::string> &Values) {
Expand All @@ -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 "
Expand Down Expand Up @@ -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) \
Expand All @@ -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) { \
Expand All @@ -559,8 +582,8 @@ static T extractMaskValue(T KeyPath) {
(Extracted != \
static_cast<decltype(KEYPATH)>((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)); \
}

Expand Down
42 changes: 12 additions & 30 deletions clang/tools/clang-installapi/Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<llvm::StringLiteral> 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<StringLiteral>
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
};
Expand All @@ -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.
Expand Down
14 changes: 8 additions & 6 deletions clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,13 @@ enum ID {
#undef OPTION
};

#define PREFIX(NAME, VALUE) \
static constexpr StringLiteral NAME##_init[] = VALUE; \
static constexpr ArrayRef<StringLiteral> 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__),
Expand All @@ -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() {
Expand Down
14 changes: 8 additions & 6 deletions clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,13 @@ enum ID {
#undef OPTION
};

#define PREFIX(NAME, VALUE) \
static constexpr StringLiteral NAME##_init[] = VALUE; \
static constexpr ArrayRef<StringLiteral> 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__),
Expand All @@ -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() {
Expand Down
14 changes: 8 additions & 6 deletions clang/tools/clang-scan-deps/ClangScanDeps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ enum ID {
#undef OPTION
};

#define PREFIX(NAME, VALUE) \
constexpr llvm::StringLiteral NAME##_init[] = VALUE; \
constexpr llvm::ArrayRef<llvm::StringLiteral> 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__),
Expand All @@ -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);
}
};
Expand Down
Loading
Loading