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