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/Twine.h"
13 #include "llvm/Support/raw_ostream.h"
14 #include "llvm/TableGen/Record.h"
15 #include "llvm/TableGen/TableGenBackend.h"
21 static std::string
getOptionName(const Record
&R
) {
22 // Use the record name unless EnumName is defined.
23 if (isa
<UnsetInit
>(R
.getValueInit("EnumName")))
24 return std::string(R
.getName());
26 return std::string(R
.getValueAsString("EnumName"));
29 static raw_ostream
&writeCstring(raw_ostream
&OS
, llvm::StringRef Str
) {
31 OS
.write_escaped(Str
);
36 static std::string
getOptionPrefixedName(const Record
&R
) {
37 std::vector
<StringRef
> Prefixes
= R
.getValueAsListOfStrings("Prefixes");
38 StringRef Name
= R
.getValueAsString("Name");
43 return (Prefixes
[0] + Twine(Name
)).str();
46 class MarshallingInfo
{
48 static constexpr const char *MacroName
= "OPTION_WITH_MARSHALLING";
50 bool ShouldAlwaysEmit
= false;
51 StringRef MacroPrefix
;
53 StringRef DefaultValue
;
54 StringRef NormalizedValuesScope
;
55 StringRef ImpliedCheck
;
56 StringRef ImpliedValue
;
57 StringRef ShouldParse
;
59 StringRef Denormalizer
;
60 StringRef ValueMerger
;
61 StringRef ValueExtractor
;
63 std::vector
<StringRef
> Values
;
64 std::vector
<StringRef
> NormalizedValues
;
65 std::string ValueTableName
;
67 static size_t NextTableIndex
;
69 static constexpr const char *ValueTablePreamble
= R
"(
70 struct SimpleEnumValue {
75 struct SimpleEnumValueTable {
76 const SimpleEnumValue *Table;
81 static constexpr const char *ValueTablesDecl
=
82 "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
84 MarshallingInfo(const Record
&R
) : R(R
) {}
86 std::string
getMacroName() const {
87 return (MacroPrefix
+ MarshallingInfo::MacroName
).str();
90 void emit(raw_ostream
&OS
) const {
93 OS
<< ShouldAlwaysEmit
;
97 emitScopedNormalizedValue(OS
, DefaultValue
);
101 emitScopedNormalizedValue(OS
, ImpliedValue
);
109 OS
<< ValueExtractor
;
114 std::optional
<StringRef
> emitValueTable(raw_ostream
&OS
) const {
115 if (TableIndex
== -1)
117 OS
<< "static const SimpleEnumValue " << ValueTableName
<< "[] = {\n";
118 for (unsigned I
= 0, E
= Values
.size(); I
!= E
; ++I
) {
120 writeCstring(OS
, Values
[I
]);
122 OS
<< "static_cast<unsigned>(";
123 emitScopedNormalizedValue(OS
, NormalizedValues
[I
]);
127 return StringRef(ValueTableName
);
131 void emitScopedNormalizedValue(raw_ostream
&OS
,
132 StringRef NormalizedValue
) const {
133 if (!NormalizedValuesScope
.empty())
134 OS
<< NormalizedValuesScope
<< "::";
135 OS
<< NormalizedValue
;
139 size_t MarshallingInfo::NextTableIndex
= 0;
141 static MarshallingInfo
createMarshallingInfo(const Record
&R
) {
142 assert(!isa
<UnsetInit
>(R
.getValueInit("KeyPath")) &&
143 !isa
<UnsetInit
>(R
.getValueInit("DefaultValue")) &&
144 !isa
<UnsetInit
>(R
.getValueInit("ValueMerger")) &&
145 "MarshallingInfo must have a provide a keypath, default value and a "
148 MarshallingInfo
Ret(R
);
150 Ret
.ShouldAlwaysEmit
= R
.getValueAsBit("ShouldAlwaysEmit");
151 Ret
.MacroPrefix
= R
.getValueAsString("MacroPrefix");
152 Ret
.KeyPath
= R
.getValueAsString("KeyPath");
153 Ret
.DefaultValue
= R
.getValueAsString("DefaultValue");
154 Ret
.NormalizedValuesScope
= R
.getValueAsString("NormalizedValuesScope");
155 Ret
.ImpliedCheck
= R
.getValueAsString("ImpliedCheck");
157 R
.getValueAsOptionalString("ImpliedValue").value_or(Ret
.DefaultValue
);
159 Ret
.ShouldParse
= R
.getValueAsString("ShouldParse");
160 Ret
.Normalizer
= R
.getValueAsString("Normalizer");
161 Ret
.Denormalizer
= R
.getValueAsString("Denormalizer");
162 Ret
.ValueMerger
= R
.getValueAsString("ValueMerger");
163 Ret
.ValueExtractor
= R
.getValueAsString("ValueExtractor");
165 if (!isa
<UnsetInit
>(R
.getValueInit("NormalizedValues"))) {
166 assert(!isa
<UnsetInit
>(R
.getValueInit("Values")) &&
167 "Cannot provide normalized values for value-less options");
168 Ret
.TableIndex
= MarshallingInfo::NextTableIndex
++;
169 Ret
.NormalizedValues
= R
.getValueAsListOfStrings("NormalizedValues");
170 Ret
.Values
.reserve(Ret
.NormalizedValues
.size());
171 Ret
.ValueTableName
= getOptionName(R
) + "ValueTable";
173 StringRef ValuesStr
= R
.getValueAsString("Values");
175 size_t Idx
= ValuesStr
.find(',');
176 if (Idx
== StringRef::npos
)
179 Ret
.Values
.push_back(ValuesStr
.slice(0, Idx
));
180 ValuesStr
= ValuesStr
.substr(Idx
+ 1);
182 if (!ValuesStr
.empty())
183 Ret
.Values
.push_back(ValuesStr
);
185 assert(Ret
.Values
.size() == Ret
.NormalizedValues
.size() &&
186 "The number of normalized values doesn't match the number of "
193 static void emitHelpTextsForVariants(
194 raw_ostream
&OS
, std::vector
<std::pair
<std::vector
<std::string
>, StringRef
>>
195 HelpTextsForVariants
) {
196 // OptTable must be constexpr so it uses std::arrays with these capacities.
197 const unsigned MaxVisibilityPerHelp
= 2;
198 const unsigned MaxVisibilityHelp
= 1;
200 assert(HelpTextsForVariants
.size() <= MaxVisibilityHelp
&&
201 "Too many help text variants to store in "
202 "OptTable::HelpTextsForVariants");
204 // This function must initialise any unused elements of those arrays.
205 for (auto [Visibilities
, _
] : HelpTextsForVariants
)
206 while (Visibilities
.size() < MaxVisibilityPerHelp
)
207 Visibilities
.push_back("0");
209 while (HelpTextsForVariants
.size() < MaxVisibilityHelp
)
210 HelpTextsForVariants
.push_back(
211 {std::vector
<std::string
>(MaxVisibilityPerHelp
, "0"), ""});
213 OS
<< ", (std::array<std::pair<std::array<unsigned, " << MaxVisibilityPerHelp
214 << ">, const char*>, " << MaxVisibilityHelp
<< ">{{ ";
216 auto VisibilityHelpEnd
= HelpTextsForVariants
.cend();
217 for (auto VisibilityHelp
= HelpTextsForVariants
.cbegin();
218 VisibilityHelp
!= VisibilityHelpEnd
; ++VisibilityHelp
) {
219 auto [Visibilities
, Help
] = *VisibilityHelp
;
221 assert(Visibilities
.size() <= MaxVisibilityPerHelp
&&
222 "Too many visibilities to store in an "
223 "OptTable::HelpTextsForVariants entry");
224 OS
<< "std::make_pair(std::array<unsigned, " << MaxVisibilityPerHelp
227 auto VisibilityEnd
= Visibilities
.cend();
228 for (auto Visibility
= Visibilities
.cbegin(); Visibility
!= VisibilityEnd
;
231 if (std::next(Visibility
) != VisibilityEnd
)
238 writeCstring(OS
, Help
);
243 if (std::next(VisibilityHelp
) != VisibilityHelpEnd
)
249 /// OptionParserEmitter - This tablegen backend takes an input .td file
250 /// describing a list of options and emits a data structure for parsing and
251 /// working with those options when given an input command line.
252 static void emitOptionParser(const RecordKeeper
&Records
, raw_ostream
&OS
) {
253 // Get the option groups and options.
254 ArrayRef
<const Record
*> Groups
=
255 Records
.getAllDerivedDefinitions("OptionGroup");
256 std::vector
<const Record
*> Opts
= Records
.getAllDerivedDefinitions("Option");
257 llvm::sort(Opts
, IsOptionRecordsLess
);
259 emitSourceFileHeader("Option Parsing Definitions", OS
);
261 // Generate prefix groups.
262 typedef SmallVector
<SmallString
<2>, 2> PrefixKeyT
;
263 typedef std::map
<PrefixKeyT
, std::string
> PrefixesT
;
265 Prefixes
.insert(std::pair(PrefixKeyT(), "prefix_0"));
266 unsigned CurPrefix
= 0;
267 for (const Record
&R
: llvm::make_pointee_range(Opts
)) {
268 std::vector
<StringRef
> RPrefixes
= R
.getValueAsListOfStrings("Prefixes");
269 PrefixKeyT
PrefixKey(RPrefixes
.begin(), RPrefixes
.end());
270 unsigned NewPrefix
= CurPrefix
+ 1;
271 std::string Prefix
= (Twine("prefix_") + Twine(NewPrefix
)).str();
272 if (Prefixes
.insert(std::pair(PrefixKey
, Prefix
)).second
)
273 CurPrefix
= NewPrefix
;
276 DenseSet
<StringRef
> PrefixesUnionSet
;
277 for (const auto &Prefix
: Prefixes
)
278 PrefixesUnionSet
.insert(Prefix
.first
.begin(), Prefix
.first
.end());
279 SmallVector
<StringRef
> PrefixesUnion(PrefixesUnionSet
.begin(),
280 PrefixesUnionSet
.end());
281 array_pod_sort(PrefixesUnion
.begin(), PrefixesUnion
.end());
285 OS
<< "// Prefixes\n\n";
286 OS
<< "#ifdef PREFIX\n";
287 OS
<< "#define COMMA ,\n";
288 for (const auto &Prefix
: Prefixes
) {
296 for (const auto &PrefixKey
: Prefix
.first
)
297 OS
<< "llvm::StringLiteral(\"" << PrefixKey
<< "\") COMMA ";
298 // Append an empty element to avoid ending up with an empty array.
299 OS
<< "llvm::StringLiteral(\"\")})\n";
301 OS
<< "#undef COMMA\n";
302 OS
<< "#endif // PREFIX\n\n";
304 // Dump prefix unions.
306 OS
<< "// Prefix Union\n\n";
307 OS
<< "#ifdef PREFIX_UNION\n";
308 OS
<< "#define COMMA ,\n";
309 OS
<< "PREFIX_UNION({\n";
310 for (const auto &Prefix
: PrefixesUnion
) {
311 OS
<< "llvm::StringLiteral(\"" << Prefix
<< "\") COMMA ";
313 OS
<< "llvm::StringLiteral(\"\")})\n";
314 OS
<< "#undef COMMA\n";
315 OS
<< "#endif // PREFIX_UNION\n\n";
319 OS
<< "// ValuesCode\n\n";
320 OS
<< "#ifdef OPTTABLE_VALUES_CODE\n";
321 for (const Record
&R
: llvm::make_pointee_range(Opts
)) {
322 // The option values, if any;
323 if (!isa
<UnsetInit
>(R
.getValueInit("ValuesCode"))) {
324 assert(isa
<UnsetInit
>(R
.getValueInit("Values")) &&
325 "Cannot choose between Values and ValuesCode");
326 OS
<< "#define VALUES_CODE " << getOptionName(R
) << "_Values\n";
327 OS
<< R
.getValueAsString("ValuesCode") << "\n";
328 OS
<< "#undef VALUES_CODE\n";
334 OS
<< "// Groups\n\n";
335 OS
<< "#ifdef OPTION\n";
336 for (const Record
&R
: llvm::make_pointee_range(Groups
)) {
337 // Start a single option entry.
340 // The option prefix;
341 OS
<< "llvm::ArrayRef<llvm::StringLiteral>()";
343 // The option string.
344 OS
<< ", \"" << R
.getValueAsString("Name") << '"';
346 // The option identifier name.
347 OS
<< ", " << getOptionName(R
);
352 // The containing option group (if any).
354 if (const DefInit
*DI
= dyn_cast
<DefInit
>(R
.getValueInit("Group")))
355 OS
<< getOptionName(*DI
->getDef());
359 // The other option arguments (unused for groups).
360 OS
<< ", INVALID, nullptr, 0, 0, 0";
362 // The option help text.
363 if (!isa
<UnsetInit
>(R
.getValueInit("HelpText"))) {
366 writeCstring(OS
, R
.getValueAsString("HelpText"));
370 // Not using Visibility specific text for group help.
371 emitHelpTextsForVariants(OS
, {});
373 // The option meta-variable name (unused).
376 // The option Values (unused for groups).
377 OS
<< ", nullptr)\n";
381 OS
<< "//////////\n";
382 OS
<< "// Options\n\n";
384 auto WriteOptRecordFields
= [&](raw_ostream
&OS
, const Record
&R
) {
385 // The option prefix;
386 std::vector
<StringRef
> RPrefixes
= R
.getValueAsListOfStrings("Prefixes");
387 OS
<< Prefixes
[PrefixKeyT(RPrefixes
.begin(), RPrefixes
.end())] << ", ";
389 // The option prefixed name.
390 writeCstring(OS
, getOptionPrefixedName(R
));
392 // The option identifier name.
393 OS
<< ", " << getOptionName(R
);
396 OS
<< ", " << R
.getValueAsDef("Kind")->getValueAsString("Name");
398 // The containing option group (if any).
400 const ListInit
*GroupFlags
= nullptr;
401 const ListInit
*GroupVis
= nullptr;
402 if (const DefInit
*DI
= dyn_cast
<DefInit
>(R
.getValueInit("Group"))) {
403 GroupFlags
= DI
->getDef()->getValueAsListInit("Flags");
404 GroupVis
= DI
->getDef()->getValueAsListInit("Visibility");
405 OS
<< getOptionName(*DI
->getDef());
409 // The option alias (if any).
411 if (const DefInit
*DI
= dyn_cast
<DefInit
>(R
.getValueInit("Alias")))
412 OS
<< getOptionName(*DI
->getDef());
416 // The option alias arguments (if any).
417 // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
418 // would become "foo\0bar\0". Note that the compiler adds an implicit
419 // terminating \0 at the end.
421 std::vector
<StringRef
> AliasArgs
= R
.getValueAsListOfStrings("AliasArgs");
422 if (AliasArgs
.size() == 0) {
426 for (StringRef AliasArg
: AliasArgs
)
427 OS
<< AliasArg
<< "\\0";
431 // "Flags" for the option, such as HelpHidden and Render*
434 const ListInit
*LI
= R
.getValueAsListInit("Flags");
435 for (const Init
*I
: *LI
)
436 OS
<< (NumFlags
++ ? " | " : "") << cast
<DefInit
>(I
)->getDef()->getName();
438 for (const Init
*I
: *GroupFlags
)
439 OS
<< (NumFlags
++ ? " | " : "")
440 << cast
<DefInit
>(I
)->getDef()->getName();
445 // Option visibility, for sharing options between drivers.
448 LI
= R
.getValueAsListInit("Visibility");
449 for (const Init
*I
: *LI
)
450 OS
<< (NumVisFlags
++ ? " | " : "")
451 << cast
<DefInit
>(I
)->getDef()->getName();
453 for (const Init
*I
: *GroupVis
)
454 OS
<< (NumVisFlags
++ ? " | " : "")
455 << cast
<DefInit
>(I
)->getDef()->getName();
457 if (NumVisFlags
== 0)
460 // The option parameter field.
461 OS
<< ", " << R
.getValueAsInt("NumArgs");
463 // The option help text.
464 if (!isa
<UnsetInit
>(R
.getValueInit("HelpText"))) {
467 writeCstring(OS
, R
.getValueAsString("HelpText"));
471 std::vector
<std::pair
<std::vector
<std::string
>, StringRef
>>
472 HelpTextsForVariants
;
473 for (const Record
*VisibilityHelp
:
474 R
.getValueAsListOfDefs("HelpTextsForVariants")) {
475 ArrayRef
<const Init
*> Visibilities
=
476 VisibilityHelp
->getValueAsListInit("Visibilities")->getValues();
478 std::vector
<std::string
> VisibilityNames
;
479 for (const Init
*Visibility
: Visibilities
)
480 VisibilityNames
.push_back(Visibility
->getAsUnquotedString());
482 HelpTextsForVariants
.push_back(std::make_pair(
483 VisibilityNames
, VisibilityHelp
->getValueAsString("Text")));
485 emitHelpTextsForVariants(OS
, HelpTextsForVariants
);
487 // The option meta-variable name.
489 if (!isa
<UnsetInit
>(R
.getValueInit("MetaVarName")))
490 writeCstring(OS
, R
.getValueAsString("MetaVarName"));
494 // The option Values. Used for shell autocompletion.
496 if (!isa
<UnsetInit
>(R
.getValueInit("Values")))
497 writeCstring(OS
, R
.getValueAsString("Values"));
498 else if (!isa
<UnsetInit
>(R
.getValueInit("ValuesCode"))) {
499 OS
<< getOptionName(R
) << "_Values";
504 auto IsMarshallingOption
= [](const Record
&R
) {
505 return !isa
<UnsetInit
>(R
.getValueInit("KeyPath")) &&
506 !R
.getValueAsString("KeyPath").empty();
509 std::vector
<const Record
*> OptsWithMarshalling
;
510 for (const Record
&R
: llvm::make_pointee_range(Opts
)) {
511 // Start a single option entry.
513 WriteOptRecordFields(OS
, R
);
515 if (IsMarshallingOption(R
))
516 OptsWithMarshalling
.push_back(&R
);
518 OS
<< "#endif // OPTION\n";
520 auto CmpMarshallingOpts
= [](const Record
*const *A
, const Record
*const *B
) {
521 unsigned AID
= (*A
)->getID();
522 unsigned BID
= (*B
)->getID();
530 // The RecordKeeper stores records (options) in lexicographical order, and we
531 // have reordered the options again when generating prefix groups. We need to
532 // restore the original definition order of options with marshalling to honor
533 // the topology of the dependency graph implied by `DefaultAnyOf`.
534 array_pod_sort(OptsWithMarshalling
.begin(), OptsWithMarshalling
.end(),
537 std::vector
<MarshallingInfo
> MarshallingInfos
;
538 MarshallingInfos
.reserve(OptsWithMarshalling
.size());
539 for (const auto *R
: OptsWithMarshalling
)
540 MarshallingInfos
.push_back(createMarshallingInfo(*R
));
542 for (const auto &MI
: MarshallingInfos
) {
543 OS
<< "#ifdef " << MI
.getMacroName() << "\n";
544 OS
<< MI
.getMacroName() << "(";
545 WriteOptRecordFields(OS
, MI
.R
);
549 OS
<< "#endif // " << MI
.getMacroName() << "\n";
553 OS
<< "#ifdef SIMPLE_ENUM_VALUE_TABLE";
555 OS
<< MarshallingInfo::ValueTablePreamble
;
556 std::vector
<StringRef
> ValueTableNames
;
557 for (const auto &MI
: MarshallingInfos
)
558 if (auto MaybeValueTableName
= MI
.emitValueTable(OS
))
559 ValueTableNames
.push_back(*MaybeValueTableName
);
561 OS
<< MarshallingInfo::ValueTablesDecl
<< "{";
562 for (auto ValueTableName
: ValueTableNames
)
563 OS
<< "{" << ValueTableName
<< ", std::size(" << ValueTableName
<< ")},\n";
565 OS
<< "static const unsigned SimpleEnumValueTablesSize = "
566 "std::size(SimpleEnumValueTables);\n";
568 OS
<< "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
574 static TableGen::Emitter::Opt
X("gen-opt-parser-defs", emitOptionParser
,
575 "Generate option definitions");