diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2024-05-22 14:04:36 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2024-06-12 13:38:05 +0200 |
| commit | 4f9a2c7a2d8464b04cc08075a7762c6d457090df (patch) | |
| tree | ae8fe229a3a5ba60d08b74299d0c1850685bda86 /src/interp.c | |
| parent | f25b015e5b668028c34974bbb22faa4105c26690 (diff) | |
| download | nanowasm-sync-4f9a2c7a2d8464b04cc08075a7762c6d457090df.tar.gz | |
WIP
Diffstat (limited to 'src/interp.c')
| -rw-r--r-- | src/interp.c | 255 |
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; +} |
