diff --git a/src/libasr/codegen/asr_to_wasm.cpp b/src/libasr/codegen/asr_to_wasm.cpp index 409dcf4288..b7018f74ea 100644 --- a/src/libasr/codegen/asr_to_wasm.cpp +++ b/src/libasr/codegen/asr_to_wasm.cpp @@ -5,15 +5,16 @@ #include #include -#include +#include +#include +#include #include #include + #include #include #include #include -#include -#include // #define SHOW_ASR @@ -106,6 +107,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { bool is_prototype_only; bool is_local_vars_only; ASR::Function_t* main_func; + WASM_INSTS_VISITOR::WASMInstsAssembler wia; Vec m_type_section; Vec m_import_section; @@ -141,7 +143,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { public: ASRToWASMVisitor(Allocator &al, diag::Diagnostics &diagnostics) - : m_al(al), diag(diagnostics) { + : m_al(al), diag(diagnostics), wia(al, m_code_section) { is_prototype_only = false; is_local_vars_only = false; main_func = nullptr; @@ -256,7 +258,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { wasm::emit_b8(m_code_section, m_al, 0x05); // starting of else else_block(); nesting_level--; - wasm::emit_expr_end(m_code_section, m_al); // emit if end + wasm::emit_expr_end(m_code_section, m_al); } void emit_loop(std::function test_cond, std::function loop_block) { @@ -275,12 +277,11 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { // nesting depth, that is, label 0 refers to the innermost structured // control instruction enclosing the referring branch instruction, while // increasing indices refer to those farther out. - wasm::emit_branch(m_code_section, m_al, nesting_level - - cur_loop_nesting_level - 1); // emit_branch and label the loop + wia.emit_br(nesting_level - cur_loop_nesting_level - 1); // emit_branch and label the loop }, [&](){}); nesting_level--; - wasm::emit_expr_end(m_code_section, m_al); // end loop + wasm::emit_expr_end(m_code_section, m_al); cur_loop_nesting_level = prev_cur_loop_nesting_level; } @@ -344,99 +345,99 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { // locals 4 is extra copy of given parameter emit_if_else([&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_i64_const(m_code_section, m_al, 0); - wasm::emit_i64_eq(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_i64_const(0); + wia.emit_i64_eq(); }, [&](){ emit_call_fd_write(1, "0", 1, 0); - wasm::emit_b8(m_code_section, m_al, 0x0F); // emit wasm return instruction + wia.emit_return(); }, [&](){}); emit_if_else([&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_i64_const(m_code_section, m_al, 0); - wasm::emit_i64_lt_s(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_i64_const(0); + wia.emit_i64_lt_s(); }, [&](){ emit_call_fd_write(1, "-", 1, 0); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_i64_const(m_code_section, m_al, -1); - wasm::emit_i64_mul(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 0); + wia.emit_local_get(0); + wia.emit_i64_const(-1); + wia.emit_i64_mul(); + wia.emit_local_set(0); }, [&](){}); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_set(m_code_section, m_al, 4); - wasm::emit_i64_const(m_code_section, m_al, 0); - wasm::emit_local_set(m_code_section, m_al, 1); + wia.emit_local_get(0); + wia.emit_local_set(4); + wia.emit_i64_const(0); + wia.emit_local_set(1); emit_loop([&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_i64_const(m_code_section, m_al, 0); - wasm::emit_i64_gt_s(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_i64_const(0); + wia.emit_i64_gt_s(); }, [&](){ - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_i64_const(m_code_section, m_al, 1); - wasm::emit_i64_add(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_i64_const(m_code_section, m_al, 10); - wasm::emit_i64_div_s(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 0); + wia.emit_local_get(1); + wia.emit_i64_const(1); + wia.emit_i64_add(); + wia.emit_local_set(1); + wia.emit_local_get(0); + wia.emit_i64_const(10); + wia.emit_i64_div_s(); + wia.emit_local_set(0); }); emit_loop([&](){ - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_i64_const(m_code_section, m_al, 0); - wasm::emit_i64_gt_s(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_i64_const(0); + wia.emit_i64_gt_s(); }, [&](){ - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_i64_const(m_code_section, m_al, 1); - wasm::emit_i64_sub(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 1); + wia.emit_local_get(1); + wia.emit_i64_const(1); + wia.emit_i64_sub(); + wia.emit_local_set(1); - wasm::emit_i64_const(m_code_section, m_al, 1); - wasm::emit_local_set(m_code_section, m_al, 2); - wasm::emit_i64_const(m_code_section, m_al, 0); - wasm::emit_local_set(m_code_section, m_al, 3); + wia.emit_i64_const(1); + wia.emit_local_set(2); + wia.emit_i64_const(0); + wia.emit_local_set(3); emit_loop([&](){ - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_i64_lt_s(m_code_section, m_al); + wia.emit_local_get(3); + wia.emit_local_get(1); + wia.emit_i64_lt_s(); }, [&](){ - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_i64_const(m_code_section, m_al, 1); - wasm::emit_i64_add(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 3); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_i64_const(m_code_section, m_al, 10); - wasm::emit_i64_mul(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 2); + wia.emit_local_get(3); + wia.emit_i64_const(1); + wia.emit_i64_add(); + wia.emit_local_set(3); + wia.emit_local_get(2); + wia.emit_i64_const(10); + wia.emit_i64_mul(); + wia.emit_local_set(2); }); - wasm::emit_local_get(m_code_section, m_al, 4); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_i64_div_s(m_code_section, m_al); - wasm::emit_i64_const(m_code_section, m_al, 10); - wasm::emit_i64_rem_s(m_code_section, m_al); + wia.emit_local_get(4); + wia.emit_local_get(2); + wia.emit_i64_div_s(); + wia.emit_i64_const(10); + wia.emit_i64_rem_s(); /* The digit is on stack */ - wasm::emit_i64_const(m_code_section, m_al, 12 /* 4 + 4 + 4 (iov vec + str size)*/); - wasm::emit_i64_mul(m_code_section, m_al); - wasm::emit_i64_const(m_code_section, m_al, digits_mem_loc); - wasm::emit_i64_add(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 0); // temporary save + wia.emit_i64_const(12 /* 4 + 4 + 4 (iov vec + str size)*/); + wia.emit_i64_mul(); + wia.emit_i64_const(digits_mem_loc); + wia.emit_i64_add(); + wia.emit_local_set(0); // temporary save { - wasm::emit_i32_const(m_code_section, m_al, 1); // file type: 1 for stdout - wasm::emit_local_get(m_code_section, m_al, 0); // use stored digit - wasm::emit_i32_wrap_i64(m_code_section, m_al); - wasm::emit_i32_const(m_code_section, m_al, 1); // size of iov vector - wasm::emit_i32_const(m_code_section, m_al, 0); // mem_loction to return no. of bytes written + wia.emit_i32_const(1); // file type: 1 for stdout + wia.emit_local_get(0); // use stored digit + wia.emit_i32_wrap_i64(); + wia.emit_i32_const(1); // size of iov vector + wia.emit_i32_const(0); // mem_loction to return no. of bytes written // call WASI fd_write - wasm::emit_call(m_code_section, m_al, m_import_func_idx_map[fd_write]); - wasm::emit_drop(m_code_section, m_al); + wia.emit_call(m_import_func_idx_map[fd_write]); + wia.emit_drop(); } }); @@ -447,205 +448,205 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { using namespace wasm; define_emit_func({f64}, {}, {i64, i64, i64}, "print_f64", [&](){ emit_if_else([&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_f64_const(m_code_section, m_al, 0); - wasm::emit_f64_lt(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_f64_const(0); + wia.emit_f64_lt(); }, [&](){ emit_call_fd_write(1, "-", 1, 0); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_f64_const(m_code_section, m_al, -1); - wasm::emit_f64_mul(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 0); + wia.emit_local_get(0); + wia.emit_f64_const(-1); + wia.emit_f64_mul(); + wia.emit_local_set(0); }, [&](){}); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_i64_trunc_f64_s(m_code_section, m_al); - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[print_i64]); + wia.emit_local_get(0); + wia.emit_i64_trunc_f64_s(); + wia.emit_call(m_rt_func_used_idx[print_i64]); emit_call_fd_write(1, ".", 1, 0); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_i64_trunc_f64_s(m_code_section, m_al); - wasm::emit_f64_convert_i64_s(m_code_section, m_al); - wasm::emit_f64_sub(m_code_section, m_al); - wasm::emit_f64_const(m_code_section, m_al, 1e8); - wasm::emit_f64_mul(m_code_section, m_al); - wasm::emit_i64_trunc_f64_s(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 2); /* save the current fractional part value */ - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_local_set(m_code_section, m_al, 3); /* save the another copy */ - - wasm::emit_i64_const(m_code_section, m_al, 0); - wasm::emit_local_set(m_code_section, m_al, 1); // digits_cnt + wia.emit_local_get(0); + wia.emit_local_get(0); + wia.emit_i64_trunc_f64_s(); + wia.emit_f64_convert_i64_s(); + wia.emit_f64_sub(); + wia.emit_f64_const(1e8); + wia.emit_f64_mul(); + wia.emit_i64_trunc_f64_s(); + wia.emit_local_set(2); /* save the current fractional part value */ + wia.emit_local_get(2); + wia.emit_local_set(3); /* save the another copy */ + + wia.emit_i64_const(0); + wia.emit_local_set(1); // digits_cnt emit_loop([&](){ - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_i64_const(m_code_section, m_al, 0); - wasm::emit_i64_gt_s(m_code_section, m_al); + wia.emit_local_get(2); + wia.emit_i64_const(0); + wia.emit_i64_gt_s(); }, [&](){ - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_i64_const(m_code_section, m_al, 1); - wasm::emit_i64_add(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 1); - - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_f64_convert_i64_s(m_code_section, m_al); - wasm::emit_i64_const(m_code_section, m_al, 10); - wasm::emit_f64_convert_i64_s(m_code_section, m_al); - wasm::emit_f64_div(m_code_section, m_al); - wasm::emit_i64_trunc_f64_s(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 2); + wia.emit_local_get(1); + wia.emit_i64_const(1); + wia.emit_i64_add(); + wia.emit_local_set(1); + + wia.emit_local_get(2); + wia.emit_f64_convert_i64_s(); + wia.emit_i64_const(10); + wia.emit_f64_convert_i64_s(); + wia.emit_f64_div(); + wia.emit_i64_trunc_f64_s(); + wia.emit_local_set(2); }); emit_loop([&](){ - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_i64_const(m_code_section, m_al, 8); - wasm::emit_i64_lt_s(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_i64_const(8); + wia.emit_i64_lt_s(); }, [&](){ - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_i64_const(m_code_section, m_al, 1); - wasm::emit_i64_add(m_code_section, m_al); - wasm::emit_local_set(m_code_section, m_al, 1); + wia.emit_local_get(1); + wia.emit_i64_const(1); + wia.emit_i64_add(); + wia.emit_local_set(1); emit_call_fd_write(1, "0", 1, 0); }); - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[print_i64]); + wia.emit_local_get(3); + wia.emit_call(m_rt_func_used_idx[print_i64]); }, fn_idx); } void emit_complex_add_32(int fn_idx = -1) { using namespace wasm; define_emit_func({f32, f32, f32, f32}, {f32, f32}, {}, "add_c32", [&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_f32_add(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(2); + wia.emit_f32_add(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_f32_add(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(3); + wia.emit_f32_add(); }, fn_idx); } void emit_complex_add_64(int fn_idx = -1) { using namespace wasm; define_emit_func({f64, f64, f64, f64}, {f64, f64}, {}, "add_c64", [&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_f64_add(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(2); + wia.emit_f64_add(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_f64_add(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(3); + wia.emit_f64_add(); }, fn_idx); } void emit_complex_sub_32(int fn_idx = -1) { using namespace wasm; define_emit_func({f32, f32, f32, f32}, {f32, f32}, {}, "sub_c32", [&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_f32_sub(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(2); + wia.emit_f32_sub(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_f32_sub(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(3); + wia.emit_f32_sub(); }, fn_idx); } void emit_complex_sub_64(int fn_idx = -1) { using namespace wasm; define_emit_func({f64, f64, f64, f64}, {f64, f64}, {}, "sub_c64", [&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_f64_sub(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(2); + wia.emit_f64_sub(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_f64_sub(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(3); + wia.emit_f64_sub(); }, fn_idx); } void emit_complex_mul_32(int fn_idx = -1) { using namespace wasm; define_emit_func({f32, f32, f32, f32}, {f32, f32}, {}, "mul_c32", [&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_f32_mul(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(2); + wia.emit_f32_mul(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_f32_mul(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(3); + wia.emit_f32_mul(); - wasm::emit_f32_sub(m_code_section, m_al); + wia.emit_f32_sub(); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_f32_mul(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(3); + wia.emit_f32_mul(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_f32_mul(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(2); + wia.emit_f32_mul(); - wasm::emit_f32_add(m_code_section, m_al); + wia.emit_f32_add(); }, fn_idx); } void emit_complex_mul_64(int fn_idx = -1) { using namespace wasm; define_emit_func({f64, f64, f64, f64}, {f64, f64}, {}, "mul_c64", [&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_f64_mul(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(2); + wia.emit_f64_mul(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_f64_mul(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(3); + wia.emit_f64_mul(); - wasm::emit_f64_sub(m_code_section, m_al); + wia.emit_f64_sub(); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 3); - wasm::emit_f64_mul(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(3); + wia.emit_f64_mul(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 2); - wasm::emit_f64_mul(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(2); + wia.emit_f64_mul(); - wasm::emit_f64_add(m_code_section, m_al); + wia.emit_f64_add(); }, fn_idx); } void emit_complex_abs_32(int fn_idx = -1) { using namespace wasm; define_emit_func({f32, f32}, {f32}, {}, "abs_c32", [&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_f32_mul(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(0); + wia.emit_f32_mul(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_f32_mul(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(1); + wia.emit_f32_mul(); - wasm::emit_f32_add(m_code_section, m_al); - wasm::emit_f32_sqrt(m_code_section, m_al); + wia.emit_f32_add(); + wia.emit_f32_sqrt(); }, fn_idx); } void emit_complex_abs_64(int fn_idx = -1) { using namespace wasm; define_emit_func({f64, f64}, {f64}, {}, "abs_c64", [&](){ - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_local_get(m_code_section, m_al, 0); - wasm::emit_f64_mul(m_code_section, m_al); + wia.emit_local_get(0); + wia.emit_local_get(0); + wia.emit_f64_mul(); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_local_get(m_code_section, m_al, 1); - wasm::emit_f64_mul(m_code_section, m_al); + wia.emit_local_get(1); + wia.emit_local_get(1); + wia.emit_f64_mul(); - wasm::emit_f64_add(m_code_section, m_al); - wasm::emit_f64_sqrt(m_code_section, m_al); + wia.emit_f64_add(); + wia.emit_f64_sqrt(); }, fn_idx); } @@ -653,24 +654,45 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { void declare_global_var(wasm::type var_type, GLOBAL_VAR name, T initial_value, bool isMutable) { m_global_section.push_back(m_al, var_type); m_global_section.push_back(m_al, isMutable); - switch (var_type) - { - case wasm::type::i32: wasm::emit_i32_const(m_global_section, m_al, initial_value); break; - case wasm::type::i64: wasm::emit_i64_const(m_global_section, m_al, initial_value); break; - case wasm::type::f32: wasm::emit_f32_const(m_global_section, m_al, initial_value); break; - case wasm::type::f64: wasm::emit_f64_const(m_global_section, m_al, initial_value); break; - default: throw CodeGenError("declare_global_var: Unsupport var_type"); break; - } - wasm::emit_expr_end(m_global_section, m_al); // end instructions + emit_const(m_global_section, var_type, initial_value); + wasm::emit_expr_end(m_global_section, m_al); m_compiler_globals[name] = no_of_globals; no_of_globals++; } + template + void emit_const(Vec &m_code, wasm::type typ, T init_val) { + using namespace wasm; + switch (typ) + { + case i32: + wasm::emit_b8(m_code, m_al, 0x41); // emit instruction + wasm::emit_i32(m_code, m_al, init_val); // emit val + break; + case i64: + wasm::emit_b8(m_code, m_al, 0x42); // emit instruction + wasm::emit_i64(m_code, m_al, init_val); // emit val + break; + case f32: + wasm::emit_b8(m_code, m_al, 0x43); // emit instruction + wasm::emit_f32(m_code, m_al, init_val); // emit val + break; + case f64: + wasm::emit_b8(m_code, m_al, 0x44); // emit instruction + wasm::emit_f64(m_code, m_al, init_val); // emit val + break; + default: + throw CodeGenError("emit_global_const: Unsupported type"); + } + } + void declare_global_var(ASR::Variable_t* v) { if (v->m_type->type == ASR::ttypeType::TypeParameter) { // Ignore type variables return; } + using namespace wasm; + m_global_var_idx_map[get_hash((ASR::asr_t *)v)] = no_of_globals; emit_var_type(m_global_section, v, no_of_globals, false); m_global_section.push_back(m_al, true); // mutable @@ -682,15 +704,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { init_val = ASR::down_cast(v->m_value)->m_n; } switch (kind) { - case 4: - wasm::emit_i32_const(m_global_section, m_al, init_val); - break; - case 8: - wasm::emit_i64_const(m_global_section, m_al, init_val); - break; - default: - throw CodeGenError( - "Declare Global: Unsupported Integer kind"); + case 4: emit_const(m_global_section, i32, init_val); break; + case 8: emit_const(m_global_section, i64, init_val); break; + default: throw CodeGenError("Declare Global: Unsupported Integer kind"); } break; } @@ -700,15 +716,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { init_val = ASR::down_cast(v->m_value)->m_r; } switch (kind) { - case 4: - wasm::emit_f32_const(m_global_section, m_al, init_val); - break; - case 8: - wasm::emit_f64_const(m_global_section, m_al, init_val); - break; - default: - throw CodeGenError( - "Declare Global: Unsupported Real kind"); + case 4: emit_const(m_global_section, f32, init_val); break; + case 8: emit_const(m_global_section, f64, init_val); break; + default: throw CodeGenError("Declare Global: Unsupported Real kind"); } break; } @@ -718,12 +728,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { init_val = ASR::down_cast(v->m_value)->m_value; } switch (kind) { - case 4: - wasm::emit_i32_const(m_global_section, m_al, init_val); - break; - default: - throw CodeGenError( - "Declare Global: Unsupported Logical kind"); + case 4: emit_const(m_global_section, i32, init_val); break; + default: throw CodeGenError("Declare Global: Unsupported Logical kind"); } break; } @@ -735,21 +741,19 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { emit_string(init_val); switch (kind) { case 1: - wasm::emit_i32_const(m_global_section, m_al, m_string_to_iov_loc_map[init_val]); + emit_const(m_global_section, i32, m_string_to_iov_loc_map[init_val]); break; - default: - throw CodeGenError( - "Declare Global: Unsupported Character kind"); + default: throw CodeGenError("Declare Global: Unsupported Character kind"); } break; } default: { diag.codegen_warning_label("Declare Global: Type " + ASRUtils::type_to_str(v->m_type) + " not yet supported", {v->base.base.loc}, ""); - wasm::emit_i32_const(m_global_section, m_al, 0); + emit_const(m_global_section, i32, 0); } } - wasm::emit_expr_end(m_global_section, m_al); // end instructions + wasm::emit_expr_end(m_global_section, m_al); } void declare_symbols(const ASR::TranslationUnit_t &x) { @@ -1036,17 +1040,17 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { uint64_t hash = get_hash((ASR::asr_t *)v); if (m_var_idx_map.find(hash) != m_var_idx_map.end()) { uint32_t var_idx = m_var_idx_map[hash]; - wasm::emit_local_get(m_code_section, m_al, var_idx); + wia.emit_local_get(var_idx); if (ASRUtils::is_complex(*v->m_type)) { // get the imaginary part - wasm::emit_local_get(m_code_section, m_al, var_idx + 1u); + wia.emit_local_get(var_idx + 1u); } } else if (m_global_var_idx_map.find(hash) != m_global_var_idx_map.end()) { uint32_t var_idx = m_global_var_idx_map[hash]; - wasm::emit_global_get(m_code_section, m_al, var_idx); + wia.emit_global_get(var_idx); if (ASRUtils::is_complex(*v->m_type)) { // get the imaginary part - wasm::emit_global_get(m_code_section, m_al, var_idx + 1u); + wia.emit_global_get(var_idx + 1u); } } else { throw CodeGenError("Variable " + std::string(v->m_name) + " not declared"); @@ -1059,16 +1063,16 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { uint32_t var_idx = m_var_idx_map[hash]; if (ASRUtils::is_complex(*v->m_type)) { // set the imaginary part - wasm::emit_local_set(m_code_section, m_al, var_idx + 1u); + wia.emit_local_set(var_idx + 1u); } - wasm::emit_local_set(m_code_section, m_al, var_idx); + wia.emit_local_set(var_idx); } else if (m_global_var_idx_map.find(hash) != m_global_var_idx_map.end()) { uint32_t var_idx = m_global_var_idx_map[hash]; if (ASRUtils::is_complex(*v->m_type)) { // set the imaginary part - wasm::emit_global_set(m_code_section, m_al, var_idx + 1u); + wia.emit_global_set(var_idx + 1u); } - wasm::emit_global_set(m_code_section, m_al, var_idx); + wia.emit_global_set(var_idx); } else { throw CodeGenError("Variable " + std::string(v->m_name) + " not declared"); } @@ -1096,8 +1100,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { total_array_size *= dim; } - wasm::emit_i32_const(m_code_section, m_al, - avail_mem_loc); + wia.emit_i32_const(avail_mem_loc); emit_var_set(v); avail_mem_loc += kind * total_array_size; } @@ -1203,8 +1206,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } if (strcmp(x.m_name, "_start") == 0) { - wasm::emit_i32_const(m_code_section, m_al, 0 /* zero exit code */); - wasm::emit_call(m_code_section, m_al, m_import_func_idx_map[proc_exit]); + wia.emit_i32_const(0 /* zero exit code */); + wia.emit_call(m_import_func_idx_map[proc_exit]); } if (x.n_body == 0 || !ASR::is_a(*x.m_body[x.n_body - 1])) { @@ -1288,12 +1291,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case ASR::ttypeType::Integer: { switch (kind) { case 4: - wasm::emit_i32_store(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i32_store(wasm::mem_align::b8, 0); break; case 8: - wasm::emit_i64_store(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i64_store(wasm::mem_align::b8, 0); break; default: throw CodeGenError( @@ -1304,12 +1305,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case ASR::ttypeType::Real: { switch (kind) { case 4: - wasm::emit_f32_store(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_f32_store(wasm::mem_align::b8, 0); break; case 8: - wasm::emit_f64_store(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_f64_store(wasm::mem_align::b8, 0); break; default: throw CodeGenError( @@ -1320,8 +1319,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case ASR::ttypeType::Logical: { switch (kind) { case 4: - wasm::emit_i32_store(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i32_store(wasm::mem_align::b8, 0); break; default: throw CodeGenError( @@ -1332,12 +1330,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case ASR::ttypeType::Character: { switch (kind) { case 4: - wasm::emit_i32_store(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i32_store(wasm::mem_align::b8, 0); break; case 8: - wasm::emit_i64_store(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i64_store(wasm::mem_align::b8, 0); break; default: throw CodeGenError( @@ -1361,12 +1357,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case ASR::ttypeType::Integer: { switch (kind) { case 4: - wasm::emit_i32_load(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i32_load(wasm::mem_align::b8, 0); break; case 8: - wasm::emit_i64_load(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i64_load(wasm::mem_align::b8, 0); break; default: throw CodeGenError( @@ -1377,12 +1371,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case ASR::ttypeType::Real: { switch (kind) { case 4: - wasm::emit_f32_load(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_f32_load(wasm::mem_align::b8, 0); break; case 8: - wasm::emit_f64_load(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_f64_load(wasm::mem_align::b8, 0); break; default: throw CodeGenError("MemoryLoad: Unsupported Real kind"); @@ -1392,8 +1384,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case ASR::ttypeType::Logical: { switch (kind) { case 4: - wasm::emit_i32_load(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i32_load(wasm::mem_align::b8, 0); break; default: throw CodeGenError( @@ -1404,12 +1395,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case ASR::ttypeType::Character: { switch (kind) { case 4: - wasm::emit_i32_load(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i32_load(wasm::mem_align::b8, 0); break; case 8: - wasm::emit_i64_load(m_code_section, m_al, - wasm::mem_align::b8, 0); + wia.emit_i64_load(wasm::mem_align::b8, 0); break; default: throw CodeGenError( @@ -1452,19 +1441,19 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (i->m_kind == 4) { switch (x.m_op) { case ASR::binopType::Add: { - wasm::emit_i32_add(m_code_section, m_al); + wia.emit_i32_add(); break; }; case ASR::binopType::Sub: { - wasm::emit_i32_sub(m_code_section, m_al); + wia.emit_i32_sub(); break; }; case ASR::binopType::Mul: { - wasm::emit_i32_mul(m_code_section, m_al); + wia.emit_i32_mul(); break; }; case ASR::binopType::Div: { - wasm::emit_i32_div_s(m_code_section, m_al); + wia.emit_i32_div_s(); break; }; case ASR::binopType::Pow: { @@ -1474,9 +1463,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { ASR::down_cast(val); if (c->m_n == 2) { // drop the last stack item in the wasm stack - wasm::emit_drop(m_code_section, m_al); + wia.emit_drop(); this->visit_expr(*x.m_left); - wasm::emit_i32_mul(m_code_section, m_al); + wia.emit_i32_mul(); } else { throw CodeGenError( "IntegerBinop kind 4: only x**2 implemented so " @@ -1490,23 +1479,23 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { break; }; case ASR::binopType::BitAnd: { - wasm::emit_i32_and(m_code_section, m_al); + wia.emit_i32_and(); break; }; case ASR::binopType::BitOr: { - wasm::emit_i32_or(m_code_section, m_al); + wia.emit_i32_or(); break; }; case ASR::binopType::BitXor: { - wasm::emit_i32_xor(m_code_section, m_al); + wia.emit_i32_xor(); break; }; case ASR::binopType::BitLShift: { - wasm::emit_i32_shl(m_code_section, m_al); + wia.emit_i32_shl(); break; }; case ASR::binopType::BitRShift: { - wasm::emit_i32_shr_s(m_code_section, m_al); + wia.emit_i32_shr_s(); break; }; default: { @@ -1517,19 +1506,19 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } else if (i->m_kind == 8) { switch (x.m_op) { case ASR::binopType::Add: { - wasm::emit_i64_add(m_code_section, m_al); + wia.emit_i64_add(); break; }; case ASR::binopType::Sub: { - wasm::emit_i64_sub(m_code_section, m_al); + wia.emit_i64_sub(); break; }; case ASR::binopType::Mul: { - wasm::emit_i64_mul(m_code_section, m_al); + wia.emit_i64_mul(); break; }; case ASR::binopType::Div: { - wasm::emit_i64_div_s(m_code_section, m_al); + wia.emit_i64_div_s(); break; }; case ASR::binopType::Pow: { @@ -1539,9 +1528,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { ASR::down_cast(val); if (c->m_n == 2) { // drop the last stack item in the wasm stack - wasm::emit_drop(m_code_section, m_al); + wia.emit_drop(); this->visit_expr(*x.m_left); - wasm::emit_i64_mul(m_code_section, m_al); + wia.emit_i64_mul(); } else { throw CodeGenError( "IntegerBinop kind 8: only x**2 implemented so " @@ -1555,23 +1544,23 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { break; }; case ASR::binopType::BitAnd: { - wasm::emit_i64_and(m_code_section, m_al); + wia.emit_i64_and(); break; }; case ASR::binopType::BitOr: { - wasm::emit_i64_or(m_code_section, m_al); + wia.emit_i64_or(); break; }; case ASR::binopType::BitXor: { - wasm::emit_i64_xor(m_code_section, m_al); + wia.emit_i64_xor(); break; }; case ASR::binopType::BitLShift: { - wasm::emit_i64_shl(m_code_section, m_al); + wia.emit_i64_shl(); break; }; case ASR::binopType::BitRShift: { - wasm::emit_i64_shr_s(m_code_section, m_al); + wia.emit_i64_shr_s(); break; }; default: { @@ -1594,12 +1583,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { // there is no direct bit-invert inst in wasm, // so xor-ing with -1 (sequence of 32/64 1s) if(i->m_kind == 4){ - wasm::emit_i32_const(m_code_section, m_al, -1); - wasm::emit_i32_xor(m_code_section, m_al); + wia.emit_i32_const(-1); + wia.emit_i32_xor(); } else if(i->m_kind == 8){ - wasm::emit_i64_const(m_code_section, m_al, -1LL); - wasm::emit_i64_xor(m_code_section, m_al); + wia.emit_i64_const(-1LL); + wia.emit_i64_xor(); } else{ throw CodeGenError("IntegerBitNot: Only kind 4 and 8 supported"); @@ -1617,19 +1606,19 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (f->m_kind == 4) { switch (x.m_op) { case ASR::binopType::Add: { - wasm::emit_f32_add(m_code_section, m_al); + wia.emit_f32_add(); break; }; case ASR::binopType::Sub: { - wasm::emit_f32_sub(m_code_section, m_al); + wia.emit_f32_sub(); break; }; case ASR::binopType::Mul: { - wasm::emit_f32_mul(m_code_section, m_al); + wia.emit_f32_mul(); break; }; case ASR::binopType::Div: { - wasm::emit_f32_div(m_code_section, m_al); + wia.emit_f32_div(); break; }; case ASR::binopType::Pow: { @@ -1639,9 +1628,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { ASR::down_cast(val); if (c->m_r == 2.0) { // drop the last stack item in the wasm stack - wasm::emit_drop(m_code_section, m_al); + wia.emit_drop(); this->visit_expr(*x.m_left); - wasm::emit_f32_mul(m_code_section, m_al); + wia.emit_f32_mul(); } else { throw CodeGenError( "RealBinop: only x**2 implemented so far for " @@ -1662,19 +1651,19 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } else if (f->m_kind == 8) { switch (x.m_op) { case ASR::binopType::Add: { - wasm::emit_f64_add(m_code_section, m_al); + wia.emit_f64_add(); break; }; case ASR::binopType::Sub: { - wasm::emit_f64_sub(m_code_section, m_al); + wia.emit_f64_sub(); break; }; case ASR::binopType::Mul: { - wasm::emit_f64_mul(m_code_section, m_al); + wia.emit_f64_mul(); break; }; case ASR::binopType::Div: { - wasm::emit_f64_div(m_code_section, m_al); + wia.emit_f64_div(); break; }; case ASR::binopType::Pow: { @@ -1684,9 +1673,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { ASR::down_cast(val); if (c->m_r == 2.0) { // drop the last stack item in the wasm stack - wasm::emit_drop(m_code_section, m_al); + wia.emit_drop(); this->visit_expr(*x.m_left); - wasm::emit_f64_mul(m_code_section, m_al); + wia.emit_f64_mul(); } else { throw CodeGenError( "RealBinop: only x**2 implemented so far for " @@ -1723,12 +1712,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (m_rt_func_used_idx[add_c32] == -1) { m_rt_func_used_idx[add_c32] = no_of_types++; } - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[add_c32]); + wia.emit_call(m_rt_func_used_idx[add_c32]); } else { if (m_rt_func_used_idx[add_c64] == -1) { m_rt_func_used_idx[add_c64] = no_of_types++; } - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[add_c64]); + wia.emit_call(m_rt_func_used_idx[add_c64]); } break; }; @@ -1737,12 +1726,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (m_rt_func_used_idx[sub_c32] == -1) { m_rt_func_used_idx[sub_c32] = no_of_types++; } - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[sub_c32]); + wia.emit_call(m_rt_func_used_idx[sub_c32]); } else { if (m_rt_func_used_idx[sub_c64] == -1) { m_rt_func_used_idx[sub_c64] = no_of_types++; } - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[sub_c64]); + wia.emit_call(m_rt_func_used_idx[sub_c64]); } break; }; @@ -1751,12 +1740,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (m_rt_func_used_idx[mul_c32] == -1) { m_rt_func_used_idx[mul_c32] = no_of_types++; } - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[mul_c32]); + wia.emit_call(m_rt_func_used_idx[mul_c32]); } else { if (m_rt_func_used_idx[mul_c64] == -1) { m_rt_func_used_idx[mul_c64] = no_of_types++; } - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[mul_c64]); + wia.emit_call(m_rt_func_used_idx[mul_c64]); } break; }; @@ -1775,13 +1764,13 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { ASR::Integer_t *i = ASR::down_cast(x.m_type); // there seems no direct unary-minus inst in wasm, so subtracting from 0 if (i->m_kind == 4) { - wasm::emit_i32_const(m_code_section, m_al, 0); + wia.emit_i32_const(0); this->visit_expr(*x.m_arg); - wasm::emit_i32_sub(m_code_section, m_al); + wia.emit_i32_sub(); } else if (i->m_kind == 8) { - wasm::emit_i64_const(m_code_section, m_al, 0LL); + wia.emit_i64_const(0LL); this->visit_expr(*x.m_arg); - wasm::emit_i64_sub(m_code_section, m_al); + wia.emit_i64_sub(); } else { throw CodeGenError( "IntegerUnaryMinus: Only kind 4 and 8 supported"); @@ -1796,10 +1785,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { ASR::Real_t *f = ASR::down_cast(x.m_type); if (f->m_kind == 4) { this->visit_expr(*x.m_arg); - wasm::emit_f32_neg(m_code_section, m_al); + wia.emit_f32_neg(); } else if (f->m_kind == 8) { this->visit_expr(*x.m_arg); - wasm::emit_f64_neg(m_code_section, m_al); + wia.emit_f64_neg(); } else { throw CodeGenError("RealUnaryMinus: Only kind 4 and 8 supported"); } @@ -1813,16 +1802,16 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { ASR::Complex_t *f = ASR::down_cast(x.m_type); if (f->m_kind == 4) { this->visit_expr(*x.m_arg); - wasm::emit_f32_neg(m_code_section, m_al); - wasm::emit_global_set(m_code_section, m_al, m_compiler_globals[tmp_reg_f32]); - wasm::emit_f32_neg(m_code_section, m_al); - wasm::emit_global_get(m_code_section, m_al, m_compiler_globals[tmp_reg_f32]); + wia.emit_f32_neg(); + wia.emit_global_set(m_compiler_globals[tmp_reg_f32]); + wia.emit_f32_neg(); + wia.emit_global_get(m_compiler_globals[tmp_reg_f32]); } else if (f->m_kind == 8) { this->visit_expr(*x.m_arg); - wasm::emit_f64_neg(m_code_section, m_al); - wasm::emit_global_set(m_code_section, m_al, m_compiler_globals[tmp_reg_f64]); - wasm::emit_f64_neg(m_code_section, m_al); - wasm::emit_global_get(m_code_section, m_al, m_compiler_globals[tmp_reg_f64]); + wia.emit_f64_neg(); + wia.emit_global_set(m_compiler_globals[tmp_reg_f64]); + wia.emit_f64_neg(); + wia.emit_global_get(m_compiler_globals[tmp_reg_f64]); } else { throw CodeGenError("ComplexUnaryMinus: Only kind 4 and 8 supported"); } @@ -1859,27 +1848,27 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (a_kind == 4) { switch (x.m_op) { case (ASR::cmpopType::Eq): { - wasm::emit_i32_eq(m_code_section, m_al); + wia.emit_i32_eq(); break; } case (ASR::cmpopType::Gt): { - wasm::emit_i32_gt_s(m_code_section, m_al); + wia.emit_i32_gt_s(); break; } case (ASR::cmpopType::GtE): { - wasm::emit_i32_ge_s(m_code_section, m_al); + wia.emit_i32_ge_s(); break; } case (ASR::cmpopType::Lt): { - wasm::emit_i32_lt_s(m_code_section, m_al); + wia.emit_i32_lt_s(); break; } case (ASR::cmpopType::LtE): { - wasm::emit_i32_le_s(m_code_section, m_al); + wia.emit_i32_le_s(); break; } case (ASR::cmpopType::NotEq): { - wasm::emit_i32_ne(m_code_section, m_al); + wia.emit_i32_ne(); break; } default: @@ -1890,27 +1879,27 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } else if (a_kind == 8) { switch (x.m_op) { case (ASR::cmpopType::Eq): { - wasm::emit_i64_eq(m_code_section, m_al); + wia.emit_i64_eq(); break; } case (ASR::cmpopType::Gt): { - wasm::emit_i64_gt_s(m_code_section, m_al); + wia.emit_i64_gt_s(); break; } case (ASR::cmpopType::GtE): { - wasm::emit_i64_ge_s(m_code_section, m_al); + wia.emit_i64_ge_s(); break; } case (ASR::cmpopType::Lt): { - wasm::emit_i64_lt_s(m_code_section, m_al); + wia.emit_i64_lt_s(); break; } case (ASR::cmpopType::LtE): { - wasm::emit_i64_le_s(m_code_section, m_al); + wia.emit_i64_le_s(); break; } case (ASR::cmpopType::NotEq): { - wasm::emit_i64_ne(m_code_section, m_al); + wia.emit_i64_ne(); break; } default: @@ -1935,27 +1924,27 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (a_kind == 4) { switch (x.m_op) { case (ASR::cmpopType::Eq): { - wasm::emit_f32_eq(m_code_section, m_al); + wia.emit_f32_eq(); break; } case (ASR::cmpopType::Gt): { - wasm::emit_f32_gt(m_code_section, m_al); + wia.emit_f32_gt(); break; } case (ASR::cmpopType::GtE): { - wasm::emit_f32_ge(m_code_section, m_al); + wia.emit_f32_ge(); break; } case (ASR::cmpopType::Lt): { - wasm::emit_f32_lt(m_code_section, m_al); + wia.emit_f32_lt(); break; } case (ASR::cmpopType::LtE): { - wasm::emit_f32_le(m_code_section, m_al); + wia.emit_f32_le(); break; } case (ASR::cmpopType::NotEq): { - wasm::emit_f32_ne(m_code_section, m_al); + wia.emit_f32_ne(); break; } default: @@ -1965,27 +1954,27 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } else if (a_kind == 8) { switch (x.m_op) { case (ASR::cmpopType::Eq): { - wasm::emit_f64_eq(m_code_section, m_al); + wia.emit_f64_eq(); break; } case (ASR::cmpopType::Gt): { - wasm::emit_f64_gt(m_code_section, m_al); + wia.emit_f64_gt(); break; } case (ASR::cmpopType::GtE): { - wasm::emit_f64_ge(m_code_section, m_al); + wia.emit_f64_ge(); break; } case (ASR::cmpopType::Lt): { - wasm::emit_f64_lt(m_code_section, m_al); + wia.emit_f64_lt(); break; } case (ASR::cmpopType::LtE): { - wasm::emit_f64_le(m_code_section, m_al); + wia.emit_f64_le(); break; } case (ASR::cmpopType::NotEq): { - wasm::emit_f64_ne(m_code_section, m_al); + wia.emit_f64_ne(); break; } default: @@ -2028,23 +2017,23 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (a_kind == 4) { switch (x.m_op) { case (ASR::logicalbinopType::And): { - wasm::emit_i32_and(m_code_section, m_al); + wia.emit_i32_and(); break; } case (ASR::logicalbinopType::Or): { - wasm::emit_i32_or(m_code_section, m_al); + wia.emit_i32_or(); break; } case ASR::logicalbinopType::Xor: { - wasm::emit_i32_xor(m_code_section, m_al); + wia.emit_i32_xor(); break; } case (ASR::logicalbinopType::NEqv): { - wasm::emit_i32_xor(m_code_section, m_al); + wia.emit_i32_xor(); break; } case (ASR::logicalbinopType::Eqv): { - wasm::emit_i32_eq(m_code_section, m_al); + wia.emit_i32_eq(); break; } default: @@ -2064,9 +2053,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { this->visit_expr(*x.m_arg); int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); if (a_kind == 4) { - wasm::emit_i32_eqz(m_code_section, m_al); + wia.emit_i32_eqz(); } else if (a_kind == 8) { - wasm::emit_i64_eqz(m_code_section, m_al); + wia.emit_i64_eqz(); } else { throw CodeGenError("LogicalNot: kind 4 and 8 supported only"); } @@ -2112,12 +2101,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { ASR::dimension_t *m_dims; ASRUtils::extract_dimensions_from_ttype(ttype, m_dims); - wasm::emit_i32_const(m_code_section, m_al, 0); + wia.emit_i32_const(0); for (uint32_t i = 0; i < x.n_args; i++) { if (x.m_args[i].m_right) { this->visit_expr(*x.m_args[i].m_right); this->visit_expr(*m_dims[i].m_start); - wasm::emit_i32_sub(m_code_section, m_al); + wia.emit_i32_sub(); size_t jmin, jmax; if (x.m_storage_format == ASR::arraystorageType::ColMajor) { @@ -2132,18 +2121,18 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { for (size_t j = jmin; j < jmax; j++) { this->visit_expr(*m_dims[j].m_length); - wasm::emit_i32_mul(m_code_section, m_al); + wia.emit_i32_mul(); } - wasm::emit_i32_add(m_code_section, m_al); + wia.emit_i32_add(); } else { diag.codegen_warning_label("/* FIXME right index */", {x.base.base.loc}, ""); } } - wasm::emit_i32_const(m_code_section, m_al, kind); - wasm::emit_i32_mul(m_code_section, m_al); - wasm::emit_i32_add(m_code_section, m_al); + wia.emit_i32_const(kind); + wia.emit_i32_mul(); + wia.emit_i32_add(); } void visit_ArrayItem(const ASR::ArrayItem_t &x) { @@ -2178,13 +2167,13 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { this->visit_expr(*(m_dims[0].m_length)); for (int i = 1; i < n_dims; i++) { this->visit_expr(*m_dims[i].m_length); - wasm::emit_i32_mul(m_code_section, m_al); + wia.emit_i32_mul(); } } int kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); if (kind == 8) { - wasm::emit_i64_extend_i32_s(m_code_section, m_al); + wia.emit_i64_extend_i32_s(); } } @@ -2196,7 +2185,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { emit_var_get(return_var); } } - wasm::emit_b8(m_code_section, m_al, 0x0F); // wasm return + wia.emit_return(); // wasm return } void visit_Return(const ASR::Return_t & /* x */) { handle_return(); } @@ -2206,11 +2195,11 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { int a_kind = ((ASR::Integer_t *)(&(x.m_type->base)))->m_kind; switch (a_kind) { case 4: { - wasm::emit_i32_const(m_code_section, m_al, val); + wia.emit_i32_const(val); break; } case 8: { - wasm::emit_i64_const(m_code_section, m_al, val); + wia.emit_i64_const(val); break; } default: { @@ -2225,11 +2214,11 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { int a_kind = ((ASR::Real_t *)(&(x.m_type->base)))->m_kind; switch (a_kind) { case 4: { - wasm::emit_f32_const(m_code_section, m_al, val); + wia.emit_f32_const(val); break; } case 8: { - wasm::emit_f64_const(m_code_section, m_al, val); + wia.emit_f64_const(val); break; } default: { @@ -2244,7 +2233,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { int a_kind = ((ASR::Logical_t *)(&(x.m_type->base)))->m_kind; switch (a_kind) { case 4: { - wasm::emit_i32_const(m_code_section, m_al, val); + wia.emit_i32_const(val); break; } default: { @@ -2266,13 +2255,13 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); switch( a_kind ) { case 4: { - wasm::emit_f32_const(m_code_section, m_al, x.m_re); - wasm::emit_f32_const(m_code_section, m_al, x.m_im); + wia.emit_f32_const(x.m_re); + wia.emit_f32_const(x.m_im); break; } case 8: { - wasm::emit_f64_const(m_code_section, m_al, x.m_re); - wasm::emit_f64_const(m_code_section, m_al, x.m_im); + wia.emit_f64_const(x.m_re); + wia.emit_f64_const(x.m_im); break; } default: { @@ -2323,7 +2312,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { void visit_StringConstant(const ASR::StringConstant_t &x) { emit_string(x.m_s); - wasm::emit_i32_const(m_code_section, m_al, m_string_to_iov_loc_map[x.m_s]); + wia.emit_i32_const(m_string_to_iov_loc_map[x.m_s]); } void visit_ArrayConstant(const ASR::ArrayConstant_t &x) { @@ -2332,14 +2321,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { uint32_t cur_mem_loc = avail_mem_loc; for (size_t i = 0; i < x.n_args; i++) { // emit memory location to store array element - wasm::emit_i32_const(m_code_section, m_al, avail_mem_loc); + wia.emit_i32_const(avail_mem_loc); this->visit_expr(*x.m_args[i]); int element_size_in_bytes = emit_memory_store(x.m_args[i]); avail_mem_loc += element_size_in_bytes; } // leave array location in memory on the stack - wasm::emit_i32_const(m_code_section, m_al, cur_mem_loc); + wia.emit_i32_const(cur_mem_loc); } void visit_FunctionCall(const ASR::FunctionCall_t &x) { @@ -2357,17 +2346,17 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { uint64_t hash = get_hash((ASR::asr_t *)fn); if (m_func_name_idx_map.find(hash) != m_func_name_idx_map.end()) { - wasm::emit_call(m_code_section, m_al, m_func_name_idx_map[hash]->index); + wia.emit_call(m_func_name_idx_map[hash]->index); } else { if (strcmp(fn->m_name, "c_caimag") == 0) { LCOMPILERS_ASSERT(x.n_args == 1); - wasm::emit_global_set(m_code_section, m_al, m_compiler_globals[tmp_reg_f32]); - wasm::emit_drop(m_code_section, m_al); - wasm::emit_global_get(m_code_section, m_al, m_compiler_globals[tmp_reg_f32]); + wia.emit_global_set(m_compiler_globals[tmp_reg_f32]); + wia.emit_drop(); + wia.emit_global_get(m_compiler_globals[tmp_reg_f32]); } else if (strcmp(fn->m_name, "c_zaimag") == 0) { - wasm::emit_global_set(m_code_section, m_al, m_compiler_globals[tmp_reg_f64]); - wasm::emit_drop(m_code_section, m_al); - wasm::emit_global_get(m_code_section, m_al, m_compiler_globals[tmp_reg_f64]); + wia.emit_global_set(m_compiler_globals[tmp_reg_f64]); + wia.emit_drop(); + wia.emit_global_get(m_compiler_globals[tmp_reg_f64]); } else { throw CodeGenError("FunctionCall: Function " + std::string(fn->m_name) + " not found"); } @@ -2420,8 +2409,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { " not yet supported"); } } - wasm::emit_global_set(m_code_section, m_al, - m_compiler_globals[global_var]); + wia.emit_global_set(m_compiler_globals[global_var]); } void temp_value_get(ASR::expr_t* expr) { @@ -2470,8 +2458,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { " not yet supported"); } } - wasm::emit_global_get(m_code_section, m_al, - m_compiler_globals[global_var]); + wia.emit_global_get(m_compiler_globals[global_var]); } void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { @@ -2498,7 +2485,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { uint64_t hash = get_hash((ASR::asr_t *)s); if (m_func_name_idx_map.find(hash) != m_func_name_idx_map.end()) { - wasm::emit_call(m_code_section, m_al, m_func_name_idx_map[hash]->index); + wia.emit_call(m_func_name_idx_map[hash]->index); } else { throw CodeGenError("SubroutineCall: Function " + std::string(s->m_name) + " not found"); } @@ -2541,13 +2528,13 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0) { if (arg_kind == 4 && dest_kind == 4) { - wasm::emit_f32_convert_i32_s(m_code_section, m_al); + wia.emit_f32_convert_i32_s(); } else if (arg_kind == 8 && dest_kind == 8) { - wasm::emit_f64_convert_i64_s(m_code_section, m_al); + wia.emit_f64_convert_i64_s(); } else if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_f64_convert_i32_s(m_code_section, m_al); + wia.emit_f64_convert_i32_s(); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_f32_convert_i64_s(m_code_section, m_al); + wia.emit_f32_convert_i64_s(); } else { std::string msg = "Conversion from " + std::to_string(arg_kind) + " to " + @@ -2563,13 +2550,13 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0) { if (arg_kind == 4 && dest_kind == 4) { - wasm::emit_i32_trunc_f32_s(m_code_section, m_al); + wia.emit_i32_trunc_f32_s(); } else if (arg_kind == 8 && dest_kind == 8) { - wasm::emit_i64_trunc_f64_s(m_code_section, m_al); + wia.emit_i64_trunc_f64_s(); } else if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_i64_trunc_f32_s(m_code_section, m_al); + wia.emit_i64_trunc_f32_s(); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_i32_trunc_f64_s(m_code_section, m_al); + wia.emit_i32_trunc_f64_s(); } else { std::string msg = "Conversion from " + std::to_string(arg_kind) + " to " + @@ -2586,9 +2573,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (arg_kind == dest_kind) { } else if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_f64_promote_f32(m_code_section, m_al); + wia.emit_f64_promote_f32(); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_f32_demote_f64(m_code_section, m_al); + wia.emit_f32_demote_f64(); } else { std::string msg = "RealToComplex: Conversion from " + std::to_string(arg_kind) + " to " + @@ -2599,10 +2586,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { switch(dest_kind) { case 4: - wasm::emit_f32_const(m_code_section, m_al, 0.0); + wia.emit_f32_const(0.0); break; case 8: - wasm::emit_f64_const(m_code_section, m_al, 0.0); + wia.emit_f64_const(0.0); break; default: throw CodeGenError("RealToComplex: Only 32 and 64 bits real kinds are supported."); @@ -2614,13 +2601,13 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0) { if (arg_kind == 4 && dest_kind == 4) { - wasm::emit_f32_convert_i32_s(m_code_section, m_al); + wia.emit_f32_convert_i32_s(); } else if (arg_kind == 8 && dest_kind == 8) { - wasm::emit_f64_convert_i64_s(m_code_section, m_al); + wia.emit_f64_convert_i64_s(); } else if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_f64_convert_i32_s(m_code_section, m_al); + wia.emit_f64_convert_i32_s(); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_f32_convert_i64_s(m_code_section, m_al); + wia.emit_f32_convert_i64_s(); } else { std::string msg = "IntegerToComplex: Conversion from " + std::to_string(arg_kind) + " to " + @@ -2632,10 +2619,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { switch(dest_kind) { case 4: - wasm::emit_f32_const(m_code_section, m_al, 0.0); + wia.emit_f32_const(0.0); break; case 8: - wasm::emit_f64_const(m_code_section, m_al, 0.0); + wia.emit_f64_const(0.0); break; default: throw CodeGenError("RealToComplex: Only 32 and 64 bits real kinds are supported."); @@ -2647,12 +2634,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0) { if (arg_kind == 4 && dest_kind == 4) { - wasm::emit_i32_eqz(m_code_section, m_al); - wasm::emit_i32_eqz(m_code_section, m_al); + wia.emit_i32_eqz(); + wia.emit_i32_eqz(); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_i64_eqz(m_code_section, m_al); - wasm::emit_i64_eqz(m_code_section, m_al); - wasm::emit_i32_wrap_i64(m_code_section, m_al); + wia.emit_i64_eqz(); + wia.emit_i64_eqz(); + wia.emit_i32_wrap_i64(); } else { std::string msg = "Conversion from kinds " + std::to_string(arg_kind) + " to " + @@ -2668,14 +2655,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0) { if (arg_kind == 4 && dest_kind == 4) { - wasm::emit_f32_const(m_code_section, m_al, 0.0); - wasm::emit_f32_eq(m_code_section, m_al); - wasm::emit_i32_eqz(m_code_section, m_al); + wia.emit_f32_const(0.0); + wia.emit_f32_eq(); + wia.emit_i32_eqz(); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_f64_const(m_code_section, m_al, 0.0); - wasm::emit_f64_eq(m_code_section, m_al); - wasm::emit_i64_eqz(m_code_section, m_al); - wasm::emit_i32_wrap_i64(m_code_section, m_al); + wia.emit_f64_const(0.0); + wia.emit_f64_eq(); + wia.emit_i64_eqz(); + wia.emit_i32_wrap_i64(); } else { std::string msg = "Conversion from kinds " + std::to_string(arg_kind) + " to " + @@ -2698,16 +2685,16 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { if (m_rt_func_used_idx[abs_c32] == -1) { m_rt_func_used_idx[abs_c32] = no_of_types++; } - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[abs_c32]); - wasm::emit_f32_const(m_code_section, m_al, 0.0); - wasm::emit_f32_gt(m_code_section, m_al); + wia.emit_call(m_rt_func_used_idx[abs_c32]); + wia.emit_f32_const(0.0); + wia.emit_f32_gt(); } else if (arg_kind == 8) { if (m_rt_func_used_idx[abs_c64] == -1) { m_rt_func_used_idx[abs_c64] = no_of_types++; } - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[abs_c64]); - wasm::emit_f64_const(m_code_section, m_al, 0.0); - wasm::emit_f64_gt(m_code_section, m_al); + wia.emit_call(m_rt_func_used_idx[abs_c64]); + wia.emit_f64_const(0.0); + wia.emit_f64_gt(); } else { std::string msg = "ComplexToLogical: Conversion from kinds " + std::to_string(arg_kind) + " to " + @@ -2722,7 +2709,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0) { if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_i64_extend_i32_s(m_code_section, m_al); + wia.emit_i64_extend_i32_s(); } else if (arg_kind == 4 && dest_kind == 4) { } else { std::string msg = "Conversion from kinds " + @@ -2739,9 +2726,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0) { if (arg_kind == 4 && dest_kind == 4) { - wasm::emit_f32_convert_i32_s(m_code_section, m_al); + wia.emit_f32_convert_i32_s(); } else if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_f64_convert_i32_s(m_code_section, m_al); + wia.emit_f64_convert_i32_s(); } else { std::string msg = "Conversion from kinds " + std::to_string(arg_kind) + " to " + @@ -2757,9 +2744,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0 && arg_kind != dest_kind) { if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_i64_extend_i32_s(m_code_section, m_al); + wia.emit_i64_extend_i32_s(); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_i32_wrap_i64(m_code_section, m_al); + wia.emit_i32_wrap_i64(); } else { std::string msg = "Conversion from " + std::to_string(arg_kind) + " to " + @@ -2775,9 +2762,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0 && arg_kind != dest_kind) { if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_f64_promote_f32(m_code_section, m_al); + wia.emit_f64_promote_f32(); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_f32_demote_f64(m_code_section, m_al); + wia.emit_f32_demote_f64(); } else { std::string msg = "Conversion from " + std::to_string(arg_kind) + " to " + @@ -2793,15 +2780,15 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0 && arg_kind != dest_kind) { if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_f64_promote_f32(m_code_section, m_al); - wasm::emit_global_set(m_code_section, m_al, m_compiler_globals[tmp_reg_f64]); - wasm::emit_f64_promote_f32(m_code_section, m_al); - wasm::emit_global_get(m_code_section, m_al, m_compiler_globals[tmp_reg_f64]); + wia.emit_f64_promote_f32(); + wia.emit_global_set(m_compiler_globals[tmp_reg_f64]); + wia.emit_f64_promote_f32(); + wia.emit_global_get(m_compiler_globals[tmp_reg_f64]); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_f32_demote_f64(m_code_section, m_al); - wasm::emit_global_set(m_code_section, m_al, m_compiler_globals[tmp_reg_f32]); - wasm::emit_f32_demote_f64(m_code_section, m_al); - wasm::emit_global_get(m_code_section, m_al, m_compiler_globals[tmp_reg_f32]); + wia.emit_f32_demote_f64(); + wia.emit_global_set(m_compiler_globals[tmp_reg_f32]); + wia.emit_f32_demote_f64(); + wia.emit_global_get(m_compiler_globals[tmp_reg_f32]); } else { std::string msg = "ComplexToComplex: Conversion from " + std::to_string(arg_kind) + " to " + @@ -2813,14 +2800,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { break; } case (ASR::cast_kindType::ComplexToReal): { - wasm::emit_drop(m_code_section, m_al); // drop imag part + wia.emit_drop(); // drop imag part int arg_kind = -1, dest_kind = -1; extract_kinds(x, arg_kind, dest_kind); if (arg_kind > 0 && dest_kind > 0 && arg_kind != dest_kind) { if (arg_kind == 4 && dest_kind == 8) { - wasm::emit_f64_promote_f32(m_code_section, m_al); + wia.emit_f64_promote_f32(); } else if (arg_kind == 8 && dest_kind == 4) { - wasm::emit_f32_demote_f64(m_code_section, m_al); + wia.emit_f32_demote_f64(); } else { std::string msg = "ComplexToReal: Conversion from " + std::to_string(arg_kind) + " to " + @@ -2838,30 +2825,28 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { void visit_ComplexRe(const ASR::ComplexRe_t &x) { this->visit_expr(*x.m_arg); - wasm::emit_drop(m_code_section, m_al); + wia.emit_drop(); } void visit_ComplexIm(const ASR::ComplexIm_t &x) { this->visit_expr(*x.m_arg); int a_kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(x.m_arg)); - wasm::emit_global_set(m_code_section, m_al, - (a_kind == 4) ? m_compiler_globals[tmp_reg_f32] + wia.emit_global_set((a_kind == 4) ? m_compiler_globals[tmp_reg_f32] : m_compiler_globals[tmp_reg_f64]); - wasm::emit_drop(m_code_section, m_al); - wasm::emit_global_get(m_code_section, m_al, - (a_kind == 4) ? m_compiler_globals[tmp_reg_f32] + wia.emit_drop(); + wia.emit_global_get((a_kind == 4) ? m_compiler_globals[tmp_reg_f32] : m_compiler_globals[tmp_reg_f64]); } void emit_call_fd_write(int filetype, const std::string &str, int iov_vec_len, int return_val_mem_loc) { - wasm::emit_i32_const(m_code_section, m_al, filetype); // file type: 1 for stdout - wasm::emit_i32_const(m_code_section, m_al, m_string_to_iov_loc_map[str]); // iov location - wasm::emit_i32_const(m_code_section, m_al, iov_vec_len); // size of iov vector - wasm::emit_i32_const(m_code_section, m_al, return_val_mem_loc); // mem_loction to return no. of bytes written + wia.emit_i32_const(filetype); // file type: 1 for stdout + wia.emit_i32_const(m_string_to_iov_loc_map[str]); // iov location + wia.emit_i32_const(iov_vec_len); // size of iov vector + wia.emit_i32_const(return_val_mem_loc); // mem_loction to return no. of bytes written // call WASI fd_write - wasm::emit_call(m_code_section, m_al, m_import_func_idx_map[fd_write]); - wasm::emit_drop(m_code_section, m_al); + wia.emit_call(m_import_func_idx_map[fd_write]); + wia.emit_drop(); } template @@ -2869,14 +2854,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { for (size_t i = 0; i < x.n_values; i++) { if (i > 0) { if (x.m_separator) { - wasm::emit_i32_const(m_code_section, m_al, 1); // file type: 1 for stdout + wia.emit_i32_const(1); // file type: 1 for stdout this->visit_expr(*x.m_separator); // iov location - wasm::emit_i32_const(m_code_section, m_al, 1); // size of iov vector - wasm::emit_i32_const(m_code_section, m_al, 0); // mem_loction to return no. of bytes written + wia.emit_i32_const(1); // size of iov vector + wia.emit_i32_const(0); // mem_loction to return no. of bytes written // call WASI fd_write - wasm::emit_call(m_code_section, m_al, m_import_func_idx_map[fd_write]); - wasm::emit_drop(m_code_section, m_al); + wia.emit_call(m_import_func_idx_map[fd_write]); + wia.emit_drop(); } else { emit_call_fd_write(1, " ", 1, 0); } @@ -2892,12 +2877,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { this->visit_expr(*x.m_values[i]); switch (a_kind) { case 4: { - wasm::emit_i64_extend_i32_s(m_code_section, m_al); - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[print_i64]); + wia.emit_i64_extend_i32_s(); + wia.emit_call(m_rt_func_used_idx[print_i64]); break; } case 8: { - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[print_i64]); + wia.emit_call(m_rt_func_used_idx[print_i64]); break; } default: { @@ -2916,12 +2901,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { this->visit_expr(*x.m_values[i]); switch (a_kind) { case 4: { - wasm::emit_f64_promote_f32(m_code_section, m_al); - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[print_f64]); + wia.emit_f64_promote_f32(); + wia.emit_call(m_rt_func_used_idx[print_f64]); break; } case 8: { - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[print_f64]); + wia.emit_call(m_rt_func_used_idx[print_f64]); break; } default: { @@ -2931,14 +2916,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } } } else if (t->type == ASR::ttypeType::Character) { - wasm::emit_i32_const(m_code_section, m_al, 1); // file type: 1 for stdout + wia.emit_i32_const(1); // file type: 1 for stdout this->visit_expr(*x.m_values[i]); // iov location - wasm::emit_i32_const(m_code_section, m_al, 1); // size of iov vector - wasm::emit_i32_const(m_code_section, m_al, 0); // mem_loction to return no. of bytes written + wia.emit_i32_const(1); // size of iov vector + wia.emit_i32_const(0); // mem_loction to return no. of bytes written // call WASI fd_write - wasm::emit_call(m_code_section, m_al, m_import_func_idx_map[fd_write]); - wasm::emit_drop(m_code_section, m_al); + wia.emit_call(m_import_func_idx_map[fd_write]); + wia.emit_drop(); } else if (t->type == ASR::ttypeType::Complex) { if (m_rt_func_used_idx[print_i64] == -1) { m_rt_func_used_idx[print_i64] = no_of_types++; @@ -2949,30 +2934,30 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { emit_call_fd_write(1, "(", 1, 0); this->visit_expr(*x.m_values[i]); if (a_kind == 4) { - wasm::emit_f64_promote_f32(m_code_section, m_al); - wasm::emit_global_set(m_code_section, m_al, m_compiler_globals[tmp_reg_f64]); - wasm::emit_f64_promote_f32(m_code_section, m_al); + wia.emit_f64_promote_f32(); + wia.emit_global_set(m_compiler_globals[tmp_reg_f64]); + wia.emit_f64_promote_f32(); } else { - wasm::emit_global_set(m_code_section, m_al, m_compiler_globals[tmp_reg_f64]); + wia.emit_global_set(m_compiler_globals[tmp_reg_f64]); } - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[print_f64]); + wia.emit_call(m_rt_func_used_idx[print_f64]); emit_call_fd_write(1, ",", 1, 0); - wasm::emit_global_get(m_code_section, m_al, m_compiler_globals[tmp_reg_f64]); - wasm::emit_call(m_code_section, m_al, m_rt_func_used_idx[print_f64]); + wia.emit_global_get(m_compiler_globals[tmp_reg_f64]); + wia.emit_call(m_rt_func_used_idx[print_f64]); emit_call_fd_write(1, ")", 1, 0); } } // print "\n" newline character if (x.m_end) { - wasm::emit_i32_const(m_code_section, m_al, 1); // file type: 1 for stdout + wia.emit_i32_const(1); // file type: 1 for stdout this->visit_expr(*x.m_end); // iov location - wasm::emit_i32_const(m_code_section, m_al, 1); // size of iov vector - wasm::emit_i32_const(m_code_section, m_al, 0); // mem_loction to return no. of bytes written + wia.emit_i32_const(1); // size of iov vector + wia.emit_i32_const(0); // mem_loction to return no. of bytes written // call WASI fd_write - wasm::emit_call(m_code_section, m_al, m_import_func_idx_map[fd_write]); - wasm::emit_drop(m_code_section, m_al); + wia.emit_call(m_import_func_idx_map[fd_write]); + wia.emit_drop(); } else { emit_call_fd_write(1, "\n", 1, 0); } @@ -3031,8 +3016,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { void exit() { // exit_code would be on stack, so set this exit code using // proc_exit(). this exit code would be read by JavaScript glue code - wasm::emit_call(m_code_section, m_al, m_import_func_idx_map[proc_exit]); - wasm::emit_unreachable(m_code_section, m_al); // raise trap/exception + wia.emit_call(m_import_func_idx_map[proc_exit]); + wia.emit_unreachable(); // raise trap/exception } void visit_ArrayBound(const ASR::ArrayBound_t& x) { @@ -3056,13 +3041,13 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } else { this->visit_expr(*m_dims[dimDir->m_n - 1].m_start); this->visit_expr(*m_dims[dimDir->m_n - 1].m_length); - wasm::emit_i32_add(m_code_section, m_al); - wasm::emit_i32_const(m_code_section, m_al, 1); - wasm::emit_i32_sub(m_code_section, m_al); + wia.emit_i32_add(); + wia.emit_i32_const(1); + wia.emit_i32_sub(); } } else { if (x.m_bound == ASR::arrayboundType::LBound) { - wasm::emit_i32_const(m_code_section, m_al, 1); + wia.emit_i32_const(1); } else { // emit the whole array size if (!m_dims[0].m_length) { @@ -3072,7 +3057,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { this->visit_expr(*(m_dims[0].m_length)); for (int i = 1; i < n_dims; i++) { this->visit_expr(*m_dims[i].m_length); - wasm::emit_i32_mul(m_code_section, m_al); + wia.emit_i32_mul(); } } } @@ -3084,14 +3069,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { ASRUtils::expr_type(x.m_code)->type == ASR::ttypeType::Integer) { this->visit_expr(*x.m_code); } else { - wasm::emit_i32_const(m_code_section, m_al, 0); // zero exit code + wia.emit_i32_const(0); // zero exit code } exit(); } void visit_ErrorStop(const ASR::ErrorStop_t & /* x */) { print_msg("ERROR STOP"); - wasm::emit_i32_const(m_code_section, m_al, 1); // non-zero exit code + wia.emit_i32_const(1); // non-zero exit code exit(); } @@ -3116,15 +3101,11 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } void visit_Exit(const ASR::Exit_t & /* x */) { - wasm::emit_branch(m_code_section, m_al, - nesting_level - cur_loop_nesting_level - - 2U); // branch to end of if + wia.emit_br(nesting_level - cur_loop_nesting_level - 2U); // branch to end of if } void visit_Cycle(const ASR::Cycle_t & /* x */) { - wasm::emit_branch( - m_code_section, m_al, - nesting_level - cur_loop_nesting_level - 1U); // branch to start of loop + wia.emit_br(nesting_level - cur_loop_nesting_level - 1U); // branch to start of loop } void visit_Assert(const ASR::Assert_t &x) { @@ -3139,9 +3120,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } else { print_msg("AssertionError"); } - wasm::emit_i32_const(m_code_section, m_al, 1); // non-zero exit code + wia.emit_i32_const(1); // non-zero exit code exit(); - wasm::emit_expr_end(m_code_section, m_al); // emit if end + wasm::emit_expr_end(m_code_section, m_al); } }; diff --git a/src/libasr/codegen/wasm_assembler.h b/src/libasr/codegen/wasm_assembler.h index 2f6df20742..1d18c66412 100644 --- a/src/libasr/codegen/wasm_assembler.h +++ b/src/libasr/codegen/wasm_assembler.h @@ -1,7 +1,6 @@ #include -#include -#include +#include namespace LCompilers { @@ -11,60 +10,8 @@ enum type { i32 = 0x7F, i64 = 0x7E, f32 = 0x7D, f64 = 0x7C }; enum mem_align { b8 = 0, b16 = 1, b32 = 2, b64 = 3 }; -void emit_leb128_u32(Vec &code, Allocator &al, - uint32_t n) { // for u32 - do { - uint8_t byte = n & 0x7f; - n >>= 7; - if (n != 0) { - byte |= 0x80; - } - code.push_back(al, byte); - } while (n != 0); -} - -void emit_leb128_i32(Vec &code, Allocator &al, int32_t n) { // for i32 - bool more = true; - do { - uint8_t byte = n & 0x7f; - n >>= 7; - more = !((((n == 0) && ((byte & 0x40) == 0)) || - ((n == -1) && ((byte & 0x40) != 0)))); - if (more) { - byte |= 0x80; - } - code.push_back(al, byte); - } while (more); -} - -void emit_leb128_i64(Vec &code, Allocator &al, int64_t n) { // for i64 - bool more = true; - do { - uint8_t byte = n & 0x7f; - n >>= 7; - more = !((((n == 0) && ((byte & 0x40) == 0)) || - ((n == -1) && ((byte & 0x40) != 0)))); - if (more) { - byte |= 0x80; - } - code.push_back(al, byte); - } while (more); -} - -void emit_ieee754_f32(Vec &code, Allocator &al, float z) { // for f32 - uint8_t encoded_float[sizeof(z)]; - std::memcpy(&encoded_float, &z, sizeof(z)); - for (auto &byte : encoded_float) { - code.push_back(al, byte); - } -} - -void emit_ieee754_f64(Vec &code, Allocator &al, double z) { // for f64 - uint8_t encoded_float[sizeof(z)]; - std::memcpy(&encoded_float, &z, sizeof(z)); - for (auto &byte : encoded_float) { - code.push_back(al, byte); - } +void emit_expr_end(Vec &code, Allocator &al) { + code.push_back(al, 0x0B); } // function to emit header of Wasm Binary Format @@ -79,36 +26,6 @@ void emit_header(Vec &code, Allocator &al) { code.push_back(al, 0x00); } -// function to append a given bytecode to the end of the code -void emit_b8(Vec &code, Allocator &al, uint8_t x) { - code.push_back(al, x); -} - -// function to emit unsigned 32 bit integer -void emit_u32(Vec &code, Allocator &al, uint32_t x) { - emit_leb128_u32(code, al, x); -} - -// function to emit signed 32 bit integer -void emit_i32(Vec &code, Allocator &al, int32_t x) { - emit_leb128_i32(code, al, x); -} - -// function to emit signed 64 bit integer -void emit_i64(Vec &code, Allocator &al, int64_t x) { - emit_leb128_i64(code, al, x); -} - -// function to emit 32 bit float -void emit_f32(Vec &code, Allocator &al, float x) { - emit_ieee754_f32(code, al, x); -} - -// function to emit 64 bit float -void emit_f64(Vec &code, Allocator &al, double x) { - emit_ieee754_f64(code, al, x); -} - // function to emit string void emit_str(Vec &code, Allocator &al, std::string text) { std::vector text_bytes(text.size()); @@ -117,6 +34,15 @@ void emit_str(Vec &code, Allocator &al, std::string text) { for (auto &byte : text_bytes) emit_b8(code, al, byte); } +void emit_str_const(Vec &code, Allocator &al, uint32_t mem_idx, + const std::string &text) { + emit_u32(code, al, 0U); // for active mode of memory with default mem_idx of 0 + emit_b8(code, al, 0x41); // i32.const + emit_i32(code, al, (int32_t)mem_idx); // specifying memory location + emit_expr_end(code, al); // end instructions + emit_str(code, al, text); +} + void emit_u32_b32_idx(Vec &code, Allocator &al, uint32_t idx, uint32_t section_size) { /* @@ -125,7 +51,7 @@ void emit_u32_b32_idx(Vec &code, Allocator &al, uint32_t idx, */ Vec num; num.reserve(al, 4); - emit_leb128_u32(num, al, section_size); + encode_leb128_u32(num, al, section_size); std::vector num_4b = {0x80, 0x80, 0x80, 0x00}; assert(num.size() <= 4); for (uint32_t i = 0; i < num.size(); i++) { @@ -221,593 +147,6 @@ void encode_section(Vec &des, Vec §ion_content, } } -// function to emit drop instruction (it throws away a single operand on stack) -void emit_drop(Vec &code, Allocator &al) { code.push_back(al, 0x1A); } - -// function to emit get local variable at given index -void emit_local_get(Vec &code, Allocator &al, uint32_t idx) { - code.push_back(al, 0x20); - emit_u32(code, al, idx); -} - -// function to emit set local variable at given index -void emit_local_set(Vec &code, Allocator &al, uint32_t idx) { - code.push_back(al, 0x21); - emit_u32(code, al, idx); -} - -// function to emit get global variable at given index -void emit_global_get(Vec &code, Allocator &al, uint32_t idx) { - code.push_back(al, 0x23); - emit_u32(code, al, idx); -} - -// function to emit set global variable at given index -void emit_global_set(Vec &code, Allocator &al, uint32_t idx) { - code.push_back(al, 0x24); - emit_u32(code, al, idx); -} - -// function to emit call instruction -void emit_call(Vec &code, Allocator &al, uint32_t idx) { - code.push_back(al, 0x10); - emit_u32(code, al, idx); -} - -// function to emit end of wasm expression -void emit_expr_end(Vec &code, Allocator &al) { - code.push_back(al, 0x0B); -} - -/**************************** Integer Operations ****************************/ - -// function to emit a i32.const instruction -void emit_i32_const(Vec &code, Allocator &al, int32_t x) { - code.push_back(al, 0x41); - emit_i32(code, al, x); -} - -// function to emit i32.clz instruction -void emit_i32_clz(Vec &code, Allocator &al) { - code.push_back(al, 0x67); -} - -// function to emit i32.ctz instruction -void emit_i32_ctz(Vec &code, Allocator &al) { - code.push_back(al, 0x68); -} - -// function to emit i32.popcnt instruction -void emit_i32_popcnt(Vec &code, Allocator &al) { - code.push_back(al, 0x69); -} - -// function to emit i32.add instruction -void emit_i32_add(Vec &code, Allocator &al) { - code.push_back(al, 0x6A); -} - -// function to emit i32.sub instruction -void emit_i32_sub(Vec &code, Allocator &al) { - code.push_back(al, 0x6B); -} - -// function to emit i32.mul instruction -void emit_i32_mul(Vec &code, Allocator &al) { - code.push_back(al, 0x6C); -} - -// function to emit i32.div_s instruction -void emit_i32_div_s(Vec &code, Allocator &al) { - code.push_back(al, 0x6D); -} - -// function to emit i32.div_u instruction -void emit_i32_div_u(Vec &code, Allocator &al) { - code.push_back(al, 0x6E); -} - -// function to emit i32.rem_s instruction -void emit_i32_rem_s(Vec &code, Allocator &al) { - code.push_back(al, 0x6F); -} - -// function to emit i32.rem_u instruction -void emit_i32_rem_u(Vec &code, Allocator &al) { - code.push_back(al, 0x70); -} - -// function to emit i32.and instruction -void emit_i32_and(Vec &code, Allocator &al) { - code.push_back(al, 0x71); -} - -// function to emit i32.or instruction -void emit_i32_or(Vec &code, Allocator &al) { - code.push_back(al, 0x72); -} - -// function to emit i32.xor instruction -void emit_i32_xor(Vec &code, Allocator &al) { - code.push_back(al, 0x73); -} - -// function to emit i32.shl instruction -void emit_i32_shl(Vec &code, Allocator &al) { - code.push_back(al, 0x74); -} - -// function to emit i32.shr_s instruction -void emit_i32_shr_s(Vec &code, Allocator &al) { - code.push_back(al, 0x75); -} - -// function to emit i32.shr_u instruction -void emit_i32_shr_u(Vec &code, Allocator &al) { - code.push_back(al, 0x76); -} - -// function to emit i32.rotl instruction -void emit_i32_rotl(Vec &code, Allocator &al) { - code.push_back(al, 0x77); -} - -// function to emit i32.rotr instruction -void emit_i32_rotr(Vec &code, Allocator &al) { - code.push_back(al, 0x78); -} - -// function to emit a i64.const instruction -void emit_i64_const(Vec &code, Allocator &al, int64_t x) { - code.push_back(al, 0x42); - emit_i64(code, al, x); -} - -// function to emit i64.clz instruction -void emit_i64_clz(Vec &code, Allocator &al) { - code.push_back(al, 0x79); -} - -// function to emit i64.ctz instruction -void emit_i64_ctz(Vec &code, Allocator &al) { - code.push_back(al, 0x7A); -} - -// function to emit i64.popcnt instruction -void emit_i64_popcnt(Vec &code, Allocator &al) { - code.push_back(al, 0x7B); -} - -// function to emit i64.add instruction -void emit_i64_add(Vec &code, Allocator &al) { - code.push_back(al, 0x7C); -} - -// function to emit i64.sub instruction -void emit_i64_sub(Vec &code, Allocator &al) { - code.push_back(al, 0x7D); -} - -// function to emit i64.mul instruction -void emit_i64_mul(Vec &code, Allocator &al) { - code.push_back(al, 0x7E); -} - -// function to emit i64.div_s instruction -void emit_i64_div_s(Vec &code, Allocator &al) { - code.push_back(al, 0x7F); -} - -// function to emit i64.div_u instruction -void emit_i64_div_u(Vec &code, Allocator &al) { - code.push_back(al, 0x80); -} - -// function to emit i64.rem_s instruction -void emit_i64_rem_s(Vec &code, Allocator &al) { - code.push_back(al, 0x81); -} - -// function to emit i64.rem_u instruction -void emit_i64_rem_u(Vec &code, Allocator &al) { - code.push_back(al, 0x82); -} - -// function to emit i64.and instruction -void emit_i64_and(Vec &code, Allocator &al) { - code.push_back(al, 0x83); -} - -// function to emit i64.or instruction -void emit_i64_or(Vec &code, Allocator &al) { - code.push_back(al, 0x84); -} - -// function to emit i64.xor instruction -void emit_i64_xor(Vec &code, Allocator &al) { - code.push_back(al, 0x85); -} - -// function to emit i64.shl instruction -void emit_i64_shl(Vec &code, Allocator &al) { - code.push_back(al, 0x86); -} - -// function to emit i64.shr_s instruction -void emit_i64_shr_s(Vec &code, Allocator &al) { - code.push_back(al, 0x87); -} - -// function to emit i64.shr_u instruction -void emit_i64_shr_u(Vec &code, Allocator &al) { - code.push_back(al, 0x88); -} - -// function to emit i64.rotl instruction -void emit_i64_rotl(Vec &code, Allocator &al) { - code.push_back(al, 0x89); -} - -// function to emit i64.rotr instruction -void emit_i64_rotr(Vec &code, Allocator &al) { - code.push_back(al, 0x8A); -} - -/******** Integer Relational Operations ********/ - -// function to emit i32.eqz instruction -void emit_i32_eqz(Vec &code, Allocator &al) { - code.push_back(al, 0x45); -} - -// function to emit i32.eq instruction -void emit_i32_eq(Vec &code, Allocator &al) { - code.push_back(al, 0x46); -} - -// function to emit i32.ne instruction -void emit_i32_ne(Vec &code, Allocator &al) { - code.push_back(al, 0x47); -} - -// function to emit i32.lt_s instruction -void emit_i32_lt_s(Vec &code, Allocator &al) { - code.push_back(al, 0x48); -} - -// function to emit i32.lt_u instruction -void emit_i32_lt_u(Vec &code, Allocator &al) { - code.push_back(al, 0x49); -} - -// function to emit i32.gt_s instruction -void emit_i32_gt_s(Vec &code, Allocator &al) { - code.push_back(al, 0x4A); -} - -// function to emit i32.gt_u instruction -void emit_i32_gt_u(Vec &code, Allocator &al) { - code.push_back(al, 0x4B); -} - -// function to emit i32.le_s instruction -void emit_i32_le_s(Vec &code, Allocator &al) { - code.push_back(al, 0x4C); -} - -// function to emit i32.le_u instruction -void emit_i32_le_u(Vec &code, Allocator &al) { - code.push_back(al, 0x4D); -} - -// function to emit i32.ge_s instruction -void emit_i32_ge_s(Vec &code, Allocator &al) { - code.push_back(al, 0x4E); -} - -// function to emit i32.ge_u instruction -void emit_i32_ge_u(Vec &code, Allocator &al) { - code.push_back(al, 0x4F); -} - -// function to emit i64.eqz instruction -void emit_i64_eqz(Vec &code, Allocator &al) { - code.push_back(al, 0x50); -} - -// function to emit i64.eq instruction -void emit_i64_eq(Vec &code, Allocator &al) { - code.push_back(al, 0x51); -} - -// function to emit i64.ne instruction -void emit_i64_ne(Vec &code, Allocator &al) { - code.push_back(al, 0x52); -} - -// function to emit i64.lt_s instruction -void emit_i64_lt_s(Vec &code, Allocator &al) { - code.push_back(al, 0x53); -} - -// function to emit i64.lt_u instruction -void emit_i64_lt_u(Vec &code, Allocator &al) { - code.push_back(al, 0x54); -} - -// function to emit i64.gt_s instruction -void emit_i64_gt_s(Vec &code, Allocator &al) { - code.push_back(al, 0x55); -} - -// function to emit i64.gt_u instruction -void emit_i64_gt_u(Vec &code, Allocator &al) { - code.push_back(al, 0x56); -} - -// function to emit i64.le_s instruction -void emit_i64_le_s(Vec &code, Allocator &al) { - code.push_back(al, 0x57); -} - -// function to emit i64.le_u instruction -void emit_i64_le_u(Vec &code, Allocator &al) { - code.push_back(al, 0x58); -} - -// function to emit i64.ge_s instruction -void emit_i64_ge_s(Vec &code, Allocator &al) { - code.push_back(al, 0x59); -} - -// function to emit i64.ge_u instruction -void emit_i64_ge_u(Vec &code, Allocator &al) { - code.push_back(al, 0x5A); -} - -/**************************** Floating Point Operations - * ****************************/ - -// function to emit a f32.const instruction -void emit_f32_const(Vec &code, Allocator &al, float x) { - code.push_back(al, 0x43); - emit_f32(code, al, x); -} - -// function to emit f32.abs instruction -void emit_f32_abs(Vec &code, Allocator &al) { - code.push_back(al, 0x8B); -} - -// function to emit f32.neg instruction -void emit_f32_neg(Vec &code, Allocator &al) { - code.push_back(al, 0x8C); -} - -// function to emit f32.ceil instruction -void emit_f32_ceil(Vec &code, Allocator &al) { - code.push_back(al, 0x8D); -} - -// function to emit f32.floor instruction -void emit_f32_floor(Vec &code, Allocator &al) { - code.push_back(al, 0x8E); -} - -// function to emit f32.trunc instruction -void emit_f32_trunc(Vec &code, Allocator &al) { - code.push_back(al, 0x8F); -} - -// function to emit f32.nearest instruction -void emit_f32_nearest(Vec &code, Allocator &al) { - code.push_back(al, 0x90); -} - -// function to emit f32.sqrt instruction -void emit_f32_sqrt(Vec &code, Allocator &al) { - code.push_back(al, 0x91); -} - -// function to emit f32.add instruction -void emit_f32_add(Vec &code, Allocator &al) { - code.push_back(al, 0x92); -} - -// function to emit f32.sub instruction -void emit_f32_sub(Vec &code, Allocator &al) { - code.push_back(al, 0x93); -} - -// function to emit f32.mul instruction -void emit_f32_mul(Vec &code, Allocator &al) { - code.push_back(al, 0x94); -} - -// function to emit f32.div instruction -void emit_f32_div(Vec &code, Allocator &al) { - code.push_back(al, 0x95); -} - -// function to emit f32.min instruction -void emit_f32_min(Vec &code, Allocator &al) { - code.push_back(al, 0x96); -} - -// function to emit f32.max instruction -void emit_f32_max(Vec &code, Allocator &al) { - code.push_back(al, 0x97); -} - -// function to emit f32.copysign instruction -void emit_f32_copysign(Vec &code, Allocator &al) { - code.push_back(al, 0x98); -} - -// function to emit a f64.const instruction -void emit_f64_const(Vec &code, Allocator &al, double x) { - code.push_back(al, 0x44); - emit_f64(code, al, x); -} - -// function to emit f64.abs instruction -void emit_f64_abs(Vec &code, Allocator &al) { - code.push_back(al, 0x99); -} - -// function to emit f64.neg instruction -void emit_f64_neg(Vec &code, Allocator &al) { - code.push_back(al, 0x9A); -} - -// function to emit f64.ceil instruction -void emit_f64_ceil(Vec &code, Allocator &al) { - code.push_back(al, 0x9B); -} - -// function to emit f64.floor instruction -void emit_f64_floor(Vec &code, Allocator &al) { - code.push_back(al, 0x9C); -} - -// function to emit f64.trunc instruction -void emit_f64_trunc(Vec &code, Allocator &al) { - code.push_back(al, 0x9D); -} - -// function to emit f64.nearest instruction -void emit_f64_nearest(Vec &code, Allocator &al) { - code.push_back(al, 0x9E); -} - -// function to emit f64.sqrt instruction -void emit_f64_sqrt(Vec &code, Allocator &al) { - code.push_back(al, 0x9F); -} - -// function to emit f64.add instruction -void emit_f64_add(Vec &code, Allocator &al) { - code.push_back(al, 0xA0); -} - -// function to emit f64.sub instruction -void emit_f64_sub(Vec &code, Allocator &al) { - code.push_back(al, 0xA1); -} - -// function to emit f64.mul instruction -void emit_f64_mul(Vec &code, Allocator &al) { - code.push_back(al, 0xA2); -} - -// function to emit f64.div instruction -void emit_f64_div(Vec &code, Allocator &al) { - code.push_back(al, 0xA3); -} - -// function to emit f64.min instruction -void emit_f64_min(Vec &code, Allocator &al) { - code.push_back(al, 0xA4); -} - -// function to emit f64.max instruction -void emit_f64_max(Vec &code, Allocator &al) { - code.push_back(al, 0xA5); -} - -// function to emit f64.copysign instruction -void emit_f64_copysign(Vec &code, Allocator &al) { - code.push_back(al, 0xA6); -} - -/******** Float Relational Operations ********/ - -// function to emit f32.eq instruction -void emit_f32_eq(Vec &code, Allocator &al) { - code.push_back(al, 0x5B); -} - -// function to emit f32.ne instruction -void emit_f32_ne(Vec &code, Allocator &al) { - code.push_back(al, 0x5C); -} - -// function to emit f32.lt instruction -void emit_f32_lt(Vec &code, Allocator &al) { - code.push_back(al, 0x5D); -} - -// function to emit f32.gt instruction -void emit_f32_gt(Vec &code, Allocator &al) { - code.push_back(al, 0x5E); -} - -// function to emit f32.le instruction -void emit_f32_le(Vec &code, Allocator &al) { - code.push_back(al, 0x5F); -} - -// function to emit f32.ge instruction -void emit_f32_ge(Vec &code, Allocator &al) { - code.push_back(al, 0x60); -} - -// function to emit f64.eq instruction -void emit_f64_eq(Vec &code, Allocator &al) { - code.push_back(al, 0x61); -} - -// function to emit f64.ne instruction -void emit_f64_ne(Vec &code, Allocator &al) { - code.push_back(al, 0x62); -} - -// function to emit f64.lt instruction -void emit_f64_lt(Vec &code, Allocator &al) { - code.push_back(al, 0x63); -} - -// function to emit f64.gt instruction -void emit_f64_gt(Vec &code, Allocator &al) { - code.push_back(al, 0x64); -} - -// function to emit f64.le instruction -void emit_f64_le(Vec &code, Allocator &al) { - code.push_back(al, 0x65); -} - -// function to emit f64.ge instruction -void emit_f64_ge(Vec &code, Allocator &al) { - code.push_back(al, 0x66); -} - -// function to emit string -void emit_str_const(Vec &code, Allocator &al, uint32_t mem_idx, - const std::string &text) { - emit_u32(code, al, - 0U); // for active mode of memory with default mem_idx of 0 - emit_i32_const( - code, al, - (int32_t)mem_idx); // specifying memory location as instructions - emit_expr_end(code, al); // end instructions - emit_str(code, al, text); -} - -void emit_unreachable(Vec &code, Allocator &al) { - code.push_back(al, 0x00); -} - -void emit_branch(Vec &code, Allocator &al, uint32_t label_idx) { - code.push_back(al, 0x0C); - emit_u32(code, al, label_idx); -} - -void emit_branch_if(Vec &code, Allocator &al, uint32_t label_idx) { - code.push_back(al, 0x0D); - emit_u32(code, al, label_idx); -} - void save_js_glue(std::string filename) { std::string js_glue = R"(function define_imports(memory, outputBuffer, exit_code, stdout_print) { @@ -904,345 +243,6 @@ void save_bin(Vec &code, std::string filename) { save_js_glue_wasi(filename); } -/**************************** Type Conversion Operations - * ****************************/ - -// function to emit i32.wrap_i64 instruction -void emit_i32_wrap_i64(Vec &code, Allocator &al) { - code.push_back(al, 0xA7); -} - -// function to emit i32.trunc_f32_s instruction -void emit_i32_trunc_f32_s(Vec &code, Allocator &al) { - code.push_back(al, 0xA8); -} - -// function to emit i32.trunc_f32_u instruction -void emit_i32_trunc_f32_u(Vec &code, Allocator &al) { - code.push_back(al, 0xA9); -} - -// function to emit i32.trunc_f64_s instruction -void emit_i32_trunc_f64_s(Vec &code, Allocator &al) { - code.push_back(al, 0xAA); -} - -// function to emit i32.trunc_f64_u instruction -void emit_i32_trunc_f64_u(Vec &code, Allocator &al) { - code.push_back(al, 0xAB); -} - -// function to emit i64.extend_i32_s instruction -void emit_i64_extend_i32_s(Vec &code, Allocator &al) { - code.push_back(al, 0xAC); -} - -// function to emit i64.extend_i32_u instruction -void emit_i64_extend_i32_u(Vec &code, Allocator &al) { - code.push_back(al, 0xAD); -} - -// function to emit i64.trunc_f32_s instruction -void emit_i64_trunc_f32_s(Vec &code, Allocator &al) { - code.push_back(al, 0xAE); -} - -// function to emit i64.trunc_f32_u instruction -void emit_i64_trunc_f32_u(Vec &code, Allocator &al) { - code.push_back(al, 0xAF); -} - -// function to emit i64.trunc_f64_s instruction -void emit_i64_trunc_f64_s(Vec &code, Allocator &al) { - code.push_back(al, 0xB0); -} - -// function to emit i64.trunc_f64_u instruction -void emit_i64_trunc_f64_u(Vec &code, Allocator &al) { - code.push_back(al, 0xB1); -} - -// function to emit f32.convert_i32_s instruction -void emit_f32_convert_i32_s(Vec &code, Allocator &al) { - code.push_back(al, 0xB2); -} - -// function to emit f32.convert_i32_u instruction -void emit_f32_convert_i32_u(Vec &code, Allocator &al) { - code.push_back(al, 0xB3); -} - -// function to emit f32.convert_i64_s instruction -void emit_f32_convert_i64_s(Vec &code, Allocator &al) { - code.push_back(al, 0xB4); -} - -// function to emit f32.convert_i64_u instruction -void emit_f32_convert_i64_u(Vec &code, Allocator &al) { - code.push_back(al, 0xB5); -} - -// function to emit f32.demote_f64 instruction -void emit_f32_demote_f64(Vec &code, Allocator &al) { - code.push_back(al, 0xB6); -} - -// function to emit f64.convert_i32_s instruction -void emit_f64_convert_i32_s(Vec &code, Allocator &al) { - code.push_back(al, 0xB7); -} - -// function to emit f64.convert_i32_u instruction -void emit_f64_convert_i32_u(Vec &code, Allocator &al) { - code.push_back(al, 0xB8); -} - -// function to emit f64.convert_i64_s instruction -void emit_f64_convert_i64_s(Vec &code, Allocator &al) { - code.push_back(al, 0xB9); -} - -// function to emit f64.convert_i64_u instruction -void emit_f64_convert_i64_u(Vec &code, Allocator &al) { - code.push_back(al, 0xBA); -} - -// function to emit f64.promote_f32 instruction -void emit_f64_promote_f32(Vec &code, Allocator &al) { - code.push_back(al, 0xBB); -} - -// function to emit i32.reinterpret_f32 instruction -void emit_i32_reinterpret_f32(Vec &code, Allocator &al) { - code.push_back(al, 0xBC); -} - -// function to emit i64.reinterpret_f64 instruction -void emit_i64_reinterpret_f64(Vec &code, Allocator &al) { - code.push_back(al, 0xBD); -} - -// function to emit f32.reinterpret_i32 instruction -void emit_f32_reinterpret_i32(Vec &code, Allocator &al) { - code.push_back(al, 0xBE); -} - -// function to emit f64.reinterpret_i64 instruction -void emit_f64_reinterpret_i64(Vec &code, Allocator &al) { - code.push_back(al, 0xBF); -} - -// function to emit i32.extend8_s instruction -void emit_i32_extend8_s(Vec &code, Allocator &al) { - code.push_back(al, 0xC0); -} - -// function to emit i32.extend16_s instruction -void emit_i32_extend16_s(Vec &code, Allocator &al) { - code.push_back(al, 0xC1); -} - -// function to emit i64.extend8_s instruction -void emit_i64_extend8_s(Vec &code, Allocator &al) { - code.push_back(al, 0xC2); -} - -// function to emit i64.extend16_s instruction -void emit_i64_extend16_s(Vec &code, Allocator &al) { - code.push_back(al, 0xC3); -} - -// function to emit i64.extend32_s instruction -void emit_i64_extend32_s(Vec &code, Allocator &al) { - code.push_back(al, 0xC4); -} - -/**************************** Memory Instructions ****************************/ - -// function to emit i32.load instruction -void emit_i32_load(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x28); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.load instruction -void emit_i64_load(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x29); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit f32.load instruction -void emit_f32_load(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x2A); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit f64.load instruction -void emit_f64_load(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x2B); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i32.load8_s instruction -void emit_i32_load8_s(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x2C); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i32.load8_u instruction -void emit_i32_load8_u(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x2D); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i32.load16_s instruction -void emit_i32_load16_s(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x2E); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i32.load16_u instruction -void emit_i32_load16_u(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x2F); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.load8_s instruction -void emit_i64_load8_s(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x30); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.load8_u instruction -void emit_i64_load8_u(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x31); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.load16_s instruction -void emit_i64_load16_s(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x32); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.load16_u instruction -void emit_i64_load16_u(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x33); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.load32_s instruction -void emit_i64_load32_s(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x34); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.load32_u instruction -void emit_i64_load32_u(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x35); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i32.store instruction -void emit_i32_store(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x36); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.store instruction -void emit_i64_store(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x37); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit f32.store instruction -void emit_f32_store(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x38); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit f64.store instruction -void emit_f64_store(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x39); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i32.store8 instruction -void emit_i32_store8(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x3A); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i32.store16 instruction -void emit_i32_store16(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x3B); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.store8 instruction -void emit_i64_store8(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x3C); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.store16 instruction -void emit_i64_store16(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x3D); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - -// function to emit i64.store32 instruction -void emit_i64_store32(Vec &code, Allocator &al, uint32_t mem_align, - uint32_t mem_offset) { - emit_b8(code, al, 0x3E); - emit_u32(code, al, mem_align); - emit_u32(code, al, mem_offset); -} - } // namespace wasm } // namespace LCompilers diff --git a/src/libasr/codegen/wasm_utils.cpp b/src/libasr/codegen/wasm_utils.cpp index c4ddb8739b..255cd1ffec 100644 --- a/src/libasr/codegen/wasm_utils.cpp +++ b/src/libasr/codegen/wasm_utils.cpp @@ -4,6 +4,17 @@ namespace LCompilers { namespace wasm { +void encode_leb128_u32(Vec &code, Allocator &al, uint32_t n) { + do { + uint8_t byte = n & 0x7f; + n >>= 7; + if (n != 0) { + byte |= 0x80; + } + code.push_back(al, byte); + } while (n != 0); +} + uint32_t decode_leb128_u32(Vec &code, uint32_t &offset) { uint32_t result = 0U; uint32_t shift = 0U; @@ -18,6 +29,20 @@ uint32_t decode_leb128_u32(Vec &code, uint32_t &offset) { } } +void encode_leb128_i32(Vec &code, Allocator &al, int32_t n) { + bool more = true; + do { + uint8_t byte = n & 0x7f; + n >>= 7; + more = !((((n == 0) && ((byte & 0x40) == 0)) || + ((n == -1) && ((byte & 0x40) != 0)))); + if (more) { + byte |= 0x80; + } + code.push_back(al, byte); + } while (more); +} + int32_t decode_leb128_i32(Vec &code, uint32_t &offset) { int32_t result = 0; uint32_t shift = 0U; @@ -38,6 +63,20 @@ int32_t decode_leb128_i32(Vec &code, uint32_t &offset) { return result; } +void encode_leb128_i64(Vec &code, Allocator &al, int64_t n) { + bool more = true; + do { + uint8_t byte = n & 0x7f; + n >>= 7; + more = !((((n == 0) && ((byte & 0x40) == 0)) || + ((n == -1) && ((byte & 0x40) != 0)))); + if (more) { + byte |= 0x80; + } + code.push_back(al, byte); + } while (more); +} + int64_t decode_leb128_i64(Vec &code, uint32_t &offset) { int64_t result = 0; uint32_t shift = 0U; @@ -58,6 +97,14 @@ int64_t decode_leb128_i64(Vec &code, uint32_t &offset) { return result; } +void encode_ieee754_f32(Vec &code, Allocator &al, float z) { + uint8_t encoded_float[sizeof(z)]; + std::memcpy(&encoded_float, &z, sizeof(z)); + for (auto &byte : encoded_float) { + code.push_back(al, byte); + } +} + float decode_ieee754_f32(Vec &code, uint32_t &offset) { float value = 0.0; std::memcpy(&value, &code.p[offset], sizeof(value)); @@ -65,6 +112,14 @@ float decode_ieee754_f32(Vec &code, uint32_t &offset) { return value; } +void encode_ieee754_f64(Vec &code, Allocator &al, double z) { + uint8_t encoded_float[sizeof(z)]; + std::memcpy(&encoded_float, &z, sizeof(z)); + for (auto &byte : encoded_float) { + code.push_back(al, byte); + } +} + double decode_ieee754_f64(Vec &code, uint32_t &offset) { double value = 0.0; std::memcpy(&value, &code.p[offset], sizeof(value)); @@ -72,6 +127,36 @@ double decode_ieee754_f64(Vec &code, uint32_t &offset) { return value; } +// function to append a given bytecode to the end of the code +void emit_b8(Vec &code, Allocator &al, uint8_t x) { + code.push_back(al, x); +} + +// function to emit unsigned 32 bit integer +void emit_u32(Vec &code, Allocator &al, uint32_t x) { + encode_leb128_u32(code, al, x); +} + +// function to emit signed 32 bit integer +void emit_i32(Vec &code, Allocator &al, int32_t x) { + encode_leb128_i32(code, al, x); +} + +// function to emit signed 64 bit integer +void emit_i64(Vec &code, Allocator &al, int64_t x) { + encode_leb128_i64(code, al, x); +} + +// function to emit 32 bit float +void emit_f32(Vec &code, Allocator &al, float x) { + encode_ieee754_f32(code, al, x); +} + +// function to emit 64 bit float +void emit_f64(Vec &code, Allocator &al, double x) { + encode_ieee754_f64(code, al, x); +} + uint8_t read_b8(Vec &code, uint32_t &offset) { LCOMPILERS_ASSERT(offset < code.size()); return code.p[offset++]; diff --git a/src/libasr/codegen/wasm_utils.h b/src/libasr/codegen/wasm_utils.h index e1cbcd57d0..d82f8fd42f 100644 --- a/src/libasr/codegen/wasm_utils.h +++ b/src/libasr/codegen/wasm_utils.h @@ -60,20 +60,33 @@ struct Data { std::string text; }; +void encode_leb128_u32(Vec &code, Allocator &al, uint32_t n); uint32_t decode_leb128_u32(Vec &code, uint32_t &offset); + +void encode_leb128_i32(Vec &code, Allocator &al, int32_t n); int32_t decode_leb128_i32(Vec &code, uint32_t &offset); + +void encode_leb128_i64(Vec &code, Allocator &al, int64_t n); int64_t decode_leb128_i64(Vec &code, uint32_t &offset); -uint8_t read_b8(Vec &code, uint32_t &offset); +void encode_ieee754_f32(Vec &code, Allocator &al, float z); +float decode_ieee754_f32(Vec &code, uint32_t &offset); -float read_f32(Vec &code, uint32_t &offset); +void encode_ieee754_f64(Vec &code, Allocator &al, double z); +double decode_ieee754_f64(Vec &code, uint32_t &offset); -double read_f64(Vec &code, uint32_t &offset); +void emit_b8(Vec &code, Allocator &al, uint8_t x); +void emit_u32(Vec &code, Allocator &al, uint32_t x); +void emit_i32(Vec &code, Allocator &al, int32_t x); +void emit_i64(Vec &code, Allocator &al, int64_t x); +void emit_f32(Vec &code, Allocator &al, float x); +void emit_f64(Vec &code, Allocator &al, double x); +uint8_t read_b8(Vec &code, uint32_t &offset); +float read_f32(Vec &code, uint32_t &offset); +double read_f64(Vec &code, uint32_t &offset); uint32_t read_u32(Vec &code, uint32_t &offset); - int32_t read_i32(Vec &code, uint32_t &offset); - int64_t read_i64(Vec &code, uint32_t &offset); void hexdump(void *ptr, int buflen); diff --git a/src/libasr/wasm_instructions_visitor.py b/src/libasr/wasm_instructions_visitor.py index 8d94d42f32..22df52eea4 100644 --- a/src/libasr/wasm_instructions_visitor.py +++ b/src/libasr/wasm_instructions_visitor.py @@ -35,7 +35,7 @@ def __init__(self, stream, data): self.stream = stream self.data = data - def visitWASMInstructions(self, mod, *args): + def visit_BaseWASMVisitor(self, mod, *args): self.emit("template ", 0) self.emit("class BaseWASMVisitor {", 0) self.emit("private:", 0) @@ -47,7 +47,7 @@ def visitWASMInstructions(self, mod, *args): self.emit( "BaseWASMVisitor(Vec &code, uint32_t offset): code(code), offset(offset) {}", 1) for inst in mod["instructions"]: - self.emit("void visit_%s(%s) {throw LCompilersException(\"visit_%s() not implemented\");}\n" % (inst["func"], make_param_list(inst["params"]), inst["func"]), 1) + self.emit("void visit_%s(%s) {throw LCompilersException(\"visit_%s() not implemented\");}\n" % (inst["func_read"], make_param_list(inst["params"], comment_out=True), inst["func_read"]), 1) self.emit( "void decode_instructions() {", 1) self.emit( "uint8_t cur_byte = wasm::read_b8(code, offset);", 2) @@ -57,7 +57,7 @@ def visitWASMInstructions(self, mod, *args): self.emit( "case %s: {" % (inst["opcode"]), 4) for param in inst["params"]: self.emit( "%s %s = %s(code, offset);" % (param["type"], param["name"], param["read_func"]), 5) - self.emit( "self().visit_%s(%s);" % (inst["func"], make_param_list(inst["params"], call=True)), 5) + self.emit( "self().visit_%s(%s);" % (inst["func_read"], make_param_list(inst["params"], call=True)), 5) self.emit( "break;", 5) self.emit( "}", 4) @@ -68,7 +68,7 @@ def visitWASMInstructions(self, mod, *args): self.emit( "case %sU: {" % (inst["params"][0]["val"]), 6) for param in inst["params"][1:]: # first param is already read right at the start of case 0xFC self.emit( "%s %s = %s(code, offset);" % (param["type"], param["name"], param["read_func"]), 7) - self.emit( "self().visit_%s(%s);" % (inst["func"], make_param_list(inst["params"], call=True)), 7) + self.emit( "self().visit_%s(%s);" % (inst["func_read"], make_param_list(inst["params"], call=True)), 7) self.emit( "break;", 7) self.emit( "}", 6) self.emit( "default: {", 6) @@ -85,7 +85,7 @@ def visitWASMInstructions(self, mod, *args): self.emit( "case %sU: {" % (inst["params"][0]["val"]), 6) for param in inst["params"][1:]: # first param is already read right at the start of case 0xFD self.emit( "%s %s = %s(code, offset);" % (param["type"], param["name"], param["read_func"]), 7) - self.emit( "self().visit_%s(%s);" % (inst["func"], make_param_list(inst["params"], call=True)), 7) + self.emit( "self().visit_%s(%s);" % (inst["func_read"], make_param_list(inst["params"], call=True)), 7) self.emit( "break;", 7) self.emit( "}", 6) self.emit( "default: {", 6) @@ -102,18 +102,56 @@ def visitWASMInstructions(self, mod, *args): self.emit( "cur_byte = wasm::read_b8(code, offset);", 3) self.emit( "}", 2) self.emit( "}", 1) - self.emit("};", 0) + self.emit("};\n", 0) + def visit_WASMInstsAssembler(self, mod): + self.emit("class WASMInstsAssembler {", 0) + self.emit("private:", 0) + self.emit( "Allocator &m_al;", 1) + self.emit( "Vec &m_code;\n", 1) + self.emit("public:", 0) + self.emit( "WASMInstsAssembler(Allocator &al, Vec &code): m_al(al), m_code(code) {}\n", 1) + + for inst in filter(lambda i: i["opcode"] not in ["0xFC", "0xFD"], mod["instructions"]): + self.emit("void emit_%s(%s) {" % (inst["func_emit"], make_param_list(inst["params"])), 1) + self.emit( "m_code.push_back(m_al, %s);" % (inst["opcode"]), 2) + for param in inst["params"]: + self.emit("%s(m_code, m_al, %s);" % (param["emit_func"], param["name"]), 2) + self.emit("}\n", 1) + + for inst in filter(lambda i: i["opcode"] == "0xFC", mod["instructions"]): + self.emit("void emit_%s(%s) {" % (inst["func_emit"], make_param_list(inst["params"])), 1) + self.emit( "m_code.push_back(m_al, %s);" % (inst["opcode"]), 2) + self.emit( "wasm::emit_u32(m_code, m_al, %s);" % (inst["params"][0]["val"]), 2) + for param in inst["params"][1:]: + self.emit("%s(m_code, m_al, %s);" % (param["emit_func"], param["name"]), 2) + self.emit("}\n", 1) + + for inst in filter(lambda i: i["opcode"] == "0xFD", mod["instructions"]): + self.emit("void emit_%s(%s) {" % (inst["func_emit"], make_param_list(inst["params"])), 1) + self.emit( "m_code.push_back(m_al, %s);" % (inst["opcode"]), 2) + self.emit( "wasm::emit_u32(m_code, m_al, %s);" % (inst["params"][0]["val"]), 2) + for param in inst["params"][1:]: + self.emit("%s(m_code, m_al, %s);" % (param["emit_func"], param["name"]), 2) + self.emit("}\n", 1) + + self.emit("};\n", 0) def emit(self, line, level=0): indent = " "*level self.stream.write(indent + line + "\n") -def make_param_list(params, call = False): - params = list(filter(lambda param: param["val"] != "0x00" and param["name"] != "num", params)) +def filter_params(params): + return list(filter(lambda param: param["val"] != "0x00" and param["name"] != "num", params)) + +def make_param_list(params, comment_out = False, call = False): + params = filter_params(params) if call: - return ", ".join(map(lambda param: param["name"], params)) - return ", ".join(map(lambda param: param["type"] + " /*" + param["name"] + "*/", params)) + return ", ".join(map(lambda p: p["name"], params)) + if comment_out: + return ", ".join(map(lambda p: p["type"] + " /*" + p["name"] + "*/", params)) + return ", ".join(map(lambda p: p["type"] + " " + p["name"], params)) + def read_file(path): with open(path, encoding="utf-8") as fp: @@ -130,8 +168,10 @@ def process_raw_instructions(instructions_raw): instructions.append(line.strip()) return instructions -def get_func_name(func): +def get_func_name(func, emit = False): splitted_name = re.split("[\._]", func) + if emit: + return "_".join(splitted_name) return "".join(map(lambda name_sub_part: name_sub_part.capitalize(), splitted_name)) param_read_function = { @@ -143,6 +183,15 @@ def get_func_name(func): "double": "wasm::read_f64" } +param_emit_function = { + "uint8_t": "wasm::emit_b8", + "uint32_t": "wasm::emit_u32", + "int32_t": "wasm::emit_i32", + "int64_t": "wasm::emit_i64", + "float": "wasm::emit_f32", + "double": "wasm::emit_f64" +} + param_type = { "u8": "uint8_t", "u32": "uint32_t", @@ -156,7 +205,9 @@ def parse_param_info(param_info): type_info, name, val = param_info.split(":") type = param_type[type_info] read_func = param_read_function[type] - return {"type": type, "read_func": read_func, "name": name, "val": val} + emit_func = param_emit_function[type] + return {"type": type, "read_func": read_func, "emit_func": emit_func, + "name": name, "val": val} def parse_instructions(instructions): instructions_info = [] @@ -166,10 +217,12 @@ def parse_instructions(instructions): opcode = binary_info[0] params_info = binary_info[1:] text_info = text_info.strip().split(" ") - func = get_func_name(text_info[0]) # first parameter is the function name + func_read = get_func_name(text_info[0]) # first parameter is the function name + func_emit = get_func_name(text_info[0], emit=True) # first parameter is the function name text_params = text_info[1:] # text_params are currently not needed and hence not used further params = list(map(lambda param_info: parse_param_info(param_info), params_info)) - instructions_info.append({"opcode": opcode, "func": func, "params": params}) + instructions_info.append({"opcode": opcode, "func_read": func_read, + "func_emit": func_emit, "params": params}) return instructions_info def main(argv): @@ -191,7 +244,8 @@ def main(argv): try: fp.write(HEAD % subs) wasm_instructions_visitor = WASMInstructionsVisitor(fp, None) - wasm_instructions_visitor.visitWASMInstructions({"instructions": instructions_info}) + wasm_instructions_visitor.visit_BaseWASMVisitor({"instructions": instructions_info}) + wasm_instructions_visitor.visit_WASMInstsAssembler({"instructions": instructions_info}) fp.write(FOOT % subs) finally: fp.close()