aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2011-04-05 18:54:36 +0000
committerAndrew Trick <atrick@apple.com>2011-04-05 18:54:36 +0000
commitce96902d88d473697f05c0465952dae374be564e (patch)
tree8dc714413e3a45a808e238a9091a6059d4575638 /include
parent5dc0c503725c56aa74656b7c1221340f238bfa3f (diff)
downloadexternal_llvm-ce96902d88d473697f05c0465952dae374be564e.zip
external_llvm-ce96902d88d473697f05c0465952dae374be564e.tar.gz
external_llvm-ce96902d88d473697f05c0465952dae374be564e.tar.bz2
Added *hidden* flags -print-options and -print-all-options so
developers can see if their driver changed any cl::Option's. The current implementation isn't perfect but handles most kinds of options. This is nice to have when decomposing the stages of compilation and moving between different drivers. It's also a good sanity check when comparing results produced by different command line invocations that are expected to produce the comparable results. Note: This is not an attempt to prolong the life of cl::Option. On the contrary, it's a placeholder for a feature that must exist when cl::Option is replaced by a more appropriate framework. A new framework needs: a central option registry, dynamic name lookup, non-global containers of option values (e.g. per-module, per-function), *and* the ability to print options values and their defaults at any point during compilation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128910 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/llvm/Support/CommandLine.h295
1 files changed, 280 insertions, 15 deletions
diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h
index 9ae3d6a..8f1dbe0 100644
--- a/include/llvm/Support/CommandLine.h
+++ b/include/llvm/Support/CommandLine.h
@@ -60,6 +60,12 @@ void ParseEnvironmentOptions(const char *progName, const char *envvar,
void SetVersionPrinter(void (*func)());
+// PrintOptionValues - Print option values.
+// With -print-options print the difference between option values and defaults.
+// With -print-all-options print all option values.
+// (Currently not perfect, but best-effort.)
+void PrintOptionValues();
+
// MarkOptionsChanged - Internal helper function.
void MarkOptionsChanged();
@@ -230,6 +236,8 @@ public:
//
virtual void printOptionInfo(size_t GlobalWidth) const = 0;
+ virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0;
+
virtual void getExtraOptionNames(SmallVectorImpl<const char*> &) {}
// addOccurrence - Wrapper around handleOccurrence that enforces Flags.
@@ -303,6 +311,120 @@ LocationClass<Ty> location(Ty &L) { return LocationClass<Ty>(L); }
//===----------------------------------------------------------------------===//
+// OptionValue class
+
+// Support value comparison outside the template.
+struct GenericOptionValue {
+ virtual ~GenericOptionValue() {}
+ virtual bool compare(const GenericOptionValue &V) const = 0;
+};
+
+template<class DataType> struct OptionValue;
+
+// The default value safely does nothing. Option value printing is only
+// best-effort.
+template<class DataType, bool isClass>
+struct OptionValueBase : public GenericOptionValue {
+ // Temporary storage for argument passing.
+ typedef OptionValue<DataType> WrapperType;
+
+ bool hasValue() const { return false; }
+
+ const DataType &getValue() const { assert(false && "no default value"); }
+
+ // Some options may take their value from a different data type.
+ template<class DT>
+ void setValue(const DT& V) {}
+
+ bool compare(const DataType &V) const { return false; }
+
+ virtual bool compare(const GenericOptionValue& V) const { return false; }
+};
+
+// Simple copy of the option value.
+template<class DataType>
+class OptionValueCopy : public GenericOptionValue {
+ DataType Value;
+ bool Valid;
+public:
+ OptionValueCopy() : Valid(false) {}
+
+ bool hasValue() const { return Valid; }
+
+ const DataType &getValue() const {
+ assert(Valid && "invalid option value");
+ return Value;
+ }
+
+ void setValue(const DataType &V) { Valid = true; Value = V; }
+
+ bool compare(const DataType &V) const {
+ return Valid && (Value != V);
+ }
+
+ virtual bool compare(const GenericOptionValue &V) const {
+ const OptionValueCopy<DataType> &VC =
+ static_cast< const OptionValueCopy<DataType>& >(V);
+ if (!VC.hasValue) return false;
+ return compare(VC.getValue());
+ }
+};
+
+// Non-class option values.
+template<class DataType>
+struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> {
+ typedef DataType WrapperType;
+};
+
+// Top-level option class.
+template<class DataType>
+struct OptionValue : OptionValueBase<DataType, is_class<DataType>::value> {
+ OptionValue() {}
+
+ OptionValue(const DataType& V) {
+ this->setValue(V);
+ }
+ // Some options may take their value from a different data type.
+ template<class DT>
+ OptionValue<DataType> &operator=(const DT& V) {
+ this->setValue(V);
+ return *this;
+ }
+};
+
+// Other safe-to-copy-by-value common option types.
+enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE };
+template<>
+struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> {
+ typedef cl::boolOrDefault WrapperType;
+
+ OptionValue() {}
+
+ OptionValue(const cl::boolOrDefault& V) {
+ this->setValue(V);
+ }
+ OptionValue<cl::boolOrDefault> &operator=(const cl::boolOrDefault& V) {
+ setValue(V);
+ return *this;
+ }
+};
+
+template<>
+struct OptionValue<std::string> : OptionValueCopy<std::string> {
+ typedef StringRef WrapperType;
+
+ OptionValue() {}
+
+ OptionValue(const std::string& V) {
+ this->setValue(V);
+ }
+ OptionValue<std::string> &operator=(const std::string& V) {
+ setValue(V);
+ return *this;
+ }
+};
+
+//===----------------------------------------------------------------------===//
// Enum valued command line option
//
#define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC
@@ -355,7 +477,6 @@ ValuesClass<DataType> END_WITH_NULL values(const char *Arg, DataType Val,
return Vals;
}
-
//===----------------------------------------------------------------------===//
// parser class - Parameterizable parser for different data types. By default,
// known data types (string, int, bool) have specialized parsers, that do what
@@ -368,7 +489,16 @@ ValuesClass<DataType> END_WITH_NULL values(const char *Arg, DataType Val,
// not need replicated for every instance of the generic parser. This also
// allows us to put stuff into CommandLine.cpp
//
-struct generic_parser_base {
+class generic_parser_base {
+protected:
+ class GenericOptionInfo {
+ public:
+ GenericOptionInfo(const char *name, const char *helpStr) :
+ Name(name), HelpStr(helpStr) {}
+ const char *Name;
+ const char *HelpStr;
+ };
+public:
virtual ~generic_parser_base() {} // Base class should have virtual-dtor
// getNumOptions - Virtual function implemented by generic subclass to
@@ -385,11 +515,28 @@ struct generic_parser_base {
// Return the width of the option tag for printing...
virtual size_t getOptionWidth(const Option &O) const;
+ virtual const GenericOptionValue &getOptionValue(unsigned N) const = 0;
+
// printOptionInfo - Print out information about this option. The
// to-be-maintained width is specified.
//
virtual void printOptionInfo(const Option &O, size_t GlobalWidth) const;
+ void printGenericOptionDiff(const Option &O, const GenericOptionValue &V,
+ const GenericOptionValue &Default,
+ size_t GlobalWidth) const;
+
+ // printOptionDiff - print the value of an option and it's default.
+ //
+ // Template definition ensures that the option and default have the same
+ // DataType (via the same AnyOptionValue).
+ template<class AnyOptionValue>
+ void printOptionDiff(const Option &O, const AnyOptionValue &V,
+ const AnyOptionValue &Default,
+ size_t GlobalWidth) const {
+ printGenericOptionDiff(O, V, Default, GlobalWidth);
+ }
+
void initialize(Option &O) {
// All of the modifiers for the option have been processed by now, so the
// argstr field should be stable, copy it down now.
@@ -443,13 +590,11 @@ protected:
template <class DataType>
class parser : public generic_parser_base {
protected:
- class OptionInfo {
+ class OptionInfo : public GenericOptionInfo {
public:
OptionInfo(const char *name, DataType v, const char *helpStr) :
- Name(name), V(v), HelpStr(helpStr) {}
- const char *Name;
- DataType V;
- const char *HelpStr;
+ GenericOptionInfo(name, helpStr), V(v) {}
+ OptionValue<DataType> V;
};
SmallVector<OptionInfo, 8> Values;
public:
@@ -462,6 +607,11 @@ public:
return Values[N].HelpStr;
}
+ // getOptionValue - Return the value of option name N.
+ virtual const GenericOptionValue &getOptionValue(unsigned N) const {
+ return Values[N].V;
+ }
+
// parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) {
StringRef ArgVal;
@@ -473,7 +623,7 @@ public:
for (unsigned i = 0, e = static_cast<unsigned>(Values.size());
i != e; ++i)
if (Values[i].Name == ArgVal) {
- V = Values[i].V;
+ V = Values[i].V.getValue();
return false;
}
@@ -522,11 +672,19 @@ public:
//
void printOptionInfo(const Option &O, size_t GlobalWidth) const;
+ // printOptionNoValue - Print a placeholder for options that don't yet support
+ // printOptionDiff().
+ void printOptionNoValue(const Option &O, size_t GlobalWidth) const;
+
// getValueName - Overload in subclass to provide a better default value.
virtual const char *getValueName() const { return "value"; }
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
+
+protected:
+ // A helper for basic_parser::printOptionDiff.
+ void printOptionName(const Option &O, size_t GlobalWidth) const;
};
// basic_parser - The real basic parser is just a template wrapper that provides
@@ -536,6 +694,7 @@ template<class DataType>
class basic_parser : public basic_parser_impl {
public:
typedef DataType parser_data_type;
+ typedef OptionValue<DataType> OptVal;
};
//--------------------------------------------------
@@ -561,6 +720,9 @@ public:
// getValueName - Do not print =<value> at all.
virtual const char *getValueName() const { return 0; }
+ void printOptionDiff(const Option &O, bool V, OptVal Default,
+ size_t GlobalWidth) const;
+
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
};
@@ -569,7 +731,6 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>);
//--------------------------------------------------
// parser<boolOrDefault>
-enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE };
template<>
class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
public:
@@ -583,6 +744,9 @@ public:
// getValueName - Do not print =<value> at all.
virtual const char *getValueName() const { return 0; }
+ void printOptionDiff(const Option &O, boolOrDefault V, OptVal Default,
+ size_t GlobalWidth) const;
+
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
};
@@ -601,6 +765,9 @@ public:
// getValueName - Overload in subclass to provide a better default value.
virtual const char *getValueName() const { return "int"; }
+ void printOptionDiff(const Option &O, int V, OptVal Default,
+ size_t GlobalWidth) const;
+
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
};
@@ -620,6 +787,9 @@ public:
// getValueName - Overload in subclass to provide a better default value.
virtual const char *getValueName() const { return "uint"; }
+ void printOptionDiff(const Option &O, unsigned V, OptVal Default,
+ size_t GlobalWidth) const;
+
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
};
@@ -638,6 +808,9 @@ public:
// getValueName - Overload in subclass to provide a better default value.
virtual const char *getValueName() const { return "number"; }
+ void printOptionDiff(const Option &O, double V, OptVal Default,
+ size_t GlobalWidth) const;
+
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
};
@@ -656,6 +829,9 @@ public:
// getValueName - Overload in subclass to provide a better default value.
virtual const char *getValueName() const { return "number"; }
+ void printOptionDiff(const Option &O, float V, OptVal Default,
+ size_t GlobalWidth) const;
+
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
};
@@ -677,6 +853,9 @@ public:
// getValueName - Overload in subclass to provide a better default value.
virtual const char *getValueName() const { return "string"; }
+ void printOptionDiff(const Option &O, StringRef V, OptVal Default,
+ size_t GlobalWidth) const;
+
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
};
@@ -698,12 +877,63 @@ public:
// getValueName - Overload in subclass to provide a better default value.
virtual const char *getValueName() const { return "char"; }
+ void printOptionDiff(const Option &O, char V, OptVal Default,
+ size_t GlobalWidth) const;
+
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
};
EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<char>);
+//--------------------------------------------------
+// PrintOptionDiff
+//
+// This collection of wrappers is the intermediary between class opt and class
+// parser to handle all the template nastiness.
+
+// This overloaded function is selected by the generic parser.
+template<class ParserClass, class DT>
+void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V,
+ const OptionValue<DT> &Default, size_t GlobalWidth) {
+ OptionValue<DT> OV = V;
+ P.printOptionDiff(O, OV, Default, GlobalWidth);
+}
+
+// This is instantiated for basic parsers when the parsed value has a different
+// type than the option value. e.g. HelpPrinter.
+template<class ParserDT, class ValDT>
+struct OptionDiffPrinter {
+ void print(const Option &O, const parser<ParserDT> P, const ValDT &V,
+ const OptionValue<ValDT> &Default, size_t GlobalWidth) {
+ P.printOptionNoValue(O, GlobalWidth);
+ }
+};
+
+// This is instantiated for basic parsers when the parsed value has the same
+// type as the option value.
+template<class DT>
+struct OptionDiffPrinter<DT, DT> {
+ void print(const Option &O, const parser<DT> P, const DT &V,
+ const OptionValue<DT> &Default, size_t GlobalWidth) {
+ P.printOptionDiff(O, V, Default, GlobalWidth);
+ }
+};
+
+// This overloaded function is selected by the basic parser, which may parse a
+// different type than the option type.
+template<class ParserClass, class ValDT>
+void printOptionDiff(
+ const Option &O,
+ const basic_parser<typename ParserClass::parser_data_type> &P,
+ const ValDT &V, const OptionValue<ValDT> &Default,
+ size_t GlobalWidth) {
+
+ OptionDiffPrinter<typename ParserClass::parser_data_type, ValDT> printer;
+ printer.print(O, static_cast<const ParserClass&>(P), V, Default,
+ GlobalWidth);
+}
+
//===----------------------------------------------------------------------===//
// applicator class - This class is used because we must use partial
// specialization to handle literal string arguments specially (const char* does
@@ -753,7 +983,6 @@ void apply(const Mod &M, Opt *O) {
applicator<Mod>::opt(M, *O);
}
-
//===----------------------------------------------------------------------===//
// opt_storage class
@@ -764,6 +993,7 @@ void apply(const Mod &M, Opt *O) {
template<class DataType, bool ExternalStorage, bool isClass>
class opt_storage {
DataType *Location; // Where to store the object...
+ OptionValue<DataType> Default;
void check() const {
assert(Location != 0 && "cl::location(...) not specified for a command "
@@ -777,21 +1007,25 @@ public:
if (Location)
return O.error("cl::location(x) specified more than once!");
Location = &L;
+ Default = L;
return false;
}
template<class T>
- void setValue(const T &V) {
+ void setValue(const T &V, bool initial = false) {
check();
*Location = V;
+ if (initial)
+ Default = V;
}
DataType &getValue() { check(); return *Location; }
const DataType &getValue() const { check(); return *Location; }
operator DataType() const { return this->getValue(); }
-};
+ const OptionValue<DataType> &getDefault() const { return Default; }
+};
// Define how to hold a class type object, such as a string. Since we can
// inherit from a class, we do so. This makes us exactly compatible with the
@@ -800,11 +1034,19 @@ public:
template<class DataType>
class opt_storage<DataType,false,true> : public DataType {
public:
+ OptionValue<DataType> Default;
+
template<class T>
- void setValue(const T &V) { DataType::operator=(V); }
+ void setValue(const T &V, bool initial = false) {
+ DataType::operator=(V);
+ if (initial)
+ Default = V;
+ }
DataType &getValue() { return *this; }
const DataType &getValue() const { return *this; }
+
+ const OptionValue<DataType> &getDefault() const { return Default; }
};
// Define a partial specialization to handle things we cannot inherit from. In
@@ -815,16 +1057,23 @@ template<class DataType>
class opt_storage<DataType, false, false> {
public:
DataType Value;
+ OptionValue<DataType> Default;
// Make sure we initialize the value with the default constructor for the
// type.
opt_storage() : Value(DataType()) {}
template<class T>
- void setValue(const T &V) { Value = V; }
+ void setValue(const T &V, bool initial = false) {
+ Value = V;
+ if (initial)
+ Default = V;
+ }
DataType &getValue() { return Value; }
DataType getValue() const { return Value; }
+ const OptionValue<DataType> &getDefault() const { return Default; }
+
operator DataType() const { return getValue(); }
// If the datatype is a pointer, support -> on it.
@@ -866,13 +1115,20 @@ class opt : public Option,
Parser.printOptionInfo(*this, GlobalWidth);
}
+ virtual void printOptionValue(size_t GlobalWidth, bool Force) const {
+ if (Force || this->getDefault().compare(this->getValue())) {
+ cl::printOptionDiff<ParserClass>(
+ *this, Parser, this->getValue(), this->getDefault(), GlobalWidth);
+ }
+ }
+
void done() {
addArgument();
Parser.initialize(*this);
}
public:
// setInitialValue - Used by the cl::init modifier...
- void setInitialValue(const DataType &V) { this->setValue(V); }
+ void setInitialValue(const DataType &V) { this->setValue(V, true); }
ParserClass &getParser() { return Parser; }
@@ -1030,6 +1286,9 @@ class list : public Option, public list_storage<DataType, Storage> {
Parser.printOptionInfo(*this, GlobalWidth);
}
+ // Unimplemented: list options don't currently store their default value.
+ virtual void printOptionValue(size_t GlobalWidth, bool Force) const {}
+
void done() {
addArgument();
Parser.initialize(*this);
@@ -1229,6 +1488,9 @@ class bits : public Option, public bits_storage<DataType, Storage> {
Parser.printOptionInfo(*this, GlobalWidth);
}
+ // Unimplemented: bits options don't currently store their default values.
+ virtual void printOptionValue(size_t GlobalWidth, bool Force) const {}
+
void done() {
addArgument();
Parser.initialize(*this);
@@ -1320,6 +1582,9 @@ class alias : public Option {
virtual size_t getOptionWidth() const;
virtual void printOptionInfo(size_t GlobalWidth) const;
+ // Aliases do not need to print their values.
+ virtual void printOptionValue(size_t GlobalWidth, bool Force) const {}
+
void done() {
if (!hasArgStr())
error("cl::alias must have argument name specified!");