brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.8 KiB · 45edde3 Raw
694 lines · cpp
1//===- OptionParserEmitter.cpp - Table Driven Command Option 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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Common/OptEmitter.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/ADT/SmallString.h"12#include "llvm/ADT/SmallVector.h"13#include "llvm/ADT/StringExtras.h"14#include "llvm/ADT/Twine.h"15#include "llvm/Option/OptTable.h"16#include "llvm/Support/InterleavedRange.h"17#include "llvm/Support/raw_ostream.h"18#include "llvm/TableGen/Record.h"19#include "llvm/TableGen/StringToOffsetTable.h"20#include "llvm/TableGen/TableGenBackend.h"21#include <cstring>22#include <map>23 24using namespace llvm;25 26static std::string getOptionName(const Record &R) {27  // Use the record name unless EnumName is defined.28  if (isa<UnsetInit>(R.getValueInit("EnumName")))29    return R.getName().str();30 31  return R.getValueAsString("EnumName").str();32}33 34static raw_ostream &writeStrTableOffset(raw_ostream &OS,35                                        const StringToOffsetTable &Table,36                                        llvm::StringRef Str) {37  OS << Table.GetStringOffset(Str) << " /* ";38  OS.write_escaped(Str);39  OS << " */";40  return OS;41}42 43static raw_ostream &writeCstring(raw_ostream &OS, llvm::StringRef Str) {44  OS << '"';45  OS.write_escaped(Str);46  OS << '"';47  return OS;48}49 50static std::string getOptionPrefixedName(const Record &R) {51  std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes");52  StringRef Name = R.getValueAsString("Name");53 54  if (Prefixes.empty())55    return Name.str();56 57  return (Prefixes[0] + Twine(Name)).str();58}59 60class MarshallingInfo {61public:62  static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";63  const Record &R;64  bool ShouldAlwaysEmit = false;65  StringRef MacroPrefix;66  StringRef KeyPath;67  StringRef DefaultValue;68  StringRef NormalizedValuesScope;69  StringRef ImpliedCheck;70  StringRef ImpliedValue;71  StringRef ShouldParse;72  StringRef Normalizer;73  StringRef Denormalizer;74  StringRef ValueMerger;75  StringRef ValueExtractor;76  int TableIndex = -1;77  std::vector<StringRef> Values;78  std::vector<StringRef> NormalizedValues;79  std::string ValueTableName;80 81  static size_t NextTableIndex;82 83  static constexpr const char *ValueTablePreamble = R"(84struct SimpleEnumValue {85  const char *Name;86  unsigned Value;87};88 89struct SimpleEnumValueTable {90  const SimpleEnumValue *Table;91  unsigned Size;92};93)";94 95  static constexpr const char *ValueTablesDecl =96      "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";97 98  MarshallingInfo(const Record &R) : R(R) {}99 100  std::string getMacroName() const {101    return (MacroPrefix + MarshallingInfo::MacroName).str();102  }103 104  void emit(raw_ostream &OS) const {105    OS << ShouldParse;106    OS << ", ";107    OS << ShouldAlwaysEmit;108    OS << ", ";109    OS << KeyPath;110    OS << ", ";111    emitScopedNormalizedValue(OS, DefaultValue);112    OS << ", ";113    OS << ImpliedCheck;114    OS << ", ";115    emitScopedNormalizedValue(OS, ImpliedValue);116    OS << ", ";117    OS << Normalizer;118    OS << ", ";119    OS << Denormalizer;120    OS << ", ";121    OS << ValueMerger;122    OS << ", ";123    OS << ValueExtractor;124    OS << ", ";125    OS << TableIndex;126  }127 128  std::optional<StringRef> emitValueTable(raw_ostream &OS) const {129    if (TableIndex == -1)130      return {};131    OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";132    for (unsigned I = 0, E = Values.size(); I != E; ++I) {133      OS << "{";134      writeCstring(OS, Values[I]);135      OS << ",";136      OS << "static_cast<unsigned>(";137      emitScopedNormalizedValue(OS, NormalizedValues[I]);138      OS << ")},";139    }140    OS << "};\n";141    return StringRef(ValueTableName);142  }143 144private:145  void emitScopedNormalizedValue(raw_ostream &OS,146                                 StringRef NormalizedValue) const {147    if (!NormalizedValuesScope.empty())148      OS << NormalizedValuesScope << "::";149    OS << NormalizedValue;150  }151};152 153size_t MarshallingInfo::NextTableIndex = 0;154 155static MarshallingInfo createMarshallingInfo(const Record &R) {156  assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&157         !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&158         !isa<UnsetInit>(R.getValueInit("ValueMerger")) &&159         "MarshallingInfo must have a provide a keypath, default value and a "160         "value merger");161 162  MarshallingInfo Ret(R);163 164  Ret.ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");165  Ret.MacroPrefix = R.getValueAsString("MacroPrefix");166  Ret.KeyPath = R.getValueAsString("KeyPath");167  Ret.DefaultValue = R.getValueAsString("DefaultValue");168  Ret.NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");169  Ret.ImpliedCheck = R.getValueAsString("ImpliedCheck");170  Ret.ImpliedValue =171      R.getValueAsOptionalString("ImpliedValue").value_or(Ret.DefaultValue);172 173  Ret.ShouldParse = R.getValueAsString("ShouldParse");174  Ret.Normalizer = R.getValueAsString("Normalizer");175  Ret.Denormalizer = R.getValueAsString("Denormalizer");176  Ret.ValueMerger = R.getValueAsString("ValueMerger");177  Ret.ValueExtractor = R.getValueAsString("ValueExtractor");178 179  if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {180    assert(!isa<UnsetInit>(R.getValueInit("Values")) &&181           "Cannot provide normalized values for value-less options");182    Ret.TableIndex = MarshallingInfo::NextTableIndex++;183    Ret.NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");184    Ret.Values.reserve(Ret.NormalizedValues.size());185    Ret.ValueTableName = getOptionName(R) + "ValueTable";186 187    StringRef ValuesStr = R.getValueAsString("Values");188    for (;;) {189      size_t Idx = ValuesStr.find(',');190      if (Idx == StringRef::npos)191        break;192      if (Idx > 0)193        Ret.Values.push_back(ValuesStr.slice(0, Idx));194      ValuesStr = ValuesStr.substr(Idx + 1);195    }196    if (!ValuesStr.empty())197      Ret.Values.push_back(ValuesStr);198 199    assert(Ret.Values.size() == Ret.NormalizedValues.size() &&200           "The number of normalized values doesn't match the number of "201           "values");202  }203 204  return Ret;205}206 207static void emitHelpTextsForVariants(208    raw_ostream &OS, std::vector<std::pair<std::vector<std::string>, StringRef>>209                         HelpTextsForVariants) {210  // OptTable must be constexpr so it uses std::arrays with these capacities.211  const unsigned MaxVisibilityPerHelp = 2;212  const unsigned MaxVisibilityHelp = 1;213 214  assert(HelpTextsForVariants.size() <= MaxVisibilityHelp &&215         "Too many help text variants to store in "216         "OptTable::HelpTextsForVariants");217 218  // This function must initialise any unused elements of those arrays.219  for (auto [Visibilities, _] : HelpTextsForVariants)220    while (Visibilities.size() < MaxVisibilityPerHelp)221      Visibilities.push_back("0");222 223  while (HelpTextsForVariants.size() < MaxVisibilityHelp)224    HelpTextsForVariants.push_back(225        {std::vector<std::string>(MaxVisibilityPerHelp, "0"), ""});226 227  OS << ", (std::array<std::pair<std::array<unsigned, " << MaxVisibilityPerHelp228     << ">, const char*>, " << MaxVisibilityHelp << ">{{ ";229 230  auto VisibilityHelpEnd = HelpTextsForVariants.cend();231  for (auto VisibilityHelp = HelpTextsForVariants.cbegin();232       VisibilityHelp != VisibilityHelpEnd; ++VisibilityHelp) {233    auto [Visibilities, Help] = *VisibilityHelp;234 235    assert(Visibilities.size() <= MaxVisibilityPerHelp &&236           "Too many visibilities to store in an "237           "OptTable::HelpTextsForVariants entry");238    OS << "{std::array<unsigned, " << MaxVisibilityPerHelp << ">{{"239       << llvm::interleaved(Visibilities) << "}}, ";240 241    if (Help.size())242      writeCstring(OS, Help);243    else244      OS << "nullptr";245    OS << "}";246 247    if (std::next(VisibilityHelp) != VisibilityHelpEnd)248      OS << ", ";249  }250  OS << " }})";251}252 253/// OptionParserEmitter - This tablegen backend takes an input .td file254/// describing a list of options and emits a data structure for parsing and255/// working with those options when given an input command line.256static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {257  // Get the option groups and options.258  ArrayRef<const Record *> Groups =259      Records.getAllDerivedDefinitions("OptionGroup");260  std::vector<const Record *> Opts = Records.getAllDerivedDefinitions("Option");261  llvm::sort(Opts, IsOptionRecordsLess);262 263  std::vector<const Record *> SubCommands =264      Records.getAllDerivedDefinitions("SubCommand");265 266  emitSourceFileHeader("Option Parsing Definitions", OS);267 268  // Generate prefix groups.269  using PrefixKeyT = SmallVector<SmallString<2>, 2>;270  using PrefixesT = std::map<PrefixKeyT, unsigned>;271  PrefixesT Prefixes;272  Prefixes.try_emplace(PrefixKeyT(), 0);273  for (const Record &R : llvm::make_pointee_range(Opts)) {274    std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");275    PrefixKeyT PrefixKey(RPrefixes.begin(), RPrefixes.end());276    Prefixes.try_emplace(PrefixKey, 0);277  }278 279  // Generate sub command groups.280  using SubCommandKeyT = SmallVector<StringRef, 2>;281  using SubCommandIDsT = std::map<SubCommandKeyT, unsigned>;282  SubCommandIDsT SubCommandIDs;283 284  auto PrintSubCommandIdsOffset = [&SubCommandIDs, &OS](const Record &R) {285    if (R.getValue("SubCommands") != nullptr) {286      std::vector<const Record *> SubCommands =287          R.getValueAsListOfDefs("SubCommands");288      SubCommandKeyT SubCommandKey;289      for (const auto &SubCommand : SubCommands)290        SubCommandKey.push_back(SubCommand->getName());291      OS << SubCommandIDs[SubCommandKey];292    } else {293      // The option SubCommandIDsOffset (for default top level toolname is 0).294      OS << " 0";295    }296  };297 298  SubCommandIDs.try_emplace(SubCommandKeyT(), 0);299  for (const Record &R : llvm::make_pointee_range(Opts)) {300    std::vector<const Record *> RSubCommands =301        R.getValueAsListOfDefs("SubCommands");302    SubCommandKeyT SubCommandKey;303    for (const auto &SubCommand : RSubCommands)304      SubCommandKey.push_back(SubCommand->getName());305    SubCommandIDs.try_emplace(SubCommandKey, 0);306  }307 308  DenseSet<StringRef> PrefixesUnionSet;309  for (const auto &[Prefix, _] : Prefixes)310    PrefixesUnionSet.insert_range(Prefix);311  SmallVector<StringRef> PrefixesUnion(PrefixesUnionSet.begin(),312                                       PrefixesUnionSet.end());313  array_pod_sort(PrefixesUnion.begin(), PrefixesUnion.end());314 315  llvm::StringToOffsetTable Table;316  // We can add all the prefixes via the union.317  for (const auto &Prefix : PrefixesUnion)318    Table.GetOrAddStringOffset(Prefix);319  for (const Record &R : llvm::make_pointee_range(Groups))320    Table.GetOrAddStringOffset(R.getValueAsString("Name"));321  for (const Record &R : llvm::make_pointee_range(Opts))322    Table.GetOrAddStringOffset(getOptionPrefixedName(R));323 324  // Dump string table.325  OS << "/////////\n";326  OS << "// String table\n\n";327  OS << "#ifdef OPTTABLE_STR_TABLE_CODE\n";328  Table.EmitStringTableDef(OS, "OptionStrTable");329  OS << "#endif // OPTTABLE_STR_TABLE_CODE\n\n";330 331  // Dump prefixes.332  OS << "/////////\n";333  OS << "// Prefixes\n\n";334  OS << "#ifdef OPTTABLE_PREFIXES_TABLE_CODE\n";335  OS << "static constexpr llvm::StringTable::Offset OptionPrefixesTable[] = "336        "{\n";337  {338    // Ensure the first prefix set is always empty.339    assert(!Prefixes.empty() &&340           "We should always emit an empty set of prefixes");341    assert(Prefixes.begin()->first.empty() &&342           "First prefix set should always be empty");343    llvm::ListSeparator Sep(",\n");344    unsigned CurIndex = 0;345    for (auto &[Prefix, PrefixIndex] : Prefixes) {346      // First emit the number of prefix strings in this list of prefixes.347      OS << Sep << "  " << Prefix.size() << " /* prefixes */";348      PrefixIndex = CurIndex;349      assert((CurIndex == 0 || !Prefix.empty()) &&350             "Only first prefix set should be empty!");351      for (const auto &PrefixKey : Prefix)352        OS << ", " << *Table.GetStringOffset(PrefixKey) << " /* '" << PrefixKey353           << "' */";354      CurIndex += Prefix.size() + 1;355    }356  }357  OS << "\n};\n";358  OS << "#endif // OPTTABLE_PREFIXES_TABLE_CODE\n\n";359 360  // Dump subcommand IDs.361  OS << "/////////";362  OS << "// SubCommand IDs\n\n";363  OS << "#ifdef OPTTABLE_SUBCOMMAND_IDS_TABLE_CODE\n";364  OS << "static constexpr unsigned OptionSubCommandIDsTable[] = {\n";365  {366    // Ensure the first subcommand set is always empty.367    assert(!SubCommandIDs.empty() &&368           "We should always emit an empty set of subcommands");369    assert(SubCommandIDs.begin()->first.empty() &&370           "First subcommand set should always be empty");371    llvm::ListSeparator Sep(",\n");372    unsigned CurIndex = 0;373    for (auto &[SubCommand, SubCommandIndex] : SubCommandIDs) {374      // First emit the number of subcommand strings in this list of375      // subcommands.376      OS << Sep << "  " << SubCommand.size() << " /* subcommands */";377      SubCommandIndex = CurIndex;378      assert((CurIndex == 0 || !SubCommand.empty()) &&379             "Only first subcommand set should be empty!");380      for (const auto &SubCommandKey : SubCommand) {381        auto It = llvm::find_if(SubCommands, [&](const Record *R) {382          return R->getName() == SubCommandKey;383        });384        assert(It != SubCommands.end() && "SubCommand not found");385        OS << ", " << std::distance(SubCommands.begin(), It) << " /* '"386           << SubCommandKey << "' */";387      }388      CurIndex += SubCommand.size() + 1;389    }390  }391  OS << "\n};\n";392  OS << "#endif // OPTTABLE_SUBCOMMAND_IDS_TABLE_CODE\n\n";393 394  // Dump prefixes union.395  OS << "/////////\n";396  OS << "// Prefix Union\n\n";397  OS << "#ifdef OPTTABLE_PREFIXES_UNION_CODE\n";398  OS << "static constexpr llvm::StringTable::Offset OptionPrefixesUnion[] = "399        "{\n";400  {401    llvm::ListSeparator Sep(", ");402    for (auto Prefix : PrefixesUnion)403      OS << Sep << "  " << *Table.GetStringOffset(Prefix) << " /* '" << Prefix404         << "' */";405  }406  OS << "\n};\n";407  OS << "#endif // OPTTABLE_PREFIXES_UNION_CODE\n\n";408 409  // Dump groups.410  OS << "/////////\n";411  OS << "// ValuesCode\n\n";412  OS << "#ifdef OPTTABLE_VALUES_CODE\n";413  for (const Record &R : llvm::make_pointee_range(Opts)) {414    // The option values, if any;415    if (!isa<UnsetInit>(R.getValueInit("ValuesCode"))) {416      assert(isa<UnsetInit>(R.getValueInit("Values")) &&417             "Cannot choose between Values and ValuesCode");418      OS << "#define VALUES_CODE " << getOptionName(R) << "_Values\n";419      OS << R.getValueAsString("ValuesCode") << "\n";420      OS << "#undef VALUES_CODE\n";421    }422  }423  OS << "#endif\n";424 425  OS << "/////////\n";426  OS << "// Groups\n\n";427  OS << "#ifdef OPTION\n";428  for (const Record &R : llvm::make_pointee_range(Groups)) {429    // Start a single option entry.430    OS << "OPTION(";431 432    // A zero prefix offset corresponds to an empty set of prefixes.433    OS << "0 /* no prefixes */";434 435    // The option string offset.436    OS << ", ";437    writeStrTableOffset(OS, Table, R.getValueAsString("Name"));438 439    // The option identifier name.440    OS << ", " << getOptionName(R);441 442    // The option kind.443    OS << ", Group";444 445    // The containing option group (if any).446    OS << ", ";447    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))448      OS << getOptionName(*DI->getDef());449    else450      OS << "INVALID";451 452    // The other option arguments (unused for groups).453    OS << ", INVALID, nullptr, 0, 0, 0";454 455    // The option help text.456    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {457      OS << ",\n";458      OS << "       ";459      writeCstring(OS, R.getValueAsString("HelpText"));460    } else {461      OS << ", nullptr";462    }463 464    // Not using Visibility specific text for group help.465    emitHelpTextsForVariants(OS, {});466 467    // The option meta-variable name (unused).468    OS << ", nullptr";469 470    // The option Values (unused for groups).471    OS << ", nullptr";472 473    // The option SubCommandIDsOffset.474    OS << ", ";475    PrintSubCommandIdsOffset(R);476    OS << ")\n";477  }478  OS << "\n";479 480  OS << "//////////\n";481  OS << "// Options\n\n";482 483  auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {484    // The option prefix;485    std::vector<StringRef> RPrefixes = R.getValueAsListOfStrings("Prefixes");486    OS << Prefixes[PrefixKeyT(RPrefixes.begin(), RPrefixes.end())] << ", ";487 488    // The option prefixed name.489    writeStrTableOffset(OS, Table, getOptionPrefixedName(R));490 491    // The option identifier name.492    OS << ", " << getOptionName(R);493 494    // The option kind.495    OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");496 497    // The containing option group (if any).498    OS << ", ";499    const ListInit *GroupFlags = nullptr;500    const ListInit *GroupVis = nullptr;501    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {502      GroupFlags = DI->getDef()->getValueAsListInit("Flags");503      GroupVis = DI->getDef()->getValueAsListInit("Visibility");504      OS << getOptionName(*DI->getDef());505    } else {506      OS << "INVALID";507    }508 509    // The option alias (if any).510    OS << ", ";511    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))512      OS << getOptionName(*DI->getDef());513    else514      OS << "INVALID";515 516    // The option alias arguments (if any).517    // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]518    // would become "foo\0bar\0". Note that the compiler adds an implicit519    // terminating \0 at the end.520    OS << ", ";521    std::vector<StringRef> AliasArgs = R.getValueAsListOfStrings("AliasArgs");522    if (AliasArgs.size() == 0) {523      OS << "nullptr";524    } else {525      OS << "\"";526      for (StringRef AliasArg : AliasArgs)527        OS << AliasArg << "\\0";528      OS << "\"";529    }530 531    // "Flags" for the option, such as HelpHidden and Render*532    OS << ", ";533    int NumFlags = 0;534    const ListInit *LI = R.getValueAsListInit("Flags");535    for (const Init *I : *LI)536      OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();537    if (GroupFlags) {538      for (const Init *I : *GroupFlags)539        OS << (NumFlags++ ? " | " : "")540           << cast<DefInit>(I)->getDef()->getName();541    }542    if (NumFlags == 0)543      OS << '0';544 545    // Option visibility, for sharing options between drivers.546    OS << ", ";547    int NumVisFlags = 0;548    LI = R.getValueAsListInit("Visibility");549    for (const Init *I : *LI)550      OS << (NumVisFlags++ ? " | " : "")551         << cast<DefInit>(I)->getDef()->getName();552    if (GroupVis) {553      for (const Init *I : *GroupVis)554        OS << (NumVisFlags++ ? " | " : "")555           << cast<DefInit>(I)->getDef()->getName();556    }557    if (NumVisFlags == 0)558      OS << '0';559 560    // The option parameter field.561    OS << ", " << R.getValueAsInt("NumArgs");562 563    // The option help text.564    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {565      OS << ",\n";566      OS << "       ";567      writeCstring(OS, R.getValueAsString("HelpText"));568    } else {569      OS << ", nullptr";570    }571 572    std::vector<std::pair<std::vector<std::string>, StringRef>>573        HelpTextsForVariants;574    for (const Record *VisibilityHelp :575         R.getValueAsListOfDefs("HelpTextsForVariants")) {576      ArrayRef<const Init *> Visibilities =577          VisibilityHelp->getValueAsListInit("Visibilities")->getElements();578 579      std::vector<std::string> VisibilityNames;580      for (const Init *Visibility : Visibilities)581        VisibilityNames.push_back(Visibility->getAsUnquotedString());582 583      HelpTextsForVariants.emplace_back(584          VisibilityNames, VisibilityHelp->getValueAsString("Text"));585    }586    emitHelpTextsForVariants(OS, std::move(HelpTextsForVariants));587 588    // The option meta-variable name.589    OS << ", ";590    if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))591      writeCstring(OS, R.getValueAsString("MetaVarName"));592    else593      OS << "nullptr";594 595    // The option Values. Used for shell autocompletion.596    OS << ", ";597    if (!isa<UnsetInit>(R.getValueInit("Values")))598      writeCstring(OS, R.getValueAsString("Values"));599    else if (!isa<UnsetInit>(R.getValueInit("ValuesCode")))600      OS << getOptionName(R) << "_Values";601    else602      OS << "nullptr";603 604    // The option SubCommandIDsOffset.605    OS << ", ";606    PrintSubCommandIdsOffset(R);607  };608 609  auto IsMarshallingOption = [](const Record &R) {610    return !isa<UnsetInit>(R.getValueInit("KeyPath")) &&611           !R.getValueAsString("KeyPath").empty();612  };613 614  std::vector<const Record *> OptsWithMarshalling;615  for (const Record &R : llvm::make_pointee_range(Opts)) {616    // Start a single option entry.617    OS << "OPTION(";618    WriteOptRecordFields(OS, R);619    OS << ")\n";620    if (IsMarshallingOption(R))621      OptsWithMarshalling.push_back(&R);622  }623  OS << "#endif // OPTION\n";624 625  auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) {626    unsigned AID = (*A)->getID();627    unsigned BID = (*B)->getID();628 629    if (AID < BID)630      return -1;631    if (AID > BID)632      return 1;633    return 0;634  };635  // The RecordKeeper stores records (options) in lexicographical order, and we636  // have reordered the options again when generating prefix groups. We need to637  // restore the original definition order of options with marshalling to honor638  // the topology of the dependency graph implied by `DefaultAnyOf`.639  array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),640                 CmpMarshallingOpts);641 642  std::vector<MarshallingInfo> MarshallingInfos;643  MarshallingInfos.reserve(OptsWithMarshalling.size());644  for (const auto *R : OptsWithMarshalling)645    MarshallingInfos.push_back(createMarshallingInfo(*R));646 647  for (const auto &MI : MarshallingInfos) {648    OS << "#ifdef " << MI.getMacroName() << "\n";649    OS << MI.getMacroName() << "(";650    WriteOptRecordFields(OS, MI.R);651    OS << ", ";652    MI.emit(OS);653    OS << ")\n";654    OS << "#endif // " << MI.getMacroName() << "\n";655  }656 657  OS << "\n";658  OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";659  OS << "\n";660  OS << MarshallingInfo::ValueTablePreamble;661  std::vector<StringRef> ValueTableNames;662  for (const auto &MI : MarshallingInfos)663    if (auto MaybeValueTableName = MI.emitValueTable(OS))664      ValueTableNames.push_back(*MaybeValueTableName);665 666  OS << MarshallingInfo::ValueTablesDecl << "{";667  for (auto ValueTableName : ValueTableNames)668    OS << "{" << ValueTableName << ", std::size(" << ValueTableName << ")},\n";669  OS << "};\n";670  OS << "static const unsigned SimpleEnumValueTablesSize = "671        "std::size(SimpleEnumValueTables);\n";672 673  OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";674  OS << "\n";675  OS << "/////////\n";676  OS << "\n// SubCommands\n\n";677  OS << "#ifdef OPTTABLE_SUBCOMMANDS_CODE\n";678  OS << "static constexpr llvm::opt::OptTable::SubCommand OptionSubCommands[] "679        "= "680        "{\n";681  for (const Record *SubCommand : SubCommands) {682    OS << "  { \"" << SubCommand->getValueAsString("Name") << "\", ";683    OS << "\"" << SubCommand->getValueAsString("HelpText") << "\", ";684    OS << "\"" << SubCommand->getValueAsString("Usage") << "\" },\n";685  }686  OS << "};\n";687  OS << "#endif // OPTTABLE_SUBCOMMANDS_CODE\n\n";688 689  OS << "\n";690}691 692static TableGen::Emitter::Opt X("gen-opt-parser-defs", emitOptionParser,693                                "Generate option definitions");694