forked from ldc-developers/ldc
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcl_helpers.h
199 lines (172 loc) · 5.55 KB
/
cl_helpers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
//===-- gen/cl_helpers.h - Command line processing helpers ------*- C++ -*-===//
//
// LDC – the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
//
// Helpers to augment the LLVM command line parsing library with some extra
// functionality.
//
//===----------------------------------------------------------------------===//
#ifndef LDC_GEN_CL_HELPERS_H
#define LDC_GEN_CL_HELPERS_H
#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
#endif
template <typename TYPE> struct Array;
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
cl::Option &owner() const { return Owner; }
#else
cl::Option *Owner;
cl::Option &owner() const { return *Owner; }
#endif
public:
#if LDC_LLVM_VER >= 307
FlagParser(cl::Option &O) : generic_parser_base(O) {}
#else
FlagParser() : generic_parser_base(), Owner(nullptr) {}
#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());
}
enum cl::ValueExpected getValueExpectedFlagDefault() const {
return cl::ValueOptional;
}
// 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);
#if LDC_LLVM_VER >= 308
return owner().ArgStr.data();
#else
return owner().ArgStr;
#endif
}
const char *getDescription(unsigned N) const LLVM_OVERRIDE {
assert(N == 0);
#if LDC_LLVM_VER >= 308
return owner().HelpStr.data();
#else
return owner().HelpStr;
#endif
}
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) {
for (const auto &pair : switches) {
const auto &name = pair.first;
if (name == ArgName || (name.size() < ArgName.size() &&
ArgName.substr(0, name.size()) == name &&
ArgName[name.size()] == '=')) {
if (!parse(owner(), Arg, Val)) {
Val = (Val == pair.second)
? FlagParserDataType<DataType>::true_val()
: FlagParserDataType<DataType>::false_val();
return false;
}
// Invalid option value
break;
}
}
return true;
}
#if LDC_LLVM_VER >= 308
void getExtraOptionNames(llvm::SmallVectorImpl<llvm::StringRef> &Names) {
#else
void getExtraOptionNames(llvm::SmallVectorImpl<const char *> &Names) {
#endif
for (auto 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");
}
};
/// Helper class for options that set multiple flags
class MultiSetter {
std::vector<bool *> locations;
bool invert;
explicit MultiSetter(bool); // not implemented, disable auto-conversion
public:
MultiSetter(bool invert, bool *p, ...) LLVM_END_WITH_NULL;
void operator=(bool val);
};
/// Helper class to fill Strings with char* when given strings
/// (Errors on empty strings)
class StringsAdapter {
const char *name;
Strings **arrp;
public:
StringsAdapter(const char *name_, Strings *&arr) {
name = name_;
arrp = &arr;
assert(name);
assert(arrp);
}
void push_back(const char *cstr);
void push_back(const std::string &str) { push_back(str.c_str()); }
};
}
#endif