3#include <sysio/vm/allocator.hpp>
4#include <sysio/vm/opcodes.hpp>
5#include <sysio/vm/types.hpp>
6#include <sysio/vm/vector.hpp>
12namespace sysio {
namespace vm {
14 class bitcode_writer {
17 decltype(
auto) append_instr(I&& instr) {
18 return (fb[op_index++] = instr).template get<std::decay_t<I>>();
24 _code_segment_base(alloc.start_code()),
25 fb(alloc, source_bytes),
37 if_t& instr = append_instr(if_t{});
41 auto& else_ = append_instr(else_t{});
42 *if_loc = _base_offset + op_index;
46 auto& instr = append_instr(br_t{});
47 instr.data = depth_change;
51 auto& instr = append_instr(br_if_t{});
52 instr.data = depth_change;
62 br_table_t&
bt =
_this->append_instr(br_table_t{});
63 bt.offset =
static_cast<uint32_t>(((table_size *
sizeof(br_table_t::elem_t))/
sizeof(
opcode))+2);
76 elem.stack_pop = depth_change;
104#define MEM_OP(op_name) \
105 void emit_ ## op_name(uint32_t offset, uint32_t alignment) { fb[op_index++] = op_name ## _t{ offset, alignment }; }
106#define LOAD_OP MEM_OP
107#define STORE_OP MEM_OP
144 void emit_ ## opname() { fb[op_index++] = opname ## _t{}; }
251 UNOP(i32_trunc_s_f32)
252 UNOP(i32_trunc_u_f32)
253 UNOP(i32_trunc_s_f64)
254 UNOP(i32_trunc_u_f64)
255 UNOP(i64_extend_s_i32)
256 UNOP(i64_extend_u_i32)
257 UNOP(i64_trunc_s_f32)
258 UNOP(i64_trunc_u_f32)
259 UNOP(i64_trunc_s_f64)
260 UNOP(i64_trunc_u_f64)
261 UNOP(f32_convert_s_i32)
262 UNOP(f32_convert_u_i32)
263 UNOP(f32_convert_s_i64)
264 UNOP(f32_convert_u_i64)
266 UNOP(f64_convert_s_i32)
267 UNOP(f64_convert_u_i32)
268 UNOP(f64_convert_s_i64)
269 UNOP(f64_convert_u_i64)
270 UNOP(f64_promote_f32)
271 UNOP(i32_reinterpret_f32)
272 UNOP(i64_reinterpret_f64)
273 UNOP(f32_reinterpret_i32)
274 UNOP(f64_reinterpret_i64)
289 fb.resize(op_index + 1);
292 locals_count +=
locals[i].count;
300 body.
code = fb.raw();
301 body.
size = op_index;
302 _base_offset += body.
size;
305 const void*
get_addr()
const {
return fb.raw() + op_index; }
311 void * _code_segment_base;
312 std::size_t op_index = 0;
315 std::size_t _base_offset = 0;
void emit_current_memory()
void emit_prologue(const func_type &ft, const guarded_vector< local_entry > &, uint32_t idx)
const void * get_base_addr() const
friend struct br_table_parser
void emit_get_local(uint32_t localidx)
void emit_set_global(uint32_t localidx)
void emit_tee_local(uint32_t localidx)
void emit_i32_const(uint32_t value)
void emit_f32_const(float value)
void emit_call(const func_type &ft, uint32_t funcnum)
void emit_call_indirect(const func_type &ft, uint32_t functypeidx)
void emit_set_local(uint32_t localidx)
const void * get_addr() const
void fix_branch(uint32_t *branch, uint32_t target)
uint32_t * emit_br(uint32_t depth_change)
auto emit_br_table(uint32_t table_size)
uint32_t * emit_else(uint32_t *if_loc)
void emit_i64_const(uint64_t value)
uint32_t * emit_br_if(uint32_t depth_change)
void emit_get_global(uint32_t localidx)
void finalize(function_body &body)
uint32_t * emit_return(uint32_t depth_change)
void emit_epilogue(const func_type &ft, const guarded_vector< local_entry > &locals, uint32_t idx)
void emit_f64_const(double value)
bitcode_writer(growable_allocator &alloc, std::size_t source_bytes, module &mod)
void end_code(void *code_base)
float32_t f32_add(float32_t a, float32_t b)
float32_t f32_div(float32_t a, float32_t b)
bool f32_eq(float32_t a, float32_t b)
bool f32_le(float32_t a, float32_t b)
bool f32_lt(float32_t a, float32_t b)
float32_t f32_mul(float32_t a, float32_t b)
float32_t f32_sqrt(float32_t a)
float32_t f32_sub(float32_t a, float32_t b)
float64_t f64_add(float64_t a, float64_t b)
float64_t f64_div(float64_t a, float64_t b)
bool f64_eq(float64_t a, float64_t b)
bool f64_le(float64_t a, float64_t b)
bool f64_lt(float64_t a, float64_t b)
float64_t f64_mul(float64_t a, float64_t b)
float64_t f64_sqrt(float64_t a)
float64_t f64_sub(float64_t a, float64_t b)
unsigned __int64 uint64_t
br_table_parser(const br_table_parser &)=delete
uint32_t * emit_default(uint32_t depth_change)
uint32_t * emit_case(uint32_t depth_change)
br_table_parser(bitcode_writer &base, uint32_t table_size)
br_table_t::elem_t * _br_tab
br_table_parser & operator=(const br_table_parser &)=delete
guarded_vector< value_type > param_types
guarded_vector< function_body > code
#define SYS_VM_ASSERT(expr, exc_type, msg)
void bt(const Operand &op, const Reg ®)