[cfe-commits] r89234 - in /cfe/trunk: include/clang/Driver/Options.h lib/Driver/Driver.cpp lib/Driver/OptTable.cpp
Daniel Dunbar
daniel at zuster.org
Wed Nov 18 12:19:37 PST 2009
Author: ddunbar
Date: Wed Nov 18 14:19:36 2009
New Revision: 89234
URL: http://llvm.org/viewvc/llvm-project?rev=89234&view=rev
Log:
Driver: Rework OptTable to have no dependency on the options it manages.
Modified:
cfe/trunk/include/clang/Driver/Options.h
cfe/trunk/lib/Driver/Driver.cpp
cfe/trunk/lib/Driver/OptTable.cpp
Modified: cfe/trunk/include/clang/Driver/Options.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.h?rev=89234&r1=89233&r2=89234&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.h (original)
+++ cfe/trunk/include/clang/Driver/Options.h Wed Nov 18 14:19:36 2009
@@ -10,18 +10,19 @@
#ifndef CLANG_DRIVER_OPTIONS_H_
#define CLANG_DRIVER_OPTIONS_H_
+#include <cassert>
+
namespace clang {
namespace driver {
namespace options {
- enum ID {
- OPT_INVALID = 0, // This is not an option ID.
- OPT_INPUT, // Reserved ID for input option.
- OPT_UNKNOWN, // Reserved ID for unknown option.
-#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) OPT_##ID,
-#include "clang/Driver/Options.def"
- LastOption
-#undef OPTION
+ enum DriverFlag {
+ DriverOption = (1 << 0),
+ LinkerInput = (1 << 1),
+ NoArgumentUnused = (1 << 2),
+ RenderAsInput = (1 << 3),
+ RenderJoined = (1 << 4),
+ RenderSeparate = (1 << 5),
+ Unsupported = (1 << 6)
};
}
@@ -31,59 +32,125 @@
/// OptTable - Provide access to the Option info table.
///
- /// The OptTable class provides a layer of indirection which allows
- /// Option instance to be created lazily. In the common case, only a
- /// few options will be needed at runtime; the OptTable class
- /// maintains enough information to parse command lines without
- /// instantiating Options, while letting other parts of the driver
- /// still use Option instances where convient.
+ /// The OptTable class provides a layer of indirection which allows Option
+ /// instance to be created lazily. In the common case, only a few options will
+ /// be needed at runtime; the OptTable class maintains enough information to
+ /// parse command lines without instantiating Options, while letting other
+ /// parts of the driver still use Option instances where convenient.
+ //
+ // FIXME: Introduce an OptionSpecifier class to wrap the option ID
+ // variant?
class OptTable {
- /// The table of options which have been constructed, indexed by
- /// option::ID - 1.
+ public:
+ /// Info - Entry for a single option instance in the option data table.
+ struct Info {
+ const char *Name;
+ const char *HelpText;
+ const char *MetaVar;
+ unsigned char Kind;
+ unsigned char Flags;
+ unsigned char Param;
+ unsigned short GroupID;
+ unsigned short AliasID;
+ };
+
+ private:
+ /// The static option information table.
+ const Info *OptionInfos;
+ unsigned NumOptionInfos;
+
+ /// The lazily constructed options table, indexed by option::ID - 1.
mutable Option **Options;
- /// The index of the first option which can be parsed (i.e., is
- /// not a special option like 'input' or 'unknown', and is not an
- /// option group).
- unsigned FirstSearchableOption;
+ /// Prebound input option instance.
+ const Option *TheInputOption;
- Option *constructOption(options::ID id) const;
+ /// Prebound unknown option instance.
+ const Option *TheUnknownOption;
+ /// The index of the first option which can be parsed (i.e., is not a
+ /// special option like 'input' or 'unknown', and is not an option group).
+ unsigned FirstSearchableIndex;
+
+ private:
+ const Info &getInfo(unsigned id) const {
+ assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID.");
+ return OptionInfos[id - 1];
+ }
+
+ Option *CreateOption(unsigned id) const;
+
+ protected:
+ OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos);
public:
- OptTable();
~OptTable();
- unsigned getNumOptions() const;
+ /// getNumOptions - Return the total number of option classes.
+ unsigned getNumOptions() const { return NumOptionInfos; }
- const char *getOptionName(options::ID id) const;
-
- /// getOption - Get the given \arg id's Option instance, lazily
- /// creating it if necessary.
- const Option *getOption(options::ID id) const;
+ /// getOption - Get the given \arg id's Option instance, lazily creating it
+ /// if necessary.
+ ///
+ /// \return The option, or null for the INVALID option id.
+ const Option *getOption(unsigned id) const {
+ if (id == 0)
+ return 0;
+
+ assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
+ Option *&Entry = Options[id - 1];
+ if (!Entry)
+ Entry = CreateOption(id);
+ return Entry;
+ }
+
+ /// getOptionName - Lookup the name of the given option.
+ const char *getOptionName(unsigned id) const {
+ return getInfo(id).Name;
+ }
/// getOptionKind - Get the kind of the given option.
- unsigned getOptionKind(options::ID id) const;
+ unsigned getOptionKind(unsigned id) const {
+ return getInfo(id).Kind;
+ }
+
+ /// getOptionHelpText - Get the help text to use to describe this option.
+ const char *getOptionHelpText(unsigned id) const {
+ return getInfo(id).HelpText;
+ }
+
+ /// getOptionMetaVar - Get the meta-variable name to use when describing
+ /// this options values in the help text.
+ const char *getOptionMetaVar(unsigned id) const {
+ return getInfo(id).MetaVar;
+ }
- /// getOptionHelpText - Get the help text to use to describe this
- /// option.
- const char *getOptionHelpText(options::ID id) const;
-
- /// getOptionMetaVar - Get the meta-variable name to use when
- /// describing this options values in the help text.
- const char *getOptionMetaVar(options::ID id) const;
-
- /// parseOneArg - Parse a single argument; returning the new
- /// argument and updating Index.
+ /// parseOneArg - Parse a single argument; returning the new argument and
+ /// updating Index.
///
- /// \param [in] [out] Index - The current parsing position in the
- /// argument string list; on return this will be the index of the
- /// next argument string to parse.
+ /// \param [in] [out] Index - The current parsing position in the argument
+ /// string list; on return this will be the index of the next argument
+ /// string to parse.
///
- /// \return - The parsed argument, or 0 if the argument is missing
- /// values (in which case Index still points at the conceptual
- /// next argument string to parse).
+ /// \return - The parsed argument, or 0 if the argument is missing values
+ /// (in which case Index still points at the conceptual next argument string
+ /// to parse).
Arg *ParseOneArg(const InputArgList &Args, unsigned &Index) const;
};
+
+namespace options {
+ enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+ OPT_INPUT, // Reserved ID for input option.
+ OPT_UNKNOWN, // Reserved ID for unknown option.
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) OPT_##ID,
+#include "clang/Driver/Options.def"
+ LastOption
+#undef OPTION
+ };
+}
+
+ OptTable *createDriverOptTable();
}
}
Modified: cfe/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=89234&r1=89233&r2=89234&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Driver.cpp (original)
+++ cfe/trunk/lib/Driver/Driver.cpp Wed Nov 18 14:19:36 2009
@@ -44,7 +44,7 @@
const char *_DefaultHostTriple,
const char *_DefaultImageName,
bool IsProduction, Diagnostic &_Diags)
- : Opts(new OptTable()), Diags(_Diags),
+ : Opts(createDriverOptTable()), Diags(_Diags),
Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple),
DefaultImageName(_DefaultImageName),
Host(0),
Modified: cfe/trunk/lib/Driver/OptTable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/OptTable.cpp?rev=89234&r1=89233&r2=89234&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/OptTable.cpp (original)
+++ cfe/trunk/lib/Driver/OptTable.cpp Wed Nov 18 14:19:36 2009
@@ -18,28 +18,6 @@
using namespace clang::driver;
using namespace clang::driver::options;
-enum DriverFlag {
- DriverOption = (1 << 0),
- LinkerInput = (1 << 1),
- NoArgumentUnused = (1 << 2),
- RenderAsInput = (1 << 3),
- RenderJoined = (1 << 4),
- RenderSeparate = (1 << 5),
- Unsupported = (1 << 6)
-};
-
-struct Info {
- const char *Name;
- const char *HelpText;
- const char *MetaVar;
-
- unsigned char Kind;
- unsigned char Flags;
- unsigned char Param;
- unsigned short GroupID;
- unsigned short AliasID;
-};
-
// Ordering on Info. The ordering is *almost* lexicographic, with two
// exceptions. First, '\0' comes at the end of the alphabet instead of
// the beginning (thus options preceed any other options which prefix
@@ -66,7 +44,7 @@
return (a < b) ? -1 : 1;
}
-static inline bool operator<(const Info &A, const Info &B) {
+static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
if (&A == &B)
return false;
@@ -82,55 +60,46 @@
//
-static Info OptionInfos[] = {
- // The InputOption info
- { "<input>", 0, 0, Option::InputClass, DriverOption, 0, OPT_INVALID, OPT_INVALID },
- // The UnknownOption info
- { "<unknown>", 0, 0, Option::UnknownClass, 0, 0, OPT_INVALID, OPT_INVALID },
-
-#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) \
- { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
- OPT_##GROUP, OPT_##ALIAS },
-#include "clang/Driver/Options.def"
-};
-static const unsigned numOptions = sizeof(OptionInfos) / sizeof(OptionInfos[0]);
-
-static Info &getInfo(unsigned id) {
- assert(id > 0 && id - 1 < numOptions && "Invalid Option ID.");
- return OptionInfos[id - 1];
-}
-
-OptTable::OptTable() : Options(new Option*[numOptions]) {
+OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
+ : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos),
+ Options(new Option*[NumOptionInfos]),
+ TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0)
+{
// Explicitly zero initialize the error to work around a bug in array
// value-initialization on MinGW with gcc 4.3.5.
- memset(Options, 0, sizeof(*Options) * numOptions);
+ memset(Options, 0, sizeof(*Options) * NumOptionInfos);
// Find start of normal options.
- FirstSearchableOption = 0;
- for (unsigned i = OPT_UNKNOWN + 1; i < LastOption; ++i) {
- if (getInfo(i).Kind != Option::GroupClass) {
- FirstSearchableOption = i;
+ for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+ unsigned Kind = getInfo(i + 1).Kind;
+ if (Kind == Option::InputClass) {
+ assert(!TheInputOption && "Cannot have multiple input options!");
+ TheInputOption = getOption(i + 1);
+ } else if (Kind == Option::UnknownClass) {
+ assert(!TheUnknownOption && "Cannot have multiple input options!");
+ TheUnknownOption = getOption(i + 1);
+ } else if (Kind != Option::GroupClass) {
+ FirstSearchableIndex = i;
break;
}
}
- assert(FirstSearchableOption != 0 && "No searchable options?");
+ assert(FirstSearchableIndex != 0 && "No searchable options?");
#ifndef NDEBUG
// Check that everything after the first searchable option is a
// regular option class.
- for (unsigned i = FirstSearchableOption; i < LastOption; ++i) {
- Option::OptionClass Kind = (Option::OptionClass) getInfo(i).Kind;
+ for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
+ Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
Kind != Option::GroupClass) &&
"Special options should be defined first!");
}
// Check that options are in order.
- for (unsigned i = FirstSearchableOption + 1; i < LastOption; ++i) {
- if (!(getInfo(i - 1) < getInfo(i))) {
- getOption((options::ID) (i - 1))->dump();
- getOption((options::ID) i)->dump();
+ for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
+ if (!(getInfo(i) < getInfo(i + 1))) {
+ getOption(i)->dump();
+ getOption(i + 1)->dump();
assert(0 && "Options are not in order!");
}
}
@@ -138,49 +107,16 @@
}
OptTable::~OptTable() {
- for (unsigned i = 0; i < numOptions; ++i)
+ for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
delete Options[i];
delete[] Options;
}
-unsigned OptTable::getNumOptions() const {
- return numOptions;
-}
-
-const char *OptTable::getOptionName(options::ID id) const {
- return getInfo(id).Name;
-}
-
-unsigned OptTable::getOptionKind(options::ID id) const {
- return getInfo(id).Kind;
-}
-
-const char *OptTable::getOptionHelpText(options::ID id) const {
- return getInfo(id).HelpText;
-}
-
-const char *OptTable::getOptionMetaVar(options::ID id) const {
- return getInfo(id).MetaVar;
-}
-
-const Option *OptTable::getOption(options::ID id) const {
- if (id == OPT_INVALID)
- return 0;
-
- assert((unsigned) (id - 1) < numOptions && "Invalid ID.");
-
- Option *&Entry = Options[id - 1];
- if (!Entry)
- Entry = constructOption(id);
-
- return Entry;
-}
-
-Option *OptTable::constructOption(options::ID id) const {
- Info &info = getInfo(id);
+Option *OptTable::CreateOption(unsigned id) const {
+ const Info &info = getInfo(id);
const OptionGroup *Group =
- cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID));
- const Option *Alias = getOption((options::ID) info.AliasID);
+ cast_or_null<OptionGroup>(getOption(info.GroupID));
+ const Option *Alias = getOption(info.AliasID);
Option *Opt = 0;
switch (info.Kind) {
@@ -229,12 +165,16 @@
}
// Support lower_bound between info and an option name.
-static inline bool operator<(struct Info &I, const char *Name) {
+namespace clang {
+namespace driver {
+static inline bool operator<(const OptTable::Info &I, const char *Name) {
return StrCmpOptionName(I.Name, Name) == -1;
}
-static inline bool operator<(const char *Name, struct Info &I) {
+static inline bool operator<(const char *Name, const OptTable::Info &I) {
return StrCmpOptionName(Name, I.Name) == -1;
}
+}
+}
Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const {
unsigned Prev = Index;
@@ -242,10 +182,10 @@
// Anything that doesn't start with '-' is an input, as is '-' itself.
if (Str[0] != '-' || Str[1] == '\0')
- return new PositionalArg(getOption(OPT_INPUT), Index++);
+ return new PositionalArg(TheInputOption, Index++);
- struct Info *Start = OptionInfos + FirstSearchableOption - 1;
- struct Info *End = OptionInfos + LastOption - 1;
+ const Info *Start = OptionInfos + FirstSearchableIndex;
+ const Info *End = OptionInfos + LastOption - 1;
// Search for the first next option which could be a prefix.
Start = std::lower_bound(Start, End, Str);
@@ -276,6 +216,34 @@
return 0;
}
- return new PositionalArg(getOption(OPT_UNKNOWN), Index++);
+ return new PositionalArg(TheUnknownOption, Index++);
}
+//
+
+static OptTable::Info InfoTable[] = {
+ // The InputOption info
+ { "<input>", 0, 0, Option::InputClass, DriverOption, 0, OPT_INVALID, OPT_INVALID },
+ // The UnknownOption info
+ { "<unknown>", 0, 0, Option::UnknownClass, 0, 0, OPT_INVALID, OPT_INVALID },
+
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
+ OPT_##GROUP, OPT_##ALIAS },
+#include "clang/Driver/Options.def"
+};
+
+namespace {
+
+class DriverOptTable : public OptTable {
+public:
+ DriverOptTable()
+ : OptTable(InfoTable, sizeof(InfoTable) / sizeof(InfoTable[0])) {}
+};
+
+}
+
+OptTable *clang::driver::createDriverOptTable() {
+ return new DriverOptTable();
+}
More information about the cfe-commits
mailing list