13#ifndef OPENMP_TRAITS_H
14#define OPENMP_TRAITS_H
23enum class token_kind {
42 token_kind kind = token_kind::UNKNOWN;
46class kmp_lexer final {
49 bool has_lookahead =
false;
55 explicit kmp_lexer(
kmp_str_ref source) : scan(source) {}
60 has_lookahead =
false;
80 static_cast<size_t>(scan.end() - t.text.begin()));
88extern "C" int omp_get_num_devices();
89extern "C" const char *omp_get_uid_from_device(
int device_num);
93 enum trait_type { WILDCARD_T, LITERAL_T, UID_T };
96 kmp_trait(trait_type type) : _type(type) {}
99 virtual ~kmp_trait() =
default;
101 kmp_trait(
const kmp_trait &) =
delete;
102 kmp_trait(kmp_trait &&) =
delete;
103 kmp_trait &operator=(
const kmp_trait &) =
delete;
104 kmp_trait &operator=(kmp_trait &&) =
delete;
108 virtual bool match([[maybe_unused]]
int device)
const {
109 KMP_ASSERT2(0,
"kmp_trait::match() must be overridden");
114 void *
operator new(
size_t size) {
return KMP_INTERNAL_MALLOC(size); }
115 void operator delete(
void *ptr) { KMP_INTERNAL_FREE(ptr); }
117 virtual bool operator==(
const kmp_trait &other)
const {
118 return _type == other._type;
127 bool match([[maybe_unused]]
int device)
const override {
return true; }
129 bool operator==(
const kmp_trait &other)
const override {
130 return kmp_trait::operator==(other);
140 : kmp_trait(LITERAL_T), device_num(device_num) {
141 assert(device_num >= 0 &&
"Device number must be non-negative");
144 bool match(
int device)
const override {
return device_num == device; }
146 bool operator==(
const kmp_trait &other)
const override {
147 return kmp_trait::operator==(other) &&
161 const char *(*get_uid_from_device)(
int device) = omp_get_uid_from_device;
168 KMP_INTERNAL_FREE(uid);
171 bool match(
int device)
const override {
172 const char *device_uid = get_uid_from_device(device);
173 if (!device_uid || !uid)
175 return strcmp(device_uid, uid) == 0;
180 void set_uid_from_device(
const char *(*uid_from_device)(
int)) {
181 get_uid_from_device = uid_from_device;
184 bool operator==(
const kmp_trait &other)
const override {
185 if (!kmp_trait::operator==(other))
187 const char *other_uid =
static_cast<const kmp_uid_trait &
>(other).uid;
188 return uid && other_uid ? strcmp(uid, other_uid) == 0 : uid == other_uid;
196 enum expr_type { SINGLE_T, GROUP_T };
199 bool negated =
false;
201 int (*get_num_devices)() = omp_get_num_devices;
205 : _type(type), negated(negated) {}
209 virtual bool match_impl([[maybe_unused]]
int device,
210 [[maybe_unused]]
int num_devices)
const {
211 KMP_ASSERT2(0,
"kmp_trait_expr::match_impl() must be overridden");
223 bool is_negated()
const {
return negated; }
226 bool match(
int device,
int num_devices = -1)
const {
227 if (num_devices == -1)
228 num_devices = get_num_devices();
229 if (device < 0 || device >= num_devices)
231 return match_impl(device, num_devices);
234 void set_negated(
bool neg =
true) { negated = neg; }
238 void set_num_devices(
int (*num_devices)()) { get_num_devices = num_devices; }
241 void *
operator new(
size_t size) {
return KMP_INTERNAL_MALLOC(size); }
242 void operator delete(
void *ptr) { KMP_INTERNAL_FREE(ptr); }
245 return _type == other._type && negated == other.negated;
251 kmp_trait *trait =
nullptr;
254 bool match_impl(
int device, [[maybe_unused]]
int num_devices)
const override {
256 bool result = trait->match(device);
257 return negated ? !result : result;
265 assert(trait &&
"kmp_trait_expr_single requires a non-null trait");
269 void set_trait(kmp_trait *new_trait) {
277 if (!kmp_trait_expr::operator==(other))
281 return trait && other_single.trait ? *trait == *other_single.trait
282 : trait == other_single.trait;
290 enum group_type { AND, OR };
295 group_type type = OR;
298 bool match_impl(
int device,
int num_devices)
const override {
301 if (expr->match(device, num_devices))
305 bool result = type == AND ? matched == exprs.size() : matched > 0;
306 return negated ? !result : result;
317 void add_expr(kmp_trait *trait) {
325 expr->set_num_devices(get_num_devices);
328 group_type get_group_type()
const {
return type; }
330 void set_group_type(group_type new_type) { type = new_type; }
332 void set_num_devices(
int (*num_devices)()) {
333 kmp_trait_expr::set_num_devices(num_devices);
335 expr->set_num_devices(num_devices);
339 if (!kmp_trait_expr::operator==(other))
343 return type == other_group.type &&
350class kmp_trait_clause final {
354 kmp_trait_clause() =
default;
355 ~kmp_trait_clause() {
delete expr; }
357 kmp_trait_clause(
const kmp_trait_clause &) =
delete;
358 kmp_trait_clause(kmp_trait_clause &&) =
delete;
359 kmp_trait_clause &operator=(
const kmp_trait_clause &) =
delete;
360 kmp_trait_clause &operator=(kmp_trait_clause &&) =
delete;
362 kmp_trait_expr *get_expr() {
return expr; }
364 bool match(
int device,
int num_devices = -1)
const {
366 return expr->match(device, num_devices);
369 void set_expr(kmp_trait *trait) {
373 expr =
new kmp_trait_expr_single(trait);
375 void set_expr(kmp_trait_expr *new_expr) {
383 void *
operator new(
size_t size) {
return KMP_INTERNAL_MALLOC(size); }
384 void operator delete(
void *ptr) { KMP_INTERNAL_FREE(ptr); }
386 bool operator==(
const kmp_trait_clause &other)
const {
387 return expr && other.expr ? *expr == *other.expr : expr == other.expr;
393class kmp_trait_context final {
394 using kmp_trait_clause = kmp_traits::kmp_trait_clause;
400 bool evaluated =
false;
402 int (*get_num_devices)() = kmp_traits::omp_get_num_devices;
406 for (
int d = 0; d < get_num_devices(); ++d) {
413 bool _match(
int device)
const {
414 if (device < 0 || device >= get_num_devices())
416 for (kmp_trait_clause *clause : clauses) {
417 if (clause->match(device))
424 kmp_trait_context() =
default;
425 ~kmp_trait_context() {
426 for (kmp_trait_clause *clause : clauses)
430 kmp_trait_context(
const kmp_trait_context &) =
delete;
431 kmp_trait_context(kmp_trait_context &&) =
delete;
432 kmp_trait_context &operator=(
const kmp_trait_context &) =
delete;
433 kmp_trait_context &operator=(kmp_trait_context &&) =
delete;
438 static kmp_trait_context *parse_from_spec(
kmp_str_ref spec,
439 const char *dbg_name =
nullptr);
441 void add_clause(kmp_trait_clause *clause) {
445 if (kmp_trait_expr *expr = clause->get_expr())
446 expr->set_num_devices(get_num_devices);
456 trigger_evaluation();
461 assert(evaluated &&
"kmp_trait_context not evaluated");
467 bool match(
int device) {
return evaluate().
contains(device); }
469 bool match(
int device)
const {
470 assert(evaluated &&
"kmp_trait_context not evaluated");
476 void set_num_devices(
int (*num_devices)()) {
477 get_num_devices = num_devices;
478 for (kmp_trait_clause *clause : clauses) {
479 if (kmp_trait_expr *expr = clause->get_expr())
480 expr->set_num_devices(num_devices);
485 void trigger_evaluation() {
491 void *
operator new(
size_t size) {
return KMP_INTERNAL_MALLOC(size); }
492 void operator delete(
void *ptr) { KMP_INTERNAL_FREE(ptr); }
494 bool operator==(
const kmp_trait_context &other)
const {
495 auto clause_comp = [](kmp_trait_clause *
const &a,
496 kmp_trait_clause *
const &b) {
return *a == *b; };
497 return clauses.
is_set_equal(other.clauses, clause_comp);
502 const int *begin() {
return evaluate().begin(); }
503 const int *end() {
return evaluate().end(); }
504 const int *begin()
const {
return evaluate().begin(); }
505 const int *end()
const {
return evaluate().end(); }
kmp_str_ref is a non-owning string class (similar to llvm::StringRef).
Represents a specific device number.
Represents a single (possibly negated) trait.
Represents a wildcard trait that matches any device.
void clear()
Destroy all elements in the vector. Doesn't free the memory.
void push_back(const T &value)
Add a new element to the end of the vector.
bool is_set_equal(const kmp_vector &other, const Fn &comp=Fn{}) const
bool contains(const T &value, const Fn &comp=Fn{}) const