blob: 6e49e248e4b81b72628993da8e16a7b79fbb3fff [file] [log] [blame]
Michael J. Spencer41ee0412012-12-05 00:29:32 +00001//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Michael J. Spencer41ee0412012-12-05 00:29:32 +00006//
7//===----------------------------------------------------------------------===//
8
Jonas Devlieghere64ada7a2019-11-22 14:07:21 -08009#include "OptEmitter.h"
Michael J. Spencer41ee0412012-12-05 00:29:32 +000010#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/SmallString.h"
12#include "llvm/ADT/Twine.h"
Daniel Grumberg29125dd2020-05-11 11:42:38 +010013#include "llvm/Support/raw_ostream.h"
Chandler Carruthb034cb72013-01-02 10:26:28 +000014#include "llvm/TableGen/Record.h"
15#include "llvm/TableGen/TableGenBackend.h"
Rui Ueyama8fb5a912013-08-28 20:04:31 +000016#include <cctype>
Chandler Carruth442f7842014-03-04 10:07:28 +000017#include <cstring>
Michael J. Spencer41ee0412012-12-05 00:29:32 +000018#include <map>
Daniel Grumberg29125dd2020-05-11 11:42:38 +010019#include <memory>
Michael J. Spencer41ee0412012-12-05 00:29:32 +000020
21using namespace llvm;
22
Michael J. Spencer41ee0412012-12-05 00:29:32 +000023static const std::string getOptionName(const Record &R) {
24 // Use the record name unless EnumName is defined.
25 if (isa<UnsetInit>(R.getValueInit("EnumName")))
Benjamin Krameradcd0262020-01-28 20:23:46 +010026 return std::string(R.getName());
Michael J. Spencer41ee0412012-12-05 00:29:32 +000027
Benjamin Krameradcd0262020-01-28 20:23:46 +010028 return std::string(R.getValueAsString("EnumName"));
Michael J. Spencer41ee0412012-12-05 00:29:32 +000029}
30
31static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
32 OS << '"';
33 OS.write_escaped(Str);
34 OS << '"';
35 return OS;
36}
37
Daniel Grumberg29125dd2020-05-11 11:42:38 +010038static const std::string getOptionSpelling(const Record &R,
39 size_t &PrefixLength) {
40 std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes");
41 StringRef Name = R.getValueAsString("Name");
42 if (Prefixes.empty()) {
43 PrefixLength = 0;
44 return Name.str();
45 }
46 PrefixLength = Prefixes[0].size();
47 return (Twine(Prefixes[0]) + Twine(Name)).str();
48}
49
50static const std::string getOptionSpelling(const Record &R) {
51 size_t PrefixLength;
52 return getOptionSpelling(R, PrefixLength);
53}
54
55static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
56 size_t PrefixLength;
57 OS << "&";
58 write_cstring(OS, StringRef(getOptionSpelling(R, PrefixLength)));
59 OS << "[" << PrefixLength << "]";
60}
61
62class MarshallingKindInfo {
63public:
64 const Record &R;
65 const char *MacroName;
66 bool ShouldAlwaysEmit;
67 StringRef KeyPath;
68 StringRef DefaultValue;
69 StringRef NormalizedValuesScope;
70
71 void emit(raw_ostream &OS) const {
72 write_cstring(OS, StringRef(getOptionSpelling(R)));
73 OS << ", ";
74 OS << ShouldAlwaysEmit;
75 OS << ", ";
76 OS << KeyPath;
77 OS << ", ";
78 emitScopedNormalizedValue(OS, DefaultValue);
79 OS << ", ";
80 emitSpecific(OS);
81 }
82
83 virtual Optional<StringRef> emitValueTable(raw_ostream &OS) const {
84 return None;
85 }
86
87 virtual ~MarshallingKindInfo() = default;
88
89 static std::unique_ptr<MarshallingKindInfo> create(const Record &R);
90
91protected:
92 void emitScopedNormalizedValue(raw_ostream &OS,
93 StringRef NormalizedValue) const {
94 if (!NormalizedValuesScope.empty())
95 OS << NormalizedValuesScope << "::";
96 OS << NormalizedValue;
97 }
98
99 virtual void emitSpecific(raw_ostream &OS) const = 0;
100 MarshallingKindInfo(const Record &R, const char *MacroName)
101 : R(R), MacroName(MacroName) {}
102};
103
104class MarshallingFlagInfo final : public MarshallingKindInfo {
105public:
106 bool IsPositive;
107
108 void emitSpecific(raw_ostream &OS) const override { OS << IsPositive; }
109
110 static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
111 std::unique_ptr<MarshallingFlagInfo> Ret(new MarshallingFlagInfo(R));
112 Ret->IsPositive = R.getValueAsBit("IsPositive");
Michael Spencer7fcc1bb2020-07-17 16:12:18 -0600113 // FIXME: This is a workaround for a bug in older versions of clang (< 3.9)
114 // The constructor that is supposed to allow for Derived to Base
115 // conversion does not work. Remove this if we drop support for such
116 // configurations.
Michael Spencerfda901a2020-07-17 13:32:12 -0600117 return std::unique_ptr<MarshallingKindInfo>(Ret.release());
Daniel Grumberg29125dd2020-05-11 11:42:38 +0100118 }
119
120private:
121 MarshallingFlagInfo(const Record &R)
122 : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {}
123};
124
125class MarshallingStringInfo final : public MarshallingKindInfo {
126public:
127 StringRef NormalizerRetTy;
128 StringRef Normalizer;
129 StringRef Denormalizer;
130 int TableIndex = -1;
131 std::vector<StringRef> Values;
132 std::vector<StringRef> NormalizedValues;
133 std::string ValueTableName;
134
135 static constexpr const char *ValueTablePreamble = R"(
136struct SimpleEnumValue {
137 const char *Name;
138 unsigned Value;
139};
140
141struct SimpleEnumValueTable {
142 const SimpleEnumValue *Table;
143 unsigned Size;
144};
145)";
146
147 static constexpr const char *ValueTablesDecl =
148 "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
149
150 void emitSpecific(raw_ostream &OS) const override {
151 emitScopedNormalizedValue(OS, NormalizerRetTy);
152 OS << ", ";
153 OS << Normalizer;
154 OS << ", ";
155 OS << Denormalizer;
156 OS << ", ";
157 OS << TableIndex;
158 }
159
160 Optional<StringRef> emitValueTable(raw_ostream &OS) const override {
161 if (TableIndex == -1)
162 return {};
163 OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
164 for (unsigned I = 0, E = Values.size(); I != E; ++I) {
165 OS << "{";
166 write_cstring(OS, Values[I]);
167 OS << ",";
168 OS << "static_cast<unsigned>(";
169 emitScopedNormalizedValue(OS, NormalizedValues[I]);
170 OS << ")},";
171 }
172 OS << "};\n";
173 return StringRef(ValueTableName);
174 }
175
176 static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
177 assert(!isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) &&
178 "String options must have a type");
179
180 std::unique_ptr<MarshallingStringInfo> Ret(new MarshallingStringInfo(R));
181 Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy");
182
183 Ret->Normalizer = R.getValueAsString("Normalizer");
184 Ret->Denormalizer = R.getValueAsString("Denormalizer");
185
186 if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
187 assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
188 "Cannot provide normalized values for value-less options");
189 Ret->TableIndex = NextTableIndex++;
190 Ret->NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
191 Ret->Values.reserve(Ret->NormalizedValues.size());
192 Ret->ValueTableName = getOptionName(R) + "ValueTable";
193
194 StringRef ValuesStr = R.getValueAsString("Values");
195 for (;;) {
196 size_t Idx = ValuesStr.find(',');
197 if (Idx == StringRef::npos)
198 break;
199 if (Idx > 0)
200 Ret->Values.push_back(ValuesStr.slice(0, Idx));
201 ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
202 }
203 if (!ValuesStr.empty())
204 Ret->Values.push_back(ValuesStr);
205
206 assert(Ret->Values.size() == Ret->NormalizedValues.size() &&
207 "The number of normalized values doesn't match the number of "
208 "values");
209 }
210
Michael Spencer7fcc1bb2020-07-17 16:12:18 -0600211 // FIXME: This is a workaround for a bug in older versions of clang (< 3.9)
212 // The constructor that is supposed to allow for Derived to Base
213 // conversion does not work. Remove this if we drop support for such
214 // configurations.
Michael Spencerfda901a2020-07-17 13:32:12 -0600215 return std::unique_ptr<MarshallingKindInfo>(Ret.release());
Daniel Grumberg29125dd2020-05-11 11:42:38 +0100216 }
217
218private:
219 MarshallingStringInfo(const Record &R)
220 : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {}
221
222 static size_t NextTableIndex;
223};
224
225size_t MarshallingStringInfo::NextTableIndex = 0;
226
227std::unique_ptr<MarshallingKindInfo>
228MarshallingKindInfo::create(const Record &R) {
229 assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
230 !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
231 "Must provide at least a key-path and a default value for emitting "
232 "marshalling information");
233
234 std::unique_ptr<MarshallingKindInfo> Ret = nullptr;
235 StringRef MarshallingKindStr = R.getValueAsString("MarshallingKind");
236
237 if (MarshallingKindStr == "flag")
238 Ret = MarshallingFlagInfo::create(R);
239 else if (MarshallingKindStr == "string")
240 Ret = MarshallingStringInfo::create(R);
241
242 Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
243 Ret->KeyPath = R.getValueAsString("KeyPath");
244 Ret->DefaultValue = R.getValueAsString("DefaultValue");
245 if (!isa<UnsetInit>(R.getValueInit("NormalizedValuesScope")))
246 Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
247 return Ret;
248}
249
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000250/// OptParserEmitter - This tablegen backend takes an input .td file
251/// describing a list of options and emits a data structure for parsing and
252/// working with those options when given an input command line.
253namespace llvm {
254void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
255 // Get the option groups and options.
256 const std::vector<Record*> &Groups =
257 Records.getAllDerivedDefinitions("OptionGroup");
258 std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
259
260 emitSourceFileHeader("Option Parsing Definitions", OS);
261
262 array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
263 // Generate prefix groups.
264 typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
265 typedef std::map<PrefixKeyT, std::string> PrefixesT;
266 PrefixesT Prefixes;
267 Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
268 unsigned CurPrefix = 0;
269 for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
270 const Record &R = *Opts[i];
Craig Topper2b8419a2017-05-31 19:01:11 +0000271 std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000272 PrefixKeyT prfkey(prf.begin(), prf.end());
273 unsigned NewPrefix = CurPrefix + 1;
274 if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
275 Twine(NewPrefix)).str())).second)
276 CurPrefix = NewPrefix;
277 }
278
279 // Dump prefixes.
280
281 OS << "/////////\n";
282 OS << "// Prefixes\n\n";
283 OS << "#ifdef PREFIX\n";
284 OS << "#define COMMA ,\n";
285 for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
286 I != E; ++I) {
287 OS << "PREFIX(";
288
289 // Prefix name.
290 OS << I->second;
291
292 // Prefix values.
293 OS << ", {";
294 for (PrefixKeyT::const_iterator PI = I->first.begin(),
295 PE = I->first.end(); PI != PE; ++PI) {
296 OS << "\"" << *PI << "\" COMMA ";
297 }
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000298 OS << "nullptr})\n";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000299 }
300 OS << "#undef COMMA\n";
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000301 OS << "#endif // PREFIX\n\n";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000302
303 OS << "/////////\n";
304 OS << "// Groups\n\n";
305 OS << "#ifdef OPTION\n";
306 for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
307 const Record &R = *Groups[i];
308
309 // Start a single option entry.
Hans Wennborg8669b972013-07-31 23:28:51 +0000310 OS << "OPTION(";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000311
312 // The option prefix;
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000313 OS << "nullptr";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000314
315 // The option string.
316 OS << ", \"" << R.getValueAsString("Name") << '"';
317
318 // The option identifier name.
Daniel Grumberg558db272020-05-15 11:26:07 -0700319 OS << ", " << getOptionName(R);
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000320
321 // The option kind.
322 OS << ", Group";
323
324 // The containing option group (if any).
325 OS << ", ";
326 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
327 OS << getOptionName(*DI->getDef());
328 else
329 OS << "INVALID";
330
331 // The other option arguments (unused for groups).
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000332 OS << ", INVALID, nullptr, 0, 0";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000333
334 // The option help text.
335 if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
336 OS << ",\n";
337 OS << " ";
338 write_cstring(OS, R.getValueAsString("HelpText"));
339 } else
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000340 OS << ", nullptr";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000341
342 // The option meta-variable name (unused).
Yuka Takahashiba5d4af2017-06-20 16:31:31 +0000343 OS << ", nullptr";
344
345 // The option Values (unused for groups).
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000346 OS << ", nullptr)\n";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000347 }
348 OS << "\n";
349
350 OS << "//////////\n";
351 OS << "// Options\n\n";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000352
Daniel Grumberg29125dd2020-05-11 11:42:38 +0100353 auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000354 // The option prefix;
Craig Topper2b8419a2017-05-31 19:01:11 +0000355 std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000356 OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
357
358 // The option string.
Daniel Grumberg29125dd2020-05-11 11:42:38 +0100359 emitNameUsingSpelling(OS, R);
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000360
361 // The option identifier name.
Daniel Grumberg558db272020-05-15 11:26:07 -0700362 OS << ", " << getOptionName(R);
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000363
364 // The option kind.
365 OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
366
367 // The containing option group (if any).
368 OS << ", ";
Reid Kleckner9ef63b22014-07-12 00:18:58 +0000369 const ListInit *GroupFlags = nullptr;
370 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
371 GroupFlags = DI->getDef()->getValueAsListInit("Flags");
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000372 OS << getOptionName(*DI->getDef());
Reid Kleckner9ef63b22014-07-12 00:18:58 +0000373 } else
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000374 OS << "INVALID";
375
376 // The option alias (if any).
377 OS << ", ";
378 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
379 OS << getOptionName(*DI->getDef());
380 else
381 OS << "INVALID";
382
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000383 // The option alias arguments (if any).
384 // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
385 // would become "foo\0bar\0". Note that the compiler adds an implicit
386 // terminating \0 at the end.
387 OS << ", ";
Craig Topper2b8419a2017-05-31 19:01:11 +0000388 std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000389 if (AliasArgs.size() == 0) {
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000390 OS << "nullptr";
Hans Wennborg5fdcf862013-07-31 22:44:41 +0000391 } else {
392 OS << "\"";
393 for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
394 OS << AliasArgs[i] << "\\0";
395 OS << "\"";
396 }
397
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000398 // The option flags.
Reid Kleckner9ef63b22014-07-12 00:18:58 +0000399 OS << ", ";
400 int NumFlags = 0;
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000401 const ListInit *LI = R.getValueAsListInit("Flags");
Reid Kleckner9ef63b22014-07-12 00:18:58 +0000402 for (Init *I : *LI)
Daniel Grumbergff0eec42020-06-05 10:46:38 +0100403 OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
Reid Kleckner9ef63b22014-07-12 00:18:58 +0000404 if (GroupFlags) {
405 for (Init *I : *GroupFlags)
406 OS << (NumFlags++ ? " | " : "")
407 << cast<DefInit>(I)->getDef()->getName();
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000408 }
Reid Kleckner9ef63b22014-07-12 00:18:58 +0000409 if (NumFlags == 0)
410 OS << '0';
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000411
412 // The option parameter field.
413 OS << ", " << R.getValueAsInt("NumArgs");
414
415 // The option help text.
416 if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
417 OS << ",\n";
418 OS << " ";
419 write_cstring(OS, R.getValueAsString("HelpText"));
420 } else
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000421 OS << ", nullptr";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000422
423 // The option meta-variable name.
424 OS << ", ";
425 if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
426 write_cstring(OS, R.getValueAsString("MetaVarName"));
427 else
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000428 OS << "nullptr";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000429
Yuka Takahashiba5d4af2017-06-20 16:31:31 +0000430 // The option Values. Used for shell autocompletion.
431 OS << ", ";
432 if (!isa<UnsetInit>(R.getValueInit("Values")))
433 write_cstring(OS, R.getValueAsString("Values"));
434 else
435 OS << "nullptr";
Daniel Grumberg29125dd2020-05-11 11:42:38 +0100436 };
Yuka Takahashiba5d4af2017-06-20 16:31:31 +0000437
Daniel Grumberg29125dd2020-05-11 11:42:38 +0100438 std::vector<std::unique_ptr<MarshallingKindInfo>> OptsWithMarshalling;
439 for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
440 const Record &R = *Opts[I];
441
442 // Start a single option entry.
443 OS << "OPTION(";
444 WriteOptRecordFields(OS, R);
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000445 OS << ")\n";
Daniel Grumberg29125dd2020-05-11 11:42:38 +0100446 if (!isa<UnsetInit>(R.getValueInit("MarshallingKind")))
447 OptsWithMarshalling.push_back(MarshallingKindInfo::create(R));
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000448 }
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000449 OS << "#endif // OPTION\n";
Yuka Takahashi24bc6a42017-08-29 00:09:31 +0000450
Daniel Grumberg29125dd2020-05-11 11:42:38 +0100451 for (const auto &KindInfo : OptsWithMarshalling) {
452 OS << "#ifdef " << KindInfo->MacroName << "\n";
453 OS << KindInfo->MacroName << "(";
454 WriteOptRecordFields(OS, KindInfo->R);
455 OS << ", ";
456 KindInfo->emit(OS);
457 OS << ")\n";
458 OS << "#endif // " << KindInfo->MacroName << "\n";
459 }
460
461 OS << "\n";
462 OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
463 OS << "\n";
464 OS << MarshallingStringInfo::ValueTablePreamble;
465 std::vector<StringRef> ValueTableNames;
466 for (const auto &KindInfo : OptsWithMarshalling)
467 if (auto MaybeValueTableName = KindInfo->emitValueTable(OS))
468 ValueTableNames.push_back(*MaybeValueTableName);
469
470 OS << MarshallingStringInfo::ValueTablesDecl << "{";
471 for (auto ValueTableName : ValueTableNames)
472 OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
473 << ") / sizeof(SimpleEnumValue)"
474 << "},\n";
475 OS << "};\n";
476 OS << "static const unsigned SimpleEnumValueTablesSize = "
477 "sizeof(SimpleEnumValueTables) / sizeof(SimpleEnumValueTable);\n";
478
479 OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
480 OS << "\n";
481
Yuka Takahashi24bc6a42017-08-29 00:09:31 +0000482 OS << "\n";
483 OS << "#ifdef OPTTABLE_ARG_INIT\n";
484 OS << "//////////\n";
485 OS << "// Option Values\n\n";
486 for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
487 const Record &R = *Opts[I];
488 if (isa<UnsetInit>(R.getValueInit("ValuesCode")))
489 continue;
490 OS << "{\n";
Yuka Takahashi45244ed2017-08-29 02:01:56 +0000491 OS << "bool ValuesWereAdded;\n";
Yuka Takahashi24bc6a42017-08-29 00:09:31 +0000492 OS << R.getValueAsString("ValuesCode");
493 OS << "\n";
Benjamin Krameradcd0262020-01-28 20:23:46 +0100494 for (StringRef Prefix : R.getValueAsListOfStrings("Prefixes")) {
Yuka Takahashi45244ed2017-08-29 02:01:56 +0000495 OS << "ValuesWereAdded = Opt.addValues(";
Benjamin Krameradcd0262020-01-28 20:23:46 +0100496 std::string S(Prefix);
Mark de Wevere8d448e2019-12-22 18:58:32 +0100497 S += R.getValueAsString("Name");
Yuka Takahashi24bc6a42017-08-29 00:09:31 +0000498 write_cstring(OS, S);
499 OS << ", Values);\n";
500 OS << "(void)ValuesWereAdded;\n";
501 OS << "assert(ValuesWereAdded && \"Couldn't add values to "
502 "OptTable!\");\n";
503 }
504 OS << "}\n";
505 }
506 OS << "\n";
507 OS << "#endif // OPTTABLE_ARG_INIT\n";
Michael J. Spencer41ee0412012-12-05 00:29:32 +0000508}
509} // end namespace llvm