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