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/TableGen/Record.h" 14 #include "llvm/TableGen/TableGenBackend.h" 15 #include <cctype> 16 #include <cstring> 17 #include <map> 18 19 using namespace llvm; 20 21 static const std::string getOptionName(const Record &R) { 22 // Use the record name unless EnumName is defined. 23 if (isa<UnsetInit>(R.getValueInit("EnumName"))) 24 return R.getName(); 25 26 return R.getValueAsString("EnumName"); 27 } 28 29 static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) { 30 OS << '"'; 31 OS.write_escaped(Str); 32 OS << '"'; 33 return OS; 34 } 35 36 /// OptParserEmitter - This tablegen backend takes an input .td file 37 /// describing a list of options and emits a data structure for parsing and 38 /// working with those options when given an input command line. 39 namespace llvm { 40 void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { 41 // Get the option groups and options. 42 const std::vector<Record*> &Groups = 43 Records.getAllDerivedDefinitions("OptionGroup"); 44 std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option"); 45 46 emitSourceFileHeader("Option Parsing Definitions", OS); 47 48 array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords); 49 // Generate prefix groups. 50 typedef SmallVector<SmallString<2>, 2> PrefixKeyT; 51 typedef std::map<PrefixKeyT, std::string> PrefixesT; 52 PrefixesT Prefixes; 53 Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0")); 54 unsigned CurPrefix = 0; 55 for (unsigned i = 0, e = Opts.size(); i != e; ++i) { 56 const Record &R = *Opts[i]; 57 std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes"); 58 PrefixKeyT prfkey(prf.begin(), prf.end()); 59 unsigned NewPrefix = CurPrefix + 1; 60 if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") + 61 Twine(NewPrefix)).str())).second) 62 CurPrefix = NewPrefix; 63 } 64 65 // Dump prefixes. 66 67 OS << "/////////\n"; 68 OS << "// Prefixes\n\n"; 69 OS << "#ifdef PREFIX\n"; 70 OS << "#define COMMA ,\n"; 71 for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end(); 72 I != E; ++I) { 73 OS << "PREFIX("; 74 75 // Prefix name. 76 OS << I->second; 77 78 // Prefix values. 79 OS << ", {"; 80 for (PrefixKeyT::const_iterator PI = I->first.begin(), 81 PE = I->first.end(); PI != PE; ++PI) { 82 OS << "\"" << *PI << "\" COMMA "; 83 } 84 OS << "nullptr})\n"; 85 } 86 OS << "#undef COMMA\n"; 87 OS << "#endif // PREFIX\n\n"; 88 89 OS << "/////////\n"; 90 OS << "// Groups\n\n"; 91 OS << "#ifdef OPTION\n"; 92 for (unsigned i = 0, e = Groups.size(); i != e; ++i) { 93 const Record &R = *Groups[i]; 94 95 // Start a single option entry. 96 OS << "OPTION("; 97 98 // The option prefix; 99 OS << "nullptr"; 100 101 // The option string. 102 OS << ", \"" << R.getValueAsString("Name") << '"'; 103 104 // The option identifier name. 105 OS << ", "<< getOptionName(R); 106 107 // The option kind. 108 OS << ", Group"; 109 110 // The containing option group (if any). 111 OS << ", "; 112 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) 113 OS << getOptionName(*DI->getDef()); 114 else 115 OS << "INVALID"; 116 117 // The other option arguments (unused for groups). 118 OS << ", INVALID, nullptr, 0, 0"; 119 120 // The option help text. 121 if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { 122 OS << ",\n"; 123 OS << " "; 124 write_cstring(OS, R.getValueAsString("HelpText")); 125 } else 126 OS << ", nullptr"; 127 128 // The option meta-variable name (unused). 129 OS << ", nullptr"; 130 131 // The option Values (unused for groups). 132 OS << ", nullptr)\n"; 133 } 134 OS << "\n"; 135 136 OS << "//////////\n"; 137 OS << "// Options\n\n"; 138 for (unsigned i = 0, e = Opts.size(); i != e; ++i) { 139 const Record &R = *Opts[i]; 140 141 // Start a single option entry. 142 OS << "OPTION("; 143 144 // The option prefix; 145 std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes"); 146 OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", "; 147 148 // The option string. 149 write_cstring(OS, R.getValueAsString("Name")); 150 151 // The option identifier name. 152 OS << ", "<< getOptionName(R); 153 154 // The option kind. 155 OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name"); 156 157 // The containing option group (if any). 158 OS << ", "; 159 const ListInit *GroupFlags = nullptr; 160 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) { 161 GroupFlags = DI->getDef()->getValueAsListInit("Flags"); 162 OS << getOptionName(*DI->getDef()); 163 } else 164 OS << "INVALID"; 165 166 // The option alias (if any). 167 OS << ", "; 168 if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias"))) 169 OS << getOptionName(*DI->getDef()); 170 else 171 OS << "INVALID"; 172 173 // The option alias arguments (if any). 174 // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"] 175 // would become "foo\0bar\0". Note that the compiler adds an implicit 176 // terminating \0 at the end. 177 OS << ", "; 178 std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs"); 179 if (AliasArgs.size() == 0) { 180 OS << "nullptr"; 181 } else { 182 OS << "\""; 183 for (size_t i = 0, e = AliasArgs.size(); i != e; ++i) 184 OS << AliasArgs[i] << "\\0"; 185 OS << "\""; 186 } 187 188 // The option flags. 189 OS << ", "; 190 int NumFlags = 0; 191 const ListInit *LI = R.getValueAsListInit("Flags"); 192 for (Init *I : *LI) 193 OS << (NumFlags++ ? " | " : "") 194 << cast<DefInit>(I)->getDef()->getName(); 195 if (GroupFlags) { 196 for (Init *I : *GroupFlags) 197 OS << (NumFlags++ ? " | " : "") 198 << cast<DefInit>(I)->getDef()->getName(); 199 } 200 if (NumFlags == 0) 201 OS << '0'; 202 203 // The option parameter field. 204 OS << ", " << R.getValueAsInt("NumArgs"); 205 206 // The option help text. 207 if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { 208 OS << ",\n"; 209 OS << " "; 210 write_cstring(OS, R.getValueAsString("HelpText")); 211 } else 212 OS << ", nullptr"; 213 214 // The option meta-variable name. 215 OS << ", "; 216 if (!isa<UnsetInit>(R.getValueInit("MetaVarName"))) 217 write_cstring(OS, R.getValueAsString("MetaVarName")); 218 else 219 OS << "nullptr"; 220 221 // The option Values. Used for shell autocompletion. 222 OS << ", "; 223 if (!isa<UnsetInit>(R.getValueInit("Values"))) 224 write_cstring(OS, R.getValueAsString("Values")); 225 else 226 OS << "nullptr"; 227 228 OS << ")\n"; 229 } 230 OS << "#endif // OPTION\n"; 231 232 OS << "\n"; 233 OS << "#ifdef OPTTABLE_ARG_INIT\n"; 234 OS << "//////////\n"; 235 OS << "// Option Values\n\n"; 236 for (unsigned I = 0, E = Opts.size(); I != E; ++I) { 237 const Record &R = *Opts[I]; 238 if (isa<UnsetInit>(R.getValueInit("ValuesCode"))) 239 continue; 240 OS << "{\n"; 241 OS << "bool ValuesWereAdded;\n"; 242 OS << R.getValueAsString("ValuesCode"); 243 OS << "\n"; 244 for (std::string S : R.getValueAsListOfStrings("Prefixes")) { 245 OS << "ValuesWereAdded = Opt.addValues("; 246 S += R.getValueAsString("Name"); 247 write_cstring(OS, S); 248 OS << ", Values);\n"; 249 OS << "(void)ValuesWereAdded;\n"; 250 OS << "assert(ValuesWereAdded && \"Couldn't add values to " 251 "OptTable!\");\n"; 252 } 253 OS << "}\n"; 254 } 255 OS << "\n"; 256 OS << "#endif // OPTTABLE_ARG_INIT\n"; 257 } 258 } // end namespace llvm 259