diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-binary-reader-interpreter.c | 591 | ||||
-rw-r--r-- | src/wasm-binary-reader.c | 22 | ||||
-rw-r--r-- | src/wasm-binary-reader.h | 7 | ||||
-rw-r--r-- | src/wasm-binary-writer.c | 99 | ||||
-rw-r--r-- | src/wasm-common.h | 26 |
5 files changed, 245 insertions, 500 deletions
diff --git a/src/wasm-binary-reader-interpreter.c b/src/wasm-binary-reader-interpreter.c index d45e2742..7296b7e2 100644 --- a/src/wasm-binary-reader-interpreter.c +++ b/src/wasm-binary-reader-interpreter.c @@ -698,6 +698,7 @@ static WasmResult on_local_decl(uint32_t decl_index, return WASM_OK; } +#if 0 static WasmResult reduce(WasmContext* ctx, WasmInterpreterExpr* expr) { WasmBool done = WASM_FALSE; while (!done) { @@ -769,124 +770,6 @@ static WasmResult reduce(WasmContext* ctx, WasmInterpreterExpr* expr) { } break; - case WASM_OPCODE_BR: { - assert(cur_index == 0 && is_expr_done); - uint32_t depth = top->expr.br.depth; - WasmDepthNode* node = get_depth_node(ctx, depth); - CHECK_RESULT( - unify_and_check_type(ctx, &node->type, expr->type, " in br")); - CHECK_RESULT(emit_br(ctx, depth, node)); - break; - } - - case WASM_OPCODE_BR_IF: { - uint32_t depth = top->expr.br.depth; - WasmDepthNode* node = get_depth_node(ctx, depth); - if (cur_index == 0) { - CHECK_RESULT(unify_and_check_type(ctx, &node->type, expr->type, - " in br_if")); - } else { - /* this actually flips the br_if so if <cond> is true it can - * discard values from the stack, e.g.: - * - * (br_if DEST <value> <cond>) - * - * becomes - * - * <value> value - * <cond> value cond - * br_unless OVER value - * discard_keep ... value - * br DEST value - * OVER: - * discard - * ... - */ - assert(cur_index == 1 && is_expr_done); - CHECK_RESULT( - check_type(ctx, WASM_TYPE_I32, expr->type, " in br_if")); - 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)); - /* adjust stack to account for br_unless consuming <cond> */ - adjust_value_stack(ctx, -get_value_count(expr->type)); - CHECK_RESULT(emit_br(ctx, depth, node)); - CHECK_RESULT( - emit_i32_at(ctx, fixup_br_offset, get_istream_offset(ctx))); - /* discard the value if the branch wasn't taken */ - CHECK_RESULT(maybe_emit_discard(ctx, node->type, NULL)); - } - break; - } - - case WASM_OPCODE_BR_TABLE: { - assert(cur_index == 0 && is_expr_done); - CHECK_RESULT( - check_type(ctx, WASM_TYPE_I32, expr->type, " in br_table")); - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_BR_TABLE)); - CHECK_RESULT(emit_i32(ctx, top->expr.br_table.num_targets)); - CHECK_RESULT(emit_i32(ctx, top->expr.br_table.table_offset)); - break; - } - - case WASM_OPCODE_CALL_FUNCTION: { - WasmInterpreterFunc* func = get_func(ctx, top->expr.call.func_index); - WasmInterpreterFuncSignature* sig = get_func_signature(ctx, func); - CHECK_RESULT(check_type(ctx, sig->param_types.data[cur_index], - expr->type, " in call")); - if (is_expr_done) { - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_FUNCTION)); - CHECK_RESULT( - emit_func_offset(ctx, func, top->expr.call.func_index)); - result_count = get_value_count(sig->result_type); - } - break; - } - - case WASM_OPCODE_CALL_IMPORT: { - WasmInterpreterImport* import = - get_import(ctx, top->expr.call_import.import_index); - WasmInterpreterFuncSignature* sig = - get_signature(ctx, import->sig_index); - CHECK_RESULT(check_type(ctx, sig->param_types.data[cur_index], - expr->type, " in call_import")); - if (is_expr_done) { - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_IMPORT)); - CHECK_RESULT(emit_i32(ctx, top->expr.call_import.import_index)); - result_count = get_value_count(sig->result_type); - } - break; - } - - case WASM_OPCODE_CALL_INDIRECT: { - WasmInterpreterFuncSignature* sig = - get_signature(ctx, top->expr.call_indirect.sig_index); - if (cur_index == 0) { - CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, expr->type, - " in call_indirect")); - } else { - CHECK_RESULT(check_type(ctx, sig->param_types.data[cur_index - 1], - expr->type, " in call_indirect")); - } - if (is_expr_done) { - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_INDIRECT)); - CHECK_RESULT(emit_i32(ctx, top->expr.call_indirect.sig_index)); - /* the callee cleans up the params for us, but we have to clean up - * the function table index */ - result_count = get_value_count(sig->result_type); - CHECK_RESULT(emit_discard_keep(ctx, 1, result_count)); - } - break; - } - - case WASM_OPCODE_GROW_MEMORY: - assert(cur_index == 0 && is_expr_done); - CHECK_RESULT( - check_type(ctx, WASM_TYPE_I32, expr->type, " in grow_memory")); - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_GROW_MEMORY)); - result_count = 1; - break; - case WASM_OPCODE_IF: if (cur_index == 0) { /* after cond */ @@ -957,28 +840,6 @@ static WasmResult reduce(WasmContext* ctx, WasmInterpreterExpr* expr) { break; } - case WASM_OPCODE_I32_LOAD8_S: - case WASM_OPCODE_I32_LOAD8_U: - case WASM_OPCODE_I32_LOAD16_S: - case WASM_OPCODE_I32_LOAD16_U: - case WASM_OPCODE_I64_LOAD8_S: - case WASM_OPCODE_I64_LOAD8_U: - case WASM_OPCODE_I64_LOAD16_S: - case WASM_OPCODE_I64_LOAD16_U: - case WASM_OPCODE_I64_LOAD32_S: - case WASM_OPCODE_I64_LOAD32_U: - case WASM_OPCODE_I32_LOAD: - case WASM_OPCODE_I64_LOAD: - case WASM_OPCODE_F32_LOAD: - case WASM_OPCODE_F64_LOAD: - assert(cur_index == 0 && is_expr_done); - /* TODO use opcode name here */ - CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, expr->type, " in load")); - CHECK_RESULT(emit_opcode(ctx, top->expr.opcode)); - CHECK_RESULT(emit_i32(ctx, top->expr.load.mem_offset)); - result_count = 1; - break; - case WASM_OPCODE_LOOP: { if (is_expr_done) { WasmDepthNode* node = top_minus_nth_depth_node(ctx, 2); @@ -995,155 +856,97 @@ static WasmResult reduce(WasmContext* ctx, WasmInterpreterExpr* expr) { } break; } +#endif - case WASM_OPCODE_RETURN: { - WasmInterpreterFuncSignature* sig = - get_func_signature(ctx, ctx->current_func); - CHECK_RESULT( - check_type(ctx, sig->result_type, expr->type, " in return")); - CHECK_RESULT(emit_return(ctx, sig->result_type)); - break; - } - - case WASM_OPCODE_SELECT: { - if (is_expr_done) { - assert(cur_index == 2); - CHECK_RESULT( - check_type(ctx, WASM_TYPE_I32, expr->type, " in select")); - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_SELECT)); - result_count = 1; - } else { - assert(cur_index < 2); - CHECK_RESULT(unify_and_check_type(ctx, &top->expr.type, expr->type, - " in select")); - } - break; - } - - case WASM_OPCODE_SET_LOCAL: { - assert(cur_index == 0 && is_expr_done); - CHECK_RESULT( - check_type(ctx, top->expr.type, expr->type, " in set_local")); - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_SET_LOCAL)); - uint32_t local_index = - translate_local_index(ctx, top->expr.set_local.local_index); - CHECK_RESULT(emit_i32(ctx, local_index)); - result_count = 1; - break; - } - - case WASM_OPCODE_I32_STORE8: - case WASM_OPCODE_I32_STORE16: - case WASM_OPCODE_I64_STORE8: - case WASM_OPCODE_I64_STORE16: - case WASM_OPCODE_I64_STORE32: - case WASM_OPCODE_I32_STORE: - case WASM_OPCODE_I64_STORE: - case WASM_OPCODE_F32_STORE: - case WASM_OPCODE_F64_STORE: - if (cur_index == 0) { - /* TODO use opcode name here */ - CHECK_RESULT( - check_type(ctx, WASM_TYPE_I32, expr->type, " in store")); - } else { - assert(cur_index == 1 && is_expr_done); - CHECK_RESULT( - check_type(ctx, top->expr.type, expr->type, " in store")); - CHECK_RESULT(emit_opcode(ctx, top->expr.opcode)); - CHECK_RESULT(emit_i32(ctx, top->expr.store.mem_offset)); - result_count = 1; - } - break; - - case WASM_OPCODE_F32_CONST: - case WASM_OPCODE_F64_CONST: - case WASM_OPCODE_GET_LOCAL: - case WASM_OPCODE_I32_CONST: - case WASM_OPCODE_I64_CONST: - case WASM_OPCODE_MEMORY_SIZE: - case WASM_OPCODE_NOP: - case WASM_OPCODE_UNREACHABLE: - assert(0); - break; - } - - if (is_expr_done) { - /* "recurse" and reduce the current expr */ - ctx->value_stack_size = top->value_stack_size + result_count; - expr = &top->expr; - ctx->expr_stack.size--; - done = WASM_FALSE; - } - } - } - - return WASM_OK; +static WasmInterpreterExpr pop_expr(WasmContext* ctx) { + /* TODO(binji) */ + WasmInterpreterExpr expr; + WASM_ZERO_MEMORY(expr); + return expr; } -static WasmResult shift(WasmContext* ctx, - WasmInterpreterExpr* expr, - uint32_t count) { - assert(count > 0); - LOGF("%3" PRIzd "(%d): shift: %s:%s %u\n", ctx->expr_stack.size, - ctx->value_stack_size, s_opcode_name[expr->opcode], - s_type_names[expr->type], count); - WasmExprNode* node = wasm_append_expr_node(ctx->allocator, &ctx->expr_stack); - CHECK_ALLOC_NULL(ctx, node); - node->expr = *expr; - node->index = 0; - node->total = count; - node->value_stack_size = ctx->value_stack_size; - return WASM_OK; +static WasmResult push_expr(WasmContext* ctx, + WasmType type, + WasmOpcode opcode) { + return WASM_ERROR; } static WasmResult on_unary_expr(WasmOpcode opcode, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = s_opcode_rtype[opcode]; - expr.opcode = opcode; - return shift(ctx, &expr, 1); + WasmType rtype = s_opcode_rtype[opcode]; + WasmInterpreterExpr value = pop_expr(ctx); + /* TODO use opcode name here */ + CHECK_RESULT(check_type(ctx, rtype, value.type, "")); + CHECK_RESULT(emit_opcode(ctx, opcode)); + return push_expr(ctx, rtype, opcode); } static WasmResult on_binary_expr(WasmOpcode opcode, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = s_opcode_rtype[opcode]; - expr.opcode = opcode; - return shift(ctx, &expr, 2); + WasmType rtype = s_opcode_rtype[opcode]; + WasmInterpreterExpr right = pop_expr(ctx); + WasmInterpreterExpr left = pop_expr(ctx); + /* TODO use opcode name here */ + CHECK_RESULT(check_type(ctx, rtype, left.type, "")); + CHECK_RESULT(check_type(ctx, rtype, right.type, "")); + CHECK_RESULT(emit_opcode(ctx, opcode)); + return push_expr(ctx, s_opcode_rtype[opcode], opcode); } -static WasmResult on_block_expr(uint32_t count, void* user_data) { +static WasmResult on_block_expr(void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = count ? WASM_TYPE_ANY : WASM_TYPE_VOID; - expr.opcode = WASM_OPCODE_BLOCK; - expr.block.value_stack_size = ctx->value_stack_size; - if (count > 0) { - CHECK_RESULT(push_depth(ctx, expr.type)); - return shift(ctx, &expr, count); - } else { - return reduce(ctx, &expr); - } + CHECK_RESULT(push_depth(ctx, WASM_TYPE_ANY)); + return push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_BLOCK); } static WasmResult on_br_expr(uint32_t depth, void* user_data) { WasmContext* ctx = user_data; + WasmInterpreterExpr value = pop_expr(ctx); CHECK_DEPTH(ctx, depth); - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_ANY; - expr.opcode = WASM_OPCODE_BR; - expr.br.depth = translate_depth(ctx, depth); - return shift(ctx, &expr, 1); + depth = translate_depth(ctx, depth); + WasmDepthNode* node = get_depth_node(ctx, depth); + CHECK_RESULT(unify_and_check_type(ctx, &node->type, value.type, " in br")); + CHECK_RESULT(emit_br(ctx, depth, node)); + return push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_BR); } static WasmResult on_br_if_expr(uint32_t depth, void* user_data) { WasmContext* ctx = user_data; + WasmInterpreterExpr cond = pop_expr(ctx); + WasmInterpreterExpr value = pop_expr(ctx); CHECK_DEPTH(ctx, depth); - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_VOID; - expr.opcode = WASM_OPCODE_BR_IF; - expr.br.depth = translate_depth(ctx, depth); - return shift(ctx, &expr, 2); + depth = translate_depth(ctx, depth); + WasmDepthNode* node = get_depth_node(ctx, depth); + CHECK_RESULT(unify_and_check_type(ctx, &node->type, value.type, " in br")); + CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, cond.type, " in br_if")); + + /* this actually flips the br_if so if <cond> is true it can + * discard values from the stack, e.g.: + * + * (br_if DEST <value> <cond>) + * + * becomes + * + * <value> value + * <cond> value cond + * br_unless OVER value + * discard_keep ... value + * br DEST value + * OVER: + * discard + * ... + */ + 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)); + /* adjust stack to account for br_unless consuming <cond> */ + adjust_value_stack(ctx, -get_value_count(value.type)); + CHECK_RESULT(emit_br(ctx, depth, node)); + CHECK_RESULT(emit_i32_at(ctx, fixup_br_offset, get_istream_offset(ctx))); + /* discard the value if the branch wasn't taken */ + CHECK_RESULT(maybe_emit_discard(ctx, node->type, NULL)); + + return push_expr(ctx, WASM_TYPE_VOID, WASM_OPCODE_BR_IF); } static WasmResult on_br_table_expr(uint32_t num_targets, @@ -1151,26 +954,13 @@ static WasmResult on_br_table_expr(uint32_t num_targets, uint32_t default_target_depth, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_ANY; - expr.opcode = WASM_OPCODE_BR_TABLE; - expr.br_table.num_targets = num_targets; - - /* we need to parse the "key" expression before we can execute the br_table. - * Rather than store the target_depths in an Expr, we just write them out - * into the instruction stream and just jump over it. */ - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_BR)); - uint32_t fixup_br_offset = get_istream_offset(ctx); - CHECK_RESULT(emit_i32(ctx, WASM_INVALID_OFFSET)); - - /* not necessary for the interpreter, but it makes it easier to disassemble. - * This opcode specifies how many bytes of data follow. */ - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_DATA)); - CHECK_RESULT(emit_i32(ctx, (num_targets + 1) * sizeof(uint32_t) * 2)); + WasmInterpreterExpr key = pop_expr(ctx); + CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, key.type, " in br_table")); + CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_BR_TABLE)); + CHECK_RESULT(emit_i32(ctx, num_targets)); + CHECK_RESULT(emit_i32(ctx, get_istream_offset(ctx))); /* write the branch table as (offset, discard count) pairs */ - expr.br_table.table_offset = get_istream_offset(ctx); - uint32_t i; for (i = 0; i <= num_targets; ++i) { uint32_t depth = i != num_targets ? target_depths[i] : default_target_depth; @@ -1181,8 +971,7 @@ static WasmResult on_br_table_expr(uint32_t num_targets, CHECK_RESULT(emit_br_table_offset(ctx, translated_depth, node)); } - CHECK_RESULT(emit_i32_at(ctx, fixup_br_offset, get_istream_offset(ctx))); - return shift(ctx, &expr, 1); + return push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_BR_TABLE); } static WasmResult on_call_expr(uint32_t func_index, void* user_data) { @@ -1190,18 +979,18 @@ static WasmResult on_call_expr(uint32_t func_index, void* user_data) { assert(func_index < ctx->funcs.size); WasmInterpreterFunc* func = get_func(ctx, func_index); WasmInterpreterFuncSignature* sig = get_func_signature(ctx, func); - WasmInterpreterExpr expr; - expr.type = sig->result_type; - expr.opcode = WASM_OPCODE_CALL_FUNCTION; - expr.call.func_index = func_index; - if (sig->param_types.size > 0) { - return shift(ctx, &expr, sig->param_types.size); - } else { - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_FUNCTION)); - CHECK_RESULT(emit_func_offset(ctx, func, func_index)); - adjust_value_stack(ctx, get_value_count(sig->result_type)); - return reduce(ctx, &expr); + + uint32_t i; + for (i = sig->param_types.size; i > 0; ++i) { + WasmInterpreterExpr arg = pop_expr(ctx); + CHECK_RESULT( + check_type(ctx, sig->param_types.data[i - 1], arg.type, " in call")); } + + CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_FUNCTION)); + CHECK_RESULT(emit_func_offset(ctx, func, func_index)); + + return push_expr(ctx, sig->result_type, WASM_OPCODE_CALL_FUNCTION); } static WasmResult on_call_import_expr(uint32_t import_index, void* user_data) { @@ -1209,109 +998,104 @@ static WasmResult on_call_import_expr(uint32_t import_index, void* user_data) { assert(import_index < ctx->module->imports.size); WasmInterpreterImport* import = get_import(ctx, import_index); WasmInterpreterFuncSignature* sig = get_signature(ctx, import->sig_index); - WasmInterpreterExpr expr; - expr.type = sig->result_type; - expr.opcode = WASM_OPCODE_CALL_IMPORT; - expr.call_import.import_index = import_index; - if (sig->param_types.size > 0) { - return shift(ctx, &expr, sig->param_types.size); - } else { - CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_IMPORT)); - CHECK_RESULT(emit_i32(ctx, import_index)); - adjust_value_stack(ctx, get_value_count(sig->result_type)); - return reduce(ctx, &expr); + + uint32_t i; + for (i = sig->param_types.size; i > 0; ++i) { + WasmInterpreterExpr arg = pop_expr(ctx); + CHECK_RESULT(check_type(ctx, sig->param_types.data[i - 1], arg.type, + " in call_import")); } + + CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_IMPORT)); + CHECK_RESULT(emit_i32(ctx, import_index)); + + return push_expr(ctx, sig->result_type, WASM_OPCODE_CALL_IMPORT); } static WasmResult on_call_indirect_expr(uint32_t sig_index, void* user_data) { WasmContext* ctx = user_data; WasmInterpreterFuncSignature* sig = get_signature(ctx, sig_index); - WasmInterpreterExpr expr; - expr.type = sig->result_type; - expr.opcode = WASM_OPCODE_CALL_INDIRECT; - expr.call_indirect.sig_index = sig_index; - return shift(ctx, &expr, sig->param_types.size + 1); + + uint32_t i; + for (i = sig->param_types.size; i > 0; ++i) { + WasmInterpreterExpr arg = pop_expr(ctx); + CHECK_RESULT(check_type(ctx, sig->param_types.data[i - 1], arg.type, + " in call_indirect")); + } + + WasmInterpreterExpr entry_index = pop_expr(ctx); + CHECK_RESULT( + check_type(ctx, WASM_TYPE_I32, entry_index.type, " in call_indirect")); + + CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_CALL_INDIRECT)); + CHECK_RESULT(emit_i32(ctx, sig_index)); + /* the callee cleans up the params for us, but we have to clean up + * the function table index */ + uint32_t result_count = get_value_count(sig->result_type); + CHECK_RESULT(emit_discard_keep(ctx, 1, result_count)); + + return push_expr(ctx, sig->result_type, WASM_OPCODE_CALL_INDIRECT); +} + +static WasmResult on_end_expr(void* user_data) { + WasmContext* ctx = user_data; + return WASM_OK; } static WasmResult on_i32_const_expr(uint32_t value, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_I32; - expr.opcode = WASM_OPCODE_I32_CONST; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_I32_CONST)); CHECK_RESULT(emit_i32(ctx, value)); - adjust_value_stack(ctx, 1); - return reduce(ctx, &expr); + return push_expr(ctx, WASM_TYPE_I32, WASM_OPCODE_I32_CONST); } static WasmResult on_i64_const_expr(uint64_t value, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_I64; - expr.opcode = WASM_OPCODE_I64_CONST; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_I64_CONST)); CHECK_RESULT(emit_i64(ctx, value)); - adjust_value_stack(ctx, 1); - return reduce(ctx, &expr); + return push_expr(ctx, WASM_TYPE_I64, WASM_OPCODE_I64_CONST); } static WasmResult on_f32_const_expr(uint32_t value_bits, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_F32; - expr.opcode = WASM_OPCODE_F32_CONST; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_F32_CONST)); CHECK_RESULT(emit_i32(ctx, value_bits)); - adjust_value_stack(ctx, 1); - return reduce(ctx, &expr); + return push_expr(ctx, WASM_TYPE_F32, WASM_OPCODE_F32_CONST); } static WasmResult on_f64_const_expr(uint64_t value_bits, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_F64; - expr.opcode = WASM_OPCODE_F64_CONST; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_F64_CONST)); CHECK_RESULT(emit_i64(ctx, value_bits)); - adjust_value_stack(ctx, 1); - return reduce(ctx, &expr); + return push_expr(ctx, WASM_TYPE_F64, WASM_OPCODE_F64_CONST); } static WasmResult on_get_local_expr(uint32_t local_index, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = get_local_index_type(ctx->current_func, local_index); - expr.opcode = WASM_OPCODE_GET_LOCAL; - expr.get_local.local_index = translate_local_index(ctx, local_index); CHECK_LOCAL(ctx, local_index); + WasmType type = get_local_index_type(ctx->current_func, local_index); CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_GET_LOCAL)); - CHECK_RESULT(emit_i32(ctx, expr.get_local.local_index)); - adjust_value_stack(ctx, 1); - return reduce(ctx, &expr); + CHECK_RESULT(emit_i32(ctx, translate_local_index(ctx, local_index))); + return push_expr(ctx, type, WASM_OPCODE_GET_LOCAL); } static WasmResult on_grow_memory_expr(void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_I32; - expr.opcode = WASM_OPCODE_GROW_MEMORY; - return shift(ctx, &expr, 1); + WasmInterpreterExpr value = pop_expr(ctx); + CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, value.type, " in grow_memory")); + CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_GROW_MEMORY)); + return push_expr(ctx, WASM_TYPE_I32, WASM_OPCODE_GROW_MEMORY); } static WasmResult on_if_expr(void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_VOID; - expr.opcode = WASM_OPCODE_IF; - return shift(ctx, &expr, 2); + return push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_IF); } -static WasmResult on_if_else_expr(void* user_data) { - WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_ANY; - expr.opcode = WASM_OPCODE_IF_ELSE; - return shift(ctx, &expr, 3); +static WasmResult on_else_expr(void* user_data) { + /* TODO(binji): else is a bit weird, skip for now */ + /* pop backward until if, push else */ + return WASM_OK; } static WasmResult on_load_expr(WasmOpcode opcode, @@ -1319,80 +1103,66 @@ static WasmResult on_load_expr(WasmOpcode opcode, uint32_t offset, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = s_opcode_rtype[opcode]; - expr.opcode = opcode; - expr.load.mem_offset = offset; - expr.load.alignment_log2 = alignment_log2; - return shift(ctx, &expr, 1); + WasmInterpreterExpr addr = pop_expr(ctx); + /* TODO use opcode name here */ + CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, addr.type, " in load")); + CHECK_RESULT(emit_opcode(ctx, opcode)); + CHECK_RESULT(emit_i32(ctx, offset)); + return push_expr(ctx, s_opcode_rtype[opcode], opcode); } -static WasmResult on_loop_expr(uint32_t count, void* user_data) { +static WasmResult on_loop_expr(void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = count ? WASM_TYPE_ANY : WASM_TYPE_VOID; - expr.opcode = WASM_OPCODE_LOOP; - expr.loop.value_stack_size = ctx->value_stack_size; - if (count > 0) { - CHECK_RESULT(push_depth(ctx, expr.type)); /* exit */ - CHECK_RESULT(push_depth_with_offset( - ctx, WASM_TYPE_VOID, get_istream_offset(ctx))); /* continue */ - return shift(ctx, &expr, count); - } else { - return reduce(ctx, &expr); - } + CHECK_RESULT(push_depth(ctx, WASM_TYPE_ANY)); /* exit */ + CHECK_RESULT(push_depth_with_offset(ctx, WASM_TYPE_VOID, + get_istream_offset(ctx))); /* continue */ + return push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_LOOP); } static WasmResult on_memory_size_expr(void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_I32; - expr.opcode = WASM_OPCODE_MEMORY_SIZE; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_MEMORY_SIZE)); - adjust_value_stack(ctx, 1); - return reduce(ctx, &expr); + return push_expr(ctx, WASM_TYPE_I32, WASM_OPCODE_MEMORY_SIZE); } static WasmResult on_nop_expr(void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_VOID; - expr.opcode = WASM_OPCODE_NOP; - return reduce(ctx, &expr); + return push_expr(ctx, WASM_TYPE_VOID, WASM_OPCODE_NOP); } static WasmResult on_return_expr(void* user_data) { WasmContext* ctx = user_data; WasmInterpreterFuncSignature* sig = get_func_signature(ctx, ctx->current_func); - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_ANY; - expr.opcode = WASM_OPCODE_RETURN; - uint32_t result_count = get_value_count(sig->result_type); - if (result_count > 0) { - return shift(ctx, &expr, result_count); - } else { - CHECK_RESULT(emit_return(ctx, sig->result_type)); - return reduce(ctx, &expr); + if (get_value_count(sig->result_type)) { + WasmInterpreterExpr value = pop_expr(ctx); + CHECK_RESULT(check_type(ctx, sig->result_type, value.type, " in return")); } + CHECK_RESULT(emit_return(ctx, sig->result_type)); + return push_expr(ctx, sig->result_type, WASM_OPCODE_RETURN); } static WasmResult on_select_expr(void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_ANY; - expr.opcode = WASM_OPCODE_SELECT; - return shift(ctx, &expr, 3); + WasmInterpreterExpr cond = pop_expr(ctx); + WasmInterpreterExpr right = pop_expr(ctx); + WasmInterpreterExpr left = pop_expr(ctx); + WasmType type = WASM_TYPE_ANY; + CHECK_RESULT(unify_and_check_type(ctx, &type, left.type, " in select")); + CHECK_RESULT(unify_and_check_type(ctx, &type, right.type, " in select")); + CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, cond.type, " in select")); + return push_expr(ctx, type, WASM_OPCODE_SELECT); } static WasmResult on_set_local_expr(uint32_t local_index, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = get_local_index_type(ctx->current_func, local_index); - expr.opcode = WASM_OPCODE_SET_LOCAL; - expr.set_local.local_index = local_index; CHECK_LOCAL(ctx, local_index); - return shift(ctx, &expr, 1); + WasmType type = get_local_index_type(ctx->current_func, local_index); + WasmInterpreterExpr value = pop_expr(ctx); + CHECK_RESULT(check_type(ctx, type, value.type, " in set_local")); + CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_SET_LOCAL)); + CHECK_RESULT(emit_i32(ctx, translate_local_index(ctx, local_index))); + return push_expr(ctx, type, WASM_OPCODE_SET_LOCAL); } static WasmResult on_store_expr(WasmOpcode opcode, @@ -1400,21 +1170,21 @@ static WasmResult on_store_expr(WasmOpcode opcode, uint32_t offset, void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = s_opcode_rtype[opcode]; - expr.opcode = opcode; - expr.store.mem_offset = offset; - expr.store.alignment_log2 = alignment_log2; - return shift(ctx, &expr, 2); + WasmInterpreterExpr value = pop_expr(ctx); + WasmInterpreterExpr addr = pop_expr(ctx); + WasmType type = s_opcode_rtype[opcode]; + /* TODO use opcode name here */ + CHECK_RESULT(check_type(ctx, WASM_TYPE_I32, addr.type, " in store")); + CHECK_RESULT(check_type(ctx, type, value.type, " in store")); + CHECK_RESULT(emit_opcode(ctx, opcode)); + CHECK_RESULT(emit_i32(ctx, offset)); + return push_expr(ctx, type, opcode); } static WasmResult on_unreachable_expr(void* user_data) { WasmContext* ctx = user_data; - WasmInterpreterExpr expr; - expr.type = WASM_TYPE_ANY; - expr.opcode = WASM_OPCODE_UNREACHABLE; CHECK_RESULT(emit_opcode(ctx, WASM_OPCODE_UNREACHABLE)); - return reduce(ctx, &expr); + return push_expr(ctx, WASM_TYPE_ANY, WASM_OPCODE_UNREACHABLE); } static WasmResult on_function_table_count(uint32_t count, void* user_data) { @@ -1529,6 +1299,8 @@ static WasmBinaryReader s_binary_reader = { .on_call_import_expr = &on_call_import_expr, .on_call_indirect_expr = &on_call_indirect_expr, .on_compare_expr = &on_binary_expr, + .on_else_expr = &on_else_expr, + .on_end_expr = &on_end_expr, .on_i32_const_expr = &on_i32_const_expr, .on_i64_const_expr = &on_i64_const_expr, .on_f32_const_expr = &on_f32_const_expr, @@ -1537,7 +1309,6 @@ static WasmBinaryReader s_binary_reader = { .on_get_local_expr = &on_get_local_expr, .on_grow_memory_expr = &on_grow_memory_expr, .on_if_expr = &on_if_expr, - .on_if_else_expr = &on_if_else_expr, .on_load_expr = &on_load_expr, .on_loop_expr = &on_loop_expr, .on_memory_size_expr = &on_memory_size_expr, diff --git a/src/wasm-binary-reader.c b/src/wasm-binary-reader.c index 47497b07..327ac242 100644 --- a/src/wasm-binary-reader.c +++ b/src/wasm-binary-reader.c @@ -588,26 +588,20 @@ WasmResult wasm_read_binary(WasmAllocator* allocator, CALLBACK0(&ctx, on_nop_expr); break; - case WASM_OPCODE_BLOCK: { - uint32_t num_exprs; - in_u32_leb128(&ctx, &num_exprs, "block expression count"); - CALLBACK(&ctx, on_block_expr, num_exprs); + case WASM_OPCODE_BLOCK: + CALLBACK0(&ctx, on_block_expr); break; - } - case WASM_OPCODE_LOOP: { - uint32_t num_exprs; - in_u32_leb128(&ctx, &num_exprs, "loop expression count"); - CALLBACK(&ctx, on_loop_expr, num_exprs); + case WASM_OPCODE_LOOP: + CALLBACK0(&ctx, on_loop_expr); break; - } case WASM_OPCODE_IF: CALLBACK0(&ctx, on_if_expr); break; - case WASM_OPCODE_IF_ELSE: - CALLBACK0(&ctx, on_if_else_expr); + case WASM_OPCODE_ELSE: + CALLBACK0(&ctx, on_else_expr); break; case WASM_OPCODE_SELECT: @@ -662,6 +656,10 @@ WasmResult wasm_read_binary(WasmAllocator* allocator, CALLBACK0(&ctx, on_unreachable_expr); break; + case WASM_OPCODE_END: + CALLBACK0(&ctx, on_end_expr); + break; + case WASM_OPCODE_I32_CONST: { uint32_t value = 0; in_i32_leb128(&ctx, &value, "i32.const value"); diff --git a/src/wasm-binary-reader.h b/src/wasm-binary-reader.h index 470f0a56..ad4c8a12 100644 --- a/src/wasm-binary-reader.h +++ b/src/wasm-binary-reader.h @@ -99,7 +99,7 @@ typedef struct WasmBinaryReader { /* function expressions; called between begin_function_body and end_function_body */ WasmResult (*on_binary_expr)(WasmOpcode opcode, void* user_data); - WasmResult (*on_block_expr)(uint32_t count, void* user_data); + WasmResult (*on_block_expr)(void* user_data); WasmResult (*on_br_expr)(uint32_t depth, void* user_data); WasmResult (*on_br_if_expr)(uint32_t depth, void* user_data); WasmResult (*on_br_table_expr)(uint32_t num_targets, @@ -110,6 +110,8 @@ typedef struct WasmBinaryReader { WasmResult (*on_call_import_expr)(uint32_t import_index, void* user_data); WasmResult (*on_call_indirect_expr)(uint32_t sig_index, void* user_data); WasmResult (*on_compare_expr)(WasmOpcode opcode, void* user_data); + WasmResult (*on_else_expr)(void* user_data); + WasmResult (*on_end_expr)(void* user_data); WasmResult (*on_i32_const_expr)(uint32_t value, void* user_data); WasmResult (*on_i64_const_expr)(uint64_t value, void* user_data); WasmResult (*on_f32_const_expr)(uint32_t value_bits, void* user_data); @@ -118,12 +120,11 @@ typedef struct WasmBinaryReader { WasmResult (*on_get_local_expr)(uint32_t local_index, void* user_data); WasmResult (*on_grow_memory_expr)(void* user_data); WasmResult (*on_if_expr)(void* user_data); - WasmResult (*on_if_else_expr)(void* user_data); WasmResult (*on_load_expr)(WasmOpcode opcode, uint32_t alignment_log2, uint32_t offset, void* user_data); - WasmResult (*on_loop_expr)(uint32_t count, void* user_data); + WasmResult (*on_loop_expr)(void* user_data); WasmResult (*on_memory_size_expr)(void* user_data); WasmResult (*on_nop_expr)(void* user_data); WasmResult (*on_return_expr)(void* user_data); diff --git a/src/wasm-binary-writer.c b/src/wasm-binary-writer.c index e713e92d..00ac5e12 100644 --- a/src/wasm-binary-writer.c +++ b/src/wasm-binary-writer.c @@ -472,84 +472,80 @@ static void write_expr_list(WasmContext* ctx, const WasmFunc* func, const WasmExprPtrVector* exprs); -static void write_expr_list_with_count(WasmContext* ctx, - const WasmModule* module, - const WasmFunc* func, - const WasmExprPtrVector* exprs); - -static void write_block(WasmContext* ctx, - const WasmModule* module, - const WasmFunc* func, - const WasmBlock* block); - static void write_expr(WasmContext* ctx, const WasmModule* module, const WasmFunc* func, const WasmExpr* expr) { switch (expr->type) { case WASM_EXPR_TYPE_BINARY: - write_opcode(&ctx->stream, expr->binary.opcode); write_expr(ctx, module, func, expr->binary.left); write_expr(ctx, module, func, expr->binary.right); + write_opcode(&ctx->stream, expr->binary.opcode); break; - case WASM_EXPR_TYPE_BLOCK: - write_block(ctx, module, func, &expr->block); + case WASM_EXPR_TYPE_BLOCK: { + WasmLabelNode node; + push_label(ctx, &node, &expr->block.label); + write_opcode(&ctx->stream, WASM_OPCODE_BLOCK); + write_expr_list(ctx, module, func, &expr->block.exprs); + write_opcode(&ctx->stream, WASM_OPCODE_END); + pop_label(ctx, &expr->block.label); break; + } case WASM_EXPR_TYPE_BR: { WasmLabelNode* node = find_label_by_var(ctx->top_label, &expr->br.var); assert(node); - write_opcode(&ctx->stream, WASM_OPCODE_BR); - write_u32_leb128(&ctx->stream, ctx->max_depth - node->depth - 1, - "break depth"); if (expr->br.expr) write_expr(ctx, module, func, expr->br.expr); else write_opcode(&ctx->stream, WASM_OPCODE_NOP); + write_opcode(&ctx->stream, WASM_OPCODE_BR); + write_u32_leb128(&ctx->stream, ctx->max_depth - node->depth - 1, + "break depth"); break; } case WASM_EXPR_TYPE_BR_IF: { WasmLabelNode* node = find_label_by_var(ctx->top_label, &expr->br_if.var); assert(node); - write_opcode(&ctx->stream, WASM_OPCODE_BR_IF); - write_u32_leb128(&ctx->stream, ctx->max_depth - node->depth - 1, - "break depth"); if (expr->br_if.expr) write_expr(ctx, module, func, expr->br_if.expr); else write_opcode(&ctx->stream, WASM_OPCODE_NOP); write_expr(ctx, module, func, expr->br_if.cond); + write_opcode(&ctx->stream, WASM_OPCODE_BR_IF); + write_u32_leb128(&ctx->stream, ctx->max_depth - node->depth - 1, + "break depth"); break; } case WASM_EXPR_TYPE_CALL: { int index = wasm_get_func_index_by_var(module, &expr->call.var); assert(index >= 0 && (size_t)index < module->funcs.size); + write_expr_list(ctx, module, func, &expr->call.args); write_opcode(&ctx->stream, WASM_OPCODE_CALL_FUNCTION); write_u32_leb128(&ctx->stream, index, "func index"); - write_expr_list(ctx, module, func, &expr->call.args); break; } case WASM_EXPR_TYPE_CALL_IMPORT: { int index = wasm_get_import_index_by_var(module, &expr->call.var); assert(index >= 0 && (size_t)index < module->imports.size); + write_expr_list(ctx, module, func, &expr->call.args); write_opcode(&ctx->stream, WASM_OPCODE_CALL_IMPORT); write_u32_leb128(&ctx->stream, index, "import index"); - write_expr_list(ctx, module, func, &expr->call.args); break; } case WASM_EXPR_TYPE_CALL_INDIRECT: { int index = wasm_get_func_type_index_by_var(module, &expr->call_indirect.var); assert(index >= 0 && (size_t)index < module->func_types.size); - write_opcode(&ctx->stream, WASM_OPCODE_CALL_INDIRECT); - write_u32_leb128(&ctx->stream, index, "signature index"); write_expr(ctx, module, func, expr->call_indirect.expr); write_expr_list(ctx, module, func, &expr->call_indirect.args); + write_opcode(&ctx->stream, WASM_OPCODE_CALL_INDIRECT); + write_u32_leb128(&ctx->stream, index, "signature index"); break; } case WASM_EXPR_TYPE_COMPARE: - write_opcode(&ctx->stream, expr->compare.opcode); write_expr(ctx, module, func, expr->compare.left); write_expr(ctx, module, func, expr->compare.right); + write_opcode(&ctx->stream, expr->compare.opcode); break; case WASM_EXPR_TYPE_CONST: switch (expr->const_.type) { @@ -577,8 +573,8 @@ static void write_expr(WasmContext* ctx, } break; case WASM_EXPR_TYPE_CONVERT: - write_opcode(&ctx->stream, expr->convert.opcode); write_expr(ctx, module, func, expr->convert.expr); + write_opcode(&ctx->stream, expr->convert.opcode); break; case WASM_EXPR_TYPE_GET_LOCAL: { int index = wasm_get_local_index_by_var(func, &expr->get_local.var); @@ -588,21 +584,25 @@ static void write_expr(WasmContext* ctx, break; } case WASM_EXPR_TYPE_GROW_MEMORY: - write_opcode(&ctx->stream, WASM_OPCODE_GROW_MEMORY); write_expr(ctx, module, func, expr->grow_memory.expr); + write_opcode(&ctx->stream, WASM_OPCODE_GROW_MEMORY); break; case WASM_EXPR_TYPE_IF: - write_opcode(&ctx->stream, WASM_OPCODE_IF); write_expr(ctx, module, func, expr->if_.cond); + write_opcode(&ctx->stream, WASM_OPCODE_IF); write_expr(ctx, module, func, expr->if_.true_); + write_opcode(&ctx->stream, WASM_OPCODE_END); break; case WASM_EXPR_TYPE_IF_ELSE: - write_opcode(&ctx->stream, WASM_OPCODE_IF_ELSE); write_expr(ctx, module, func, expr->if_else.cond); + write_opcode(&ctx->stream, WASM_OPCODE_IF); write_expr(ctx, module, func, expr->if_else.true_); + write_opcode(&ctx->stream, WASM_OPCODE_ELSE); write_expr(ctx, module, func, expr->if_else.false_); + write_opcode(&ctx->stream, WASM_OPCODE_END); break; case WASM_EXPR_TYPE_LOAD: { + write_expr(ctx, module, func, expr->load.addr); write_opcode(&ctx->stream, expr->load.opcode); uint32_t align = wasm_get_opcode_alignment(expr->load.opcode, expr->load.align); @@ -614,7 +614,6 @@ static void write_expr(WasmContext* ctx, wasm_write_u8(&ctx->stream, align_log, "alignment"); write_u32_leb128(&ctx->stream, (uint32_t)expr->load.offset, "load offset"); - write_expr(ctx, module, func, expr->load.addr); break; } case WASM_EXPR_TYPE_LOOP: { @@ -623,7 +622,8 @@ static void write_expr(WasmContext* ctx, push_label(ctx, &outer, &expr->loop.outer); push_label(ctx, &inner, &expr->loop.inner); write_opcode(&ctx->stream, WASM_OPCODE_LOOP); - write_expr_list_with_count(ctx, module, func, &expr->loop.exprs); + write_expr_list(ctx, module, func, &expr->loop.exprs); + write_opcode(&ctx->stream, WASM_OPCODE_END); pop_label(ctx, &expr->loop.inner); pop_label(ctx, &expr->loop.outer); break; @@ -635,25 +635,27 @@ static void write_expr(WasmContext* ctx, write_opcode(&ctx->stream, WASM_OPCODE_NOP); break; case WASM_EXPR_TYPE_RETURN: - write_opcode(&ctx->stream, WASM_OPCODE_RETURN); if (expr->return_.expr) write_expr(ctx, module, func, expr->return_.expr); + write_opcode(&ctx->stream, WASM_OPCODE_RETURN); break; case WASM_EXPR_TYPE_SELECT: - write_opcode(&ctx->stream, WASM_OPCODE_SELECT); write_expr(ctx, module, func, expr->select.true_); write_expr(ctx, module, func, expr->select.false_); write_expr(ctx, module, func, expr->select.cond); + write_opcode(&ctx->stream, WASM_OPCODE_SELECT); break; case WASM_EXPR_TYPE_SET_LOCAL: { int index = wasm_get_local_index_by_var(func, &expr->get_local.var); + write_expr(ctx, module, func, expr->set_local.expr); write_opcode(&ctx->stream, WASM_OPCODE_SET_LOCAL); write_u32_leb128(&ctx->stream, ctx->remapped_locals[index], "remapped local index"); - write_expr(ctx, module, func, expr->set_local.expr); break; } case WASM_EXPR_TYPE_STORE: { + write_expr(ctx, module, func, expr->store.addr); + write_expr(ctx, module, func, expr->store.value); write_opcode(&ctx->stream, expr->store.opcode); uint32_t align = wasm_get_opcode_alignment(expr->store.opcode, expr->store.align); @@ -665,11 +667,10 @@ static void write_expr(WasmContext* ctx, wasm_write_u8(&ctx->stream, align_log, "alignment"); write_u32_leb128(&ctx->stream, (uint32_t)expr->store.offset, "store offset"); - write_expr(ctx, module, func, expr->store.addr); - write_expr(ctx, module, func, expr->store.value); break; } case WASM_EXPR_TYPE_BR_TABLE: { + write_expr(ctx, module, func, expr->br_table.expr); write_opcode(&ctx->stream, WASM_OPCODE_BR_TABLE); write_u32_leb128(&ctx->stream, expr->br_table.targets.size, "num targets"); @@ -684,12 +685,11 @@ static void write_expr(WasmContext* ctx, node = find_label_by_var(ctx->top_label, &expr->br_table.default_target); wasm_write_u32(&ctx->stream, ctx->max_depth - node->depth - 1, "break depth for default"); - write_expr(ctx, module, func, expr->br_table.expr); break; } case WASM_EXPR_TYPE_UNARY: - write_opcode(&ctx->stream, expr->unary.opcode); write_expr(ctx, module, func, expr->unary.expr); + write_opcode(&ctx->stream, expr->unary.opcode); break; case WASM_EXPR_TYPE_UNREACHABLE: write_opcode(&ctx->stream, WASM_OPCODE_UNREACHABLE); @@ -706,31 +706,6 @@ static void write_expr_list(WasmContext* ctx, write_expr(ctx, module, func, exprs->data[i]); } -static void write_expr_list_with_count(WasmContext* ctx, - const WasmModule* module, - const WasmFunc* func, - const WasmExprPtrVector* exprs) { - write_u32_leb128(&ctx->stream, exprs->size, "num expressions"); - write_expr_list(ctx, module, func, exprs); -} - -static void write_block(WasmContext* ctx, - const WasmModule* module, - const WasmFunc* func, - const WasmBlock* block) { - WasmLabelNode node; - if (block->exprs.size == 1 && !block->used) { - push_unused_label(ctx, &node, &block->label); - write_expr(ctx, module, func, block->exprs.data[0]); - pop_unused_label(ctx, &block->label); - } else { - push_label(ctx, &node, &block->label); - write_opcode(&ctx->stream, WASM_OPCODE_BLOCK); - write_expr_list_with_count(ctx, module, func, &block->exprs); - pop_label(ctx, &block->label); - } -} - static void write_func_locals(WasmContext* ctx, const WasmModule* module, const WasmFunc* func, diff --git a/src/wasm-common.h b/src/wasm-common.h index 051203b1..3bc5f227 100644 --- a/src/wasm-common.h +++ b/src/wasm-common.h @@ -149,23 +149,23 @@ enum { WASM_USE_NATURAL_ALIGNMENT = 0xFFFFFFFF }; V(___, ___, ___, 0, 0x01, BLOCK, "block") \ V(___, ___, ___, 0, 0x02, LOOP, "loop") \ V(___, ___, ___, 0, 0x03, IF, "if") \ - V(___, ___, ___, 0, 0x04, IF_ELSE, "if_else") \ + V(___, ___, ___, 0, 0x04, ELSE, "else") \ V(___, ___, ___, 0, 0x05, SELECT, "select") \ V(___, ___, ___, 0, 0x06, BR, "br") \ V(___, ___, ___, 0, 0x07, BR_IF, "br_if") \ V(___, ___, ___, 0, 0x08, BR_TABLE, "br_table") \ - V(___, ___, ___, 0, 0x09, I8_CONST, "i8.const") \ - V(I32, ___, ___, 0, 0x0a, I32_CONST, "i32.const") \ - V(I64, ___, ___, 0, 0x0b, I64_CONST, "i64.const") \ - V(F64, ___, ___, 0, 0x0c, F64_CONST, "f64.const") \ - V(F32, ___, ___, 0, 0x0d, F32_CONST, "f32.const") \ - V(___, ___, ___, 0, 0x0e, GET_LOCAL, "get_local") \ - V(___, ___, ___, 0, 0x0f, SET_LOCAL, "set_local") \ - V(___, ___, ___, 0, 0x12, CALL_FUNCTION, "call") \ - V(___, ___, ___, 0, 0x13, CALL_INDIRECT, "call_indirect") \ - V(___, ___, ___, 0, 0x14, RETURN, "return") \ - V(___, ___, ___, 0, 0x15, UNREACHABLE, "unreachable") \ - V(___, ___, ___, 0, 0x1f, CALL_IMPORT, "call_import") \ + V(___, ___, ___, 0, 0x09, RETURN, "return") \ + V(___, ___, ___, 0, 0x0a, UNREACHABLE, "unreachable") \ + V(___, ___, ___, 0, 0x0f, END, "end") \ + V(I32, ___, ___, 0, 0x10, I32_CONST, "i32.const") \ + V(I64, ___, ___, 0, 0x11, I64_CONST, "i64.const") \ + V(F64, ___, ___, 0, 0x12, F64_CONST, "f64.const") \ + V(F32, ___, ___, 0, 0x13, F32_CONST, "f32.const") \ + V(___, ___, ___, 0, 0x14, GET_LOCAL, "get_local") \ + V(___, ___, ___, 0, 0x15, SET_LOCAL, "set_local") \ + V(___, ___, ___, 0, 0x16, CALL_FUNCTION, "call") \ + V(___, ___, ___, 0, 0x17, CALL_INDIRECT, "call_indirect") \ + V(___, ___, ___, 0, 0x18, CALL_IMPORT, "call_import") \ V(I32, I32, ___, 1, 0x20, I32_LOAD8_S, "i32.load8_s") \ V(I32, I32, ___, 1, 0x21, I32_LOAD8_U, "i32.load8_u") \ V(I32, I32, ___, 2, 0x22, I32_LOAD16_S, "i32.load16_s") \ |