xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/OptParserEmitter.cpp (revision 25ecdc7d52770caf1c9b44b5ec11f468f6b636f3)
1 //===- OptParserEmitter.cpp - Table Driven Command 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/Twine.h"
13 #include "llvm/Support/raw_ostream.h"
14 #include "llvm/TableGen/Record.h"
15 #include "llvm/TableGen/TableGenBackend.h"
16 #include <cctype>
17 #include <cstring>
18 #include <map>
19 #include <memory>
20 
21 using namespace llvm;
22 
23 static const std::string getOptionName(const Record &R) {
24   // Use the record name unless EnumName is defined.
25   if (isa<UnsetInit>(R.getValueInit("EnumName")))
26     return std::string(R.getName());
27 
28   return std::string(R.getValueAsString("EnumName"));
29 }
30 
31 static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
32   OS << '"';
33   OS.write_escaped(Str);
34   OS << '"';
35   return OS;
36 }
37 
38 static 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 
50 static const std::string getOptionSpelling(const Record &R) {
51   size_t PrefixLength;
52   return getOptionSpelling(R, PrefixLength);
53 }
54 
55 static 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 
62 class MarshallingKindInfo {
63 public:
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 
91 protected:
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 
104 class MarshallingFlagInfo final : public MarshallingKindInfo {
105 public:
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");
113     return Ret;
114   }
115 
116 private:
117   MarshallingFlagInfo(const Record &R)
118       : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {}
119 };
120 
121 class MarshallingStringInfo final : public MarshallingKindInfo {
122 public:
123   StringRef NormalizerRetTy;
124   StringRef Normalizer;
125   StringRef Denormalizer;
126   int TableIndex = -1;
127   std::vector<StringRef> Values;
128   std::vector<StringRef> NormalizedValues;
129   std::string ValueTableName;
130 
131   static constexpr const char *ValueTablePreamble = R"(
132 struct SimpleEnumValue {
133   const char *Name;
134   unsigned Value;
135 };
136 
137 struct SimpleEnumValueTable {
138   const SimpleEnumValue *Table;
139   unsigned Size;
140 };
141 )";
142 
143   static constexpr const char *ValueTablesDecl =
144       "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
145 
146   void emitSpecific(raw_ostream &OS) const override {
147     emitScopedNormalizedValue(OS, NormalizerRetTy);
148     OS << ", ";
149     OS << Normalizer;
150     OS << ", ";
151     OS << Denormalizer;
152     OS << ", ";
153     OS << TableIndex;
154   }
155 
156   Optional<StringRef> emitValueTable(raw_ostream &OS) const override {
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       write_cstring(OS, Values[I]);
163       OS << ",";
164       OS << "static_cast<unsigned>(";
165       emitScopedNormalizedValue(OS, NormalizedValues[I]);
166       OS << ")},";
167     }
168     OS << "};\n";
169     return StringRef(ValueTableName);
170   }
171 
172   static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
173     assert(!isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) &&
174            "String options must have a type");
175 
176     std::unique_ptr<MarshallingStringInfo> Ret(new MarshallingStringInfo(R));
177     Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy");
178 
179     Ret->Normalizer = R.getValueAsString("Normalizer");
180     Ret->Denormalizer = R.getValueAsString("Denormalizer");
181 
182     if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
183       assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
184              "Cannot provide normalized values for value-less options");
185       Ret->TableIndex = NextTableIndex++;
186       Ret->NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
187       Ret->Values.reserve(Ret->NormalizedValues.size());
188       Ret->ValueTableName = getOptionName(R) + "ValueTable";
189 
190       StringRef ValuesStr = R.getValueAsString("Values");
191       for (;;) {
192         size_t Idx = ValuesStr.find(',');
193         if (Idx == StringRef::npos)
194           break;
195         if (Idx > 0)
196           Ret->Values.push_back(ValuesStr.slice(0, Idx));
197         ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
198       }
199       if (!ValuesStr.empty())
200         Ret->Values.push_back(ValuesStr);
201 
202       assert(Ret->Values.size() == Ret->NormalizedValues.size() &&
203              "The number of normalized values doesn't match the number of "
204              "values");
205     }
206 
207     return Ret;
208   }
209 
210 private:
211   MarshallingStringInfo(const Record &R)
212       : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {}
213 
214   static size_t NextTableIndex;
215 };
216 
217 size_t MarshallingStringInfo::NextTableIndex = 0;
218 
219 std::unique_ptr<MarshallingKindInfo>
220 MarshallingKindInfo::create(const Record &R) {
221   assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
222          !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
223          "Must provide at least a key-path and a default value for emitting "
224          "marshalling information");
225 
226   std::unique_ptr<MarshallingKindInfo> Ret = nullptr;
227   StringRef MarshallingKindStr = R.getValueAsString("MarshallingKind");
228 
229   if (MarshallingKindStr == "flag")
230     Ret = MarshallingFlagInfo::create(R);
231   else if (MarshallingKindStr == "string")
232     Ret = MarshallingStringInfo::create(R);
233 
234   Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
235   Ret->KeyPath = R.getValueAsString("KeyPath");
236   Ret->DefaultValue = R.getValueAsString("DefaultValue");
237   if (!isa<UnsetInit>(R.getValueInit("NormalizedValuesScope")))
238     Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
239   return Ret;
240 }
241 
242 /// OptParserEmitter - This tablegen backend takes an input .td file
243 /// describing a list of options and emits a data structure for parsing and
244 /// working with those options when given an input command line.
245 namespace llvm {
246 void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
247   // Get the option groups and options.
248   const std::vector<Record*> &Groups =
249     Records.getAllDerivedDefinitions("OptionGroup");
250   std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
251 
252   emitSourceFileHeader("Option Parsing Definitions", OS);
253 
254   array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
255   // Generate prefix groups.
256   typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
257   typedef std::map<PrefixKeyT, std::string> PrefixesT;
258   PrefixesT Prefixes;
259   Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
260   unsigned CurPrefix = 0;
261   for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
262     const Record &R = *Opts[i];
263     std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
264     PrefixKeyT prfkey(prf.begin(), prf.end());
265     unsigned NewPrefix = CurPrefix + 1;
266     if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
267                                               Twine(NewPrefix)).str())).second)
268       CurPrefix = NewPrefix;
269   }
270 
271   // Dump prefixes.
272 
273   OS << "/////////\n";
274   OS << "// Prefixes\n\n";
275   OS << "#ifdef PREFIX\n";
276   OS << "#define COMMA ,\n";
277   for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
278                                   I != E; ++I) {
279     OS << "PREFIX(";
280 
281     // Prefix name.
282     OS << I->second;
283 
284     // Prefix values.
285     OS << ", {";
286     for (PrefixKeyT::const_iterator PI = I->first.begin(),
287                                     PE = I->first.end(); PI != PE; ++PI) {
288       OS << "\"" << *PI << "\" COMMA ";
289     }
290     OS << "nullptr})\n";
291   }
292   OS << "#undef COMMA\n";
293   OS << "#endif // PREFIX\n\n";
294 
295   OS << "/////////\n";
296   OS << "// Groups\n\n";
297   OS << "#ifdef OPTION\n";
298   for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
299     const Record &R = *Groups[i];
300 
301     // Start a single option entry.
302     OS << "OPTION(";
303 
304     // The option prefix;
305     OS << "nullptr";
306 
307     // The option string.
308     OS << ", \"" << R.getValueAsString("Name") << '"';
309 
310     // The option identifier name.
311     OS << ", " << getOptionName(R);
312 
313     // The option kind.
314     OS << ", Group";
315 
316     // The containing option group (if any).
317     OS << ", ";
318     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
319       OS << getOptionName(*DI->getDef());
320     else
321       OS << "INVALID";
322 
323     // The other option arguments (unused for groups).
324     OS << ", INVALID, nullptr, 0, 0";
325 
326     // The option help text.
327     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
328       OS << ",\n";
329       OS << "       ";
330       write_cstring(OS, R.getValueAsString("HelpText"));
331     } else
332       OS << ", nullptr";
333 
334     // The option meta-variable name (unused).
335     OS << ", nullptr";
336 
337     // The option Values (unused for groups).
338     OS << ", nullptr)\n";
339   }
340   OS << "\n";
341 
342   OS << "//////////\n";
343   OS << "// Options\n\n";
344 
345   auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
346     // The option prefix;
347     std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
348     OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
349 
350     // The option string.
351     emitNameUsingSpelling(OS, R);
352 
353     // The option identifier name.
354     OS << ", " << getOptionName(R);
355 
356     // The option kind.
357     OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
358 
359     // The containing option group (if any).
360     OS << ", ";
361     const ListInit *GroupFlags = nullptr;
362     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
363       GroupFlags = DI->getDef()->getValueAsListInit("Flags");
364       OS << getOptionName(*DI->getDef());
365     } else
366       OS << "INVALID";
367 
368     // The option alias (if any).
369     OS << ", ";
370     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
371       OS << getOptionName(*DI->getDef());
372     else
373       OS << "INVALID";
374 
375     // The option alias arguments (if any).
376     // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
377     // would become "foo\0bar\0". Note that the compiler adds an implicit
378     // terminating \0 at the end.
379     OS << ", ";
380     std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
381     if (AliasArgs.size() == 0) {
382       OS << "nullptr";
383     } else {
384       OS << "\"";
385       for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
386         OS << AliasArgs[i] << "\\0";
387       OS << "\"";
388     }
389 
390     // The option flags.
391     OS << ", ";
392     int NumFlags = 0;
393     const ListInit *LI = R.getValueAsListInit("Flags");
394     for (Init *I : *LI)
395       OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
396     if (GroupFlags) {
397       for (Init *I : *GroupFlags)
398         OS << (NumFlags++ ? " | " : "")
399            << cast<DefInit>(I)->getDef()->getName();
400     }
401     if (NumFlags == 0)
402       OS << '0';
403 
404     // The option parameter field.
405     OS << ", " << R.getValueAsInt("NumArgs");
406 
407     // The option help text.
408     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
409       OS << ",\n";
410       OS << "       ";
411       write_cstring(OS, R.getValueAsString("HelpText"));
412     } else
413       OS << ", nullptr";
414 
415     // The option meta-variable name.
416     OS << ", ";
417     if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
418       write_cstring(OS, R.getValueAsString("MetaVarName"));
419     else
420       OS << "nullptr";
421 
422     // The option Values. Used for shell autocompletion.
423     OS << ", ";
424     if (!isa<UnsetInit>(R.getValueInit("Values")))
425       write_cstring(OS, R.getValueAsString("Values"));
426     else
427       OS << "nullptr";
428   };
429 
430   std::vector<std::unique_ptr<MarshallingKindInfo>> OptsWithMarshalling;
431   for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
432     const Record &R = *Opts[I];
433 
434     // Start a single option entry.
435     OS << "OPTION(";
436     WriteOptRecordFields(OS, R);
437     OS << ")\n";
438     if (!isa<UnsetInit>(R.getValueInit("MarshallingKind")))
439       OptsWithMarshalling.push_back(MarshallingKindInfo::create(R));
440   }
441   OS << "#endif // OPTION\n";
442 
443   for (const auto &KindInfo : OptsWithMarshalling) {
444     OS << "#ifdef " << KindInfo->MacroName << "\n";
445     OS << KindInfo->MacroName << "(";
446     WriteOptRecordFields(OS, KindInfo->R);
447     OS << ", ";
448     KindInfo->emit(OS);
449     OS << ")\n";
450     OS << "#endif // " << KindInfo->MacroName << "\n";
451   }
452 
453   OS << "\n";
454   OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
455   OS << "\n";
456   OS << MarshallingStringInfo::ValueTablePreamble;
457   std::vector<StringRef> ValueTableNames;
458   for (const auto &KindInfo : OptsWithMarshalling)
459     if (auto MaybeValueTableName = KindInfo->emitValueTable(OS))
460       ValueTableNames.push_back(*MaybeValueTableName);
461 
462   OS << MarshallingStringInfo::ValueTablesDecl << "{";
463   for (auto ValueTableName : ValueTableNames)
464     OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
465        << ") / sizeof(SimpleEnumValue)"
466        << "},\n";
467   OS << "};\n";
468   OS << "static const unsigned SimpleEnumValueTablesSize = "
469         "sizeof(SimpleEnumValueTables) / sizeof(SimpleEnumValueTable);\n";
470 
471   OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
472   OS << "\n";
473 
474   OS << "\n";
475   OS << "#ifdef OPTTABLE_ARG_INIT\n";
476   OS << "//////////\n";
477   OS << "// Option Values\n\n";
478   for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
479     const Record &R = *Opts[I];
480     if (isa<UnsetInit>(R.getValueInit("ValuesCode")))
481       continue;
482     OS << "{\n";
483     OS << "bool ValuesWereAdded;\n";
484     OS << R.getValueAsString("ValuesCode");
485     OS << "\n";
486     for (StringRef Prefix : R.getValueAsListOfStrings("Prefixes")) {
487       OS << "ValuesWereAdded = Opt.addValues(";
488       std::string S(Prefix);
489       S += R.getValueAsString("Name");
490       write_cstring(OS, S);
491       OS << ", Values);\n";
492       OS << "(void)ValuesWereAdded;\n";
493       OS << "assert(ValuesWereAdded && \"Couldn't add values to "
494             "OptTable!\");\n";
495     }
496     OS << "}\n";
497   }
498   OS << "\n";
499   OS << "#endif // OPTTABLE_ARG_INIT\n";
500 }
501 } // end namespace llvm
502