summaryrefslogtreecommitdiffstats
path: root/clang/utils/TableGen/OptParserEmitter.cpp
diff options
context:
space:
mode:
authorMichael J. Spencer <bigcheesegs@gmail.com>2012-10-22 22:13:48 +0000
committerMichael J. Spencer <bigcheesegs@gmail.com>2012-10-22 22:13:48 +0000
commit929fccd4761b3de9d6c651cc85799d4bbfd165b0 (patch)
treeba81d70746265516fbbef1bb9f00057257bcdb38 /clang/utils/TableGen/OptParserEmitter.cpp
parentdbeb0f0e0cdb0201d35635e72baed288e3021906 (diff)
downloadbcm5719-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.cpp81
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"));
OpenPOWER on IntegriCloud