mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 17:43:35 +03:00
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:
parent
cbb4d6d5b3
commit
4db0123bb7
5 changed files with 127 additions and 96 deletions
|
@ -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));
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
164
gen/cl_helpers.h
164
gen/cl_helpers.h
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue