• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getOptionName(const Record & R)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 
write_cstring(raw_ostream & OS,llvm::StringRef Str)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 
getOptionSpelling(const Record & R,size_t & PrefixLength)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 
43   if (Prefixes.empty()) {
44     PrefixLength = 0;
45     return Name.str();
46   }
47 
48   PrefixLength = Prefixes[0].size();
49   return (Twine(Prefixes[0]) + Twine(Name)).str();
50 }
51 
getOptionSpelling(const Record & R)52 static const std::string getOptionSpelling(const Record &R) {
53   size_t PrefixLength;
54   return getOptionSpelling(R, PrefixLength);
55 }
56 
emitNameUsingSpelling(raw_ostream & OS,const Record & R)57 static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
58   size_t PrefixLength;
59   OS << "&";
60   write_cstring(OS, StringRef(getOptionSpelling(R, PrefixLength)));
61   OS << "[" << PrefixLength << "]";
62 }
63 
64 class MarshallingInfo {
65 public:
66   static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";
67   const Record &R;
68   bool ShouldAlwaysEmit;
69   StringRef KeyPath;
70   StringRef DefaultValue;
71   StringRef NormalizedValuesScope;
72   StringRef ImpliedCheck;
73   StringRef ImpliedValue;
74   StringRef Normalizer;
75   StringRef Denormalizer;
76   StringRef ValueMerger;
77   StringRef ValueExtractor;
78   int TableIndex = -1;
79   std::vector<StringRef> Values;
80   std::vector<StringRef> NormalizedValues;
81   std::string ValueTableName;
82 
83   static size_t NextTableIndex;
84 
85   static constexpr const char *ValueTablePreamble = R"(
86 struct SimpleEnumValue {
87   const char *Name;
88   unsigned Value;
89 };
90 
91 struct SimpleEnumValueTable {
92   const SimpleEnumValue *Table;
93   unsigned Size;
94 };
95 )";
96 
97   static constexpr const char *ValueTablesDecl =
98       "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
99 
MarshallingInfo(const Record & R)100   MarshallingInfo(const Record &R) : R(R) {}
101 
emit(raw_ostream & OS) const102   void emit(raw_ostream &OS) const {
103     write_cstring(OS, StringRef(getOptionSpelling(R)));
104     OS << ", ";
105     OS << ShouldAlwaysEmit;
106     OS << ", ";
107     OS << KeyPath;
108     OS << ", ";
109     emitScopedNormalizedValue(OS, DefaultValue);
110     OS << ", ";
111     OS << ImpliedCheck;
112     OS << ", ";
113     emitScopedNormalizedValue(OS, ImpliedValue);
114     OS << ", ";
115     OS << Normalizer;
116     OS << ", ";
117     OS << Denormalizer;
118     OS << ", ";
119     OS << ValueMerger;
120     OS << ", ";
121     OS << ValueExtractor;
122     OS << ", ";
123     OS << TableIndex;
124   }
125 
emitValueTable(raw_ostream & OS) const126   Optional<StringRef> emitValueTable(raw_ostream &OS) const {
127     if (TableIndex == -1)
128       return {};
129     OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
130     for (unsigned I = 0, E = Values.size(); I != E; ++I) {
131       OS << "{";
132       write_cstring(OS, Values[I]);
133       OS << ",";
134       OS << "static_cast<unsigned>(";
135       emitScopedNormalizedValue(OS, NormalizedValues[I]);
136       OS << ")},";
137     }
138     OS << "};\n";
139     return StringRef(ValueTableName);
140   }
141 
142 private:
emitScopedNormalizedValue(raw_ostream & OS,StringRef NormalizedValue) const143   void emitScopedNormalizedValue(raw_ostream &OS,
144                                  StringRef NormalizedValue) const {
145     if (!NormalizedValuesScope.empty())
146       OS << NormalizedValuesScope << "::";
147     OS << NormalizedValue;
148   }
149 };
150 
151 size_t MarshallingInfo::NextTableIndex = 0;
152 
createMarshallingInfo(const Record & R)153 static MarshallingInfo createMarshallingInfo(const Record &R) {
154   assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
155          !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
156          !isa<UnsetInit>(R.getValueInit("ValueMerger")) &&
157          "MarshallingInfo must have a provide a keypath, default value and a "
158          "value merger");
159 
160   MarshallingInfo Ret(R);
161 
162   Ret.ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
163   Ret.KeyPath = R.getValueAsString("KeyPath");
164   Ret.DefaultValue = R.getValueAsString("DefaultValue");
165   Ret.NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
166   Ret.ImpliedCheck = R.getValueAsString("ImpliedCheck");
167   Ret.ImpliedValue =
168       R.getValueAsOptionalString("ImpliedValue").getValueOr(Ret.DefaultValue);
169 
170   Ret.Normalizer = R.getValueAsString("Normalizer");
171   Ret.Denormalizer = R.getValueAsString("Denormalizer");
172   Ret.ValueMerger = R.getValueAsString("ValueMerger");
173   Ret.ValueExtractor = R.getValueAsString("ValueExtractor");
174 
175   if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
176     assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
177            "Cannot provide normalized values for value-less options");
178     Ret.TableIndex = MarshallingInfo::NextTableIndex++;
179     Ret.NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
180     Ret.Values.reserve(Ret.NormalizedValues.size());
181     Ret.ValueTableName = getOptionName(R) + "ValueTable";
182 
183     StringRef ValuesStr = R.getValueAsString("Values");
184     for (;;) {
185       size_t Idx = ValuesStr.find(',');
186       if (Idx == StringRef::npos)
187         break;
188       if (Idx > 0)
189         Ret.Values.push_back(ValuesStr.slice(0, Idx));
190       ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
191     }
192     if (!ValuesStr.empty())
193       Ret.Values.push_back(ValuesStr);
194 
195     assert(Ret.Values.size() == Ret.NormalizedValues.size() &&
196            "The number of normalized values doesn't match the number of "
197            "values");
198   }
199 
200   return Ret;
201 }
202 
203 /// OptParserEmitter - This tablegen backend takes an input .td file
204 /// describing a list of options and emits a data structure for parsing and
205 /// working with those options when given an input command line.
206 namespace llvm {
EmitOptParser(RecordKeeper & Records,raw_ostream & OS)207 void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
208   // Get the option groups and options.
209   const std::vector<Record*> &Groups =
210     Records.getAllDerivedDefinitions("OptionGroup");
211   std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
212 
213   emitSourceFileHeader("Option Parsing Definitions", OS);
214 
215   array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
216   // Generate prefix groups.
217   typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
218   typedef std::map<PrefixKeyT, std::string> PrefixesT;
219   PrefixesT Prefixes;
220   Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
221   unsigned CurPrefix = 0;
222   for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
223     const Record &R = *Opts[i];
224     std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
225     PrefixKeyT prfkey(prf.begin(), prf.end());
226     unsigned NewPrefix = CurPrefix + 1;
227     if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
228                                               Twine(NewPrefix)).str())).second)
229       CurPrefix = NewPrefix;
230   }
231 
232   // Dump prefixes.
233 
234   OS << "/////////\n";
235   OS << "// Prefixes\n\n";
236   OS << "#ifdef PREFIX\n";
237   OS << "#define COMMA ,\n";
238   for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
239                                   I != E; ++I) {
240     OS << "PREFIX(";
241 
242     // Prefix name.
243     OS << I->second;
244 
245     // Prefix values.
246     OS << ", {";
247     for (PrefixKeyT::const_iterator PI = I->first.begin(),
248                                     PE = I->first.end(); PI != PE; ++PI) {
249       OS << "\"" << *PI << "\" COMMA ";
250     }
251     OS << "nullptr})\n";
252   }
253   OS << "#undef COMMA\n";
254   OS << "#endif // PREFIX\n\n";
255 
256   OS << "/////////\n";
257   OS << "// Groups\n\n";
258   OS << "#ifdef OPTION\n";
259   for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
260     const Record &R = *Groups[i];
261 
262     // Start a single option entry.
263     OS << "OPTION(";
264 
265     // The option prefix;
266     OS << "nullptr";
267 
268     // The option string.
269     OS << ", \"" << R.getValueAsString("Name") << '"';
270 
271     // The option identifier name.
272     OS << ", " << getOptionName(R);
273 
274     // The option kind.
275     OS << ", Group";
276 
277     // The containing option group (if any).
278     OS << ", ";
279     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
280       OS << getOptionName(*DI->getDef());
281     else
282       OS << "INVALID";
283 
284     // The other option arguments (unused for groups).
285     OS << ", INVALID, nullptr, 0, 0";
286 
287     // The option help text.
288     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
289       OS << ",\n";
290       OS << "       ";
291       write_cstring(OS, R.getValueAsString("HelpText"));
292     } else
293       OS << ", nullptr";
294 
295     // The option meta-variable name (unused).
296     OS << ", nullptr";
297 
298     // The option Values (unused for groups).
299     OS << ", nullptr)\n";
300   }
301   OS << "\n";
302 
303   OS << "//////////\n";
304   OS << "// Options\n\n";
305 
306   auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
307     // The option prefix;
308     std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
309     OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
310 
311     // The option string.
312     emitNameUsingSpelling(OS, R);
313 
314     // The option identifier name.
315     OS << ", " << getOptionName(R);
316 
317     // The option kind.
318     OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
319 
320     // The containing option group (if any).
321     OS << ", ";
322     const ListInit *GroupFlags = nullptr;
323     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
324       GroupFlags = DI->getDef()->getValueAsListInit("Flags");
325       OS << getOptionName(*DI->getDef());
326     } else
327       OS << "INVALID";
328 
329     // The option alias (if any).
330     OS << ", ";
331     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
332       OS << getOptionName(*DI->getDef());
333     else
334       OS << "INVALID";
335 
336     // The option alias arguments (if any).
337     // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
338     // would become "foo\0bar\0". Note that the compiler adds an implicit
339     // terminating \0 at the end.
340     OS << ", ";
341     std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
342     if (AliasArgs.size() == 0) {
343       OS << "nullptr";
344     } else {
345       OS << "\"";
346       for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
347         OS << AliasArgs[i] << "\\0";
348       OS << "\"";
349     }
350 
351     // The option flags.
352     OS << ", ";
353     int NumFlags = 0;
354     const ListInit *LI = R.getValueAsListInit("Flags");
355     for (Init *I : *LI)
356       OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
357     if (GroupFlags) {
358       for (Init *I : *GroupFlags)
359         OS << (NumFlags++ ? " | " : "")
360            << cast<DefInit>(I)->getDef()->getName();
361     }
362     if (NumFlags == 0)
363       OS << '0';
364 
365     // The option parameter field.
366     OS << ", " << R.getValueAsInt("NumArgs");
367 
368     // The option help text.
369     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
370       OS << ",\n";
371       OS << "       ";
372       write_cstring(OS, R.getValueAsString("HelpText"));
373     } else
374       OS << ", nullptr";
375 
376     // The option meta-variable name.
377     OS << ", ";
378     if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
379       write_cstring(OS, R.getValueAsString("MetaVarName"));
380     else
381       OS << "nullptr";
382 
383     // The option Values. Used for shell autocompletion.
384     OS << ", ";
385     if (!isa<UnsetInit>(R.getValueInit("Values")))
386       write_cstring(OS, R.getValueAsString("Values"));
387     else
388       OS << "nullptr";
389   };
390 
391   auto IsMarshallingOption = [](const Record &R) {
392     return !isa<UnsetInit>(R.getValueInit("KeyPath")) &&
393            !R.getValueAsString("KeyPath").empty();
394   };
395 
396   std::vector<const Record *> OptsWithMarshalling;
397   for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
398     const Record &R = *Opts[I];
399 
400     // Start a single option entry.
401     OS << "OPTION(";
402     WriteOptRecordFields(OS, R);
403     OS << ")\n";
404     if (IsMarshallingOption(R))
405       OptsWithMarshalling.push_back(&R);
406   }
407   OS << "#endif // OPTION\n";
408 
409   auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) {
410     unsigned AID = (*A)->getID();
411     unsigned BID = (*B)->getID();
412 
413     if (AID < BID)
414       return -1;
415     if (AID > BID)
416       return 1;
417     return 0;
418   };
419   // The RecordKeeper stores records (options) in lexicographical order, and we
420   // have reordered the options again when generating prefix groups. We need to
421   // restore the original definition order of options with marshalling to honor
422   // the topology of the dependency graph implied by `DefaultAnyOf`.
423   array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),
424                  CmpMarshallingOpts);
425 
426   std::vector<MarshallingInfo> MarshallingInfos;
427   for (const auto *R : OptsWithMarshalling)
428     MarshallingInfos.push_back(createMarshallingInfo(*R));
429 
430   for (const auto &MI : MarshallingInfos) {
431     OS << "#ifdef " << MarshallingInfo::MacroName << "\n";
432     OS << MarshallingInfo::MacroName << "(";
433     WriteOptRecordFields(OS, MI.R);
434     OS << ", ";
435     MI.emit(OS);
436     OS << ")\n";
437     OS << "#endif // " << MarshallingInfo::MacroName << "\n";
438   }
439 
440   OS << "\n";
441   OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
442   OS << "\n";
443   OS << MarshallingInfo::ValueTablePreamble;
444   std::vector<StringRef> ValueTableNames;
445   for (const auto &MI : MarshallingInfos)
446     if (auto MaybeValueTableName = MI.emitValueTable(OS))
447       ValueTableNames.push_back(*MaybeValueTableName);
448 
449   OS << MarshallingInfo::ValueTablesDecl << "{";
450   for (auto ValueTableName : ValueTableNames)
451     OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
452        << ") / sizeof(SimpleEnumValue)"
453        << "},\n";
454   OS << "};\n";
455   OS << "static const unsigned SimpleEnumValueTablesSize = "
456         "sizeof(SimpleEnumValueTables) / sizeof(SimpleEnumValueTable);\n";
457 
458   OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
459   OS << "\n";
460 
461   OS << "\n";
462   OS << "#ifdef OPTTABLE_ARG_INIT\n";
463   OS << "//////////\n";
464   OS << "// Option Values\n\n";
465   for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
466     const Record &R = *Opts[I];
467     if (isa<UnsetInit>(R.getValueInit("ValuesCode")))
468       continue;
469     OS << "{\n";
470     OS << "bool ValuesWereAdded;\n";
471     OS << R.getValueAsString("ValuesCode");
472     OS << "\n";
473     for (StringRef Prefix : R.getValueAsListOfStrings("Prefixes")) {
474       OS << "ValuesWereAdded = Opt.addValues(";
475       std::string S(Prefix);
476       S += R.getValueAsString("Name");
477       write_cstring(OS, S);
478       OS << ", Values);\n";
479       OS << "(void)ValuesWereAdded;\n";
480       OS << "assert(ValuesWereAdded && \"Couldn't add values to "
481             "OptTable!\");\n";
482     }
483     OS << "}\n";
484   }
485   OS << "\n";
486   OS << "#endif // OPTTABLE_ARG_INIT\n";
487 }
488 } // end namespace llvm
489