aboutsummaryrefslogtreecommitdiff
path: root/src
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
parentf25b015e5b668028c34974bbb22faa4105c26690 (diff)
downloadnanowasm-sync-4f9a2c7a2d8464b04cc08075a7762c6d457090df.tar.gz
WIP
Diffstat (limited to 'src')
-rw-r--r--src/interp.c255
-rw-r--r--src/op/call/call.c7
-rw-r--r--src/op/memory/i32_load.c9
-rw-r--r--src/op/memory/i32_store.c5
-rw-r--r--src/op/variable_access/CMakeLists.txt1
-rw-r--r--src/op/variable_access/get_local.c19
-rw-r--r--src/op/variable_access/set_local.c65
-rw-r--r--src/section/code.c211
-rw-r--r--src/section/common.c88
-rw-r--r--src/section/function.c5
-rw-r--r--src/section/global.c103
-rw-r--r--src/section/type.c10
-rw-r--r--src/start.c7
-rw-r--r--src/types.c96
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 *)&in;
-
- 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];
+}