[PATCH] D79796: Sketch support for generating CC1 command line from CompilerInvocation
Daniel Grumberg via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 15 10:58:49 PDT 2020
dang marked 2 inline comments as done.
dang added inline comments.
================
Comment at: clang/lib/Frontend/CompilerInvocation.cpp:3845
+ IS_POSITIVE != DEFAULT_VALUE && this->KEYPATH != DEFAULT_VALUE) \
+ Args.push_back(StringAllocator(Twine(PREFIX_TYPE[0]) + NAME));
+#include "clang/Driver/Options.inc"
----------------
dexonsmith wrote:
> Bigcheese wrote:
> > It's a little sad that we need to allocation every string just because of the `-`. We definitely need to be able to allocate strings for options with data, but it would be good if we could just have the strings with `-` prefixed in the option table if that's reasonable to do.
> I want to highlight @Bigcheese's comment again so it doesn't get lost. I think a reasonable name would be `SPELLING`.
Yes I haven't forgotten just have not gotten around to it yet. I just want to do some form of suffix merging with the string the the OptTable receives
================
Comment at: llvm/utils/TableGen/OptParserEmitter.cpp:351-354
+ OS << "#define " << MacroName << "(V, D) .Case(V, D)\n";
+ emitValueTable(OS, OptionName, R.getValueAsString("Values"),
+ NormalizedValuesScope, NormalizedValues);
+ OS << "#undef " << MacroName << "\n";
----------------
dexonsmith wrote:
> It seems unnecessary to generate macros here; you can just generate the code directly...
>
> But looking more closely, I wonder if we really need this generated code at all.
>
> Instead, can we create a table like this in Options.inc?
> ```
> struct EnumValue {
> const char *Name;
> unsigned Value;
> };
>
> struct EnumValueTable {
> const EnumValue *Table;
> unsigned Size;
> };
>
> static const EnumValue RelocationModelTable[] = {
> {"static", static_cast<unsigned>(llvm::Reloc::Static)},
> {"pic", static_cast<unsigned>(llvm::Reloc::_PIC)},
> // ...
> };
>
> static const EnumValue SomeOtherTable[] = {
> {"name", static_cast<unsigned>(clang::SomeOtherEnumValue)},
> // ...
> };
>
> static const EnumValueTable *EnumValueTables[] = {
> {&RelocationModelTable, sizeof(RelocationModelTable) / sizeof(EnumValue)},
> {&SomeOtherTable, sizeof(SomeOtherTable) / sizeof(EnumValue)},
> };
> static const unsigned EnumValueTablesSize =
> sizeof(EnumValueTables) / sizeof(EnumValueTable);
> ```
>
> We can then have this code directly in Options.cpp:
> ```
> static llvm::Optional<unsigned> extractSimpleEnum(
> llvm::opt::OptSpecifier Opt, int TableIndex,
> const ArgList &ArgList, DiagnosticsEngine &Diags) {
> assert(TableIndex >= 0);
> assert(TableIndex < EnumValueTablesSize);
> const EnumValueTable &Table = *EnumValueTables[TableIndex];
>
> auto Arg = Args.getLastArg(Opt);
> if (!Arg)
> return None;
>
> StringRef ArgValue = Arg->getValue();
> for (int I = 0, E = Table.Size; I != E; ++I)
> if (ArgValue == Table.Table[I].Name)
> return Table.Table[I].Value;
>
> Diags.Report(diag::err_drv_invalid_value)
> << Arg->getAsString(ArgList) << ArgValue;
> return None;
> }
> ```
> and change the normalizer contract to:
> - return an `Optional`,
> - take an `llvm::opt::OptSpecifier`,
> - take an index into a table (set to `-1` if there's no relevant table), and
> - be responsible for the boilerplate call to `getLastArg`.
> Simple enums would have `NORMALIZER` hardcoded to `extractSimpleEnum`. The handler code that calls it needs new arguments `TABLE_INDEX` and `TYPE` but also looks simpler this way:
> ```
> if (auto MaybeValue = NORMALIZER(Opt##ID, TABLE_INDEX, Args, Diags)) \
> this->KEYPATH = static_cast<TYPE>(*MaybeValue); \
> else \
> this->KEYPATH = DEFAULT_VALUE;
> ```
>
> We could similarly have a single `serializeSimpleEnum` function in Options.cpp for a hardcoded `DENORMALIZER` for simple enums:
> ```
> static const char *serializeSimpleEnum(int TableIndex, unsigned Value) {
> assert(TableIndex >= 0);
> assert(TableIndex < EnumValueTablesSize);
> const EnumValueTable &Table = *EnumValueTables[TableIndex];
> for (int I = 0, E = Table.Size; I != E; ++I)
> if (Value == Table.Table[I].Value)
> return Table.Table[I].Name;
>
> llvm::report_fatal_error("good error message");
> }
> ```
I originally wanted to generate the normalizers without the table to allow and arbitrary code fragment to be used as the normalized value (one that is potentially not a constant evaluated expression) and just regenerating the macros was the path of least resistance at the time. Having had a closer look at the existing cases of enum based options there doesn't seem to be a need for this functionality so I went ahead and did this. Although I haven't split the backends yet.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D79796/new/
https://reviews.llvm.org/D79796
More information about the cfe-commits
mailing list