1*9880d681SAndroid Build Coastguard Worker //===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "llvm/TableGen/Error.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallString.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/TableGen/Record.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/TableGen/TableGenBackend.h"
16*9880d681SAndroid Build Coastguard Worker #include <cctype>
17*9880d681SAndroid Build Coastguard Worker #include <cstring>
18*9880d681SAndroid Build Coastguard Worker #include <map>
19*9880d681SAndroid Build Coastguard Worker
20*9880d681SAndroid Build Coastguard Worker using namespace llvm;
21*9880d681SAndroid Build Coastguard Worker
22*9880d681SAndroid Build Coastguard Worker // Ordering on Info. The logic should match with the consumer-side function in
23*9880d681SAndroid Build Coastguard Worker // llvm/Option/OptTable.h.
StrCmpOptionName(const char * A,const char * B)24*9880d681SAndroid Build Coastguard Worker static int StrCmpOptionName(const char *A, const char *B) {
25*9880d681SAndroid Build Coastguard Worker const char *X = A, *Y = B;
26*9880d681SAndroid Build Coastguard Worker char a = tolower(*A), b = tolower(*B);
27*9880d681SAndroid Build Coastguard Worker while (a == b) {
28*9880d681SAndroid Build Coastguard Worker if (a == '\0')
29*9880d681SAndroid Build Coastguard Worker return strcmp(A, B);
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker a = tolower(*++X);
32*9880d681SAndroid Build Coastguard Worker b = tolower(*++Y);
33*9880d681SAndroid Build Coastguard Worker }
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker if (a == '\0') // A is a prefix of B.
36*9880d681SAndroid Build Coastguard Worker return 1;
37*9880d681SAndroid Build Coastguard Worker if (b == '\0') // B is a prefix of A.
38*9880d681SAndroid Build Coastguard Worker return -1;
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker // Otherwise lexicographic.
41*9880d681SAndroid Build Coastguard Worker return (a < b) ? -1 : 1;
42*9880d681SAndroid Build Coastguard Worker }
43*9880d681SAndroid Build Coastguard Worker
CompareOptionRecords(Record * const * Av,Record * const * Bv)44*9880d681SAndroid Build Coastguard Worker static int CompareOptionRecords(Record *const *Av, Record *const *Bv) {
45*9880d681SAndroid Build Coastguard Worker const Record *A = *Av;
46*9880d681SAndroid Build Coastguard Worker const Record *B = *Bv;
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker // Sentinel options precede all others and are only ordered by precedence.
49*9880d681SAndroid Build Coastguard Worker bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
50*9880d681SAndroid Build Coastguard Worker bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
51*9880d681SAndroid Build Coastguard Worker if (ASent != BSent)
52*9880d681SAndroid Build Coastguard Worker return ASent ? -1 : 1;
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker // Compare options by name, unless they are sentinels.
55*9880d681SAndroid Build Coastguard Worker if (!ASent)
56*9880d681SAndroid Build Coastguard Worker if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
57*9880d681SAndroid Build Coastguard Worker B->getValueAsString("Name").c_str()))
58*9880d681SAndroid Build Coastguard Worker return Cmp;
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker if (!ASent) {
61*9880d681SAndroid Build Coastguard Worker std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes");
62*9880d681SAndroid Build Coastguard Worker std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes");
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker for (std::vector<std::string>::const_iterator APre = APrefixes.begin(),
65*9880d681SAndroid Build Coastguard Worker AEPre = APrefixes.end(),
66*9880d681SAndroid Build Coastguard Worker BPre = BPrefixes.begin(),
67*9880d681SAndroid Build Coastguard Worker BEPre = BPrefixes.end();
68*9880d681SAndroid Build Coastguard Worker APre != AEPre &&
69*9880d681SAndroid Build Coastguard Worker BPre != BEPre;
70*9880d681SAndroid Build Coastguard Worker ++APre, ++BPre) {
71*9880d681SAndroid Build Coastguard Worker if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str()))
72*9880d681SAndroid Build Coastguard Worker return Cmp;
73*9880d681SAndroid Build Coastguard Worker }
74*9880d681SAndroid Build Coastguard Worker }
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker // Then by the kind precedence;
77*9880d681SAndroid Build Coastguard Worker int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
78*9880d681SAndroid Build Coastguard Worker int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
79*9880d681SAndroid Build Coastguard Worker if (APrec == BPrec &&
80*9880d681SAndroid Build Coastguard Worker A->getValueAsListOfStrings("Prefixes") ==
81*9880d681SAndroid Build Coastguard Worker B->getValueAsListOfStrings("Prefixes")) {
82*9880d681SAndroid Build Coastguard Worker PrintError(A->getLoc(), Twine("Option is equivalent to"));
83*9880d681SAndroid Build Coastguard Worker PrintError(B->getLoc(), Twine("Other defined here"));
84*9880d681SAndroid Build Coastguard Worker PrintFatalError("Equivalent Options found.");
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker return APrec < BPrec ? -1 : 1;
87*9880d681SAndroid Build Coastguard Worker }
88*9880d681SAndroid Build Coastguard Worker
getOptionName(const Record & R)89*9880d681SAndroid Build Coastguard Worker static const std::string getOptionName(const Record &R) {
90*9880d681SAndroid Build Coastguard Worker // Use the record name unless EnumName is defined.
91*9880d681SAndroid Build Coastguard Worker if (isa<UnsetInit>(R.getValueInit("EnumName")))
92*9880d681SAndroid Build Coastguard Worker return R.getName();
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker return R.getValueAsString("EnumName");
95*9880d681SAndroid Build Coastguard Worker }
96*9880d681SAndroid Build Coastguard Worker
write_cstring(raw_ostream & OS,llvm::StringRef Str)97*9880d681SAndroid Build Coastguard Worker static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
98*9880d681SAndroid Build Coastguard Worker OS << '"';
99*9880d681SAndroid Build Coastguard Worker OS.write_escaped(Str);
100*9880d681SAndroid Build Coastguard Worker OS << '"';
101*9880d681SAndroid Build Coastguard Worker return OS;
102*9880d681SAndroid Build Coastguard Worker }
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker /// OptParserEmitter - This tablegen backend takes an input .td file
105*9880d681SAndroid Build Coastguard Worker /// describing a list of options and emits a data structure for parsing and
106*9880d681SAndroid Build Coastguard Worker /// working with those options when given an input command line.
107*9880d681SAndroid Build Coastguard Worker namespace llvm {
EmitOptParser(RecordKeeper & Records,raw_ostream & OS)108*9880d681SAndroid Build Coastguard Worker void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
109*9880d681SAndroid Build Coastguard Worker // Get the option groups and options.
110*9880d681SAndroid Build Coastguard Worker const std::vector<Record*> &Groups =
111*9880d681SAndroid Build Coastguard Worker Records.getAllDerivedDefinitions("OptionGroup");
112*9880d681SAndroid Build Coastguard Worker std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker emitSourceFileHeader("Option Parsing Definitions", OS);
115*9880d681SAndroid Build Coastguard Worker
116*9880d681SAndroid Build Coastguard Worker array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
117*9880d681SAndroid Build Coastguard Worker // Generate prefix groups.
118*9880d681SAndroid Build Coastguard Worker typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
119*9880d681SAndroid Build Coastguard Worker typedef std::map<PrefixKeyT, std::string> PrefixesT;
120*9880d681SAndroid Build Coastguard Worker PrefixesT Prefixes;
121*9880d681SAndroid Build Coastguard Worker Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
122*9880d681SAndroid Build Coastguard Worker unsigned CurPrefix = 0;
123*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
124*9880d681SAndroid Build Coastguard Worker const Record &R = *Opts[i];
125*9880d681SAndroid Build Coastguard Worker std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
126*9880d681SAndroid Build Coastguard Worker PrefixKeyT prfkey(prf.begin(), prf.end());
127*9880d681SAndroid Build Coastguard Worker unsigned NewPrefix = CurPrefix + 1;
128*9880d681SAndroid Build Coastguard Worker if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
129*9880d681SAndroid Build Coastguard Worker Twine(NewPrefix)).str())).second)
130*9880d681SAndroid Build Coastguard Worker CurPrefix = NewPrefix;
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker // Dump prefixes.
134*9880d681SAndroid Build Coastguard Worker
135*9880d681SAndroid Build Coastguard Worker OS << "/////////\n";
136*9880d681SAndroid Build Coastguard Worker OS << "// Prefixes\n\n";
137*9880d681SAndroid Build Coastguard Worker OS << "#ifdef PREFIX\n";
138*9880d681SAndroid Build Coastguard Worker OS << "#define COMMA ,\n";
139*9880d681SAndroid Build Coastguard Worker for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
140*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
141*9880d681SAndroid Build Coastguard Worker OS << "PREFIX(";
142*9880d681SAndroid Build Coastguard Worker
143*9880d681SAndroid Build Coastguard Worker // Prefix name.
144*9880d681SAndroid Build Coastguard Worker OS << I->second;
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker // Prefix values.
147*9880d681SAndroid Build Coastguard Worker OS << ", {";
148*9880d681SAndroid Build Coastguard Worker for (PrefixKeyT::const_iterator PI = I->first.begin(),
149*9880d681SAndroid Build Coastguard Worker PE = I->first.end(); PI != PE; ++PI) {
150*9880d681SAndroid Build Coastguard Worker OS << "\"" << *PI << "\" COMMA ";
151*9880d681SAndroid Build Coastguard Worker }
152*9880d681SAndroid Build Coastguard Worker OS << "nullptr})\n";
153*9880d681SAndroid Build Coastguard Worker }
154*9880d681SAndroid Build Coastguard Worker OS << "#undef COMMA\n";
155*9880d681SAndroid Build Coastguard Worker OS << "#endif // PREFIX\n\n";
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker OS << "/////////\n";
158*9880d681SAndroid Build Coastguard Worker OS << "// Groups\n\n";
159*9880d681SAndroid Build Coastguard Worker OS << "#ifdef OPTION\n";
160*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
161*9880d681SAndroid Build Coastguard Worker const Record &R = *Groups[i];
162*9880d681SAndroid Build Coastguard Worker
163*9880d681SAndroid Build Coastguard Worker // Start a single option entry.
164*9880d681SAndroid Build Coastguard Worker OS << "OPTION(";
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker // The option prefix;
167*9880d681SAndroid Build Coastguard Worker OS << "nullptr";
168*9880d681SAndroid Build Coastguard Worker
169*9880d681SAndroid Build Coastguard Worker // The option string.
170*9880d681SAndroid Build Coastguard Worker OS << ", \"" << R.getValueAsString("Name") << '"';
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker // The option identifier name.
173*9880d681SAndroid Build Coastguard Worker OS << ", "<< getOptionName(R);
174*9880d681SAndroid Build Coastguard Worker
175*9880d681SAndroid Build Coastguard Worker // The option kind.
176*9880d681SAndroid Build Coastguard Worker OS << ", Group";
177*9880d681SAndroid Build Coastguard Worker
178*9880d681SAndroid Build Coastguard Worker // The containing option group (if any).
179*9880d681SAndroid Build Coastguard Worker OS << ", ";
180*9880d681SAndroid Build Coastguard Worker if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
181*9880d681SAndroid Build Coastguard Worker OS << getOptionName(*DI->getDef());
182*9880d681SAndroid Build Coastguard Worker else
183*9880d681SAndroid Build Coastguard Worker OS << "INVALID";
184*9880d681SAndroid Build Coastguard Worker
185*9880d681SAndroid Build Coastguard Worker // The other option arguments (unused for groups).
186*9880d681SAndroid Build Coastguard Worker OS << ", INVALID, nullptr, 0, 0";
187*9880d681SAndroid Build Coastguard Worker
188*9880d681SAndroid Build Coastguard Worker // The option help text.
189*9880d681SAndroid Build Coastguard Worker if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
190*9880d681SAndroid Build Coastguard Worker OS << ",\n";
191*9880d681SAndroid Build Coastguard Worker OS << " ";
192*9880d681SAndroid Build Coastguard Worker write_cstring(OS, R.getValueAsString("HelpText"));
193*9880d681SAndroid Build Coastguard Worker } else
194*9880d681SAndroid Build Coastguard Worker OS << ", nullptr";
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker // The option meta-variable name (unused).
197*9880d681SAndroid Build Coastguard Worker OS << ", nullptr)\n";
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker OS << "\n";
200*9880d681SAndroid Build Coastguard Worker
201*9880d681SAndroid Build Coastguard Worker OS << "//////////\n";
202*9880d681SAndroid Build Coastguard Worker OS << "// Options\n\n";
203*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
204*9880d681SAndroid Build Coastguard Worker const Record &R = *Opts[i];
205*9880d681SAndroid Build Coastguard Worker
206*9880d681SAndroid Build Coastguard Worker // Start a single option entry.
207*9880d681SAndroid Build Coastguard Worker OS << "OPTION(";
208*9880d681SAndroid Build Coastguard Worker
209*9880d681SAndroid Build Coastguard Worker // The option prefix;
210*9880d681SAndroid Build Coastguard Worker std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
211*9880d681SAndroid Build Coastguard Worker OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker // The option string.
214*9880d681SAndroid Build Coastguard Worker write_cstring(OS, R.getValueAsString("Name"));
215*9880d681SAndroid Build Coastguard Worker
216*9880d681SAndroid Build Coastguard Worker // The option identifier name.
217*9880d681SAndroid Build Coastguard Worker OS << ", "<< getOptionName(R);
218*9880d681SAndroid Build Coastguard Worker
219*9880d681SAndroid Build Coastguard Worker // The option kind.
220*9880d681SAndroid Build Coastguard Worker OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
221*9880d681SAndroid Build Coastguard Worker
222*9880d681SAndroid Build Coastguard Worker // The containing option group (if any).
223*9880d681SAndroid Build Coastguard Worker OS << ", ";
224*9880d681SAndroid Build Coastguard Worker const ListInit *GroupFlags = nullptr;
225*9880d681SAndroid Build Coastguard Worker if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
226*9880d681SAndroid Build Coastguard Worker GroupFlags = DI->getDef()->getValueAsListInit("Flags");
227*9880d681SAndroid Build Coastguard Worker OS << getOptionName(*DI->getDef());
228*9880d681SAndroid Build Coastguard Worker } else
229*9880d681SAndroid Build Coastguard Worker OS << "INVALID";
230*9880d681SAndroid Build Coastguard Worker
231*9880d681SAndroid Build Coastguard Worker // The option alias (if any).
232*9880d681SAndroid Build Coastguard Worker OS << ", ";
233*9880d681SAndroid Build Coastguard Worker if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
234*9880d681SAndroid Build Coastguard Worker OS << getOptionName(*DI->getDef());
235*9880d681SAndroid Build Coastguard Worker else
236*9880d681SAndroid Build Coastguard Worker OS << "INVALID";
237*9880d681SAndroid Build Coastguard Worker
238*9880d681SAndroid Build Coastguard Worker // The option alias arguments (if any).
239*9880d681SAndroid Build Coastguard Worker // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
240*9880d681SAndroid Build Coastguard Worker // would become "foo\0bar\0". Note that the compiler adds an implicit
241*9880d681SAndroid Build Coastguard Worker // terminating \0 at the end.
242*9880d681SAndroid Build Coastguard Worker OS << ", ";
243*9880d681SAndroid Build Coastguard Worker std::vector<std::string> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
244*9880d681SAndroid Build Coastguard Worker if (AliasArgs.size() == 0) {
245*9880d681SAndroid Build Coastguard Worker OS << "nullptr";
246*9880d681SAndroid Build Coastguard Worker } else {
247*9880d681SAndroid Build Coastguard Worker OS << "\"";
248*9880d681SAndroid Build Coastguard Worker for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
249*9880d681SAndroid Build Coastguard Worker OS << AliasArgs[i] << "\\0";
250*9880d681SAndroid Build Coastguard Worker OS << "\"";
251*9880d681SAndroid Build Coastguard Worker }
252*9880d681SAndroid Build Coastguard Worker
253*9880d681SAndroid Build Coastguard Worker // The option flags.
254*9880d681SAndroid Build Coastguard Worker OS << ", ";
255*9880d681SAndroid Build Coastguard Worker int NumFlags = 0;
256*9880d681SAndroid Build Coastguard Worker const ListInit *LI = R.getValueAsListInit("Flags");
257*9880d681SAndroid Build Coastguard Worker for (Init *I : *LI)
258*9880d681SAndroid Build Coastguard Worker OS << (NumFlags++ ? " | " : "")
259*9880d681SAndroid Build Coastguard Worker << cast<DefInit>(I)->getDef()->getName();
260*9880d681SAndroid Build Coastguard Worker if (GroupFlags) {
261*9880d681SAndroid Build Coastguard Worker for (Init *I : *GroupFlags)
262*9880d681SAndroid Build Coastguard Worker OS << (NumFlags++ ? " | " : "")
263*9880d681SAndroid Build Coastguard Worker << cast<DefInit>(I)->getDef()->getName();
264*9880d681SAndroid Build Coastguard Worker }
265*9880d681SAndroid Build Coastguard Worker if (NumFlags == 0)
266*9880d681SAndroid Build Coastguard Worker OS << '0';
267*9880d681SAndroid Build Coastguard Worker
268*9880d681SAndroid Build Coastguard Worker // The option parameter field.
269*9880d681SAndroid Build Coastguard Worker OS << ", " << R.getValueAsInt("NumArgs");
270*9880d681SAndroid Build Coastguard Worker
271*9880d681SAndroid Build Coastguard Worker // The option help text.
272*9880d681SAndroid Build Coastguard Worker if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
273*9880d681SAndroid Build Coastguard Worker OS << ",\n";
274*9880d681SAndroid Build Coastguard Worker OS << " ";
275*9880d681SAndroid Build Coastguard Worker write_cstring(OS, R.getValueAsString("HelpText"));
276*9880d681SAndroid Build Coastguard Worker } else
277*9880d681SAndroid Build Coastguard Worker OS << ", nullptr";
278*9880d681SAndroid Build Coastguard Worker
279*9880d681SAndroid Build Coastguard Worker // The option meta-variable name.
280*9880d681SAndroid Build Coastguard Worker OS << ", ";
281*9880d681SAndroid Build Coastguard Worker if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
282*9880d681SAndroid Build Coastguard Worker write_cstring(OS, R.getValueAsString("MetaVarName"));
283*9880d681SAndroid Build Coastguard Worker else
284*9880d681SAndroid Build Coastguard Worker OS << "nullptr";
285*9880d681SAndroid Build Coastguard Worker
286*9880d681SAndroid Build Coastguard Worker OS << ")\n";
287*9880d681SAndroid Build Coastguard Worker }
288*9880d681SAndroid Build Coastguard Worker OS << "#endif // OPTION\n";
289*9880d681SAndroid Build Coastguard Worker }
290*9880d681SAndroid Build Coastguard Worker } // end namespace llvm
291