protoverse

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

commit 78e56aa88a5ce28025eb1399284aa6019dc69807
parent 326cd090d6e82df46502c626a56e7c9439a4d18e
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 16 Jul 2021 22:12:25 -0700

make room for param locals

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Msrc/wasm.c | 166++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 114 insertions(+), 52 deletions(-)

diff --git a/src/wasm.c b/src/wasm.c @@ -87,20 +87,14 @@ static INLINE struct func *get_function(struct module *module, int ind) return &module->funcs[ind]; } -static struct val *get_local(struct wasm_interp *interp, int ind) +static struct val *get_fn_local(struct wasm_interp *interp, int fn, int ind) { - struct callframe *frame; struct func *func; struct local *locals; int num_locals; - if (unlikely(!(frame = top_callframe(&interp->callframes)))) { - interp_error(interp, "no callframe?"); - return NULL; - } - - if (unlikely(!(func = get_function(interp->module, frame->fn)))) { - interp_error(interp, "unknown fn %d", frame->fn); + if (unlikely(!(func = get_function(interp->module, fn)))) { + interp_error(interp, "unknown fn %d", fn); return NULL; } @@ -119,6 +113,18 @@ static struct val *get_local(struct wasm_interp *interp, int ind) return &locals[ind].val; } +static struct val *get_local(struct wasm_interp *interp, int ind) +{ + struct callframe *frame; + + if (unlikely(!(frame = top_callframe(&interp->callframes)))) { + interp_error(interp, "no callframe?"); + return NULL; + } + + return get_fn_local(interp, frame->fn, ind); +} + static INLINE int stack_popval(struct wasm_interp *interp, struct val *val) { return cursor_popval(&interp->stack, val); @@ -839,8 +845,9 @@ static int parse_valtype(struct wasm_parser *p, enum valtype *valtype) } if (unlikely(!is_valtype((unsigned char)*valtype))) { + cursor_print_around(&p->cur, 10); p->cur.p = start; - return parse_err(p, "%c is not a valid valtype tag", *valtype); + return parse_err(p, "0x%02x is not a valid valtype tag", *valtype); } return 1; @@ -970,13 +977,13 @@ static int parse_export(struct wasm_parser *p, struct wexport *export) static int parse_local(struct wasm_parser *p, struct local *local) { if (unlikely(!leb128_read(&p->cur, (unsigned int*)&local->val.i32))) { - parse_err(p, "n"); - return 0; + debug("fail parse local\n"); + return parse_err(p, "n"); } if (unlikely(!parse_valtype(p, &local->val.type))) { - parse_err(p, "valtype"); - return 0; + debug("fail parse valtype\n"); + return parse_err(p, "valtype"); } return 1; @@ -1000,68 +1007,114 @@ static int parse_vector(struct wasm_parser *p, unsigned int item_size, return 1; } -static int parse_func(struct wasm_parser *p, struct wasm_func *func) +static int parse_func(struct wasm_parser *p, struct wasm_func *func, + struct functype *functype) { - unsigned int elems, size, i; + unsigned int size, code_locals, i; unsigned char *start; struct local *locals; if (!leb128_read(&p->cur, &size)) { - parse_err(p, "code size"); - return 0; + return parse_err(p, "code size"); } start = p->cur.p; + locals = (struct local*)p->mem.p; - if (!parse_vector(p, sizeof(*locals), &elems, (void**)&locals)) { - parse_err(p, "locals"); - return 0; + if (!leb128_read(&p->cur, &code_locals)) { + return parse_err(p, "read locals vec"); } - for (i = 0; i < elems; i++) { + func->num_locals = functype->params.num_valtypes + code_locals; + + if (!cursor_alloc(&p->mem, sizeof(*locals) * func->num_locals)) { + return parse_err(p, "oom alloc param locals"); + } + + if (p->cur.p > p->cur.end) { + return parse_err(p, "corrupt functype?"); + } + + for (i = 0; i < code_locals; i++) { if (!parse_local(p, &locals[i])) { - parse_err(p, "local #%d", i); - return 0; + return parse_err(p, "local #%d", i); } } func->locals = locals; - func->num_locals = elems; func->code.code_len = size - (p->cur.p - start); if (!pull_data_into_cursor(&p->cur, &p->mem, &func->code.code, func->code.code_len)) { - parse_err(p, "code oom"); - return 0; + return parse_err(p, "code oom"); } if (!(func->code.code[func->code.code_len-1] == i_end)) { - parse_err(p, "no end tag (corruption?)"); - return 0; + return parse_err(p, "no end tag (corruption?)"); } return 1; } +/* this is needed in the parsing phase when we haven't built a function map yet */ +static struct functype *get_code_function_type(struct module *module, int code_ind) +{ + int typeidx; + + if (code_ind < 0 || code_ind >= module->func_section.num_indices) { + printf("UNUSUAL: func index oob %d of %d\n", code_ind, + module->code_section.num_funcs); + return 0; + } + + typeidx = module->func_section.type_indices[code_ind]; + + if (typeidx < 0 || typeidx >= module->type_section.num_functypes) { + printf("UNUSUAL: type index oob %d of %d\n", typeidx, + module->type_section.num_functypes); + return 0; + } + + return &module->type_section.functypes[typeidx]; +} + +static INLINE int count_internal_functions(struct module *module) +{ + return !was_section_parsed(module, section_code) ? 0 : + module->code_section.num_funcs; +} + + static int parse_code_section(struct wasm_parser *p, struct codesec *code_section) { struct wasm_func *funcs; - unsigned int elems, i; + struct functype *functype; + int i; - if (!parse_vector(p, sizeof(*funcs), &elems, (void**)&funcs)) { - parse_err(p, "funcs"); - return 0; + if (!parse_vector(p, sizeof(*funcs), + (unsigned int*)&code_section->num_funcs, + (void**)&funcs)) { + return parse_err(p, "funcs"); } - for (i = 0; i < elems; i++) { - if (!parse_func(p, &funcs[i])) { - parse_err(p, "func #%d", i); - return 0; + if (code_section->num_funcs < 0) { + return parse_err(p, "code_section num_funcs < 0"); + } + + for (i = 0; i < code_section->num_funcs; i++) { + if (unlikely(!(functype = + get_code_function_type(&p->module, i)))) { + return parse_err(p, + "couldn't get code func type %d of %d", + i, p->module.code_section.num_funcs); + } + + if (!parse_func(p, &funcs[i], functype)) { + return parse_err(p, "func #%d", i); } } - code_section->num_funcs = elems; code_section->funcs = funcs; return 1; @@ -1307,7 +1360,7 @@ static int parse_const_expr(struct expr_parser *p, struct expr *expr) instr_name(tag)); } - if (p->stack && + if (p->stack && unlikely(!eval_const_instr(&instr, p->errs, p->stack))) { return note_error(p->errs, p->code, "eval const instr"); } @@ -1958,13 +2011,11 @@ static int parse_section(struct wasm_parser *p) } if (!leb128_read(&p->cur, &bytes)) { - parse_err(p, "section len"); - return 0; + return parse_err(p, "section len"); } if (!parse_section_by_tag(p, tag, bytes)) { - parse_err(p, "%s (%d bytes)", section_name(tag), bytes); - return 0; + return parse_err(p, "%s (%d bytes)", section_name(tag), bytes); } p->module.parsed |= 1 << tag; @@ -1987,12 +2038,6 @@ static struct builtin *builtin_func(int ind) return &BUILTINS[ind]; } -static INLINE int count_internal_functions(struct module *module) -{ - return !was_section_parsed(module, section_code) ? 0 : - module->code_section.num_funcs; -} - static const char *find_exported_function_name(struct module *module, int fn) { int i; @@ -2065,6 +2110,8 @@ static int make_func_lookup_table(struct wasm_parser *parser) func->wasm_func = &parser->module.code_section.funcs[i]; func->functype = &parser->module.type_section.functypes[typeidx]; func->name = find_exported_function_name(&parser->module, fn); + debug("func %s, %d params\n", func->name, + func->functype->params.num_valtypes); } assert(fn == parser->module.num_funcs); @@ -2163,11 +2210,12 @@ static int interp_i32_sub(struct wasm_interp *interp) return stack_pushval(interp, &c); } -static int set_local(struct wasm_interp *interp, int ind, struct val *val) +static INLINE int set_fn_local(struct wasm_interp *interp, int fn, int ind, + struct val *val) { struct val *local; - if (unlikely(!(local = get_local(interp, ind)))) { + if (unlikely(!(local = get_fn_local(interp, fn, ind)))) { return interp_error(interp, "no local?"); } @@ -2175,6 +2223,18 @@ static int set_local(struct wasm_interp *interp, int ind, struct val *val) return 1; } +static INLINE int set_local(struct wasm_interp *interp, int ind, + struct val *val) +{ + struct callframe *frame; + + if (unlikely(!(frame = top_callframe(&interp->callframes)))) { + return interp_error(interp, "no callframe?"); + } + + return set_fn_local(interp, frame->fn, ind, val); +} + static int interp_local_tee(struct wasm_interp *interp) { struct val *val; @@ -2406,7 +2466,7 @@ static int prepare_call(struct wasm_interp *interp, int func_index) valtype_name(paramtype)); } - if (unlikely(!set_local(interp, i, &val))) { + if (unlikely(!set_fn_local(interp, func_index, i, &val))) { return interp_error(interp, "set param local %d", i); } } @@ -3239,6 +3299,8 @@ void wasm_parser_init(struct wasm_parser *p, u8 *wasm, size_t wasm_len, size_t a make_cursor(wasm, wasm + wasm_len, &p->cur); make_cursor(mem, mem + arena_size, &p->mem); + p->errs.enabled = 1; + cursor_slice(&p->mem, &p->errs.cur, 0xFFFF); }