commit ec9e6662287ed9f6d301d5e7b7bc73fa56e0c6f5
parent 4f5a16fbb02d5e378f028a7715e5d309930d2871
Author: William Casarin <jb55@jb55.com>
Date: Sat, 3 Jun 2023 09:26:13 -0700
wasm updates from damus
Diffstat:
M | Makefile | | | 11 | +++++++---- |
M | src/bench.c | | | 2 | +- |
M | src/wasm.c | | | 220 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
M | src/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 */