[Frontend] Remove unused includes (NFC) (#116927)
[llvm-project.git] / llvm / utils / TableGen / OptionParserEmitter.cpp
blob86e8378ad5ac5d67d363ef29cceaf10e48278ba0
1 //===- OptionParserEmitter.cpp - Table Driven Command Option Line Parsing -===//
2 //
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
6 //
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"
16 #include <cstring>
17 #include <map>
19 using namespace llvm;
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) {
30 OS << '"';
31 OS.write_escaped(Str);
32 OS << '"';
33 return OS;
36 static std::string getOptionPrefixedName(const Record &R) {
37 std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes");
38 StringRef Name = R.getValueAsString("Name");
40 if (Prefixes.empty())
41 return Name.str();
43 return (Prefixes[0] + Twine(Name)).str();
46 class MarshallingInfo {
47 public:
48 static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";
49 const Record &R;
50 bool ShouldAlwaysEmit = false;
51 StringRef MacroPrefix;
52 StringRef KeyPath;
53 StringRef DefaultValue;
54 StringRef NormalizedValuesScope;
55 StringRef ImpliedCheck;
56 StringRef ImpliedValue;
57 StringRef ShouldParse;
58 StringRef Normalizer;
59 StringRef Denormalizer;
60 StringRef ValueMerger;
61 StringRef ValueExtractor;
62 int TableIndex = -1;
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 {
71 const char *Name;
72 unsigned Value;
75 struct SimpleEnumValueTable {
76 const SimpleEnumValue *Table;
77 unsigned Size;
79 )";
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 {
91 OS << ShouldParse;
92 OS << ", ";
93 OS << ShouldAlwaysEmit;
94 OS << ", ";
95 OS << KeyPath;
96 OS << ", ";
97 emitScopedNormalizedValue(OS, DefaultValue);
98 OS << ", ";
99 OS << ImpliedCheck;
100 OS << ", ";
101 emitScopedNormalizedValue(OS, ImpliedValue);
102 OS << ", ";
103 OS << Normalizer;
104 OS << ", ";
105 OS << Denormalizer;
106 OS << ", ";
107 OS << ValueMerger;
108 OS << ", ";
109 OS << ValueExtractor;
110 OS << ", ";
111 OS << TableIndex;
114 std::optional<StringRef> emitValueTable(raw_ostream &OS) const {
115 if (TableIndex == -1)
116 return {};
117 OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
118 for (unsigned I = 0, E = Values.size(); I != E; ++I) {
119 OS << "{";
120 writeCstring(OS, Values[I]);
121 OS << ",";
122 OS << "static_cast<unsigned>(";
123 emitScopedNormalizedValue(OS, NormalizedValues[I]);
124 OS << ")},";
126 OS << "};\n";
127 return StringRef(ValueTableName);
130 private:
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 "
146 "value merger");
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");
156 Ret.ImpliedValue =
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");
174 for (;;) {
175 size_t Idx = ValuesStr.find(',');
176 if (Idx == StringRef::npos)
177 break;
178 if (Idx > 0)
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 "
187 "values");
190 return Ret;
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
225 << ">{{";
227 auto VisibilityEnd = Visibilities.cend();
228 for (auto Visibility = Visibilities.cbegin(); Visibility != VisibilityEnd;
229 ++Visibility) {
230 OS << *Visibility;
231 if (std::next(Visibility) != VisibilityEnd)
232 OS << ", ";
235 OS << "}}, ";
237 if (Help.size())
238 writeCstring(OS, Help);
239 else
240 OS << "nullptr";
241 OS << ")";
243 if (std::next(VisibilityHelp) != VisibilityHelpEnd)
244 OS << ", ";
246 OS << " }})";
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;
264 PrefixesT Prefixes;
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());
283 // Dump prefixes.
284 OS << "/////////\n";
285 OS << "// Prefixes\n\n";
286 OS << "#ifdef PREFIX\n";
287 OS << "#define COMMA ,\n";
288 for (const auto &Prefix : Prefixes) {
289 OS << "PREFIX(";
291 // Prefix name.
292 OS << Prefix.second;
294 // Prefix values.
295 OS << ", {";
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.
305 OS << "/////////\n";
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";
317 // Dump groups.
318 OS << "/////////\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";
331 OS << "#endif\n";
333 OS << "/////////\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.
338 OS << "OPTION(";
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);
349 // The option kind.
350 OS << ", Group";
352 // The containing option group (if any).
353 OS << ", ";
354 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
355 OS << getOptionName(*DI->getDef());
356 else
357 OS << "INVALID";
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"))) {
364 OS << ",\n";
365 OS << " ";
366 writeCstring(OS, R.getValueAsString("HelpText"));
367 } else
368 OS << ", nullptr";
370 // Not using Visibility specific text for group help.
371 emitHelpTextsForVariants(OS, {});
373 // The option meta-variable name (unused).
374 OS << ", nullptr";
376 // The option Values (unused for groups).
377 OS << ", nullptr)\n";
379 OS << "\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);
395 // The option kind.
396 OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
398 // The containing option group (if any).
399 OS << ", ";
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());
406 } else
407 OS << "INVALID";
409 // The option alias (if any).
410 OS << ", ";
411 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
412 OS << getOptionName(*DI->getDef());
413 else
414 OS << "INVALID";
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.
420 OS << ", ";
421 std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
422 if (AliasArgs.size() == 0) {
423 OS << "nullptr";
424 } else {
425 OS << "\"";
426 for (StringRef AliasArg : AliasArgs)
427 OS << AliasArg << "\\0";
428 OS << "\"";
431 // "Flags" for the option, such as HelpHidden and Render*
432 OS << ", ";
433 int NumFlags = 0;
434 const ListInit *LI = R.getValueAsListInit("Flags");
435 for (const Init *I : *LI)
436 OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
437 if (GroupFlags) {
438 for (const Init *I : *GroupFlags)
439 OS << (NumFlags++ ? " | " : "")
440 << cast<DefInit>(I)->getDef()->getName();
442 if (NumFlags == 0)
443 OS << '0';
445 // Option visibility, for sharing options between drivers.
446 OS << ", ";
447 int NumVisFlags = 0;
448 LI = R.getValueAsListInit("Visibility");
449 for (const Init *I : *LI)
450 OS << (NumVisFlags++ ? " | " : "")
451 << cast<DefInit>(I)->getDef()->getName();
452 if (GroupVis) {
453 for (const Init *I : *GroupVis)
454 OS << (NumVisFlags++ ? " | " : "")
455 << cast<DefInit>(I)->getDef()->getName();
457 if (NumVisFlags == 0)
458 OS << '0';
460 // The option parameter field.
461 OS << ", " << R.getValueAsInt("NumArgs");
463 // The option help text.
464 if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
465 OS << ",\n";
466 OS << " ";
467 writeCstring(OS, R.getValueAsString("HelpText"));
468 } else
469 OS << ", nullptr";
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.
488 OS << ", ";
489 if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
490 writeCstring(OS, R.getValueAsString("MetaVarName"));
491 else
492 OS << "nullptr";
494 // The option Values. Used for shell autocompletion.
495 OS << ", ";
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";
500 } else
501 OS << "nullptr";
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.
512 OS << "OPTION(";
513 WriteOptRecordFields(OS, R);
514 OS << ")\n";
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();
524 if (AID < BID)
525 return -1;
526 if (AID > BID)
527 return 1;
528 return 0;
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(),
535 CmpMarshallingOpts);
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);
546 OS << ", ";
547 MI.emit(OS);
548 OS << ")\n";
549 OS << "#endif // " << MI.getMacroName() << "\n";
552 OS << "\n";
553 OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
554 OS << "\n";
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";
564 OS << "};\n";
565 OS << "static const unsigned SimpleEnumValueTablesSize = "
566 "std::size(SimpleEnumValueTables);\n";
568 OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
569 OS << "\n";
571 OS << "\n";
574 static TableGen::Emitter::Opt X("gen-opt-parser-defs", emitOptionParser,
575 "Generate option definitions");