mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
WasmUtil.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "backend/WasmDSL.hpp"
4#include <functional>
9#include <optional>
10#include <variant>
11
13
14
15namespace m {
16
17namespace wasm {
18
19// forward declarations
20struct Environment;
21template<bool IsGlobal> struct Buffer;
22template<bool IsGlobal> struct buffer_load_proxy_t;
23template<bool IsGlobal> struct buffer_store_proxy_t;
24template<bool IsGlobal> struct buffer_swap_proxy_t;
25
26
27/*======================================================================================================================
28 * Declare SQL helper type for character sequences
29 *====================================================================================================================*/
30
31struct NChar : Ptr<Charx1>
32{
34
35 private:
38
39 public:
41 : Ptr<Charx1>(ptr), can_be_null_(can_be_null), type_(type)
42 { }
44 : Ptr<Charx1>(ptr)
46 , type_(guarantees_terminating_nul ? Type::Get_Varchar(Type::TY_Scalar, length)
47 : Type::Get_Char(Type::TY_Scalar, length))
48 { }
49
50 NChar(NChar&) = default;
51 NChar(NChar&&) = default;
52
54
55 Ptr<Charx1> val() { return *this; }
56
58 if (can_be_null())
59 Wasm_insist(clone().not_null(), "must not be NULL");
60 return val();
61 }
62
63 Boolx1 is_null() {
64 if (can_be_null()) {
65 return Ptr<Charx1>::is_null();
66 } else {
67 discard();
68 return Boolx1(false);
69 }
70 }
71 Boolx1 not_null() {
72 if (can_be_null()) {
73 return Ptr<Charx1>::not_null();
74 } else {
75 discard();
76 return Boolx1(true);
77 }
78 }
79
80 bool can_be_null() const { return can_be_null_; }
81 std::size_t length() const { return type_->length; }
82 uint64_t size_in_bytes() const { return type_->size() / 8; }
84};
85
86
87/*======================================================================================================================
88 * Decimal
89 *====================================================================================================================*/
90
91template<signed_integral Base>
92struct Decimal : Expr<Base>
93{
95 using arithmetic_type = Base;
96
97 private:
99 uint32_t scale_;
100
101 public:
105 M_insist(scale != 0);
106 }
107
111
112 Decimal(Decimal &other) : Decimal(other.val(), other.scale_) { }
113 Decimal(Decimal &&other) : Decimal(other.val(), other.scale_) { }
114
117 static Decimal Scaled(expr_type value, uint32_t scale) {
118 const arithmetic_type scaling_factor = powi(arithmetic_type(10), scale);
119 return Decimal(value * scaling_factor, scale);
120 }
121
122
123 public:
124 expr_type val() { return *this; }
125
126 uint32_t scale() const { return scale_; }
127
128 template<signed_integral To>
129 Expr<To> to() { return val().template to<To>() / powi(To(10), To(scale_)); }
130
131 Decimal clone() const { return Decimal(expr_type::clone(), scale_); }
132
133
134 /*------------------------------------------------------------------------------------------------------------------
135 * Unary operations
136 *----------------------------------------------------------------------------------------------------------------*/
137
140 requires false
141 { M_unreachable("modulo division on decimals is not defined"); }
142
143
144 /*------------------------------------------------------------------------------------------------------------------
145 * Binary operations
146 *----------------------------------------------------------------------------------------------------------------*/
147
149 if (this->scale_ == other.scale_)
150 return Decimal(this->val() + other.val(), scale_); // fall back to regular integer arithmetic
151
152 if (this->scale() > other.scale()) {
153 const arithmetic_type scaling_factor = powi(arithmetic_type(10), this->scale() - other.scale());
154 return Decimal(this->val() + (other * scaling_factor).val() , this->scale());
155 } else {
156 const arithmetic_type scaling_factor = powi(arithmetic_type(10), other.scale() - this->scale());
157 return Decimal((*this * scaling_factor).val() + other.val() , other.scale());
158 }
159 }
160
161 template<typename T>
163 Decimal operator+(T &&other) { return Decimal(*this + Scaled(expr_t<T>(other), scale_)); }
164
166 if (this->scale_ == other.scale_)
167 return Decimal(this->val() - other.val(), scale_); // fall back to regular integer arithmetic
168
169 if (this->scale() > other.scale()) {
170 const arithmetic_type scaling_factor = powi(arithmetic_type(10), this->scale() - other.scale());
171 return Decimal(this->val() - (other * scaling_factor).val() , this->scale());
172 } else {
173 const arithmetic_type scaling_factor = powi(arithmetic_type(10), other.scale() - this->scale());
174 return Decimal((*this * scaling_factor).val() - other.val() , other.scale());
175 }
176 }
177
178 template<typename T>
180 Decimal operator-(T &&other) { return Decimal(*this - Scaled(expr_t<T>(other), scale_)); }
181
183 uint32_t smaller_scale = this->scale();
184 uint32_t higher_scale = other.scale();
185 if (smaller_scale > higher_scale)
186 std::swap(smaller_scale, higher_scale);
187 M_insist(smaller_scale <= higher_scale);
188 const arithmetic_type scaling_factor = powi(arithmetic_type(10), smaller_scale);
189 return Decimal((this->val() * other.val()) / scaling_factor, higher_scale);
190 }
191
192 template<typename T>
194 Decimal operator*(T &&other) { return Decimal(this->val() * expr_t<T>(other), scale()); }
195
197 const uint32_t scale_res = std::max(this->scale(), other.scale());
198 const arithmetic_type scaling_factor = powi(arithmetic_type(10), scale_res + other.scale() - this->scale());
199 return Decimal((this->val() * scaling_factor) / other.val(), scale_res);
200 }
201
202 template<typename T>
204 Decimal operator/(T &&other) { return Decimal(this->val() / expr_t<T>(other), scale()); }
205
207 template<typename T>
208 requires false
209 Decimal operator%(T&&) { M_unreachable("modulo division on decimals is not defined"); }
210
212 template<typename T>
213 requires false
214 Decimal operator bitand(T&&) { M_unreachable("bitwise and on decimals is not defined"); }
215
217 template<typename T>
218 requires false
219 Decimal operator bitor(T&&) { M_unreachable("bitwise or on decimals is not defined"); }
220
222 template<typename T>
223 requires false
224 Decimal operator xor(T&&) { M_unreachable("exclusive or on decimals is not defined"); }
225
227 template<typename T>
228 requires false
229 Decimal operator<<(T&&) { M_unreachable("shift left on decimals is not defined"); }
230
232 template<typename T>
233 requires false
234 Decimal operator>>(T&&) { M_unreachable("shift right on decimals is not defined"); }
235
237 template<typename T>
238 requires false
239 Decimal rotl(T&&) { M_unreachable("rotate left on decimals is not defined"); }
240
242 template<typename T>
243 requires false
244 Decimal rotr(T&&) { M_unreachable("rotate right on decimals is not defined"); }
245
246
247 friend std::ostream & operator<<(std::ostream &out, const Decimal &d) {
248 return out << "Decimal: " << static_cast<const expr_type&>(d) << ", scale = " << d.scale_;
249 }
250
251 void dump(std::ostream &out) const { out << *this << std::endl; }
252 void dump() const { dump(std::cerr); }
253};
254
255/*----------------------------------------------------------------------------------------------------------------------
256 * Binary operations
257 *--------------------------------------------------------------------------------------------------------------------*/
258
259template<typename Base>
260requires expr_convertible<Base> and signed_integral<typename expr_t<Base>::type>
262{
263 return right + left;
264}
265
266template<typename Base>
267requires expr_convertible<Base> and signed_integral<typename expr_t<Base>::type>
269{
270 return Decimal<typename expr_t<Base>::type>::Scaled(expr_t<Base>(left), right.scale()) - right;
271}
272
273template<typename Base>
274requires expr_convertible<Base> and signed_integral<typename expr_t<Base>::type>
276{
277 return right * left;
278}
279
280template<typename Base>
281requires expr_convertible<Base> and signed_integral<typename expr_t<Base>::type>
283{
284 return Decimal<typename expr_t<Base>::type>(expr_t<Base>(left), 0) / right;
285}
286
289
290
291
292/*======================================================================================================================
293 * Declare valid SQL types
294 *====================================================================================================================*/
295
296template<typename>
298
299template<typename>
301
302#define SQL_TYPES_SCALAR(X) \
303 X(_Boolx1) \
304 X(_I8x1) \
305 X(_I16x1) \
306 X(_I32x1) \
307 X(_I64x1) \
308 X(_Floatx1) \
309 X(_Doublex1) \
310 X(NChar)
311
312#define SQL_ADDR_TYPES_SCALAR(X) \
313 X(Ptr<Boolx1>) \
314 X(Ptr<I8x1>) \
315 X(Ptr<I16x1>) \
316 X(Ptr<I32x1>) \
317 X(Ptr<I64x1>) \
318 X(Ptr<Floatx1>) \
319 X(Ptr<Doublex1>) \
320 X(NChar)
321
322#define SQL_TYPES(X) \
323 SQL_TYPES_SCALAR(X) \
324 X(_Boolx16) \
325 X(_Boolx32) \
326 X(_I8x16) \
327 X(_I8x32) \
328 X(_I16x8) \
329 X(_I16x16) \
330 X(_I16x32) \
331 X(_I32x4) \
332 X(_I32x8) \
333 X(_I32x16) \
334 X(_I32x32) \
335 X(_I64x2) \
336 X(_I64x4) \
337 X(_I64x8) \
338 X(_I64x16) \
339 X(_I64x32) \
340 X(_Floatx4) \
341 X(_Floatx8) \
342 X(_Floatx16) \
343 X(_Floatx32) \
344 X(_Doublex2) \
345 X(_Doublex4) \
346 X(_Doublex8) \
347 X(_Doublex16) \
348 X(_Doublex32)
349
350#define SQL_ADDR_TYPES(X) \
351 SQL_ADDR_TYPES_SCALAR(X) \
352 X(Ptr<Boolx16>) \
353 X(Ptr<Boolx32>) \
354 X(Ptr<I8x16>) \
355 X(Ptr<I8x32>) \
356 X(Ptr<I16x8>) \
357 X(Ptr<I16x16>) \
358 X(Ptr<I16x32>) \
359 X(Ptr<I32x4>) \
360 X(Ptr<I32x8>) \
361 X(Ptr<I32x16>) \
362 X(Ptr<I32x32>) \
363 X(Ptr<I64x2>) \
364 X(Ptr<I64x4>) \
365 X(Ptr<I64x8>) \
366 X(Ptr<I64x16>) \
367 X(Ptr<I64x32>) \
368 X(Ptr<Floatx4>) \
369 X(Ptr<Floatx8>) \
370 X(Ptr<Floatx16>) \
371 X(Ptr<Floatx32>) \
372 X(Ptr<Doublex2>) \
373 X(Ptr<Doublex4>) \
374 X(Ptr<Doublex8>) \
375 X(Ptr<Doublex16>) \
376 X(Ptr<Doublex32>)
377
378#define ADD_EXPR_SQL_TYPE(TYPE) template<> struct is_sql_type<TYPE>{};
380#undef ADD_EXPR_SQL_TYPE
381
382#define ADD_EXPR_SQL_ADDR_TYPE(TYPE) template<> struct is_sql_addr_type<TYPE>{};
384#undef ADD_EXPR_SQL_ADDR_TYPE
385
386template<typename T>
387concept sql_type = requires { is_sql_type<T>{}; };
388
389template<typename T>
390concept sql_addr_type = requires { is_sql_addr_type<T>{}; };
391
392using SQL_t = std::variant<
393 std::monostate
394#define ADD_TYPE(TYPE) , TYPE
396#undef ADD_TYPE
397>;
398
399using SQL_addr_t = std::variant<
400 std::monostate
401#define ADD_TYPE(TYPE) , TYPE
403#undef ADD_TYPE
404>;
405
406template<typename T>
408
409using SQL_boolean_t = std::variant<std::monostate, _Boolx1, _Boolx16, _Boolx32>;
410
411
412/*======================================================================================================================
413 * Helper functions for SQL types
414 *====================================================================================================================*/
415
416inline void discard(SQL_t &variant)
417{
418 std::visit(overloaded {
419 []<sql_type T>(T actual) -> void { actual.discard(); },
420 [](std::monostate) -> void { M_unreachable("invalid variant"); },
421 }, variant);
422}
423
424inline void discard(SQL_addr_t &variant)
425{
426 std::visit(overloaded {
427 []<sql_addr_type T>(T actual) -> void { actual.discard(); },
428 [](std::monostate) -> void { M_unreachable("invalid variant"); },
429 }, variant);
430}
431
432template<sql_type To>
433inline To convert(SQL_t &variant)
434{
435 using type = typename To::type;
436 static constexpr std::size_t num_simd_lanes = To::num_simd_lanes;
437
438 return std::visit(overloaded {
439 [](auto actual) -> To requires requires { actual.template to<type, num_simd_lanes>(); } {
440 return actual.template to<type, num_simd_lanes>();
441 },
442 [](NChar actual) -> NChar requires std::same_as<To, NChar> {
443 return actual;
444 },
445 [](auto actual) -> To requires (not requires { actual.template to<type, num_simd_lanes>(); }) {
446 M_unreachable("illegal conversion");
447 },
448 [](std::monostate) -> To { M_unreachable("invalid variant"); },
449 }, variant);
450}
451
452inline bool can_be_null(const SQL_t &variant)
453{
454 return std::visit(overloaded {
455 []<sql_type T>(const T &actual) -> bool { return actual.can_be_null(); },
456 [](std::monostate) -> bool { M_unreachable("invalid variant"); },
457 }, variant);
458}
459
460template<std::size_t L = 1>
461inline Bool<L> is_null(SQL_t &variant)
462{
463 return std::visit(overloaded {
464 []<sql_type T>(T actual) -> Bool<L> requires requires { { actual.is_null() } -> std::same_as<Bool<L>>; } {
465 return actual.is_null();
466 },
467 []<sql_type T>(T actual) -> Bool<L> requires (not requires { { actual.is_null() } -> std::same_as<Bool<L>>; }) {
468 M_unreachable("invalid type for given number of SIMD lanes");
469 },
470 [](std::monostate) -> Bool<L> { M_unreachable("invalid variant"); },
471 }, variant);
472}
473
474template<std::size_t L = 1>
475inline Bool<L> not_null(SQL_t &variant)
476{
477 return std::visit(overloaded {
478 []<sql_type T>(T actual) -> Bool<L> requires requires { { actual.not_null() } -> std::same_as<Bool<L>>; } {
479 return actual.not_null();
480 },
481 []<sql_type T>(T actual) -> Bool<L> requires (not requires { { actual.not_null() } -> std::same_as<Bool<L>>; }) {
482 M_unreachable("invalid type for given number of SIMD lanes");
483 },
484 [](std::monostate) -> Bool<L> { M_unreachable("invalid variant"); },
485 }, variant);
486}
487
488
489/*======================================================================================================================
490 * ExprCompiler
491 *====================================================================================================================*/
492
494struct ExprCompiler : ast::ConstASTExprVisitor
495{
496 private:
501
502 public:
503 ExprCompiler(const Environment &env) : env_(env) { }
504
507 (*this)(e);
508 return std::move(intermediate_result_);
509 }
511 template<sql_type T>
513 (*this)(e);
514 M_insist(std::holds_alternative<T>(intermediate_result_));
515 return *std::get_if<T>(&intermediate_result_);
516 }
517
519 SQL_boolean_t compile(const cnf::CNF &cnf);
520
522 template<sql_boolean_type T>
523 T compile(const cnf::CNF &cnf) {
524 auto result = compile(cnf);
525 M_insist(std::holds_alternative<T>(result));
526 return *std::get_if<T>(&result);
527 }
528
529 private:
530 using ConstASTExprVisitor::operator();
531 void operator()(const ast::ErrorExpr&) override;
532 void operator()(const ast::Designator &op) override;
533 void operator()(const ast::Constant &op) override;
534 void operator()(const ast::UnaryExpr &op) override;
535 void operator()(const ast::BinaryExpr &op) override;
536 void operator()(const ast::FnApplicationExpr &op) override;
537 void operator()(const ast::QueryExpr &op) override;
538
539 SQL_t get() { return std::move(intermediate_result_); }
540
541 template<sql_type T>
542 T get() {
543 M_insist(std::holds_alternative<T>(intermediate_result_));
544 return *std::get_if<T>(&intermediate_result_);
545 }
546
547 void set(SQL_t &&value) {
548 intermediate_result_.~SQL_t(); // destroy old
549 new (&intermediate_result_) SQL_t(std::move(value)); // placement-new
550 }
551
552 template<sql_type T>
553 void set(T &&value) { set(SQL_t(std::forward<T>(value))); }
554};
555
556
557/*======================================================================================================================
558 * Environment
559 *====================================================================================================================*/
560
563{
564 private:
566 std::unordered_map<Schema::Identifier, SQL_t> exprs_;
568 std::unordered_map<Schema::Identifier, SQL_addr_t> expr_addrs_;
571
572 public:
573 Environment() = default;
574 Environment(const Environment&) = delete;
576
578 for (auto &p : exprs_)
579 discard(p.second);
580 for (auto &p : expr_addrs_)
581 discard(p.second);
582 /* do not discard `predicate_` to make sure predication predicate is used if it was set */
583 }
584
585 /*----- Access methods -------------------------------------------------------------------------------------------*/
587 bool has(const Schema::Identifier &id) const { return exprs_.find(id) != exprs_.end(); }
589 bool has_addr(const Schema::Identifier &id) const { return expr_addrs_.find(id) != expr_addrs_.end(); }
591 template<sql_type T>
592 bool is(const Schema::Identifier &id) const {
593 auto it = exprs_.find(id);
594 M_insist(it != exprs_.end(), "identifier not found");
595 return std::holds_alternative<T>(it->second);
596 }
598 template<sql_addr_type T>
600 auto it = expr_addrs_.find(id);
601 M_insist(it != expr_addrs_.end(), "identifier not found");
602 return std::holds_alternative<T>(it->second);
603 }
605 bool empty() const { return exprs_.empty() and expr_addrs_.empty(); }
606
608 void clear() {
609 for (auto &p : exprs_)
610 discard(p.second);
611 for (auto &p : expr_addrs_)
612 discard(p.second);
613 exprs_.clear();
614 expr_addrs_.clear();
615 }
616
618 template<sql_type T>
620 auto res = exprs_.emplace(std::move(id), std::forward<T>(expr));
621 M_insist(res.second, "duplicate ID");
622 }
625 auto res = exprs_.emplace(std::move(id), std::move(expr));
626 M_insist(res.second, "duplicate ID");
627 }
628
630 template<sql_addr_type T>
632 auto res = expr_addrs_.emplace(id, std::forward<T>(expr));
633 M_insist(res.second, "duplicate ID");
634 }
637 auto res = expr_addrs_.emplace(id, std::move(expr));
638 M_insist(res.second, "duplicate ID");
639 }
640
642 void add(const Environment &other) {
643 for (auto &p : other.exprs_) {
644 std::visit(overloaded {
645 [](std::monostate) -> void { M_unreachable("invalid expression"); },
646 [this, &p](auto &e) -> void { this->add(p.first, e.clone()); },
647 }, p.second);
648 }
649 for (auto &p : other.expr_addrs_) {
650 std::visit(overloaded {
651 [](std::monostate) -> void { M_unreachable("invalid expression"); },
652 [this, &p](auto &e) -> void { this->add_addr(p.first, e.clone()); },
653 }, p.second);
654 }
655 }
657 void add(Environment &&other) {
658 this->exprs_.merge(other.exprs_);
659 M_insist(other.exprs_.empty(), "duplicate ID not moved from other to this");
660 this->expr_addrs_.merge(other.expr_addrs_);
661 M_insist(other.expr_addrs_.empty(), "duplicate ID not moved from other to this");
662 }
663
666 auto it = exprs_.find(id);
667 M_insist(it != exprs_.end(), "identifier not found");
668 auto nh = exprs_.extract(it);
669 return std::move(nh.mapped());
670 }
672 template<sql_type T>
674 auto it = exprs_.find(id);
675 M_insist(it != exprs_.end(), "identifier not found");
676 auto nh = exprs_.extract(it);
677 M_insist(std::holds_alternative<T>(nh.mapped()));
678 return *std::get_if<T>(&nh.mapped());
679 }
680
683 auto it = expr_addrs_.find(id);
684 M_insist(it != expr_addrs_.end(), "identifier not found");
685 auto nh = expr_addrs_.extract(it);
686 return std::move(nh.mapped());
687 }
689 template<sql_addr_type T>
691 auto it = expr_addrs_.find(id);
692 M_insist(it != expr_addrs_.end(), "identifier not found");
693 auto nh = expr_addrs_.extract(it);
694 M_insist(std::holds_alternative<T>(nh.mapped()));
695 return *std::get_if<T>(&nh.mapped());
696 }
697
699 SQL_t get(const Schema::Identifier &id) const {
700 auto it = exprs_.find(id);
701 M_insist(it != exprs_.end(), "identifier not found");
702 return std::visit(overloaded {
703 [](auto &e) -> SQL_t { return e.clone(); },
704 [](std::monostate) -> SQL_t { M_unreachable("invalid expression"); },
705 }, it->second);
706 }
708 template<sql_type T>
709 T get(const Schema::Identifier &id) const {
710 auto it = exprs_.find(id);
711 M_insist(it != exprs_.end(), "identifier not found");
712 M_insist(std::holds_alternative<T>(it->second));
713 return std::get_if<T>(&it->second)->clone();
714 }
715
718 auto it = expr_addrs_.find(id);
719 M_insist(it != expr_addrs_.end(), "identifier not found");
720 return std::visit(overloaded {
721 [](auto &e) -> SQL_addr_t { return e.clone(); },
722 [](std::monostate) -> SQL_addr_t { M_unreachable("invalid expression"); },
723 }, it->second);
724 }
726 template<sql_addr_type T>
727 T get_addr(const Schema::Identifier &id) const {
728 auto it = expr_addrs_.find(id);
729 M_insist(it != expr_addrs_.end(), "identifier not found");
730 M_insist(std::holds_alternative<T>(it->second));
731 return std::get_if<T>(&it->second)->clone();
732 }
733
735 SQL_t operator[](const Schema::Identifier &id) const { return get(id); }
736
737
738 /*----- Expression and CNF compilation ---------------------------------------------------------------------------*/
740 template<typename T>
741 requires requires (ExprCompiler C, T &&t) { C.compile(std::forward<T>(t)); }
742 auto compile(T &&t) const {
743 ExprCompiler C(*this);
744 return C.compile(std::forward<T>(t));
745 }
747 template<typename T, typename U>
748 requires requires (ExprCompiler C, U &&u) { C.compile<T>(std::forward<U>(u)); }
749 auto compile(U &&u) const {
750 ExprCompiler C(*this);
751 return C.compile<T>(std::forward<U>(u));
752 }
753
754 /*----- Predication ----------------------------------------------------------------------------------------------*/
756 bool predicated() const { return not std::holds_alternative<std::monostate>(predicate_); }
757
760 std::visit(overloaded {
761 [](std::monostate) -> void { M_unreachable("invalid predicate"); },
762 [this]<sql_boolean_type T>(T &&e) -> void { this->add_predicate<T>(std::forward<T>(e)); },
763 }, std::forward<SQL_boolean_t>(pred));
764 }
766 template<sql_boolean_type T>
767 void add_predicate(T &&pred) {
768 if (predicated()) {
769 auto old = extract_predicate<T>();
770 new (&predicate_) SQL_boolean_t(old and std::forward<T>(pred)); // placement-new
771 } else {
772 new (&predicate_) SQL_boolean_t(std::forward<T>(pred)); // placement-new
773 }
774 }
776 void add_predicate(const cnf::CNF &cnf) { add_predicate(compile(cnf)); }
777
780 M_insist(predicated(), "cannot access an undefined or already extracted predicate");
781 auto tmp = std::move(predicate_);
782 new (&predicate_) SQL_boolean_t(std::monostate()); // placement-new
783 return tmp;
784 }
786 template<sql_boolean_type T>
788 M_insist(predicated(), "cannot access an undefined or already extracted predicate");
789 M_insist(std::holds_alternative<T>(predicate_));
790 auto tmp = *std::get_if<T>(&predicate_);
791 predicate_.~SQL_boolean_t(); // destroy old
792 new (&predicate_) SQL_boolean_t(std::monostate()); // placement-new
793 return tmp;
794 }
795
798 return std::visit(overloaded {
799 [](const std::monostate&) -> SQL_boolean_t {
800 M_unreachable("cannot access an undefined or already extracted predicate");
801 },
802 [](const auto &e) -> SQL_boolean_t { return e.clone(); },
803 }, predicate_);
804 }
806 template<sql_boolean_type T>
807 T get_predicate() const {
808 M_insist(predicated(), "cannot access an undefined or already extracted predicate");
809 M_insist(std::holds_alternative<T>(predicate_));
810 return std::get_if<T>(&predicate_)->clone();
811 }
812
813 void dump(std::ostream &out) const;
814 void dump() const;
815};
816
817
818/*======================================================================================================================
819 * CodeGenContext
820 *====================================================================================================================*/
821
822struct Scope
823{
824 friend struct CodeGenContext;
825
826 private:
829
830 Scope() = delete;
831 Scope(Environment inner);
832
833 Scope(const Scope&) = delete;
834 Scope(Scope&&) = default;
835
836 public:
837 ~Scope();
838
841};
842
852{
853 friend struct Scope;
854
855 private:
856 Environment *env_ = nullptr;
858 std::unordered_map<const char*, std::pair<uint32_t, NChar>> literals_;
860 std::size_t num_simd_lanes_ = 1;
863
864 public:
865 CodeGenContext() = default;
867
869#ifdef M_ENABLE_SANITY_FIELDS
870 num_tuples_.val().discard(); // artificial use of `num_tuples_` to silence diagnostics if unittests are executed
871#endif
872 for (auto &p : literals_)
873 p.second.second.discard();
874 }
875
876 /*----- Thread-local instance ------------------------------------------------------------------------------------*/
877 private:
878 static thread_local std::unique_ptr<CodeGenContext> the_context_;
879
880 public:
881 static void Init() {
882 M_insist(not the_context_, "must not have a context yet");
883 the_context_ = std::make_unique<CodeGenContext>();
884 }
885 static void Dispose() {
886 M_insist(bool(the_context_), "must have a context");
887 the_context_ = nullptr;
888 }
889 static CodeGenContext & Get() {
890 M_insist(bool(the_context_), "must have a context");
891 return *the_context_;
892 }
893
902
903 /*----- Access methods -------------------------------------------------------------------------------------------*/
905 Environment & env() { M_insist(bool(env_)); return *env_; }
907 const Environment & env() const { M_insist(bool(env_)); return *env_; }
908
910 U32x1 num_tuples() const { return num_tuples_; }
912 void set_num_tuples(U32x1 n) { num_tuples_ = n; }
914 void inc_num_tuples(U32x1 n = U32x1(1)) { num_tuples_ += n; }
915
917 void add_literal(const char *literal, uint32_t ptr) {
918 auto [_, inserted] = literals_.emplace(
919 std::piecewise_construct,
920 std::forward_as_tuple(literal),
921 std::forward_as_tuple(ptr, NChar(Ptr<Charx1>(U32x1(ptr)), false, strlen(literal) + 1, true))
922 );
923 M_insist(inserted);
924 }
926 uint32_t get_literal_raw_address(const char *literal) const {
927 auto it = literals_.find(literal);
928 M_insist(it != literals_.end(), "unknown literal");
929 return it->second.first;
930 }
932 NChar get_literal_address(const char *literal) const {
933 auto it = literals_.find(literal);
934 M_insist(it != literals_.end(), "unknown literal");
935 return it->second.second.clone();
936 }
937
939 std::size_t num_simd_lanes() const { return num_simd_lanes_; }
941 void set_num_simd_lanes(std::size_t n) { num_simd_lanes_ = n; }
942
948 }
949};
950
952 : inner_(std::move(inner))
953{
954 outer_ = std::exchange(CodeGenContext::Get().env_, &inner_);
955}
956
958{
960}
961
963{
965 return std::move(inner_);
966}
967
968
969/*======================================================================================================================
970 * compile data layout
971 *====================================================================================================================*/
972
985template<VariableKind Kind>
986std::tuple<Block, Block, Block>
987compile_store_sequential(const Schema &tuple_value_schema, const Schema &tuple_addr_schema, Ptr<void> base_address,
988 const storage::DataLayout &layout, std::size_t num_simd_lanes, const Schema &layout_schema,
990
1003template<VariableKind Kind>
1004std::tuple<Block, Block, Block>
1005compile_store_sequential_single_pass(const Schema &tuple_value_schema, const Schema &tuple_addr_schema,
1006 Ptr<void> base_address, const storage::DataLayout &layout,
1007 std::size_t num_simd_lanes, const Schema &layout_schema,
1009
1020template<VariableKind Kind>
1021std::tuple<Block, Block, Block>
1022compile_load_sequential(const Schema &tuple_value_schema, const Schema &tuple_addr_schema, Ptr<void> base_address,
1023 const storage::DataLayout &layout, std::size_t num_simd_lanes, const Schema &layout_schema,
1025
1031void compile_store_point_access(const Schema &tuple_value_schema, const Schema &tuple_addr_schema,
1032 Ptr<void> base_address, const storage::DataLayout &layout, const Schema &layout_schema,
1033 U32x1 tuple_id);
1034
1041void compile_load_point_access(const Schema &tuple_value_schema, const Schema &tuple_addr_schema,
1042 Ptr<void> base_address, const storage::DataLayout &layout, const Schema &layout_schema,
1043 U32x1 tuple_id);
1044
1045
1046/*======================================================================================================================
1047 * Buffer
1048 *====================================================================================================================*/
1049
1050template<bool IsGlobal>
1052
1053template<>
1054class buffer_storage<false> {};
1055
1056template<>
1058{
1059 friend struct Buffer<true>;
1060
1064 std::optional<Global<U32x1>> capacity_;
1065};
1066
1068template<bool IsGlobal>
1070{
1071 private:
1073 using param_t = std::optional<std::reference_wrapper<const Schema>>;
1074
1075 std::reference_wrapper<const Schema> schema_;
1077 bool load_simdfied_ = false;
1078 std::optional<Var<Ptr<void>>> base_address_;
1079 std::optional<Var<U32x1>> size_;
1080 std::optional<Var<U32x1>> capacity_;
1081 std::optional<Var<Boolx1>> first_iteration_;
1087 mutable std::optional<FunctionProxy<void(void*, uint32_t)>> resume_pipeline_;
1088
1089 public:
1094 Buffer(const Schema &schema, const storage::DataLayoutFactory &factory, bool load_simdfied = false,
1095 std::size_t num_tuples = 0, setup_t setup = setup_t::Make_Without_Parent(),
1097
1098 Buffer(const Buffer&) = delete;
1099 Buffer(Buffer&&) = default;
1100
1101 ~Buffer();
1102
1103 Buffer & operator=(Buffer&&) = default;
1104
1106 const Schema & schema() const { return schema_; }
1108 const storage::DataLayout & layout() const { return layout_; }
1111 if constexpr (IsGlobal) {
1112 return base_address_ ? base_address_->val() : storage_.base_address_.val(); // since global may be outdated
1113 } else {
1114 M_insist(bool(base_address_));
1115 return *base_address_;
1116 }
1117 }
1119 U32x1 size() const {
1120 if constexpr (IsGlobal) {
1121 return size_ ? size_->val() : storage_.size_.val(); // since global may be outdated
1122 } else {
1123 M_insist(bool(size_));
1124 return *size_;
1125 }
1126 }
1127
1131 param_t tuple_addr_schema = param_t()) const;
1138
1141 void setup();
1144 void teardown();
1145
1147 void setup_base_address() requires IsGlobal {
1148 M_insist(not base_address_, "must not call `setup_base_address()` twice");
1149 if (not layout_.is_finite()) {
1150 M_insist(bool(storage_.capacity_));
1151 Wasm_insist(*storage_.capacity_ != 0U, "buffer must be already allocated");
1152 }
1153 base_address_.emplace(storage_.base_address_);
1154 }
1157 void teardown_base_address() requires IsGlobal {
1158 M_insist(bool(base_address_), "must call `setup_base_address()` before");
1159 base_address_.reset();
1160 }
1161
1165 void resume_pipeline(param_t tuple_value_schema = param_t(), param_t tuple_addr_schema = param_t()) const;
1171 void resume_pipeline_inline(param_t tuple_value_schema = param_t(), param_t tuple_addr_schema = param_t()) const;
1172
1177 param_t tuple_value_schema = param_t(), param_t tuple_addr_schema = param_t()) const;
1184 param_t tuple_value_schema = param_t(), param_t tuple_addr_schema = param_t()) const;
1185
1193 void consume();
1194};
1195
1198
1199
1200/*======================================================================================================================
1201 * buffer accesses
1202 *====================================================================================================================*/
1203
1205template<bool IsGlobal>
1207{
1208 friend struct Buffer<IsGlobal>;
1209
1210 private:
1211 std::reference_wrapper<const Buffer<IsGlobal>> buffer_;
1212 std::reference_wrapper<const Schema> value_schema_;
1213 std::reference_wrapper<const Schema> addr_schema_;
1214
1216 : buffer_(std::cref(buffer))
1218 , addr_schema_(std::cref(addr_schema))
1219 { }
1220
1221 public:
1224
1226
1228 const Schema & value_schema() const { return value_schema_; }
1230 const Schema & addr_schema() const { return addr_schema_; }
1231
1233 void operator()(U32x1 tuple_id) {
1234 Wasm_insist(tuple_id.clone() < buffer_.get().size(), "tuple ID out of bounds");
1235 compile_load_point_access(value_schema_, addr_schema_, buffer_.get().base_address(), buffer_.get().layout(),
1236 buffer_.get().schema(), tuple_id);
1237 }
1238};
1239
1241template<bool IsGlobal>
1243{
1244 friend struct Buffer<IsGlobal>;
1245
1246 private:
1247 std::reference_wrapper<const Buffer<IsGlobal>> buffer_;
1248 std::reference_wrapper<const Schema> schema_;
1249
1251 : buffer_(std::cref(buffer))
1252 , schema_(std::cref(schema))
1253 { }
1254
1255 public:
1258
1260
1262 const Schema & schema() const { return schema_; }
1263
1265 void operator()(U32x1 tuple_id) {
1266 static Schema empty_schema;
1267 Wasm_insist(tuple_id.clone() < buffer_.get().size(), "tuple ID out of bounds");
1268 compile_store_point_access(schema_, empty_schema, buffer_.get().base_address(), buffer_.get().layout(),
1269 buffer_.get().schema(), tuple_id);
1270 }
1271};
1272
1274template<bool IsGlobal>
1276{
1277 friend struct Buffer<IsGlobal>;
1278
1279 private:
1280 std::reference_wrapper<const Buffer<IsGlobal>> buffer_;
1281 std::reference_wrapper<const Schema> schema_;
1282
1284 : buffer_(std::cref(buffer))
1285 , schema_(std::cref(schema))
1286 { }
1287
1288 public:
1290 const Schema & schema() const { return schema_; }
1291
1293 void operator()(U32x1 first, U32x1 second);
1299 void operator()(U32x1 first, U32x1 second, const Environment &env_first);
1306 void operator()(U32x1 first, U32x1 second, const Environment &env_first, const Environment &env_second);
1307};
1308
1309
1310/*======================================================================================================================
1311 * bit operations
1312 *====================================================================================================================*/
1313
1315template<typename T, std::size_t L>
1316requires integral<typename T::type> and (T::num_simd_lanes == L)
1317void setbit(Ptr<T> bytes, Bool<L> value, uint8_t n)
1318{
1319 *bytes ^= (-value.template to<typename T::type>() xor *bytes.clone()) bitand T(1 << n);
1320}
1322template<typename T, std::size_t L>
1323requires integral<typename T::type> and (T::num_simd_lanes == L)
1324void setbit(Ptr<T> bytes, Bool<L> value, T mask)
1325{
1326 *bytes ^= (-value.template to<typename T::type>() xor *bytes.clone()) bitand mask;
1327}
1328
1329
1330/*======================================================================================================================
1331 * string comparison
1332 *====================================================================================================================*/
1333
1336{
1339
1341_I32x1 strncmp(NChar left, NChar right, U32x1 len, bool reverse = false);
1343_I32x1 strcmp(NChar left, NChar right, bool reverse = false);
1345_Boolx1 strncmp(NChar left, NChar right, U32x1 len, cmp_op op, bool reverse = false);
1347_Boolx1 strcmp(NChar left, NChar right, cmp_op op, bool reverse = false);
1348
1349
1350/*======================================================================================================================
1351 * string copy
1352 *====================================================================================================================*/
1353
1358Ptr<Charx1> strncpy(Ptr<Charx1> dst, Ptr<Charx1> src, U32x1 count);
1359
1360
1361/*======================================================================================================================
1362 * SQL LIKE
1363 *====================================================================================================================*/
1364
1367_Boolx1 like(NChar str, NChar pattern, const char escape_char = '\\');
1371_Boolx1 like_contains(NChar str, const ThreadSafePooledString &pattern);
1375_Boolx1 like_prefix(NChar str, const ThreadSafePooledString &pattern);
1379_Boolx1 like_suffix(NChar str, const ThreadSafePooledString &pattern);
1380
1381
1382/*======================================================================================================================
1383 * signum and comparator
1384 *====================================================================================================================*/
1385
1387template<typename T>
1390{
1391 using type = typename T::type;
1392 return (value.clone() > type(0)).template to<type>() - (value < type(0)).template to<type>();
1393}
1394
1402template<bool Predicated>
1403I32x1 compare(const Environment &env_left, const Environment &env_right,
1404 const std::vector<SortingOperator::order_type> &order);
1405
1406
1407/*======================================================================================================================
1408 * explicit instantiation declarations
1409 *====================================================================================================================*/
1410
1411template void Environment::add_predicate(_Boolx1 &&);
1412template void Environment::add_predicate(_Boolx16&&);
1413template void Environment::add_predicate(_Boolx32&&);
1414template _Boolx1 Environment::extract_predicate();
1415template _Boolx16 Environment::extract_predicate();
1416template _Boolx32 Environment::extract_predicate();
1417template _Boolx1 Environment::get_predicate() const;
1418template _Boolx16 Environment::get_predicate() const;
1419template _Boolx32 Environment::get_predicate() const;
1420extern template std::tuple<Block, Block, Block> compile_store_sequential(
1421 const Schema&, const Schema&, Ptr<void>, const storage::DataLayout&, std::size_t, const Schema&, Var<U32x1>&
1422);
1423extern template std::tuple<Block, Block, Block> compile_store_sequential(
1424 const Schema&, const Schema&, Ptr<void>, const storage::DataLayout&, std::size_t, const Schema&, Global<U32x1>&
1425);
1426extern template std::tuple<Block, Block, Block> compile_store_sequential(
1427 const Schema&, const Schema&, Ptr<void>, const storage::DataLayout&, std::size_t, const Schema&,
1429);
1430extern template std::tuple<Block, Block, Block> compile_store_sequential_single_pass(
1431 const Schema&, const Schema&, Ptr<void>, const storage::DataLayout&, std::size_t, const Schema&, Var<U32x1>&
1432);
1433extern template std::tuple<Block, Block, Block> compile_store_sequential_single_pass(
1434 const Schema&, const Schema&, Ptr<void>, const storage::DataLayout&, std::size_t, const Schema&, Global<U32x1>&
1435);
1436extern template std::tuple<Block, Block, Block> compile_store_sequential_single_pass(
1437 const Schema&, const Schema&, Ptr<void>, const storage::DataLayout&, std::size_t, const Schema&,
1439);
1440extern template std::tuple<Block, Block, Block> compile_load_sequential(
1441 const Schema&, const Schema&, Ptr<void>, const storage::DataLayout&, std::size_t, const Schema&, Var<U32x1>&
1442);
1443extern template std::tuple<Block, Block, Block> compile_load_sequential(
1444 const Schema&, const Schema&, Ptr<void>, const storage::DataLayout&, std::size_t, const Schema&, Global<U32x1>&
1445);
1446extern template std::tuple<Block, Block, Block> compile_load_sequential(
1447 const Schema&, const Schema&, Ptr<void>, const storage::DataLayout&, std::size_t, const Schema&,
1449);
1450extern template struct Buffer<false>;
1451extern template struct Buffer<true>;
1452extern template struct buffer_swap_proxy_t<false>;
1453extern template struct buffer_swap_proxy_t<true>;
1454extern template I32x1 compare<false>(
1455 const Environment&, const Environment&, const std::vector<SortingOperator::order_type>&
1456);
1457extern template I32x1 compare<true>(
1458 const Environment&, const Environment&, const std::vector<SortingOperator::order_type>&
1459);
1460
1461}
1462
1463}
#define ADD_TYPE(TYPE)
#define Wasm_insist(...)
Definition: WasmDSL.hpp:373
#define ADD_EXPR_SQL_ADDR_TYPE(TYPE)
#define SQL_TYPES(X)
Definition: WasmUtil.hpp:322
#define SQL_ADDR_TYPES(X)
Definition: WasmUtil.hpp:350
#define ADD_EXPR_SQL_TYPE(TYPE)
Definition: WasmUtil.hpp:378
Global< U32x1 > size_
global backup for current size of buffer, default initialized to 0
Definition: WasmUtil.hpp:1062
std::optional< Global< U32x1 > > capacity_
‍global backup for dynamic capacity of infinite buffer, default initialized to 0
Definition: WasmUtil.hpp:1064
Global< Ptr< void > > base_address_
global backup for base address of buffer
Definition: WasmUtil.hpp:1061
Check whether.
Definition: concepts.hpp:35
Check whether.
Definition: concepts.hpp:14
Check whether.
Definition: concepts.hpp:23
Check whether.
Definition: concepts.hpp:27
Detect whether a type.
Definition: WasmDSL.hpp:210
#define M_unreachable(MSG)
Definition: macro.hpp:146
#define M_insist(...)
Definition: macro.hpp:129
_I32x1 strcmp(NChar left, NChar right, bool reverse=false)
Compares two strings left and right.
Definition: WasmUtil.cpp:3270
typename expr< T >::type expr_t
Convenience alias for expr.
Definition: WasmDSL.hpp:205
_Boolx1 like_prefix(NChar str, const ThreadSafePooledString &pattern)
Checks whether the string str has the prefix pattern.
Definition: WasmUtil.cpp:3635
_Boolx1 like_contains(NChar str, const ThreadSafePooledString &pattern)
Checks whether the string str contains the pattern pattern.
Definition: WasmUtil.cpp:3543
_I32x1 strncmp(NChar left, NChar right, U32x1 len, bool reverse=false)
Compares two strings left and right.
Definition: WasmUtil.cpp:3102
std::variant< std::monostate #define ADD_TYPE(TYPE) SQL_TYPES(ADD_TYPE) > SQL_t
Definition: WasmUtil.hpp:397
Ptr< Charx1 > strncpy(Ptr< Charx1 > dst, Ptr< Charx1 > src, U32x1 count)
Copies the contents of src to dst, but no more than count characters.
Definition: WasmUtil.cpp:3311
template I32x1 compare< true >(const Environment &, const Environment &, const std::vector< SortingOperator::order_type > &)
bool can_be_null(const SQL_t &variant)
Definition: WasmUtil.hpp:452
Bool< L > not_null(SQL_t &variant)
Definition: WasmUtil.hpp:475
T signum(T value)
Returns the signum of value, i.e.
Definition: WasmUtil.hpp:1389
Bool< L > T mask
Definition: WasmUtil.hpp:1325
typename detail::var_helper< T >::type Var
Local variable.
Definition: WasmDSL.hpp:5779
and arithmetically_combinable< T, U, L > auto operator/(PrimitiveExpr< U, L > other) -> PrimitiveExpr< common_type_t< T, U >, L >
Divides this by other.
Definition: WasmDSL.hpp:2436
std::tuple< Block, Block, Block > compile_store_sequential(const Schema &tuple_value_schema, const Schema &tuple_addr_schema, Ptr< void > base_address, const storage::DataLayout &layout, std::size_t num_simd_lanes, const Schema &layout_schema, Variable< uint32_t, Kind, false > &tuple_id)
Compiles the data layout layout containing tuples of schema layout_schema such that it sequentially s...
std::variant< std::monostate #define ADD_TYPE(TYPE) SQL_ADDR_TYPES(ADD_TYPE) > SQL_addr_t
Definition: WasmUtil.hpp:404
std::tuple< Block, Block, Block > compile_store_sequential_single_pass(const Schema &tuple_value_schema, const Schema &tuple_addr_schema, Ptr< void > base_address, const storage::DataLayout &layout, std::size_t num_simd_lanes, const Schema &layout_schema, Variable< uint32_t, Kind, false > &tuple_id)
Compiles the data layout layout containing tuples of schema layout_schema such that it sequentially s...
void compile_load_point_access(const Schema &tuple_value_schema, const Schema &tuple_addr_schema, Ptr< void > base_address, const storage::DataLayout &layout, const Schema &layout_schema, U32x1 tuple_id)
Compiles the data layout layout starting at memory address base_address and containing tuples of sche...
Definition: WasmUtil.cpp:2480
template I32x1 compare< false >(const Environment &, const Environment &, const std::vector< SortingOperator::order_type > &)
and
Constructs a new PrimitiveExpr from a constant value.
Definition: WasmDSL.hpp:1519
std::size_t L
Definition: WasmDSL.hpp:528
PrimitiveExpr< U, M > convert()
Definition: WasmDSL.hpp:1635
void compile_store_point_access(const Schema &tuple_value_schema, const Schema &tuple_addr_schema, Ptr< void > base_address, const storage::DataLayout &layout, const Schema &layout_schema, U32x1 tuple_id)
Compiles the data layout layout starting at memory address base_address and containing tuples of sche...
Definition: WasmUtil.cpp:2472
typename detail::global_helper< T >::type Global
Global variable.
Definition: WasmDSL.hpp:5789
Bool< L > value
Definition: WasmUtil.hpp:1317
Bool< L > is_null(SQL_t &variant)
Definition: WasmUtil.hpp:461
PrimitiveExpr operator-() and(L
_Boolx1 like(NChar str, NChar pattern, const char escape_char='\\')
Checks whether the string str matches the pattern pattern regarding SQL LIKE semantics using escape c...
Definition: WasmUtil.cpp:3360
std::tuple< Block, Block, Block > compile_load_sequential(const Schema &tuple_value_schema, const Schema &tuple_addr_schema, Ptr< void > base_address, const storage::DataLayout &layout, std::size_t num_simd_lanes, const Schema &layout_schema, Variable< uint32_t, Kind, false > &tuple_id)
Compiles the data layout layout containing tuples of schema layout_schema such that it sequentially l...
auto operator*(PrimitiveExpr< U, L > other) -> PrimitiveExpr< common_type_t< T, U >, L >
Multiplies this and other.
Definition: WasmDSL.hpp:2375
Bool< L > uint8_t n
Definition: WasmUtil.hpp:1318
void discard()
Discards this.
Definition: WasmDSL.hpp:1588
PrimitiveExpr< uint64_t, L > L L L L U
Definition: WasmDSL.hpp:2352
_Boolx1 like_suffix(NChar str, const ThreadSafePooledString &pattern)
Checks whether the string str has the suffix pattern.
Definition: WasmUtil.cpp:3661
for(std::size_t idx=1;idx< num_vectors;++idx) res.emplace((vectors_[idx].bitmask()<< uint32_t(idx *vector_type return * res
Definition: WasmDSL.hpp:3696
auto op
Definition: WasmDSL.hpp:2384
std::variant< std::monostate, _Boolx1, _Boolx16, _Boolx32 > SQL_boolean_t
Definition: WasmUtil.hpp:409
I32x1 compare(const Environment &env_left, const Environment &env_right, const std::vector< SortingOperator::order_type > &order)
Compares two tuples, which must be already loaded into the environments env_left and env_right,...
Definition: WasmUtil.cpp:3695
std::conditional_t< std::is_signed_v< T >, int16_t, uint16_t > To
Definition: WasmDSL.hpp:2408
std::pair<::wasm::Expression *, std::list< std::shared_ptr< Bit > > > move()
Moves the underlying Binaryen ::wasm::Expression and the referenced bits out of this.
Definition: WasmDSL.hpp:1567
PrimitiveExpr operator+()
Definition: WasmDSL.hpp:2142
cmp_op
‍comparison operations, e.g. for string comparison
Definition: WasmUtil.hpp:1336
static constexpr std::size_t num_simd_lanes
‍the number of SIMD lanes of the represented expression, i.e. 1 for scalar and at least 2 for vectori...
Definition: WasmDSL.hpp:1466
‍mutable namespace
Definition: Backend.hpp:10
T M_EXPORT powi(const T base, const U exp)
Power function for integral types.
Definition: fn.hpp:428
std::function< void(void)> pipeline_t
T(x)
ThreadSafeStringPool::proxy_type ThreadSafePooledString
Definition: Pool.hpp:464
void M_EXPORT setbit(T *bytes, bool value, uint32_t n)
Definition: fn.hpp:442
STL namespace.
The type of character strings, both fixed length and varying length.
Definition: Type.hpp:290
std::size_t length
the maximum length of the string in bytes
Definition: Type.hpp:293
bool is_varying
true if varying, false otherwise; corresponds to Char(N) and Varchar(N)
Definition: Type.hpp:294
uint64_t size() const override
Returns the number of bits required to store a sequence of length many characters.
Definition: Type.hpp:314
An Identifier is composed of a name and an optional prefix.
Definition: Schema.hpp:42
A Schema represents a sequence of identifiers, optionally with a prefix, and their associated types.
Definition: Schema.hpp:39
This class represents types in the SQL type system.
Definition: Type.hpp:46
A binary expression.
Definition: AST.hpp:348
A constant: a string literal or a numeric constant.
Definition: AST.hpp:213
A designator.
Definition: AST.hpp:134
The error expression.
Definition: AST.hpp:116
An expression.
Definition: AST.hpp:39
A function application.
Definition: AST.hpp:246
A query expression for nested queries.
Definition: AST.hpp:389
A unary expression: "+e", "-e", "~e", "NOT e".
Definition: AST.hpp:324
A CNF represents a conjunction of cnf::Clauses.
Definition: CNF.hpp:134
static setup_t Make_Without_Parent(base_t &&callback=base_t())
This is an interface for factories that compute particular DataLayouts for a given sequence of Types,...
Models how data is laid out in a linear address space.
Definition: DataLayout.hpp:29
bool is_finite() const
‍returns true iff this DataLayout lays out a finite sequence of tuples
Definition: DataLayout.hpp:200
static teardown_t Make_Without_Parent(base_t &&callback=base_t())
Buffers tuples by materializing them into memory.
Definition: WasmUtil.hpp:1070
buffer_load_proxy_t< IsGlobal > create_load_proxy(param_t tuple_value_schema=param_t(), param_t tuple_addr_schema=param_t()) const
Creates and returns a proxy object to load value tuples of schema tuple_value_schema (default: entire...
Definition: WasmUtil.cpp:2535
void execute_pipeline_inline(setup_t setup, pipeline_t pipeline, teardown_t teardown, param_t tuple_value_schema=param_t(), param_t tuple_addr_schema=param_t()) const
Emits code inline to execute the given pipeline pipeline for each value tuple of schema tuple_value_s...
Definition: WasmUtil.cpp:2833
void resume_pipeline(param_t tuple_value_schema=param_t(), param_t tuple_addr_schema=param_t()) const
Emits code into a separate function to resume the pipeline for each value tuple of schema tuple_value...
Definition: WasmUtil.cpp:2679
pipeline_t pipeline_
remaining actual pipeline
Definition: WasmUtil.hpp:1084
Buffer(Buffer &&)=default
teardown_t teardown_
remaining pipeline post-processing
Definition: WasmUtil.hpp:1085
std::reference_wrapper< const Schema > schema_
schema of buffer
Definition: WasmUtil.hpp:1075
std::optional< FunctionProxy< void(void *, uint32_t)> > resume_pipeline_
‍function to resume pipeline for entire buffer; expects base address and size of buffer as parameters
Definition: WasmUtil.hpp:1087
const storage::DataLayout & layout() const
Returns the layout of the buffer.
Definition: WasmUtil.hpp:1108
void execute_pipeline(setup_t setup, pipeline_t pipeline, teardown_t teardown, param_t tuple_value_schema=param_t(), param_t tuple_addr_schema=param_t()) const
Emits code into a separate function to execute the give pipeline pipeline for each value tuple of sch...
Definition: WasmUtil.cpp:2761
bool load_simdfied_
flag whether to load from the buffer in SIMDfied manner
Definition: WasmUtil.hpp:1077
const Schema & schema() const
Returns the schema of the buffer.
Definition: WasmUtil.hpp:1106
Ptr< void > base_address() const
Returns the base address of the buffer.
Definition: WasmUtil.hpp:1110
void setup_base_address()
Performs the setup of the local base address of this buffer by reading it from the global backup.
Definition: WasmUtil.hpp:1147
void consume()
Emits code to store the current tuple into the buffer.
Definition: WasmUtil.cpp:2910
void teardown_base_address()
Performs the teardown of the local base address of this buffer by destroying it but without storing i...
Definition: WasmUtil.hpp:1157
buffer_swap_proxy_t< IsGlobal > create_swap_proxy(param_t tuple_schema=param_t()) const
Creates and returns a proxy object to swap tuples of schema tuple_schema (default: entire tuples) in ...
Definition: WasmUtil.cpp:2570
std::optional< Var< Boolx1 > > first_iteration_
flag to indicate first loop iteration for infinite buffer
Definition: WasmUtil.hpp:1081
std::optional< Var< Ptr< void > > > base_address_
base address of buffer
Definition: WasmUtil.hpp:1078
std::optional< std::reference_wrapper< const Schema > > param_t
‍parameter type for proxy creation and pipeline resuming methods
Definition: WasmUtil.hpp:1073
void setup()
Performs the setup of all local variables of this buffer (by reading them from the global backups iff...
Definition: WasmUtil.cpp:2583
std::optional< Var< U32x1 > > size_
current size of buffer, default initialized to 0
Definition: WasmUtil.hpp:1079
storage::DataLayout layout_
data layout of buffer
Definition: WasmUtil.hpp:1076
std::optional< Var< U32x1 > > capacity_
dynamic capacity of infinite buffer, default initialized to 0
Definition: WasmUtil.hpp:1080
buffer_storage< IsGlobal > storage_
if IsGlobal, contains backups for base address, capacity, and size
Definition: WasmUtil.hpp:1082
setup_t setup_
remaining pipeline initializations
Definition: WasmUtil.hpp:1083
buffer_store_proxy_t< IsGlobal > create_store_proxy(param_t tuple_schema=param_t()) const
Creates and returns a proxy object to store tuples of schema tuple_schema (default: entire tuples) to...
Definition: WasmUtil.cpp:2557
void resume_pipeline_inline(param_t tuple_value_schema=param_t(), param_t tuple_addr_schema=param_t()) const
Emits code inline to resume the pipeline for each value tuple of schema tuple_value_schema (default: ...
Definition: WasmUtil.cpp:2755
void teardown()
Performs the teardown of all local variables of this buffer (by storing them into the global backups ...
Definition: WasmUtil.cpp:2642
U32x1 size() const
Returns the current size of the buffer.
Definition: WasmUtil.hpp:1119
Buffer(const Buffer &)=delete
Buffer & operator=(Buffer &&)=default
The Wasm CodeGenContext provides context information necessary for code generation.
Definition: WasmUtil.hpp:852
uint32_t get_literal_raw_address(const char *literal) const
Returns the raw address at which literal is stored.
Definition: WasmUtil.hpp:926
Scope scoped_environment(Environment env)
Creates a new Scope using the Environment env which is immediately used by the CodeGenContext.
Definition: WasmUtil.hpp:901
void inc_num_tuples(U32x1 n=U32x1(1))
Increments the number of result tuples produced by n.
Definition: WasmUtil.hpp:914
std::unordered_map< const char *, std::pair< uint32_t, NChar > > literals_
maps each literal to its address at which it is stored
Definition: WasmUtil.hpp:858
U32x1 num_tuples() const
Returns the number of result tuples produced.
Definition: WasmUtil.hpp:910
const Environment & env() const
Returns the current Environment.
Definition: WasmUtil.hpp:907
std::size_t num_simd_lanes() const
Returns the number of SIMD lanes used.
Definition: WasmUtil.hpp:939
NChar get_literal_address(const char *literal) const
Returns the address at which literal is stored.
Definition: WasmUtil.hpp:932
static void Dispose()
Definition: WasmUtil.hpp:885
std::size_t num_simd_lanes_preferred_
‍number of SIMD lanes currently preferred, i.e. 1 for scalar and at least 2 for vectorial values
Definition: WasmUtil.hpp:862
std::size_t num_simd_lanes_preferred() const
Returns the number of SIMD lanes preferred by other operators.
Definition: WasmUtil.hpp:944
static thread_local std::unique_ptr< CodeGenContext > the_context_
Definition: WasmUtil.hpp:878
Global< U32x1 > num_tuples_
variable to hold the number of result tuples produced
Definition: WasmUtil.hpp:857
void add_literal(const char *literal, uint32_t ptr)
Adds the string literal literal located at pointer offset ptr.
Definition: WasmUtil.hpp:917
Environment & env()
Returns the current Environment.
Definition: WasmUtil.hpp:905
CodeGenContext(const CodeGenContext &)=delete
void set_num_simd_lanes(std::size_t n)
Sets the number of SIMD lanes used to n.
Definition: WasmUtil.hpp:941
static void Init()
Definition: WasmUtil.hpp:881
std::size_t num_simd_lanes_
‍number of SIMD lanes currently used, i.e. 1 for scalar and at least 2 for vectorial values
Definition: WasmUtil.hpp:860
void update_num_simd_lanes_preferred(std::size_t n)
Updates the number of SIMD lanes preferred by n.
Definition: WasmUtil.hpp:946
friend struct Scope
Definition: WasmUtil.hpp:853
Environment * env_
environment for locally bound identifiers
Definition: WasmUtil.hpp:856
void set_num_tuples(U32x1 n)
Set the number of result tuples produced to n.
Definition: WasmUtil.hpp:912
static CodeGenContext & Get()
Definition: WasmUtil.hpp:889
Scope scoped_environment()
Creates a new, scoped Environment.
Definition: WasmUtil.hpp:897
Decimal(Decimal &other)
Definition: WasmUtil.hpp:112
static Decimal Scaled(expr_type value, uint32_t scale)
Constructs a Decimal from a given value at the given scale.
Definition: WasmUtil.hpp:117
Decimal(Decimal &&other)
Definition: WasmUtil.hpp:113
Decimal operator/(Decimal other)
Definition: WasmUtil.hpp:196
friend std::ostream & operator<<(std::ostream &out, const Decimal &d)
Definition: WasmUtil.hpp:247
Decimal operator-(Decimal other)
Definition: WasmUtil.hpp:165
and signed_integral< typename expr_t< T >::type > Decimal operator*(T &&other)
Definition: WasmUtil.hpp:194
Decimal operator%(T &&)
Modulo division is not supported by Decimal type.
Definition: WasmUtil.hpp:209
Decimal(expr_type value, uint32_t scale)
Constructs a Decimal from a given value at the given scale.
Definition: WasmUtil.hpp:110
and signed_integral< typename expr_t< T >::type > Decimal operator-(T &&other)
Definition: WasmUtil.hpp:180
Decimal operator>>(T &&)
Shift right is not supported by Decimal type.
Definition: WasmUtil.hpp:234
and signed_integral< typename expr_t< T >::type > Decimal operator/(T &&other)
Definition: WasmUtil.hpp:204
Expr< To > to()
Definition: WasmUtil.hpp:129
and signed_integral< typename expr_t< T >::type > Decimal operator+(T &&other)
Definition: WasmUtil.hpp:163
Decimal rotl(T &&)
Shift right is not supported by Decimal type.
Definition: WasmUtil.hpp:239
void dump(std::ostream &out) const
Definition: WasmUtil.hpp:251
Base arithmetic_type
Definition: WasmUtil.hpp:95
uint32_t scale() const
Definition: WasmUtil.hpp:126
expr_type val()
Definition: WasmUtil.hpp:124
void dump() const
Definition: WasmUtil.hpp:252
Decimal clone() const
Definition: WasmUtil.hpp:131
Decimal rotr(T &&)
Shift right is not supported by Decimal type.
Definition: WasmUtil.hpp:244
Decimal(Base value, uint32_t scale)
Constructs a Decimal from a given value at the given scale.
Definition: WasmUtil.hpp:104
Decimal operator*(Decimal other)
Definition: WasmUtil.hpp:182
Decimal operator~()
Bitwise negation is not supported by Decimal type.
Definition: WasmUtil.hpp:139
Decimal operator<<(T &&)
Shift left is not supported by Decimal type.
Definition: WasmUtil.hpp:229
uint32_t scale_
‍the number of decimal digits right of the decimal point
Definition: WasmUtil.hpp:99
Decimal operator+(Decimal other)
Definition: WasmUtil.hpp:148
Binds Schema::Identifiers to Expr<T>s.
Definition: WasmUtil.hpp:563
auto compile(T &&t) const
‍Compile t by delegating compilation to an ExprCompiler for this Environment.
Definition: WasmUtil.hpp:742
T extract_predicate()
‍Returns the moved current predication predicate.
Definition: WasmUtil.hpp:787
void dump() const
Definition: WasmUtil.cpp:539
void add_addr(Schema::Identifier id, SQL_addr_t &&expr)
‍Adds a address mapping from id to expr.
Definition: WasmUtil.hpp:636
SQL_t extract(const Schema::Identifier &id)
‍Returns the moved entry for identifier id.
Definition: WasmUtil.hpp:665
void add_predicate(const cnf::CNF &cnf)
‍Adds the predicate compiled from the cnf::CNF cnf to the predication predicate.
Definition: WasmUtil.hpp:776
void add(const Environment &other)
‍Copies all entries of other into this.
Definition: WasmUtil.hpp:642
SQL_t operator[](const Schema::Identifier &id) const
‍Returns the copied entry for identifier id.
Definition: WasmUtil.hpp:735
auto compile(U &&u) const
‍Compile t by delegating compilation to an ExprCompiler for this Environment.
Definition: WasmUtil.hpp:749
void add_predicate(SQL_boolean_t &&pred)
‍Adds the predicate pred to the predication predicate.
Definition: WasmUtil.hpp:759
Environment(const Environment &)=delete
bool predicated() const
‍Returns true iff this Environment uses predication.
Definition: WasmUtil.hpp:756
void clear()
Clears this Environment.
Definition: WasmUtil.hpp:608
void add(Schema::Identifier id, T &&expr)
‍Adds a mapping from id to expr.
Definition: WasmUtil.hpp:619
SQL_boolean_t predicate_
‍optional predicate if predication is used
Definition: WasmUtil.hpp:570
std::unordered_map< Schema::Identifier, SQL_t > exprs_
‍maps Schema::Identifiers to Expr<T>s that evaluate to the current expression
Definition: WasmUtil.hpp:566
SQL_addr_t get_addr(const Schema::Identifier &id) const
‍Returns the copied address entry for identifier id.
Definition: WasmUtil.hpp:717
T get_addr(const Schema::Identifier &id) const
‍Returns the copied address entry for identifier id.
Definition: WasmUtil.hpp:727
bool empty() const
Returns true iff this Environment is empty.
Definition: WasmUtil.hpp:605
void add_addr(Schema::Identifier id, T &&expr)
‍Adds a address mapping from id to expr.
Definition: WasmUtil.hpp:631
T get(const Schema::Identifier &id) const
‍Returns the copied entry for identifier id.
Definition: WasmUtil.hpp:709
SQL_t get(const Schema::Identifier &id) const
‍Returns the copied entry for identifier id.
Definition: WasmUtil.hpp:699
std::unordered_map< Schema::Identifier, SQL_addr_t > expr_addrs_
‍maps Schema::Identifiers to Ptr<Expr<T>>s that evaluate to the address of the current expression
Definition: WasmUtil.hpp:568
Environment(Environment &&)=default
bool has_addr(const Schema::Identifier &id) const
Returns true iff this Environment contains the address of id.
Definition: WasmUtil.hpp:589
T extract_addr(const Schema::Identifier &id)
‍Returns the moved address entry for identifier id.
Definition: WasmUtil.hpp:690
SQL_boolean_t extract_predicate()
‍Returns the moved current predication predicate.
Definition: WasmUtil.hpp:779
bool has(const Schema::Identifier &id) const
Returns true iff this Environment contains id.
Definition: WasmUtil.hpp:587
T extract(const Schema::Identifier &id)
‍Returns the moved entry for identifier id.
Definition: WasmUtil.hpp:673
void add(Schema::Identifier id, SQL_t &&expr)
‍Adds a mapping from id to expr.
Definition: WasmUtil.hpp:624
SQL_addr_t extract_addr(const Schema::Identifier &id)
‍Returns the moved address entry for identifier id.
Definition: WasmUtil.hpp:682
void add(Environment &&other)
‍Moves all entries of other into this.
Definition: WasmUtil.hpp:657
bool is(const Schema::Identifier &id) const
Returns true iff the entry for identifier id has sql_type
Definition: WasmUtil.hpp:592
T get_predicate() const
‍Returns the copied current predication predicate.
Definition: WasmUtil.hpp:807
void add_predicate(T &&pred)
‍Adds the predicate pred to the predication predicate.
Definition: WasmUtil.hpp:767
SQL_boolean_t get_predicate() const
‍Returns the copied current predication predicate.
Definition: WasmUtil.hpp:797
bool is_addr(Schema::Identifier id) const
Returns true iff the address entry for identifier id has sql_addr_type
Definition: WasmUtil.hpp:599
Compiles AST expressions m::Expr to Wasm ASTs m::wasm::Expr<T>.
Definition: WasmUtil.hpp:495
SQL_t intermediate_result_
‍current intermediate results during AST traversal and compilation
Definition: WasmUtil.hpp:498
void operator()(const ast::ErrorExpr &) override
Definition: WasmUtil.cpp:153
SQL_t compile(const m::ast::Expr &e)
‍Compiles a m::Expr e of statically unknown type to a SQL_t.
Definition: WasmUtil.hpp:506
void set(T &&value)
Definition: WasmUtil.hpp:553
void set(SQL_t &&value)
Definition: WasmUtil.hpp:547
T compile(const cnf::CNF &cnf)
‍Compile a m::cnf::CNF cnf of statically known type to
Definition: WasmUtil.hpp:523
T compile(const m::ast::Expr &e)
‍Compile a m::Expr e of statically known type to
Definition: WasmUtil.hpp:512
ExprCompiler(const Environment &env)
Definition: WasmUtil.hpp:503
const Environment & env_
‍the environment to use for resolving designators to Expr<T>s
Definition: WasmUtil.hpp:500
A handle to create a Function and to create invocations of that function.
Definition: WasmDSL.hpp:1367
Boolx1 not_null()
Definition: WasmUtil.hpp:71
std::size_t length() const
Definition: WasmUtil.hpp:81
NChar(NChar &)=default
bool can_be_null_
Definition: WasmUtil.hpp:36
bool guarantees_terminating_nul() const
Definition: WasmUtil.hpp:83
NChar clone() const
Definition: WasmUtil.hpp:53
NChar(NChar &&)=default
NChar(Ptr< Charx1 > ptr, bool can_be_null, std::size_t length, bool guarantees_terminating_nul)
Definition: WasmUtil.hpp:43
bool can_be_null() const
Definition: WasmUtil.hpp:80
uint64_t size_in_bytes() const
Definition: WasmUtil.hpp:82
const CharacterSequence * type_
Definition: WasmUtil.hpp:37
Ptr< Charx1 > insist_not_null()
Definition: WasmUtil.hpp:57
NChar(Ptr< Charx1 > ptr, bool can_be_null, const CharacterSequence *type)
Definition: WasmUtil.hpp:40
Ptr< Charx1 > val()
Definition: WasmUtil.hpp:55
Boolx1 is_null()
Definition: WasmUtil.hpp:63
Scope(const Scope &)=delete
Scope(Scope &&)=default
Environment extract()
Ends this Scope by returning the currently active environment and setting the former one active again...
Definition: WasmUtil.hpp:962
Scope()=delete
Environment * outer_
environment active before and after this Scopes lifetime
Definition: WasmUtil.hpp:828
Environment inner_
environment active during this Scopes lifetime
Definition: WasmUtil.hpp:827
Proxy to implement loads from a buffer.
Definition: WasmUtil.hpp:1207
std::reference_wrapper< const Buffer< IsGlobal > > buffer_
buffer to load from
Definition: WasmUtil.hpp:1211
buffer_load_proxy_t & operator=(buffer_load_proxy_t &&)=default
buffer_load_proxy_t(const buffer_load_proxy_t &)=delete
buffer_load_proxy_t(buffer_load_proxy_t &&)=default
buffer_load_proxy_t(const Buffer< IsGlobal > &buffer, const Schema &value_schema, const Schema &addr_schema)
Definition: WasmUtil.hpp:1215
std::reference_wrapper< const Schema > addr_schema_
address entries to load
Definition: WasmUtil.hpp:1213
void operator()(U32x1 tuple_id)
Loads tuple with ID tuple_id into the current environment.
Definition: WasmUtil.hpp:1233
std::reference_wrapper< const Schema > value_schema_
value entries to load
Definition: WasmUtil.hpp:1212
const Schema & addr_schema() const
Returns the address entries to load.
Definition: WasmUtil.hpp:1230
const Schema & value_schema() const
Returns the value entries to load.
Definition: WasmUtil.hpp:1228
Proxy to implement stores to a buffer.
Definition: WasmUtil.hpp:1243
buffer_store_proxy_t(const buffer_store_proxy_t &)=delete
void operator()(U32x1 tuple_id)
Stores values from the current environment to tuple with ID tuple_id.
Definition: WasmUtil.hpp:1265
buffer_store_proxy_t & operator=(buffer_store_proxy_t &&)=default
std::reference_wrapper< const Buffer< IsGlobal > > buffer_
buffer to store to
Definition: WasmUtil.hpp:1247
std::reference_wrapper< const Schema > schema_
entries to store
Definition: WasmUtil.hpp:1248
buffer_store_proxy_t(buffer_store_proxy_t &&)=default
buffer_store_proxy_t(const Buffer< IsGlobal > &buffer, const Schema &schema)
Definition: WasmUtil.hpp:1250
const Schema & schema() const
Returns the entries to store.
Definition: WasmUtil.hpp:1262
Proxy to implement swaps in a buffer.
Definition: WasmUtil.hpp:1276
const Schema & schema() const
Returns the entries to swap.
Definition: WasmUtil.hpp:1290
buffer_swap_proxy_t(const Buffer< IsGlobal > &buffer, const Schema &schema)
Definition: WasmUtil.hpp:1283
std::reference_wrapper< const Schema > schema_
entries to swap
Definition: WasmUtil.hpp:1281
void operator()(U32x1 first, U32x1 second)
Swaps tuples with IDs first and second.
Definition: WasmUtil.cpp:2980
std::reference_wrapper< const Buffer< IsGlobal > > buffer_
buffer in which swaps are performed
Definition: WasmUtil.hpp:1280
Helper type to deduce the Expr<U> type given a.
Definition: WasmDSL.hpp:160