commit bd10754520fbf6254303bf1624047d24a59cadc3
parent bc673207c2f89c8c35768a5c24124c99d8d7626f
Author: William Casarin <jb55@jb55.com>
Date: Mon, 19 Jul 2021 12:52:05 -0700
implement call_indirect
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
3 files changed, 247 insertions(+), 82 deletions(-)
diff --git a/src/wasm.c b/src/wasm.c
@@ -145,7 +145,7 @@ static INLINE int cursor_pop_i32(struct cursor *stack, int *i)
return 0;
if (unlikely(val.type != val_i32))
return 0;
- *i = val.i32;
+ *i = val.num.i32;
return 1;
}
@@ -212,10 +212,10 @@ static INLINE int stack_pop_number(struct wasm_interp *interp, struct val *val)
static void print_val(struct val *val)
{
switch (val->type) {
- case val_i32: printf("%d", val->i32); break;
- case val_i64: printf("%lu", val->i64); break;
- case val_f32: printf("%f", val->f32); break;
- case val_f64: printf("%f", val->f64); break;
+ case val_i32: printf("%d", val->num.i32); break;
+ case val_i64: printf("%lu", val->num.i64); break;
+ case val_f32: printf("%f", val->num.f32); break;
+ case val_f64: printf("%f", val->num.f64); break;
case val_ref_null:
case val_ref_func:
@@ -258,7 +258,7 @@ static int builtin_get_args(struct wasm_interp *interp)
print_stack(&interp->stack);
- debug("get args %d %d\n", argv->i32, argv_buf->i32);
+ debug("get args %d %d\n", argv->num.i32, argv_buf->num.i32);
return 1;
}
@@ -272,7 +272,7 @@ static INLINE int cursor_push_i32(struct cursor *stack, int i)
{
struct val val;
val.type = val_i32;
- val.i32 = i;
+ val.num.i32 = i;
return cursor_pushval(stack, &val);
}
@@ -293,7 +293,7 @@ static int builtin_get_args_sizes(struct wasm_interp *interp)
if (!(argv_buf_size = get_local(interp, 1)))
return interp_error(interp, "argv_buf_size");
- debug("get_args_sizes %d %d\n", argc->i32, argv_buf_size->i32);
+ debug("get_args_sizes %d %d\n", argc->num.i32, argv_buf_size->num.i32);
return stack_push_i32(interp, 0);
}
@@ -584,60 +584,51 @@ void print_error_backtrace(struct errors *errors)
}
}
-static int _functype_str(struct functype *ft, struct cursor *buf)
+static void _functype_str(struct functype *ft, struct cursor *buf)
{
int i;
- if (!cursor_push_str(buf, "("))
- return 0;
+ cursor_push_str(buf, "(");
for (i = 0; i < ft->params.num_valtypes; i++) {
- if (!cursor_push_str(buf, valtype_name(ft->params.valtypes[i])))
- return 0;
+ cursor_push_str(buf, valtype_name(ft->params.valtypes[i]));
if (i != ft->params.num_valtypes-1) {
- if (!cursor_push_str(buf, ", "))
- return 0;
+ cursor_push_str(buf, ", ");
}
}
- if (!cursor_push_str(buf, ") -> ("))
- return 0;
+ cursor_push_str(buf, ") -> (");
for (i = 0; i < ft->result.num_valtypes; i++) {
- if (!cursor_push_str(buf, valtype_name(ft->result.valtypes[i])))
- return 0;
+ cursor_push_str(buf, valtype_name(ft->result.valtypes[i]));
if (i != ft->result.num_valtypes-1) {
- if (!cursor_push_str(buf, ", "))
- return 0;
+ cursor_push_str(buf, ", ");
}
}
- return cursor_push_c_str(buf, ")");
+ cursor_push_c_str(buf, ")");
}
-static const char *functype_str(struct functype *ft, struct cursor *buf)
+static const char *functype_str(struct functype *ft, char *buf, int buflen)
{
- if (buf->start == buf->end)
+ struct cursor cur;
+ if (buflen == 0)
return "";
- if (!_functype_str(ft, buf)) {
- if (buf->p == buf->start)
- return "";
- buf->p[-1] = 0;
- }
+ buf[buflen-1] = 0;
+ make_cursor((u8*)buf, (u8*)buf + buflen-1, &cur);
- return (const char*)buf->start;
+ _functype_str(ft, &cur);
+
+ return (const char*)buf;
}
static void print_functype(struct functype *ft)
{
- static unsigned char buf[0xFF];
- struct cursor cur;
- buf[0] = 0;
- make_cursor(buf, buf + sizeof(buf), &cur);
- printf("%s\n", functype_str(ft, &cur));
+ static char buf[0xFF];
+ printf("%s\n", functype_str(ft, buf, sizeof(buf)));
}
static void print_type_section(struct typesec *typesec)
@@ -1137,7 +1128,7 @@ static int parse_export(struct wasm_parser *p, struct wexport *export)
static int parse_local(struct wasm_parser *p, struct local *local)
{
- if (unlikely(!read_int(&p->cur, &local->val.i32))) {
+ if (unlikely(!read_int(&p->cur, &local->val.num.i32))) {
debug("fail parse local\n");
return parse_err(p, "n");
}
@@ -2335,7 +2326,7 @@ static int interp_i32_add(struct wasm_interp *interp)
return 0;
}
- c.i32 = a.i32 + b.i32;
+ c.num.i32 = a.num.i32 + b.num.i32;
return stack_pushval(interp, &c);
}
@@ -2349,7 +2340,7 @@ static int interp_i32_sub(struct wasm_interp *interp)
return 0;
}
- c.i32 = a.i32 - b.i32;
+ c.num.i32 = a.num.i32 - b.num.i32;
return stack_pushval(interp, &c);
}
@@ -2424,13 +2415,13 @@ static INLINE int interp_local_get(struct wasm_interp *interp, int index)
static INLINE void make_i64_val(struct val *val, int64_t v)
{
val->type = val_i64;
- val->i64 = v;
+ val->num.i64 = v;
}
static INLINE void make_i32_val(struct val *val, int v)
{
val->type = val_i32;
- val->i32 = v;
+ val->num.i32 = v;
}
static INLINE int interp_gt(struct wasm_interp *interp, enum valtype vt, int sign)
@@ -2444,12 +2435,12 @@ static INLINE int interp_gt(struct wasm_interp *interp, enum valtype vt, int sig
switch (vt) {
case val_i32:
- c.i32 = sign? (signed int)lhs.i32 > (signed int)rhs.i32
- : (unsigned int)lhs.i32 > (unsigned int)rhs.i32;
+ c.num.i32 = sign? (signed int)lhs.num.i32 > (signed int)rhs.num.i32
+ : (unsigned int)lhs.num.i32 > (unsigned int)rhs.num.i32;
break;
case val_i64:
- c.i64 = sign? (int64_t)lhs.i64 > (int64_t)rhs.i64
- : (uint64_t)lhs.i64 > (uint64_t)rhs.i64;
+ c.num.i64 = sign? (int64_t)lhs.num.i64 > (int64_t)rhs.num.i64
+ : (uint64_t)lhs.num.i64 > (uint64_t)rhs.num.i64;
break;
default:
return interp_error(interp, "todo: interp_gt %s",
@@ -2465,7 +2456,7 @@ static INLINE int interp_i32_lt_s(struct wasm_interp *interp)
if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i32))) {
return interp_error(interp, "binop prep");
}
- c.i32 = (signed int)lhs.i32 < (signed int)rhs.i32;
+ c.num.i32 = (signed int)lhs.num.i32 < (signed int)rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -2475,7 +2466,7 @@ static INLINE int interp_i32_lt_u(struct wasm_interp *interp)
if (unlikely(!interp_prep_binop(interp, &lhs, &rhs, &c, val_i32))) {
return interp_error(interp, "binop prep");
}
- c.i32 = (unsigned int)lhs.i32 < (unsigned int)rhs.i32;
+ c.num.i32 = (unsigned int)lhs.num.i32 < (unsigned int)rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -2484,7 +2475,7 @@ static INLINE int interp_i32_le_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.i32 = (unsigned int)lhs.i32 <= (unsigned int)rhs.i32;
+ c.num.i32 = (unsigned int)lhs.num.i32 <= (unsigned int)rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -2493,7 +2484,7 @@ static INLINE int interp_i32_gt_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");
- c.i32 = (signed int)lhs.i32 > (signed int)rhs.i32;
+ c.num.i32 = (signed int)lhs.num.i32 > (signed int)rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -2502,7 +2493,7 @@ static INLINE int interp_i32_gt_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.i32 = (unsigned int)lhs.i32 > (unsigned int)rhs.i32;
+ c.num.i32 = (unsigned int)lhs.num.i32 > (unsigned int)rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -2511,7 +2502,7 @@ 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.i32 = (unsigned int)lhs.i32 >= (unsigned int)rhs.i32;
+ c.num.i32 = (unsigned int)lhs.num.i32 >= (unsigned int)rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -2520,7 +2511,7 @@ static INLINE int interp_i32_ge_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");
- c.i32 = (signed int)lhs.i32 >= (signed int)rhs.i32;
+ c.num.i32 = (signed int)lhs.num.i32 >= (signed int)rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -2529,7 +2520,7 @@ static INLINE int interp_i32_le_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");
- c.i32 = (signed int)lhs.i32 <= (signed int)rhs.i32;
+ c.num.i32 = (signed int)lhs.num.i32 <= (signed int)rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -2629,9 +2620,8 @@ static INLINE int count_local_resolvers(struct wasm_interp *interp, int *count)
static int prepare_call(struct wasm_interp *interp, int func_index)
{
- static u8 tmp[0xFF];
+ static char buf[128];
int i;
- struct cursor buf;
struct functype *functype;
struct func *func;
struct val val;
@@ -2674,12 +2664,10 @@ static int prepare_call(struct wasm_interp *interp, int func_index)
paramtype = (enum valtype)functype->params.valtypes[i];
if (unlikely(!cursor_popval(&interp->stack, &val))) {
- make_cursor(tmp, tmp + sizeof(tmp), &buf);
-
return interp_error(interp,
"not enough arguments for call to %s: [%s], needed %d args, got %d",
get_function_name(interp->module, func_index),
- functype_str(functype, &buf),
+ functype_str(functype, buf, sizeof(buf)),
functype->params.num_valtypes,
i);
}
@@ -2737,6 +2725,81 @@ static int interp_call(struct wasm_interp *interp, int func_index)
return 1;
}
+static int interp_call_indirect(struct wasm_interp *interp, struct call_indirect *call)
+{
+ static char buf[128];
+ static char buf2[128];
+ struct functype *type;
+ struct func *func;
+ struct table_inst *table;
+ struct refval *ref;
+ int i, ftidx;
+
+ if (unlikely(!was_section_parsed(interp->module, section_table))) {
+ return interp_error(interp, "no table section");
+ }
+
+ if (unlikely(call->tableidx >= interp->num_tables)) {
+ return interp_error(interp, "invalid table index %d (max %d)",
+ call->tableidx, interp->num_tables-1);
+ }
+
+ if (unlikely(call->typeidx >=
+ interp->module->type_section.num_functypes)) {
+ return interp_error(interp, "invalid function type index: %d (max %d)",
+ call->typeidx,
+ interp->module->type_section.num_functypes);
+ }
+
+ table = &interp->tables[call->tableidx];
+ type = &interp->module->type_section.functypes[call->typeidx];
+
+ if (unlikely(table->reftype != funcref)) {
+ return interp_error(interp,
+ "table[%d] is not a function reference table",
+ call->tableidx
+ );
+ }
+
+ if (unlikely(!stack_pop_i32(interp, &i))) {
+ return interp_error(interp, "pop i32");
+ }
+
+ if (unlikely(i >= table->num_refs)) {
+ return interp_error(interp, "invalid index %d in table %d (max %d)",
+ i, call->tableidx, table->num_refs-1);
+ }
+
+ ref = &table->refs[i];
+
+ if (ref->addr == 0) {
+ return interp_error(interp, "null ref in index %d of table %d",
+ i, call->tableidx);
+ }
+
+ if (ref->addr >= interp->module->num_funcs) {
+ return interp_error(interp, "invalid function ref %d (max %d)",
+ ref, interp->module->num_funcs-1);
+ }
+
+ func = &interp->module->funcs[ref->addr];
+
+ if (func->functype != type) {
+ ftidx = (func->functype -
+ interp->module->type_section.functypes
+ ) / sizeof(struct functype);
+
+ return interp_error(interp,
+ "functype mismatch, expected %d `%s`, got %d `%s`",
+ ftidx,
+ functype_str(func->functype, buf, sizeof(buf)),
+ call->typeidx,
+ functype_str(type, buf2, sizeof(buf2)),
+ ref, interp->module->num_funcs-1);
+ }
+
+ return interp_call(interp, ref->addr);
+}
static int parse_blocktype(struct cursor *cur, struct errors *errs, struct blocktype *blocktype)
{
@@ -3078,7 +3141,7 @@ static INLINE int parse_memarg(struct cursor *code, struct memarg *memarg)
static int parse_call_indirect(struct cursor *code,
struct call_indirect *call_indirect)
{
- return read_int(code, &call_indirect->typeidx) &&
+ return read_int(code, &call_indirect->typeidx) &&
read_int(code, &call_indirect->tableidx);
}
@@ -3386,7 +3449,7 @@ static int interp_if(struct wasm_interp *interp)
return interp_error(interp, "if pop val");
}
- if (cond.i32 == 1) {
+ if (cond.num.i32 == 1) {
return 1;
}
@@ -3405,7 +3468,7 @@ static int interp_i32_eqz(struct wasm_interp *interp)
return interp_error(interp, "if pop val");
res.type = val_i32;
- res.i32 = a.i32 == 0;
+ res.num.i32 = a.num.i32 == 0;
return cursor_pushval(&interp->stack, &res);
}
@@ -3658,10 +3721,10 @@ static int interp_mem_offset(struct wasm_interp *interp,
static int wrap_val(struct val *val, int size) {
switch (val->type) {
case val_i32:
- val->i32 &= (1 << size)-1;
+ val->num.i32 &= (1 << size)-1;
break;
case val_i64:
- val->i64 &= (1UL << size)-1;
+ val->num.i64 &= (1UL << size)-1;
break;
default:
return 0;
@@ -3696,7 +3759,7 @@ static int interp_store(struct wasm_interp *interp, struct memarg *memarg,
}
}
- memcpy(target.pos, &c.i32, target.size);
+ memcpy(target.pos, &c.num.i32, target.size);
return 1;
}
@@ -3720,7 +3783,7 @@ static int interp_load(struct wasm_interp *interp, struct memarg *memarg,
return interp_error(interp, "memory target");
}
- memcpy(&out.i32, target.pos, target.size);
+ memcpy(&out.num.i32, target.pos, target.size);
if (unlikely(!stack_pushval(interp, &out))) {
return interp_error(interp,
@@ -3803,7 +3866,7 @@ static INLINE int interp_i32_mul(struct wasm_interp *interp)
return interp_error(interp, "binop prep");
}
- c.i32 = lhs.i32 * rhs.i32;
+ c.num.i32 = lhs.num.i32 * rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -3816,7 +3879,7 @@ static INLINE int interp_i32_or(struct wasm_interp *interp)
return interp_error(interp, "binop prep");
}
- c.i32 = lhs.i32 | rhs.i32;
+ c.num.i32 = lhs.num.i32 | rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -3829,7 +3892,7 @@ static INLINE int interp_i32_and(struct wasm_interp *interp)
return interp_error(interp, "binop prep");
}
- c.i32 = lhs.i32 & rhs.i32;
+ c.num.i32 = lhs.num.i32 & rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -3842,7 +3905,7 @@ static int interp_i64_or(struct wasm_interp *interp)
return interp_error(interp, "binop prep");
}
- c.i64 = lhs.i64 | rhs.i64;
+ c.num.i64 = lhs.num.i64 | rhs.num.i64;
return stack_pushval(interp, &c);
}
@@ -3854,7 +3917,7 @@ static int interp_i64_shl(struct wasm_interp *interp)
return interp_error(interp, "binop prep");
}
- c.i64 = lhs.i64 << rhs.i64;
+ c.num.i64 = lhs.num.i64 << rhs.num.i64;
return stack_pushval(interp, &c);
}
@@ -3866,7 +3929,7 @@ static int interp_i32_shl(struct wasm_interp *interp)
return interp_error(interp, "binop prep");
}
- c.i32 = lhs.i32 << rhs.i32;
+ c.num.i32 = lhs.num.i32 << rhs.num.i32;
return stack_pushval(interp, &c);
}
@@ -3902,7 +3965,7 @@ static const char *show_instr(struct instr *instr)
cursor_push_str(&buf, instr_name(instr->tag));
len = buf.p - buf.start;
- for (i = 0; i < 12-len; i++)
+ for (i = 0; i < 14-len; i++)
cursor_push_byte(&buf, ' ');
switch (instr->tag) {
@@ -3964,7 +4027,12 @@ static const char *show_instr(struct instr *instr)
break;
case i_br_table:
+ break;
+
case i_call_indirect:
+ sprintf(tmp, "%d %d", instr->call_indirect.typeidx,
+ instr->call_indirect.tableidx);
+ cursor_push_str(&buf, tmp);
break;
case i_f32_const:
@@ -4136,12 +4204,12 @@ static int interp_extend(struct wasm_interp *interp, enum valtype to,
switch (from) {
case val_i32:
- i64 = val->i32;
- val->i64 = i64;
+ i64 = val->num.i32;
+ val->num.i64 = i64;
break;
case val_i64:
- i32 = val->i64;
- val->i32 = i32;
+ i32 = val->num.i64;
+ val->num.i32 = i32;
break;
default:
return interp_error(interp, "unhandled extend from %s to %s",
@@ -4253,6 +4321,7 @@ static int interp_instr(struct wasm_interp *interp, struct instr *instr)
case i_if: return interp_if(interp);
case i_end: return pop_label_checkpoint(interp);
case i_call: return interp_call(interp, instr->integer);
+ case i_call_indirect: return interp_call_indirect(interp, &instr->call_indirect);
case i_block: return interp_block(interp);
case i_br: return interp_br(interp, instr->integer);
case i_br_if: return interp_br_if(interp, instr->integer);
@@ -4453,7 +4522,7 @@ static int count_fn_locals(struct func *func)
if (func->type == func_type_wasm) {
for (i = 0; i < func->wasm_func->num_locals; i++) {
- num_locals += func->wasm_func->locals->val.i32;
+ num_locals += func->wasm_func->locals->val.num.i32;
}
}
@@ -4473,6 +4542,51 @@ static int calculate_locals_size(struct module *module)
return locals_size;
}
+static int calculate_tables_size(struct module *module)
+{
+ int i, num_tables, size;
+ struct table *tables;
+
+ tables = module->table_section.tables;
+ num_tables = module->table_section.num_tables;
+ size = num_tables * sizeof(struct table_inst);
+
+ for (i = 0; i < num_tables; i++) {
+ size += sizeof(struct refval) * tables[i].limits.min;
+ }
+
+ return size;
+}
+
+static int alloc_tables(struct wasm_interp *interp)
+{
+ int size;
+ struct table *t;
+ struct table_inst *inst;
+ int i;
+
+ interp->num_tables = interp->module->table_section.num_tables;
+ if (!(interp->tables = cursor_alloc(&interp->mem, interp->num_tables *
+ sizeof(struct table_inst)))) {
+ return interp_error(interp, "couldn't alloc table instances");
+ }
+
+ for (i = 0; i < interp->num_tables; i++) {
+ t = &interp->module->table_section.tables[i];
+ inst = &(interp->tables[i]);
+ inst->reftype = t->reftype;
+ inst->num_refs = t->limits.min;
+ size = sizeof(struct refval) * t->limits.min;
+ if (!(inst->refs = cursor_alloc(&interp->mem, size))) {
+ return interp_error(interp,
+ "couldn't alloc table inst %d/%d",
+ i+1, interp->module->table_section.num_tables);
+ }
+ }
+
+ return 1;
+}
+
static int alloc_locals(struct module *module, struct cursor *mem,
struct errors *errs)
{
@@ -4504,7 +4618,7 @@ int wasm_interp_init(struct wasm_interp *interp, struct module *module)
callframes_size, resolver_size, labels_size, num_labels_size,
labels_capacity, num_labels_elemsize, memsize, memory_pages_size,
resolver_offsets_size, num_mems, globals_size, num_globals,
- global_init_size;
+ global_init_size, tables_size;
memset(interp, 0, sizeof(*interp));
@@ -4536,6 +4650,7 @@ int wasm_interp_init(struct wasm_interp *interp, struct module *module)
resolver_size = sizeof(struct resolver) * MAX_LABELS;
globals_size = sizeof(struct val) * num_globals;
locals_size = calculate_locals_size(module);
+ tables_size = calculate_tables_size(module);
global_init_size = num_globals;
if (num_mems > 1) {
@@ -4560,6 +4675,7 @@ int wasm_interp_init(struct wasm_interp *interp, struct module *module)
globals_size +
global_init_size +
locals_size +
+ tables_size +
resolver_size;
mem = calloc(1, memsize);
@@ -4582,6 +4698,7 @@ int wasm_interp_init(struct wasm_interp *interp, struct module *module)
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) &&
+ alloc_tables(interp) &&
alloc_locals(interp->module, &interp->mem, &interp->errors);
/* init memory pages */
@@ -4627,6 +4744,30 @@ static int reset_memory(struct wasm_interp *interp)
return 1;
}
+/*
+static int init_tables(struct wasm_interp *interp)
+{
+ struct element *elem, *elems;
+
+ if (!(was_section_parsed(interp->module, section_element) &&
+ was_section_parsed(interp->module, section_table))) {
+ // nothing to init
+ return 1;
+ }
+
+ elems = interp->module->element_section.elements;
+ for (i = 0; i < interp->module->element_section.num_elements; i++) {
+ elem = &elems[i];
+
+ if (elem->mode == elem_mode_passive ||
+ elem->mode == elem_mode_declarative) {
+ continue;
+ }
+
+ }
+}
+*/
+
int interp_wasm_module(struct wasm_interp *interp)
{
int func;
@@ -4645,6 +4786,8 @@ int interp_wasm_module(struct wasm_interp *interp)
reset_cursor(&interp->errors.cur);
reset_cursor(&interp->callframes);
+ //init_tables(interp);
+
if (!reset_memory(interp))
return interp_error(interp, "reset memory");
diff --git a/src/wasm.h b/src/wasm.h
@@ -82,6 +82,12 @@ struct table {
struct limits limits;
};
+struct table_inst {
+ struct refval *refs;
+ enum reftype reftype;
+ int num_refs;
+};
+
struct tablesec {
struct table *tables;
int num_tables;
@@ -177,14 +183,24 @@ struct importsec {
int num_imports;
};
-struct val {
- enum valtype type;
+struct refval {
+ int addr;
+};
+
+struct numval {
union {
int i32;
u64 i64;
float f32;
double f64;
- int addr;
+ };
+};
+
+struct val {
+ enum valtype type;
+ union {
+ struct numval num;
+ struct refval ref;
};
};
@@ -483,8 +499,8 @@ struct br_table {
};
struct call_indirect {
- int typeidx;
int tableidx;
+ int typeidx;
};
struct instr {
@@ -584,6 +600,9 @@ struct wasm_interp {
struct cursor globals; /* struct val */
struct cursor global_init; /* u8 */
+ struct table_inst *tables;
+ int num_tables;
+
struct cursor memory; /* memory pages (65536 blocks) */
struct array labels; /* struct labels */
diff --git a/todo/todo.txt b/todo/todo.txt
@@ -1,2 +1,5 @@
chunked envelope (1280-byte sized chunks) @net
-do we need to reset function locals on return? @wasm +locals
+do we need to reset function locals on return? @wasm
+check blocktypes when popping labels @wasm
+make chess demo @examples
+getting started @docs