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