summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Smith <binji@chromium.org>2016-09-02 14:44:58 -0700
committerBen Smith <binji@chromium.org>2016-09-29 11:37:27 -0700
commit1fdcfa2b9cac4101f5ea0134c4ec2d9769bd7d05 (patch)
treeddf5d5e0b089a0509f911791aa1504d7b2b6a954 /src
parentde342e989d2892416771cd9e2b87c87abae776c1 (diff)
downloadwabt-1fdcfa2b9cac4101f5ea0134c4ec2d9769bd7d05.tar.gz
wabt-1fdcfa2b9cac4101f5ea0134c4ec2d9769bd7d05.tar.bz2
wabt-1fdcfa2b9cac4101f5ea0134c4ec2d9769bd7d05.zip
WIP fixing call_indirect
need to rewrite interpreter, I think
Diffstat (limited to 'src')
-rw-r--r--src/wasm-ast-checker.c4
-rw-r--r--src/wasm-binary-reader-interpreter.c26
-rw-r--r--src/wasm-interpreter.c24
3 files changed, 36 insertions, 18 deletions
diff --git a/src/wasm-ast-checker.c b/src/wasm-ast-checker.c
index 6b659965..e6f25c9d 100644
--- a/src/wasm-ast-checker.c
+++ b/src/wasm-ast-checker.c
@@ -645,6 +645,10 @@ static void check_expr(Context* ctx, const WasmExpr* expr) {
case WASM_EXPR_TYPE_CALL_INDIRECT: {
const WasmFuncType* func_type;
+ if (!ctx->current_module->table) {
+ print_error(ctx, CHECK_STYLE_FULL, &expr->loc,
+ "found call_indirect operator, but no table");
+ }
if (WASM_SUCCEEDED(
check_func_type_var(ctx, &expr->call_indirect.var, &func_type))) {
WasmCheckType type = pop_type(ctx);
diff --git a/src/wasm-binary-reader-interpreter.c b/src/wasm-binary-reader-interpreter.c
index ad11bccb..bcc8193d 100644
--- a/src/wasm-binary-reader-interpreter.c
+++ b/src/wasm-binary-reader-interpreter.c
@@ -607,12 +607,14 @@ static void pop_typecheck_label(Context* ctx) {
}
static void push_expr(Context* ctx, WasmType type, WasmOpcode opcode) {
- LOGF("%3" PRIzd ": push %s:%s (#%u)\n", ctx->expr_stack.size,
- s_opcode_name[opcode], s_type_names[type], ctx->expr_count);
- ExprNode* expr;
- expr = wasm_append_expr_node(ctx->allocator, &ctx->expr_stack);
- expr->index = ctx->expr_count;
- expr->type = type;
+ if (type != WASM_TYPE_VOID) {
+ LOGF("%3" PRIzd ": push %s:%s (#%u)\n", ctx->expr_stack.size,
+ s_opcode_name[opcode], s_type_names[type], ctx->expr_count);
+ ExprNode* expr;
+ expr = wasm_append_expr_node(ctx->allocator, &ctx->expr_stack);
+ expr->index = ctx->expr_count;
+ expr->type = type;
+ }
ctx->expr_count++;
}
@@ -944,6 +946,9 @@ 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);
+ 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);
@@ -951,8 +956,6 @@ static WasmResult on_call_indirect_expr(uint32_t sig_index, void* user_data) {
check_type(ctx, sig->param_types.data[i - 1], arg, "call_indirect"));
}
- WasmType entry_index = pop_expr(ctx);
- CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, entry_index, "call_indirect"));
push_expr(ctx, sig->result_type, WASM_OPCODE_CALL_INDIRECT);
return WASM_OK;
}
@@ -1608,11 +1611,8 @@ static WasmResult on_emit_call_indirect_expr(uint32_t sig_index,
WasmInterpreterFuncSignature* sig = get_signature(ctx, sig_index);
CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_INDIRECT));
CHECK_RESULT(emit_i32(ctx, sig_index));
- uint32_t result_count = get_value_count(sig->result_type);
- /* the callee cleans up the params for us, but we have to clean up the
- * function table index */
- adjust_value_stack(ctx, result_count - sig->param_types.size);
- CHECK_RESULT(emit_discard_keep(ctx, 1, result_count));
+ adjust_value_stack(ctx,
+ get_value_count(sig->result_type) - sig->param_types.size);
adjust_value_stack(ctx, -1);
CHECK_RESULT(maybe_emit_discard(ctx, ctx->expr_count));
ctx->expr_count++;
diff --git a/src/wasm-interpreter.c b/src/wasm-interpreter.c
index 5e33aea5..4a8813f5 100644
--- a/src/wasm-interpreter.c
+++ b/src/wasm-interpreter.c
@@ -594,6 +594,22 @@ static WASM_INLINE void read_table_entry_at(const uint8_t* pc,
*out_keep = *(pc + WASM_TABLE_ENTRY_KEEP_OFFSET);
}
+static WasmBool signatures_are_equal(WasmInterpreterModule* module,
+ uint32_t sig_index_0,
+ 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;
+}
+
WasmInterpreterResult wasm_run_interpreter(WasmInterpreterModule* module,
WasmInterpreterThread* thread,
uint32_t num_instructions,
@@ -718,14 +734,12 @@ WasmInterpreterResult wasm_run_interpreter(WasmInterpreterModule* module,
case WASM_OPCODE_CALL_INDIRECT: {
uint32_t sig_index = read_u32(&pc);
assert(sig_index < module->sigs.size);
- WasmInterpreterFuncSignature* sig = &module->sigs.data[sig_index];
- uint32_t num_args = sig->param_types.size;
- VALUE_TYPE_I32 entry_index = PICK(num_args + 1).i32;
+ VALUE_TYPE_I32 entry_index = POP_I32();
TRAP_IF(entry_index >= module->func_table.size, UNDEFINED_TABLE_INDEX);
WasmInterpreterFuncTableEntry* entry =
&module->func_table.data[entry_index];
- TRAP_IF(entry->sig_index != sig_index,
- INDIRECT_CALL_SIGNATURE_MISMATCH);
+ TRAP_UNLESS(signatures_are_equal(module, entry->sig_index, sig_index),
+ INDIRECT_CALL_SIGNATURE_MISMATCH);
PUSH_CALL();
GOTO(entry->func_offset);
break;