1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

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.

llvm-svn: 128910
This commit is contained in:
Andrew Trick 2011-04-05 18:54:36 +00:00
parent f2d8c2ea3d
commit 7e2e555075
4 changed files with 436 additions and 41 deletions

View File

@ -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.
@ -302,6 +310,120 @@ template<class Ty>
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
//
@ -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!");

View File

@ -908,8 +908,6 @@ void alias::printOptionInfo(size_t GlobalWidth) const {
errs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n";
}
//===----------------------------------------------------------------------===//
// Parser Implementation code...
//
@ -939,7 +937,11 @@ void basic_parser_impl::printOptionInfo(const Option &O,
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 @@ void generic_parser_base::printOptionInfo(const Option &O,
}
}
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 @@ static int OptNameCompare(const void *LHS, const void *RHS) {
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 @@ public:
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 @@ static cl::opt<HelpPrinter, true, parser<bool> >
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) {

View File

@ -338,6 +338,9 @@ int main(int argc, char **argv) {
return 1;
}
// Before executing passes, print the final values of the LLVM options.
cl::PrintOptionValues();
PM.run(mod);
}

View File

@ -701,6 +701,9 @@ int main(int argc, char **argv) {
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());