protoverse

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

commit 7d0b3bff7882cdfe878cf36786110e787241b2eb
parent 98f2f94a107e7f9f84ac7b8fae8e50a8cb1cfbd4
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 18 Jul 2021 16:58:41 -0700

fix locals

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

Diffstat:
Msrc/wasm.c | 136+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/wasm.h | 4++--
2 files changed, 69 insertions(+), 71 deletions(-)

diff --git a/src/wasm.c b/src/wasm.c @@ -81,22 +81,6 @@ static const char *valtype_literal(enum valtype valtype) return "?"; } - -static INLINE struct local *get_locals(struct func *func, int *num_locals) -{ - switch (func->type) { - case func_type_wasm: - *num_locals = func->wasm_func->num_locals; - return func->wasm_func->locals; - case func_type_builtin: - if (func->builtin == NULL) - return NULL; - *num_locals = func->builtin->num_locals; - return func->builtin->locals; - } - return NULL; -} - static INLINE int is_valid_fn_index(struct module *module, int ind) { return ind >= 0 && ind < module->num_funcs; @@ -112,27 +96,19 @@ static INLINE struct func *get_function(struct module *module, int ind) static struct val *get_fn_local(struct wasm_interp *interp, int fn, int ind) { struct func *func; - struct local *locals; - int num_locals; if (unlikely(!(func = get_function(interp->module, fn)))) { interp_error(interp, "unknown fn %d", fn); return NULL; } - if (unlikely(!(locals = get_locals(func, &num_locals)))) { - interp_error(interp, "couldn't find locals for %s", - func->name); - return NULL; - } - - if (unlikely(ind >= num_locals)) { + if (unlikely(ind >= func->num_locals)) { interp_error(interp, "local index %d too high for %s:%d (max %d)", - ind, func->name, fn, num_locals-1); + ind, func->name, fn, func->num_locals-1); return NULL; } - return &locals[ind].val; + return &func->locals[ind].val; } static struct val *get_local(struct wasm_interp *interp, int ind) @@ -339,9 +315,9 @@ static int builtin_proc_exit(struct wasm_interp *interp) } static struct builtin BUILTINS[] = { - { .name = "args_get", .fn = builtin_get_args, .num_locals = 2 }, - { .name = "args_sizes_get", .fn = builtin_get_args_sizes, .num_locals = 2 }, - { .name = "proc_exit", .fn = builtin_proc_exit, .num_locals = 2 }, + { .name = "args_get", .fn = builtin_get_args }, + { .name = "args_sizes_get", .fn = builtin_get_args_sizes }, + { .name = "proc_exit", .fn = builtin_proc_exit }, }; static const int NUM_BUILTINS = sizeof(BUILTINS) / sizeof(*BUILTINS); @@ -1192,10 +1168,10 @@ 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, - struct functype *functype) +static int parse_func(struct wasm_parser *p, struct wasm_func *func) { - unsigned int size, code_locals, i; + unsigned int size; + int i; unsigned char *start; struct local *locals; @@ -1206,12 +1182,10 @@ static int parse_func(struct wasm_parser *p, struct wasm_func *func, start = p->cur.p; locals = (struct local*)p->mem.p; - if (!leb128_read(&p->cur, &code_locals)) { + if (!read_int(&p->cur, &func->num_locals)) { return parse_err(p, "read locals vec"); } - 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"); } @@ -1220,7 +1194,7 @@ static int parse_func(struct wasm_parser *p, struct wasm_func *func, return parse_err(p, "corrupt functype?"); } - for (i = 0; i < code_locals; i++) { + for (i = 0; i < func->num_locals; i++) { if (!parse_local(p, &locals[i])) { return parse_err(p, "local #%d", i); } @@ -1241,28 +1215,6 @@ static int parse_func(struct wasm_parser *p, struct wasm_func *func, 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 : @@ -1274,7 +1226,6 @@ static int parse_code_section(struct wasm_parser *p, struct codesec *code_section) { struct wasm_func *funcs; - struct functype *functype; int i; if (!parse_vector(p, sizeof(*funcs), @@ -1288,14 +1239,7 @@ static int parse_code_section(struct wasm_parser *p, } 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)) { + if (!parse_func(p, &funcs[i])) { return parse_err(p, "func #%d", i); } } @@ -4404,6 +4348,57 @@ void wasm_parser_init(struct wasm_parser *p, u8 *wasm, size_t wasm_len, size_t a cursor_slice(&p->mem, &p->errs.cur, 0xFFFF); } +static int count_fn_locals(struct func *func) +{ + int i, num_locals = 0; + + num_locals += func->functype->params.num_valtypes; + + if (func->type == func_type_wasm) { + for (i = 0; i < func->wasm_func->num_locals; i++) { + num_locals += func->wasm_func->locals->val.i32; + } + } + + return num_locals; +} + +static int calculate_locals_size(struct module *module) +{ + int i, locals_size = 0; + struct func *func; + + for (i = 0; i < module->num_funcs; i++) { + func = &module->funcs[i]; + locals_size += count_fn_locals(func) * sizeof(struct val); + } + + return locals_size; +} + +static int alloc_locals(struct module *module, struct cursor *mem, + struct errors *errs) +{ + int i, num_locals; + struct func *func; + + for (i = 0; i < module->num_funcs; i++) { + func = &module->funcs[i]; + num_locals = count_fn_locals(func); + + func->locals = (struct local*)mem->p; + func->num_locals = num_locals; + + if (!cursor_alloc(mem, num_locals * sizeof(struct val))) { + return note_error(errs, mem, + "could not alloc locals for %s", + func->name); + } + } + + return 1; +} + int wasm_interp_init(struct wasm_interp *interp, struct module *module) { unsigned char *mem, *heap; @@ -4443,6 +4438,7 @@ int wasm_interp_init(struct wasm_interp *interp, struct module *module) callframes_size = sizeof(struct callframe) * 0xFF; resolver_size = sizeof(struct resolver) * MAX_LABELS; globals_size = sizeof(struct val) * num_globals; + locals_size = calculate_locals_size(module); global_init_size = num_globals; if (num_mems > 1) { @@ -4466,6 +4462,7 @@ int wasm_interp_init(struct wasm_interp *interp, struct module *module) callframes_size + globals_size + global_init_size + + locals_size + resolver_size; mem = calloc(1, memsize); @@ -4487,7 +4484,8 @@ int wasm_interp_init(struct wasm_interp *interp, struct module *module) cursor_slice(&interp->mem, &interp->globals, globals_size) && cursor_slice(&interp->mem, &interp->global_init, global_init_size) && array_alloc(&interp->mem, &interp->labels, labels_capacity) && - array_alloc(&interp->mem, &interp->num_labels, fns); + array_alloc(&interp->mem, &interp->num_labels, fns) && + alloc_locals(interp->module, &interp->mem, &interp->errors); /* init memory pages */ assert((interp->mem.end - interp->mem.start) == memsize); diff --git a/src/wasm.h b/src/wasm.h @@ -215,6 +215,8 @@ struct func { struct wasm_func *wasm_func; struct builtin *builtin; }; + struct local *locals; + int num_locals; struct functype *functype; enum func_type type; const char *name; @@ -596,8 +598,6 @@ struct wasm_interp { struct builtin { const char *name; - struct local locals[8]; - int num_locals; int (*fn)(struct wasm_interp *); int (*prepare_args)(struct wasm_interp *); };