Implement FlagParser using llvm:🆑:generic_parser_base.

This approach is easier and requires less code. With some template foo
the BoolOrDefaultAdapter is not required.

This solutions applies to previous LLVM versions, too.
This commit is contained in:
kai 2015-04-22 07:51:18 +02:00
parent cbb4d6d5b3
commit 4db0123bb7
5 changed files with 127 additions and 96 deletions

View file

@ -347,7 +347,7 @@ cl::opt<bool> disableFpElim("disable-fp-elim",
cl::desc("Disable frame pointer elimination optimization"),
cl::init(false));
static cl::opt<bool, true, FlagParser> asserts("asserts",
static cl::opt<bool, true, FlagParser<bool> > asserts("asserts",
cl::desc("(*) Enable assertions"),
cl::value_desc("bool"),
cl::location(global.params.useAssert),
@ -362,13 +362,11 @@ public:
}
};
#if LDC_LLVM_VER < 307
cl::opt<BoundsChecksAdapter, false, FlagParser> boundsChecksOld("boundscheck",
cl::opt<BoundsChecksAdapter, false, FlagParser<bool> > boundsChecksOld("boundscheck",
cl::desc("(*) Enable array bounds check (deprecated, use -boundscheck=on|off)"));
#endif
cl::opt<BoundsCheck, true> boundsChecksNew("boundscheck",
cl::desc("(*) Enable array bounds check"),
cl::desc("Enable array bounds check"),
cl::location(boundsCheck),
cl::values(
clEnumValN(BC_Off, "off", "no array bounds checks"),
@ -376,17 +374,17 @@ cl::opt<BoundsCheck, true> boundsChecksNew("boundscheck",
clEnumValN(BC_On, "on", "array bounds checks for all functions"),
clEnumValEnd));
static cl::opt<bool, true, FlagParser> invariants("invariants",
static cl::opt<bool, true, FlagParser<bool> > invariants("invariants",
cl::desc("(*) Enable invariants"),
cl::location(global.params.useInvariants),
cl::init(true));
static cl::opt<bool, true, FlagParser> preconditions("preconditions",
static cl::opt<bool, true, FlagParser<bool> > preconditions("preconditions",
cl::desc("(*) Enable function preconditions"),
cl::location(global.params.useIn),
cl::init(true));
static cl::opt<bool, true, FlagParser> postconditions("postconditions",
static cl::opt<bool, true, FlagParser<bool> > postconditions("postconditions",
cl::desc("(*) Enable function postconditions"),
cl::location(global.params.useOut),
cl::init(true));
@ -394,7 +392,7 @@ static cl::opt<bool, true, FlagParser> postconditions("postconditions",
static MultiSetter ContractsSetter(false,
&global.params.useIn, &global.params.useOut, NULL);
static cl::opt<MultiSetter, true, FlagParser> contracts("contracts",
static cl::opt<MultiSetter, true, FlagParser<bool> > contracts("contracts",
cl::desc("(*) Enable function pre- and post-conditions"),
cl::location(ContractsSetter));
@ -436,7 +434,7 @@ cl::opt<bool, true> vgc("vgc",
cl::desc("list all gc allocations including hidden ones"),
cl::location(global.params.vgc));
cl::opt<bool, true, FlagParser> color("color",
cl::opt<bool, true, FlagParser<bool> > color("color",
cl::desc("Force colored console output"),
cl::location(global.params.color));

View file

@ -18,39 +18,6 @@
namespace opts {
#if LDC_LLVM_VER < 307
bool FlagParser::parse(cl::Option &O, llvm::StringRef ArgName, llvm::StringRef Arg, bool &Val) {
// Make a std::string out of it to make comparisons easier
// (and avoid repeated conversion)
llvm::StringRef argname = ArgName;
typedef std::vector<std::pair<std::string, bool> >::iterator It;
for (It I = switches.begin(), E = switches.end(); I != E; ++I) {
llvm::StringRef name = I->first;
if (name == argname
|| (name.size() < argname.size()
&& argname.substr(0, name.size()) == name
&& argname[name.size()] == '=')) {
if (!cl::parser<bool>::parse(O, ArgName, Arg, Val)) {
Val = (Val == I->second);
return false;
}
// Invalid option value
break;
}
}
return true;
}
void FlagParser::getExtraOptionNames(llvm::SmallVectorImpl<const char*> &Names) {
typedef std::vector<std::pair<std::string, bool> >::iterator It;
for (It I = switches.begin() + 1, E = switches.end(); I != E; ++I) {
Names.push_back(I->first.data());
}
}
#endif
MultiSetter::MultiSetter(bool invert, bool* p, ...) {
this->invert = invert;
if (p) {

View file

@ -17,6 +17,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "gen/llvmcompat.h"
#if LDC_LLVM_VER < 306
#define LLVM_END_WITH_NULL END_WITH_NULL
@ -28,46 +29,132 @@ typedef Array<const char *> Strings;
namespace opts {
namespace cl = llvm::cl;
/// Helper class to determine values
template<class DT>
struct FlagParserDataType {};
template<>
struct FlagParserDataType<bool>{
static bool true_val() { return true; }
static bool false_val() { return false; }
};
template<>
struct FlagParserDataType<cl::boolOrDefault> {
static cl::boolOrDefault true_val() { return cl::BOU_TRUE; }
static cl::boolOrDefault false_val() { return cl::BOU_FALSE; }
};
template <class DataType>
class FlagParser : public cl::generic_parser_base {
protected:
llvm::SmallVector<std::pair<std::string, DataType>, 2> switches;
#if LDC_LLVM_VER >= 307
typedef cl::parser<bool> FlagParser;
cl::Option& owner() const { return Owner; }
#else
/// Helper class for fancier options
class FlagParser : public cl::parser<bool> {
#if LDC_LLVM_VER >= 307
cl::Option &Opt;
cl::Option* Owner;
cl::Option& owner() const { return *Owner; }
#endif
std::vector<std::pair<std::string, bool> > switches;
public:
#if LDC_LLVM_VER >= 307
FlagParser(cl::Option &O) : parser(O), Opt(O) { }
void initialize() {
std::string Name(Opt.ArgStr);
switches.push_back(make_pair("enable-" + Name, true));
switches.push_back(make_pair("disable-" + Name, false));
// Replace <foo> with -enable-<foo> and register -disable-<foo>
// A literal option can only registered if the argstr is empty -
// just do this first.
Opt.setArgStr("");
AddLiteralOption(Opt, strdup(switches[1].first.data()));
Opt.setArgStr(switches[0].first.data());
}
FlagParser(cl::Option& O) : generic_parser_base(O) {}
#else
template <class Opt>
void initialize(Opt &O) {
std::string Name = O.ArgStr;
switches.push_back(make_pair("enable-" + Name, true));
switches.push_back(make_pair("disable-" + Name, false));
// Replace <foo> with -enable-<foo>
O.ArgStr = switches[0].first.data();
FlagParser() : generic_parser_base(), Owner(0) {}
#endif
typedef DataType parser_data_type;
#if LDC_LLVM_VER >= 307
void initialize() {
#else
void initialize(cl::Option& O) {
Owner = &O;
#endif
std::string Name(owner().ArgStr);
switches.push_back(make_pair("enable-" + Name, FlagParserDataType<DataType>::true_val()));
switches.push_back(make_pair("disable-" + Name, FlagParserDataType<DataType>::false_val()));
// Replace <foo> with -enable-<foo> and register -disable-<foo>
#if LDC_LLVM_VER >= 307
// A literal option can only registered if the argstr is empty -
// just do this first.
owner().setArgStr("");
AddLiteralOption(Owner, strdup(switches[1].first.data()));
#endif
owner().setArgStr(switches[0].first.data());
}
#endif
bool parse(cl::Option &O, llvm::StringRef ArgName, llvm::StringRef ArgValue, bool &Val);
enum cl::ValueExpected getValueExpectedFlagDefault() const {
return cl::ValueOptional;
}
void getExtraOptionNames(llvm::SmallVectorImpl<const char*> &Names);
// Implement virtual functions needed by generic_parser_base
unsigned getNumOptions() const LLVM_OVERRIDE { return 1; }
const char* getOption(unsigned N) const LLVM_OVERRIDE {
assert(N == 0);
return owner().ArgStr;
}
const char* getDescription(unsigned N) const LLVM_OVERRIDE {
assert(N == 0);
return owner().HelpStr;
}
private:
struct OptionValue : cl::OptionValueBase < DataType, false > {
OptionValue() { };
};
const OptionValue EmptyOptionValue;
public:
// getOptionValue - Return the value of option name N.
const cl::GenericOptionValue &getOptionValue(unsigned N) const LLVM_OVERRIDE {
return EmptyOptionValue;
}
// parse - Return true on error.
bool parse(cl::Option& O, llvm::StringRef ArgName, llvm::StringRef Arg, DataType& Val) {
typedef typename llvm::SmallVector<std::pair<std::string, DataType>, 2>::iterator It;
for (It I = switches.begin(), E = switches.end(); I != E; ++I) {
llvm::StringRef name = I->first;
if (name == ArgName
|| (name.size() < ArgName.size()
&& ArgName.substr(0, name.size()) == name
&& ArgName[name.size()] == '=')) {
if (!parse(owner(), Arg, Val))
{
Val = (Val == I->second) ? FlagParserDataType<DataType>::true_val() : FlagParserDataType<DataType>::false_val();
return false;
}
// Invalid option value
break;
}
}
return true;
}
void getExtraOptionNames(llvm::SmallVectorImpl<const char*>& Names) {
typedef typename llvm::SmallVector<std::pair<std::string, DataType>, 2>::iterator It;
for (It I = switches.begin() + 1, E = switches.end(); I != E; ++I) {
Names.push_back(I->first.data());
}
}
private:
static bool parse(cl::Option &O, llvm::StringRef Arg, DataType &Val) {
if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
Arg == "1") {
Val = FlagParserDataType<DataType>::true_val();
return false;
}
if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
Val = FlagParserDataType<DataType>::false_val();
return false;
}
return O.error("'" + Arg +
"' is invalid value for boolean argument! Try 0 or 1");
}
};
#endif
/// Helper class for options that set multiple flags
class MultiSetter {
@ -99,23 +186,6 @@ typedef cl::parser<bool> FlagParser;
push_back(str.c_str());
}
};
/// Helper class to allow use of a parser<bool> with BoolOrDefault
class BoolOrDefaultAdapter {
cl::boolOrDefault value;
public:
operator cl::boolOrDefault() {
return value;
}
void operator=(cl::boolOrDefault val) {
value = val;
}
void operator=(bool val) {
*this = (val ? cl::BOU_TRUE : cl::BOU_FALSE);
}
};
}
#endif

View file

@ -111,7 +111,7 @@ disableGCToStack("disable-gc2stack",
cl::desc("Disable promotion of GC allocations to stack memory"),
cl::ZeroOrMore);
static cl::opt<opts::BoolOrDefaultAdapter, false, opts::FlagParser>
static cl::opt<cl::boolOrDefault, false, opts::FlagParser<cl::boolOrDefault> >
enableInlining("inlining",
cl::desc("Enable function inlining (default in -O2 and higher)"),
cl::ZeroOrMore);

View file

@ -322,11 +322,7 @@ macro(compile_druntime d_flags lib_suffix path_suffix outlist_o outlist_bc)
# Always disable invariants for debug builds of core.* and gc.* (there
# are/were some broken invariants around; druntime is always built in
# release mode in upstream builds).
if(${LDC_LLVM_VER} LESS 307)
set(rt_flags "${d_flags};-disable-invariants")
else ()
set(rt_flags "${d_flags};-invariants=false")
endif()
set(rt_flags "${d_flags};-disable-invariants")
if(BUILD_SHARED_LIBS)
set(shared ";-d-version=Shared")