diff options
author | Ben Smith <binji@chromium.org> | 2016-08-02 14:36:57 -0700 |
---|---|---|
committer | Ben Smith <binji@chromium.org> | 2016-09-29 11:37:27 -0700 |
commit | b8793f6aabd4932114674443fd42c3448036044c (patch) | |
tree | 4c6da7d69e6ad12be1691e5469b3da42adc96aeb /src/wasm-binary-reader-ast.c | |
parent | 47cd3242fee70aedef3a2d595ee23fa2fe0efc28 (diff) | |
download | wabt-b8793f6aabd4932114674443fd42c3448036044c.tar.gz wabt-b8793f6aabd4932114674443fd42c3448036044c.tar.bz2 wabt-b8793f6aabd4932114674443fd42c3448036044c.zip |
WIP on stack changes
This is enough to pass the parse tests, not including the roundtrip
tests.
This change includes the new `drop` and `tee_local` operators, as well
as the type-checking for the "full stack machine". The parser has also
been updated to allow the new linear text format.
Diffstat (limited to 'src/wasm-binary-reader-ast.c')
-rw-r--r-- | src/wasm-binary-reader-ast.c | 678 |
1 files changed, 195 insertions, 483 deletions
diff --git a/src/wasm-binary-reader-ast.c b/src/wasm-binary-reader-ast.c index 91a79dcd..845d671b 100644 --- a/src/wasm-binary-reader-ast.c +++ b/src/wasm-binary-reader-ast.c @@ -27,61 +27,21 @@ #include "wasm-binary-reader.h" #include "wasm-common.h" -#define LOG 0 - -#if LOG -#define LOGF(...) fprintf(stderr, __VA_ARGS__) -#else -#define LOGF(...) (void)0 -#endif - #define CHECK_RESULT(expr) \ do { \ if (WASM_FAILED(expr)) \ return WASM_ERROR; \ } while (0) -#define CHECK_DEPTH(depth) \ - do { \ - if ((depth) >= ctx->max_depth) { \ - print_error(ctx, "invalid depth: %d (max %u)", (depth), ctx->max_depth); \ - return WASM_ERROR; \ - } \ - } while (0) - -#define CHECK_LOCAL(local_index) \ - do { \ - uint32_t max_local_index = \ - wasm_get_num_params_and_locals(ctx->module, ctx->current_func); \ - if ((local_index) >= max_local_index) { \ - print_error(ctx, "invalid local_index: %d (max %d)", (local_index), \ - max_local_index); \ - return WASM_ERROR; \ - } \ - } while (0) - #if LOG #define V(rtype, type1, type2, mem_size, code, NAME, text) [code] = text, static const char* s_opcode_name[] = {WASM_FOREACH_OPCODE(V)}; #undef V #endif -typedef enum LabelType { - LABEL_TYPE_FUNC, - LABEL_TYPE_BLOCK, - LABEL_TYPE_IF, - LABEL_TYPE_ELSE, - LABEL_TYPE_LOOP, -} LabelType; - -static const char* s_label_type_name[] = {"func", "block", "if", "else", - "loop"}; - typedef struct LabelNode { - LabelType type; - WasmExpr* expr_stack_top; - size_t expr_stack_size; - WasmExpr* expr; + WasmExpr** first; + WasmExpr* last; } LabelNode; WASM_DEFINE_VECTOR(label_node, LabelNode); @@ -91,8 +51,6 @@ typedef struct Context { WasmModule* module; WasmFunc* current_func; - WasmExpr* expr_stack_top; - size_t expr_stack_size; LabelNodeVector label_stack; uint32_t max_depth; } Context; @@ -105,13 +63,11 @@ static void WASM_PRINTF_FORMAT(2, 3) on_error(WASM_UNKNOWN_OFFSET, buffer, ctx); } -static void push_label(Context* ctx, LabelType type, WasmExpr* expr) { +static void push_label(Context* ctx, WasmExpr** first) { LabelNode label; - label.type = type; - label.expr_stack_top = ctx->expr_stack_top; - label.expr_stack_size = ctx->expr_stack_size; - label.expr = expr; - ctx->max_depth += type == LABEL_TYPE_LOOP ? 2 : 1; + label.first = first; + label.last = NULL; + ctx->max_depth++; wasm_append_label_node_value(ctx->allocator, &ctx->label_stack, &label); } @@ -121,8 +77,7 @@ static WasmResult pop_label(Context* ctx) { return WASM_ERROR; } - LabelType type = ctx->label_stack.data[ctx->label_stack.size - 1].type; - ctx->max_depth -= type == LABEL_TYPE_LOOP ? 2 : 1; + ctx->max_depth--; ctx->label_stack.size--; return WASM_OK; } @@ -138,8 +93,8 @@ static WasmResult top_label(Context* ctx, LabelNode** label) { } static void dup_name(Context* ctx, - WasmStringSlice* name, - WasmStringSlice* out_name) { + WasmStringSlice* name, + WasmStringSlice* out_name) { if (name->length > 0) { *out_name = wasm_dup_string_slice(ctx->allocator, *name); } else { @@ -147,98 +102,19 @@ static void dup_name(Context* ctx, } } -static void push_expr(Context* ctx, WasmExpr* expr) { - expr->next = ctx->expr_stack_top; - ctx->expr_stack_top = expr; - ctx->expr_stack_size++; -} - -static WasmResult pop_expr(Context* ctx, WasmExpr** expr) { - if (!ctx->expr_stack_top) { - print_error(ctx, "popping empty stack"); - return WASM_ERROR; - } - - if (ctx->label_stack.size > 0) { - LabelNode* label; - WasmResult result = top_label(ctx, &label); - WASM_USE(result); - assert(WASM_SUCCEEDED(result)); - if (ctx->expr_stack_size <= label->expr_stack_size) { - print_error(ctx, "popping past %s label", s_label_type_name[label->type]); - return WASM_ERROR; - } - } - - *expr = ctx->expr_stack_top; - ctx->expr_stack_top = ctx->expr_stack_top->next; - ctx->expr_stack_size--; - return WASM_OK; -} - -static WasmResult pop_expr_if(Context* ctx, WasmExpr** expr, WasmBool cond) { - if (cond) - return pop_expr(ctx, expr); - *expr = NULL; - return WASM_OK; -} - -static void pop_into_expr_list(Context* ctx, - WasmExpr* new_expr_stack_top, - WasmExpr** out_first_expr) { - /* the stack contains expressions pushed on in execution order, e.g. - * - * new_expr_stack_top - * | - * V - * expr_stack_top -> expr2 -> expr1 -> expr0 -> other -> NULL - * - * |out_expr_first| will be set to the first element of the reversed list: - * - * out_first_expr -> expr0 -> expr1 -> expr2 -> NULL - * expr_stack_top -> other -> NULL - */ - assert(!*out_first_expr); - WasmExpr* first = NULL; - WasmExpr* expr = ctx->expr_stack_top; - while (expr != new_expr_stack_top) { - assert(expr); - WasmExpr* next = expr->next; - expr->next = first; - first = expr; - expr = next; - } - ctx->expr_stack_top = new_expr_stack_top; - *out_first_expr = first; -} - -static WasmResult pop_into_args(Context* ctx, - WasmFuncSignature* sig, - WasmExpr** out_first_arg) { - assert(!*out_first_arg); - size_t num_params = sig->param_types.size; - - WasmExpr* first = NULL; - WasmExpr* expr = ctx->expr_stack_top; - size_t i; - for (i = 0; i < num_params; ++i) { - if (!expr) { - print_error(ctx, - "call requires %" PRIzd " args, but only %" PRIzd " on stack", - num_params, i); - return WASM_ERROR; - } - WasmExpr* next = expr->next; - expr->next = first; - first = expr; - expr = next; +static WasmResult append_expr(Context* ctx, WasmExpr* expr) { + LabelNode* label; + CHECK_RESULT(top_label(ctx, &label)); + if (*label->first) { + label->last->next = expr; + label->last = expr; + } else { + *label->first = label->last = expr; } - ctx->expr_stack_top = expr; - *out_first_arg = first; return WASM_OK; } -void on_error(uint32_t offset, const char* message, void* user_data) { +static void on_error(uint32_t offset, const char* message, void* user_data) { Context* ctx = user_data; if (ctx->error_handler->on_error) { ctx->error_handler->on_error(offset, message, @@ -416,17 +292,7 @@ static WasmResult begin_function_body(uint32_t index, void* user_data) { Context* ctx = user_data; assert(index < ctx->module->funcs.size); ctx->current_func = ctx->module->funcs.data[index]; - ctx->expr_stack_size = 0; - LOGF("func %d\n", index); - push_label(ctx, LABEL_TYPE_FUNC, NULL); - return WASM_OK; -} - -static WasmResult end_function_body(uint32_t index, void* user_data) { - Context* ctx = user_data; - pop_into_expr_list(ctx, NULL, &ctx->current_func->first_expr); - CHECK_RESULT(pop_label(ctx)); - ctx->current_func = NULL; + push_label(ctx, &ctx->current_func->first_expr); return WASM_OK; } @@ -446,178 +312,39 @@ static WasmResult on_local_decl(uint32_t decl_index, return WASM_OK; } -static WasmResult on_unary_expr(WasmOpcode opcode, void* user_data) { - Context* ctx = user_data; - LOGF("%" PRIzd ": %s\n", ctx->expr_stack_size, s_opcode_name[opcode]); - WasmExpr *result, *expr; - CHECK_RESULT(pop_expr(ctx, &expr)); - result = wasm_new_unary_expr(ctx->allocator); - result->unary.opcode = opcode; - result->unary.expr = expr; - push_expr(ctx, result); - return WASM_OK; -} - static WasmResult on_binary_expr(WasmOpcode opcode, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": %s\n", ctx->expr_stack_size, s_opcode_name[opcode]); - WasmExpr *result, *left, *right; - CHECK_RESULT(pop_expr(ctx, &right)); - CHECK_RESULT(pop_expr(ctx, &left)); - result = wasm_new_binary_expr(ctx->allocator); - result->binary.opcode = opcode; - result->binary.left = left; - result->binary.right = right; - push_expr(ctx, result); - return WASM_OK; -} - -static WasmResult on_compare_expr(WasmOpcode opcode, void* user_data) { - Context* ctx = user_data; - LOGF("%" PRIzd ": %s\n", ctx->expr_stack_size, s_opcode_name[opcode]); - WasmExpr *result, *left, *right; - CHECK_RESULT(pop_expr(ctx, &right)); - CHECK_RESULT(pop_expr(ctx, &left)); - result = wasm_new_compare_expr(ctx->allocator); - result->compare.opcode = opcode; - result->compare.left = left; - result->compare.right = right; - push_expr(ctx, result); - return WASM_OK; -} - -static WasmResult on_convert_expr(WasmOpcode opcode, void* user_data) { - Context* ctx = user_data; - LOGF("%" PRIzd ": %s\n", ctx->expr_stack_size, s_opcode_name[opcode]); - WasmExpr *result, *expr; - CHECK_RESULT(pop_expr(ctx, &expr)); - result = wasm_new_convert_expr(ctx->allocator); - result->convert.opcode = opcode; - result->convert.expr = expr; - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_binary_expr(ctx->allocator); + expr->binary.opcode = opcode; + return append_expr(ctx, expr); } static WasmResult on_block_expr(void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": block\n", ctx->expr_stack_size); - WasmExpr* result; - result = wasm_new_block_expr(ctx->allocator); - push_label(ctx, LABEL_TYPE_BLOCK, result); - return WASM_OK; -} - -static WasmResult on_loop_expr(void* user_data) { - Context* ctx = user_data; - LOGF("%" PRIzd ": loop\n", ctx->expr_stack_size); - WasmExpr* result; - result = wasm_new_loop_expr(ctx->allocator); - push_label(ctx, LABEL_TYPE_LOOP, result); - return WASM_OK; -} - -static WasmResult on_if_expr(void* user_data) { - Context* ctx = user_data; - LOGF("%" PRIzd ": if\n", ctx->expr_stack_size); - WasmExpr *cond, *result; - CHECK_RESULT(pop_expr(ctx, &cond)); - result = wasm_new_if_expr(ctx->allocator); - result->if_.cond = cond; - push_label(ctx, LABEL_TYPE_IF, result); - return WASM_OK; -} - -static WasmResult on_else_expr(void* user_data) { - Context* ctx = user_data; - LOGF("%" PRIzd ": else\n", ctx->expr_stack_size); - LabelNode* label; - CHECK_RESULT(top_label(ctx, &label)); - if (label->type != LABEL_TYPE_IF) { - print_error(ctx, "else expression without matching if"); - return WASM_ERROR; - } - - /* destroy the if expr, replace it with an if_else */ - /* TODO(binji): remove if_else and just have false branch be an empty block - * for if without else? */ - WasmExpr* cond = label->expr->if_.cond; - label->expr->if_.cond = NULL; - wasm_free(ctx->allocator, label->expr); - - WasmExpr* result; - result = wasm_new_if_else_expr(ctx->allocator); - result->if_else.cond = cond; - pop_into_expr_list(ctx, label->expr_stack_top, &result->if_else.true_.first); - label->type = LABEL_TYPE_ELSE; - label->expr = result; - return WASM_OK; -} - -static WasmResult on_end_expr(void* user_data) { - Context* ctx = user_data; - LOGF("%" PRIzd ": end\n", ctx->expr_stack_size); - LabelNode* label; - CHECK_RESULT(top_label(ctx, &label)); - WasmExpr* expr = label->expr; - - switch (label->type) { - case LABEL_TYPE_IF: - pop_into_expr_list(ctx, label->expr_stack_top, &expr->if_.true_.first); - break; - - case LABEL_TYPE_ELSE: - pop_into_expr_list(ctx, label->expr_stack_top, - &expr->if_else.false_.first); - break; - - case LABEL_TYPE_BLOCK: - pop_into_expr_list(ctx, label->expr_stack_top, &expr->block.first); - break; - - case LABEL_TYPE_LOOP: - pop_into_expr_list(ctx, label->expr_stack_top, &expr->loop.first); - break; - - default: - assert(0); - return WASM_ERROR; - } - - CHECK_RESULT(pop_label(ctx)); - push_expr(ctx, expr); + WasmExpr* expr = wasm_new_block_expr(ctx->allocator); + append_expr(ctx, expr); + push_label(ctx, &expr->block.first); return WASM_OK; } static WasmResult on_br_expr(uint8_t arity, uint32_t depth, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": br:%d %u\n", ctx->expr_stack_size, arity, depth); - WasmExpr *result, *expr; - CHECK_RESULT(pop_expr_if(ctx, &expr, arity == 1)); - result = wasm_new_br_expr(ctx->allocator); - result->br.var.type = WASM_VAR_TYPE_INDEX; - CHECK_DEPTH(depth); - result->br.var.index = depth; - result->br.expr = expr; - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_br_expr(ctx->allocator); + expr->br.var.type = WASM_VAR_TYPE_INDEX; + expr->br.arity = arity; + expr->br.var.index = depth; + return append_expr(ctx, expr); } static WasmResult on_br_if_expr(uint8_t arity, uint32_t depth, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": br_if:%d %u\n", ctx->expr_stack_size, arity, depth); - WasmExpr *result, *cond, *expr; - CHECK_RESULT(pop_expr(ctx, &cond)); - CHECK_RESULT(pop_expr_if(ctx, &expr, arity == 1)); - result = wasm_new_br_if_expr(ctx->allocator); - result->br_if.var.type = WASM_VAR_TYPE_INDEX; - CHECK_DEPTH(depth); - result->br_if.var.index = depth; - result->br_if.cond = cond; - result->br_if.expr = expr; - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_br_if_expr(ctx->allocator); + expr->br_if.arity = arity; + expr->br_if.var.type = WASM_VAR_TYPE_INDEX; + expr->br_if.var.index = depth; + return append_expr(ctx, expr); } static WasmResult on_br_table_expr(uint8_t arity, @@ -626,177 +353,157 @@ static WasmResult on_br_table_expr(uint8_t arity, uint32_t default_target_depth, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": br_table:%d %u\n", ctx->expr_stack_size, arity, - num_targets); - WasmExpr *result, *expr, *key; - CHECK_RESULT(pop_expr(ctx, &key)); - CHECK_RESULT(pop_expr_if(ctx, &expr, arity == 1)); - result = wasm_new_br_table_expr(ctx->allocator); - wasm_reserve_vars(ctx->allocator, &result->br_table.targets, num_targets); - result->br_table.key = key; - result->br_table.expr = expr; - result->br_table.targets.size = num_targets; + WasmExpr* expr = wasm_new_br_table_expr(ctx->allocator); + wasm_reserve_vars(ctx->allocator, &expr->br_table.targets, num_targets); + expr->br_table.arity = arity; + expr->br_table.targets.size = num_targets; uint32_t i; for (i = 0; i < num_targets; ++i) { - WasmVar* var = &result->br_table.targets.data[i]; + WasmVar* var = &expr->br_table.targets.data[i]; var->type = WASM_VAR_TYPE_INDEX; - CHECK_DEPTH(target_depths[i]); var->index = target_depths[i]; } - result->br_table.default_target.type = WASM_VAR_TYPE_INDEX; - CHECK_DEPTH(default_target_depth); - result->br_table.default_target.index = default_target_depth; - push_expr(ctx, result); - return WASM_OK; + expr->br_table.default_target.type = WASM_VAR_TYPE_INDEX; + expr->br_table.default_target.index = default_target_depth; + return append_expr(ctx, expr); } static WasmResult on_call_expr(uint32_t arity, uint32_t func_index, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": call:%d %d\n", ctx->expr_stack_size, arity, func_index); assert(func_index < ctx->module->funcs.size); - WasmFunc* func = ctx->module->funcs.data[func_index]; - uint32_t sig_index = (uint32_t)func->decl.type_var.index; - assert(sig_index < ctx->module->func_types.size); - WasmFuncType* func_type = ctx->module->func_types.data[sig_index]; - - WasmExpr* result; - result = wasm_new_call_expr(ctx->allocator); - result->call.var.type = WASM_VAR_TYPE_INDEX; - result->call.var.index = func_index; - result->call.num_args = func_type->sig.param_types.size; - CHECK_RESULT(pop_into_args(ctx, &func_type->sig, &result->call.first_arg)); - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_call_expr(ctx->allocator); + expr->call.var.type = WASM_VAR_TYPE_INDEX; + expr->call.var.index = func_index; + return append_expr(ctx, expr); } static WasmResult on_call_import_expr(uint32_t arity, uint32_t import_index, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": call_import:%d %u\n", ctx->expr_stack_size, arity, - import_index); assert(import_index < ctx->module->imports.size); - WasmImport* import = ctx->module->imports.data[import_index]; - uint32_t sig_index = (uint32_t)import->decl.type_var.index; - assert(sig_index < ctx->module->func_types.size); - WasmFuncType* func_type = ctx->module->func_types.data[sig_index]; - - WasmExpr* result; - result = wasm_new_call_import_expr(ctx->allocator); - result->call.var.type = WASM_VAR_TYPE_INDEX; - result->call.var.index = import_index; - result->call.num_args = func_type->sig.param_types.size; - CHECK_RESULT(pop_into_args(ctx, &func_type->sig, &result->call.first_arg)); - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_call_import_expr(ctx->allocator); + expr->call.var.type = WASM_VAR_TYPE_INDEX; + expr->call.var.index = import_index; + return append_expr(ctx, expr); } static WasmResult on_call_indirect_expr(uint32_t arity, uint32_t sig_index, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": call_indirect:%d %u\n", ctx->expr_stack_size, arity, - sig_index); assert(sig_index < ctx->module->func_types.size); - WasmFuncType* func_type = ctx->module->func_types.data[sig_index]; - - WasmExpr* result; - result = wasm_new_call_indirect_expr(ctx->allocator); - result->call_indirect.var.type = WASM_VAR_TYPE_INDEX; - result->call_indirect.var.index = sig_index; - result->call_indirect.num_args = func_type->sig.param_types.size; - CHECK_RESULT( - pop_into_args(ctx, &func_type->sig, &result->call_indirect.first_arg)); - CHECK_RESULT(pop_expr(ctx, &result->call_indirect.expr)); - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_call_indirect_expr(ctx->allocator); + expr->call_indirect.var.type = WASM_VAR_TYPE_INDEX; + expr->call_indirect.var.index = sig_index; + return append_expr(ctx, expr); } -static WasmResult on_i32_const_expr(uint32_t value, void* user_data) { +static WasmResult on_compare_expr(WasmOpcode opcode, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": i32.const %u\n", ctx->expr_stack_size, value); - WasmExpr* result = wasm_new_const_expr(ctx->allocator); - result->const_.type = WASM_TYPE_I32; - result->const_.u32 = value; - push_expr(ctx, result); - return WASM_OK; + WasmExpr *expr = wasm_new_compare_expr(ctx->allocator); + expr->compare.opcode = opcode; + return append_expr(ctx, expr); } -static WasmResult on_i64_const_expr(uint64_t value, void* user_data) { +static WasmResult on_convert_expr(WasmOpcode opcode, void* user_data) { + Context* ctx = user_data; + WasmExpr* expr = wasm_new_convert_expr(ctx->allocator); + expr->convert.opcode = opcode; + return append_expr(ctx, expr); +} + +static WasmResult on_current_memory_expr(void* user_data) { + Context* ctx = user_data; + WasmExpr* expr = wasm_new_current_memory_expr(ctx->allocator); + return append_expr(ctx, expr); +} + +static WasmResult on_drop_expr(void* user_data) { + Context* ctx = user_data; + WasmExpr* expr = wasm_new_drop_expr(ctx->allocator); + return append_expr(ctx, expr); +} + +static WasmResult on_else_expr(void* user_data) { + /* destroy the if expr, replace it with an if_else */ + /* TODO(binji): remove if_else and just have false branch be an empty block + * for if without else? */ Context* ctx = user_data; - LOGF("%" PRIzd ": i64.const %" PRIu64 "\n", ctx->expr_stack_size, value); - WasmExpr* result = wasm_new_const_expr(ctx->allocator); - result->const_.type = WASM_TYPE_I64; - result->const_.u64 = value; - push_expr(ctx, result); + CHECK_RESULT(pop_label(ctx)); + LabelNode* label; + CHECK_RESULT(top_label(ctx, &label)); + WasmExpr* if_expr = label->last; + if (if_expr->type != WASM_EXPR_TYPE_IF) { + print_error(ctx, "else expression without matching if"); + return WASM_ERROR; + } + + WasmExpr* if_else_expr = wasm_new_if_else_expr(ctx->allocator); + if_else_expr->if_else.true_.first = if_expr->if_.true_.first; + wasm_free(ctx->allocator, if_expr); + push_label(ctx, &if_else_expr->if_else.false_.first); return WASM_OK; } +static WasmResult on_end_expr(void* user_data) { + Context* ctx = user_data; + return pop_label(ctx); +} + static WasmResult on_f32_const_expr(uint32_t value_bits, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": f32.const %u\n", ctx->expr_stack_size, value_bits); - WasmExpr* result = wasm_new_const_expr(ctx->allocator); - result->const_.type = WASM_TYPE_F32; - result->const_.f32_bits = value_bits; - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_const_expr(ctx->allocator); + expr->const_.type = WASM_TYPE_F32; + expr->const_.f32_bits = value_bits; + return append_expr(ctx, expr); } static WasmResult on_f64_const_expr(uint64_t value_bits, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": f64.const %" PRIu64 "\n", ctx->expr_stack_size, value_bits); - WasmExpr* result = wasm_new_const_expr(ctx->allocator); - result->const_.type = WASM_TYPE_F64; - result->const_.f64_bits = value_bits; - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_const_expr(ctx->allocator); + expr->const_.type = WASM_TYPE_F64; + expr->const_.f64_bits = value_bits; + return append_expr(ctx, expr); } static WasmResult on_get_local_expr(uint32_t local_index, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": get_local %u\n", ctx->expr_stack_size, local_index); - WasmExpr* result; - result = wasm_new_get_local_expr(ctx->allocator); - result->get_local.var.type = WASM_VAR_TYPE_INDEX; - result->get_local.var.index = local_index; - CHECK_LOCAL(local_index); - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_get_local_expr(ctx->allocator); + expr->get_local.var.type = WASM_VAR_TYPE_INDEX; + expr->get_local.var.index = local_index; + return append_expr(ctx, expr); } -static WasmResult on_set_local_expr(uint32_t local_index, void* user_data) { +static WasmResult on_grow_memory_expr(void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": set_local %u\n", ctx->expr_stack_size, local_index); - WasmExpr *result, *expr; - CHECK_RESULT(pop_expr(ctx, &expr)); - result = wasm_new_set_local_expr(ctx->allocator); - result->set_local.var.type = WASM_VAR_TYPE_INDEX; - result->set_local.var.index = local_index; - result->set_local.expr = expr; - CHECK_LOCAL(local_index); - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_grow_memory_expr(ctx->allocator); + return append_expr(ctx, expr); } -static WasmResult on_grow_memory_expr(void* user_data) { +static WasmResult on_i32_const_expr(uint32_t value, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": grow_memory\n", ctx->expr_stack_size); - WasmExpr *result, *expr; - CHECK_RESULT(pop_expr(ctx, &expr)); - result = wasm_new_grow_memory_expr(ctx->allocator); - result->grow_memory.expr = expr; - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_const_expr(ctx->allocator); + expr->const_.type = WASM_TYPE_I32; + expr->const_.u32 = value; + return append_expr(ctx, expr); } -static WasmResult on_current_memory_expr(void* user_data) { +static WasmResult on_i64_const_expr(uint64_t value, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": current_memory\n", ctx->expr_stack_size); - WasmExpr* result; - result = wasm_new_empty_expr(ctx->allocator, WASM_EXPR_TYPE_CURRENT_MEMORY); - push_expr(ctx, result); + WasmExpr* expr = wasm_new_const_expr(ctx->allocator); + expr->const_.type = WASM_TYPE_I64; + expr->const_.u64 = value; + return append_expr(ctx, expr); +} + +static WasmResult on_if_expr(void* user_data) { + Context* ctx = user_data; + WasmExpr* expr = wasm_new_if_expr(ctx->allocator); + append_expr(ctx, expr); + push_label(ctx, &expr->if_.true_.first); return WASM_OK; } @@ -805,80 +512,84 @@ static WasmResult on_load_expr(WasmOpcode opcode, uint32_t offset, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": %s align=%u offset=%u\n", ctx->expr_stack_size, - s_opcode_name[opcode], alignment_log2, offset); - WasmExpr *result, *addr; - CHECK_RESULT(pop_expr(ctx, &addr)); - result = wasm_new_load_expr(ctx->allocator); - result->load.opcode = opcode; - result->load.align = 1 << alignment_log2; - result->load.offset = offset; - result->load.addr = addr; - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_load_expr(ctx->allocator); + expr->load.opcode = opcode; + expr->load.align = 1 << alignment_log2; + expr->load.offset = offset; + return append_expr(ctx, expr); } -static WasmResult on_store_expr(WasmOpcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data) { +static WasmResult on_loop_expr(void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": %s align=%u offset=%u\n", ctx->expr_stack_size, - s_opcode_name[opcode], alignment_log2, offset); - WasmExpr *result, *addr, *value; - CHECK_RESULT(pop_expr(ctx, &value)); - CHECK_RESULT(pop_expr(ctx, &addr)); - result = wasm_new_store_expr(ctx->allocator); - result->store.opcode = opcode; - result->store.align = 1 << alignment_log2; - result->store.offset = offset; - result->store.addr = addr; - result->store.value = value; - push_expr(ctx, result); + WasmExpr* expr = wasm_new_loop_expr(ctx->allocator); + append_expr(ctx, expr); + push_label(ctx, &expr->loop.first); return WASM_OK; } static WasmResult on_nop_expr(void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": nop\n", ctx->expr_stack_size); - WasmExpr* result; - result = wasm_new_empty_expr(ctx->allocator, WASM_EXPR_TYPE_NOP); - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_nop_expr(ctx->allocator); + return append_expr(ctx, expr); } static WasmResult on_return_expr(uint8_t arity, void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": return:%d\n", ctx->expr_stack_size, arity); - WasmExpr *result, *expr; - CHECK_RESULT(pop_expr_if(ctx, &expr, arity == 1)); - result = wasm_new_return_expr(ctx->allocator); - result->return_.expr = expr; - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_return_expr(ctx->allocator); + return append_expr(ctx, expr); } static WasmResult on_select_expr(void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": select\n", ctx->expr_stack_size); - WasmExpr *result, *true_, *false_, *cond; - CHECK_RESULT(pop_expr(ctx, &cond)); - CHECK_RESULT(pop_expr(ctx, &false_)); - CHECK_RESULT(pop_expr(ctx, &true_)); - result = wasm_new_select_expr(ctx->allocator); - result->select.cond = cond; - result->select.true_ = true_; - result->select.false_ = false_; - push_expr(ctx, result); - return WASM_OK; + WasmExpr* expr = wasm_new_select_expr(ctx->allocator); + return append_expr(ctx, expr); +} + +static WasmResult on_set_local_expr(uint32_t local_index, void* user_data) { + Context* ctx = user_data; + WasmExpr* expr = wasm_new_set_local_expr(ctx->allocator); + expr->set_local.var.type = WASM_VAR_TYPE_INDEX; + expr->set_local.var.index = local_index; + return append_expr(ctx, expr); +} + +static WasmResult on_store_expr(WasmOpcode opcode, + uint32_t alignment_log2, + uint32_t offset, + void* user_data) { + Context* ctx = user_data; + WasmExpr* expr = wasm_new_store_expr(ctx->allocator); + expr->store.opcode = opcode; + expr->store.align = 1 << alignment_log2; + expr->store.offset = offset; + return append_expr(ctx, expr); +} + +static WasmResult on_tee_local_expr(uint32_t local_index, void* user_data) { + Context* ctx = user_data; + WasmExpr* expr = wasm_new_tee_local_expr(ctx->allocator); + expr->tee_local.var.type = WASM_VAR_TYPE_INDEX; + expr->tee_local.var.index = local_index; + return append_expr(ctx, expr); +} + +static WasmResult on_unary_expr(WasmOpcode opcode, void* user_data) { + Context* ctx = user_data; + WasmExpr* expr = wasm_new_unary_expr(ctx->allocator); + expr->unary.opcode = opcode; + return append_expr(ctx, expr); } static WasmResult on_unreachable_expr(void* user_data) { Context* ctx = user_data; - LOGF("%" PRIzd ": unreachable\n", ctx->expr_stack_size); - WasmExpr* result; - result = wasm_new_empty_expr(ctx->allocator, WASM_EXPR_TYPE_UNREACHABLE); - push_expr(ctx, result); + WasmExpr* expr = wasm_new_unreachable_expr(ctx->allocator); + return append_expr(ctx, expr); +} + +static WasmResult end_function_body(uint32_t index, void* user_data) { + Context* ctx = user_data; + CHECK_RESULT(pop_label(ctx)); + ctx->current_func = NULL; return WASM_OK; } @@ -1055,6 +766,8 @@ static WasmBinaryReader s_binary_reader = { .on_call_indirect_expr = &on_call_indirect_expr, .on_compare_expr = &on_compare_expr, .on_convert_expr = &on_convert_expr, + .on_current_memory_expr = &on_current_memory_expr, + .on_drop_expr = &on_drop_expr, .on_else_expr = &on_else_expr, .on_end_expr = &on_end_expr, .on_f32_const_expr = &on_f32_const_expr, @@ -1066,12 +779,12 @@ static WasmBinaryReader s_binary_reader = { .on_if_expr = &on_if_expr, .on_load_expr = &on_load_expr, .on_loop_expr = &on_loop_expr, - .on_current_memory_expr = &on_current_memory_expr, .on_nop_expr = &on_nop_expr, .on_return_expr = &on_return_expr, .on_select_expr = &on_select_expr, .on_set_local_expr = &on_set_local_expr, .on_store_expr = &on_store_expr, + .on_tee_local_expr = &on_tee_local_expr, .on_unary_expr = &on_unary_expr, .on_unreachable_expr = &on_unreachable_expr, .end_function_body = &end_function_body, @@ -1091,8 +804,8 @@ static WasmBinaryReader s_binary_reader = { }; static void wasm_destroy_label_node(WasmAllocator* allocator, LabelNode* node) { - if (node->expr) - wasm_destroy_expr(allocator, node->expr); + if (*node->first) + wasm_destroy_expr_list(allocator, *node->first); } WasmResult wasm_read_binary_ast(struct WasmAllocator* allocator, @@ -1115,6 +828,5 @@ WasmResult wasm_read_binary_ast(struct WasmAllocator* allocator, WasmResult result = wasm_read_binary(allocator, data, size, &reader, 1, options); WASM_DESTROY_VECTOR_AND_ELEMENTS(allocator, ctx.label_stack, label_node); - wasm_destroy_expr_list(allocator, ctx.expr_stack_top); return result; } |