diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-apply-names.c | 70 | ||||
-rw-r--r-- | src/wasm-ast.c | 24 | ||||
-rw-r--r-- | src/wasm-ast.h | 18 | ||||
-rw-r--r-- | src/wasm-binary-reader-ast.c | 17 | ||||
-rw-r--r-- | src/wasm-binary-reader-interpreter.c | 579 | ||||
-rw-r--r-- | src/wasm-generate-names.c | 34 | ||||
-rw-r--r-- | src/wasm-interp.c | 103 | ||||
-rw-r--r-- | src/wasm-interpreter.c | 42 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 4 | ||||
-rw-r--r-- | src/wasm-type-vector.h | 17 | ||||
-rw-r--r-- | src/wast2wasm.c | 3 |
11 files changed, 483 insertions, 428 deletions
diff --git a/src/wasm-apply-names.c b/src/wasm-apply-names.c index b9fdcaa7..68ec4354 100644 --- a/src/wasm-apply-names.c +++ b/src/wasm-apply-names.c @@ -110,13 +110,23 @@ static WasmResult use_name_for_global_var(WasmAllocator* allocator, return WASM_OK; } -static WasmResult use_name_for_import_var(WasmAllocator* allocator, +static WasmResult use_name_for_table_var(WasmAllocator* allocator, + WasmModule* module, + WasmVar* var) { + WasmTable* table = wasm_get_table_by_var(module, var); + if (table == NULL) + return WASM_ERROR; + use_name_for_var(allocator, &table->name, var); + return WASM_OK; +} + +static WasmResult use_name_for_memory_var(WasmAllocator* allocator, WasmModule* module, WasmVar* var) { - WasmImport* import = wasm_get_import_by_var(module, var); - if (import == NULL) + WasmMemory* memory = wasm_get_memory_by_var(module, var); + if (memory == NULL) return WASM_ERROR; - use_name_for_var(allocator, &import->name, var); + use_name_for_var(allocator, &memory->name, var); return WASM_OK; } @@ -125,10 +135,9 @@ static WasmResult use_name_for_param_and_local_var(Context* ctx, WasmVar* var) { int local_index = wasm_get_local_index_by_var(func, var); assert(local_index >= 0 && - (size_t)local_index < - wasm_get_num_params_and_locals(ctx->module, func)); + (size_t)local_index < wasm_get_num_params_and_locals(func)); - uint32_t num_params = wasm_get_num_params(ctx->module, func); + uint32_t num_params = wasm_get_num_params(func); WasmStringSlice* name; if ((uint32_t)local_index < num_params) { /* param */ @@ -214,13 +223,6 @@ static WasmResult on_call_expr(WasmExpr* expr, void* user_data) { return WASM_OK; } -static WasmResult on_call_import_expr(WasmExpr* expr, void* user_data) { - Context* ctx = user_data; - CHECK_RESULT(use_name_for_import_var(ctx->allocator, ctx->module, - &expr->call_import.var)); - return WASM_OK; -} - static WasmResult on_call_indirect_expr(WasmExpr* expr, void* user_data) { Context* ctx = user_data; CHECK_RESULT(use_name_for_func_type_var(ctx->allocator, ctx->module, @@ -254,25 +256,6 @@ static WasmResult end_if_expr(WasmExpr* expr, void* user_data) { return WASM_OK; } -static WasmResult begin_if_else_expr(WasmExpr* expr, void* user_data) { - Context* ctx = user_data; - push_label(ctx, &expr->if_else.true_.label); - return WASM_OK; -} - -static WasmResult after_if_else_true_expr(WasmExpr* expr, void* user_data) { - Context* ctx = user_data; - pop_label(ctx); - push_label(ctx, &expr->if_else.false_.label); - return WASM_OK; -} - -static WasmResult end_if_else_expr(WasmExpr* expr, void* user_data) { - Context* ctx = user_data; - pop_label(ctx); - return WASM_OK; -} - static WasmResult on_set_global_expr(WasmExpr* expr, void* user_data) { Context* ctx = user_data; CHECK_RESULT(use_name_for_global_var(ctx->allocator, ctx->module, @@ -319,9 +302,10 @@ static WasmResult visit_func(Context* ctx, static WasmResult visit_import(Context* ctx, uint32_t import_index, WasmImport* import) { - if (wasm_decl_has_func_type(&import->decl)) { + if (import->kind == WASM_EXTERNAL_KIND_FUNC && + wasm_decl_has_func_type(&import->func.decl)) { CHECK_RESULT(use_name_for_func_type_var(ctx->allocator, ctx->module, - &import->decl.type_var)); + &import->func.decl.type_var)); } return WASM_OK; } @@ -337,6 +321,8 @@ static WasmResult visit_elem_segment(Context* ctx, uint32_t elem_segment_index, WasmElemSegment* segment) { size_t i; + CHECK_RESULT( + use_name_for_table_var(ctx->allocator, ctx->module, &segment->table_var)); for (i = 0; i < segment->vars.size; ++i) { CHECK_RESULT(use_name_for_func_var(ctx->allocator, ctx->module, &segment->vars.data[i])); @@ -344,6 +330,14 @@ static WasmResult visit_elem_segment(Context* ctx, return WASM_OK; } +static WasmResult visit_data_segment(Context* ctx, + uint32_t data_segment_index, + WasmDataSegment* segment) { + CHECK_RESULT(use_name_for_memory_var(ctx->allocator, ctx->module, + &segment->memory_var)); + return WASM_OK; +} + static WasmResult visit_module(Context* ctx, WasmModule* module) { size_t i; for (i = 0; i < module->imports.size; ++i) @@ -354,6 +348,8 @@ static WasmResult visit_module(Context* ctx, WasmModule* module) { CHECK_RESULT(visit_export(ctx, i, module->exports.data[i])); for (i = 0; i < module->elem_segments.size; ++i) CHECK_RESULT(visit_elem_segment(ctx, i, module->elem_segments.data[i])); + for (i = 0; i < module->data_segments.size; ++i) + CHECK_RESULT(visit_data_segment(ctx, i, module->data_segments.data[i])); return WASM_OK; } @@ -371,15 +367,11 @@ WasmResult wasm_apply_names(WasmAllocator* allocator, WasmModule* module) { ctx.visitor.on_br_if_expr = on_br_if_expr; ctx.visitor.on_br_table_expr = on_br_table_expr; ctx.visitor.on_call_expr = on_call_expr; - ctx.visitor.on_call_import_expr = on_call_import_expr; ctx.visitor.on_call_indirect_expr = on_call_indirect_expr; ctx.visitor.on_get_global_expr = on_get_global_expr; ctx.visitor.on_get_local_expr = on_get_local_expr; ctx.visitor.begin_if_expr = begin_if_expr; ctx.visitor.end_if_expr = end_if_expr; - ctx.visitor.begin_if_else_expr = begin_if_else_expr; - ctx.visitor.after_if_else_true_expr = after_if_else_true_expr; - ctx.visitor.end_if_else_expr = end_if_else_expr; ctx.visitor.on_set_global_expr = on_set_global_expr; ctx.visitor.on_set_local_expr = on_set_local_expr; ctx.visitor.on_tee_local_expr = on_tee_local_expr; diff --git a/src/wasm-ast.c b/src/wasm-ast.c index f6353bff..12febdb0 100644 --- a/src/wasm-ast.c +++ b/src/wasm-ast.c @@ -186,6 +186,14 @@ int wasm_get_global_index_by_var(const WasmModule* module, const WasmVar* var) { return wasm_get_index_from_var(&module->global_bindings, var); } +int wasm_get_table_index_by_var(const WasmModule* module, const WasmVar* var) { + return wasm_get_index_from_var(&module->table_bindings, var); +} + +int wasm_get_memory_index_by_var(const WasmModule* module, const WasmVar* var) { + return wasm_get_index_from_var(&module->memory_bindings, var); +} + int wasm_get_func_type_index_by_var(const WasmModule* module, const WasmVar* var) { return wasm_get_index_from_var(&module->func_type_bindings, var); @@ -222,6 +230,22 @@ WasmGlobalPtr wasm_get_global_by_var(const WasmModule* module, return module->globals.data[index]; } +WasmTablePtr wasm_get_table_by_var(const WasmModule* module, + const WasmVar* var) { + int index = wasm_get_index_from_var(&module->table_bindings, var); + if (index < 0 || (size_t)index >= module->tables.size) + return NULL; + return module->tables.data[index]; +} + +WasmMemoryPtr wasm_get_memory_by_var(const WasmModule* module, + const WasmVar* var) { + int index = wasm_get_index_from_var(&module->memory_bindings, var); + if (index < 0 || (size_t)index >= module->memories.size) + return NULL; + return module->memories.data[index]; +} + WasmFuncTypePtr wasm_get_func_type_by_var(const WasmModule* module, const WasmVar* var) { int index = wasm_get_index_from_var(&module->func_type_bindings, var); diff --git a/src/wasm-ast.h b/src/wasm-ast.h index b58a1cb1..bff73f35 100644 --- a/src/wasm-ast.h +++ b/src/wasm-ast.h @@ -486,7 +486,6 @@ int wasm_get_func_type_index_by_decl(const WasmModule* module, const WasmFuncDeclaration* decl); int wasm_get_table_index_by_var(const WasmModule* module, const WasmVar* var); int wasm_get_memory_index_by_var(const WasmModule* module, const WasmVar* var); - int wasm_get_import_index_by_var(const WasmModule* module, const WasmVar* var); int wasm_get_local_index_by_var(const WasmFunc* func, const WasmVar* var); @@ -495,6 +494,10 @@ WasmGlobalPtr wasm_get_global_by_var(const WasmModule* func, const WasmVar* var); WasmFuncTypePtr wasm_get_func_type_by_var(const WasmModule* module, const WasmVar* var); +WasmTablePtr wasm_get_table_by_var(const WasmModule* module, + const WasmVar* var); +WasmMemoryPtr wasm_get_memory_by_var(const WasmModule* module, + const WasmVar* var); WasmImportPtr wasm_get_import_by_var(const WasmModule* module, const WasmVar* var); WasmExportPtr wasm_get_export_by_name(const WasmModule* module, @@ -512,19 +515,6 @@ wasm_decl_has_func_type(const WasmFuncDeclaration* decl) { } static WASM_INLINE WasmBool -wasm_type_vectors_are_equal(const WasmTypeVector* types1, - const WasmTypeVector* types2) { - if (types1->size != types2->size) - return WASM_FALSE; - size_t i; - for (i = 0; i < types1->size; ++i) { - if (types1->data[i] != types2->data[i]) - return WASM_FALSE; - } - return WASM_TRUE; -} - -static WASM_INLINE WasmBool wasm_signatures_are_equal(const WasmFuncSignature* sig1, const WasmFuncSignature* sig2) { return wasm_type_vectors_are_equal(&sig1->param_types, &sig2->param_types) && diff --git a/src/wasm-binary-reader-ast.c b/src/wasm-binary-reader-ast.c index f0665d05..081ab0d4 100644 --- a/src/wasm-binary-reader-ast.c +++ b/src/wasm-binary-reader-ast.c @@ -202,6 +202,9 @@ static WasmResult on_import_func(uint32_t index, import->func.decl.type_var.type = WASM_VAR_TYPE_INDEX; import->func.decl.type_var.index = sig_index; import->func.decl.sig = ctx->module->func_types.data[sig_index]->sig; + + WasmFuncPtr func_ptr = &import->func; + wasm_append_func_ptr_value(ctx->allocator, &ctx->module->funcs, &func_ptr); return WASM_OK; } @@ -212,8 +215,10 @@ static WasmResult on_import_table(uint32_t index, Context* ctx = user_data; assert(index == ctx->module->imports.size - 1); WasmImport* import = ctx->module->imports.data[index]; - import->table.elem_limits = *elem_limits; + + WasmTablePtr table_ptr = &import->table; + wasm_append_table_ptr_value(ctx->allocator, &ctx->module->tables, &table_ptr); return WASM_OK; } @@ -223,8 +228,11 @@ static WasmResult on_import_memory(uint32_t index, Context* ctx = user_data; assert(index == ctx->module->imports.size - 1); WasmImport* import = ctx->module->imports.data[index]; - import->memory.page_limits = *page_limits; + + WasmMemoryPtr memory_ptr = &import->memory; + wasm_append_memory_ptr_value(ctx->allocator, &ctx->module->memories, + &memory_ptr); return WASM_OK; } @@ -235,9 +243,12 @@ static WasmResult on_import_global(uint32_t index, Context* ctx = user_data; assert(index == ctx->module->imports.size - 1); WasmImport* import = ctx->module->imports.data[index]; - import->global.type = type; import->global.mutable_ = mutable_; + + WasmGlobalPtr global_ptr = &import->global; + wasm_append_global_ptr_value(ctx->allocator, &ctx->module->globals, + &global_ptr); return WASM_OK; } diff --git a/src/wasm-binary-reader-interpreter.c b/src/wasm-binary-reader-interpreter.c index ce0e27c0..c5f43b45 100644 --- a/src/wasm-binary-reader-interpreter.c +++ b/src/wasm-binary-reader-interpreter.c @@ -116,14 +116,10 @@ typedef enum LabelType { LABEL_TYPE_ELSE, } LabelType; -static const char* s_label_type_name[] = { - "func", "block", "loop", "if", "else", -}; - typedef struct Label { LabelType label_type; - WasmType type; - uint32_t expr_stack_size; + WasmTypeVector sig; + uint32_t type_stack_size; uint32_t offset; /* branch location in the istream */ uint32_t fixup_offset; } Label; @@ -146,7 +142,7 @@ typedef struct Context { WasmInterpreterModule* module; InterpreterFuncArray funcs; InterpreterFunc* current_func; - WasmTypeVector expr_stack; + WasmTypeVector type_stack; LabelVector label_stack; Uint32VectorVector func_fixups; Uint32VectorVector depth_fixups; @@ -167,11 +163,6 @@ static Label* top_label(Context* ctx) { return get_label(ctx, ctx->label_stack.size - 1); } -static uint32_t get_value_count(WasmType result_type) { - return (result_type == WASM_TYPE_VOID || result_type == WASM_TYPE_ANY) ? 0 - : 1; -} - static void on_error(uint32_t offset, const char* message, void* user_data); static void print_error(Context* ctx, const char* format, ...) { @@ -184,10 +175,12 @@ static InterpreterFunc* get_func(Context* ctx, uint32_t func_index) { return &ctx->funcs.data[func_index]; } +#if 0 static WasmInterpreterImport* get_import(Context* ctx, uint32_t import_index) { assert(import_index < ctx->module->imports.size); return &ctx->module->imports.data[import_index]; } +#endif static WasmInterpreterExport* get_export(Context* ctx, uint32_t export_index) { assert(export_index < ctx->module->exports.size); @@ -205,20 +198,25 @@ static WasmInterpreterFuncSignature* get_func_signature(Context* ctx, return get_signature(ctx, func->sig_index); } -static WasmType get_local_index_type(InterpreterFunc* func, - uint32_t local_index) { +static WasmType get_local_type_by_index(InterpreterFunc* func, + uint32_t local_index) { assert(local_index < func->param_and_local_types.size); return func->param_and_local_types.data[local_index]; } -static WasmType get_global_index_type(Context* ctx, uint32_t global_index) { +static WasmInterpreterGlobal* get_global_by_index(Context* ctx, + uint32_t global_index) { assert(global_index < ctx->module->globals.size); - return ctx->module->globals.data[global_index].type; + return &ctx->module->globals.data[global_index]; +} + +static WasmType get_global_type_by_index(Context* ctx, uint32_t global_index) { + return get_global_by_index(ctx, global_index)->typed_value.type; } static uint32_t translate_local_index(Context* ctx, uint32_t local_index) { - assert(local_index < ctx->expr_stack.size); - return ctx->expr_stack.size - local_index; + assert(local_index < ctx->type_stack.size); + return ctx->type_stack.size - local_index; } static uint32_t get_istream_offset(Context* ctx) { @@ -264,10 +262,10 @@ static WasmResult emit_drop_keep(Context* ctx, uint32_t drop, uint8_t keep) { assert(keep <= 1); if (drop > 0) { if (drop == 1 && keep == 0) { - LOGF("%3" PRIzd ": drop\n", ctx->expr_stack.size); + LOGF("%3" PRIzd ": drop\n", ctx->type_stack.size); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_DROP)); } else { - LOGF("%3" PRIzd ": drop_keep %u %u\n", ctx->expr_stack.size, drop, keep); + LOGF("%3" PRIzd ": drop_keep %u %u\n", ctx->type_stack.size, drop, keep); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_DROP_KEEP)); CHECK_RESULT(emit_i32(ctx, drop)); CHECK_RESULT(emit_i8(ctx, keep)); @@ -276,12 +274,11 @@ static WasmResult emit_drop_keep(Context* ctx, uint32_t drop, uint8_t keep) { return WASM_OK; } -static WasmResult drop_exprs_for_return(Context* ctx, WasmType result_type) { +static WasmResult drop_types_for_return(Context* ctx, uint32_t arity) { /* drop the locals and params, but keep the return value, if any */ - uint32_t keep_count = get_value_count(result_type); - assert(ctx->expr_stack.size >= keep_count); - uint32_t drop_count = ctx->expr_stack.size - keep_count; - CHECK_RESULT(emit_drop_keep(ctx, drop_count, keep_count)); + assert(ctx->type_stack.size >= arity); + uint32_t drop_count = ctx->type_stack.size - arity; + CHECK_RESULT(emit_drop_keep(ctx, drop_count, arity)); return WASM_OK; } @@ -305,22 +302,22 @@ static WasmResult emit_br_offset(Context* ctx, return WASM_OK; } -static WasmResult emit_br(Context* ctx, uint8_t arity, uint32_t depth) { +static WasmResult emit_br(Context* ctx, uint32_t depth) { Label* label = get_label(ctx, depth); - assert(ctx->expr_stack.size >= label->expr_stack_size + arity); - uint32_t drop_count = (ctx->expr_stack.size - label->expr_stack_size) - arity; + uint32_t arity = label->sig.size; + assert(ctx->type_stack.size >= label->type_stack_size + arity); + uint32_t drop_count = (ctx->type_stack.size - label->type_stack_size) - arity; CHECK_RESULT(emit_drop_keep(ctx, drop_count, arity)); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_BR)); CHECK_RESULT(emit_br_offset(ctx, depth, label->offset)); return WASM_OK; } -static WasmResult emit_br_table_offset(Context* ctx, - uint8_t arity, - uint32_t depth) { +static WasmResult emit_br_table_offset(Context* ctx, uint32_t depth) { Label* label = get_label(ctx, depth); - assert(ctx->expr_stack.size >= label->expr_stack_size + arity); - uint32_t drop_count = (ctx->expr_stack.size - label->expr_stack_size) - arity; + uint32_t arity = label->sig.size; + assert(ctx->type_stack.size >= label->type_stack_size + arity); + uint32_t drop_count = (ctx->type_stack.size - label->type_stack_size) - arity; CHECK_RESULT(emit_br_offset(ctx, depth, label->offset)); CHECK_RESULT(emit_i32(ctx, drop_count)); CHECK_RESULT(emit_i8(ctx, arity)); @@ -369,17 +366,21 @@ static WasmResult on_signature_count(uint32_t count, void* user_data) { } static WasmResult on_signature(uint32_t index, - WasmType result_type, uint32_t param_count, WasmType* param_types, + uint32_t result_count, + WasmType* result_types, void* user_data) { Context* ctx = user_data; WasmInterpreterFuncSignature* sig = get_signature(ctx, index); - sig->result_type = result_type; wasm_reserve_types(ctx->allocator, &sig->param_types, param_count); sig->param_types.size = param_count; memcpy(sig->param_types.data, param_types, param_count * sizeof(WasmType)); + + wasm_reserve_types(ctx->allocator, &sig->result_types, result_count); + sig->result_types.size = result_count; + memcpy(sig->result_types.data, result_types, result_count * sizeof(WasmType)); return WASM_OK; } @@ -395,20 +396,30 @@ static WasmResult trapping_import_callback( WasmInterpreterImport* import, uint32_t num_args, WasmInterpreterTypedValue* args, - WasmInterpreterTypedValue* out_result, + uint32_t num_results, + WasmInterpreterTypedValue* out_results, void* user_data) { return WASM_ERROR; } static WasmResult on_import(uint32_t index, - uint32_t sig_index, WasmStringSlice module_name, - WasmStringSlice function_name, + WasmStringSlice field_name, void* user_data) { Context* ctx = user_data; + assert(index < ctx->module->imports.size); WasmInterpreterImport* import = &ctx->module->imports.data[index]; import->module_name = wasm_dup_string_slice(ctx->allocator, module_name); - import->func_name = wasm_dup_string_slice(ctx->allocator, function_name); + import->field_name = wasm_dup_string_slice(ctx->allocator, field_name); + return WASM_OK; +} + +static WasmResult on_import_func(uint32_t index, + uint32_t sig_index, + void* user_data) { + Context* ctx = user_data; + assert(index < ctx->module->imports.size); + WasmInterpreterImport* import = &ctx->module->imports.data[index]; assert(sig_index < ctx->module->sigs.size); import->sig_index = sig_index; import->callback = trapping_import_callback; @@ -416,6 +427,31 @@ static WasmResult on_import(uint32_t index, return WASM_OK; } +static WasmResult on_import_table(uint32_t index, + uint32_t elem_type, + const WasmLimits* elem_limits, + void* user_data) { + /* TODO */ + return WASM_ERROR; +} + +static WasmResult on_import_memory(uint32_t index, + const WasmLimits* page_limits, + void* user_data) { + /* TODO */ + return WASM_ERROR; +} + +static WasmResult on_import_global(uint32_t index, + WasmType type, + WasmBool mutable_, + void* user_data) { + /* TODO */ + return WASM_ERROR; +} + +/* TODO(binji): implement import_table, import_memory, import_global */ + static WasmResult on_function_signatures_count(uint32_t count, void* user_data) { Context* ctx = user_data; @@ -435,26 +471,26 @@ static WasmResult on_function_signature(uint32_t index, return WASM_OK; } -static WasmResult on_table_limits(WasmBool has_max, - uint32_t initial_elems, - uint32_t max_elems, - void* user_data) { +static WasmResult on_table(uint32_t index, + uint32_t elem_type, + const WasmLimits* elem_limits, + void* user_data) { Context* ctx = user_data; wasm_new_interpreter_func_table_entry_array( - ctx->allocator, &ctx->module->func_table, initial_elems); + ctx->allocator, &ctx->module->func_table, elem_limits->initial); return WASM_OK; } -static WasmResult on_memory_limits(WasmBool has_max, - uint32_t initial_pages, - uint32_t max_pages, - void* user_data) { +static WasmResult on_memory(uint32_t index, + const WasmLimits* page_limits, + void* user_data) { Context* ctx = user_data; WasmInterpreterMemory* memory = &ctx->module->memory; memory->allocator = ctx->memory_allocator; - memory->page_size = initial_pages; - memory->byte_size = initial_pages * WASM_PAGE_SIZE; - memory->max_page_size = has_max ? max_pages : WASM_MAX_PAGES; + memory->page_size = page_limits->initial; + memory->byte_size = page_limits->initial * WASM_PAGE_SIZE; + memory->max_page_size = + page_limits->has_max ? page_limits->max : WASM_MAX_PAGES; memory->data = wasm_alloc_zero(ctx->memory_allocator, memory->byte_size, WASM_DEFAULT_ALIGN); return WASM_OK; @@ -462,24 +498,28 @@ static WasmResult on_memory_limits(WasmBool has_max, static WasmResult on_global_count(uint32_t count, void* user_data) { Context* ctx = user_data; - wasm_new_interpreter_typed_value_array(ctx->allocator, &ctx->module->globals, - count); + wasm_new_interpreter_global_array(ctx->allocator, &ctx->module->globals, + count); return WASM_OK; } -static WasmResult begin_global(uint32_t index, WasmType type, void* user_data) { +static WasmResult begin_global(uint32_t index, + WasmType type, + WasmBool mutable_, + void* user_data) { Context* ctx = user_data; assert(index < ctx->module->globals.size); - WasmInterpreterTypedValue* typed_value = &ctx->module->globals.data[index]; - typed_value->type = type; + WasmInterpreterGlobal* global = &ctx->module->globals.data[index]; + global->typed_value.type = type; + global->mutable_ = mutable_; return WASM_OK; } static WasmResult end_global_init_expr(uint32_t index, void* user_data) { Context* ctx = user_data; assert(index < ctx->module->globals.size); - WasmInterpreterTypedValue* typed_value = &ctx->module->globals.data[index]; - *typed_value = ctx->init_expr_value; + WasmInterpreterGlobal* global = &ctx->module->globals.data[index]; + global->typed_value = ctx->init_expr_value; return WASM_OK; } @@ -506,9 +546,9 @@ static WasmResult on_init_expr_get_global_expr(uint32_t index, void* user_data) { Context* ctx = user_data; assert(global_index < ctx->module->globals.size); - WasmInterpreterTypedValue* ref_typed_value = + WasmInterpreterGlobal* ref_global = &ctx->module->globals.data[global_index]; - ctx->init_expr_value = *ref_typed_value; + ctx->init_expr_value = ref_global->typed_value; return WASM_OK; } @@ -538,16 +578,39 @@ static WasmResult on_export_count(uint32_t count, void* user_data) { } static WasmResult on_export(uint32_t index, - uint32_t func_index, + WasmExternalKind kind, + uint32_t item_index, WasmStringSlice name, void* user_data) { Context* ctx = user_data; WasmInterpreterExport* export = &ctx->module->exports.data[index]; - InterpreterFunc* func = get_func(ctx, func_index); export->name = wasm_dup_string_slice(ctx->allocator, name); - export->func_index = func_index; - export->sig_index = func->sig_index; - export->func_offset = WASM_INVALID_OFFSET; + + switch (kind) { + case WASM_EXTERNAL_KIND_FUNC: { + InterpreterFunc* func = get_func(ctx, item_index); + export->func_index = item_index; + export->sig_index = func->sig_index; + export->func_offset = WASM_INVALID_OFFSET; + break; + } + + case WASM_EXTERNAL_KIND_TABLE: + /* TODO */ + break; + + case WASM_EXTERNAL_KIND_MEMORY: + /* TODO */ + break; + + case WASM_EXTERNAL_KIND_GLOBAL: + /* TODO */ + break; + + case WASM_NUM_EXTERNAL_KINDS: + assert(0); + break; + } return WASM_OK; } @@ -604,41 +667,25 @@ static WasmResult on_function_bodies_count(uint32_t count, void* user_data) { return WASM_OK; } -static WasmResult type_mismatch(Context* ctx, - WasmType expected_type, - WasmType type, - const char* desc) { - print_error(ctx, "type mismatch in %s, expected %s but got %s.", desc, - s_type_names[expected_type], s_type_names[type]); - return WASM_ERROR; -} - +/* TODO(binji): share a lot of the type-checking code w/ wasm-ast-checker.c */ +/* TODO(binji): flip actual + expected types, to match wasm-ast-checker.c */ static WasmResult check_type(Context* ctx, - WasmType expected_type, - WasmType type, + WasmType expected, + WasmType actual, const char* desc) { - if (expected_type == WASM_TYPE_ANY || type == WASM_TYPE_ANY || - expected_type == WASM_TYPE_VOID) { - return WASM_OK; + if (expected != actual) { + print_error(ctx, "type mismatch in %s, expected %s but got %s.", desc, + s_type_names[expected], s_type_names[actual]); + return WASM_ERROR; } - if (expected_type == type) - return WASM_OK; - return type_mismatch(ctx, expected_type, type, desc); -} - -static void unify_type(WasmType* dest_type, WasmType type) { - if (*dest_type == WASM_TYPE_ANY) - *dest_type = type; - else if (type != WASM_TYPE_ANY && *dest_type != type) - *dest_type = WASM_TYPE_VOID; + return WASM_OK; } -static WasmResult unify_and_check_type(Context* ctx, - WasmType* dest_type, - WasmType type, - const char* desc) { - unify_type(dest_type, type); - return check_type(ctx, *dest_type, type, desc); +static WasmResult check_n_types(Context* ctx, + const WasmTypeVector* expected, + const char* desc) { + /* TODO */ + return WASM_OK; } static uint32_t translate_depth(Context* ctx, uint32_t depth) { @@ -648,13 +695,13 @@ static uint32_t translate_depth(Context* ctx, uint32_t depth) { static void push_label(Context* ctx, LabelType label_type, - WasmType type, + const WasmTypeVector* sig, uint32_t offset, uint32_t fixup_offset) { Label* label = wasm_append_label(ctx->allocator, &ctx->label_stack); label->label_type = label_type; - label->type = type; - label->expr_stack_size = ctx->expr_stack.size; + wasm_extend_types(ctx->allocator, &label->sig, sig); + label->type_stack_size = ctx->type_stack.size; label->offset = offset; label->fixup_offset = fixup_offset; LOGF(" : +depth %" PRIzd ":%s\n", ctx->label_stack.size - 1, @@ -663,7 +710,8 @@ static void push_label(Context* ctx, static void pop_label(Context* ctx) { LOGF(" : -depth %" PRIzd "\n", ctx->label_stack.size - 1); - assert(ctx->label_stack.size > 0); + Label* label = top_label(ctx); + wasm_destroy_type_vector(ctx->allocator, &label->sig); ctx->label_stack.size--; /* reduce the depth_fixups stack as well, but it may be smaller than * label_stack so only do it conditionally. */ @@ -677,72 +725,45 @@ static void pop_label(Context* ctx) { } } -static WasmType top_expr(Context* ctx) { +static WasmType top_type(Context* ctx) { Label* label = top_label(ctx); - assert(ctx->expr_stack.size > label->expr_stack_size); - return ctx->expr_stack.data[ctx->expr_stack.size - 1]; + assert(ctx->type_stack.size > label->type_stack_size); + return ctx->type_stack.data[ctx->type_stack.size - 1]; } -static WasmBool top_expr_is_any(Context* ctx) { +static WasmBool top_type_is_any(Context* ctx) { Label* label = top_label(ctx); - if (ctx->expr_stack.size > label->expr_stack_size) { - WasmType top_type = ctx->expr_stack.data[ctx->expr_stack.size - 1]; + if (ctx->type_stack.size > label->type_stack_size) { + WasmType top_type = ctx->type_stack.data[ctx->type_stack.size - 1]; if (top_type == WASM_TYPE_ANY) return WASM_TRUE; } return WASM_FALSE; } -static WasmType pop_expr(Context* ctx) { - WasmType type = top_expr(ctx); +static WasmType pop_type(Context* ctx) { + WasmType type = top_type(ctx); if (type != WASM_TYPE_ANY) { - LOGF("%3" PRIzd ": pop %s\n", ctx->expr_stack.size, s_type_names[type]); - ctx->expr_stack.size--; + LOGF("%3" PRIzd ": pop %s\n", ctx->type_stack.size, s_type_names[type]); + ctx->type_stack.size--; } return type; } -static WasmType top_expr_if(Context* ctx, WasmBool cond) { - if (cond) - return top_expr(ctx); - return WASM_TYPE_VOID; -} - -static void push_expr(Context* ctx, WasmType type, WasmOpcode opcode) { +static void push_type(Context* ctx, WasmType type, WasmOpcode opcode) { /* TODO: refactor to remove opcode param */ if (type != WASM_TYPE_VOID) { - if (top_expr_is_any(ctx)) + if (top_type_is_any(ctx)) return; - LOGF("%3" PRIzd ": push %s:%s\n", ctx->expr_stack.size, + LOGF("%3" PRIzd ": push %s:%s\n", ctx->type_stack.size, s_opcode_name[opcode], s_type_names[type]); - wasm_append_type_value(ctx->allocator, &ctx->expr_stack, &type); + wasm_append_type_value(ctx->allocator, &ctx->type_stack, &type); } } -static WasmResult check_end(Context* ctx, - WasmType* top_type, - size_t stack_size_adjustment) { - Label* label = top_label(ctx); - /* the stack_size_adjustment is typically 0; it is non-zero when checking the - * implicit function label. The function label stack size does not include - * the parameters, so it will appear as though there are too many values on - * the stack if the stack size is not adjusted. */ - size_t label_stack_size = label->expr_stack_size + stack_size_adjustment; - assert(ctx->expr_stack.size >= label_stack_size); - size_t stack_size = ctx->expr_stack.size - label_stack_size; - if (stack_size == 0) { - *top_type = WASM_TYPE_VOID; - return WASM_OK; - } - - WasmType type = top_expr(ctx); - *top_type = type; - if (type == WASM_TYPE_ANY || stack_size == 1) - return WASM_OK; - - print_error(ctx, "maximum arity is 1, got %" PRIzd ".", stack_size); - return WASM_ERROR; +static void push_types(Context* ctx, const WasmTypeVector* types) { + /* TODO */ } static WasmResult begin_function_body(uint32_t index, void* user_data) { @@ -756,12 +777,12 @@ static WasmResult begin_function_body(uint32_t index, void* user_data) { ctx->current_func = func; ctx->depth_fixups.size = 0; - ctx->expr_stack.size = 0; + ctx->type_stack.size = 0; ctx->label_stack.size = 0; ctx->depth = 0; /* push implicit func label (equivalent to return) */ - push_label(ctx, LABEL_TYPE_FUNC, sig->result_type, WASM_INVALID_OFFSET, + push_label(ctx, LABEL_TYPE_FUNC, &sig->result_types, WASM_INVALID_OFFSET, WASM_INVALID_OFFSET); /* fixup function references */ @@ -774,7 +795,7 @@ static WasmResult begin_function_body(uint32_t index, void* user_data) { for (i = 0; i < sig->param_types.size; ++i) { WasmType type = sig->param_types.data[i]; wasm_append_type_value(ctx->allocator, &func->param_and_local_types, &type); - wasm_append_type_value(ctx->allocator, &ctx->expr_stack, &type); + wasm_append_type_value(ctx->allocator, &ctx->type_stack, &type); } return WASM_OK; @@ -788,20 +809,13 @@ static WasmResult end_function_body(uint32_t index, void* user_data) { return WASM_ERROR; } - WasmInterpreterFuncSignature* sig = - get_func_signature(ctx, ctx->current_func); - - WasmType top_type; - CHECK_RESULT(check_end(ctx, &top_type, sig->param_types.size)); - unify_type(&label->type, top_type); - CHECK_RESULT( - check_type(ctx, sig->result_type, label->type, "implicit return")); - CHECK_RESULT(drop_exprs_for_return(ctx, sig->result_type)); + CHECK_RESULT(check_n_types(ctx, &label->sig, "implicit return")); + CHECK_RESULT(drop_types_for_return(ctx, label->sig.size)); fixup_top_label(ctx, get_istream_offset(ctx)); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_RETURN)); pop_label(ctx); ctx->current_func = NULL; - ctx->expr_stack.size = 0; + ctx->type_stack.size = 0; return WASM_OK; } @@ -817,24 +831,24 @@ static WasmResult on_local_decl(uint32_t decl_index, WasmType type, void* user_data) { Context* ctx = user_data; - LOGF("%3" PRIzd ": alloca\n", ctx->expr_stack.size); + LOGF("%3" PRIzd ": alloca\n", ctx->type_stack.size); InterpreterFunc* func = ctx->current_func; func->local_count += count; uint32_t i; for (i = 0; i < count; ++i) { wasm_append_type_value(ctx->allocator, &func->param_and_local_types, &type); - push_expr(ctx, type, WASM_OPCODE_ALLOCA); + push_type(ctx, type, WASM_OPCODE_ALLOCA); } if (decl_index == func->local_decl_count - 1) { /* last local declaration, allocate space for all locals. */ CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_ALLOCA)); CHECK_RESULT(emit_i32(ctx, func->local_count)); - /* fixup the function label's expr_stack_size to include these values. */ + /* fixup the function label's type_stack_size to include these values. */ Label* label = top_label(ctx); assert(label->label_type == LABEL_TYPE_FUNC); - label->expr_stack_size += func->local_count; + label->type_stack_size += func->local_count; } return WASM_OK; } @@ -842,48 +856,62 @@ static WasmResult on_local_decl(uint32_t decl_index, static WasmResult on_unary_expr(WasmOpcode opcode, void* user_data) { Context* ctx = user_data; const char* opcode_name = s_opcode_name[opcode]; - WasmType value = pop_expr(ctx); + WasmType value = pop_type(ctx); CHECK_RESULT(check_type(ctx, s_opcode_type1[opcode], value, opcode_name)); CHECK_RESULT(emit_opcode(ctx, opcode)); - push_expr(ctx, s_opcode_rtype[opcode], opcode); + push_type(ctx, s_opcode_rtype[opcode], opcode); return WASM_OK; } static WasmResult on_binary_expr(WasmOpcode opcode, void* user_data) { Context* ctx = user_data; const char* opcode_name = s_opcode_name[opcode]; - WasmType right = pop_expr(ctx); - WasmType left = pop_expr(ctx); + WasmType right = pop_type(ctx); + WasmType left = pop_type(ctx); CHECK_RESULT(check_type(ctx, s_opcode_type1[opcode], left, opcode_name)); CHECK_RESULT(check_type(ctx, s_opcode_type2[opcode], right, opcode_name)); CHECK_RESULT(emit_opcode(ctx, opcode)); - push_expr(ctx, s_opcode_rtype[opcode], opcode); + push_type(ctx, s_opcode_rtype[opcode], opcode); return WASM_OK; } -static WasmResult on_block_expr(void* user_data) { +static WasmResult on_block_expr(uint32_t num_types, + WasmType* sig_types, + void* user_data) { Context* ctx = user_data; - push_label(ctx, LABEL_TYPE_BLOCK, WASM_TYPE_ANY, WASM_INVALID_OFFSET, + WasmTypeVector sig; + sig.size = num_types; + sig.data = sig_types; + push_label(ctx, LABEL_TYPE_BLOCK, &sig, WASM_INVALID_OFFSET, WASM_INVALID_OFFSET); return WASM_OK; } -static WasmResult on_loop_expr(void* user_data) { +static WasmResult on_loop_expr(uint32_t num_types, + WasmType* sig_types, + void* user_data) { Context* ctx = user_data; - push_label(ctx, LABEL_TYPE_LOOP, WASM_TYPE_VOID, get_istream_offset(ctx), + WasmTypeVector sig; + sig.size = num_types; + sig.data = sig_types; + push_label(ctx, LABEL_TYPE_LOOP, &sig, get_istream_offset(ctx), WASM_INVALID_OFFSET); return WASM_OK; } -static WasmResult on_if_expr(void* user_data) { +static WasmResult on_if_expr(uint32_t num_types, + WasmType* sig_types, + void* user_data) { Context* ctx = user_data; - WasmType cond = pop_expr(ctx); + WasmType cond = pop_type(ctx); CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, cond, "if")); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_BR_UNLESS)); uint32_t fixup_offset = get_istream_offset(ctx); CHECK_RESULT(emit_i32(ctx, WASM_INVALID_OFFSET)); - push_label(ctx, LABEL_TYPE_IF, WASM_TYPE_ANY, WASM_INVALID_OFFSET, - fixup_offset); + WasmTypeVector sig; + sig.size = num_types; + sig.data = sig_types; + push_label(ctx, LABEL_TYPE_IF, &sig, WASM_INVALID_OFFSET, fixup_offset); return WASM_OK; } @@ -895,10 +923,7 @@ static WasmResult on_else_expr(void* user_data) { return WASM_ERROR; } - WasmType top_type; - CHECK_RESULT(check_end(ctx, &top_type, 0)); - CHECK_RESULT( - unify_and_check_type(ctx, &label->type, top_type, "if true branch")); + CHECK_RESULT(check_n_types(ctx, &label->sig, "if true branch")); label->label_type = LABEL_TYPE_ELSE; uint32_t fixup_cond_offset = label->fixup_offset; @@ -906,89 +931,89 @@ static WasmResult on_else_expr(void* user_data) { label->fixup_offset = get_istream_offset(ctx); CHECK_RESULT(emit_i32(ctx, WASM_INVALID_OFFSET)); CHECK_RESULT(emit_i32_at(ctx, fixup_cond_offset, get_istream_offset(ctx))); - /* reset the expr stack for the other branch arm */ - ctx->expr_stack.size = label->expr_stack_size; + /* reset the type stack for the other branch arm */ + ctx->type_stack.size = label->type_stack_size; return WASM_OK; } static WasmResult on_end_expr(void* user_data) { Context* ctx = user_data; Label* label = top_label(ctx); - if (!label || label->label_type == LABEL_TYPE_FUNC) { + if (!label) { print_error(ctx, "unexpected end operator"); return WASM_ERROR; } - if (label->label_type == LABEL_TYPE_IF) - label->type = WASM_TYPE_VOID; - - WasmType top_type; - CHECK_RESULT(check_end(ctx, &top_type, 0)); - if (label->label_type != LABEL_TYPE_LOOP) { - CHECK_RESULT(unify_and_check_type(ctx, &label->type, top_type, - s_label_type_name[label->label_type])); - top_type = label->type; - } - - if (label->label_type == LABEL_TYPE_IF || - label->label_type == LABEL_TYPE_ELSE) { - uint32_t fixup_true_offset = label->fixup_offset; - CHECK_RESULT(emit_i32_at(ctx, fixup_true_offset, get_istream_offset(ctx))); + const char* desc = NULL; + switch (label->label_type) { + case LABEL_TYPE_IF: + case LABEL_TYPE_ELSE: + desc = (label->label_type == LABEL_TYPE_IF) ? "if true branch" + : "if false branch"; + CHECK_RESULT( + emit_i32_at(ctx, label->fixup_offset, get_istream_offset(ctx))); + break; + + case LABEL_TYPE_BLOCK: + desc = "block"; + break; + + case LABEL_TYPE_LOOP: + desc = "loop"; + break; + + case LABEL_TYPE_FUNC: + print_error(ctx, "unexpected end operator"); + return WASM_ERROR; } + CHECK_RESULT(check_n_types(ctx, &label->sig, desc)); fixup_top_label(ctx, get_istream_offset(ctx)); - ctx->expr_stack.size = label->expr_stack_size; + ctx->type_stack.size = label->type_stack_size; pop_label(ctx); - push_expr(ctx, top_type, WASM_OPCODE_END); + push_types(ctx, &label->sig); return WASM_OK; } -static WasmResult on_br_expr(uint8_t arity, uint32_t depth, void* user_data) { +static WasmResult on_br_expr(uint32_t depth, void* user_data) { Context* ctx = user_data; - WasmType value = top_expr_if(ctx, arity > 0); CHECK_DEPTH(ctx, depth); depth = translate_depth(ctx, depth); Label* label = get_label(ctx, depth); - CHECK_RESULT(unify_and_check_type(ctx, &label->type, value, "br")); - CHECK_RESULT(emit_br(ctx, arity, depth)); - push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_BR); + CHECK_RESULT(check_n_types(ctx, &label->sig, "br")); + CHECK_RESULT(emit_br(ctx, depth)); + push_type(ctx, WASM_TYPE_ANY, WASM_OPCODE_BR); return WASM_OK; } -static WasmResult on_br_if_expr(uint8_t arity, - uint32_t depth, - void* user_data) { +static WasmResult on_br_if_expr(uint32_t depth, void* user_data) { Context* ctx = user_data; - WasmType cond = pop_expr(ctx); - WasmType value = top_expr_if(ctx, arity > 0); + WasmType cond = pop_type(ctx); CHECK_DEPTH(ctx, depth); depth = translate_depth(ctx, depth); Label* label = get_label(ctx, depth); - CHECK_RESULT(unify_and_check_type(ctx, &label->type, value, "br_if")); CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, cond, "br_if")); /* flip the br_if so if <cond> is true it can drop values from the stack */ CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_BR_UNLESS)); uint32_t fixup_br_offset = get_istream_offset(ctx); CHECK_RESULT(emit_i32(ctx, WASM_INVALID_OFFSET)); - CHECK_RESULT(emit_br(ctx, arity, depth)); + CHECK_RESULT(emit_br(ctx, depth)); CHECK_RESULT(emit_i32_at(ctx, fixup_br_offset, get_istream_offset(ctx))); - /* clean up the value (if any), when the branch isn't taken */ - CHECK_RESULT(emit_drop_keep(ctx, arity, 0)); + /* clean up the values (if any), when the branch isn't taken */ + CHECK_RESULT(emit_drop_keep(ctx, label->sig.size, 0)); /* don't pop the top expr from the stack if it is ANY; we want that to * propagate through */ - if (!top_expr_is_any(ctx)) - ctx->expr_stack.size -= arity; + if (!top_type_is_any(ctx)) + ctx->type_stack.size -= label->sig.size; return WASM_OK; } -static WasmResult on_br_table_expr(uint8_t arity, - uint32_t num_targets, +static WasmResult on_br_table_expr(uint32_t num_targets, uint32_t* target_depths, uint32_t default_target_depth, void* user_data) { Context* ctx = user_data; - WasmType key = pop_expr(ctx); - WasmType value = top_expr_if(ctx, arity > 0); + WasmType key = pop_type(ctx); CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, key, "br_table")); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_BR_TABLE)); @@ -1006,11 +1031,11 @@ static WasmResult on_br_table_expr(uint8_t arity, uint32_t depth = i != num_targets ? target_depths[i] : default_target_depth; depth = translate_depth(ctx, depth); Label* label = get_label(ctx, depth); - CHECK_RESULT(unify_and_check_type(ctx, &label->type, value, "br_table")); - CHECK_RESULT(emit_br_table_offset(ctx, arity, depth)); + CHECK_RESULT(check_n_types(ctx, &label->sig, "br_table")); + CHECK_RESULT(emit_br_table_offset(ctx, depth)); } - push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_BR_TABLE); + push_type(ctx, WASM_TYPE_ANY, WASM_OPCODE_BR_TABLE); return WASM_OK; } @@ -1022,58 +1047,39 @@ static WasmResult on_call_expr(uint32_t func_index, void* user_data) { uint32_t i; for (i = sig->param_types.size; i > 0; --i) { - WasmType arg = pop_expr(ctx); + WasmType arg = pop_type(ctx); CHECK_RESULT(check_type(ctx, sig->param_types.data[i - 1], arg, "call")); } CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_FUNCTION)); CHECK_RESULT(emit_func_offset(ctx, func, func_index)); - push_expr(ctx, sig->result_type, WASM_OPCODE_CALL_FUNCTION); - return WASM_OK; -} - -static WasmResult on_call_import_expr(uint32_t import_index, void* user_data) { - Context* ctx = user_data; - assert(import_index < ctx->module->imports.size); - WasmInterpreterImport* import = get_import(ctx, import_index); - WasmInterpreterFuncSignature* sig = get_signature(ctx, import->sig_index); - - uint32_t i; - for (i = sig->param_types.size; i > 0; --i) { - WasmType arg = pop_expr(ctx); - CHECK_RESULT( - check_type(ctx, sig->param_types.data[i - 1], arg, "call_import")); - } - - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_IMPORT)); - CHECK_RESULT(emit_i32(ctx, import_index)); - push_expr(ctx, sig->result_type, WASM_OPCODE_CALL_IMPORT); + push_types(ctx, &sig->result_types); return WASM_OK; } static WasmResult on_call_indirect_expr(uint32_t sig_index, void* user_data) { Context* ctx = user_data; WasmInterpreterFuncSignature* sig = get_signature(ctx, sig_index); - WasmType entry_index = pop_expr(ctx); + WasmType entry_index = pop_type(ctx); CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, entry_index, "call_indirect")); uint32_t i; for (i = sig->param_types.size; i > 0; --i) { - WasmType arg = pop_expr(ctx); + WasmType arg = pop_type(ctx); CHECK_RESULT( check_type(ctx, sig->param_types.data[i - 1], arg, "call_indirect")); } CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_INDIRECT)); CHECK_RESULT(emit_i32(ctx, sig_index)); - push_expr(ctx, sig->result_type, WASM_OPCODE_CALL_INDIRECT); + push_types(ctx, &sig->result_types); return WASM_OK; } static WasmResult on_drop_expr(void* user_data) { Context* ctx = user_data; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_DROP)); - pop_expr(ctx); + pop_type(ctx); return WASM_OK; } @@ -1081,7 +1087,7 @@ static WasmResult on_i32_const_expr(uint32_t value, void* user_data) { Context* ctx = user_data; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_I32_CONST)); CHECK_RESULT(emit_i32(ctx, value)); - push_expr(ctx, WASM_TYPE_I32, WASM_OPCODE_I32_CONST); + push_type(ctx, WASM_TYPE_I32, WASM_OPCODE_I32_CONST); return WASM_OK; } @@ -1089,7 +1095,7 @@ static WasmResult on_i64_const_expr(uint64_t value, void* user_data) { Context* ctx = user_data; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_I64_CONST)); CHECK_RESULT(emit_i64(ctx, value)); - push_expr(ctx, WASM_TYPE_I64, WASM_OPCODE_I64_CONST); + push_type(ctx, WASM_TYPE_I64, WASM_OPCODE_I64_CONST); return WASM_OK; } @@ -1097,7 +1103,7 @@ static WasmResult on_f32_const_expr(uint32_t value_bits, void* user_data) { Context* ctx = user_data; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_F32_CONST)); CHECK_RESULT(emit_i32(ctx, value_bits)); - push_expr(ctx, WASM_TYPE_F32, WASM_OPCODE_F32_CONST); + push_type(ctx, WASM_TYPE_F32, WASM_OPCODE_F32_CONST); return WASM_OK; } @@ -1105,26 +1111,31 @@ static WasmResult on_f64_const_expr(uint64_t value_bits, void* user_data) { Context* ctx = user_data; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_F64_CONST)); CHECK_RESULT(emit_i64(ctx, value_bits)); - push_expr(ctx, WASM_TYPE_F64, WASM_OPCODE_F64_CONST); + push_type(ctx, WASM_TYPE_F64, WASM_OPCODE_F64_CONST); return WASM_OK; } static WasmResult on_get_global_expr(uint32_t global_index, void* user_data) { Context* ctx = user_data; CHECK_GLOBAL(ctx, global_index); - WasmType type = get_global_index_type(ctx, global_index); + WasmType type = get_global_type_by_index(ctx, global_index); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_GET_GLOBAL)); CHECK_RESULT(emit_i32(ctx, global_index)); - push_expr(ctx, type, WASM_OPCODE_GET_GLOBAL); + push_type(ctx, type, WASM_OPCODE_GET_GLOBAL); return WASM_OK; } static WasmResult on_set_global_expr(uint32_t global_index, void* user_data) { Context* ctx = user_data; CHECK_GLOBAL(ctx, global_index); - WasmType type = get_global_index_type(ctx, global_index); - WasmType value = pop_expr(ctx); - CHECK_RESULT(check_type(ctx, type, value, "set_global")); + WasmInterpreterGlobal* global = get_global_by_index(ctx, global_index); + if (global->mutable_ != WASM_TRUE) { + print_error(ctx, "can't set_global on immutable global at index %u.", + global_index); + return WASM_ERROR; + } + WasmType value = pop_type(ctx); + CHECK_RESULT(check_type(ctx, global->typed_value.type, value, "set_global")); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_SET_GLOBAL)); CHECK_RESULT(emit_i32(ctx, global_index)); return WASM_OK; @@ -1133,18 +1144,18 @@ static WasmResult on_set_global_expr(uint32_t global_index, void* user_data) { static WasmResult on_get_local_expr(uint32_t local_index, void* user_data) { Context* ctx = user_data; CHECK_LOCAL(ctx, local_index); - WasmType type = get_local_index_type(ctx->current_func, local_index); + WasmType type = get_local_type_by_index(ctx->current_func, local_index); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_GET_LOCAL)); CHECK_RESULT(emit_i32(ctx, translate_local_index(ctx, local_index))); - push_expr(ctx, type, WASM_OPCODE_GET_LOCAL); + push_type(ctx, type, WASM_OPCODE_GET_LOCAL); return WASM_OK; } static WasmResult on_set_local_expr(uint32_t local_index, void* user_data) { Context* ctx = user_data; CHECK_LOCAL(ctx, local_index); - WasmType type = get_local_index_type(ctx->current_func, local_index); - WasmType value = pop_expr(ctx); + WasmType type = get_local_type_by_index(ctx->current_func, local_index); + WasmType value = pop_type(ctx); CHECK_RESULT(check_type(ctx, type, value, "set_local")); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_SET_LOCAL)); CHECK_RESULT(emit_i32(ctx, translate_local_index(ctx, local_index))); @@ -1154,8 +1165,8 @@ static WasmResult on_set_local_expr(uint32_t local_index, void* user_data) { static WasmResult on_tee_local_expr(uint32_t local_index, void* user_data) { Context* ctx = user_data; CHECK_LOCAL(ctx, local_index); - WasmType type = get_local_index_type(ctx->current_func, local_index); - WasmType value = top_expr(ctx); + WasmType type = get_local_type_by_index(ctx->current_func, local_index); + WasmType value = top_type(ctx); CHECK_RESULT(check_type(ctx, type, value, "tee_local")); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_TEE_LOCAL)); CHECK_RESULT(emit_i32(ctx, translate_local_index(ctx, local_index))); @@ -1164,10 +1175,10 @@ static WasmResult on_tee_local_expr(uint32_t local_index, void* user_data) { static WasmResult on_grow_memory_expr(void* user_data) { Context* ctx = user_data; - WasmType value = pop_expr(ctx); + WasmType value = pop_type(ctx); CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, value, "grow_memory")); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_GROW_MEMORY)); - push_expr(ctx, WASM_TYPE_I32, WASM_OPCODE_GROW_MEMORY); + push_type(ctx, WASM_TYPE_I32, WASM_OPCODE_GROW_MEMORY); return WASM_OK; } @@ -1176,11 +1187,11 @@ static WasmResult on_load_expr(WasmOpcode opcode, uint32_t offset, void* user_data) { Context* ctx = user_data; - WasmType addr = pop_expr(ctx); + WasmType addr = pop_type(ctx); CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, addr, s_opcode_name[opcode])); CHECK_RESULT(emit_opcode(ctx, opcode)); CHECK_RESULT(emit_i32(ctx, offset)); - push_expr(ctx, s_opcode_rtype[opcode], opcode); + push_type(ctx, s_opcode_rtype[opcode], opcode); return WASM_OK; } @@ -1189,21 +1200,21 @@ static WasmResult on_store_expr(WasmOpcode opcode, uint32_t offset, void* user_data) { Context* ctx = user_data; - WasmType value = pop_expr(ctx); - WasmType addr = pop_expr(ctx); + WasmType value = pop_type(ctx); + WasmType addr = pop_type(ctx); WasmType type = s_opcode_rtype[opcode]; CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, addr, s_opcode_name[opcode])); CHECK_RESULT(check_type(ctx, type, value, s_opcode_name[opcode])); CHECK_RESULT(emit_opcode(ctx, opcode)); CHECK_RESULT(emit_i32(ctx, offset)); - push_expr(ctx, type, opcode); + push_type(ctx, type, opcode); return WASM_OK; } static WasmResult on_current_memory_expr(void* user_data) { Context* ctx = user_data; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CURRENT_MEMORY)); - push_expr(ctx, WASM_TYPE_I32, WASM_OPCODE_CURRENT_MEMORY); + push_type(ctx, WASM_TYPE_I32, WASM_OPCODE_CURRENT_MEMORY); return WASM_OK; } @@ -1217,34 +1228,29 @@ static WasmResult on_return_expr(void* user_data) { Context* ctx = user_data; WasmInterpreterFuncSignature* sig = get_func_signature(ctx, ctx->current_func); - if (get_value_count(sig->result_type)) { - WasmType value = top_expr(ctx); - CHECK_RESULT(check_type(ctx, sig->result_type, value, "return")); - } - CHECK_RESULT(drop_exprs_for_return(ctx, sig->result_type)); + CHECK_RESULT(check_n_types(ctx, &sig->result_types, "return")); + CHECK_RESULT(drop_types_for_return(ctx, sig->result_types.size)); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_RETURN)); - push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_RETURN); + push_type(ctx, WASM_TYPE_ANY, WASM_OPCODE_RETURN); return WASM_OK; } static WasmResult on_select_expr(void* user_data) { Context* ctx = user_data; - WasmType cond = pop_expr(ctx); - WasmType right = pop_expr(ctx); - WasmType left = pop_expr(ctx); - WasmType type = WASM_TYPE_ANY; - CHECK_RESULT(unify_and_check_type(ctx, &type, left, "select")); - CHECK_RESULT(unify_and_check_type(ctx, &type, right, "select")); + WasmType cond = pop_type(ctx); + WasmType right = pop_type(ctx); + WasmType left = pop_type(ctx); + CHECK_RESULT(check_type(ctx, left, right, "select")); CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, cond, "select")); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_SELECT)); - push_expr(ctx, type, WASM_OPCODE_SELECT); + push_type(ctx, left, WASM_OPCODE_SELECT); return WASM_OK; } static WasmResult on_unreachable_expr(void* user_data) { Context* ctx = user_data; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_UNREACHABLE)); - push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_UNREACHABLE); + push_type(ctx, WASM_TYPE_ANY, WASM_OPCODE_UNREACHABLE); return WASM_OK; } @@ -1277,13 +1283,17 @@ static WasmBinaryReader s_binary_reader = { .on_import_count = on_import_count, .on_import = on_import, + .on_import_func = on_import_func, + .on_import_table = on_import_table, + .on_import_memory = on_import_memory, + .on_import_global = on_import_global, .on_function_signatures_count = on_function_signatures_count, .on_function_signature = on_function_signature, - .on_table_limits = on_table_limits, + .on_table = on_table, - .on_memory_limits = on_memory_limits, + .on_memory = on_memory, .on_global_count = on_global_count, .begin_global = begin_global, @@ -1304,7 +1314,6 @@ static WasmBinaryReader s_binary_reader = { .on_br_if_expr = on_br_if_expr, .on_br_table_expr = on_br_table_expr, .on_call_expr = on_call_expr, - .on_call_import_expr = on_call_import_expr, .on_call_indirect_expr = on_call_indirect_expr, .on_compare_expr = on_binary_expr, .on_convert_expr = on_unary_expr, @@ -1352,7 +1361,7 @@ static void wasm_destroy_interpreter_func(WasmAllocator* allocator, } static void destroy_context(Context* ctx) { - wasm_destroy_type_vector(ctx->allocator, &ctx->expr_stack); + wasm_destroy_type_vector(ctx->allocator, &ctx->type_stack); wasm_destroy_label_vector(ctx->allocator, &ctx->label_stack); WASM_DESTROY_ARRAY_AND_ELEMENTS(ctx->allocator, ctx->funcs, interpreter_func); WASM_DESTROY_VECTOR_AND_ELEMENTS(ctx->allocator, ctx->depth_fixups, diff --git a/src/wasm-generate-names.c b/src/wasm-generate-names.c index 64f8de1d..db7af0c3 100644 --- a/src/wasm-generate-names.c +++ b/src/wasm-generate-names.c @@ -120,15 +120,6 @@ static WasmResult begin_if_expr(WasmExpr* expr, void* user_data) { return WASM_OK; } -static WasmResult begin_if_else_expr(WasmExpr* expr, void* user_data) { - Context* ctx = user_data; - maybe_generate_name(ctx->allocator, "$L", ctx->label_count++, - &expr->if_else.true_.label); - maybe_generate_name(ctx->allocator, "$L", ctx->label_count++, - &expr->if_else.false_.label); - return WASM_OK; -} - static WasmResult visit_func(Context* ctx, uint32_t func_index, @@ -169,11 +160,19 @@ static WasmResult visit_func_type(Context* ctx, return WASM_OK; } -static WasmResult visit_import(Context* ctx, - uint32_t import_index, - WasmImport* import) { - maybe_generate_and_bind_name(ctx->allocator, &ctx->module->import_bindings, - "$i", import_index, &import->name); +static WasmResult visit_table(Context* ctx, + uint32_t table_index, + WasmTable* table) { + maybe_generate_and_bind_name(ctx->allocator, &ctx->module->table_bindings, + "$T", table_index, &table->name); + return WASM_OK; +} + +static WasmResult visit_memory(Context* ctx, + uint32_t memory_index, + WasmMemory* memory) { + maybe_generate_and_bind_name(ctx->allocator, &ctx->module->memory_bindings, + "$M", memory_index, &memory->name); return WASM_OK; } @@ -183,10 +182,12 @@ static WasmResult visit_module(Context* ctx, WasmModule* module) { CHECK_RESULT(visit_global(ctx, i, module->globals.data[i])); for (i = 0; i < module->func_types.size; ++i) CHECK_RESULT(visit_func_type(ctx, i, module->func_types.data[i])); - for (i = 0; i < module->imports.size; ++i) - CHECK_RESULT(visit_import(ctx, i, module->imports.data[i])); for (i = 0; i < module->funcs.size; ++i) CHECK_RESULT(visit_func(ctx, i, module->funcs.data[i])); + for (i = 0; i < module->tables.size; ++i) + CHECK_RESULT(visit_table(ctx, i, module->tables.data[i])); + for (i = 0; i < module->memories.size; ++i) + CHECK_RESULT(visit_memory(ctx, i, module->memories.data[i])); return WASM_OK; } @@ -198,7 +199,6 @@ WasmResult wasm_generate_names(WasmAllocator* allocator, WasmModule* module) { ctx.visitor.begin_block_expr = begin_block_expr; ctx.visitor.begin_loop_expr = begin_loop_expr; ctx.visitor.begin_if_expr = begin_if_expr; - ctx.visitor.begin_if_else_expr = begin_if_else_expr; ctx.module = module; WasmResult result = visit_module(&ctx, module); wasm_destroy_string_slice_vector(allocator, &ctx.index_to_name); diff --git a/src/wasm-interp.c b/src/wasm-interp.c index f45055e5..ab679e90 100644 --- a/src/wasm-interp.c +++ b/src/wasm-interp.c @@ -231,15 +231,21 @@ static void print_typed_value(WasmInterpreterTypedValue* tv) { } } -static WasmResult default_import_callback(WasmInterpreterModule* module, - WasmInterpreterImport* import, - uint32_t num_args, - WasmInterpreterTypedValue* args, - WasmInterpreterTypedValue* out_result, - void* user_data) { +static WasmResult default_import_callback( + WasmInterpreterModule* module, + WasmInterpreterImport* import, + uint32_t num_args, + WasmInterpreterTypedValue* args, + uint32_t num_results, + WasmInterpreterTypedValue* out_results, + void* user_data) { + assert(import->sig_index < module->sigs.size); + WasmInterpreterFuncSignature* sig = &module->sigs.data[import->sig_index]; + memset(out_results, 0, sizeof(WasmInterpreterTypedValue) * num_results); + printf("called import " PRIstringslice "." PRIstringslice "(", WASM_PRINTF_STRING_SLICE_ARG(import->module_name), - WASM_PRINTF_STRING_SLICE_ARG(import->func_name)); + WASM_PRINTF_STRING_SLICE_ARG(import->field_name)); uint32_t i; for (i = 0; i < num_args; ++i) { print_typed_value(&args[i]); @@ -247,21 +253,14 @@ static WasmResult default_import_callback(WasmInterpreterModule* module, printf(", "); } - assert(import->sig_index < module->sigs.size); - WasmInterpreterFuncSignature* sig = &module->sigs.data[import->sig_index]; - - WasmInterpreterTypedValue result; - WASM_ZERO_MEMORY(result); - result.type = sig->result_type; - - if (sig->result_type != WASM_TYPE_VOID) { - printf(") => "); - print_typed_value(&result); - printf("\n"); - } else { - printf(")\n"); + printf(") => ("); + for (i = 0; i < num_results; ++i) { + out_results[i].type = sig->result_types.data[i]; + print_typed_value(&out_results[i]); + if (i != num_results - 1) + printf(", "); } - *out_result = result; + printf(")\n"); return WASM_OK; } @@ -310,10 +309,11 @@ static WasmResult run_start_function(WasmInterpreterModule* module, } static WasmInterpreterResult run_export( + WasmAllocator* allocator, WasmInterpreterModule* module, WasmInterpreterThread* thread, WasmInterpreterExport* export, - WasmInterpreterTypedValue* out_return_value, + WasmInterpreterTypedValueVector* out_results, RunVerbosity verbose) { /* pass all zeroes to the function */ assert(export->sig_index < module->sigs.size); @@ -339,23 +339,25 @@ static WasmInterpreterResult run_export( if (i != num_params - 1) printf(", "); } - if (sig->result_type != WASM_TYPE_VOID) - printf(") => "); - else - printf(") "); + printf(") => "); } if (result == WASM_INTERPRETER_RETURNED) { - out_return_value->type = sig->result_type; - - if (sig->result_type != WASM_TYPE_VOID) { - assert(thread->value_stack_top == 1); - out_return_value->value = thread->value_stack.data[0]; - - if (verbose) - print_typed_value(out_return_value); - } else { - assert(thread->value_stack_top == 0); + uint32_t expected_results = sig->result_types.size; + assert(expected_results == thread->value_stack.size); + wasm_resize_interpreter_typed_value_vector(allocator, out_results, + expected_results); + uint32_t i; + for (i = 0; i < expected_results; ++i) { + /* copy as many results as the caller wants */ + out_results->data[i].type = sig->result_types.data[i]; + out_results->data[i].value = thread->value_stack.data[i]; + + if (verbose) { + print_typed_value(&out_results->data[i]); + if (i != expected_results - 1) + printf(", "); + } } if (verbose) @@ -371,29 +373,31 @@ static WasmInterpreterResult run_export( } static WasmResult run_export_by_name( + WasmAllocator* allocator, WasmInterpreterModule* module, WasmInterpreterThread* thread, WasmStringSlice* name, WasmInterpreterResult* out_iresult, - WasmInterpreterTypedValue* out_return_value, + WasmInterpreterTypedValueVector* out_results, RunVerbosity verbose) { WasmInterpreterExport* export = wasm_get_interpreter_export_by_name(module, name); if (!export) return WASM_ERROR; - *out_iresult = run_export(module, thread, export, out_return_value, verbose); + *out_iresult = + run_export(allocator, module, thread, export, out_results, verbose); return WASM_OK; } -static void run_all_exports(WasmInterpreterModule* module, +static void run_all_exports(WasmAllocator* allocator, + WasmInterpreterModule* module, WasmInterpreterThread* thread, RunVerbosity verbose) { uint32_t i; for (i = 0; i < module->exports.size; ++i) { WasmInterpreterExport* export = &module->exports.data[i]; - WasmInterpreterTypedValue return_value; - run_export(module, thread, export, &return_value, verbose); + run_export(allocator, module, thread, export, NULL, verbose); } } @@ -445,7 +449,7 @@ static WasmResult read_and_run_module(WasmAllocator* allocator, result = run_start_function(&module, &thread); if (WASM_SUCCEEDED(result) && s_run_all_exports) - run_all_exports(&module, &thread, RUN_VERBOSE); + run_all_exports(allocator, &module, &thread, RUN_VERBOSE); destroy_module_and_thread(allocator, &module, &thread); return result; } @@ -458,6 +462,7 @@ static WasmResult read_and_run_spec_json(WasmAllocator* allocator, WasmStringSlice command_file; WasmStringSlice command_name; WasmAllocatorMark module_mark; + WasmInterpreterTypedValueVector result_values; uint32_t command_line_no; WasmBool has_module = WASM_FALSE; uint32_t passed = 0; @@ -468,6 +473,7 @@ static WasmResult read_and_run_spec_json(WasmAllocator* allocator, WASM_ZERO_MEMORY(command_file); WASM_ZERO_MEMORY(command_name); WASM_ZERO_MEMORY(module_mark); + WASM_ZERO_MEMORY(result_values); void* data; size_t size; @@ -673,12 +679,10 @@ static WasmResult read_and_run_spec_json(WasmAllocator* allocator, case END_COMMAND_OBJECT: { WasmInterpreterResult iresult; - WasmInterpreterTypedValue return_value; - WASM_ZERO_MEMORY(return_value); EXPECT('}'); RunVerbosity verbose = command_type == INVOKE ? RUN_VERBOSE : RUN_QUIET; - result = run_export_by_name(&module, &thread, &command_name, &iresult, - &return_value, verbose); + result = run_export_by_name(allocator, &module, &thread, &command_name, + &iresult, &result_values, verbose); if (WASM_FAILED(result)) { FAILED("unknown export"); failed++; @@ -698,10 +702,13 @@ static WasmResult read_and_run_spec_json(WasmAllocator* allocator, if (iresult != WASM_INTERPRETER_RETURNED) { FAILED("trapped"); failed++; - } else if (return_value.type != WASM_TYPE_I32) { + } else if (result_values.size != 1) { + FAILED("result arity mismatch"); + failed++; + } else if (result_values.data[0].type != WASM_TYPE_I32) { FAILED("type mismatch"); failed++; - } else if (return_value.value.i32 != 1) { + } else if (result_values.data[0].value.i32 != 1) { FAILED("didn't return 1"); failed++; } else { diff --git a/src/wasm-interpreter.c b/src/wasm-interpreter.c index f6eab79e..3129f599 100644 --- a/src/wasm-interpreter.c +++ b/src/wasm-interpreter.c @@ -94,7 +94,7 @@ WasmInterpreterImport* wasm_get_interpreter_import_by_name( for (i = 0; i < module->imports.size; ++i) { WasmInterpreterImport* import = &module->imports.data[i]; if (wasm_string_slices_are_equal(module_name, &import->module_name) && - wasm_string_slices_are_equal(func_name, &import->func_name)) { + wasm_string_slices_are_equal(func_name, &import->field_name)) { return import; } } @@ -604,15 +604,10 @@ static WasmBool signatures_are_equal(WasmInterpreterModule* module, uint32_t sig_index_1) { WasmInterpreterFuncSignature* sig_0 = &module->sigs.data[sig_index_0]; WasmInterpreterFuncSignature* sig_1 = &module->sigs.data[sig_index_1]; - if (sig_0->result_type != sig_1->result_type) - return WASM_FALSE; - if (sig_0->param_types.size != sig_1->param_types.size) - return WASM_FALSE; - size_t i; - for (i = 0; i < sig_0->param_types.size; ++i) - if (sig_0->param_types.data[i] != sig_1->param_types.data[i]) - return WASM_FALSE; - return WASM_TRUE; + return wasm_type_vectors_are_equal(&sig_0->param_types, + &sig_1->param_types) && + wasm_type_vectors_are_equal(&sig_0->result_types, + &sig_1->result_types); } WasmInterpreterResult wasm_run_interpreter(WasmInterpreterModule* module, @@ -701,14 +696,14 @@ WasmInterpreterResult wasm_run_interpreter(WasmInterpreterModule* module, case WASM_OPCODE_GET_GLOBAL: { uint32_t index = read_u32(&pc); assert(index < module->globals.size); - PUSH(module->globals.data[index].value); + PUSH(module->globals.data[index].typed_value.value); break; } case WASM_OPCODE_SET_GLOBAL: { uint32_t index = read_u32(&pc); assert(index < module->globals.size); - module->globals.data[index].value = POP(); + module->globals.data[index].typed_value.value = POP(); break; } @@ -756,6 +751,7 @@ WasmInterpreterResult wasm_run_interpreter(WasmInterpreterModule* module, uint32_t sig_index = import->sig_index; assert(sig_index < module->sigs.size); WasmInterpreterFuncSignature* sig = &module->sigs.data[sig_index]; + uint32_t num_args = sig->param_types.size; uint32_t i; assert(num_args <= thread->import_args.size); @@ -765,16 +761,21 @@ WasmInterpreterResult wasm_run_interpreter(WasmInterpreterModule* module, arg->type = sig->param_types.data[i - 1]; arg->value = value; } + + uint32_t num_results = sig->result_types.size; + WasmInterpreterTypedValue* call_result_values = + alloca(sizeof(WasmInterpreterTypedValue) * num_results); + assert(import->callback); - WasmInterpreterTypedValue call_result_value; - WasmResult call_result = - import->callback(module, import, num_args, thread->import_args.data, - &call_result_value, import->user_data); + WasmResult call_result = import->callback( + module, import, num_args, thread->import_args.data, num_results, + call_result_values, import->user_data); TRAP_IF(call_result != WASM_OK, IMPORT_TRAPPED); - if (sig->result_type != WASM_TYPE_VOID) { - TRAP_IF(call_result_value.type != sig->result_type, + + for (i = 0; i < num_results; ++i) { + TRAP_IF(call_result_values[i].type != sig->result_types.data[i], IMPORT_RESULT_TYPE_MISMATCH); - PUSH(call_result_value.value); + PUSH(call_result_values[i].value); } break; } @@ -2179,12 +2180,13 @@ static void wasm_destroy_interpreter_func_signature( WasmAllocator* allocator, WasmInterpreterFuncSignature* sig) { wasm_destroy_type_vector(allocator, &sig->param_types); + wasm_destroy_type_vector(allocator, &sig->result_types); } static void wasm_destroy_interpreter_import(WasmAllocator* allocator, WasmInterpreterImport* import) { wasm_destroy_string_slice(allocator, &import->module_name); - wasm_destroy_string_slice(allocator, &import->func_name); + wasm_destroy_string_slice(allocator, &import->field_name); } static void wasm_destroy_interpreter_export(WasmAllocator* allocator, diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index ca546216..7fe6a29f 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -113,6 +113,7 @@ typedef struct WasmInterpreterTypedValue { WasmInterpreterValue value; } WasmInterpreterTypedValue; WASM_DEFINE_ARRAY(interpreter_typed_value, WasmInterpreterTypedValue); +WASM_DEFINE_VECTOR(interpreter_typed_value, WasmInterpreterTypedValue); typedef struct WasmInterpreterGlobal { WasmInterpreterTypedValue typed_value; @@ -128,7 +129,8 @@ typedef WasmResult (*WasmInterpreterImportCallback)( struct WasmInterpreterImport* import, uint32_t num_args, WasmInterpreterTypedValue* args, - WasmInterpreterTypedValue* out_result, + uint32_t num_results, + WasmInterpreterTypedValue* out_results, void* user_data); typedef struct WasmInterpreterImport { diff --git a/src/wasm-type-vector.h b/src/wasm-type-vector.h index c8ec768b..5b7e08bf 100644 --- a/src/wasm-type-vector.h +++ b/src/wasm-type-vector.h @@ -22,4 +22,21 @@ WASM_DEFINE_VECTOR(type, WasmType) +WASM_EXTERN_C_BEGIN + +static WASM_INLINE WasmBool +wasm_type_vectors_are_equal(const WasmTypeVector* types1, + const WasmTypeVector* types2) { + if (types1->size != types2->size) + return WASM_FALSE; + size_t i; + for (i = 0; i < types1->size; ++i) { + if (types1->data[i] != types2->data[i]) + return WASM_FALSE; + } + return WASM_TRUE; +} + +WASM_EXTERN_C_END + #endif /* WASM_TYPE_VECTOR_H_ */ diff --git a/src/wast2wasm.c b/src/wast2wasm.c index 53876cef..74a3ef2e 100644 --- a/src/wast2wasm.c +++ b/src/wast2wasm.c @@ -320,7 +320,8 @@ static void on_command(uint32_t index, void* user_data) { static const char* s_command_names[] = { "module", - "invoke", + "action", + "register", "assert_invalid", "assert_return", "assert_return_nan", |