summaryrefslogtreecommitdiff
path: root/weerun_runtime.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'weerun_runtime.cpp')
-rw-r--r--weerun_runtime.cpp300
1 files changed, 300 insertions, 0 deletions
diff --git a/weerun_runtime.cpp b/weerun_runtime.cpp
new file mode 100644
index 0000000..e499670
--- /dev/null
+++ b/weerun_runtime.cpp
@@ -0,0 +1,300 @@
+#include <cmath>
+#include <cstdio>
+#include <ctime>
+#include <iostream>
+#include <map>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "weerun.hpp"
+
+void trap();
+
+std::unordered_map<std::string, wasm_rt_func_t> g_runtime_funcs;
+
+static void weewasm_puti(wasm_instance_t* ins) {
+ wasm_value_t v = ins->pop_value();
+ std::printf("%d", (int32_t)v.val.i32);
+}
+
+static void weewasm_putd(wasm_instance_t* ins) {
+ wasm_value_t v = ins->pop_value();
+ std::printf("%f", v.val.f64);
+}
+
+static void weewasm_puts(wasm_instance_t* ins) {
+ wasm_value_t size = ins->pop_value();
+ wasm_value_t start = ins->pop_value();
+ const byte* base = ins->memory_.data() + start.val.i32;
+ std::cout << std::string(base, base + size.val.i32);
+}
+
+static void weewasm_puti_jit(int32_t v) {
+ std::printf("%d", v);
+}
+
+static void weewasm_putd_jit(double v) {
+ std::printf("%f", v);
+}
+
+static void weewasm_puts_jit(uint32_t start, uint32_t size) {
+ const byte* base = active_instance->memory_.data() + start;
+ std::cout << std::string(base, base + size);
+}
+
+static inline wasm_key_t convert_key(wasm_externref_t* ref) {
+ union {
+ uint64_t i64;
+ double f64;
+ void* ptr;
+ } u;
+ if (ref == nullptr) {
+ return {WASM_EXTERN_NULL, 0};
+ }
+ switch (ref->type_) {
+ case WASM_EXTERN_BOXI32:
+ u.i64 = ((wasm_e_box_t*)ref)->i32_;
+ break;
+ case WASM_EXTERN_BOXF64:
+ u.f64 = ((wasm_e_box_t*)ref)->f64_;
+ break;
+ default:
+ u.ptr = (void*)ref;
+ break;
+ }
+ return {ref->type_, u.i64};
+}
+
+static void weewasm_obj_new(wasm_instance_t* ins) {
+ wasm_value_t v;
+ v.val.ref = (void*)(new wasm_e_object_t());
+ ins->push_value(v);
+}
+
+static void weewasm_obj_box_i32(wasm_instance_t* ins) {
+ wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXI32);
+ wasm_value_t x = ins->pop_value();
+ obj->i32_ = (int32_t)x.val.i32;
+ wasm_value_t v;
+ v.val.ref = (void*)(obj);
+ ins->push_value(v);
+}
+
+static void weewasm_obj_box_f64(wasm_instance_t* ins) {
+ wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXF64);
+ wasm_value_t x = ins->pop_value();
+ obj->f64_ = x.val.f64;
+ wasm_value_t v;
+ v.val.ref = (void*)(obj);
+ ins->push_value(v);
+}
+
+static void weewasm_obj_get(wasm_instance_t* ins) {
+ wasm_value_t key = ins->pop_value();
+ wasm_value_t o = ins->pop_value();
+ if (key.val.ref == nullptr || o.val.ref == nullptr) {
+ ins->trap(WASM_TRAP_REASON_NULLEXTERNREF);
+ return;
+ }
+ wasm_e_object_t* obj = (wasm_e_object_t*)o.val.ref;
+ if (obj->type_ != WASM_EXTERN_OBJECT) {
+ ins->trap(WASM_TRAP_REASON_BADOBJECT);
+ return;
+ }
+ wasm_value_t v;
+ auto result = obj->map_.find(convert_key((wasm_externref_t*)key.val.ref));
+ if (result == obj->map_.end()) {
+ v.val.ref = nullptr;
+ } else {
+ v.val.ref = (void*)result->second;
+ }
+ ins->push_value(v);
+ return;
+}
+
+static void weewasm_obj_set(wasm_instance_t* ins) {
+ wasm_value_t value = ins->pop_value();
+ wasm_value_t key = ins->pop_value();
+ wasm_value_t o = ins->pop_value();
+ if (key.val.ref == nullptr || o.val.ref == nullptr) {
+ ins->trap(WASM_TRAP_REASON_NULLEXTERNREF);
+ return;
+ }
+ wasm_e_object_t* obj = (wasm_e_object_t*)o.val.ref;
+ if (obj->type_ != WASM_EXTERN_OBJECT) {
+ ins->trap(WASM_TRAP_REASON_BADOBJECT);
+ return;
+ }
+ obj->map_[convert_key((wasm_externref_t*)key.val.ref)] =
+ (wasm_externref_t*)value.val.ref;
+ return;
+}
+
+static void weewasm_i32_unbox(wasm_instance_t* ins) {
+ wasm_value_t value = ins->pop_value();
+ wasm_e_box_t* box = (wasm_e_box_t*)value.val.ref;
+ if (box == nullptr || box->type_ != WASM_EXTERN_BOXI32) {
+ ins->trap(WASM_TRAP_REASON_BADOBJECT);
+ return;
+ }
+ wasm_value_t v;
+ v.val.i32 = (uint32_t)box->i32_;
+ ins->push_value(v);
+ return;
+}
+
+static void weewasm_f64_unbox(wasm_instance_t* ins) {
+ wasm_value_t value = ins->pop_value();
+ wasm_e_box_t* box = (wasm_e_box_t*)value.val.ref;
+ if (box == nullptr || box->type_ != WASM_EXTERN_BOXF64) {
+ ins->trap(WASM_TRAP_REASON_BADOBJECT);
+ return;
+ }
+ wasm_value_t v;
+ v.val.f64 = box->f64_;
+ ins->push_value(v);
+ return;
+}
+
+static void weewasm_obj_eq(wasm_instance_t* ins) {
+ wasm_value_t rhs = ins->pop_value();
+ wasm_value_t lhs = ins->pop_value();
+ wasm_value_t v;
+ v.val.i32 = (convert_key((wasm_externref_t*)lhs.val.ref) ==
+ convert_key((wasm_externref_t*)rhs.val.ref))
+ ? 1
+ : 0;
+ ins->push_value(v);
+}
+
+static wasm_e_object_t* weewasm_obj_new_jit() {
+ return new wasm_e_object_t();
+}
+
+static wasm_e_box_t* weewasm_obj_box_i32_jit(int32_t v) {
+ wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXI32);
+ obj->i32_ = v;
+ return obj;
+}
+
+static wasm_e_box_t* weewasm_obj_box_f64_jit(double v) {
+ wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXF64);
+ obj->f64_ = v;
+ return obj;
+}
+
+static wasm_externref_t* weewasm_obj_get_jit(wasm_e_object_t* obj,
+ wasm_externref_t* key) {
+ if (key == nullptr || obj == nullptr) {
+ trap();
+ }
+ if (obj->type_ != WASM_EXTERN_OBJECT) {
+ trap();
+ }
+ auto result = obj->map_.find(convert_key(key));
+ if (result == obj->map_.end()) {
+ return nullptr;
+ }
+ return result->second;
+}
+
+static void weewasm_obj_set_jit(wasm_e_object_t* obj,
+ wasm_externref_t* key,
+ wasm_externref_t* value) {
+ if (key == nullptr || obj == nullptr) {
+ trap();
+ }
+ if (obj->type_ != WASM_EXTERN_OBJECT) {
+ trap();
+ }
+ obj->map_[convert_key(key)] = value;
+}
+
+static int32_t weewasm_i32_unbox_jit(wasm_e_box_t* box) {
+ if (box == nullptr || box->type_ != WASM_EXTERN_BOXI32) {
+ trap();
+ }
+ return box->i32_;
+}
+
+static double weewasm_f64_unbox_jit(wasm_e_box_t* box) {
+ if (box == nullptr || box->type_ != WASM_EXTERN_BOXF64) {
+ trap();
+ }
+ return box->f64_;
+}
+
+static uint32_t weewasm_obj_eq_jit(wasm_externref_t* lhs,
+ wasm_externref_t* rhs) {
+ return (convert_key(lhs) == convert_key(rhs)) ? 1 : 0;
+}
+
+extern "C" void init_runtime() {
+ g_runtime_funcs["weewasm.puti"] = {weewasm_puti, (void*)weewasm_puti_jit};
+ g_runtime_funcs["weewasm.putd"] = {weewasm_putd, (void*)weewasm_putd_jit};
+ g_runtime_funcs["weewasm.puts"] = {weewasm_puts, (void*)weewasm_puts_jit};
+ g_runtime_funcs["weewasm.obj.new"] = {weewasm_obj_new,
+ (void*)weewasm_obj_new_jit};
+ g_runtime_funcs["weewasm.obj.box_i32"] = {weewasm_obj_box_i32,
+ (void*)weewasm_obj_box_i32_jit};
+ g_runtime_funcs["weewasm.obj.box_f64"] = {weewasm_obj_box_f64,
+ (void*)weewasm_obj_box_f64_jit};
+ g_runtime_funcs["weewasm.obj.get"] = {weewasm_obj_get,
+ (void*)weewasm_obj_get_jit};
+ g_runtime_funcs["weewasm.obj.set"] = {weewasm_obj_set,
+ (void*)weewasm_obj_set_jit};
+ g_runtime_funcs["weewasm.i32.unbox"] = {weewasm_i32_unbox,
+ (void*)weewasm_i32_unbox_jit};
+ g_runtime_funcs["weewasm.f64.unbox"] = {weewasm_f64_unbox,
+ (void*)weewasm_f64_unbox_jit};
+ g_runtime_funcs["weewasm.obj.eq"] = {weewasm_obj_eq,
+ (void*)weewasm_obj_eq_jit};
+}
+
+static void libc_sin(wasm_instance_t* ins) {
+ wasm_value_t x = ins->pop_value();
+ x.val.f64 = std::sin(x.val.f64);
+ ins->push_value(x);
+}
+
+static void libc_cos(wasm_instance_t* ins) {
+ wasm_value_t x = ins->pop_value();
+ x.val.f64 = std::cos(x.val.f64);
+ ins->push_value(x);
+}
+
+static void libc_rand(wasm_instance_t* ins) {
+ wasm_value_t x;
+ x.val.i32 = std::rand();
+ ins->push_value(x);
+}
+
+static void libc_time(wasm_instance_t* ins) {
+ wasm_value_t x;
+ x.val.i32 = std::time(nullptr);
+ ins->push_value(x);
+}
+
+static void libc_srand(wasm_instance_t* ins) {
+ wasm_value_t x = ins->pop_value();
+ std::srand(x.val.i32);
+}
+
+int32_t libc_time_jit() {
+ return std::time(nullptr);
+}
+
+extern "C" void init_libc_runtime() {
+ static std::vector<wasm_func_decl_t> func_decls;
+ func_decls.push_back({{WASM_TYPE_F64}, {WASM_TYPE_F64}});
+ func_decls.push_back({{}, {WASM_TYPE_I32}});
+ func_decls.push_back({{WASM_TYPE_I32}, {}});
+ g_runtime_funcs["libc.sin"] = {
+ libc_sin, (void*)static_cast<double (*)(double)>(std::sin)};
+ g_runtime_funcs["libc.cos"] = {
+ libc_cos, (void*)static_cast<double (*)(double)>(std::cos)};
+ g_runtime_funcs["libc.rand"] = {libc_rand, (void*)std::rand};
+ g_runtime_funcs["libc.time"] = {libc_time, (void*)libc_time_jit};
+ g_runtime_funcs["libc.srand"] = {libc_srand, (void*)std::srand};
+}