aboutsummaryrefslogtreecommitdiff
path: root/src/interp.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2024-05-22 14:04:36 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2024-06-12 13:38:05 +0200
commit4f9a2c7a2d8464b04cc08075a7762c6d457090df (patch)
treeae8fe229a3a5ba60d08b74299d0c1850685bda86 /src/interp.c
parentf25b015e5b668028c34974bbb22faa4105c26690 (diff)
downloadnanowasm-sync-4f9a2c7a2d8464b04cc08075a7762c6d457090df.tar.gz
WIP
Diffstat (limited to 'src/interp.c')
-rw-r--r--src/interp.c255
1 files changed, 75 insertions, 180 deletions
diff --git a/src/interp.c b/src/interp.c
index 3a32df0..a9fc9c8 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -192,152 +192,6 @@ void *interp_stackptr(const struct nw_interp *const i)
return (char *)i->cfg.stack.buf + i->stack_i;
}
-static int push_frame(struct nw_interp *const i,
- const struct nw_frame *const src)
-{
- struct nw_frame *const dst = interp_stackptr(i);
-
- if (interp_stack_push(i, src, sizeof (*src)))
- {
- LOG("%s: interp_stack_push failed\n", __func__);
- return -1;
- }
- else if (i->fp)
- i->fp->next = dst;
-
- i->fp = dst;
- return 0;
-}
-
-static bool mul_overflow(const size_t a, const size_t b)
-{
- return a && (a * b) / a != b;
-}
-
-static void init_i32(const varuint32 count, void *const p)
-{
- for (int32_t *i = p; i - (const int32_t *)p < count; i++)
- *i = 0;
-}
-
-static void init_i64(const varuint32 count, void *const p)
-{
- for (int64_t *i = p; i - (const int64_t *)p < count; i++)
- *i = 0;
-}
-
-static void init_f32(const varuint32 count, void *const p)
-{
- for (float *i = p; i - (const float *)p < count; i++)
- *i = 0;
-}
-
-static void init_f64(const varuint32 count, void *const p)
-{
- for (double *i = p; i - (const double *)p < count; i++)
- *i = 0;
-}
-
-static void init_locals(const enum value_type type, const varuint32 count,
- void *const p)
-{
- static void (*const init[])(varuint32, void *) =
- {
- [VALUE_TYPE_I32] = init_i32,
- [VALUE_TYPE_I64] = init_i64,
- [VALUE_TYPE_F32] = init_f32,
- [VALUE_TYPE_F64] = init_f64
- };
-
- init[type](count, p);
-}
-
-static int push_locals(struct nw_interp *const i,
- const struct nw_frame *const f)
-{
- const enum value_type t = f->local_type;
- const size_t typesz = get_type_size(t);
- const unsigned long n = f->n_locals;
-
- if (mul_overflow(typesz, f->n_locals))
- {
- LOG("%s: local variables size mul overflow", __func__);
- i->exception = "mul overfllow";
- return -1;
- }
-
- const size_t totalsz = typesz * n, max = i->cfg.stack.n;
-
- if (totalsz > max || i->stack_i > max - totalsz)
- {
- LOG("%s: cannot allocate locals\n", __func__);
- i->exception = "stack overflow";
- return 1;
- }
-
- init_locals(t, n, interp_stackptr(i));
- i->stack_i += totalsz;
- return 0;
-}
-
-static int do_push_labels(struct nw_interp *const i,
- const struct nw_frame *const fr)
-{
- size_t n = 0;
-
- for (;;)
- {
-
- interp_check_opcode();
- }
-}
-
-static int push_labels(struct nw_interp *const i,
- const struct nw_frame *const fr)
-{
- FILE *const f = i->f;
- const long orig = ftell(f);
-
- if (orig < 0)
- {
- LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
- return -1;
- }
- else if (do_push_labels(i, fr))
- {
- LOG("%s: do_push_labels failed\n", __func__);
- return -1;
- }
- else if (fseek(f, orig, SEEK_SET))
- {
- LOG("%s: fseek(3): %s\n", __func__, strerror(errno));
- return -1;
- }
-
- return -1;
-}
-
-int interp_push(struct nw_interp *const i, const struct nw_frame *const f)
-{
- if (push_frame(i, f))
- {
- LOG("%s: push_frame failed\n", __func__);
- return -1;
- }
- else if (push_locals(i, f))
- {
- LOG("%s: push_locals failed\n", __func__);
- return -1;
- }
- else if (push_labels(i, f))
- {
- LOG("%s: push_labels failed\n", __func__);
- return -1;
- }
-
- return 0;
-}
-
struct retval_priv
{
enum value_type type;
@@ -351,43 +205,31 @@ struct retval_priv
} u;
};
-static void get_i32(const void *const buf, struct retval_priv *const rp)
+static int get_i32(struct nw_interp *const i, struct retval_priv *const rp)
{
- rp->u.i32 = *(((const int32_t *)buf) - 1);
+ return interp_stack_pop(i, &rp->u.i32, sizeof rp->u.i32);
}
-static void get_i64(const void *const buf, struct retval_priv *const rp)
+static int get_i64(struct nw_interp *const i, struct retval_priv *const rp)
{
- rp->u.i64 = *(((const int64_t *)buf) - 1);
+ return interp_stack_pop(i, &rp->u.i64, sizeof rp->u.i64);
}
-static void get_f32(const void *const buf, struct retval_priv *const rp)
+static int get_f32(struct nw_interp *const i, struct retval_priv *const rp)
{
- rp->u.f32 = *(((const float *)buf) - 1);
+ return interp_stack_pop(i, &rp->u.f32, sizeof rp->u.f32);
}
-static void get_f64(const void *const buf, struct retval_priv *const rp)
+static int get_f64(struct nw_interp *const i, struct retval_priv *const rp)
{
- rp->u.f64 = *(((const double *)buf) - 1);
+ return interp_stack_pop(i, &rp->u.f64, sizeof rp->u.f64);
}
-static int get_retval(struct nw_interp *const i,
- struct retval_priv *const rp)
+static int get_retval(struct nw_interp *const i, struct retval_priv *const rp)
{
const struct retval *const r = &i->fp->retval;
- const size_t sz = get_type_size(r->type), max = i->cfg.stack.n;
-
- if (max < sz || i->stack_i >= max - sz)
- {
- static const char exc[] = "stack underflow";
-
- LOG("%s: %s\n", __func__, exc);
- i->exception = exc;
- return -1;
- }
-
- const void *const buf = (const char *)interp_stackptr(i) - sz;
- static void (*const get[])(const void *, struct retval_priv *) =
+ const enum value_type v = r->type;
+ static int (*const f[])(struct nw_interp *, struct retval_priv *) =
{
[VALUE_TYPE_I32] = get_i32,
[VALUE_TYPE_I64] = get_i64,
@@ -395,9 +237,14 @@ static int get_retval(struct nw_interp *const i,
[VALUE_TYPE_F64] = get_f64
};
- get[r->type](buf, rp);
+ if (f[r->type](i, rp))
+ {
+ LOG("%s: callback for type %s failed\n", __func__,
+ value_type_tostr(v));
+ return -1;
+ }
+
rp->type = r->type;
- i->stack_i -= sz;
return 0;
}
@@ -421,10 +268,9 @@ int interp_pop(struct nw_interp *const i)
return -1;
}
- const char *const stackptr = interp_stackptr(i);
- const ptrdiff_t diff = stackptr - (const char *)i->fp;
-
- i->stack_i -= diff;
+#if 0
+#error TODO: do Wasm modules really have an exit status?
+#endif
if (!(i->fp = i->fp->prev))
{
@@ -448,12 +294,15 @@ int interp_pop(struct nw_interp *const i)
int interp_stack_push(struct nw_interp *const i, const void *const src,
const size_t n)
{
+ const size_t max = i->cfg.stack.n;
void *const dst = interp_stackptr(i);
- if (i->cfg.stack.n < n || i->stack_i > i->cfg.stack.n - n)
+ if (max < n || i->stack_i > max - n)
{
- LOG("%s: stack overflow\n", __func__);
- i->exception = "stack overflow";
+ static const char exc[] = "stack overflow";
+
+ LOG("%s: %s\n", __func__, exc);
+ i->exception = exc;
return -1;
}
@@ -467,8 +316,10 @@ int interp_stack_pop(struct nw_interp *const i, void *const dst,
{
if (i->stack_i < n)
{
- LOG("%s: stack underflow\n", __func__);
- i->exception = "stack underflow";
+ static const char exc[] = "stack underflow";
+
+ LOG("%s: %s\n", __func__, exc);
+ i->exception = exc;
return -1;
}
@@ -514,3 +365,47 @@ int interp_heap_load(struct nw_interp *const i, const size_t addr,
memcpy(dst, src, n);
return 0;
}
+
+int interp_global_push(struct nw_interp *const i, const void *const src,
+ const size_t n)
+{
+ const size_t max = i->cfg.global.n;
+ void *const dst = (char *)i->cfg.global.buf + i->global_i;
+
+ if (max < n || i->global_i > max - n)
+ {
+ static const char exc[] = "global memory overflow";
+
+ LOG("%s: %s\n", __func__, exc);
+ i->exception = exc;
+ return -1;
+ }
+
+ memcpy(dst, src, n);
+ i->global_i += n;
+ return 0;
+}
+
+int interp_global_pop(struct nw_interp *const i, void *const dst,
+ const size_t n)
+{
+ const void *const src = (const char *)i->cfg.global.buf + i->global_i;
+
+ if (i->global_i < n)
+ {
+ static const char exc[] = "global memory underflow";
+
+ LOG("%s: %s\n", __func__, exc);
+ i->exception = exc;
+ return -1;
+ }
+
+ i->global_i -= n;
+ memcpy(dst, src, n);
+ return 0;
+}
+
+void *interp_globalptr(const struct nw_interp *const i)
+{
+ return (char *)i->cfg.global.buf + i->global_i;
+}