1 //===- OptionParserEmitter.cpp - Table Driven Command Option Line Parsing -===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "Common/OptEmitter.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/TableGen/Record.h"
16 #include "llvm/TableGen/StringToOffsetTable.h"
17 #include "llvm/TableGen/TableGenBackend.h"
23 static std::string
getOptionName(const Record
&R
) {
24 // Use the record name unless EnumName is defined.
25 if (isa
<UnsetInit
>(R
.getValueInit("EnumName")))
26 return std::string(R
.getName());
28 return std::string(R
.getValueAsString("EnumName"));
31 static raw_ostream
&writeStrTableOffset(raw_ostream
&OS
,
32 const StringToOffsetTable
&Table
,
33 llvm::StringRef Str
) {
34 OS
<< Table
.GetStringOffset(Str
) << " /* ";
35 OS
.write_escaped(Str
);
40 static raw_ostream
&writeCstring(raw_ostream
&OS
, llvm::StringRef Str
) {
42 OS
.write_escaped(Str
);
47 static std::string
getOptionPrefixedName(const Record
&R
) {
48 std::vector
<StringRef
> Prefixes
= R
.getValueAsListOfStrings("Prefixes");
49 StringRef Name
= R
.getValueAsString("Name");
54 return (Prefixes
[0] + Twine(Name
)).str();
57 class MarshallingInfo
{
59 static constexpr const char *MacroName
= "OPTION_WITH_MARSHALLING";
61 bool ShouldAlwaysEmit
= false;
62 StringRef MacroPrefix
;
64 StringRef DefaultValue
;
65 StringRef NormalizedValuesScope
;
66 StringRef ImpliedCheck
;
67 StringRef ImpliedValue
;
68 StringRef ShouldParse
;
70 StringRef Denormalizer
;
71 StringRef ValueMerger
;
72 StringRef ValueExtractor
;
74 std::vector
<StringRef
> Values
;
75 std::vector
<StringRef
> NormalizedValues
;
76 std::string ValueTableName
;
78 static size_t NextTableIndex
;
80 static constexpr const char *ValueTablePreamble
= R
"(
81 struct SimpleEnumValue {
86 struct SimpleEnumValueTable {
87 const SimpleEnumValue *Table;
92 static constexpr const char *ValueTablesDecl
=
93 "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
95 MarshallingInfo(const Record
&R
) : R(R
) {}
97 std::string
getMacroName() const {
98 return (MacroPrefix
+ MarshallingInfo::MacroName
).str();
101 void emit(raw_ostream
&OS
) const {
104 OS
<< ShouldAlwaysEmit
;
108 emitScopedNormalizedValue(OS
, DefaultValue
);
112 emitScopedNormalizedValue(OS
, ImpliedValue
);
120 OS
<< ValueExtractor
;
125 std::optional
<StringRef
> emitValueTable(raw_ostream
&OS
) const {
126 if (TableIndex
== -1)
128 OS
<< "static const SimpleEnumValue " << ValueTableName
<< "[] = {\n";
129 for (unsigned I
= 0, E
= Values
.size(); I
!= E
; ++I
) {
131 writeCstring(OS
, Values
[I
]);
133 OS
<< "static_cast<unsigned>(";
134 emitScopedNormalizedValue(OS
, NormalizedValues
[I
]);
138 return StringRef(ValueTableName
);
142 void emitScopedNormalizedValue(raw_ostream
&OS
,
143 StringRef NormalizedValue
) const {
144 if (!NormalizedValuesScope
.empty())
145 OS
<< NormalizedValuesScope
<< "::";
146 OS
<< NormalizedValue
;
150 size_t MarshallingInfo::NextTableIndex
= 0;
152 static MarshallingInfo
createMarshallingInfo(const Record
&R
) {
153 assert(!isa
<UnsetInit
>(R
.getValueInit("KeyPath")) &&
154 !isa
<UnsetInit
>(R
.getValueInit("DefaultValue")) &&
155 !isa
<UnsetInit
>(R
.getValueInit("ValueMerger")) &&
156 "MarshallingInfo must have a provide a keypath, default value and a "
159 MarshallingInfo
Ret(R
);
161 Ret
.ShouldAlwaysEmit
= R
.getValueAsBit("ShouldAlwaysEmit");
162 Ret
.MacroPrefix
= R
.getValueAsString("MacroPrefix");
163 Ret
.KeyPath
= R
.getValueAsString("KeyPath");
164 Ret
.DefaultValue
= R
.getValueAsString("DefaultValue");
165 Ret
.NormalizedValuesScope
= R
.getValueAsString("NormalizedValuesScope");
166 Ret
.ImpliedCheck
= R
.getValueAsString("ImpliedCheck");
168 R
.getValueAsOptionalString("ImpliedValue").value_or(Ret
.DefaultValue
);
170 Ret
.ShouldParse
= R
.getValueAsString("ShouldParse");
171 Ret
.Normalizer
= R
.getValueAsString("Normalizer");
172 Ret
.Denormalizer
= R
.getValueAsString("Denormalizer");
173 Ret
.ValueMerger
= R
.getValueAsString("ValueMerger");
174 Ret
.ValueExtractor
= R
.getValueAsString("ValueExtractor");
176 if (!isa
<UnsetInit
>(R
.getValueInit("NormalizedValues"))) {
177 assert(!isa
<UnsetInit
>(R
.getValueInit("Values")) &&
178 "Cannot provide normalized values for value-less options");
179 Ret
.TableIndex
= MarshallingInfo::NextTableIndex
++;
180 Ret
.NormalizedValues
= R
.getValueAsListOfStrings("NormalizedValues");
181 Ret
.Values
.reserve(Ret
.NormalizedValues
.size());
182 Ret
.ValueTableName
= getOptionName(R
) + "ValueTable";
184 StringRef ValuesStr
= R
.getValueAsString("Values");
186 size_t Idx
= ValuesStr
.find(',');
187 if (Idx
== StringRef::npos
)
190 Ret
.Values
.push_back(ValuesStr
.slice(0, Idx
));
191 ValuesStr
= ValuesStr
.substr(Idx
+ 1);
193 if (!ValuesStr
.empty())
194 Ret
.Values
.push_back(ValuesStr
);
196 assert(Ret
.Values
.size() == Ret
.NormalizedValues
.size() &&
197 "The number of normalized values doesn't match the number of "
204 static void emitHelpTextsForVariants(
205 raw_ostream
&OS
, std::vector
<std::pair
<std::vector
<std::string
>, StringRef
>>
206 HelpTextsForVariants
) {
207 // OptTable must be constexpr so it uses std::arrays with these capacities.
208 const unsigned MaxVisibilityPerHelp
= 2;
209 const unsigned MaxVisibilityHelp
= 1;
211 assert(HelpTextsForVariants
.size() <= MaxVisibilityHelp
&&
212 "Too many help text variants to store in "
213 "OptTable::HelpTextsForVariants");
215 // This function must initialise any unused elements of those arrays.
216 for (auto [Visibilities
, _
] : HelpTextsForVariants
)
217 while (Visibilities
.size() < MaxVisibilityPerHelp
)
218 Visibilities
.push_back("0");
220 while (HelpTextsForVariants
.size() < MaxVisibilityHelp
)
221 HelpTextsForVariants
.push_back(
222 {std::vector
<std::string
>(MaxVisibilityPerHelp
, "0"), ""});
224 OS
<< ", (std::array<std::pair<std::array<unsigned, " << MaxVisibilityPerHelp
225 << ">, const char*>, " << MaxVisibilityHelp
<< ">{{ ";
227 auto VisibilityHelpEnd
= HelpTextsForVariants
.cend();
228 for (auto VisibilityHelp
= HelpTextsForVariants
.cbegin();
229 VisibilityHelp
!= VisibilityHelpEnd
; ++VisibilityHelp
) {
230 auto [Visibilities
, Help
] = *VisibilityHelp
;
232 assert(Visibilities
.size() <= MaxVisibilityPerHelp
&&
233 "Too many visibilities to store in an "
234 "OptTable::HelpTextsForVariants entry");
235 OS
<< "{std::array<unsigned, " << MaxVisibilityPerHelp
<< ">{{";
237 auto VisibilityEnd
= Visibilities
.cend();
238 for (auto Visibility
= Visibilities
.cbegin(); Visibility
!= VisibilityEnd
;
241 if (std::next(Visibility
) != VisibilityEnd
)
248 writeCstring(OS
, Help
);
253 if (std::next(VisibilityHelp
) != VisibilityHelpEnd
)
259 /// OptionParserEmitter - This tablegen backend takes an input .td file
260 /// describing a list of options and emits a data structure for parsing and
261 /// working with those options when given an input command line.
262 static void emitOptionParser(const RecordKeeper
&Records
, raw_ostream
&OS
) {
263 // Get the option groups and options.
264 ArrayRef
<const Record
*> Groups
=
265 Records
.getAllDerivedDefinitions("OptionGroup");
266 std::vector
<const Record
*> Opts
= Records
.getAllDerivedDefinitions("Option");
267 llvm::sort(Opts
, IsOptionRecordsLess
);
269 emitSourceFileHeader("Option Parsing Definitions", OS
);
271 // Generate prefix groups.
272 typedef SmallVector
<SmallString
<2>, 2> PrefixKeyT
;
273 typedef std::map
<PrefixKeyT
, unsigned> PrefixesT
;
275 Prefixes
.insert({PrefixKeyT(), 0});
276 for (const Record
&R
: llvm::make_pointee_range(Opts
)) {
277 std::vector
<StringRef
> RPrefixes
= R
.getValueAsListOfStrings("Prefixes");
278 PrefixKeyT
PrefixKey(RPrefixes
.begin(), RPrefixes
.end());
279 Prefixes
.insert({PrefixKey
, 0});
282 DenseSet
<StringRef
> PrefixesUnionSet
;
283 for (const auto &[Prefix
, _
] : Prefixes
)
284 PrefixesUnionSet
.insert(Prefix
.begin(), Prefix
.end());
285 SmallVector
<StringRef
> PrefixesUnion(PrefixesUnionSet
.begin(),
286 PrefixesUnionSet
.end());
287 array_pod_sort(PrefixesUnion
.begin(), PrefixesUnion
.end());
289 llvm::StringToOffsetTable Table
;
290 // We can add all the prefixes via the union.
291 for (const auto &Prefix
: PrefixesUnion
)
292 Table
.GetOrAddStringOffset(Prefix
);
293 for (const Record
&R
: llvm::make_pointee_range(Groups
))
294 Table
.GetOrAddStringOffset(R
.getValueAsString("Name"));
295 for (const Record
&R
: llvm::make_pointee_range(Opts
))
296 Table
.GetOrAddStringOffset(getOptionPrefixedName(R
));
298 // Dump string table.
300 OS
<< "// String table\n\n";
301 OS
<< "#ifdef OPTTABLE_STR_TABLE_CODE\n";
302 Table
.EmitStringTableDef(OS
, "OptionStrTable", /*Indent=*/"");
303 OS
<< "#endif // OPTTABLE_STR_TABLE_CODE\n\n";
307 OS
<< "// Prefixes\n\n";
308 OS
<< "#ifdef OPTTABLE_PREFIXES_TABLE_CODE\n";
309 OS
<< "static constexpr llvm::StringTable::Offset OptionPrefixesTable[] = "
312 // Ensure the first prefix set is always empty.
313 assert(!Prefixes
.empty() &&
314 "We should always emit an empty set of prefixes");
315 assert(Prefixes
.begin()->first
.empty() &&
316 "First prefix set should always be empty");
317 llvm::ListSeparator
Sep(",\n");
318 unsigned CurIndex
= 0;
319 for (auto &[Prefix
, PrefixIndex
] : Prefixes
) {
320 // First emit the number of prefix strings in this list of prefixes.
321 OS
<< Sep
<< " " << Prefix
.size() << " /* prefixes */";
322 PrefixIndex
= CurIndex
;
323 assert((CurIndex
== 0 || !Prefix
.empty()) &&
324 "Only first prefix set should be empty!");
325 for (const auto &PrefixKey
: Prefix
)
326 OS
<< ", " << *Table
.GetStringOffset(PrefixKey
) << " /* '" << PrefixKey
328 CurIndex
+= Prefix
.size() + 1;
332 OS
<< "#endif // OPTTABLE_PREFIXES_TABLE_CODE\n\n";
334 // Dump prefixes union.
336 OS
<< "// Prefix Union\n\n";
337 OS
<< "#ifdef OPTTABLE_PREFIXES_UNION_CODE\n";
338 OS
<< "static constexpr llvm::StringTable::Offset OptionPrefixesUnion[] = "
341 llvm::ListSeparator
Sep(", ");
342 for (auto Prefix
: PrefixesUnion
)
343 OS
<< Sep
<< " " << *Table
.GetStringOffset(Prefix
) << " /* '" << Prefix
347 OS
<< "#endif // OPTTABLE_PREFIXES_UNION_CODE\n\n";
351 OS
<< "// ValuesCode\n\n";
352 OS
<< "#ifdef OPTTABLE_VALUES_CODE\n";
353 for (const Record
&R
: llvm::make_pointee_range(Opts
)) {
354 // The option values, if any;
355 if (!isa
<UnsetInit
>(R
.getValueInit("ValuesCode"))) {
356 assert(isa
<UnsetInit
>(R
.getValueInit("Values")) &&
357 "Cannot choose between Values and ValuesCode");
358 OS
<< "#define VALUES_CODE " << getOptionName(R
) << "_Values\n";
359 OS
<< R
.getValueAsString("ValuesCode") << "\n";
360 OS
<< "#undef VALUES_CODE\n";
366 OS
<< "// Groups\n\n";
367 OS
<< "#ifdef OPTION\n";
368 for (const Record
&R
: llvm::make_pointee_range(Groups
)) {
369 // Start a single option entry.
372 // A zero prefix offset corresponds to an empty set of prefixes.
373 OS
<< "0 /* no prefixes */";
375 // The option string offset.
377 writeStrTableOffset(OS
, Table
, R
.getValueAsString("Name"));
379 // The option identifier name.
380 OS
<< ", " << getOptionName(R
);
385 // The containing option group (if any).
387 if (const DefInit
*DI
= dyn_cast
<DefInit
>(R
.getValueInit("Group")))
388 OS
<< getOptionName(*DI
->getDef());
392 // The other option arguments (unused for groups).
393 OS
<< ", INVALID, nullptr, 0, 0, 0";
395 // The option help text.
396 if (!isa
<UnsetInit
>(R
.getValueInit("HelpText"))) {
399 writeCstring(OS
, R
.getValueAsString("HelpText"));
403 // Not using Visibility specific text for group help.
404 emitHelpTextsForVariants(OS
, {});
406 // The option meta-variable name (unused).
409 // The option Values (unused for groups).
410 OS
<< ", nullptr)\n";
414 OS
<< "//////////\n";
415 OS
<< "// Options\n\n";
417 auto WriteOptRecordFields
= [&](raw_ostream
&OS
, const Record
&R
) {
418 // The option prefix;
419 std::vector
<StringRef
> RPrefixes
= R
.getValueAsListOfStrings("Prefixes");
420 OS
<< Prefixes
[PrefixKeyT(RPrefixes
.begin(), RPrefixes
.end())] << ", ";
422 // The option prefixed name.
423 writeStrTableOffset(OS
, Table
, getOptionPrefixedName(R
));
425 // The option identifier name.
426 OS
<< ", " << getOptionName(R
);
429 OS
<< ", " << R
.getValueAsDef("Kind")->getValueAsString("Name");
431 // The containing option group (if any).
433 const ListInit
*GroupFlags
= nullptr;
434 const ListInit
*GroupVis
= nullptr;
435 if (const DefInit
*DI
= dyn_cast
<DefInit
>(R
.getValueInit("Group"))) {
436 GroupFlags
= DI
->getDef()->getValueAsListInit("Flags");
437 GroupVis
= DI
->getDef()->getValueAsListInit("Visibility");
438 OS
<< getOptionName(*DI
->getDef());
442 // The option alias (if any).
444 if (const DefInit
*DI
= dyn_cast
<DefInit
>(R
.getValueInit("Alias")))
445 OS
<< getOptionName(*DI
->getDef());
449 // The option alias arguments (if any).
450 // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
451 // would become "foo\0bar\0". Note that the compiler adds an implicit
452 // terminating \0 at the end.
454 std::vector
<StringRef
> AliasArgs
= R
.getValueAsListOfStrings("AliasArgs");
455 if (AliasArgs
.size() == 0) {
459 for (StringRef AliasArg
: AliasArgs
)
460 OS
<< AliasArg
<< "\\0";
464 // "Flags" for the option, such as HelpHidden and Render*
467 const ListInit
*LI
= R
.getValueAsListInit("Flags");
468 for (const Init
*I
: *LI
)
469 OS
<< (NumFlags
++ ? " | " : "") << cast
<DefInit
>(I
)->getDef()->getName();
471 for (const Init
*I
: *GroupFlags
)
472 OS
<< (NumFlags
++ ? " | " : "")
473 << cast
<DefInit
>(I
)->getDef()->getName();
478 // Option visibility, for sharing options between drivers.
481 LI
= R
.getValueAsListInit("Visibility");
482 for (const Init
*I
: *LI
)
483 OS
<< (NumVisFlags
++ ? " | " : "")
484 << cast
<DefInit
>(I
)->getDef()->getName();
486 for (const Init
*I
: *GroupVis
)
487 OS
<< (NumVisFlags
++ ? " | " : "")
488 << cast
<DefInit
>(I
)->getDef()->getName();
490 if (NumVisFlags
== 0)
493 // The option parameter field.
494 OS
<< ", " << R
.getValueAsInt("NumArgs");
496 // The option help text.
497 if (!isa
<UnsetInit
>(R
.getValueInit("HelpText"))) {
500 writeCstring(OS
, R
.getValueAsString("HelpText"));
504 std::vector
<std::pair
<std::vector
<std::string
>, StringRef
>>
505 HelpTextsForVariants
;
506 for (const Record
*VisibilityHelp
:
507 R
.getValueAsListOfDefs("HelpTextsForVariants")) {
508 ArrayRef
<const Init
*> Visibilities
=
509 VisibilityHelp
->getValueAsListInit("Visibilities")->getValues();
511 std::vector
<std::string
> VisibilityNames
;
512 for (const Init
*Visibility
: Visibilities
)
513 VisibilityNames
.push_back(Visibility
->getAsUnquotedString());
515 HelpTextsForVariants
.emplace_back(
516 VisibilityNames
, VisibilityHelp
->getValueAsString("Text"));
518 emitHelpTextsForVariants(OS
, std::move(HelpTextsForVariants
));
520 // The option meta-variable name.
522 if (!isa
<UnsetInit
>(R
.getValueInit("MetaVarName")))
523 writeCstring(OS
, R
.getValueAsString("MetaVarName"));
527 // The option Values. Used for shell autocompletion.
529 if (!isa
<UnsetInit
>(R
.getValueInit("Values")))
530 writeCstring(OS
, R
.getValueAsString("Values"));
531 else if (!isa
<UnsetInit
>(R
.getValueInit("ValuesCode"))) {
532 OS
<< getOptionName(R
) << "_Values";
537 auto IsMarshallingOption
= [](const Record
&R
) {
538 return !isa
<UnsetInit
>(R
.getValueInit("KeyPath")) &&
539 !R
.getValueAsString("KeyPath").empty();
542 std::vector
<const Record
*> OptsWithMarshalling
;
543 for (const Record
&R
: llvm::make_pointee_range(Opts
)) {
544 // Start a single option entry.
546 WriteOptRecordFields(OS
, R
);
548 if (IsMarshallingOption(R
))
549 OptsWithMarshalling
.push_back(&R
);
551 OS
<< "#endif // OPTION\n";
553 auto CmpMarshallingOpts
= [](const Record
*const *A
, const Record
*const *B
) {
554 unsigned AID
= (*A
)->getID();
555 unsigned BID
= (*B
)->getID();
563 // The RecordKeeper stores records (options) in lexicographical order, and we
564 // have reordered the options again when generating prefix groups. We need to
565 // restore the original definition order of options with marshalling to honor
566 // the topology of the dependency graph implied by `DefaultAnyOf`.
567 array_pod_sort(OptsWithMarshalling
.begin(), OptsWithMarshalling
.end(),
570 std::vector
<MarshallingInfo
> MarshallingInfos
;
571 MarshallingInfos
.reserve(OptsWithMarshalling
.size());
572 for (const auto *R
: OptsWithMarshalling
)
573 MarshallingInfos
.push_back(createMarshallingInfo(*R
));
575 for (const auto &MI
: MarshallingInfos
) {
576 OS
<< "#ifdef " << MI
.getMacroName() << "\n";
577 OS
<< MI
.getMacroName() << "(";
578 WriteOptRecordFields(OS
, MI
.R
);
582 OS
<< "#endif // " << MI
.getMacroName() << "\n";
586 OS
<< "#ifdef SIMPLE_ENUM_VALUE_TABLE";
588 OS
<< MarshallingInfo::ValueTablePreamble
;
589 std::vector
<StringRef
> ValueTableNames
;
590 for (const auto &MI
: MarshallingInfos
)
591 if (auto MaybeValueTableName
= MI
.emitValueTable(OS
))
592 ValueTableNames
.push_back(*MaybeValueTableName
);
594 OS
<< MarshallingInfo::ValueTablesDecl
<< "{";
595 for (auto ValueTableName
: ValueTableNames
)
596 OS
<< "{" << ValueTableName
<< ", std::size(" << ValueTableName
<< ")},\n";
598 OS
<< "static const unsigned SimpleEnumValueTablesSize = "
599 "std::size(SimpleEnumValueTables);\n";
601 OS
<< "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
607 static TableGen::Emitter::Opt
X("gen-opt-parser-defs", emitOptionParser
,
608 "Generate option definitions");