protoverse

A metaverse protocol
git clone git://jb55.com/protoverse
Log | Files | Refs | README | LICENSE

commit 3850ab18521d02d00c75fc86a08d048314f8060c
parent 82b440cf195f62b009b88532baca1d2815d7dd1d
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 23 Jul 2021 13:03:46 -0700

don't recursively call interp_code

things break on many nested functions

Diffstat:
MMakefile | 2+-
Msrc/wasm.c | 290+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/wasm.h | 1+
3 files changed, 166 insertions(+), 127 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ CFLAGS = -Wno-error=unused-function -O2 -g -std=gnu90 -Wall -Wextra -Werror \ -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes \ - -Wmissing-declarations -Wdeclaration-after-statement + -Wmissing-declarations -Wdeclaration-after-statement -fno-stack-protector OBJS = src/io.o \ src/parse.o \ diff --git a/src/wasm.c b/src/wasm.c @@ -585,6 +585,8 @@ static INLINE int was_section_parsed(struct module *module, return module->parsed & (1 << section); } +//static int callframe_cnt = 0; + static INLINE int cursor_push_callframe(struct cursor *cur, struct callframe *frame) { //debug("pushing callframe %d fn:%d\n", ++callframe_cnt, frame->fn); @@ -3011,8 +3013,9 @@ static INLINE int count_local_resolvers(struct wasm_interp *interp, int *count) static INLINE int drop_callframe(struct wasm_interp *interp) { int offset; +#ifdef DEBUG + int count; - /* if (unlikely(!count_local_resolvers(interp, &count))) { return interp_error(interp, "count local resolvers"); } @@ -3021,12 +3024,14 @@ static INLINE int drop_callframe(struct wasm_interp *interp) return interp_error(interp, "unclean callframe drop, still have" " %d unpopped labels", count); } - */ +#endif if (unlikely(!cursor_popint(&interp->resolver_offsets, &offset))) { return interp_error(interp, "pop resolver_offsets"); } + debug("dropping callframe\n"); + return cursor_drop_callframe(&interp->callframes); } @@ -3043,6 +3048,7 @@ static INLINE int call_wasm_func(struct wasm_interp *interp, struct wasm_func *f if (unlikely(!cursor_push_callframe(&interp->callframes, &callframe))) return interp_error(interp, "oob cursor_pushcode"); + /* if (unlikely(!interp_code(interp))) { return interp_error(interp, "call %s:%d", get_function_name(interp->module, fn), @@ -3051,6 +3057,7 @@ static INLINE int call_wasm_func(struct wasm_interp *interp, struct wasm_func *f if (unlikely(!drop_callframe(interp))) return interp_error(interp, "drop callframe"); + */ return 1; } @@ -3120,14 +3127,14 @@ static void make_default_val(struct val *val) } } -static int prepare_function_args(struct wasm_interp *interp, struct func *func, +static int prepare_call(struct wasm_interp *interp, struct func *func, int func_index) { static char buf[128]; struct local *local; enum valtype paramtype; struct val val; - u32 i, ind; + u32 i, ind, offset; /* push params as locals */ for (i = 0; i < func->functype->params.num_valtypes; i++) { @@ -3161,6 +3168,11 @@ static int prepare_function_args(struct wasm_interp *interp, struct func *func, memcpy(&func->locals[ind], &val, sizeof(struct val)); } + offset = count_resolvers(interp); + /* push label resolver offsets, used to keep track of per-func resolvers */ + /* TODO: maybe move this data to struct func? */ + if (unlikely(!cursor_push_int(&interp->resolver_offsets, offset))) + return interp_error(interp, "push resolver offset"); for (i=func->functype->params.num_valtypes; i < func->num_locals; i++) { @@ -3177,7 +3189,6 @@ static int prepare_function_args(struct wasm_interp *interp, struct func *func, static int call_function(struct wasm_interp *interp, int func_index) { struct func *func; - unsigned int offset; debug("calling %s:%d\n", get_function_name(interp->module, func_index), func_index); @@ -3189,13 +3200,7 @@ static int call_function(struct wasm_interp *interp, int func_index) interp->module->code_section.num_funcs); } - offset = count_resolvers(interp); - /* push label resolver offsets, used to keep track of per-func resolvers */ - /* TODO: maybe move this data to struct func? */ - if (unlikely(!cursor_push_int(&interp->resolver_offsets, offset))) - return interp_error(interp, "push resolver offset"); - - if (!prepare_function_args(interp, func, func_index)) { + if (!prepare_call(interp, func, func_index)) { return interp_error(interp, "prepare args"); } @@ -3214,11 +3219,13 @@ static int interp_call(struct wasm_interp *interp, int func_index) if (unlikely(!call_function(interp, func_index))) return 0; + /* debug("returning from %s:%d to %s:%d\n", get_function_name(interp->module, func_index), func_index, get_function_name(interp->module, prev_frame.fn), prev_frame.fn); + */ return 1; } @@ -3379,18 +3386,15 @@ static INLINE int resolve_label(struct label *label, struct cursor *code) static INLINE int pop_resolver(struct wasm_interp *interp, struct resolver *resolver) { - /* #ifdef DEBUG int num_resolvers; struct label *label; #endif -*/ if (!cursor_pop(&interp->resolver_stack, (u8*)resolver, sizeof(*resolver))) { return interp_error(interp, "pop resolver"); } - /* #ifdef DEBUG if (unlikely(!count_local_resolvers(interp, &num_resolvers))) { return interp_error(interp, "local resolvers fn start"); @@ -3410,7 +3414,6 @@ static INLINE int pop_resolver(struct wasm_interp *interp, count_resolvers(interp), num_resolvers ); - */ return 1; } @@ -3533,11 +3536,9 @@ static int push_label_checkpoint(struct wasm_interp *interp, struct label **labe struct resolver resolver; struct callframe *frame; - /* #ifdef DEBUG int num_resolvers; #endif -*/ resolver.start_tag = start_tag; resolver.end_tag = end_tag; @@ -3569,7 +3570,6 @@ static int push_label_checkpoint(struct wasm_interp *interp, struct label **labe return interp_error(interp, "push label index to resolver stack oob"); } - /* #ifdef DEBUG if (unlikely(!count_local_resolvers(interp, &num_resolvers))) { return interp_error(interp, "local resolvers fn start"); @@ -3582,7 +3582,6 @@ static int push_label_checkpoint(struct wasm_interp *interp, struct label **labe instr_name(resolver.end_tag), cursor_count(&interp->resolver_stack, sizeof(resolver)), num_resolvers); - */ return 1; } @@ -3671,7 +3670,7 @@ static int pop_label_and_break(struct wasm_interp *interp, struct label *label, // we have a loop, push the popped resolver if (resolver.start_tag == i_loop) { - debug("repushing resolver\n"); + debug("repushing resolver for loop\n"); if (unlikely(!cursor_push_resolver(&interp->resolver_stack, &resolver))) { return interp_error(interp, "re-push loop resolver"); } @@ -4024,7 +4023,6 @@ static int if_jump(struct wasm_interp *interp, u8 start_tag, u8 end_tag) // consume instructions, use resolver stack to resolve jumps if (!parse_instrs_until(&parser, end_tag, &instrs, &instrs_len)) { - cursor_print_around(interp_codeptr(interp), 10); return interp_error(interp, "parse instrs start @ %s end @ %s", instr_name(start_tag), instr_name(end_tag)); @@ -4055,30 +4053,6 @@ static int interp_block(struct wasm_interp *interp) return 1; } -static INLINE int interp_end(struct wasm_interp *interp) -{ - return pop_label_checkpoint(interp); - - /* - struct resolver resolver; - struct callframe *frame; - struct label *label; - - debug("interp end\n"); - - if (!pop_label(interp, &resolver, &frame, &label)) { - return interp_error(interp, "pop label at end inst"); - } - - if (resolver.start_tag == i_loop) { - debug("loop jumping at end instr\n"); - return interp_jump(interp, label->jump); - } - - return 1; - */ -} - static int interp_if(struct wasm_interp *interp) { struct val cond; @@ -4757,6 +4731,24 @@ static INLINE int interp_i32_or(struct wasm_interp *interp) return stack_pushval(interp, &c); } +static int interp_i32_rem_s(struct wasm_interp *interp) +{ + struct val lhs, rhs, c; + if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i32))) + return interp_error(interp, "binop prep"); + c.num.i32 = lhs.num.i32 % rhs.num.i32; + return stack_pushval(interp, &c); +} + +static int interp_i32_rem_u(struct wasm_interp *interp) +{ + struct val lhs, rhs, c; + if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i32))) + return interp_error(interp, "binop prep"); + c.num.u32 = lhs.num.u32 % rhs.num.u32; + return stack_pushval(interp, &c); +} + static INLINE int interp_i32_and(struct wasm_interp *interp) { struct val lhs, rhs, c; @@ -4785,12 +4777,45 @@ static int interp_i64_or(struct wasm_interp *interp) static int interp_i64_shl(struct wasm_interp *interp) { struct val lhs, rhs, c; + if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i64))) + return interp_error(interp, "binop prep"); + c.num.i64 = lhs.num.i64 << rhs.num.i64; + return stack_pushval(interp, &c); +} - if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i64))) { +static int interp_i64_ne(struct wasm_interp *interp) +{ + struct val lhs, rhs, c; + if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i64))) return interp_error(interp, "binop prep"); - } + make_i32_val(&c, lhs.num.i64 != rhs.num.i64); + return stack_pushval(interp, &c); +} - c.num.i64 = lhs.num.i64 << rhs.num.i64; +static int interp_i64_eq(struct wasm_interp *interp) +{ + struct val lhs, rhs, c; + if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i64))) + return interp_error(interp, "binop prep"); + make_i32_val(&c, lhs.num.i64 == rhs.num.i64); + return stack_pushval(interp, &c); +} + +static int interp_i64_rem_s(struct wasm_interp *interp) +{ + struct val lhs, rhs, c; + if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i64))) + return interp_error(interp, "binop prep"); + c.num.i64 = lhs.num.i64 % rhs.num.i64; + return stack_pushval(interp, &c); +} + +static int interp_i64_rem_u(struct wasm_interp *interp) +{ + struct val lhs, rhs, c; + if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i64))) + return interp_error(interp, "binop prep"); + c.num.u64 = lhs.num.u64 % rhs.num.u64; return stack_pushval(interp, &c); } @@ -5137,9 +5162,65 @@ static int interp_return(struct wasm_interp *interp) count); } - return i_return; + return drop_callframe(interp); } +enum interp_end { + interp_end_err, + interp_end_next, + interp_end_done, +}; + +// tricky... +static int interp_end(struct wasm_interp *interp) +{ + struct resolver *resolver; + //struct label *label; + int loc_resolvers; + + if (unlikely(!(resolver = top_resolver(interp, 0)))) { + // no more resolvers, we done. + return interp_end_done; + } + + if (unlikely(!count_local_resolvers(interp, &loc_resolvers))) { + return interp_error(interp, "count local resolvers"); + } + + //debug("interp_code_end local resolvers: %d\n", num_resolvers); + + debug("ending ? local_resolvers %d\n", loc_resolvers); + + if (loc_resolvers == 0) { + if (!drop_callframe(interp)) + return interp_error(interp, "drop callframe at end of fn"); + return interp_end_next; + } + + // if we hit the end of a loop, continue at the start + /* + if (resolver && resolver->start_tag == i_loop) { + if (unlikely(!(label = index_label(&interp->labels, frame->fn, + resolver->label)))) { + return interp_error(interp, "no loop label?"); + } + + resolve_label(label, code); + + debug("loop jumping\n"); + if (!interp_jump(interp, label_instr_pos(label))) { + return interp_error(interp, "jump to loop label"); + } + + return interp_end_cont; + } + */ + + return pop_label_checkpoint(interp); + +} + + static int interp_instr(struct wasm_interp *interp, struct instr *instr) { interp->ops++; @@ -5184,6 +5265,8 @@ static int interp_instr(struct wasm_interp *interp, struct instr *instr) case i_i32_mul: return interp_i32_mul(interp); case i_i32_xor: return interp_i32_xor(interp); case i_i32_ne: return interp_i32_ne(interp); + case i_i32_rem_u: return interp_i32_rem_u(interp); + case i_i32_rem_s: return interp_i32_rem_s(interp); case i_i32_eq: return interp_i32_eq(interp); case i_i32_wrap_i64:return interp_i32_wrap_i64(interp); @@ -5197,6 +5280,10 @@ static int interp_instr(struct wasm_interp *interp, struct instr *instr) case i_i64_xor: return interp_i64_xor(interp); case i_i64_mul: return interp_i64_mul(interp); case i_i64_shl: return interp_i64_shl(interp); + case i_i64_ne: return interp_i64_ne(interp); + case i_i64_eq: return interp_i64_eq(interp); + case i_i64_rem_u: return interp_i64_rem_u(interp); + case i_i64_rem_s: return interp_i64_rem_s(interp); case i_i64_shr_u: return interp_i64_shr_u(interp); case i_i64_shr_s: return interp_i64_shr_s(interp); case i_i64_or: return interp_i64_or(interp); @@ -5278,6 +5365,7 @@ static INLINE int interp_parse_instr(struct wasm_interp *interp, return interp_error(interp, "no more instrs to pull"); } + instr->tag = tag; instr->pos = code->p - 1 - code->start; @@ -5285,6 +5373,7 @@ static INLINE int interp_parse_instr(struct wasm_interp *interp, return 1; } + parser->code = code; if (!parse_instr(parser, instr->tag, instr)) { return interp_error(interp, "parse instr %s", instr_name(tag)); } @@ -5292,60 +5381,6 @@ static INLINE int interp_parse_instr(struct wasm_interp *interp, return 1; } -enum interp_end { - interp_end_err, - interp_end_done, - interp_end_cont, - interp_end_next, -}; - -// tricky... -static enum interp_end interp_code_end(struct wasm_interp *interp, - struct callframe *frame, struct cursor *code) -{ - struct resolver *resolver; - //struct label *label; - int num_resolvers = 0; - (void)frame; - (void)code; - - if (unlikely(!(resolver = top_resolver(interp, 0)))) { - // no more resolvers, we done. - return interp_end_done; - } - - if (unlikely(!count_local_resolvers(interp, &num_resolvers))) { - return interp_error(interp, "count local resolvers"); - } - - //debug("interp_code_end local resolvers: %d\n", num_resolvers); - - if (num_resolvers == 0) { - return interp_end_done; - } - - // if we hit the end of a loop, continue at the start - /* - if (resolver && resolver->start_tag == i_loop) { - if (unlikely(!(label = index_label(&interp->labels, frame->fn, - resolver->label)))) { - return interp_error(interp, "no loop label?"); - } - - resolve_label(label, code); - - debug("loop jumping\n"); - if (!interp_jump(interp, label_instr_pos(label))) { - return interp_error(interp, "jump to loop label"); - } - - return interp_end_cont; - } - */ - - return interp_end_next; -} - static int interp_elem_drop(struct wasm_interp *interp, int elemidx) { (void)interp; @@ -5358,43 +5393,42 @@ static int interp_code(struct wasm_interp *interp) { struct instr instr; struct expr_parser parser; - struct cursor *code; struct callframe *frame; int ret; - make_interp_expr_parser(interp, &parser); - - if (unlikely(!(frame = top_callframe(&interp->callframes)))) { - return interp_error(interp, "no callframe"); - } + parser.interp = interp; + parser.errs = &interp->errors; for (;;) { - if (unlikely(!(code = interp_codeptr(interp)))) { - return interp_error(interp, "codeptr"); + + if (unlikely(!(frame = top_callframe(&interp->callframes)))) { + return interp_error(interp, "no callframe"); } - if (unlikely(!interp_parse_instr(interp, code, &parser, &instr))) { - cursor_print_around(code, 5); - debug("end ? %d\n", top_callframe(&interp->callframes)->fn); + debug("parsing in frame %s:%d\n", + interp->module->funcs[frame->fn].name, frame->fn); + + if (unlikely(!interp_parse_instr(interp, &frame->code, &parser, + &instr))) { return interp_error(interp, "parse instr"); } + //cursor_print_around(&frame->code, 10); + + if (unlikely(!(ret = interp_instr(interp, &instr)))) { + return interp_error(interp, "interp instr %s", + show_instr(&instr)); + } + if (instr.tag == i_end) { - switch (interp_code_end(interp, frame, code)) { + //cursor_print_around(&frame->code, 10); + switch (ret) { case interp_end_err: return 0; case interp_end_done: return 1; - case interp_end_cont: continue; case interp_end_next: break; } } - if (unlikely(!(ret = interp_instr(interp, &instr)))) { - return interp_error(interp, "interp instr %s", - show_instr(&instr)); - } - - if (ret == i_return) - return 1; } return 1; @@ -5882,7 +5916,7 @@ static int reset_memory(struct wasm_interp *interp) return 1; } -static void setup_wasi(struct wasm_interp *interp, int argc, const char **argv) +void setup_wasi(struct wasm_interp *interp, int argc, const char **argv) { interp->wasi.argc = argc; interp->wasi.argv = argv; @@ -6066,7 +6100,11 @@ int interp_wasm_module(struct wasm_interp *interp) //interp->mem.p = interp->mem.start; - if (call_function(interp, interp->module_inst.start_fn)) { + if (!call_function(interp, interp->module_inst.start_fn)) { + return interp_error(interp, "call start function"); + } + + if (interp_code(interp)) { debug("interp success!!\n"); } else if (interp->quitting) { debug("finished running via process exit\n"); diff --git a/src/wasm.h b/src/wasm.h @@ -685,5 +685,6 @@ void wasm_parser_init(struct wasm_parser *parser, u8 *wasm, size_t wasm_len, siz void wasm_interp_free(struct wasm_interp *interp); int interp_wasm_module(struct wasm_interp *interp); void print_error_backtrace(struct errors *errors); +void setup_wasi(struct wasm_interp *interp, int argc, const char **argv); #endif /* PROTOVERSE_WASM_H */