diff options
author | Michael J. Spencer <bigcheesegs@gmail.com> | 2012-10-22 22:13:48 +0000 |
---|---|---|
committer | Michael J. Spencer <bigcheesegs@gmail.com> | 2012-10-22 22:13:48 +0000 |
commit | 929fccd4761b3de9d6c651cc85799d4bbfd165b0 (patch) | |
tree | ba81d70746265516fbbef1bb9f00057257bcdb38 /clang/utils/TableGen/OptParserEmitter.cpp | |
parent | dbeb0f0e0cdb0201d35635e72baed288e3021906 (diff) | |
download | bcm5719-llvm-929fccd4761b3de9d6c651cc85799d4bbfd165b0.tar.gz bcm5719-llvm-929fccd4761b3de9d6c651cc85799d4bbfd165b0.zip |
[Options] Add prefixes to options.
Each option has a set of prefixes. When matching an argument such as
-funroll-loops. First the leading - is removed as it is a prefix. Then
a lower_bound search for "funroll-loops" is done against the option table by
option name. From there each option prefix + option name combination is tested
against the argument.
This allows us to support Microsoft style options where both / and - are valid
prefixes. It also simplifies the cases we already have where options come in
both - and -- forms. Almost every option for gnu-ld happens to have this form.
llvm-svn: 166444
Diffstat (limited to 'clang/utils/TableGen/OptParserEmitter.cpp')
-rw-r--r-- | clang/utils/TableGen/OptParserEmitter.cpp | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/clang/utils/TableGen/OptParserEmitter.cpp b/clang/utils/TableGen/OptParserEmitter.cpp index 9b4bc29cf41..f095a28b4a7 100644 --- a/clang/utils/TableGen/OptParserEmitter.cpp +++ b/clang/utils/TableGen/OptParserEmitter.cpp @@ -7,9 +7,15 @@ // //===----------------------------------------------------------------------===// +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" + +#include <map> + using namespace llvm; static int StrCmpOptionName(const char *A, const char *B) { @@ -47,10 +53,32 @@ static int CompareOptionRecords(const void *Av, const void *Bv) { B->getValueAsString("Name").c_str())) return Cmp; + if (!ASent) { + std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes"); + std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes"); + + for (std::vector<std::string>::const_iterator APre = APrefixes.begin(), + AEPre = APrefixes.end(), + BPre = BPrefixes.begin(), + BEPre = BPrefixes.end(); + APre != AEPre && + BPre != BEPre; + ++APre, ++BPre) { + if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str())) + return Cmp; + } + } + // Then by the kind precedence; int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence"); int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence"); - assert(APrec != BPrec && "Options are equivalent!"); + if (APrec == BPrec && + A->getValueAsListOfStrings("Prefixes") == + B->getValueAsListOfStrings("Prefixes")) { + PrintError(A->getLoc(), Twine("Option is equivilent to")); + PrintError(B->getLoc(), Twine("Other defined here")); + throw "Eqivilant Options found."; + } return APrec < BPrec ? -1 : 1; } @@ -86,6 +114,48 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS, bool GenDefs) { array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords); if (GenDefs) { + // Generate prefix groups. + typedef SmallVector<SmallString<2>, 2> PrefixKeyT; + typedef std::map<PrefixKeyT, std::string> PrefixesT; + PrefixesT Prefixes; + Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0")); + unsigned CurPrefix = 0; + for (unsigned i = 0, e = Opts.size(); i != e; ++i) { + const Record &R = *Opts[i]; + std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); + PrefixKeyT prfkey(prf.begin(), prf.end()); + unsigned NewPrefix = CurPrefix + 1; + if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") + + Twine(NewPrefix)).str())).second) + CurPrefix = NewPrefix; + } + + OS << "#ifndef PREFIX\n"; + OS << "#error \"Define PREFIX prior to including this file!\"\n"; + OS << "#endif\n\n"; + + // Dump prefixes. + OS << "/////////\n"; + OS << "// Prefixes\n\n"; + OS << "#define COMMA ,\n"; + for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end(); + I != E; ++I) { + OS << "PREFIX("; + + // Prefix name. + OS << I->second; + + // Prefix values. + OS << ", {"; + for (PrefixKeyT::const_iterator PI = I->first.begin(), + PE = I->first.end(); PI != PE; ++PI) { + OS << "\"" << *PI << "\" COMMA "; + } + OS << "0})\n"; + } + OS << "#undef COMMA\n"; + OS << "\n"; + OS << "#ifndef OPTION\n"; OS << "#error \"Define OPTION prior to including this file!\"\n"; OS << "#endif\n\n"; @@ -98,8 +168,11 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS, bool GenDefs) { // Start a single option entry. OS << "OPTION("; + // The option prefix; + OS << "0"; + // The option string. - OS << '"' << R.getValueAsString("Name") << '"'; + OS << ", \"" << R.getValueAsString("Name") << '"'; // The option identifier name. OS << ", "<< getOptionName(R); @@ -138,6 +211,10 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS, bool GenDefs) { // Start a single option entry. OS << "OPTION("; + // The option prefix; + std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); + OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", "; + // The option string. write_cstring(OS, R.getValueAsString("Name")); |