diff options
Diffstat (limited to 'src/binary-reader-ast.cc')
-rw-r--r-- | src/binary-reader-ast.cc | 1141 |
1 files changed, 1141 insertions, 0 deletions
diff --git a/src/binary-reader-ast.cc b/src/binary-reader-ast.cc new file mode 100644 index 00000000..89ede529 --- /dev/null +++ b/src/binary-reader-ast.cc @@ -0,0 +1,1141 @@ +/* + * Copyright 2016 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "binary-reader-ast.h" + +#include <assert.h> +#include <inttypes.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> + +#include "ast.h" +#include "binary-reader.h" +#include "common.h" + +#define CHECK_RESULT(expr) \ + do { \ + if (WABT_FAILED(expr)) \ + return WABT_ERROR; \ + } while (0) + +typedef struct LabelNode { + WabtLabelType label_type; + WabtExpr** first; + WabtExpr* last; +} LabelNode; +WABT_DEFINE_VECTOR(label_node, LabelNode); + +typedef struct Context { + WabtBinaryErrorHandler* error_handler; + WabtModule* module; + + WabtFunc* current_func; + LabelNodeVector label_stack; + uint32_t max_depth; + WabtExpr** current_init_expr; +} Context; + +static void handle_error(Context* ctx, uint32_t offset, const char* message); + +static void WABT_PRINTF_FORMAT(2, 3) + print_error(Context* ctx, const char* format, ...) { + WABT_SNPRINTF_ALLOCA(buffer, length, format); + handle_error(ctx, WABT_UNKNOWN_OFFSET, buffer); +} + +static void push_label(Context* ctx, + WabtLabelType label_type, + WabtExpr** first) { + LabelNode label; + label.label_type = label_type; + label.first = first; + label.last = NULL; + ctx->max_depth++; + wabt_append_label_node_value(&ctx->label_stack, &label); +} + +static WabtResult pop_label(Context* ctx) { + if (ctx->label_stack.size == 0) { + print_error(ctx, "popping empty label stack"); + return WABT_ERROR; + } + + ctx->max_depth--; + ctx->label_stack.size--; + return WABT_OK; +} + +static WabtResult get_label_at(Context* ctx, + LabelNode** label, + uint32_t depth) { + if (depth >= ctx->label_stack.size) { + print_error(ctx, "accessing stack depth: %u >= max: %" PRIzd, depth, + ctx->label_stack.size); + return WABT_ERROR; + } + + *label = &ctx->label_stack.data[ctx->label_stack.size - depth - 1]; + return WABT_OK; +} + +static WabtResult top_label(Context* ctx, LabelNode** label) { + return get_label_at(ctx, label, 0); +} + +static void dup_name(Context* ctx, + WabtStringSlice* name, + WabtStringSlice* out_name) { + if (name->length > 0) { + *out_name = wabt_dup_string_slice(*name); + } else { + WABT_ZERO_MEMORY(*out_name); + } +} + +static WabtResult append_expr(Context* ctx, WabtExpr* expr) { + LabelNode* label; + if (WABT_FAILED(top_label(ctx, &label))) { + wabt_free(expr); + return WABT_ERROR; + } + if (*label->first) { + label->last->next = expr; + label->last = expr; + } else { + *label->first = label->last = expr; + } + return WABT_OK; +} + +static void handle_error(Context* ctx, uint32_t offset, const char* message) { + if (ctx->error_handler->on_error) { + ctx->error_handler->on_error(offset, message, + ctx->error_handler->user_data); + } +} + +static void on_error(WabtBinaryReaderContext* reader_context, + const char* message) { + Context* ctx = (Context*)reader_context->user_data; + handle_error(ctx, reader_context->offset, message); +} + +static WabtResult on_signature_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + wabt_reserve_func_type_ptrs(&ctx->module->func_types, count); + return WABT_OK; +} + +static WabtResult on_signature(uint32_t index, + uint32_t param_count, + WabtType* param_types, + uint32_t result_count, + WabtType* result_types, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_FUNC_TYPE; + + WabtFuncType* func_type = &field->func_type; + WABT_ZERO_MEMORY(*func_type); + + wabt_reserve_types(&func_type->sig.param_types, param_count); + func_type->sig.param_types.size = param_count; + memcpy(func_type->sig.param_types.data, param_types, + param_count * sizeof(WabtType)); + + wabt_reserve_types(&func_type->sig.result_types, result_count); + func_type->sig.result_types.size = result_count; + memcpy(func_type->sig.result_types.data, result_types, + result_count * sizeof(WabtType)); + + assert(index < ctx->module->func_types.capacity); + WabtFuncTypePtr* func_type_ptr = + wabt_append_func_type_ptr(&ctx->module->func_types); + *func_type_ptr = func_type; + return WABT_OK; +} + +static WabtResult on_import_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + wabt_reserve_import_ptrs(&ctx->module->imports, count); + return WABT_OK; +} + +static WabtResult on_import(uint32_t index, + WabtStringSlice module_name, + WabtStringSlice field_name, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(index < ctx->module->imports.capacity); + + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_IMPORT; + + WabtImport* import = &field->import; + WABT_ZERO_MEMORY(*import); + import->module_name = wabt_dup_string_slice(module_name); + import->field_name = wabt_dup_string_slice(field_name); + + WabtImportPtr* import_ptr = wabt_append_import_ptr(&ctx->module->imports); + *import_ptr = import; + return WABT_OK; +} + +static WabtResult on_import_func(uint32_t import_index, + uint32_t func_index, + uint32_t sig_index, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(import_index == ctx->module->imports.size - 1); + assert(sig_index < ctx->module->func_types.size); + WabtImport* import = ctx->module->imports.data[import_index]; + + import->kind = WABT_EXTERNAL_KIND_FUNC; + import->func.decl.flags = WABT_FUNC_DECLARATION_FLAG_HAS_FUNC_TYPE | + WABT_FUNC_DECLARATION_FLAG_SHARED_SIGNATURE; + import->func.decl.type_var.type = WABT_VAR_TYPE_INDEX; + import->func.decl.type_var.index = sig_index; + import->func.decl.sig = ctx->module->func_types.data[sig_index]->sig; + + WabtFuncPtr func_ptr = &import->func; + wabt_append_func_ptr_value(&ctx->module->funcs, &func_ptr); + ctx->module->num_func_imports++; + return WABT_OK; +} + +static WabtResult on_import_table(uint32_t import_index, + uint32_t table_index, + WabtType elem_type, + const WabtLimits* elem_limits, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(import_index == ctx->module->imports.size - 1); + WabtImport* import = ctx->module->imports.data[import_index]; + import->kind = WABT_EXTERNAL_KIND_TABLE; + import->table.elem_limits = *elem_limits; + + WabtTablePtr table_ptr = &import->table; + wabt_append_table_ptr_value(&ctx->module->tables, &table_ptr); + ctx->module->num_table_imports++; + return WABT_OK; +} + +static WabtResult on_import_memory(uint32_t import_index, + uint32_t memory_index, + const WabtLimits* page_limits, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(import_index == ctx->module->imports.size - 1); + WabtImport* import = ctx->module->imports.data[import_index]; + import->kind = WABT_EXTERNAL_KIND_MEMORY; + import->memory.page_limits = *page_limits; + + WabtMemoryPtr memory_ptr = &import->memory; + wabt_append_memory_ptr_value(&ctx->module->memories, &memory_ptr); + ctx->module->num_memory_imports++; + return WABT_OK; +} + +static WabtResult on_import_global(uint32_t import_index, + uint32_t global_index, + WabtType type, + bool mutable_, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(import_index == ctx->module->imports.size - 1); + WabtImport* import = ctx->module->imports.data[import_index]; + import->kind = WABT_EXTERNAL_KIND_GLOBAL; + import->global.type = type; + import->global.mutable_ = mutable_; + + WabtGlobalPtr global_ptr = &import->global; + wabt_append_global_ptr_value(&ctx->module->globals, &global_ptr); + ctx->module->num_global_imports++; + return WABT_OK; +} + +static WabtResult on_function_signatures_count(uint32_t count, + void* user_data) { + Context* ctx = (Context*)user_data; + wabt_reserve_func_ptrs(&ctx->module->funcs, + ctx->module->num_func_imports + count); + return WABT_OK; +} + +static WabtResult on_function_signature(uint32_t index, + uint32_t sig_index, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(index < ctx->module->funcs.capacity); + assert(sig_index < ctx->module->func_types.size); + + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_FUNC; + + WabtFunc* func = &field->func; + WABT_ZERO_MEMORY(*func); + func->decl.flags = WABT_FUNC_DECLARATION_FLAG_HAS_FUNC_TYPE | + WABT_FUNC_DECLARATION_FLAG_SHARED_SIGNATURE; + func->decl.type_var.type = WABT_VAR_TYPE_INDEX; + func->decl.type_var.index = sig_index; + func->decl.sig = ctx->module->func_types.data[sig_index]->sig; + + WabtFuncPtr* func_ptr = wabt_append_func_ptr(&ctx->module->funcs); + *func_ptr = func; + return WABT_OK; +} + +static WabtResult on_table_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + wabt_reserve_table_ptrs(&ctx->module->tables, + ctx->module->num_table_imports + count); + return WABT_OK; +} + +static WabtResult on_table(uint32_t index, + WabtType elem_type, + const WabtLimits* elem_limits, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(index < ctx->module->tables.capacity); + + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_TABLE; + + WabtTable* table = &field->table; + WABT_ZERO_MEMORY(*table); + table->elem_limits = *elem_limits; + + WabtTablePtr* table_ptr = wabt_append_table_ptr(&ctx->module->tables); + *table_ptr = table; + return WABT_OK; +} + +static WabtResult on_memory_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + wabt_reserve_memory_ptrs(&ctx->module->memories, + ctx->module->num_memory_imports + count); + return WABT_OK; +} + +static WabtResult on_memory(uint32_t index, + const WabtLimits* page_limits, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(index < ctx->module->memories.capacity); + + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_MEMORY; + + WabtMemory* memory = &field->memory; + WABT_ZERO_MEMORY(*memory); + memory->page_limits = *page_limits; + + WabtMemoryPtr* memory_ptr = wabt_append_memory_ptr(&ctx->module->memories); + *memory_ptr = memory; + return WABT_OK; +} + +static WabtResult on_global_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + wabt_reserve_global_ptrs(&ctx->module->globals, + ctx->module->num_global_imports + count); + return WABT_OK; +} + +static WabtResult begin_global(uint32_t index, + WabtType type, + bool mutable_, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(index < ctx->module->globals.capacity); + + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_GLOBAL; + + WabtGlobal* global = &field->global; + WABT_ZERO_MEMORY(*global); + global->type = type; + global->mutable_ = mutable_; + + WabtGlobalPtr* global_ptr = wabt_append_global_ptr(&ctx->module->globals); + *global_ptr = global; + return WABT_OK; +} + +static WabtResult begin_global_init_expr(uint32_t index, void* user_data) { + Context* ctx = (Context*)user_data; + assert(index == ctx->module->globals.size - 1); + WabtGlobal* global = ctx->module->globals.data[index]; + ctx->current_init_expr = &global->init_expr; + return WABT_OK; +} + +static WabtResult end_global_init_expr(uint32_t index, void* user_data) { + Context* ctx = (Context*)user_data; + ctx->current_init_expr = NULL; + return WABT_OK; +} + +static WabtResult on_export_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + wabt_reserve_export_ptrs(&ctx->module->exports, count); + return WABT_OK; +} + +static WabtResult on_export(uint32_t index, + WabtExternalKind kind, + uint32_t item_index, + WabtStringSlice name, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_EXPORT; + + WabtExport* export_ = &field->export_; + WABT_ZERO_MEMORY(*export_); + export_->name = wabt_dup_string_slice(name); + switch (kind) { + case WABT_EXTERNAL_KIND_FUNC: + assert(item_index < ctx->module->funcs.size); + break; + case WABT_EXTERNAL_KIND_TABLE: + assert(item_index < ctx->module->tables.size); + break; + case WABT_EXTERNAL_KIND_MEMORY: + assert(item_index < ctx->module->memories.size); + break; + case WABT_EXTERNAL_KIND_GLOBAL: + assert(item_index < ctx->module->globals.size); + break; + case WABT_NUM_EXTERNAL_KINDS: + assert(0); + break; + } + export_->var.type = WABT_VAR_TYPE_INDEX; + export_->var.index = item_index; + export_->kind = kind; + + assert(index < ctx->module->exports.capacity); + WabtExportPtr* export_ptr = wabt_append_export_ptr(&ctx->module->exports); + *export_ptr = export_; + return WABT_OK; +} + +static WabtResult on_start_function(uint32_t func_index, void* user_data) { + Context* ctx = (Context*)user_data; + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_START; + + field->start.type = WABT_VAR_TYPE_INDEX; + assert(func_index < ctx->module->funcs.size); + field->start.index = func_index; + + ctx->module->start = &field->start; + return WABT_OK; +} + +static WabtResult on_function_bodies_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + assert(ctx->module->num_func_imports + count == ctx->module->funcs.size); + (void)ctx; + return WABT_OK; +} + +static WabtResult begin_function_body(WabtBinaryReaderContext* context, + uint32_t index) { + Context* ctx = (Context*)context->user_data; + assert(index < ctx->module->funcs.size); + ctx->current_func = ctx->module->funcs.data[index]; + push_label(ctx, WABT_LABEL_TYPE_FUNC, &ctx->current_func->first_expr); + return WABT_OK; +} + +static WabtResult on_local_decl(uint32_t decl_index, + uint32_t count, + WabtType type, + void* user_data) { + Context* ctx = (Context*)user_data; + size_t old_local_count = ctx->current_func->local_types.size; + size_t new_local_count = old_local_count + count; + wabt_reserve_types(&ctx->current_func->local_types, new_local_count); + WabtTypeVector* types = &ctx->current_func->local_types; + size_t i; + for (i = 0; i < count; ++i) + types->data[old_local_count + i] = type; + types->size = new_local_count; + return WABT_OK; +} + +static WabtResult on_binary_expr(WabtOpcode opcode, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_binary_expr(); + expr->binary.opcode = opcode; + return append_expr(ctx, expr); +} + +static WabtResult on_block_expr(uint32_t num_types, + WabtType* sig_types, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_block_expr(); + WabtTypeVector src; + WABT_ZERO_MEMORY(src); + src.size = num_types; + src.data = sig_types; + wabt_extend_types(&expr->block.sig, &src); + append_expr(ctx, expr); + push_label(ctx, WABT_LABEL_TYPE_BLOCK, &expr->block.first); + return WABT_OK; +} + +static WabtResult on_br_expr(uint32_t depth, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_br_expr(); + expr->br.var.type = WABT_VAR_TYPE_INDEX; + expr->br.var.index = depth; + return append_expr(ctx, expr); +} + +static WabtResult on_br_if_expr(uint32_t depth, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_br_if_expr(); + expr->br_if.var.type = WABT_VAR_TYPE_INDEX; + expr->br_if.var.index = depth; + return append_expr(ctx, expr); +} + +static WabtResult on_br_table_expr(WabtBinaryReaderContext* context, + uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth) { + Context* ctx = (Context*)context->user_data; + WabtExpr* expr = wabt_new_br_table_expr(); + wabt_reserve_vars(&expr->br_table.targets, num_targets); + expr->br_table.targets.size = num_targets; + uint32_t i; + for (i = 0; i < num_targets; ++i) { + WabtVar* var = &expr->br_table.targets.data[i]; + var->type = WABT_VAR_TYPE_INDEX; + var->index = target_depths[i]; + } + expr->br_table.default_target.type = WABT_VAR_TYPE_INDEX; + expr->br_table.default_target.index = default_target_depth; + return append_expr(ctx, expr); +} + +static WabtResult on_call_expr(uint32_t func_index, void* user_data) { + Context* ctx = (Context*)user_data; + assert(func_index < ctx->module->funcs.size); + WabtExpr* expr = wabt_new_call_expr(); + expr->call.var.type = WABT_VAR_TYPE_INDEX; + expr->call.var.index = func_index; + return append_expr(ctx, expr); +} + +static WabtResult on_call_indirect_expr(uint32_t sig_index, void* user_data) { + Context* ctx = (Context*)user_data; + assert(sig_index < ctx->module->func_types.size); + WabtExpr* expr = wabt_new_call_indirect_expr(); + expr->call_indirect.var.type = WABT_VAR_TYPE_INDEX; + expr->call_indirect.var.index = sig_index; + return append_expr(ctx, expr); +} + +static WabtResult on_compare_expr(WabtOpcode opcode, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_compare_expr(); + expr->compare.opcode = opcode; + return append_expr(ctx, expr); +} + +static WabtResult on_convert_expr(WabtOpcode opcode, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_convert_expr(); + expr->convert.opcode = opcode; + return append_expr(ctx, expr); +} + +static WabtResult on_current_memory_expr(void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_current_memory_expr(); + return append_expr(ctx, expr); +} + +static WabtResult on_drop_expr(void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_drop_expr(); + return append_expr(ctx, expr); +} + +static WabtResult on_else_expr(void* user_data) { + Context* ctx = (Context*)user_data; + LabelNode* label; + CHECK_RESULT(top_label(ctx, &label)); + if (label->label_type != WABT_LABEL_TYPE_IF) { + print_error(ctx, "else expression without matching if"); + return WABT_ERROR; + } + + LabelNode* parent_label; + CHECK_RESULT(get_label_at(ctx, &parent_label, 1)); + assert(parent_label->last->type == WABT_EXPR_TYPE_IF); + + label->label_type = WABT_LABEL_TYPE_ELSE; + label->first = &parent_label->last->if_.false_; + label->last = NULL; + return WABT_OK; +} + +static WabtResult on_end_expr(void* user_data) { + Context* ctx = (Context*)user_data; + return pop_label(ctx); +} + +static WabtResult on_f32_const_expr(uint32_t value_bits, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_const_expr(); + expr->const_.type = WABT_TYPE_F32; + expr->const_.f32_bits = value_bits; + return append_expr(ctx, expr); +} + +static WabtResult on_f64_const_expr(uint64_t value_bits, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_const_expr(); + expr->const_.type = WABT_TYPE_F64; + expr->const_.f64_bits = value_bits; + return append_expr(ctx, expr); +} + +static WabtResult on_get_global_expr(uint32_t global_index, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_get_global_expr(); + expr->get_global.var.type = WABT_VAR_TYPE_INDEX; + expr->get_global.var.index = global_index; + return append_expr(ctx, expr); +} + +static WabtResult on_get_local_expr(uint32_t local_index, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_get_local_expr(); + expr->get_local.var.type = WABT_VAR_TYPE_INDEX; + expr->get_local.var.index = local_index; + return append_expr(ctx, expr); +} + +static WabtResult on_grow_memory_expr(void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_grow_memory_expr(); + return append_expr(ctx, expr); +} + +static WabtResult on_i32_const_expr(uint32_t value, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_const_expr(); + expr->const_.type = WABT_TYPE_I32; + expr->const_.u32 = value; + return append_expr(ctx, expr); +} + +static WabtResult on_i64_const_expr(uint64_t value, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_const_expr(); + expr->const_.type = WABT_TYPE_I64; + expr->const_.u64 = value; + return append_expr(ctx, expr); +} + +static WabtResult on_if_expr(uint32_t num_types, + WabtType* sig_types, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_if_expr(); + WabtTypeVector src; + WABT_ZERO_MEMORY(src); + src.size = num_types; + src.data = sig_types; + wabt_extend_types(&expr->if_.true_.sig, &src); + append_expr(ctx, expr); + push_label(ctx, WABT_LABEL_TYPE_IF, &expr->if_.true_.first); + return WABT_OK; +} + +static WabtResult on_load_expr(WabtOpcode opcode, + uint32_t alignment_log2, + uint32_t offset, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_load_expr(); + expr->load.opcode = opcode; + expr->load.align = 1 << alignment_log2; + expr->load.offset = offset; + return append_expr(ctx, expr); +} + +static WabtResult on_loop_expr(uint32_t num_types, + WabtType* sig_types, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_loop_expr(); + WabtTypeVector src; + WABT_ZERO_MEMORY(src); + src.size = num_types; + src.data = sig_types; + wabt_extend_types(&expr->loop.sig, &src); + append_expr(ctx, expr); + push_label(ctx, WABT_LABEL_TYPE_LOOP, &expr->loop.first); + return WABT_OK; +} + +static WabtResult on_nop_expr(void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_nop_expr(); + return append_expr(ctx, expr); +} + +static WabtResult on_return_expr(void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_return_expr(); + return append_expr(ctx, expr); +} + +static WabtResult on_select_expr(void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_select_expr(); + return append_expr(ctx, expr); +} + +static WabtResult on_set_global_expr(uint32_t global_index, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_set_global_expr(); + expr->set_global.var.type = WABT_VAR_TYPE_INDEX; + expr->set_global.var.index = global_index; + return append_expr(ctx, expr); +} + +static WabtResult on_set_local_expr(uint32_t local_index, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_set_local_expr(); + expr->set_local.var.type = WABT_VAR_TYPE_INDEX; + expr->set_local.var.index = local_index; + return append_expr(ctx, expr); +} + +static WabtResult on_store_expr(WabtOpcode opcode, + uint32_t alignment_log2, + uint32_t offset, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_store_expr(); + expr->store.opcode = opcode; + expr->store.align = 1 << alignment_log2; + expr->store.offset = offset; + return append_expr(ctx, expr); +} + +static WabtResult on_tee_local_expr(uint32_t local_index, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_tee_local_expr(); + expr->tee_local.var.type = WABT_VAR_TYPE_INDEX; + expr->tee_local.var.index = local_index; + return append_expr(ctx, expr); +} + +static WabtResult on_unary_expr(WabtOpcode opcode, void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_unary_expr(); + expr->unary.opcode = opcode; + return append_expr(ctx, expr); +} + +static WabtResult on_unreachable_expr(void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_unreachable_expr(); + return append_expr(ctx, expr); +} + +static WabtResult end_function_body(uint32_t index, void* user_data) { + Context* ctx = (Context*)user_data; + CHECK_RESULT(pop_label(ctx)); + ctx->current_func = NULL; + return WABT_OK; +} + +static WabtResult on_elem_segment_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + wabt_reserve_elem_segment_ptrs(&ctx->module->elem_segments, + count); + return WABT_OK; +} + +static WabtResult begin_elem_segment(uint32_t index, + uint32_t table_index, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_ELEM_SEGMENT; + + WabtElemSegment* segment = &field->elem_segment; + WABT_ZERO_MEMORY(*segment); + segment->table_var.type = WABT_VAR_TYPE_INDEX; + segment->table_var.index = table_index; + + assert(index == ctx->module->elem_segments.size); + assert(index < ctx->module->elem_segments.capacity); + WabtElemSegmentPtr* segment_ptr = + wabt_append_elem_segment_ptr(&ctx->module->elem_segments); + *segment_ptr = segment; + return WABT_OK; +} + +static WabtResult begin_elem_segment_init_expr(uint32_t index, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(index == ctx->module->elem_segments.size - 1); + WabtElemSegment* segment = ctx->module->elem_segments.data[index]; + ctx->current_init_expr = &segment->offset; + return WABT_OK; +} + +static WabtResult end_elem_segment_init_expr(uint32_t index, void* user_data) { + Context* ctx = (Context*)user_data; + ctx->current_init_expr = NULL; + return WABT_OK; +} + +static WabtResult on_elem_segment_function_index_count( + WabtBinaryReaderContext* context, + uint32_t index, + uint32_t count) { + Context* ctx = (Context*)context->user_data; + assert(index == ctx->module->elem_segments.size - 1); + WabtElemSegment* segment = ctx->module->elem_segments.data[index]; + wabt_reserve_vars(&segment->vars, count); + return WABT_OK; +} + +static WabtResult on_elem_segment_function_index(uint32_t index, + uint32_t func_index, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(index == ctx->module->elem_segments.size - 1); + WabtElemSegment* segment = ctx->module->elem_segments.data[index]; + WabtVar* var = wabt_append_var(&segment->vars); + var->type = WABT_VAR_TYPE_INDEX; + var->index = func_index; + return WABT_OK; +} + +static WabtResult on_data_segment_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + wabt_reserve_data_segment_ptrs(&ctx->module->data_segments, count); + return WABT_OK; +} + +static WabtResult begin_data_segment(uint32_t index, + uint32_t memory_index, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtModuleField* field = wabt_append_module_field(ctx->module); + field->type = WABT_MODULE_FIELD_TYPE_DATA_SEGMENT; + + WabtDataSegment* segment = &field->data_segment; + WABT_ZERO_MEMORY(*segment); + segment->memory_var.type = WABT_VAR_TYPE_INDEX; + segment->memory_var.index = memory_index; + + assert(index == ctx->module->data_segments.size); + assert(index < ctx->module->data_segments.capacity); + WabtDataSegmentPtr* segment_ptr = + wabt_append_data_segment_ptr(&ctx->module->data_segments); + *segment_ptr = segment; + return WABT_OK; +} + +static WabtResult begin_data_segment_init_expr(uint32_t index, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(index == ctx->module->data_segments.size - 1); + WabtDataSegment* segment = ctx->module->data_segments.data[index]; + ctx->current_init_expr = &segment->offset; + return WABT_OK; +} + +static WabtResult end_data_segment_init_expr(uint32_t index, void* user_data) { + Context* ctx = (Context*)user_data; + ctx->current_init_expr = NULL; + return WABT_OK; +} + +static WabtResult on_data_segment_data(uint32_t index, + const void* data, + uint32_t size, + void* user_data) { + Context* ctx = (Context*)user_data; + assert(index == ctx->module->data_segments.size - 1); + WabtDataSegment* segment = ctx->module->data_segments.data[index]; + segment->data = wabt_alloc(size); + segment->size = size; + memcpy(segment->data, data, size); + return WABT_OK; +} + +static WabtResult on_function_names_count(uint32_t count, void* user_data) { + Context* ctx = (Context*)user_data; + if (count > ctx->module->funcs.size) { + print_error( + ctx, "expected function name count (%u) <= function count (%" PRIzd ")", + count, ctx->module->funcs.size); + return WABT_ERROR; + } + return WABT_OK; +} + +static WabtResult on_function_name(uint32_t index, + WabtStringSlice name, + void* user_data) { + Context* ctx = (Context*)user_data; + + WabtStringSlice new_name; + dup_name(ctx, &name, &new_name); + + WabtBinding* binding = + wabt_insert_binding(&ctx->module->func_bindings, &new_name); + binding->index = index; + + WabtFunc* func = ctx->module->funcs.data[index]; + func->name = new_name; + return WABT_OK; +} + +static WabtResult on_local_names_count(uint32_t index, + uint32_t count, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtModule* module = ctx->module; + assert(index < module->funcs.size); + WabtFunc* func = module->funcs.data[index]; + uint32_t num_params_and_locals = wabt_get_num_params_and_locals(func); + if (count > num_params_and_locals) { + print_error(ctx, "expected local name count (%d) <= local count (%d)", + count, num_params_and_locals); + return WABT_ERROR; + } + return WABT_OK; +} + +static WabtResult on_init_expr_f32_const_expr(uint32_t index, + uint32_t value, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_const_expr(); + expr->const_.type = WABT_TYPE_F32; + expr->const_.f32_bits = value; + *ctx->current_init_expr = expr; + return WABT_OK; +} + +static WabtResult on_init_expr_f64_const_expr(uint32_t index, + uint64_t value, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_const_expr(); + expr->const_.type = WABT_TYPE_F64; + expr->const_.f64_bits = value; + *ctx->current_init_expr = expr; + return WABT_OK; +} + +static WabtResult on_init_expr_get_global_expr(uint32_t index, + uint32_t global_index, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_get_global_expr(); + expr->get_global.var.type = WABT_VAR_TYPE_INDEX; + expr->get_global.var.index = global_index; + *ctx->current_init_expr = expr; + return WABT_OK; +} + +static WabtResult on_init_expr_i32_const_expr(uint32_t index, + uint32_t value, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_const_expr(); + expr->const_.type = WABT_TYPE_I32; + expr->const_.u32 = value; + *ctx->current_init_expr = expr; + return WABT_OK; +} + +static WabtResult on_init_expr_i64_const_expr(uint32_t index, + uint64_t value, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtExpr* expr = wabt_new_const_expr(); + expr->const_.type = WABT_TYPE_I64; + expr->const_.u64 = value; + *ctx->current_init_expr = expr; + return WABT_OK; +} + +static WabtResult on_local_name(uint32_t func_index, + uint32_t local_index, + WabtStringSlice name, + void* user_data) { + Context* ctx = (Context*)user_data; + WabtModule* module = ctx->module; + WabtFunc* func = module->funcs.data[func_index]; + uint32_t num_params = wabt_get_num_params(func); + WabtStringSlice new_name; + dup_name(ctx, &name, &new_name); + WabtBindingHash* bindings; + WabtBinding* binding; + uint32_t index; + if (local_index < num_params) { + /* param name */ + bindings = &func->param_bindings; + index = local_index; + } else { + /* local name */ + bindings = &func->local_bindings; + index = local_index - num_params; + } + binding = wabt_insert_binding(bindings, &new_name); + binding->index = index; + return WABT_OK; +} + +static void wabt_destroy_label_node(LabelNode* node) { + if (*node->first) + wabt_destroy_expr_list(*node->first); +} + +WabtResult wabt_read_binary_ast(const void* data, + size_t size, + const WabtReadBinaryOptions* options, + WabtBinaryErrorHandler* error_handler, + struct WabtModule* out_module) { + Context ctx; + WABT_ZERO_MEMORY(ctx); + ctx.error_handler = error_handler; + ctx.module = out_module; + + WabtBinaryReader reader; + WABT_ZERO_MEMORY(reader); + reader.user_data = &ctx; + reader.on_error = on_error; + + reader.on_signature_count = on_signature_count; + reader.on_signature = on_signature; + + reader.on_import_count = on_import_count; + reader.on_import = on_import; + reader.on_import_func = on_import_func; + reader.on_import_table = on_import_table; + reader.on_import_memory = on_import_memory; + reader.on_import_global = on_import_global; + + reader.on_function_signatures_count = on_function_signatures_count; + reader.on_function_signature = on_function_signature; + + reader.on_table_count = on_table_count; + reader.on_table = on_table; + + reader.on_memory_count = on_memory_count; + reader.on_memory = on_memory; + + reader.on_global_count = on_global_count; + reader.begin_global = begin_global; + reader.begin_global_init_expr = begin_global_init_expr; + reader.end_global_init_expr = end_global_init_expr; + + reader.on_export_count = on_export_count; + reader.on_export = on_export; + + reader.on_start_function = on_start_function; + + reader.on_function_bodies_count = on_function_bodies_count; + reader.begin_function_body = begin_function_body; + reader.on_local_decl = on_local_decl; + reader.on_binary_expr = on_binary_expr; + reader.on_block_expr = on_block_expr; + reader.on_br_expr = on_br_expr; + reader.on_br_if_expr = on_br_if_expr; + reader.on_br_table_expr = on_br_table_expr; + reader.on_call_expr = on_call_expr; + reader.on_call_indirect_expr = on_call_indirect_expr; + reader.on_compare_expr = on_compare_expr; + reader.on_convert_expr = on_convert_expr; + reader.on_current_memory_expr = on_current_memory_expr; + reader.on_drop_expr = on_drop_expr; + reader.on_else_expr = on_else_expr; + reader.on_end_expr = on_end_expr; + reader.on_f32_const_expr = on_f32_const_expr; + reader.on_f64_const_expr = on_f64_const_expr; + reader.on_get_global_expr = on_get_global_expr; + reader.on_get_local_expr = on_get_local_expr; + reader.on_grow_memory_expr = on_grow_memory_expr; + reader.on_i32_const_expr = on_i32_const_expr; + reader.on_i64_const_expr = on_i64_const_expr; + reader.on_if_expr = on_if_expr; + reader.on_load_expr = on_load_expr; + reader.on_loop_expr = on_loop_expr; + reader.on_nop_expr = on_nop_expr; + reader.on_return_expr = on_return_expr; + reader.on_select_expr = on_select_expr; + reader.on_set_global_expr = on_set_global_expr; + reader.on_set_local_expr = on_set_local_expr; + reader.on_store_expr = on_store_expr; + reader.on_tee_local_expr = on_tee_local_expr; + reader.on_unary_expr = on_unary_expr; + reader.on_unreachable_expr = on_unreachable_expr; + reader.end_function_body = end_function_body; + + reader.on_elem_segment_count = on_elem_segment_count; + reader.begin_elem_segment = begin_elem_segment; + reader.begin_elem_segment_init_expr = begin_elem_segment_init_expr; + reader.end_elem_segment_init_expr = end_elem_segment_init_expr; + reader.on_elem_segment_function_index_count = + on_elem_segment_function_index_count; + reader.on_elem_segment_function_index = on_elem_segment_function_index; + + reader.on_data_segment_count = on_data_segment_count; + reader.begin_data_segment = begin_data_segment; + reader.begin_data_segment_init_expr = begin_data_segment_init_expr; + reader.end_data_segment_init_expr = end_data_segment_init_expr; + reader.on_data_segment_data = on_data_segment_data; + + reader.on_function_names_count = on_function_names_count; + reader.on_function_name = on_function_name; + reader.on_local_names_count = on_local_names_count; + reader.on_local_name = on_local_name; + + reader.on_init_expr_f32_const_expr = on_init_expr_f32_const_expr; + reader.on_init_expr_f64_const_expr = on_init_expr_f64_const_expr; + reader.on_init_expr_get_global_expr = on_init_expr_get_global_expr; + reader.on_init_expr_i32_const_expr = on_init_expr_i32_const_expr; + reader.on_init_expr_i64_const_expr = on_init_expr_i64_const_expr; + + WabtResult result = wabt_read_binary(data, size, &reader, 1, options); + WABT_DESTROY_VECTOR_AND_ELEMENTS(ctx.label_stack, label_node); + if (WABT_FAILED(result)) + wabt_destroy_module(out_module); + return result; +} |