22struct StackMachineBuilder;
34#define M_OPCODE(CODE, ...) CODE,
35#include "tables/Opcodes.tbl"
39 static_assert(uint64_t(
Opcode::Last) < (1UL << (
sizeof(
Opcode) * 8)),
"too many opcodes");
45#define M_OPCODE(CODE, ...) #CODE,
46#include "tables/Opcodes.tbl"
60 std::vector<Opcode>
ops;
68 mutable decltype(
ops)::const_iterator
op_;
69 mutable std::size_t
top_ = 0;
117 std::vector<Schema> &schemas,
118 std::vector<std::size_t> &tuple_ids);
121 void emit(
const cnf::CNF &cnf, std::size_t tuple_id = 0);
125 std::vector<Schema> &schemas,
126 std::vector<std::size_t> &tuple_ids);
135#define SELECT(XXX, _1, _2, _3, FN, ...) FN(__VA_ARGS__)
136#define ARGS_0(XXX, ...)
137#define ARGS_1(I, XXX, ARG0, ...) uint8_t ARG0
138#define ARGS_2(I, II, XXX, ARG0, ARG1, ...) uint8_t ARG0, uint8_t ARG1
139#define ARGS_3(I, II, III, XXX, ARG0, ARG1, ARG2, ...) uint8_t ARG0, uint8_t ARG1, uint8_t ARG2
140#define ARGS(...) SELECT(__VA_ARGS__, ARGS_3, ARGS_2, ARGS_1, ARGS_0, __VA_ARGS__)
141#define PUSH_0(XXX, ...)
142#define PUSH_1(I, XXX, ARG0, ...) \
143 ops.push_back(static_cast<Opcode>((ARG0)));
144#define PUSH_2(I, II, XXX, ARG0, ARG1, ...) \
145 ops.push_back(static_cast<Opcode>((ARG0))); \
146 ops.push_back(static_cast<Opcode>((ARG1)));
147#define PUSH_3(I, II, III, XXX, ARG0, ARG1, ARG2, ...) \
148 ops.push_back(static_cast<Opcode>((ARG0))); \
149 ops.push_back(static_cast<Opcode>((ARG1))); \
150 ops.push_back(static_cast<Opcode>((ARG2)));
151#define PUSH(...) SELECT(__VA_ARGS__, PUSH_3, PUSH_2, PUSH_1, PUSH_0, __VA_ARGS__)
153#define M_OPCODE(CODE, DELTA, ...) \
154 void emit_ ## CODE ( ARGS(XXX, ##__VA_ARGS__) ) { \
155 ops.push_back(StackMachine::Opcode:: CODE ); \
156 current_stack_size_ += DELTA; \
157 M_insist(current_stack_size_ >= 0); \
158 required_stack_size_ = std::max(required_stack_size_, current_stack_size_); \
159 PUSH(XXX, ##__VA_ARGS__) \
162#include "tables/Opcodes.tbl"
185 void emit_St_Tup(std::size_t tuple_id, std::size_t index,
const Type *ty);
220 void dump(std::ostream &out)
const;
Evaluates SQL operator trees on the database.
A Schema represents a sequence of identifiers, optionally with a prefix, and their associated types.
A stack machine that evaluates an expression.
void set(std::size_t idx, Value val)
Sets the Value in the context at index idx to val.
Schema in_schema
schema of the input tuple
void emit_Print(std::size_t ostream_index, const Type *ty)
Emit a Print_X instruction based on Type ty, e.g. Print_i for integral Types.
std::size_t add_and_emit_load(Value val)
Adds the Value val to the context and emits a load instruction to load this value to the top of the s...
int64_t required_stack_size_
the required size of the stack
static Opcode str_to_opcode(const std::string &str)
std::vector< Value > context_
the context of the stack machine, e.g. constants or global variables
bool * null_bits_
array of NULL bits used as a stack
static const std::unordered_map< std::string, Opcode > STR_TO_OPCODE
StackMachine(Schema in_schema)
Create a StackMachine with the given input Schema in_schema.
static constexpr const char * OPCODE_TO_STR[]
StackMachine()
Create a StackMachine that does not accept input.
int64_t current_stack_size_
the "current" stack size; i.e. after the last operation is executed
void emit_Ld(const Type *ty)
Emit a Ld_X instruction based on Type ty, e.g. Ld_i32 for 4 byte integral types.
std::size_t num_ops() const
Value * values_
array of values used as a stack
const Schema & schema_in() const
Returns the Schema of input Tuples.
std::size_t top_
the top of the stack
StackMachine(StackMachine &&)=default
void emit_St(const Type *ty)
Emit a St_X instruction based on Type ty, e.g. St_i32 for 4 byte integral types.
std::vector< Opcode > ops
the sequence of operations to perform
decltype(ops) ::const_iterator op_
the next operation to execute
std::vector< const Type * > out_schema
schema of the output tuple
void operator()(Tuple **tuples) const
Evaluate this StackMachine given the Tuples referenced by tuples.
std::size_t add(Value val)
Appends the Value val to the context and returns its assigned index.
void emit_St_Tup(std::size_t tuple_id, std::size_t index, const Type *ty)
Emit a St_Tup_X instruction based on Type ty, e.g. St_Tup_i for integral Types.
void emit(Opcode opc)
Append the given opcode to the opcode sequence.
uint8_t memory_[SIZE_OF_MEMORY]
memory usable by the stack machine, e.g. to work on BLOBs
static constexpr std::size_t SIZE_OF_MEMORY
void emit(const ast::Expr &expr, std::size_t tuple_id=0)
Emit operations evaluating the Expr expr.
StackMachine(const StackMachine &)=delete
const std::vector< const Type * > & schema_out() const
Returns a sequence of Types defining the schema of output Tuples.
std::size_t required_stack_size() const
Returns the required size of the stack to evaluate the opcode sequence.
void emit_Cast(const Type *to_ty, const Type *from_ty)
Emit opcodes to convert a value of Type from_ty to Type to_ty.
This class represents types in the SQL type system.
This class holds a SQL attribute value.
A CNF represents a conjunction of cnf::Clauses.