protoverse

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

commit ec9e6662287ed9f6d301d5e7b7bc73fa56e0c6f5
parent 4f5a16fbb02d5e378f028a7715e5d309930d2871
Author: William Casarin <jb55@jb55.com>
Date:   Sat,  3 Jun 2023 09:26:13 -0700

wasm updates from damus

Diffstat:
MMakefile | 11+++++++----
Msrc/bench.c | 2+-
Msrc/wasm.c | 220++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/wasm.h | 70+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
4 files changed, 180 insertions(+), 123 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,5 +1,5 @@ -CFLAGS = -O2 -g -std=gnu90 -Wall -Wextra -Werror \ +CFLAGS = -O0 -g -std=gnu90 -Wall -Wextra \ -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes \ -Wmissing-declarations -Wdeclaration-after-statement -fno-stack-protector \ -Wno-unused-function @@ -18,10 +18,10 @@ OBJS = src/io.o \ SRCS=$(OBJS:.o=.c) -WASMS = wasm/hello-c.wasm \ - wasm/hello.wasm +WASMS = wasm/hello.wasm \ + wasm/primal.wasm -all: protoverse bench test libprotoverse.a +all: protoverse bench test libprotoverse.a wasm noinline: CFLAGS += -DNOINLINE noinline: all @@ -41,6 +41,9 @@ wasm: $(WASMS) %.c.wasm: %.wasm.c emcc -g $< -s WASM=1 -o $@ +wasm/primal.wasm: wasm/primal.ts wasm/nostr.ts + asc $< --outFile $@ + wasm/hello-c.wasm: wasm/hello-c.c emcc -g $< -s WASM=1 -o $@ diff --git a/src/bench.c b/src/bench.c @@ -16,7 +16,7 @@ static int bench_wasm(unsigned char *wasm, unsigned long len, int times, int retval; long nanos, ms; - wasm_parser_init(&p, wasm, len, len*16); + wasm_parser_init(&p, wasm, len, len*16, 0, 0); if (!parse_wasm(&p)) { return 0; diff --git a/src/wasm.c b/src/wasm.c @@ -15,14 +15,6 @@ #include <stdint.h> #include <inttypes.h> -#define interp_error(p, fmt, ...) note_error(&((p)->errors), interp_codeptr(p), fmt, ##__VA_ARGS__) -#define parse_err(p, fmt, ...) note_error(&((p)->errs), &(p)->cur, fmt, ##__VA_ARGS__) - -#ifdef NOINLINE - #define INLINE __attribute__((noinline)) -#else - #define INLINE inline -#endif #define ERR_STACK_SIZE 16 #define NUM_LOCALS 0xFFFF @@ -46,19 +38,6 @@ static INLINE struct callframe *top_callframes(struct cursor *cur, int top) return (struct callframe*)cursor_topn(cur, sizeof(struct callframe), top); } -static INLINE struct callframe *top_callframe(struct cursor *cur) -{ - return (struct callframe*)cursor_top(cur, sizeof(struct callframe)); -} - -static INLINE struct cursor *interp_codeptr(struct wasm_interp *interp) -{ - struct callframe *frame; - if (unlikely(!(frame = top_callframe(&interp->callframes)))) - return 0; - return &frame->code; -} - static INLINE int cursor_popval(struct cursor *cur, struct val *val) { return cursor_pop(cur, (unsigned char*)val, sizeof(*val)); @@ -110,7 +89,7 @@ static INLINE struct func *get_fn(struct module *module, u32 ind) return &module->funcs[ind]; } -static INLINE u8 *mem_ptr(struct wasm_interp *interp, u32 ptr, int size) +u8 *interp_mem_ptr(struct wasm_interp *interp, u32 ptr, int size) { u8 *pos = interp->memory.start + ptr; @@ -132,7 +111,7 @@ static INLINE int read_mem(struct wasm_interp *interp, u32 ptr, int size, void *dest) { u8 *mem; - if (!(mem = mem_ptr(interp, ptr, size))) + if (!(mem = interp_mem_ptr(interp, ptr, size))) return interp_error(interp, "invalid mem pointer"); memcpy(dest, mem, size); return 1; @@ -145,43 +124,33 @@ static INLINE int read_mem_u32(struct wasm_interp *interp, u32 ptr, u32 *i) static INLINE int mem_ptr_i32(struct wasm_interp *interp, u32 ptr, int **i) { - if (!(*i = (int*)mem_ptr(interp, ptr, sizeof(int)))) + if (!(*i = (int*)interp_mem_ptr(interp, ptr, sizeof(int)))) return interp_error(interp, "int memptr"); return 1; } static INLINE int mem_ptr_f32(struct wasm_interp *interp, u32 ptr, float **i) { - if (!(*i = (float*)mem_ptr(interp, ptr, sizeof(float)))) + if (!(*i = (float*)interp_mem_ptr(interp, ptr, sizeof(float)))) return interp_error(interp, "int memptr"); return 1; } static INLINE int mem_ptr_u32(struct wasm_interp *interp, u32 ptr, u32 **i) { - if (!(*i = (u32*)mem_ptr(interp, ptr, sizeof(int)))) + if (!(*i = (u32*)interp_mem_ptr(interp, ptr, sizeof(int)))) return interp_error(interp, "uint memptr"); return 1; } static INLINE int mem_ptr_u32_arr(struct wasm_interp *interp, u32 ptr, int n, u32 **i) { - if (!(*i = (u32*)mem_ptr(interp, ptr, n * sizeof(int)))) + if (!(*i = (u32*)interp_mem_ptr(interp, ptr, n * sizeof(int)))) return interp_error(interp, "uint memptr"); return 1; } -static INLINE int mem_ptr_str(struct wasm_interp *interp, u32 ptr, - const char **str) -{ - // still technically unsafe if the string runs over the end of memory... - if (!(*str = (const char*)mem_ptr(interp, ptr, 1))) { - return interp_error(interp, "int memptr"); - } - return 1; -} - static INLINE int read_mem_i32(struct wasm_interp *interp, u32 ptr, int *i) { return read_mem(interp, ptr, sizeof(*i), i); @@ -206,8 +175,7 @@ static INLINE struct val *get_local(struct wasm_interp *interp, u32 ind) return &frame->locals[ind]; } -static INLINE int get_params(struct wasm_interp *interp, struct val** vals, - u32 num_vals) +int get_params(struct wasm_interp *interp, struct val** vals, u32 num_vals) { struct callframe *frame; @@ -452,6 +420,33 @@ static INLINE int cursor_push_i32(struct cursor *stack, int i) return cursor_pushval(stack, &val); } +static INLINE int cursor_push_i64(struct cursor *stack, s64 i) +{ + struct val val; + val.type = val_i64; + val.num.i64 = i; + + return cursor_pushval(stack, &val); +} + +static INLINE int cursor_push_f32(struct cursor *stack, float f) +{ + struct val val; + val.type = val_f32; + val.num.f32 = f; + + return cursor_pushval(stack, &val); +} + +static INLINE int cursor_push_f64(struct cursor *stack, double f) +{ + struct val val; + val.type = val_f64; + val.num.f64 = f; + + return cursor_pushval(stack, &val); +} + static INLINE int cursor_push_u64(struct cursor *stack, u64 i) { struct val val; @@ -554,20 +549,6 @@ static int wasi_fd_close(struct wasm_interp *interp); static int wasi_environ_sizes_get(struct wasm_interp *interp); static int wasi_environ_get(struct wasm_interp *interp); -static struct builtin BUILTINS[] = { - { .name = "null", .fn = NULL }, // for reasons - { .name = "args_get", .fn = wasi_args_get }, - { .name = "fd_write", .fn = wasi_fd_write }, - { .name = "fd_close", .fn = wasi_fd_close }, - { .name = "environ_sizes_get", .fn = wasi_environ_sizes_get }, - { .name = "environ_get", .fn = wasi_environ_get }, - { .name = "args_sizes_get", .fn = wasi_args_sizes_get }, - { .name = "proc_exit", .fn = wasi_proc_exit }, - { .name = "abort", .fn = wasi_abort }, -}; - -static const int NUM_BUILTINS = sizeof(BUILTINS) / sizeof(*BUILTINS); - static int parse_instr(struct expr_parser *parser, u8 tag, struct instr *op); static INLINE int is_valtype(unsigned char byte) @@ -802,7 +783,7 @@ static INLINE int was_section_parsed(struct module *module, if (section == section_custom) return module->custom_sections > 0; - return module->parsed & (1 << section); + return module->parsed & (1 << section); } static INLINE int was_name_section_parsed(struct module *module, @@ -812,7 +793,7 @@ static INLINE int was_name_section_parsed(struct module *module, return 0; } - return module->name_section.parsed & (1 << subsection); + return module->name_section.parsed & (1 << subsection); } //static int callframe_cnt = 0; @@ -825,7 +806,7 @@ static INLINE int cursor_push_callframe(struct cursor *cur, struct callframe *fr static INLINE int count_resolvers(struct wasm_interp *interp) { - return cursor_count(&interp->resolver_stack, sizeof(struct resolver)); + return (int)cursor_count(&interp->resolver_stack, sizeof(struct resolver)); } static INLINE int push_callframe(struct wasm_interp *interp, struct callframe *frame) @@ -1524,7 +1505,7 @@ static int parse_vector(struct wasm_parser *p, int item_size, *items = cursor_alloc(&p->mem, *elems * item_size); if (*items == NULL) { - parse_err(p, "vector alloc oom"); + parse_err(p, "vector alloc oom. item_size:%d elems:%d", item_size, *elems); return 0; } @@ -1666,7 +1647,7 @@ static int parse_func(struct wasm_parser *p, struct wasm_func *func) } func->local_defs = defs; - func->code.code_len = size - (p->cur.p - start); + func->code.code_len = (int)(size - (p->cur.p - start)); if (!pull_data_into_cursor(&p->cur, &p->mem, &func->code.code, func->code.code_len)) { @@ -1687,8 +1668,7 @@ static INLINE int count_internal_functions(struct module *module) } -static int parse_code_section(struct wasm_parser *p, - struct codesec *code_section) +static int parse_code_section(struct wasm_parser *p, struct codesec *code_section) { struct wasm_func *funcs; u32 i; @@ -1914,7 +1894,7 @@ static const char *show_instr(struct instr *instr) make_cursor((u8*)buffer, (u8*)buffer + sizeof(buffer) - 1, &buf); cursor_push_str(&buf, instr_name(instr->tag)); - len = buf.p - buf.start; + len = (int)(buf.p - buf.start); for (i = 0; i < 14-len; i++) cursor_push_byte(&buf, ' '); @@ -2182,13 +2162,25 @@ static int eval_const_instr(struct instr *instr, struct errors *errs, } return 1; case ci_const_i64: - return note_error(errs, stack, "todo: global push const i64"); + if (unlikely(!cursor_push_i64(stack, instr->i64))) { + return note_error(errs, stack, + "global push i64 const"); + } + return 1; case ci_const_f32: - return note_error(errs, stack, "todo: global push const f32"); + if (unlikely(!cursor_push_f32(stack, instr->f32))) { + return note_error(errs, stack, + "global push f32 const"); + } + return 1; case ci_end: return note_error(errs, stack, "unexpected end tag"); case ci_const_f64: - return note_error(errs, stack, "todo: global push const f64"); + if (unlikely(!cursor_push_f64(stack, instr->f64))) { + return note_error(errs, stack, + "global push f64 const"); + } + return 1; } return note_error(errs, stack, "non-const expr instr %s", @@ -2214,7 +2206,7 @@ static int parse_const_expr(struct expr_parser *p, struct expr *expr) } if (tag == i_end) { - expr->code_len = p->code->p - expr->code; + expr->code_len = (int)(p->code->p - expr->code); return 1; } @@ -2371,7 +2363,7 @@ static int parse_instrs_until_at(struct expr_parser *p, u8 stop_instr, if ((tag != i_if && tag == stop_instr) || (stop_instr == i_if && (tag == i_else || tag == i_end))) { //debug("parse_instrs_until ending\n"); - expr->code_len = p->code->p - expr->code; + expr->code_len = (int)(p->code->p - expr->code); *stopped_at = tag; @@ -2431,7 +2423,7 @@ static int parse_elem_func_inits(struct wasm_parser *p, struct elem *elem) if (!cursor_push_byte(&p->mem, i_end)) return parse_err(p, "push i_end for init %d", i); - expr->code_len = p->mem.p - expr->code; + expr->code_len = (int)(p->mem.p - expr->code); } return 1; @@ -2487,7 +2479,7 @@ static int parse_custom_section(struct wasm_parser *p, u32 size, return parse_err(p, "name"); section->data = p->cur.p; - section->data_len = size - (p->cur.p - start); + section->data_len = (int)(size - (p->cur.p - start)); debug("custom sec minus %ld\n", p->cur.p - start); @@ -2773,13 +2765,13 @@ static int parse_importdesc(struct wasm_parser *p, struct importdesc *desc) return 0; } -static int find_builtin(const char *name) +static int find_builtin(struct builtin *builtins, int num_builtins, const char *name) { struct builtin *b; u32 i; - for (i = 0; i < NUM_BUILTINS; i++) { - b = &BUILTINS[i]; + for (i = 0; i < num_builtins; i++) { + b = &builtins[i]; if (!strcmp(b->name, name)) return i; } @@ -2801,7 +2793,7 @@ static int parse_import(struct wasm_parser *p, struct import *import) if (import->desc.type == import_func) { import->resolved_builtin = - find_builtin(import->name); + find_builtin(p->builtins, p->num_builtins, import->name); } return 1; @@ -2992,14 +2984,14 @@ static int parse_section(struct wasm_parser *p) return 1; } -static struct builtin *builtin_func(u32 ind) +static struct builtin *builtin_func(struct builtin *builtins, u32 num_builtins, u32 ind) { - if (unlikely(ind >= NUM_BUILTINS)) { + if (unlikely(ind >= num_builtins)) { printf("UNUSUAL: invalid builtin index %d (max %d)\n", ind, - NUM_BUILTINS-1); + num_builtins-1); return NULL; } - return &BUILTINS[ind]; + return &builtins[ind]; } static const char *find_exported_function_name(struct module *module, u32 fn) @@ -3107,6 +3099,7 @@ static int make_func_lookup_table(struct wasm_parser *parser) /* imports */ num_imports = count_imports(&parser->module, NULL); + debug("num_imports %d\n", num_imports); for (i = 0; i < num_imports; i++) { import = &imports->imports[i]; @@ -3120,7 +3113,7 @@ static int make_func_lookup_table(struct wasm_parser *parser) debug("warning: %s not resolved\n", func->name); builtin = NULL; } else { - builtin = builtin_func(import->resolved_builtin); + builtin = builtin_func(parser->builtins, parser->num_builtins, import->resolved_builtin); } make_builtin_func( @@ -3746,14 +3739,14 @@ static INLINE int count_local_resolvers(struct wasm_interp *interp, int *count) p >= interp->resolver_stack.end)) { return interp_error(interp, "resolver offset oob?"); } - *count = (interp->resolver_stack.p - p) / sizeof(struct resolver); + *count = (int)((interp->resolver_stack.p - p) / sizeof(struct resolver)); //debug("offset %d count %d stack.p - p %ld\n", offset, *count, interp->resolver_stack.p - p); return 1; } static INLINE u32 count_stack_vals(struct cursor *stack) { - return cursor_count(stack, sizeof(struct val)); + return (u32)cursor_count(stack, sizeof(struct val)); } static INLINE int drop_callframe_return(struct wasm_interp *interp, int returning) @@ -3993,7 +3986,7 @@ static INLINE int call_builtin_func(struct wasm_interp *interp, struct func *fun { struct callframe callframe = {}; struct val *locals; - int prev_items; + int prev_items, res; if (!prepare_call(interp, func, &locals, &prev_items)) return interp_error(interp, "prepare args"); @@ -4006,13 +3999,14 @@ static INLINE int call_builtin_func(struct wasm_interp *interp, struct func *fun if (unlikely(!push_callframe(interp, &callframe))) return interp_error(interp, "oob cursor_pushcode"); - if (!func->builtin->fn(interp)) + res = func->builtin->fn(interp); + if (!res) return interp_error(interp, "builtin trap"); if (unlikely(!drop_callframe(interp))) return interp_error(interp, "pop callframe"); - return 1; + return res; } static INLINE int call_func(struct wasm_interp *interp, struct func *func) @@ -4058,7 +4052,8 @@ static int interp_call(struct wasm_interp *interp, int func_index) memcpy(&prev_frame, top_callframe(&interp->callframes), sizeof(struct callframe)); #endif - if (unlikely(!call_function(interp, func_index))) + int res = call_function(interp, func_index); + if (unlikely(!res)) return 0; /* @@ -4069,7 +4064,7 @@ static int interp_call(struct wasm_interp *interp, int func_index) prev_frame.fn); */ - return 1; + return res; } static int interp_call_indirect(struct wasm_interp *interp, struct call_indirect *call) @@ -4129,8 +4124,8 @@ static int interp_call_indirect(struct wasm_interp *interp, struct call_indirect // HACKY special case for indirect host builtins i = -((int)ref->addr); - if (-i < 0 && i < NUM_BUILTINS) { - builtin = &BUILTINS[i]; + if (-i < 0 && i < interp->num_builtins ) { + builtin = &interp->builtins[i]; make_builtin_func(&pfunc, builtin->name, type, builtin, -i); debug("calling indirect builtin %s\n", pfunc.name); return call_builtin_func(interp, &pfunc); @@ -4139,9 +4134,7 @@ static int interp_call_indirect(struct wasm_interp *interp, struct call_indirect func = &interp->module->funcs[ref->addr]; if (func->functype != type) { - ftidx = (func->functype - - interp->module->type_section.functypes - ) / sizeof(struct functype); + ftidx = (int)((func->functype - interp->module->type_section.functypes ) / sizeof(struct functype)); return interp_error(interp, "functype mismatch, expected %d `%s`, got %d `%s`", @@ -4217,7 +4210,7 @@ static INLINE int resolve_label(struct label *label, struct cursor *code) return 1; } - label->jump = code->p - code->start; + label->jump = (u32)(code->p - code->start); label->instr_pos |= 0x80000000; /* @@ -4402,7 +4395,7 @@ static int push_label_checkpoint(struct wasm_interp *interp, struct label **labe return interp_error(interp, "invalid fn index?"); } - instr_pos = frame->code.p - frame->code.start; + instr_pos = (int)(frame->code.p - frame->code.start); if (unlikely(!upsert_label(interp, frame->func->idx, instr_pos, &ind))) { return interp_error(interp, "upsert label"); } @@ -4556,6 +4549,7 @@ static int pop_label_and_break(struct wasm_interp *interp, int times) if (unlikely(times == 0)) return interp_error(interp, "can't pop label 0 times"); + label = NULL; for (i = 0; i < times; i++) { if (!pop_label(interp, &resolver, &frame, &label)) { return interp_error(interp, "pop resolver"); @@ -4581,7 +4575,7 @@ static int parse_block_instrs_at(struct expr_parser *p, debug("label is resolved, skipping block parse\n"); // TODO verify this is correct exprs->code = p->code->start + label_instr_pos(label); - exprs->code_len = (p->code->start + label->jump) - exprs->code; + exprs->code_len = (int)((p->code->start + label->jump) - exprs->code); return pop_label_and_skip(p->interp, label, 1); } @@ -4786,7 +4780,7 @@ static int parse_if(struct expr_parser *p, struct block *block) static int parse_instr(struct expr_parser *p, u8 tag, struct instr *op) { - op->pos = p->code->p - 1 - p->code->start; + op->pos = (int)(p->code->p - 1 - p->code->start); op->tag = tag; switch ((enum instr_tag)tag) { @@ -5577,6 +5571,7 @@ static INLINE int load_i32(struct wasm_interp *interp, int addr, int *i) return stack_pop_i32(interp, i); } +/* static int wasi_fd_close(struct wasm_interp *interp) { struct val *params = NULL; @@ -5638,10 +5633,7 @@ static int wasi_fd_write(struct wasm_interp *interp) str_len, interp->memory.start + iovec_data); - wrote = write(fd->num.i32, - interp->memory.start + iovec_data, - str_len - ); + wrote = (int)write(fd->num.i32, interp->memory.start + iovec_data, str_len ); all += wrote; @@ -5675,11 +5667,11 @@ static int wasi_get_strs(struct wasm_interp *interp, int count, const char **str for (i = 0; i < count; i++) { if (!store_i32(interp, argv->num.i32 + i*4, - writer.p - interp->memory.start)) { + (int)(writer.p - interp->memory.start))) { return interp_error(interp, "store argv %d ptr\n", i); } - len = strlen(strs[i]) + 1; + len = (int)strlen(strs[i]) + 1; // debug("get_str %d '%.*s'\n", i, len, strs[i]); @@ -5739,6 +5731,7 @@ static int wasi_environ_sizes_get(struct wasm_interp *interp) return wasi_strs_sizes_get(interp, interp->wasi.environc, interp->wasi.environ); } + */ static int interp_store(struct wasm_interp *interp, struct memarg *memarg, @@ -5778,7 +5771,7 @@ static INLINE int interp_global_set(struct wasm_interp *interp, int global_ind) static INLINE int active_pages(struct wasm_interp *interp) { - return cursor_count(&interp->memory, WASM_PAGE_SIZE); + return (int)cursor_count(&interp->memory, WASM_PAGE_SIZE); } static int interp_memory_grow(struct wasm_interp *interp, u8 memidx) @@ -5995,7 +5988,7 @@ static int interp_extend(struct wasm_interp *interp, enum valtype to, val->num.i64 = i64; break; case val_i64: - i32 = val->num.i64; + i32 = (int)val->num.i64; val->num.i32 = i32; break; default: @@ -6076,10 +6069,10 @@ static int interp_memory_copy(struct wasm_interp *interp) if (unlikely(!stack_pop_i32(interp, &dest))) return interp_error(interp, "destination"); - if (!(data_dest = mem_ptr(interp, dest, size))) + if (!(data_dest = interp_mem_ptr(interp, dest, size))) return interp_error(interp, "memory copy dest out of bounds"); - if (!(data_src = mem_ptr(interp, src, size))) + if (!(data_src = interp_mem_ptr(interp, src, size))) return interp_error(interp, "memory copy src out of bounds"); debug("memory.copy src:%d dst:%d size:%d\n", @@ -6104,7 +6097,7 @@ static int interp_memory_fill(struct wasm_interp *interp) if (unlikely(!stack_pop_i32(interp, &dest))) return interp_error(interp, "destination"); - if (!(data = mem_ptr(interp, dest, size))) + if (!(data = interp_mem_ptr(interp, dest, size))) return interp_error(interp, "memory fill out of bounds"); debug("memory.fill dst:%d byte:%d size:%d\n", @@ -6543,7 +6536,7 @@ static INLINE int interp_parse_instr(struct wasm_interp *interp, instr->tag = tag; - instr->pos = code->p - 1 - code->start; + instr->pos = (int)(code->p - 1 - code->start); if (is_control_instr(tag)) { return 1; @@ -6601,6 +6594,8 @@ static int interp_code(struct wasm_interp *interp) } } + if (ret == BUILTIN_SUSPEND) + return BUILTIN_SUSPEND; } return 1; @@ -6637,7 +6632,7 @@ static int find_start_function(struct module *module) return find_function(module, "start"); } -void wasm_parser_init(struct wasm_parser *p, u8 *wasm, size_t wasm_len, size_t arena_size) +void wasm_parser_init(struct wasm_parser *p, u8 *wasm, size_t wasm_len, size_t arena_size, struct builtin *builtins, int num_builtins) { u8 *mem; @@ -6648,6 +6643,10 @@ void wasm_parser_init(struct wasm_parser *p, u8 *wasm, size_t wasm_len, size_t a make_cursor(mem, mem + arena_size, &p->mem); p->errs.enabled = 1; + p->num_builtins = 0; + + p->builtins = builtins; + p->num_builtins = num_builtins; cursor_slice(&p->mem, &p->errs.cur, 0xFFFF); } @@ -7211,13 +7210,16 @@ int interp_wasm_module(struct wasm_interp *interp, int *retval) return interp_error(interp, "call start function"); } - if (interp_code(interp)) { + int res = interp_code(interp); + if (res == 1) { stack_pop_i32(interp, retval); debug("interp success!!\n"); } else if (interp->quitting) { stack_pop_i32(interp, retval); debug("process exited\n"); - } else { + } else if (res == BUILTIN_SUSPEND) { + return BUILTIN_SUSPEND; + } else { *retval = 8; return interp_error(interp, "interp_code"); } @@ -7232,7 +7234,7 @@ int run_wasm(unsigned char *wasm, unsigned long len, struct wasm_parser p; struct wasm_interp interp; - wasm_parser_init(&p, wasm, len, len * 16); + wasm_parser_init(&p, wasm, len, len * 16, 0, 0); if (!parse_wasm(&p)) { wasm_parser_free(&p); diff --git a/src/wasm.h b/src/wasm.h @@ -8,12 +8,25 @@ static const unsigned char WASM_MAGIC[] = {0,'a','s','m'}; #define MAX_U32_LEB128_BYTES 5 #define MAX_U64_LEB128_BYTES 10 #define MAX_CUSTOM_SECTIONS 32 +#define MAX_BUILTINS 64 +#define BUILTIN_SUSPEND 42 #define FUNC_TYPE_TAG 0x60 + #include "cursor.h" #include "error.h" +#ifdef NOINLINE + #define INLINE __attribute__((noinline)) +#else + #define INLINE inline +#endif + + +#define interp_error(p, fmt, ...) note_error(&((p)->errors), interp_codeptr(p), fmt, ##__VA_ARGS__) +#define parse_err(p, fmt, ...) note_error(&((p)->errs), &(p)->cur, fmt, ##__VA_ARGS__) + enum valtype { val_i32 = 0x7F, val_i64 = 0x7E, @@ -296,7 +309,7 @@ struct namesec { int parsed; }; -struct section { +struct wsection { enum section_tag tag; }; @@ -640,6 +653,7 @@ struct module { unsigned int custom_sections; struct func *funcs; + u32 num_funcs; struct customsec custom_section[MAX_CUSTOM_SECTIONS]; @@ -701,11 +715,23 @@ struct wasi { const char **environ; }; +struct wasm_interp; + +struct builtin { + const char *name; + int (*fn)(struct wasm_interp *); + int (*prepare_args)(struct wasm_interp *); +}; + struct wasm_interp { struct module *module; struct module_inst module_inst; struct wasi wasi; - + void *context; + + struct builtin builtins[MAX_BUILTINS]; + int num_builtins; + int prev_resolvers, quitting; struct errors errors; /* struct error */ @@ -728,14 +754,10 @@ struct wasm_interp { struct cursor resolver_offsets; /* int */ }; -struct builtin { - const char *name; - int (*fn)(struct wasm_interp *); - int (*prepare_args)(struct wasm_interp *); -}; - struct wasm_parser { struct module module; + struct builtin *builtins; + u32 num_builtins; struct cursor cur; struct cursor mem; struct errors errs; @@ -746,11 +768,41 @@ int run_wasm(unsigned char *wasm, unsigned long len, int argc, const char **argv int parse_wasm(struct wasm_parser *p); int wasm_interp_init(struct wasm_interp *interp, struct module *module); void wasm_parser_free(struct wasm_parser *parser); -void wasm_parser_init(struct wasm_parser *parser, u8 *wasm, size_t wasm_len, size_t arena_size); +void wasm_parser_init(struct wasm_parser *p, u8 *wasm, size_t wasm_len, size_t arena_size, struct builtin *, int num_builtins); void wasm_interp_free(struct wasm_interp *interp); int interp_wasm_module(struct wasm_interp *interp, int *retval); void print_error_backtrace(struct errors *errors); void setup_wasi(struct wasm_interp *interp, int argc, const char **argv, char **env); void print_callstack(struct wasm_interp *interp); +// builtin helpers +int get_params(struct wasm_interp *interp, struct val** vals, u32 num_vals); +u8 *interp_mem_ptr(struct wasm_interp *interp, u32 ptr, int size); + +static INLINE struct callframe *top_callframe(struct cursor *cur) +{ + return (struct callframe*)cursor_top(cur, sizeof(struct callframe)); +} + + +static INLINE struct cursor *interp_codeptr(struct wasm_interp *interp) +{ + struct callframe *frame; + if (unlikely(!(frame = top_callframe(&interp->callframes)))) + return 0; + return &frame->code; +} + + +static INLINE int mem_ptr_str(struct wasm_interp *interp, u32 ptr, + const char **str) +{ + // still technically unsafe if the string runs over the end of memory... + if (!(*str = (const char*)interp_mem_ptr(interp, ptr, 1))) { + return interp_error(interp, "int memptr"); + } + return 1; +} + + #endif /* PROTOVERSE_WASM_H */