aboutsummaryrefslogtreecommitdiff
path: root/src/section/code.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/section/code.c')
-rw-r--r--src/section/code.c211
1 files changed, 57 insertions, 154 deletions
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);
}