protoverse

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

commit 6fac5d9691602606c9f46d38c06a40eb0258716c
parent abe815d88e46970ecf8352305573312fb4386889
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 24 Jul 2021 09:53:42 -0700

fix many things

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

Diffstat:
Msrc/bench.c | 9+++++----
Msrc/cursor.h | 13+++++++++++--
Msrc/protoverse.c | 4++--
Msrc/wasm.c | 175+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/wasm.h | 6+++---
5 files changed, 152 insertions(+), 55 deletions(-)

diff --git a/src/bench.c b/src/bench.c @@ -7,7 +7,7 @@ #include "wasm.h" static int bench_wasm(unsigned char *wasm, unsigned long len, int times, - int argc, const char **argv) + int argc, const char **argv, char **env) { struct wasm_parser p; struct wasm_interp interp; @@ -27,7 +27,7 @@ static int bench_wasm(unsigned char *wasm, unsigned long len, int times, } interp.errors.enabled = 0; - setup_wasi(&interp, argc, argv); + setup_wasi(&interp, argc, argv, env); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1); for (i = 0; i < times; i++) { @@ -48,7 +48,7 @@ static int bench_wasm(unsigned char *wasm, unsigned long len, int times, return 1; } -int main(int argc, char *argv[]) +int main(int argc, char *argv[], char **env) { unsigned char *wasm_data; const char *code_file; @@ -75,7 +75,8 @@ int main(int argc, char *argv[]) return 1; } fprintf(stderr, "executing %s %d times\n", code_file, times); - if (!bench_wasm(wasm_data, len, times, argc-args, ((const char**)argv)+args)) { + if (!bench_wasm(wasm_data, len, times, argc-args, + ((const char**)argv)+args, env)) { return 2; } diff --git a/src/cursor.h b/src/cursor.h @@ -184,6 +184,15 @@ static inline int cursor_drop(struct cursor *cur, int size) return cursor_dropn(cur, size, 1); } +static inline unsigned char *cursor_topn(struct cursor *cur, int len, int n) +{ + n += 1; + if (unlikely(cur->p - len*n < cur->start)) { + return NULL; + } + return cur->p - len*n; +} + static inline unsigned char *cursor_top(struct cursor *cur, int len) { if (unlikely(cur->p - len < cur->start)) { @@ -216,7 +225,7 @@ static inline int cursor_pop(struct cursor *cur, u8 *data, int len) static inline int cursor_push(struct cursor *cursor, u8 *data, int len) { - if (unlikely(cursor->p + len > cursor->end)) { + if (unlikely(cursor->p + len >= cursor->end)) { return 0; } @@ -303,7 +312,7 @@ static inline void *index_cursor(struct cursor *cursor, unsigned int index, int u8 *p; p = &cursor->start[elem_size * index]; - if (unlikely(p > cursor->end)) + if (unlikely(p >= cursor->end)) return NULL; return (void*)p; diff --git a/src/protoverse.c b/src/protoverse.c @@ -100,7 +100,7 @@ static int usage(void) -int main(int argc, const char *argv[]) +int main(int argc, const char *argv[], char **env) { const char *space, *code_file; const char *cmd; @@ -157,7 +157,7 @@ int main(int argc, const char *argv[]) perror("mmap"); return 1; } - if (!run_wasm(wasm_data, len, argc - 2, argv + 2)) { + if (!run_wasm(wasm_data, len, argc - 2, argv + 2, env)) { return 2; } munmap(wasm_data, len); diff --git a/src/wasm.c b/src/wasm.c @@ -25,6 +25,7 @@ #define ERR_STACK_SIZE 16 #define NUM_LOCALS 0xFFFF #define WASM_PAGE_SIZE 65536 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) static const int MAX_LABELS = 256; @@ -37,6 +38,11 @@ struct expr_parser { struct cursor *stack; // optional }; +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)); @@ -94,7 +100,7 @@ static INLINE int is_valid_fn_index(struct module *module, u32 ind) return ind < module->num_funcs; } -static INLINE struct func *get_function(struct module *module, u32 ind) +static INLINE struct func *get_fn(struct module *module, u32 ind) { if (unlikely(!is_valid_fn_index(module, ind))) return NULL; @@ -105,7 +111,7 @@ static struct val *get_fn_local(struct wasm_interp *interp, int fn, u32 ind) { struct func *func; - if (unlikely(!(func = get_function(interp->module, fn)))) { + if (unlikely(!(func = get_fn(interp->module, fn)))) { interp_error(interp, "unknown fn %d", fn); return NULL; } @@ -803,7 +809,7 @@ static INLINE int count_imported_functions(struct module *module) static INLINE const char *get_function_name(struct module *module, int fn) { struct func *func = NULL; - if (unlikely(!(func = get_function(module, fn)))) { + if (unlikely(!(func = get_fn(module, fn)))) { return "unknown"; } return func->name; @@ -2852,6 +2858,16 @@ static INLINE int interp_i64_ge_u(struct wasm_interp *interp) if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i64))) return interp_error(interp, "binop prep"); c.type = val_i32; + c.num.u32 = lhs.num.u64 >= rhs.num.u64; + return stack_pushval(interp, &c); +} + +static INLINE int interp_i64_ge_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.type = val_i32; c.num.i32 = lhs.num.i64 >= rhs.num.i64; return stack_pushval(interp, &c); } @@ -2895,6 +2911,24 @@ static int interp_i64_eqz(struct wasm_interp *interp) return cursor_pushval(&interp->stack, &res); } +static INLINE int interp_i64_and(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 INLINE int interp_i64_add(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 INLINE int interp_i64_gt_s(struct wasm_interp *interp) { struct val lhs, rhs, c; @@ -2925,6 +2959,26 @@ static INLINE int interp_i64_lt_s(struct wasm_interp *interp) return stack_pushval(interp, &c); } +static INLINE int interp_i64_le_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.type = val_i32; + c.num.i32 = lhs.num.i64 <= rhs.num.i64; + return stack_pushval(interp, &c); +} + +static INLINE int interp_i64_le_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.type = val_i32; + c.num.u32 = lhs.num.u64 <= rhs.num.u64; + return stack_pushval(interp, &c); +} + static INLINE int interp_i64_gt_u(struct wasm_interp *interp) { struct val lhs, rhs, c; @@ -2944,23 +2998,34 @@ static INLINE int interp_i32_gt_u(struct wasm_interp *interp) return stack_pushval(interp, &c); } -static INLINE int interp_i32_div_u(struct wasm_interp *interp) +static INLINE int interp_i32_div_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"); - if (rhs.num.u64 == 0) + if (rhs.num.i32 == 0) return interp_error(interp, "congrats, you divided by zero"); c.num.i32 = lhs.num.i32 / rhs.num.i32; return stack_pushval(interp, &c); } +static INLINE int interp_i32_div_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"); + if (rhs.num.u32 == 0) + return interp_error(interp, "congrats, you divided by zero"); + c.num.u32 = lhs.num.u32 / rhs.num.u32; + return stack_pushval(interp, &c); +} + static INLINE int interp_i32_ge_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.i32 = (unsigned int)lhs.num.i32 >= (unsigned int)rhs.num.i32; + c.num.u32 = lhs.num.u32 >= rhs.num.u32; return stack_pushval(interp, &c); } @@ -3018,7 +3083,9 @@ static INLINE int drop_callframe(struct wasm_interp *interp) { int offset; #ifdef DEBUG - int count; + int count, from_fn, to_fn; + const char *from, *to; + struct callframe *frame; if (unlikely(!count_local_resolvers(interp, &count))) { return interp_error(interp, "count local resolvers"); @@ -3028,13 +3095,29 @@ static INLINE int drop_callframe(struct wasm_interp *interp) return interp_error(interp, "unclean callframe drop, still have" " %d unpopped labels", count); } + + if (!(frame = top_callframes(&interp->callframes, 0))) { + from = "(aux)"; + from_fn = -1; + } else { + from = get_function_name(interp->module, frame->fn); + from_fn = frame->fn; + } + + if (!(frame = top_callframes(&interp->callframes, 1))) { + to = "(aux)"; + to_fn = -1; + } else { + to = get_function_name(interp->module, frame->fn); + to_fn = frame->fn; + } #endif if (unlikely(!cursor_popint(&interp->resolver_offsets, &offset))) { return interp_error(interp, "pop resolver_offsets"); } - debug("dropping callframe\n"); + debug("returning from %s:%d to %s:%d\n", from, from_fn, to, to_fn); return cursor_drop_callframe(&interp->callframes); } @@ -3196,7 +3279,7 @@ static int call_function(struct wasm_interp *interp, int func_index) debug("calling %s:%d\n", get_function_name(interp->module, func_index), func_index); - if (unlikely(!(func = get_function(interp->module, func_index)))) { + if (unlikely(!(func = get_fn(interp->module, func_index)))) { return interp_error(interp, "function %s (%d) not found (%d funcs)", get_function_name(interp->module, func_index), @@ -3499,7 +3582,7 @@ static int upsert_label(struct wasm_interp *interp, u32 fn, return 1; } - if (*num_labels + 1 > MAX_LABELS) { + if (*num_labels + 1 >= MAX_LABELS) { interp_error(interp, "too many labels in %s (> %d)", get_function_name(interp->module, fn), MAX_LABELS); return 0; @@ -3739,6 +3822,14 @@ static int parse_br_table(struct cursor *code, struct errors *errs, return note_error(errs, code, "fail read br_table num_indices"); } + if (br_table->num_label_indices > ARRAY_SIZE(br_table->label_indices)) { + return note_error(errs, code, "whoa slow down on that one chief. " + "This br_table has %d indices but we only have room " + "in our tiny struct for %d indices", + br_table->num_label_indices, + ARRAY_SIZE(br_table->label_indices)); + } + for (i = 0; i < br_table->num_label_indices; i++) { if (unlikely(!read_u32(code, &br_table->label_indices[i]))) { return note_error(errs, code, @@ -4556,7 +4647,7 @@ static int wasi_get_strs(struct wasm_interp *interp, int count, const char **str { struct val *argv, *argv_buf; struct cursor writer; - int i; + int i, len; if (!(argv = get_local(interp, 0))) return interp_error(interp, "strs"); @@ -4575,7 +4666,11 @@ static int wasi_get_strs(struct wasm_interp *interp, int count, const char **str return interp_error(interp, "store argv %d ptr\n", i); } - if (!cursor_push(&writer, (u8*)strs[i], strlen(strs[i])+1)) { + len = strlen(strs[i]) + 1; + + debug("get_str %d '%.*s'\n", i, len, strs[i]); + + if (!cursor_push(&writer, (u8*)strs[i], len)) { return interp_error(interp,"write arg %d", i+1); } } @@ -5208,11 +5303,11 @@ enum interp_end { // tricky... static int interp_end(struct wasm_interp *interp) { - struct resolver *resolver; - //struct label *label; + struct callframe *frame; int loc_resolvers; - if (unlikely(!(resolver = top_resolver(interp, 0)))) { + if (unlikely(!(frame = top_callframe(&interp->callframes)))) { + debug("no callframes, done.\n"); // no more resolvers, we done. return interp_end_done; } @@ -5221,35 +5316,12 @@ static int interp_end(struct wasm_interp *interp) 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); } @@ -5283,6 +5355,7 @@ static int interp_instr(struct wasm_interp *interp, struct instr *instr) case i_i32_sub: return interp_i32_sub(interp); case i_i32_const: return interp_i32_const(interp, instr->i32); case i_i32_div_u: return interp_i32_div_u(interp); + case i_i32_div_s: return interp_i32_div_s(interp); case i_i32_ge_u: return interp_i32_ge_u(interp); case i_i32_ge_s: return interp_i32_ge_s(interp); case i_i32_gt_u: return interp_i32_gt_u(interp); @@ -5304,12 +5377,17 @@ static int interp_instr(struct wasm_interp *interp, struct instr *instr) case i_i32_eq: return interp_i32_eq(interp); case i_i32_wrap_i64:return interp_i32_wrap_i64(interp); + case i_i64_add: return interp_i64_add(interp); + case i_i64_and: return interp_i64_and(interp); case i_i64_eqz: return interp_i64_eqz(interp); case i_i64_gt_s: return interp_i64_gt_s(interp); case i_i64_lt_u: return interp_i64_lt_u(interp); case i_i64_lt_s: return interp_i64_lt_s(interp); + case i_i64_le_u: return interp_i64_le_u(interp); + case i_i64_le_s: return interp_i64_le_s(interp); case i_i64_gt_u: return interp_i64_gt_u(interp); case i_i64_ge_u: return interp_i64_ge_u(interp); + case i_i64_ge_s: return interp_i64_ge_s(interp); case i_i64_div_u: return interp_i64_div_u(interp); case i_i64_xor: return interp_i64_xor(interp); case i_i64_mul: return interp_i64_mul(interp); @@ -5434,9 +5512,8 @@ static int interp_code(struct wasm_interp *interp) parser.errs = &interp->errors; for (;;) { - if (unlikely(!(frame = top_callframe(&interp->callframes)))) { - return interp_error(interp, "no callframe"); + return 1; } if (unlikely(!interp_parse_instr(interp, &frame->code, &parser, @@ -5941,16 +6018,25 @@ static int reset_memory(struct wasm_interp *interp) pages); } assert(interp->memory.p > interp->memory.start); + // I technically need this... //memset(interp->memory.start, 0, pages * WASM_PAGE_SIZE); } return 1; } -void setup_wasi(struct wasm_interp *interp, int argc, const char **argv) +void setup_wasi(struct wasm_interp *interp, int argc, + const char **argv, char **env) { + char **s = env; + interp->wasi.argc = argc; interp->wasi.argv = argv; + + interp->wasi.environ = (const char**)env; + interp->wasi.environc = 0; + if (env) + for (; *s; s++, interp->wasi.environc++); } int wasm_interp_init(struct wasm_interp *interp, struct module *module) @@ -5965,7 +6051,7 @@ int wasm_interp_init(struct wasm_interp *interp, struct module *module) memset(interp, 0, sizeof(*interp)); - setup_wasi(interp, 0, NULL); + setup_wasi(interp, 0, NULL, NULL); interp->quitting = 0; interp->module = module; @@ -5977,6 +6063,7 @@ int wasm_interp_init(struct wasm_interp *interp, struct module *module) //stack = calloc(1, STACK_SPACE); fns = module->num_funcs; labels_capacity = fns * MAX_LABELS; + debug("%d fns, labels capacity %d\n", fns, labels_capacity); num_mems = was_section_parsed(module, section_memory)? module->memory_section.num_mems : 0; @@ -6147,7 +6234,7 @@ int interp_wasm_module(struct wasm_interp *interp) } int run_wasm(unsigned char *wasm, unsigned long len, - int argc, const char **argv) + int argc, const char **argv, char **env) { struct wasm_parser p; struct wasm_interp interp; @@ -6164,7 +6251,7 @@ int run_wasm(unsigned char *wasm, unsigned long len, return 0; } - setup_wasi(&interp, argc, argv); + setup_wasi(&interp, argc, argv, env); if (!interp_wasm_module(&interp)) { print_error_backtrace(&interp.errors); diff --git a/src/wasm.h b/src/wasm.h @@ -511,7 +511,7 @@ struct memarg { struct br_table { u32 num_label_indices; - u32 label_indices[32]; + u32 label_indices[512]; u32 default_label; }; @@ -680,7 +680,7 @@ struct wasm_parser { }; -int run_wasm(unsigned char *wasm, unsigned long len, int argc, const char **argv); +int run_wasm(unsigned char *wasm, unsigned long len, int argc, const char **argv, char **env); 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); @@ -688,6 +688,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); +void setup_wasi(struct wasm_interp *interp, int argc, const char **argv, char **env); #endif /* PROTOVERSE_WASM_H */