[llvm-commits] [llvm] r128910 - in /llvm/trunk: include/llvm/Support/CommandLine.h lib/Support/CommandLine.cpp tools/llc/llc.cpp tools/opt/opt.cpp

Andrew Trick atrick at apple.com
Tue Apr 5 11:54:36 PDT 2011


Author: atrick
Date: Tue Apr  5 13:54:36 2011
New Revision: 128910

URL: http://llvm.org/viewvc/llvm-project?rev=128910&view=rev
Log:
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.

Modified:
    llvm/trunk/include/llvm/Support/CommandLine.h
    llvm/trunk/lib/Support/CommandLine.cpp
    llvm/trunk/tools/llc/llc.cpp
    llvm/trunk/tools/opt/opt.cpp

Modified: llvm/trunk/include/llvm/Support/CommandLine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CommandLine.h?rev=128910&r1=128909&r2=128910&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/CommandLine.h (original)
+++ llvm/trunk/include/llvm/Support/CommandLine.h Tue Apr  5 13:54:36 2011
@@ -60,6 +60,12 @@
 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 @@
   //
   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 @@
 
 
 //===----------------------------------------------------------------------===//
+// 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 @@
     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 @@
 // 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 @@
   // 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 @@
 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 @@
     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 @@
     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 @@
   //
   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 @@
 class basic_parser : public basic_parser_impl {
 public:
   typedef DataType parser_data_type;
+  typedef OptionValue<DataType> OptVal;
 };
 
 //--------------------------------------------------
@@ -561,6 +720,9 @@
   // 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 @@
 
 //--------------------------------------------------
 // parser<boolOrDefault>
-enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE };
 template<>
 class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
 public:
@@ -583,6 +744,9 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   // 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 @@
   applicator<Mod>::opt(M, *O);
 }
 
-
 //===----------------------------------------------------------------------===//
 // opt_storage class
 
@@ -764,6 +993,7 @@
 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 @@
     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 @@
 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 @@
 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 @@
     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 @@
     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 @@
     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 @@
   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!");

Modified: llvm/trunk/lib/Support/CommandLine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CommandLine.cpp?rev=128910&r1=128909&r2=128910&view=diff
==============================================================================
--- llvm/trunk/lib/Support/CommandLine.cpp (original)
+++ llvm/trunk/lib/Support/CommandLine.cpp Tue Apr  5 13:54:36 2011
@@ -908,8 +908,6 @@
   errs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n";
 }
 
-
-
 //===----------------------------------------------------------------------===//
 // Parser Implementation code...
 //
@@ -939,7 +937,11 @@
   outs().indent(GlobalWidth-getOptionWidth(O)) << " - " << O.HelpStr << '\n';
 }
 
-
+void basic_parser_impl::printOptionName(const Option &O,
+                                        size_t GlobalWidth) const {
+  outs() << "  -" << O.ArgStr;
+  outs().indent(GlobalWidth-std::strlen(O.ArgStr));
+}
 
 
 // parser<bool> implementation
@@ -1083,6 +1085,89 @@
   }
 }
 
+static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff
+
+// printGenericOptionDiff - Print the value of this option and it's default.
+//
+// "Generic" options have each value mapped to a name.
+void generic_parser_base::
+printGenericOptionDiff(const Option &O, const GenericOptionValue &Value,
+                       const GenericOptionValue &Default,
+                       size_t GlobalWidth) const {
+  outs() << "  -" << O.ArgStr;
+  outs().indent(GlobalWidth-std::strlen(O.ArgStr));
+
+  unsigned NumOpts = getNumOptions();
+  for (unsigned i = 0; i != NumOpts; ++i) {
+    if (Value.compare(getOptionValue(i)))
+      continue;
+
+    outs() << "= " << getOption(i);
+    size_t L = std::strlen(getOption(i));
+    size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0;
+    outs().indent(NumSpaces) << " (default: ";
+    for (unsigned j = 0; j != NumOpts; ++j) {
+      if (Default.compare(getOptionValue(j)))
+        continue;
+      outs() << getOption(j);
+      break;
+    }
+    outs() << ")\n";
+    return;
+  }
+  outs() << "= *unknown option value*\n";
+}
+
+// printOptionDiff - Specializations for printing basic value types.
+//
+#define PRINT_OPT_DIFF(T)                                               \
+  void parser<T>::                                                      \
+  printOptionDiff(const Option &O, T V, OptionValue<T> D,               \
+                  size_t GlobalWidth) const {                           \
+    printOptionName(O, GlobalWidth);                                    \
+    std::string Str;                                                    \
+    {                                                                   \
+      raw_string_ostream SS(Str);                                       \
+      SS << V;                                                          \
+    }                                                                   \
+    outs() << "= " << Str;                                              \
+    size_t NumSpaces = MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0;\
+    outs().indent(NumSpaces) << " (default: ";                          \
+    if (D.hasValue())                                                   \
+      outs() << D.getValue();                                           \
+    else                                                                \
+      outs() << "*no default*";                                         \
+    outs() << ")\n";                                                    \
+  }                                                                     \
+
+PRINT_OPT_DIFF(bool);
+PRINT_OPT_DIFF(boolOrDefault);
+PRINT_OPT_DIFF(int);
+PRINT_OPT_DIFF(unsigned);
+PRINT_OPT_DIFF(double);
+PRINT_OPT_DIFF(float);
+PRINT_OPT_DIFF(char);
+
+void parser<std::string>::
+printOptionDiff(const Option &O, StringRef V, OptionValue<std::string> D,
+                size_t GlobalWidth) const {
+  printOptionName(O, GlobalWidth);
+  outs() << "= " << V;
+  size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0;
+  outs().indent(NumSpaces) << " (default: ";
+  if (D.hasValue())
+    outs() << D.getValue();
+  else
+    outs() << "*no default*";
+  outs() << ")\n";
+}
+
+// Print a placeholder for options that don't yet support printOptionDiff().
+void basic_parser_impl::
+printOptionNoValue(const Option &O, size_t GlobalWidth) const {
+  printOptionName(O, GlobalWidth);
+  outs() << "= *cannot print option value*\n";
+}
 
 //===----------------------------------------------------------------------===//
 // -help and -help-hidden option implementation
@@ -1094,6 +1179,35 @@
   return strcmp(((pair_ty*)LHS)->first, ((pair_ty*)RHS)->first);
 }
 
+// Copy Options into a vector so we can sort them as we like.
+static void
+sortOpts(StringMap<Option*> &OptMap,
+         SmallVectorImpl< std::pair<const char *, Option*> > &Opts,
+         bool ShowHidden) {
+  SmallPtrSet<Option*, 128> OptionSet;  // Duplicate option detection.
+
+  for (StringMap<Option*>::iterator I = OptMap.begin(), E = OptMap.end();
+       I != E; ++I) {
+    // Ignore really-hidden options.
+    if (I->second->getOptionHiddenFlag() == ReallyHidden)
+      continue;
+
+    // Unless showhidden is set, ignore hidden flags.
+    if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden)
+      continue;
+
+    // If we've already seen this option, don't add it to the list again.
+    if (!OptionSet.insert(I->second))
+      continue;
+
+    Opts.push_back(std::pair<const char *, Option*>(I->getKey().data(),
+                                                    I->second));
+  }
+
+  // Sort the options list alphabetically.
+  qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare);
+}
+
 namespace {
 
 class HelpPrinter {
@@ -1115,30 +1229,8 @@
     StringMap<Option*> OptMap;
     GetOptionInfo(PositionalOpts, SinkOpts, OptMap);
 
-    // Copy Options into a vector so we can sort them as we like.
     SmallVector<std::pair<const char *, Option*>, 128> Opts;
-    SmallPtrSet<Option*, 128> OptionSet;  // Duplicate option detection.
-
-    for (StringMap<Option*>::iterator I = OptMap.begin(), E = OptMap.end();
-         I != E; ++I) {
-      // Ignore really-hidden options.
-      if (I->second->getOptionHiddenFlag() == ReallyHidden)
-        continue;
-
-      // Unless showhidden is set, ignore hidden flags.
-      if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden)
-        continue;
-
-      // If we've already seen this option, don't add it to the list again.
-      if (!OptionSet.insert(I->second))
-        continue;
-
-      Opts.push_back(std::pair<const char *, Option*>(I->getKey().data(),
-                                                      I->second));
-    }
-
-    // Sort the options list alphabetically.
-    qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare);
+    sortOpts(OptMap, Opts, ShowHidden);
 
     if (ProgramOverview)
       outs() << "OVERVIEW: " << ProgramOverview << "\n";
@@ -1197,6 +1289,38 @@
 HHOp("help-hidden", cl::desc("Display all available options"),
      cl::location(HiddenPrinter), cl::Hidden, cl::ValueDisallowed);
 
+static cl::opt<bool>
+PrintOptions("print-options",
+             cl::desc("Print non-default options after command line parsing"),
+             cl::Hidden, cl::init(false));
+
+static cl::opt<bool>
+PrintAllOptions("print-all-options",
+                cl::desc("Print all option values after command line parsing"),
+                cl::Hidden, cl::init(false));
+
+// Print the value of each option.
+void cl::PrintOptionValues() {
+  if (!PrintOptions && !PrintAllOptions) return;
+
+  // Get all the options.
+  SmallVector<Option*, 4> PositionalOpts;
+  SmallVector<Option*, 4> SinkOpts;
+  StringMap<Option*> OptMap;
+  GetOptionInfo(PositionalOpts, SinkOpts, OptMap);
+
+  SmallVector<std::pair<const char *, Option*>, 128> Opts;
+  sortOpts(OptMap, Opts, /*ShowHidden*/true);
+
+  // Compute the maximum argument length...
+  size_t MaxArgLen = 0;
+  for (size_t i = 0, e = Opts.size(); i != e; ++i)
+    MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth());
+
+  for (size_t i = 0, e = Opts.size(); i != e; ++i)
+    Opts[i].second->printOptionValue(MaxArgLen, PrintAllOptions);
+}
+
 static void (*OverrideVersionPrinter)() = 0;
 
 static int TargetArraySortFn(const void *LHS, const void *RHS) {

Modified: llvm/trunk/tools/llc/llc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llc/llc.cpp?rev=128910&r1=128909&r2=128910&view=diff
==============================================================================
--- llvm/trunk/tools/llc/llc.cpp (original)
+++ llvm/trunk/tools/llc/llc.cpp Tue Apr  5 13:54:36 2011
@@ -338,6 +338,9 @@
       return 1;
     }
 
+    // Before executing passes, print the final values of the LLVM options.
+    cl::PrintOptionValues();
+
     PM.run(mod);
   }
 

Modified: llvm/trunk/tools/opt/opt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/opt.cpp?rev=128910&r1=128909&r2=128910&view=diff
==============================================================================
--- llvm/trunk/tools/opt/opt.cpp (original)
+++ llvm/trunk/tools/opt/opt.cpp Tue Apr  5 13:54:36 2011
@@ -701,6 +701,9 @@
       Passes.add(createBitcodeWriterPass(Out->os()));
   }
 
+  // Before executing passes, print the final values of the LLVM options.
+  cl::PrintOptionValues();
+
   // Now that we have all of the passes ready, run them.
   Passes.run(*M.get());
 





More information about the llvm-commits mailing list