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//===----------------------------------------------------------------------===//
8
9#include "OptEmitter.h"
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/SmallString.h"
12#include "llvm/ADT/SmallVector.h"
13#include "llvm/ADT/StringExtras.h"
14#include "llvm/ADT/StringMap.h"
15#include "llvm/ADT/Twine.h"
16#include "llvm/Support/raw_ostream.h"
17#include "llvm/TableGen/Error.h"
18#include "llvm/TableGen/Record.h"
19#include "llvm/TableGen/StringToOffsetTable.h"
20#include "llvm/TableGen/TableGenBackend.h"
21#include <array>
22#include <cstring>
23#include <map>
24#include <set>
25
26using namespace llvm;
27
28static std::string getOptionName(const Record &R) {
29 // Use the record name unless EnumName is defined.
30 if (isa<UnsetInit>(Val: R.getValueInit(FieldName: "EnumName")))
31 return R.getName().str();
32
33 return R.getValueAsString(FieldName: "EnumName").str();
34}
35
36// Only pass EmitComment for short strings that cannot contain "*/".
37static void writeStrTableOffset(raw_ostream &OS,
38 const StringToOffsetTable &Table,
39 llvm::StringRef Str, bool EmitComment = false) {
40 std::optional<unsigned> Offset = Table.GetStringOffset(Str);
41 if (!Offset)
42 PrintFatalError(Msg: "string was not added to the option string table: " + Str);
43 OS << *Offset;
44 if (EmitComment) {
45 OS << " /* ";
46 OS.write_escaped(Str);
47 OS << " */";
48 }
49}
50
51static raw_ostream &writeCstring(raw_ostream &OS, llvm::StringRef Str) {
52 OS << '"';
53 OS.write_escaped(Str);
54 OS << '"';
55 return OS;
56}
57
58static StringRef getOptionalString(const Record &R, StringRef Field) {
59 return R.getValueAsOptionalString(FieldName: Field).value_or(u: "");
60}
61
62// Offset zero is the empty string and stands for an unset HelpText. A
63// HelpText<""> marks an option as deliberately undocumented, so it maps to a
64// second empty string that the table does not put at offset zero.
65static StringRef getHelpText(const Record &R) {
66 std::optional<StringRef> S = R.getValueAsOptionalString(FieldName: "HelpText");
67 if (!S)
68 return StringRef();
69 return S->empty() ? StringRef("\0", 1) : *S;
70}
71
72// The string table appends the empty string that terminates the list.
73static std::string getAliasArgsBlob(const Record &R) {
74 std::string Blob;
75 for (StringRef AliasArg : R.getValueAsListOfStrings(FieldName: "AliasArgs")) {
76 if (AliasArg.empty())
77 PrintFatalError(ErrorLoc: R.getLoc(), Msg: "AliasArgs entries must not be empty");
78 Blob += AliasArg;
79 Blob += '\0';
80 }
81 return Blob;
82}
83
84static std::string getOptionPrefixedName(const Record &R) {
85 std::vector<StringRef> Prefixes = R.getValueAsListOfStrings(FieldName: "Prefixes");
86 StringRef Name = R.getValueAsString(FieldName: "Name");
87
88 if (Prefixes.empty())
89 return Name.str();
90
91 return (Prefixes[0] + Twine(Name)).str();
92}
93
94class MarshallingInfo {
95public:
96 static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";
97 const Record &R;
98 bool ShouldAlwaysEmit = false;
99 StringRef MacroPrefix;
100 StringRef KeyPath;
101 StringRef DefaultValue;
102 StringRef NormalizedValuesScope;
103 StringRef ImpliedCheck;
104 StringRef ImpliedValue;
105 StringRef ShouldParse;
106 StringRef Normalizer;
107 StringRef Denormalizer;
108 int TableIndex = -1;
109 std::vector<StringRef> Values;
110 std::vector<StringRef> NormalizedValues;
111 std::string ValueTableName;
112
113 static size_t NextTableIndex;
114
115 static constexpr const char *ValueTablePreamble = R"(
116struct SimpleEnumValue {
117 const char *Name;
118 unsigned Value;
119};
120
121struct SimpleEnumValueTable {
122 const SimpleEnumValue *Table;
123 unsigned Size;
124};
125)";
126
127 static constexpr const char *ValueTablesDecl =
128 "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
129
130 MarshallingInfo(const Record &R) : R(R) {}
131
132 std::string getMacroName() const {
133 return (MacroPrefix + MarshallingInfo::MacroName).str();
134 }
135
136 void emit(raw_ostream &OS) const {
137 OS << ShouldParse;
138 OS << ", ";
139 OS << ShouldAlwaysEmit;
140 OS << ", ";
141 OS << KeyPath;
142 OS << ", ";
143 emitScopedNormalizedValue(OS, NormalizedValue: DefaultValue);
144 OS << ", ";
145 OS << ImpliedCheck;
146 OS << ", ";
147 emitScopedNormalizedValue(OS, NormalizedValue: ImpliedValue);
148 OS << ", ";
149 OS << Normalizer;
150 OS << ", ";
151 OS << Denormalizer;
152 OS << ", ";
153 OS << TableIndex;
154 }
155
156 std::optional<StringRef> emitValueTable(raw_ostream &OS) const {
157 if (TableIndex == -1)
158 return {};
159 OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
160 for (unsigned I = 0, E = Values.size(); I != E; ++I) {
161 OS << "{";
162 writeCstring(OS, Str: Values[I]);
163 OS << ",";
164 OS << "static_cast<unsigned>(";
165 emitScopedNormalizedValue(OS, NormalizedValue: NormalizedValues[I]);
166 OS << ")},";
167 }
168 OS << "};\n";
169 return StringRef(ValueTableName);
170 }
171
172private:
173 void emitScopedNormalizedValue(raw_ostream &OS,
174 StringRef NormalizedValue) const {
175 if (!NormalizedValuesScope.empty())
176 OS << NormalizedValuesScope << "::";
177 OS << NormalizedValue;
178 }
179};
180
181size_t MarshallingInfo::NextTableIndex = 0;
182
183static MarshallingInfo createMarshallingInfo(const Record &R) {
184 assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
185 !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
186 "MarshallingInfo must have a provide a keypath, default value and a "
187 "value merger");
188
189 MarshallingInfo Ret(R);
190
191 Ret.ShouldAlwaysEmit = R.getValueAsBit(FieldName: "ShouldAlwaysEmit");
192 Ret.MacroPrefix = R.getValueAsString(FieldName: "MacroPrefix");
193 Ret.KeyPath = R.getValueAsString(FieldName: "KeyPath");
194 Ret.DefaultValue = R.getValueAsString(FieldName: "DefaultValue");
195 Ret.NormalizedValuesScope = R.getValueAsString(FieldName: "NormalizedValuesScope");
196 Ret.ImpliedCheck = R.getValueAsString(FieldName: "ImpliedCheck");
197 Ret.ImpliedValue =
198 R.getValueAsOptionalString(FieldName: "ImpliedValue").value_or(u&: Ret.DefaultValue);
199
200 Ret.ShouldParse = R.getValueAsString(FieldName: "ShouldParse");
201 Ret.Normalizer = R.getValueAsString(FieldName: "Normalizer");
202 Ret.Denormalizer = R.getValueAsString(FieldName: "Denormalizer");
203
204 if (!isa<UnsetInit>(Val: R.getValueInit(FieldName: "NormalizedValues"))) {
205 assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
206 "Cannot provide normalized values for value-less options");
207 Ret.TableIndex = MarshallingInfo::NextTableIndex++;
208 Ret.NormalizedValues = R.getValueAsListOfStrings(FieldName: "NormalizedValues");
209 Ret.Values.reserve(n: Ret.NormalizedValues.size());
210 Ret.ValueTableName = getOptionName(R) + "ValueTable";
211
212 StringRef ValuesStr = R.getValueAsString(FieldName: "Values");
213 for (;;) {
214 size_t Idx = ValuesStr.find(C: ',');
215 if (Idx == StringRef::npos)
216 break;
217 if (Idx > 0)
218 Ret.Values.push_back(x: ValuesStr.slice(Start: 0, End: Idx));
219 ValuesStr = ValuesStr.substr(Start: Idx + 1);
220 }
221 if (!ValuesStr.empty())
222 Ret.Values.push_back(x: ValuesStr);
223
224 assert(Ret.Values.size() == Ret.NormalizedValues.size() &&
225 "The number of normalized values doesn't match the number of "
226 "values");
227 }
228
229 return Ret;
230}
231
232// -foo-bar becomes foo_bar, or bar if Prefix is "foo-".
233static std::string getSpellingIdentifier(const Record &R,
234 StringRef Prefix = "") {
235 StringRef Spelling = R.getValueAsString(FieldName: "Name");
236 Spelling.consume_front(Prefix);
237 std::string ID = Spelling.str();
238 llvm::replace(Range&: ID, OldValue: '-', NewValue: '_');
239 if (ID.empty() || isDigit(C: ID[0]) ||
240 !all_of(Range&: ID, P: [](char C) { return isAlnum(C) || C == '_'; }))
241 PrintFatalError(ErrorLoc: R.getLoc(), Msg: "the spelling is not an identifier; name the "
242 "defm");
243 return ID;
244}
245
246// `defm : BoolField<"foo-bar", ...>` declares member foo_bar, and a named defm
247// names it.
248static std::string getMemberName(const Record &R, StringRef Prefix) {
249 StringRef Name = R.getValueAsString(FieldName: "FieldName");
250 return Name.starts_with(Prefix: "anonymous_") ? getSpellingIdentifier(R, Prefix)
251 : Name.str();
252}
253
254// The OPT_ name of an option of an OptionsStruct. `defm :` rows are named
255// after the spelling: -foo-bar is OPT_foo_bar.
256static std::string getStructOptionID(const Record &R) {
257 if (!R.getName().starts_with(Prefix: "anonymous_"))
258 return getOptionName(R);
259 return getSpellingIdentifier(R);
260}
261
262// The preprocessor expression of R's Condition, or "" if it has none.
263static StringRef getCondition(const Record &R) {
264 const RecordVal *V = R.getValue(Name: "Condition");
265 const auto *DI = V ? dyn_cast<DefInit>(Val: V->getValue()) : nullptr;
266 return DI ? DI->getDef()->getValueAsString(FieldName: "Expr") : "";
267}
268
269namespace {
270// Wraps what is emitted during its lifetime in `#if Condition` where R has one.
271class ConditionScope {
272 raw_ostream &OS;
273 StringRef Condition;
274
275public:
276 ConditionScope(raw_ostream &OS, const Record &R)
277 : OS(OS), Condition(getCondition(R)) {
278 if (!Condition.empty())
279 OS << "#if " << Condition << '\n';
280 }
281 ~ConditionScope() {
282 if (!Condition.empty())
283 OS << "#endif\n";
284 }
285};
286} // namespace
287
288// Emits the OPT_ IDs of an OptionsStruct, which its table rows name.
289static void emitStructOptionIDs(ArrayRef<const Record *> Groups,
290 ArrayRef<const Record *> Opts,
291 raw_ostream &OS) {
292 OS << "namespace {\nenum ID : unsigned {\n OPT_INVALID = 0,\n";
293 for (const Record *R : Groups)
294 OS << " OPT_" << getOptionName(R: *R) << ",\n";
295 for (const Record *R : Opts) {
296 ConditionScope CS(OS, *R);
297 OS << " OPT_" << getStructOptionID(R: *R) << ",\n";
298 }
299 OS << "};\n} // namespace\n\n";
300}
301
302// Emits the struct an OptionsStruct def declares: its declaration under
303// OPTIONS_STRUCT_DECL, and under OPTIONS_STRUCT_DEFS the global instance, the
304// option table, and apply(), which sets the member an argument names.
305static void emitOptionsStruct(const Record &Struct,
306 ArrayRef<const Record *> Groups,
307 ArrayRef<const Record *> Opts, raw_ostream &OS) {
308 struct Member {
309 std::string Name;
310 StringRef Type, Default, Spelling;
311 };
312 std::vector<const Record *> Fields;
313 for (const Record *R : Opts) {
314 StringRef Kind = R->getValueAsDef(FieldName: "Kind")->getValueAsString(FieldName: "Name");
315 if (!R->getValue(Name: "FieldName")) {
316 if (Kind != "Input" && Kind != "Unknown" && !R->getValue(Name: "AliasTarget"))
317 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "an option of an OptionsStruct must be "
318 "declared with BoolField, ValueField or "
319 "AliasOf");
320 continue;
321 }
322 if (Kind != "FlagOrEq" && Kind != "SeparateOrEq")
323 PrintFatalError(ErrorLoc: R->getLoc(),
324 Msg: "a member is set by a FlagOrEq or SeparateOrEq");
325 StringRef Type = R->getValueAsString(FieldName: "FieldType");
326 if (Kind == "FlagOrEq" && Type != "bool" && Type != "llvm::BoolOrDefault" &&
327 !R->getValue(Name: "BareValue"))
328 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "a FlagOrEq sets a bool or has a BareValue");
329 Fields.push_back(x: R);
330 }
331 // Members in declaration order.
332 std::vector<const Record *> ByID = Fields;
333 llvm::sort(C&: ByID, Comp: [](const Record *A, const Record *B) {
334 return A->getID() < B->getID();
335 });
336 StringRef Prefix = Struct.getValueAsString(FieldName: "MemberPrefix");
337 std::vector<Member> Members;
338 StringMap<StringRef> MemberSpelling;
339 for (const Record *R : ByID) {
340 Member M{.Name: getMemberName(R: *R, Prefix), .Type: R->getValueAsString(FieldName: "FieldType"),
341 .Default: R->getValueAsString(FieldName: "FieldDefault"), .Spelling: R->getValueAsString(FieldName: "Name")};
342 auto [It, Inserted] = MemberSpelling.try_emplace(Key: M.Name, Args&: M.Spelling);
343 if (!Inserted)
344 PrintFatalError(ErrorLoc: R->getLoc(),
345 Msg: "member '" + M.Name + "' is also set by -" + It->second);
346 Members.push_back(x: M);
347 }
348
349 StringRef Name = Struct.getName();
350 OS << "\n#ifdef OPTIONS_STRUCT_DECL\n#undef OPTIONS_STRUCT_DECL\n";
351 OS << "#include \"llvm/ADT/ArrayRef.h\"\n";
352 OS << "#include \"llvm/ADT/BoolOrDefault.h\"\n";
353 OS << "#include \"llvm/ADT/StringRef.h\"\n";
354 OS << "#include \"llvm/Support/Allocator.h\"\n";
355 bool PerContext = Struct.getValueAsBit(FieldName: "PerContext");
356 if (PerContext)
357 OS << "#include \"llvm/Support/LibraryOptionsContext.h\"\n";
358 OS << "\n";
359 StringRef Namespace = Struct.getValueAsString(FieldName: "Namespace");
360 OS << "namespace llvm {\nnamespace opt {\nclass Arg;\n";
361 if (PerContext)
362 OS << "class LibraryOptionsParser;\n";
363 OS << "class OptTable;\n} // namespace opt\n} // namespace llvm\n\n";
364 OS << "namespace " << Namespace << " {\n";
365 OS << "struct " << Name << " {\n";
366 if (Namespace != "llvm")
367 OS << " using StringRef = llvm::StringRef;\n";
368 for (auto [R, M] : llvm::zip_equal(t&: ByID, u&: Members)) {
369 ConditionScope CS(OS, *R);
370 OS << " " << M.Type << " " << M.Name << "{" << M.Default << "};\n";
371 }
372 OS << "\n static constexpr bool PerContext = "
373 << (PerContext ? "true" : "false") << ";\n";
374 OS << " static const llvm::opt::OptTable &optTable();\n";
375 OS << " /// Sets the member that \\p A names, allocating a list from \\p "
376 "Alloc.\n /// Returns false if the value is invalid.\n";
377 OS << " bool apply(const llvm::opt::Arg &A, llvm::BumpPtrAllocator "
378 "&Alloc);\n";
379 if (PerContext)
380 OS << "\nprivate:\n friend class llvm::cl::LibraryOptionsContext;\n"
381 " friend class llvm::opt::LibraryOptionsParser;\n";
382 OS << "\n static " << Name << " Global;\n";
383 OS << " static const " << Name << " Default;\n";
384 OS << "};\n} // namespace " << Namespace << "\n";
385 OS << "#endif // OPTIONS_STRUCT_DECL\n";
386
387 std::string Qualified = (Namespace + "::" + Name).str();
388 OS << "\n#ifdef OPTIONS_STRUCT_DEFS\n#undef OPTIONS_STRUCT_DEFS\n";
389 OS << Qualified << " " << Qualified << "::Global;\n";
390 OS << "LLVM_REQUIRE_CONSTANT_INITIALIZATION const " << Qualified << " "
391 << Qualified << "::Default;\n\n";
392 OS << "const llvm::opt::OptTable &" << Qualified << "::optTable() {\n";
393 OS << " static const llvm::opt::LibraryOptTable T(optionTables());\n";
394 OS << " return T;\n}\n\n";
395 OS << "bool " << Qualified
396 << "::apply(const llvm::opt::Arg &A, llvm::BumpPtrAllocator &Alloc) {\n";
397 OS << " switch (A.getOption().getID()) {\n";
398 for (const Record *R : Fields) {
399 ConditionScope CS(OS, *R);
400 OS << " case OPT_" << getStructOptionID(R: *R) << ":\n";
401 std::string Member = getMemberName(R: *R, Prefix);
402 if (R->getValue(Name: "BareValue"))
403 OS << " if (!A.getNumValues()) { " << Member << " = "
404 << R->getValueAsString(FieldName: "BareValue") << "; return true; }\n";
405 if (!isa<UnsetInit>(Val: R->getValueInit(FieldName: "NormalizedValues"))) {
406 SmallVector<StringRef> Values;
407 R->getValueAsString(FieldName: "Values").split(A&: Values, Separator: ',');
408 std::vector<StringRef> Enumerators =
409 R->getValueAsListOfStrings(FieldName: "NormalizedValues");
410 if (Values.size() != Enumerators.size())
411 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "an EnumField needs one enumerator per "
412 "value");
413 // The generic lambda sets a scalar, a std::optional, or a list element.
414 OS << " return llvm::opt::parseArgValue(A.getValue(), " << Member
415 << ", Alloc, [](llvm::StringRef V, auto &X) {\n";
416 for (auto [Value, Enumerator] : llvm::zip_equal(t&: Values, u&: Enumerators))
417 OS << " if (V == \"" << Value
418 << "\") {\n X = " << Enumerator
419 << ";\n return true;\n }\n";
420 OS << " return false;\n });\n";
421 continue;
422 }
423 // A FlagOrEq without a value means =true.
424 StringRef Value =
425 R->getValueAsDef(FieldName: "Kind")->getValueAsString(FieldName: "Name") == "FlagOrEq"
426 ? "A.getNumValues() ? A.getValue() : \"true\""
427 : "A.getValue()";
428 OS << " return llvm::opt::parseArgValue(" << Value << ", " << Member
429 << ", Alloc);\n";
430 }
431 OS << " }\n llvm_unreachable(\"option without a member\");\n}\n";
432 OS << "#endif // OPTIONS_STRUCT_DEFS\n";
433}
434
435/// OptionParserEmitter - This tablegen backend takes an input .td file
436/// describing a list of options and emits a data structure for parsing and
437/// working with those options when given an input command line.
438static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {
439 // Get the option groups and options.
440 ArrayRef<const Record *> Groups =
441 Records.getAllDerivedDefinitions(ClassName: "OptionGroup");
442 std::vector<const Record *> Opts = Records.getAllDerivedDefinitions(ClassName: "Option");
443 llvm::sort(C&: Opts, Comp: IsOptionRecordsLess);
444
445 std::vector<const Record *> SubCommands =
446 Records.getAllDerivedDefinitions(ClassName: "SubCommand");
447
448 ArrayRef<const Record *> Structs =
449 Records.getAllDerivedDefinitionsIfDefined(ClassName: "OptionsStruct");
450 if (Structs.size() > 1)
451 PrintFatalError(ErrorLoc: Structs[1]->getLoc(), Msg: "only one OptionsStruct is allowed");
452
453 StringMap<const Record *> Members;
454 for (const Record *R : Opts)
455 if (R->getValue(Name: "FieldName"))
456 Members[R->getValueAsString(FieldName: "Name")] = R;
457 DenseMap<const Record *, const Record *> AliasTargets;
458 for (const Record *R : Opts) {
459 if (!R->getValue(Name: "AliasTarget"))
460 continue;
461 StringRef Target = R->getValueAsString(FieldName: "AliasTarget");
462 const Record *T = Members.lookup(Key: Target);
463 if (!T)
464 PrintFatalError(ErrorLoc: R->getLoc(),
465 Msg: "'-" + Target +
466 "' is not an option of the OptionsStruct");
467 if (!getCondition(R: *T).empty())
468 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "an alias cannot refer to an option with a "
469 "Condition");
470 AliasTargets[R] = T;
471 }
472
473 emitSourceFileHeader(Desc: "Option Parsing Definitions", OS);
474
475 // Generate prefix groups.
476 using PrefixKeyT = SmallVector<SmallString<2>, 2>;
477 using PrefixesT = std::map<PrefixKeyT, unsigned>;
478 PrefixesT Prefixes;
479 Prefixes.try_emplace(k: PrefixKeyT(), args: 0);
480 for (const Record &R : llvm::make_pointee_range(Range&: Opts)) {
481 std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings(FieldName: "Prefixes");
482 PrefixKeyT PrefixKey(RPrefixes.begin(), RPrefixes.end());
483 Prefixes.try_emplace(k: PrefixKey, args: 0);
484 }
485
486 // Generate sub command groups.
487 using SubCommandKeyT = SmallVector<StringRef, 2>;
488 using SubCommandIDsT = std::map<SubCommandKeyT, unsigned>;
489 SubCommandIDsT SubCommandIDs;
490
491 auto GetSubCommandIDsOffset = [&SubCommandIDs](const Record &R) {
492 SubCommandKeyT SubCommandKey;
493 for (const Record *SubCommand : R.getValueAsListOfDefs(FieldName: "SubCommands"))
494 SubCommandKey.push_back(Elt: SubCommand->getName());
495 return SubCommandIDs[SubCommandKey];
496 };
497
498 SubCommandIDs.try_emplace(k: SubCommandKeyT(), args: 0);
499 for (const Record &R : llvm::make_pointee_range(Range&: Opts)) {
500 std::vector<const Record *> RSubCommands =
501 R.getValueAsListOfDefs(FieldName: "SubCommands");
502 SubCommandKeyT SubCommandKey;
503 for (const auto &SubCommand : RSubCommands)
504 SubCommandKey.push_back(Elt: SubCommand->getName());
505 SubCommandIDs.try_emplace(k: SubCommandKey, args: 0);
506 }
507
508 llvm::StringToOffsetTable Table;
509 for (const auto &[PrefixSet, _] : Prefixes)
510 for (const auto &Prefix : PrefixSet)
511 Table.GetOrAddStringOffset(Str: Prefix);
512 for (const Record &R : llvm::make_pointee_range(Range&: Groups)) {
513 Table.GetOrAddStringOffset(Str: R.getValueAsString(FieldName: "Name"));
514 Table.GetOrAddStringOffset(Str: getHelpText(R));
515 }
516 for (const Record &R : llvm::make_pointee_range(Range&: Opts)) {
517 Table.GetOrAddStringOffset(Str: getOptionPrefixedName(R));
518 Table.GetOrAddStringOffset(Str: getHelpText(R));
519 Table.GetOrAddStringOffset(Str: getOptionalString(R, Field: "MetaVarName"));
520 Table.GetOrAddStringOffset(Str: getOptionalString(R, Field: "Values"));
521 Table.GetOrAddStringOffset(Str: getAliasArgsBlob(R));
522 for (const Record *V : R.getValueAsListOfDefs(FieldName: "HelpTextsForVariants"))
523 Table.GetOrAddStringOffset(Str: V->getValueAsString(FieldName: "Text"));
524 }
525
526 // Flags and Visibility name enumerators of the including tool. An option
527 // inherits its group's. Names are sorted so that equal masks share an
528 // InfoExtra row.
529 auto GetMask = [](const Record &R, StringRef Field) {
530 std::set<StringRef> Names;
531 for (const Init *I : *R.getValueAsListInit(FieldName: Field))
532 Names.insert(x: cast<DefInit>(Val: I)->getDef()->getName());
533 if (const DefInit *DI = dyn_cast<DefInit>(Val: R.getValueInit(FieldName: "Group")))
534 for (const Init *I : *DI->getDef()->getValueAsListInit(FieldName: Field))
535 Names.insert(x: cast<DefInit>(Val: I)->getDef()->getName());
536 std::string Mask;
537 raw_string_ostream MaskOS(Mask);
538 ListSeparator Sep(" | ");
539 for (StringRef Name : Names)
540 MaskOS << Sep << "static_cast<unsigned>(" << Name << ")";
541 return Mask.empty() ? std::string("0") : Mask;
542 };
543
544 // IDs are 1-based positions in the table, which lists groups first.
545 DenseMap<const Record *, unsigned> OptionID;
546 for (const Record &R : llvm::make_pointee_range(Range&: Groups))
547 OptionID.try_emplace(Key: &R, Args: OptionID.size() + 1);
548 for (const Record &R : llvm::make_pointee_range(Range&: Opts))
549 OptionID.try_emplace(Key: &R, Args: OptionID.size() + 1);
550 // An OptionsStruct's rows name the IDs, since a false Condition omits a row
551 // and shifts the IDs after it.
552 auto GetRefID = [&](const Record &R, StringRef Field) -> std::string {
553 const Record *Ref = Field == "Alias" ? AliasTargets.lookup(Val: &R) : nullptr;
554 if (const auto *DI = dyn_cast<DefInit>(Val: R.getValueInit(FieldName: Field)))
555 Ref = DI->getDef();
556 if (!Ref)
557 return "0";
558 if (Structs.empty())
559 return utostr(X: OptionID.lookup(Val: Ref));
560 return "OPT_" + getStructOptionID(R: *Ref);
561 };
562
563 OS << "/////////\n";
564 OS << "// Tables\n\n";
565 // An OptionsStruct's definitions use the tables.
566 OS << (Structs.empty()
567 ? "#ifdef OPTTABLE_CODE\n"
568 : "#if defined(OPTTABLE_CODE) || defined(OPTIONS_STRUCT_DEFS)\n");
569 if (!Structs.empty())
570 emitStructOptionIDs(Groups, Opts, OS);
571 // A function rather than an object: the object needs dynamic relocations.
572 OS << "static llvm::opt::OptTable::Tables optionTables() {\n";
573 // An OptionsStruct's .cpp has no using-directive for llvm::opt.
574 if (!Structs.empty())
575 OS << " using llvm::opt::DefaultVis, llvm::opt::HelpHidden,\n"
576 " llvm::opt::RenderAsInput, llvm::opt::RenderJoined,\n"
577 " llvm::opt::RenderSeparate;\n";
578 Table.EmitStringTableDef(OS, Name: "OptionStrTable");
579 OS << "\n";
580
581 // Dump prefixes.
582 OS << " static constexpr llvm::StringTable::Offset OptionPrefixesTable[] = "
583 "{\n";
584 {
585 // Ensure the first prefix set is always empty.
586 assert(!Prefixes.empty() &&
587 "We should always emit an empty set of prefixes");
588 assert(Prefixes.begin()->first.empty() &&
589 "First prefix set should always be empty");
590 llvm::ListSeparator Sep(",\n");
591 unsigned CurIndex = 0;
592 for (auto &[Prefix, PrefixIndex] : Prefixes) {
593 // First emit the number of prefix strings in this list of prefixes.
594 OS << Sep << " " << Prefix.size() << " /* prefixes */";
595 PrefixIndex = CurIndex;
596 if (PrefixIndex > 255)
597 PrintFatalError(Msg: "too many distinct prefix sets");
598 assert((CurIndex == 0 || !Prefix.empty()) &&
599 "Only first prefix set should be empty!");
600 for (const auto &PrefixKey : Prefix)
601 OS << ", " << *Table.GetStringOffset(Str: PrefixKey) << " /* '" << PrefixKey
602 << "' */";
603 CurIndex += Prefix.size() + 1;
604 }
605 }
606 OS << "\n };\n\n";
607
608 // Dump help text variants. Each option's variants form a run ended by a zero
609 // row; offset 0 is the empty run.
610 OS << " static constexpr llvm::opt::OptTable::HelpTextVariant "
611 "OptionHelpTextVariantsTable[] = {\n";
612 DenseMap<const Record *, unsigned> HelpTextVariantsOffset;
613 unsigned NumVariantRows = 1;
614 OS << " {0, 0},\n";
615 for (const Record &R : llvm::make_pointee_range(Range&: Opts)) {
616 std::vector<const Record *> Variants =
617 R.getValueAsListOfDefs(FieldName: "HelpTextsForVariants");
618 if (Variants.empty())
619 continue;
620 HelpTextVariantsOffset[&R] = NumVariantRows;
621 NumVariantRows += Variants.size() + 1;
622 for (const Record *V : Variants) {
623 const ListInit *Vis = V->getValueAsListInit(FieldName: "Visibilities");
624 if (Vis->empty())
625 PrintFatalError(ErrorLoc: V->getLoc(), Msg: "HelpTextVariant needs a visibility");
626 OS << " {";
627 ListSeparator Sep(" | ");
628 for (const Init *I : *Vis)
629 OS << Sep << I->getAsUnquotedString();
630 OS << ", ";
631 writeStrTableOffset(OS, Table, Str: V->getValueAsString(FieldName: "Text"));
632 OS << "},\n";
633 }
634 OS << " {0, 0},\n";
635 }
636 OS << " };\n\n";
637
638 // Dump subcommands.
639 if (!SubCommands.empty()) {
640 OS << " static constexpr llvm::opt::OptTable::SubCommand "
641 "OptionSubCommands[] = {\n";
642 for (const Record *SubCommand : SubCommands) {
643 OS << " { \"" << SubCommand->getValueAsString(FieldName: "Name") << "\", ";
644 OS << "\"" << SubCommand->getValueAsString(FieldName: "HelpText") << "\", ";
645 OS << "\"" << SubCommand->getValueAsString(FieldName: "Usage") << "\" },\n";
646 }
647 OS << " };\n\n";
648 }
649
650 // Dump subcommand IDs.
651 OS << " static constexpr unsigned OptionSubCommandIDsTable[] = {\n";
652 {
653 // Ensure the first subcommand set is always empty.
654 assert(!SubCommandIDs.empty() &&
655 "We should always emit an empty set of subcommands");
656 assert(SubCommandIDs.begin()->first.empty() &&
657 "First subcommand set should always be empty");
658 llvm::ListSeparator Sep(",\n");
659 unsigned CurIndex = 0;
660 for (auto &[SubCommand, SubCommandIndex] : SubCommandIDs) {
661 // First emit the number of subcommand strings in this list of
662 // subcommands.
663 OS << Sep << " " << SubCommand.size() << " /* subcommands */";
664 SubCommandIndex = CurIndex;
665 assert((CurIndex == 0 || !SubCommand.empty()) &&
666 "Only first subcommand set should be empty!");
667 for (const auto &SubCommandKey : SubCommand) {
668 auto It = llvm::find_if(Range&: SubCommands, P: [&](const Record *R) {
669 return R->getName() == SubCommandKey;
670 });
671 assert(It != SubCommands.end() && "SubCommand not found");
672 OS << ", " << std::distance(first: SubCommands.begin(), last: It) << " /* '"
673 << SubCommandKey << "' */";
674 }
675 CurIndex += SubCommand.size() + 1;
676 }
677 }
678 OS << "\n };\n\n";
679
680 // Fields that are rarely set or take few distinct values, in
681 // OptTable::InfoExtra order. Options with equal values share a row; row 0 is
682 // all zero.
683 OS << " static constexpr llvm::opt::OptTable::InfoExtra "
684 "OptionInfoExtrasTable[] = {\n {0, 0, 0, 0, 0, 0, 0, 0},\n";
685 std::map<std::array<std::string, 8>, unsigned> ExtraRows;
686 ExtraRows.try_emplace(k: {"0", "0", "0", "0", "0", "0", "0", "0"}, args: 0);
687 DenseMap<const Record *, unsigned> ExtraOffset;
688 for (const Record &R : llvm::make_pointee_range(Range&: Opts)) {
689 int64_t NumArgs = R.getValueAsInt(FieldName: "NumArgs");
690 if (NumArgs < 0 || NumArgs > 255)
691 PrintFatalError(ErrorLoc: R.getLoc(), Msg: "NumArgs must be in [0, 255]");
692 std::array<std::string, 8> Row = {
693 utostr(X: *Table.GetStringOffset(Str: getOptionalString(R, Field: "MetaVarName"))),
694 utostr(X: *Table.GetStringOffset(Str: getAliasArgsBlob(R))),
695 utostr(X: *Table.GetStringOffset(Str: getOptionalString(R, Field: "Values"))),
696 GetMask(R, "Flags"),
697 GetMask(R, "Visibility"),
698 utostr(X: HelpTextVariantsOffset.lookup(Val: &R)),
699 utostr(X: GetSubCommandIDsOffset(R)),
700 utostr(X: NumArgs)};
701 auto [It, Inserted] = ExtraRows.try_emplace(k: Row, args: ExtraRows.size());
702 if (Inserted) {
703 OS << " {";
704 interleaveComma(c: Row, os&: OS);
705 OS << "},\n";
706 }
707 ExtraOffset[&R] = It->second;
708 }
709 OS << " };\n\n";
710
711 // Dump the option table in OptTable::Info field order.
712 OS << " static constexpr llvm::opt::OptTable::Info OptionInfoTable[] = {\n";
713 for (const Record &R : llvm::make_pointee_range(Range&: Groups)) {
714 OS << " {";
715 writeStrTableOffset(OS, Table, Str: R.getValueAsString(FieldName: "Name"),
716 /*EmitComment=*/true);
717 OS << ", ";
718 writeStrTableOffset(OS, Table, Str: getHelpText(R));
719 OS << ", " << GetRefID(R, "Group")
720 << ", 0, 0, 0, llvm::opt::Option::GroupClass},\n";
721 }
722 for (const Record &R : llvm::make_pointee_range(Range&: Opts)) {
723 ConditionScope CS(OS, R);
724 OS << " {";
725 writeStrTableOffset(OS, Table, Str: getOptionPrefixedName(R),
726 /*EmitComment=*/true);
727 OS << ", ";
728 writeStrTableOffset(OS, Table, Str: getHelpText(R));
729 OS << ", " << GetRefID(R, "Group") << ", " << GetRefID(R, "Alias");
730 OS << ", " << ExtraOffset.lookup(Val: &R);
731 std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings(FieldName: "Prefixes");
732 OS << ", " << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())];
733 // An AliasOf without AliasArgs takes its target's kind.
734 const Record *KindR = AliasTargets.lookup(Val: &R);
735 if (!KindR || !R.getValueAsListOfStrings(FieldName: "AliasArgs").empty())
736 KindR = &R;
737 OS << ", llvm::opt::Option::"
738 << KindR->getValueAsDef(FieldName: "Kind")->getValueAsString(FieldName: "Name") << "Class},\n";
739 }
740 OS << " };\n\n";
741
742 OS << " return {OptionStrTable, OptionPrefixesTable,\n";
743 OS << " OptionInfoTable, OptionInfoExtrasTable, "
744 "OptionHelpTextVariantsTable, "
745 << (SubCommands.empty() ? "{}" : "OptionSubCommands")
746 << ", OptionSubCommandIDsTable};\n";
747 OS << "}\n";
748 OS << "#undef OPTTABLE_CODE\n";
749 OS << (Structs.empty()
750 ? "#endif // OPTTABLE_CODE\n\n"
751 : "#endif // OPTTABLE_CODE || OPTIONS_STRUCT_DEFS\n\n");
752
753 if (!Structs.empty())
754 emitOptionsStruct(Struct: *Structs[0], Groups, Opts, OS);
755
756 // Dump ValuesCode.
757 OS << "/////////\n";
758 OS << "// ValuesCode\n\n";
759 OS << "#ifdef OPTTABLE_VALUES_CODE\n";
760 std::vector<const Record *> ValuesCodeOpts;
761 for (const Record &R : llvm::make_pointee_range(Range&: Opts)) {
762 // The option values, if any;
763 if (!isa<UnsetInit>(Val: R.getValueInit(FieldName: "ValuesCode"))) {
764 if (!isa<UnsetInit>(Val: R.getValueInit(FieldName: "Values")))
765 PrintFatalError(ErrorLoc: R.getLoc(), Msg: "cannot set both Values and ValuesCode");
766 ValuesCodeOpts.push_back(x: &R);
767 OS << "#define VALUES_CODE " << getOptionName(R) << "_Values\n";
768 OS << R.getValueAsString(FieldName: "ValuesCode") << "\n";
769 OS << "#undef VALUES_CODE\n";
770 }
771 }
772 // A function keeps these strings out of a relocated table. It names OPT_ IDs,
773 // so include this block after the option enum; a table that uses a different
774 // ID prefix cannot use ValuesCode.
775 OS << "static llvm::StringRef getOptionValuesCode(unsigned ID) {\n";
776 OS << " switch (ID) {\n";
777 for (const Record *R : ValuesCodeOpts)
778 OS << " case OPT_" << getOptionName(R: *R) << ": return " << getOptionName(R: *R)
779 << "_Values;\n";
780 OS << " }\n return {};\n}\n";
781 OS << "#undef OPTTABLE_VALUES_CODE\n";
782 OS << "#endif // OPTTABLE_VALUES_CODE\n";
783
784 OS << "/////////\n";
785 OS << "// Groups\n\n";
786 OS << "#ifdef OPTION\n";
787 for (const Record &R : llvm::make_pointee_range(Range&: Groups)) {
788 // Start a single option entry.
789 OS << "OPTION(";
790
791 // A zero prefix offset corresponds to an empty set of prefixes.
792 OS << "0 /* no prefixes */";
793
794 // The option string offset.
795 OS << ", ";
796 writeStrTableOffset(OS, Table, Str: R.getValueAsString(FieldName: "Name"),
797 /*EmitComment=*/true);
798
799 // The option identifier name.
800 OS << ", " << getOptionName(R);
801
802 // The option kind.
803 OS << ", Group";
804
805 // The containing option group (if any).
806 OS << ", ";
807 if (const DefInit *DI = dyn_cast<DefInit>(Val: R.getValueInit(FieldName: "Group")))
808 OS << getOptionName(R: *DI->getDef());
809 else
810 OS << "INVALID";
811
812 // The other option arguments (unused for groups).
813 OS << ", INVALID, 0, 0, 0, 0";
814
815 // The option help text.
816 OS << ", ";
817 writeStrTableOffset(OS, Table, Str: getHelpText(R));
818
819 // Groups have no help text variants.
820 OS << ", 0";
821
822 // The option meta-variable name (unused).
823 OS << ", 0";
824
825 // The option Values and SubCommandIDsOffset (unused for groups).
826 OS << ", 0, 0)\n";
827 }
828 OS << "\n";
829
830 OS << "//////////\n";
831 OS << "// Options\n\n";
832
833 auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
834 // The option prefix;
835 std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings(FieldName: "Prefixes");
836 OS << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())] << ", ";
837
838 // The option prefixed name.
839 writeStrTableOffset(OS, Table, Str: getOptionPrefixedName(R),
840 /*EmitComment=*/true);
841
842 // The option identifier name.
843 OS << ", " << getOptionName(R);
844
845 // The option kind.
846 OS << ", " << R.getValueAsDef(FieldName: "Kind")->getValueAsString(FieldName: "Name");
847
848 // The containing option group (if any).
849 OS << ", ";
850 if (const DefInit *DI = dyn_cast<DefInit>(Val: R.getValueInit(FieldName: "Group")))
851 OS << getOptionName(R: *DI->getDef());
852 else
853 OS << "INVALID";
854
855 // The option alias (if any).
856 OS << ", ";
857 if (const DefInit *DI = dyn_cast<DefInit>(Val: R.getValueInit(FieldName: "Alias")))
858 OS << getOptionName(R: *DI->getDef());
859 else
860 OS << "INVALID";
861
862 // The option alias arguments (if any).
863 OS << ", ";
864 writeStrTableOffset(OS, Table, Str: getAliasArgsBlob(R));
865
866 // "Flags" for the option, such as HelpHidden and Render*
867 OS << ", " << GetMask(R, "Flags");
868
869 // Option visibility, for sharing options between drivers.
870 OS << ", " << GetMask(R, "Visibility");
871
872 // The option parameter field.
873 OS << ", " << R.getValueAsInt(FieldName: "NumArgs");
874
875 // The option help text.
876 OS << ", ";
877 writeStrTableOffset(OS, Table, Str: getHelpText(R));
878
879 // The option help text variants.
880 OS << ", " << HelpTextVariantsOffset.lookup(Val: &R);
881
882 // The option meta-variable name.
883 OS << ", ";
884 writeStrTableOffset(OS, Table, Str: getOptionalString(R, Field: "MetaVarName"));
885
886 // The option Values. Used for shell autocompletion.
887 OS << ", ";
888 writeStrTableOffset(OS, Table, Str: getOptionalString(R, Field: "Values"));
889
890 // The option SubCommandIDsOffset.
891 OS << ", " << GetSubCommandIDsOffset(R);
892 };
893
894 auto IsMarshallingOption = [](const Record &R) {
895 return !isa<UnsetInit>(Val: R.getValueInit(FieldName: "KeyPath")) &&
896 !R.getValueAsString(FieldName: "KeyPath").empty();
897 };
898
899 std::vector<const Record *> OptsWithMarshalling;
900 for (const Record &R : llvm::make_pointee_range(Range&: Opts)) {
901 ConditionScope CS(OS, R);
902 // Start a single option entry.
903 OS << "OPTION(";
904 WriteOptRecordFields(OS, R);
905 OS << ")\n";
906 if (IsMarshallingOption(R))
907 OptsWithMarshalling.push_back(x: &R);
908 }
909 OS << "#endif // OPTION\n";
910
911 auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) {
912 unsigned AID = (*A)->getID();
913 unsigned BID = (*B)->getID();
914
915 if (AID < BID)
916 return -1;
917 if (AID > BID)
918 return 1;
919 return 0;
920 };
921 // The RecordKeeper stores records (options) in lexicographical order, and we
922 // have reordered the options again when generating prefix groups. We need to
923 // restore the original definition order of options with marshalling to honor
924 // the topology of the dependency graph implied by `DefaultAnyOf`.
925 array_pod_sort(Start: OptsWithMarshalling.begin(), End: OptsWithMarshalling.end(),
926 Compare: CmpMarshallingOpts);
927
928 std::vector<MarshallingInfo> MarshallingInfos;
929 MarshallingInfos.reserve(n: OptsWithMarshalling.size());
930 for (const auto *R : OptsWithMarshalling)
931 MarshallingInfos.push_back(x: createMarshallingInfo(R: *R));
932
933 for (const auto &MI : MarshallingInfos) {
934 OS << "#ifdef " << MI.getMacroName() << "\n";
935 OS << MI.getMacroName() << "(";
936 WriteOptRecordFields(OS, MI.R);
937 OS << ", ";
938 MI.emit(OS);
939 OS << ")\n";
940 OS << "#endif // " << MI.getMacroName() << "\n";
941 }
942
943 OS << "\n";
944 OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
945 OS << "\n";
946 OS << MarshallingInfo::ValueTablePreamble;
947 std::vector<StringRef> ValueTableNames;
948 for (const auto &MI : MarshallingInfos)
949 if (auto MaybeValueTableName = MI.emitValueTable(OS))
950 ValueTableNames.push_back(x: *MaybeValueTableName);
951
952 OS << MarshallingInfo::ValueTablesDecl << "{";
953 for (auto ValueTableName : ValueTableNames)
954 OS << "{" << ValueTableName << ", std::size(" << ValueTableName << ")},\n";
955 OS << "};\n";
956 OS << "static const unsigned SimpleEnumValueTablesSize = "
957 "std::size(SimpleEnumValueTables);\n";
958
959 OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
960}
961
962static TableGen::Emitter::Opt X("gen-opt-parser-defs", emitOptionParser,
963 "Generate option definitions");
964