summaryrefslogtreecommitdiff
path: root/src/wasm-binary-reader-ast.c
diff options
context:
space:
mode:
authorBen Smith <binji@chromium.org>2016-08-02 14:36:57 -0700
committerBen Smith <binji@chromium.org>2016-09-29 11:37:27 -0700
commitb8793f6aabd4932114674443fd42c3448036044c (patch)
tree4c6da7d69e6ad12be1691e5469b3da42adc96aeb /src/wasm-binary-reader-ast.c
parent47cd3242fee70aedef3a2d595ee23fa2fe0efc28 (diff)
downloadwabt-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.c678
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;
}