aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-11-18 21:29:51 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-11-18 21:29:51 +0000
commit2d6a8fb827e3c83ab2271dfb05c7c73902859297 (patch)
tree72e7afcf9f8ac16add00de9c09b20aae9ab3a237
parent8f16e02fc95c9b197d38bcd681f2612d36ed5c11 (diff)
TableGen: Add initial backend for clang Driver's option parsing.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89245 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--utils/TableGen/OptParserEmitter.cpp192
-rw-r--r--utils/TableGen/OptParserEmitter.h34
-rw-r--r--utils/TableGen/TableGen.cpp32
3 files changed, 248 insertions, 10 deletions
diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp
new file mode 100644
index 0000000000..a09ba083f3
--- /dev/null
+++ b/utils/TableGen/OptParserEmitter.cpp
@@ -0,0 +1,192 @@
+//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OptParserEmitter.h"
+#include "Record.h"
+#include "llvm/ADT/STLExtras.h"
+using namespace llvm;
+
+static int StrCmpOptionName(const char *A, const char *B) {
+ char a = *A, b = *B;
+ while (a == b) {
+ if (a == '\0')
+ return 0;
+
+ a = *++A;
+ b = *++B;
+ }
+
+ if (a == '\0') // A is a prefix of B.
+ return 1;
+ if (b == '\0') // B is a prefix of A.
+ return -1;
+
+ // Otherwise lexicographic.
+ return (a < b) ? -1 : 1;
+}
+
+static int CompareOptionRecords(const void *Av, const void *Bv) {
+ const Record *A = *(Record**) Av;
+ const Record *B = *(Record**) Bv;
+
+ // Compare options by name first.
+ if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
+ B->getValueAsString("Name").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!");
+ return APrec < BPrec ? -1 : 1;
+}
+
+static const std::string getOptionName(const Record &R) {
+ // Use the record name unless EnumName is defined.
+ if (dynamic_cast<UnsetInit*>(R.getValueInit("EnumName")))
+ return R.getName();
+
+ return R.getValueAsString("EnumName");
+}
+
+static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
+ OS << '"';
+ OS.write_escaped(Str);
+ OS << '"';
+ return OS;
+}
+
+void OptParserEmitter::run(raw_ostream &OS) {
+ // Get the option groups and options.
+ const std::vector<Record*> &Groups =
+ Records.getAllDerivedDefinitions("OptionGroup");
+ std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
+
+ if (GenDefs) {
+ OS << "\
+//=== TableGen'erated File - Option Parsing Definitions ---------*- C++ -*-===//\n \
+//\n\
+// Option Parsing Definitions\n\
+//\n\
+// Automatically generated file, do not edit!\n\
+//\n\
+//===----------------------------------------------------------------------===//\n";
+ } else {
+ OS << "\
+//=== TableGen'erated File - Option Parsing Table ---------------*- C++ -*-===//\n \
+//\n\
+// Option Parsing Definitions\n\
+//\n\
+// Automatically generated file, do not edit!\n\
+//\n\
+//===----------------------------------------------------------------------===//\n";
+ }
+ OS << "\n";
+
+ array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
+ if (GenDefs) {
+ OS << "#ifndef OPTION\n";
+ OS << "#error \"Define OPTION prior to including this file!\"\n";
+ OS << "#endif\n\n";
+
+ OS << "/////////\n";
+ OS << "// Groups\n\n";
+ for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
+ const Record &R = *Groups[i];
+
+ // Start a single option entry.
+ OS << "OPTION(";
+
+ // The option string.
+ OS << '"' << R.getValueAsString("Name") << '"';
+
+ // The option identifier name.
+ OS << ", "<< getOptionName(R);
+
+ // The option kind.
+ OS << ", Group";
+
+ // The containing option group (if any).
+ OS << ", ";
+ if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
+ OS << getOptionName(*DI->getDef());
+ else
+ OS << "INVALID";
+
+ // The other option arguments (unused for groups).
+ OS << ", INVALID, 0, 0, 0, 0)\n";
+ }
+ OS << "\n";
+
+ OS << "//////////\n";
+ OS << "// Options\n\n";
+ for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
+ const Record &R = *Opts[i];
+
+ // Start a single option entry.
+ OS << "OPTION(";
+
+ // The option string.
+ write_cstring(OS, R.getValueAsString("Name"));
+
+ // The option identifier name.
+ OS << ", "<< getOptionName(R);
+
+ // The option kind.
+ OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
+
+ // The containing option group (if any).
+ OS << ", ";
+ if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group")))
+ OS << getOptionName(*DI->getDef());
+ else
+ OS << "INVALID";
+
+ // The option alias (if any).
+ OS << ", ";
+ if (const DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Alias")))
+ OS << getOptionName(*DI->getDef());
+ else
+ OS << "INVALID";
+
+ // The option flags.
+ const ListInit *LI = R.getValueAsListInit("Flags");
+ if (LI->empty()) {
+ OS << ", 0";
+ } else {
+ OS << ", ";
+ for (unsigned i = 0, e = LI->size(); i != e; ++i) {
+ if (i)
+ OS << " | ";
+ OS << dynamic_cast<DefInit*>(LI->getElement(i))->getDef()->getName();
+ }
+ }
+
+ // The option parameter field.
+ OS << ", " << R.getValueAsInt("NumArgs");
+
+ // The option help text.
+ if (!dynamic_cast<UnsetInit*>(R.getValueInit("HelpText"))) {
+ OS << ",\n";
+ OS << " ";
+ write_cstring(OS, R.getValueAsString("HelpText"));
+ } else
+ OS << ", 0";
+
+ // The option meta-variable name.
+ OS << ", ";
+ if (!dynamic_cast<UnsetInit*>(R.getValueInit("MetaVarName")))
+ write_cstring(OS, R.getValueAsString("MetaVarName"));
+ else
+ OS << "0";
+
+ OS << ")\n";
+ }
+ }
+}
diff --git a/utils/TableGen/OptParserEmitter.h b/utils/TableGen/OptParserEmitter.h
new file mode 100644
index 0000000000..241a3f2b4a
--- /dev/null
+++ b/utils/TableGen/OptParserEmitter.h
@@ -0,0 +1,34 @@
+//===- OptParserEmitter.h - Table Driven Command Line Parsing ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef UTILS_TABLEGEN_OPTPARSEREMITTER_H
+#define UTILS_TABLEGEN_OPTPARSEREMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+ /// OptParserEmitter - This tablegen backend takes an input .td file
+ /// describing a list of options and emits a data structure for parsing and
+ /// working with those options when given an input command line.
+ class OptParserEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ bool GenDefs;
+
+ public:
+ OptParserEmitter(RecordKeeper &R, bool _GenDefs)
+ : Records(R), GenDefs(_GenDefs) {}
+
+ /// run - Output the option parsing information.
+ ///
+ /// \param GenHeader - Generate the header describing the option IDs.x
+ void run(raw_ostream &OS);
+ };
+}
+
+#endif
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index c6d75020c7..c6c4306295 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -15,21 +15,22 @@
//
//===----------------------------------------------------------------------===//
-#include "Record.h"
-#include "TGParser.h"
+#include "AsmMatcherEmitter.h"
+#include "AsmWriterEmitter.h"
#include "CallingConvEmitter.h"
+#include "ClangDiagnosticsEmitter.h"
#include "CodeEmitterGen.h"
-#include "RegisterInfoEmitter.h"
-#include "InstrInfoEmitter.h"
-#include "InstrEnumEmitter.h"
-#include "AsmWriterEmitter.h"
-#include "AsmMatcherEmitter.h"
#include "DAGISelEmitter.h"
#include "FastISelEmitter.h"
-#include "SubtargetEmitter.h"
+#include "InstrEnumEmitter.h"
+#include "InstrInfoEmitter.h"
#include "IntrinsicEmitter.h"
#include "LLVMCConfigurationEmitter.h"
-#include "ClangDiagnosticsEmitter.h"
+#include "OptParserEmitter.h"
+#include "Record.h"
+#include "RegisterInfoEmitter.h"
+#include "SubtargetEmitter.h"
+#include "TGParser.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -50,6 +51,7 @@ enum ActionType {
GenClangDiagGroups,
GenDAGISel,
GenFastISel,
+ GenOptParserDefs, GenOptParserImpl,
GenSubtarget,
GenIntrinsic,
GenTgtIntrinsic,
@@ -84,6 +86,10 @@ namespace {
"Generate a DAG instruction selector"),
clEnumValN(GenFastISel, "gen-fast-isel",
"Generate a \"fast\" instruction selector"),
+ clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
+ "Generate option definitions"),
+ clEnumValN(GenOptParserImpl, "gen-opt-parser-impl",
+ "Generate option parser implementation"),
clEnumValN(GenSubtarget, "gen-subtarget",
"Generate subtarget enumerations"),
clEnumValN(GenIntrinsic, "gen-intrinsic",
@@ -221,7 +227,13 @@ int main(int argc, char **argv) {
break;
case GenClangDiagGroups:
ClangDiagGroupsEmitter(Records).run(*Out);
- break;
+ break;
+ case GenOptParserDefs:
+ OptParserEmitter(Records, true).run(*Out);
+ break;
+ case GenOptParserImpl:
+ OptParserEmitter(Records, false).run(*Out);
+ break;
case GenDAGISel:
DAGISelEmitter(Records).run(*Out);
break;