diff options
Diffstat (limited to 'src/section/code.c')
| -rw-r--r-- | src/section/code.c | 211 |
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); } |
