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 | |
| parent | f25b015e5b668028c34974bbb22faa4105c26690 (diff) | |
| download | nanowasm-sync-4f9a2c7a2d8464b04cc08075a7762c6d457090df.tar.gz | |
WIP
Diffstat (limited to 'src')
| -rw-r--r-- | src/interp.c | 255 | ||||
| -rw-r--r-- | src/op/call/call.c | 7 | ||||
| -rw-r--r-- | src/op/memory/i32_load.c | 9 | ||||
| -rw-r--r-- | src/op/memory/i32_store.c | 5 | ||||
| -rw-r--r-- | src/op/variable_access/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/op/variable_access/get_local.c | 19 | ||||
| -rw-r--r-- | src/op/variable_access/set_local.c | 65 | ||||
| -rw-r--r-- | src/section/code.c | 211 | ||||
| -rw-r--r-- | src/section/common.c | 88 | ||||
| -rw-r--r-- | src/section/function.c | 5 | ||||
| -rw-r--r-- | src/section/global.c | 103 | ||||
| -rw-r--r-- | src/section/type.c | 10 | ||||
| -rw-r--r-- | src/start.c | 7 | ||||
| -rw-r--r-- | src/types.c | 96 |
14 files changed, 335 insertions, 546 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; +} diff --git a/src/op/call/call.c b/src/op/call/call.c index 19355ca..4c970c5 100644 --- a/src/op/call/call.c +++ b/src/op/call/call.c @@ -36,16 +36,11 @@ static int call(struct nw_interp *const i, const varuint32 function_index) LOG("%s: section_type_push failed\n", __func__); return -1; } - else if (section_code_push(f, fn.start, &fr)) + else if (section_code_push(i, fn.start)) { LOG("%s: section_code_push failed\n", __func__); return -1; } - else if (interp_push(i, &fr)) - { - LOG("%s: interp_push failed\n", __func__); - return -1; - } return 0; } diff --git a/src/op/memory/i32_load.c b/src/op/memory/i32_load.c index 04dbec7..ad5abe5 100644 --- a/src/op/memory/i32_load.c +++ b/src/op/memory/i32_load.c @@ -19,7 +19,7 @@ static int load(struct nw_interp *const i, const varuint32 flags, const varuint32 offset) { enum {ALIGN = 2}; - int32_t value; + int32_t value_le; if (flags != ALIGN) { @@ -28,12 +28,15 @@ static int load(struct nw_interp *const i, const varuint32 flags, i->exception = "unaligned access"; return -1; } - else if (interp_heap_load(i, offset, &value, sizeof value)) + else if (interp_heap_load(i, offset, &value_le, sizeof value_le)) { LOG("%s: interp_heap_load failed\n", __func__); return -1; } - else if (interp_stack_push(i, &value, sizeof value)) + + const int32_t value = ntohi32(value_le); + + if (interp_stack_push(i, &value, sizeof value)) { LOG("%s: interp_stack_push failed\n", __func__); return -1; diff --git a/src/op/memory/i32_store.c b/src/op/memory/i32_store.c index 212cd86..9f5351b 100644 --- a/src/op/memory/i32_store.c +++ b/src/op/memory/i32_store.c @@ -49,7 +49,10 @@ static int store(struct nw_interp *const i, const varuint32 flags, i->exception = exc; return -1; } - else if (interp_heap_store(i, offset + addr, &value, sizeof value)) + + const int32_t value_le = htoni32(value); + + if (interp_heap_store(i, offset + addr, &value_le, sizeof value_le)) { LOG("%s: interp_heap_store failed\n", __func__); return -1; diff --git a/src/op/variable_access/CMakeLists.txt b/src/op/variable_access/CMakeLists.txt index 314b5bf..181f330 100644 --- a/src/op/variable_access/CMakeLists.txt +++ b/src/op/variable_access/CMakeLists.txt @@ -6,6 +6,7 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. target_sources(${PROJECT_NAME} PRIVATE + common.c get_global.c get_local.c set_global.c diff --git a/src/op/variable_access/get_local.c b/src/op/variable_access/get_local.c index 745a2e7..7c80450 100644 --- a/src/op/variable_access/get_local.c +++ b/src/op/variable_access/get_local.c @@ -51,22 +51,17 @@ static int get_f64(struct nw_interp *const i, const void *const data, static int get_local(const varuint32 local_index, struct nw_interp *const i) { - struct nw_frame *fr; + struct nw_locals *l; varuint32 idx; - for (idx = local_index, fr = i->fp; fr; fr = fr->next) - if (idx < fr->n_locals) - break; - - if (!fr) + if (locals_get(local_index, i, &l, &idx)) { - LOG("%s: cannot access local variable %lu\n", __func__, - (unsigned long)local_index); - i->exception = "local variable index out of bounds"; + LOG("%s: locals_get failed\n", __func__); return -1; } - static int (*const get[])(struct nw_interp *, const void *, varuint32) = + static int (*const get[])(struct nw_interp *, const void *, + varuint32) = { [VALUE_TYPE_I32] = get_i32, [VALUE_TYPE_I64] = get_i64, @@ -74,9 +69,9 @@ static int get_local(const varuint32 local_index, struct nw_interp *const i) [VALUE_TYPE_F64] = get_f64, }; - if (get[fr->local_type](i, fr + 1, idx)) + if (get[l->type](i, l + 1, idx)) { - LOG("%s: get type %d failed\n", __func__, fr->local_type); + LOG("%s: get type %d failed\n", __func__, l->type); return -1; } diff --git a/src/op/variable_access/set_local.c b/src/op/variable_access/set_local.c index 8cf6440..d9ea884 100644 --- a/src/op/variable_access/set_local.c +++ b/src/op/variable_access/set_local.c @@ -7,6 +7,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +#include <nw/interp.h> #include <nw/log.h> #include <nw/ops.h> #include <nanowasm/nw.h> @@ -20,61 +21,71 @@ static int set_i32(struct nw_interp *const i, void *const data, const varuint32 idx) { - const void *const stackptr = (const char *)i->cfg.stack.buf + i->stack_i; - const int32_t *const src = (const int32_t *)stackptr - 1; - int32_t *const dst = (int32_t *)data + idx; + int32_t *const a = data, v; - *dst = *src; + if (interp_stack_pop(i, &v, sizeof v)) + { + LOG("%s: interp_stack_pop failed\n", __func__); + return -1; + } + + a[idx] = v; return 0; } static int set_i64(struct nw_interp *const i, void *const data, const varuint32 idx) { - const void *const stackptr = (const char *)i->cfg.stack.buf + i->stack_i; - const int64_t *const src = (const int64_t *)stackptr - 1; - int64_t *const dst = (int64_t *)data + idx; + int64_t *const a = data, v; - *dst = *src; + if (interp_stack_pop(i, &v, sizeof v)) + { + LOG("%s: interp_stack_pop failed\n", __func__); + return -1; + } + + a[idx] = v; return 0; } static int set_f32(struct nw_interp *const i, void *const data, const varuint32 idx) { - const void *const stackptr = (const char *)i->cfg.stack.buf + i->stack_i; - const float *const src = (const float *)stackptr - 1; - float *const dst = (float *)data + idx; + float *const a = data, v; - *dst = *src; + if (interp_stack_pop(i, &v, sizeof v)) + { + LOG("%s: interp_stack_pop failed\n", __func__); + return -1; + } + + a[idx] = v; return 0; } static int set_f64(struct nw_interp *const i, void *const data, const varuint32 idx) { - const void *const stackptr = (const char *)i->cfg.stack.buf + i->stack_i; - const double *const src = (const double *)stackptr - 1; - double *const dst = (double *)data + idx; + double *const a = data, v; + + if (interp_stack_pop(i, &v, sizeof v)) + { + LOG("%s: interp_stack_pop failed\n", __func__); + return -1; + } - *dst = *src; + a[idx] = v; return 0; } static int set_local(const varuint32 local_index, struct nw_interp *const i) { - struct nw_frame *fr; varuint32 idx; + struct nw_locals *l; - for (idx = local_index, fr = i->fp; fr; fr = fr->next) - if (idx < fr->n_locals) - break; - - if (!fr) + if (!locals_get(local_index, i, &l, &idx)) { - LOG("%s: cannot access local variable %lu\n", __func__, - (unsigned long)local_index); - i->exception = "local variable index out of bounds"; + LOG("%s: get_pos failed\n", __func__); return -1; } @@ -86,9 +97,9 @@ static int set_local(const varuint32 local_index, struct nw_interp *const i) [VALUE_TYPE_F64] = set_f64, }; - if (set[fr->local_type](i, fr + 1, idx)) + if (set[l->type](i, l + 1, idx)) { - LOG("%s: set type %d failed\n", __func__, fr->local_type); + LOG("%s: set type %d failed\n", __func__, l->type); return -1; } diff --git a/src/section/code.c b/src/section/code.c index da45047..3d62143 100644 --- a/src/section/code.c +++ b/src/section/code.c @@ -66,146 +66,35 @@ static int check_body(FILE *const f, const unsigned long n) return 0; } -#if 0 - -static int push_locals(struct nw_interp *const i, - const struct nw_frame *const f) +static int push_i32(struct nw_interp *const i) { - 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; + const int32_t value = 0; - 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; + return interp_stack_push(i, &value, sizeof value); } -static int push_block(struct nw_interp *const i) +static int push_i64(struct nw_interp *const i) { - const long pc = ftell(i->f); - - if (pc < 0) - { - LOG("%s: ftell(3): %s\n", __func__, strerror(errno)); - return -1; - } - - const struct nw_block b = - { - .pc = pc - }; - - if (interp_stack_push(i, &b, sizeof b)) - { - LOG("%s: interp_stack_push failed\n", __func__); - return -1; - } + const int64_t value = 0; - struct nw_block *const p = (struct nw_block *)interp_stackptr(i) - 1; - - if (i->fp->block) - { - for (struct nw_block *b = i->fp->block; b; b = b->next) - if (!b->next) - { - b->next = p; - break; - } - } - else - i->fp->block = p; - - return 0; + return interp_stack_push(i, &value, sizeof value); } -static int loop_push_blocks(struct nw_interp *const i) +static int push_f32(struct nw_interp *const i) { - for (;;) - { - uint8_t op; - - if (!fread(&op, sizeof op, 1, i->f)) - { - LOG("%s: fread(3) failed, feof=%d, ferror=%d\n", __func__, - feof(i->f), ferror(i->f)); - i->exception = "I/O error"; - return -1; - } - else if (op >= sizeof ops / sizeof *ops) - { - LOG("%s: invalid opcode %#" PRIx8 "\n", __func__, op); - i->exception = "invalid opcode"; - return -1; - } - else if (interp_check_opcode(op, i->f)) - { - LOG("%s: interp_check_opcode failed\n", __func__); - return -1; - } + const float value = 0; - switch (op) - { - case OP_END: - return 0; - - case OP_BLOCK: - if (push_block(i)) - { - LOG("%s: push_block failed\n", __func__); - return -1; - } - - break; - - default: - break; - } - } + return interp_stack_push(i, &value, sizeof value); } -static int push_blocks(struct nw_interp *const i, - const struct nw_frame *const fr) +static int push_f64(struct nw_interp *const i) { - 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 (loop_push_blocks(i)) - { - LOG("%s: loop_push_blocks failed\n", __func__); - return -1; - } - else if (fseek(f, orig, SEEK_SET)) - { - LOG("%s: fseek(3): %s\n", __func__, strerror(errno)); - return -1; - } + const double value = 0; - return 0; + return interp_stack_push(i, &value, sizeof value); } -#endif -static int push_local_count(struct nw_frame *const f, const varuint32 count, +static int push_locals(struct nw_interp *const in, const varuint32 count, const varint7 type) { enum value_type vtype; @@ -216,12 +105,26 @@ static int push_local_count(struct nw_frame *const f, const varuint32 count, return -1; } - f->n_locals = count; - f->local_type = vtype; + static int (*const f[])(struct nw_interp *) = + { + [VALUE_TYPE_I32] = push_i32, + [VALUE_TYPE_I64] = push_i64, + [VALUE_TYPE_F32] = push_f32, + [VALUE_TYPE_F64] = push_f64 + }; + + for (varuint32 i = 0; i < count; i++) + if (f[vtype](in)) + { + LOG("%s: local variable push failed, type=%s, index=%lu\n", + __func__, value_type_tostr(vtype), (unsigned long)i); + return -1; + } + return 0; } -static int check_local(FILE *const f, struct nw_frame *const fr) +static int check_local_group(FILE *const f, struct nw_interp *const i) { varuint32 count; varint7 type; @@ -236,16 +139,16 @@ static int check_local(FILE *const f, struct nw_frame *const fr) LOG("%s: varint7_read failed\n", __func__); return -1; } - else if (fr && push_local_count(fr, count, type)) + else if (i && push_locals(i, count, type)) { - LOG("%s: push_local_count failed\n", __func__); + LOG("%s: push_locals failed\n", __func__); return -1; } return 0; } -static int check_locals(FILE *const f, struct nw_frame *const fr) +static int run(FILE *const f, struct nw_interp *const in) { varuint32 local_count; @@ -256,7 +159,7 @@ static int check_locals(FILE *const f, struct nw_frame *const fr) } for (varuint32 i = 0; i < local_count; i++) - if (check_local(f, fr)) + if (check_local_group(f, in)) { LOG("%s: check_local failed\n", __func__); return -1; @@ -265,6 +168,23 @@ static int check_locals(FILE *const f, struct nw_frame *const fr) return 0; } +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 int check_function_body(FILE *const f, long *const out) { varuint32 body_size; @@ -282,9 +202,9 @@ static int check_function_body(FILE *const f, long *const out) LOG("%s: ftell(3) start: %s\n", __func__, strerror(errno)); return -1; } - else if (check_locals(f, NULL)) + else if (run(f, NULL)) { - LOG("%s: check_locals failed\n", __func__); + LOG("%s: check_local_groups failed\n", __func__); return -1; } @@ -313,8 +233,7 @@ static int check_function_body(FILE *const f, long *const out) return 0; } -static int run(FILE *const f, const varuint32 idx, - struct section_code *const out) +static int run(FILE *const f, const varuint32 idx, struct nw_interp *const in) { varuint32 count; @@ -323,11 +242,6 @@ static int run(FILE *const f, const varuint32 idx, LOG("%s: varuint32_read failed\n", __func__); return -1; } - else if (count > ULONG_MAX - 1) - { - fprintf(stderr, "%s: count overflow\n", __func__); - return -1; - } for (varuint32 i = 0; i < count; i++) { @@ -366,7 +280,7 @@ int section_code_check(const struct section *const s, struct nw_mod *const m, LOG("%s: ftell(3): %s\n", __func__, strerror(errno)); return -1; } - else if (run(f, 0, NULL)) + else if (run(f, NULL)) { LOG("%s: run failed\n", __func__); return -1; @@ -412,18 +326,7 @@ int section_code(const struct section *const s, const struct nw_mod *const m, return run(s->f, idx, out); } -int section_code_push(FILE *const f, const long pc, struct nw_frame *const fr) +int section_code_push(FILE *const f, struct nw_interp *const i) { - if (fseek(f, pc, SEEK_SET)) - { - LOG("%s: fseek(3): %s\n", __func__, strerror(errno)); - return -1; - } - else if (check_locals(f, fr)) - { - LOG("%s: check_local failed\n", __func__); - return -1; - } - - return 0; + return run(f, i); } diff --git a/src/section/common.c b/src/section/common.c index b768470..84ed191 100644 --- a/src/section/common.c +++ b/src/section/common.c @@ -60,91 +60,3 @@ int check_resizable_limits(FILE *const f, struct resizable_limits *const r) r->sz = initial * page_size; return 0; } - -size_t get_type_size(const enum value_type type) -{ - static const size_t list[] = - { - [VALUE_TYPE_I32] = sizeof (int32_t), - [VALUE_TYPE_I64] = sizeof (int64_t), - [VALUE_TYPE_F32] = sizeof (float), - [VALUE_TYPE_F64] = sizeof (double) - }; - - return list[type]; -} - -enum -{ - I32 = 0x7f, - I64 = 0x7e, - F32 = 0x7d, - F64 = 0x7c, - ANYFUNC = 0x70, - FUNC = 0x60, - BLOCK_TYPE = 0x40 -}; - -int get_value_type(const varint7 type, enum value_type *const vtype) -{ - static const struct size - { - varint7 type; - enum value_type vtype; - } sizes[] = - { - {.type = I32, .vtype = VALUE_TYPE_I32}, - {.type = I64, .vtype = VALUE_TYPE_I64}, - {.type = F32, .vtype = VALUE_TYPE_F32}, - {.type = F64, .vtype = VALUE_TYPE_F64}, - /* TODO: check this. */ - {.type = ANYFUNC, .vtype = VALUE_TYPE_I32}, - /* TODO: check this. */ - {.type = FUNC, .vtype = VALUE_TYPE_I32}, - /* TODO: check this. */ - {.type = BLOCK_TYPE, .vtype = VALUE_TYPE_I32} - }; - - for (size_t i = 0; i < sizeof sizes / sizeof *sizes; i++) - { - const struct size *const s = &sizes[i]; - - if (type == s->type) - { - *vtype = s->vtype; - return 0; - } - } - - LOG("%s: unknown type %#hhx\n", __func__, (char)type); - return -1; -} - -static int32_t swap_i32(const int32_t in) -{ - const int8_t *const p = (const int8_t *)∈ - - return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); -} - -int32_t htoni32(const int32_t in) -{ - return swap_i32(in); -} - -int32_t ntohi32(const int32_t in) -{ - return swap_i32(in); -} - -const char *value_type_tostr(const enum value_type v) -{ - static const char *const s[] = - { -#define X(x) [x] = #x, - VALUE_TYPES -#undef X - }; - - return s[v]; -} diff --git a/src/section/function.c b/src/section/function.c index 3ffed36..0395b24 100644 --- a/src/section/function.c +++ b/src/section/function.c @@ -28,11 +28,6 @@ static int run(FILE *const f, const varuint32 idx, LOG("%s: varuint32_read count failed\n", __func__); return -1; } - else if (count > ULONG_MAX - 1) - { - fprintf(stderr, "%s: count overflow\n", __func__); - return -1; - } for (varuint32 i = 0; i < count; i++) { diff --git a/src/section/global.c b/src/section/global.c index eff2e0b..4f3a2ee 100644 --- a/src/section/global.c +++ b/src/section/global.c @@ -30,66 +30,44 @@ struct global_type } value; }; -static int get_i32(const struct nw_interp *const i, - union global_value *const value) +static int get_global(struct nw_interp *const i, void *const dst, + const size_t n) { - if (i->stack_i != sizeof value->i32) + if (i->stack_i != n) { LOG("%s: expected %zu used stack bytes, got %zu\n", - __func__, i->stack_i, sizeof value->i32); + __func__, i->stack_i, n); + i->exception = "unexpected stack consumption"; return -1; } - value->i32 = *(const int32_t *)i->cfg.stack.buf; - return 0; + return interp_global_pop(i, dst, n); } -static int get_i64(const struct nw_interp *const i, - union global_value *const value) +static int get_i32(struct nw_interp *const i, union global_value *const value) { - if (i->stack_i != sizeof value->i64) - { - LOG("%s: expected %zu used stack bytes, got %zu\n", - __func__, i->stack_i, sizeof value->i64); - return -1; - } - - value->i64 = *(const int64_t *)i->cfg.stack.buf; - return 0; + return get_global(i, &value->i32, sizeof value->i32); } -static int get_f32(const struct nw_interp *const i, - union global_value *const value) +static int get_i64(struct nw_interp *const i, union global_value *const value) { - if (i->stack_i != sizeof value->f32) - { - LOG("%s: expected %zu used stack bytes, got %zu\n", - __func__, i->stack_i, sizeof value->f32); - return -1; - } - - value->f32 = *(const float *)i->cfg.stack.buf; - return 0; + return get_global(i, &value->i64, sizeof value->i64); } -static int get_f64(const struct nw_interp *const i, - union global_value *const value) +static int get_f32(struct nw_interp *const i, union global_value *const value) { - if (i->stack_i != sizeof value->f64) - { - LOG("%s: expected %zu used stack bytes, got %zu\n", - __func__, i->stack_i, sizeof value->f64); - return -1; - } + return get_global(i, &value->f32, sizeof value->f32); +} - value->f64 = *(const double *)i->cfg.stack.buf; - return 0; +static int get_f64(struct nw_interp *const i, union global_value *const value) +{ + return get_global(i, &value->f64, sizeof value->f64); } -static int get_value(const struct nw_interp *const i, - const enum value_type type, union global_value *const value) +static int get_value(struct nw_interp *const i, const enum value_type type, + union global_value *const value) { - static int (*const get[])(const struct nw_interp *, union global_value *) = + static int (*const get[])(struct nw_interp *, union global_value *) = { [VALUE_TYPE_I32] = get_i32, [VALUE_TYPE_I64] = get_i64, @@ -163,29 +141,33 @@ static int check_global_type(FILE *const f, struct global_type *const g) static int set_i32(struct nw_interp *const i, void *const dst, const struct global_type *const g) { - *(int32_t *)dst = g->value.i32; - return 0; + const int32_t value = g->value.i32; + + return interp_global_push(i, &value, sizeof value); } static int set_i64(struct nw_interp *const i, void *const dst, const struct global_type *const g) { - *(int64_t *)dst = g->value.i64; - return 0; + const int64_t value = g->value.i64; + + return interp_global_push(i, &value, sizeof value); } static int set_f32(struct nw_interp *const i, void *const dst, const struct global_type *const g) { - *(float *)dst = g->value.f32; - return 0; + const float value = g->value.f32; + + return interp_global_push(i, &value, sizeof value); } static int set_f64(struct nw_interp *const i, void *const dst, const struct global_type *const g) { - *(double *)dst = g->value.f64; - return 0; + const double value = g->value.f64; + + return interp_global_push(i, &value, sizeof value); } static int add_global(struct nw_interp *const i, @@ -197,24 +179,14 @@ static int add_global(struct nw_interp *const i, .type = g->type }; - const size_t sz = sizeof f + get_type_size(g->type), - max = i->cfg.global.n; + struct nw_gframe *const dst = interp_globalptr(i);; - if (max < sz || i->global_i > max - sz) + if (interp_global_push(i, &f, sizeof f)) { - LOG("%s: global memory overflow\n", __func__); - i->exception = "global memory overflow"; + LOG("%s: interp_global_push failed\n", __func__); return -1; } - void *const buf = (char *)i->cfg.global.buf + i->global_i; - struct nw_gframe *const dst = buf; - - if (i->gfp) - i->gfp->next = dst; - - *dst = f; - static int (*const set[])(struct nw_interp *, void *, const struct global_type *) = { @@ -226,11 +198,14 @@ static int add_global(struct nw_interp *const i, if (set[g->type](i, dst + 1, g)) { - LOG("%s: set failed with type %d\n", __func__, g->type); + LOG("%s: set failed with type %s\n", __func__, + value_type_tostr(g->type)); return -1; } - i->global_i += sz; + if (i->gfp) + i->gfp->next = dst; + i->gfp = dst; return 0; } diff --git a/src/section/type.c b/src/section/type.c index 0bf7a06..f7bc712 100644 --- a/src/section/type.c +++ b/src/section/type.c @@ -80,7 +80,7 @@ static int check_func_type(FILE *const f, struct retval *const r) } static int run(FILE *const f, const unsigned long len, const varuint32 idx, - struct nw_frame *const fr) + struct retval *const out) { const long start = ftell(f); varuint32 count; @@ -105,9 +105,9 @@ static int run(FILE *const f, const unsigned long len, const varuint32 idx, LOG("%s: check_func_type failed\n", __func__); return -1; } - else if (fr && i == idx) + else if (out && i == idx) { - fr->retval = r; + *out = r; return 0; } } @@ -161,7 +161,7 @@ int section_type_check(const struct section *const s, struct nw_mod *const m, } int section_type_push(FILE *const f, const struct nw_mod *const m, - const varuint32 idx, struct nw_frame *const fr) + const varuint32 idx, struct retval *const out) { const long offset = m->sections.type; @@ -176,5 +176,5 @@ int section_type_push(FILE *const f, const struct nw_mod *const m, return -1; } - return run(f, 0, idx, fr); + return run(f, 0, idx, out); } diff --git a/src/start.c b/src/start.c index c22bddf..e8bc730 100644 --- a/src/start.c +++ b/src/start.c @@ -56,7 +56,12 @@ int nw_start(const struct nw_inst_cfg *const icfg, struct nw_inst *const i) LOG("%s: section_type_push failed\n", __func__); goto end; } - else if (section_code_push(f, fn.start, &fr)) + else if (fseek(f, fn.start, SEEK_SET)) + { + LOG("%s: fseek(3): %s\n", __func__, strerror(errno)); + return -1; + } + else if (section_code_push(f, &fr)) { LOG("%s: section_code_push failed\n", __func__); goto end; diff --git a/src/types.c b/src/types.c index 88c883e..56b2bc1 100644 --- a/src/types.c +++ b/src/types.c @@ -8,6 +8,7 @@ */ #include <nw/leb128.h> +#include <nw/log.h> #include <nw/types.h> #include <stdio.h> @@ -87,3 +88,98 @@ int varint64_read(FILE *const f, varint64 *const out) *out = value; return 0; } + +size_t get_type_size(const enum value_type type) +{ + static const size_t list[] = + { + [VALUE_TYPE_I32] = sizeof (int32_t), + [VALUE_TYPE_I64] = sizeof (int64_t), + [VALUE_TYPE_F32] = sizeof (float), + [VALUE_TYPE_F64] = sizeof (double) + }; + + return list[type]; +} + +enum +{ + I32 = 0x7f, + I64 = 0x7e, + F32 = 0x7d, + F64 = 0x7c, + ANYFUNC = 0x70, + FUNC = 0x60, + BLOCK_TYPE = 0x40 +}; + +int get_value_type(const varint7 type, enum value_type *const vtype) +{ + static const struct size + { + varint7 type; + enum value_type vtype; + } sizes[] = + { + {.type = I32, .vtype = VALUE_TYPE_I32}, + {.type = I64, .vtype = VALUE_TYPE_I64}, + {.type = F32, .vtype = VALUE_TYPE_F32}, + {.type = F64, .vtype = VALUE_TYPE_F64}, + /* TODO: check this. */ + {.type = ANYFUNC, .vtype = VALUE_TYPE_I32}, + /* TODO: check this. */ + {.type = FUNC, .vtype = VALUE_TYPE_I32}, + /* TODO: check this. */ + {.type = BLOCK_TYPE, .vtype = VALUE_TYPE_I32} + }; + + for (size_t i = 0; i < sizeof sizes / sizeof *sizes; i++) + { + const struct size *const s = &sizes[i]; + + if (type == s->type) + { + *vtype = s->vtype; + return 0; + } + } + + LOG("%s: unknown type %#hhx\n", __func__, (char)type); + return -1; +} + +static int32_t little_endian_i32(const int32_t in) +{ + const union + { + uint8_t a[4]; + uint32_t b; + } v = + { + .b = in + }; + + return v.a[0] | (v.a[1] << 8l) | (v.a[2] << 16l) | (v.a[3] << 24l); +} + +int32_t htoni32(const int32_t in) +{ + return little_endian_i32(in); +} + +int32_t ntohi32(const int32_t in) +{ + return little_endian_i32(in); +} + +const char *value_type_tostr(const enum value_type v) +{ + static const char *const s[] = + { +#define X(x) [x] = #x, + VALUE_TYPES +#undef X + }; + + return s[v]; +} |
