diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader-ast.cc | 945 | ||||
-rw-r--r-- | src/binary-reader-interpreter.cc | 1763 | ||||
-rw-r--r-- | src/binary-reader-linker.cc | 305 | ||||
-rw-r--r-- | src/binary-reader-logging.cc | 592 | ||||
-rw-r--r-- | src/binary-reader-logging.h | 242 | ||||
-rw-r--r-- | src/binary-reader-nop.h | 329 | ||||
-rw-r--r-- | src/binary-reader-objdump.cc | 936 | ||||
-rw-r--r-- | src/binary-reader-opcnt.cc | 115 | ||||
-rw-r--r-- | src/binary-reader.cc | 1284 | ||||
-rw-r--r-- | src/binary-reader.h | 523 | ||||
-rw-r--r-- | src/tools/wasm-link.cc | 12 | ||||
-rw-r--r-- | src/wasm-link.h | 4 |
12 files changed, 3644 insertions, 3406 deletions
diff --git a/src/binary-reader-ast.cc b/src/binary-reader-ast.cc index 39c9e8fa..de0a2a93 100644 --- a/src/binary-reader-ast.cc +++ b/src/binary-reader-ast.cc @@ -25,7 +25,7 @@ #include <vector> #include "ast.h" -#include "binary-reader.h" +#include "binary-reader-nop.h" #include "common.h" #define CHECK_RESULT(expr) \ @@ -49,7 +49,155 @@ struct LabelNode { LabelNode::LabelNode(LabelType label_type, Expr** first) : label_type(label_type), first(first), last(nullptr) {} -struct Context { +class BinaryReaderAST : public BinaryReaderNop { + public: + BinaryReaderAST(Module* out_module, BinaryErrorHandler* error_handler); + + virtual bool OnError(const char* message); + + virtual Result OnTypeCount(uint32_t count); + virtual Result OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types); + + virtual Result OnImportCount(uint32_t count); + virtual Result OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name); + virtual Result OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index); + virtual Result OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits); + virtual Result OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits); + virtual Result OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_); + + virtual Result OnFunctionCount(uint32_t count); + virtual Result OnFunction(uint32_t index, uint32_t sig_index); + + virtual Result OnTableCount(uint32_t count); + virtual Result OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits); + + virtual Result OnMemoryCount(uint32_t count); + virtual Result OnMemory(uint32_t index, const Limits* limits); + + virtual Result OnGlobalCount(uint32_t count); + virtual Result BeginGlobal(uint32_t index, Type type, bool mutable_); + virtual Result BeginGlobalInitExpr(uint32_t index); + virtual Result EndGlobalInitExpr(uint32_t index); + + virtual Result OnExportCount(uint32_t count); + virtual Result OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name); + + virtual Result OnStartFunction(uint32_t func_index); + + virtual Result OnFunctionBodyCount(uint32_t count); + virtual Result BeginFunctionBody(uint32_t index); + virtual Result OnLocalDecl(uint32_t decl_index, uint32_t count, Type type); + + virtual Result OnBinaryExpr(Opcode opcode); + virtual Result OnBlockExpr(uint32_t num_types, Type* sig_types); + virtual Result OnBrExpr(uint32_t depth); + virtual Result OnBrIfExpr(uint32_t depth); + virtual Result OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth); + virtual Result OnCallExpr(uint32_t func_index); + virtual Result OnCallIndirectExpr(uint32_t sig_index); + virtual Result OnCompareExpr(Opcode opcode); + virtual Result OnConvertExpr(Opcode opcode); + virtual Result OnDropExpr(); + virtual Result OnElseExpr(); + virtual Result OnEndExpr(); + virtual Result OnF32ConstExpr(uint32_t value_bits); + virtual Result OnF64ConstExpr(uint64_t value_bits); + virtual Result OnGetGlobalExpr(uint32_t global_index); + virtual Result OnGetLocalExpr(uint32_t local_index); + virtual Result OnGrowMemoryExpr(); + virtual Result OnI32ConstExpr(uint32_t value); + virtual Result OnI64ConstExpr(uint64_t value); + virtual Result OnIfExpr(uint32_t num_types, Type* sig_types); + virtual Result OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset); + virtual Result OnLoopExpr(uint32_t num_types, Type* sig_types); + virtual Result OnCurrentMemoryExpr(); + virtual Result OnNopExpr(); + virtual Result OnReturnExpr(); + virtual Result OnSelectExpr(); + virtual Result OnSetGlobalExpr(uint32_t global_index); + virtual Result OnSetLocalExpr(uint32_t local_index); + virtual Result OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset); + virtual Result OnTeeLocalExpr(uint32_t local_index); + virtual Result OnUnaryExpr(Opcode opcode); + virtual Result OnUnreachableExpr(); + virtual Result EndFunctionBody(uint32_t index); + + virtual Result OnElemSegmentCount(uint32_t count); + virtual Result BeginElemSegment(uint32_t index, uint32_t table_index); + virtual Result BeginElemSegmentInitExpr(uint32_t index); + virtual Result EndElemSegmentInitExpr(uint32_t index); + virtual Result OnElemSegmentFunctionIndexCount(uint32_t index, + uint32_t count); + virtual Result OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index); + + virtual Result OnDataSegmentCount(uint32_t count); + virtual Result BeginDataSegment(uint32_t index, uint32_t memory_index); + virtual Result BeginDataSegmentInitExpr(uint32_t index); + virtual Result EndDataSegmentInitExpr(uint32_t index); + virtual Result OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size); + + virtual Result OnFunctionNamesCount(uint32_t num_functions); + virtual Result OnFunctionName(uint32_t function_index, + StringSlice function_name); + virtual Result OnLocalNameLocalCount(uint32_t function_index, + uint32_t num_locals); + virtual Result OnLocalName(uint32_t function_index, + uint32_t local_index, + StringSlice local_name); + + virtual Result OnInitExprF32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprF64ConstExpr(uint32_t index, uint64_t value); + virtual Result OnInitExprGetGlobalExpr(uint32_t index, uint32_t global_index); + virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprI64ConstExpr(uint32_t index, uint64_t value); + + private: + bool HandleError(uint32_t offset, const char* message); + void PrintError(const char* format, ...); + void PushLabel(LabelType label_type, Expr** first); + Result PopLabel(); + Result GetLabelAt(LabelNode** label, uint32_t depth); + Result TopLabel(LabelNode** label); + Result AppendExpr(Expr* expr); + BinaryErrorHandler* error_handler = nullptr; Module* module = nullptr; @@ -59,50 +207,50 @@ struct Context { Expr** current_init_expr = nullptr; }; -} // namespace +BinaryReaderAST::BinaryReaderAST(Module* out_module, + BinaryErrorHandler* error_handler) + : error_handler(error_handler), module(out_module) {} -static bool handle_error(Context* ctx, uint32_t offset, const char* message); - -static void WABT_PRINTF_FORMAT(2, 3) - print_error(Context* ctx, const char* format, ...) { +void WABT_PRINTF_FORMAT(2, 3) BinaryReaderAST::PrintError(const char* format, + ...) { WABT_SNPRINTF_ALLOCA(buffer, length, format); - handle_error(ctx, WABT_UNKNOWN_OFFSET, buffer); + HandleError(WABT_UNKNOWN_OFFSET, buffer); } -static void push_label(Context* ctx, LabelType label_type, Expr** first) { - ctx->max_depth++; - ctx->label_stack.emplace_back(label_type, first); +void BinaryReaderAST::PushLabel(LabelType label_type, Expr** first) { + max_depth++; + label_stack.emplace_back(label_type, first); } -static Result pop_label(Context* ctx) { - if (ctx->label_stack.size() == 0) { - print_error(ctx, "popping empty label stack"); +Result BinaryReaderAST::PopLabel() { + if (label_stack.size() == 0) { + PrintError("popping empty label stack"); return Result::Error; } - ctx->max_depth--; - ctx->label_stack.pop_back(); + max_depth--; + label_stack.pop_back(); return Result::Ok; } -static Result 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()); +Result BinaryReaderAST::GetLabelAt(LabelNode** label, uint32_t depth) { + if (depth >= label_stack.size()) { + PrintError("accessing stack depth: %u >= max: %" PRIzd, depth, + label_stack.size()); return Result::Error; } - *label = &ctx->label_stack[ctx->label_stack.size() - depth - 1]; + *label = &label_stack[label_stack.size() - depth - 1]; return Result::Ok; } -static Result top_label(Context* ctx, LabelNode** label) { - return get_label_at(ctx, label, 0); +Result BinaryReaderAST::TopLabel(LabelNode** label) { + return GetLabelAt(label, 0); } -static Result append_expr(Context* ctx, Expr* expr) { +Result BinaryReaderAST::AppendExpr(Expr* expr) { LabelNode* label; - if (WABT_FAILED(top_label(ctx, &label))) { + if (WABT_FAILED(TopLabel(&label))) { delete expr; return Result::Error; } @@ -115,154 +263,132 @@ static Result append_expr(Context* ctx, Expr* expr) { return Result::Ok; } -static bool handle_error(Context* ctx, uint32_t offset, const char* message) { - if (ctx->error_handler->on_error) { - return ctx->error_handler->on_error(offset, message, - ctx->error_handler->user_data); +bool BinaryReaderAST::HandleError(uint32_t offset, const char* message) { + if (error_handler->on_error) { + return error_handler->on_error(offset, message, error_handler->user_data); } return false; } -static bool on_error(BinaryReaderContext* reader_context, const char* message) { - Context* ctx = static_cast<Context*>(reader_context->user_data); - return handle_error(ctx, reader_context->offset, message); +bool BinaryReaderAST::OnError(const char* message) { + return HandleError(state->offset, message); } -static Result on_signature_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->func_types.reserve(count); +Result BinaryReaderAST::OnTypeCount(uint32_t count) { + module->func_types.reserve(count); return Result::Ok; } -static Result on_signature(uint32_t index, - uint32_t param_count, - Type* param_types, - uint32_t result_count, - Type* result_types, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::FuncType; field->func_type = new FuncType(); FuncType* func_type = field->func_type; func_type->sig.param_types.assign(param_types, param_types + param_count); func_type->sig.result_types.assign(result_types, result_types + result_count); - ctx->module->func_types.push_back(func_type); + module->func_types.push_back(func_type); return Result::Ok; } -static Result on_import_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->imports.reserve(count); +Result BinaryReaderAST::OnImportCount(uint32_t count) { + module->imports.reserve(count); return Result::Ok; } -static Result on_import(uint32_t index, - StringSlice module_name, - StringSlice field_name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::Import; field->import = new Import(); Import* import = field->import; import->module_name = dup_string_slice(module_name); import->field_name = dup_string_slice(field_name); - ctx->module->imports.push_back(import); + module->imports.push_back(import); return Result::Ok; } -static Result on_import_func(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t func_index, - uint32_t sig_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(import_index == ctx->module->imports.size() - 1); - Import* import = ctx->module->imports[import_index]; +Result BinaryReaderAST::OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index) { + assert(import_index == module->imports.size() - 1); + Import* import = module->imports[import_index]; import->kind = ExternalKind::Func; import->func = new Func(); import->func->decl.has_func_type = true; import->func->decl.type_var.type = VarType::Index; import->func->decl.type_var.index = sig_index; - import->func->decl.sig = ctx->module->func_types[sig_index]->sig; + import->func->decl.sig = module->func_types[sig_index]->sig; - ctx->module->funcs.push_back(import->func); - ctx->module->num_func_imports++; + module->funcs.push_back(import->func); + module->num_func_imports++; return Result::Ok; } -static Result on_import_table(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t table_index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(import_index == ctx->module->imports.size() - 1); - Import* import = ctx->module->imports[import_index]; +Result BinaryReaderAST::OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits) { + assert(import_index == module->imports.size() - 1); + Import* import = module->imports[import_index]; import->kind = ExternalKind::Table; import->table = new Table(); import->table->elem_limits = *elem_limits; - ctx->module->tables.push_back(import->table); - ctx->module->num_table_imports++; + module->tables.push_back(import->table); + module->num_table_imports++; return Result::Ok; } -static Result on_import_memory(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t memory_index, - const Limits* page_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(import_index == ctx->module->imports.size() - 1); - Import* import = ctx->module->imports[import_index]; +Result BinaryReaderAST::OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits) { + assert(import_index == module->imports.size() - 1); + Import* import = module->imports[import_index]; import->kind = ExternalKind::Memory; import->memory = new Memory(); import->memory->page_limits = *page_limits; - ctx->module->memories.push_back(import->memory); - ctx->module->num_memory_imports++; + module->memories.push_back(import->memory); + module->num_memory_imports++; return Result::Ok; } -static Result on_import_global(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t global_index, - Type type, - bool mutable_, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(import_index == ctx->module->imports.size() - 1); - Import* import = ctx->module->imports[import_index]; +Result BinaryReaderAST::OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_) { + assert(import_index == module->imports.size() - 1); + Import* import = module->imports[import_index]; import->kind = ExternalKind::Global; import->global = new Global(); import->global->type = type; import->global->mutable_ = mutable_; - ctx->module->globals.push_back(import->global); - ctx->module->num_global_imports++; + module->globals.push_back(import->global); + module->num_global_imports++; return Result::Ok; } -static Result on_function_signatures_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->funcs.reserve(ctx->module->num_func_imports + count); +Result BinaryReaderAST::OnFunctionCount(uint32_t count) { + module->funcs.reserve(module->num_func_imports + count); return Result::Ok; } -static Result on_function_signature(uint32_t index, - uint32_t sig_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::OnFunction(uint32_t index, uint32_t sig_index) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::Func; field->func = new Func(); @@ -270,99 +396,79 @@ static Result on_function_signature(uint32_t index, func->decl.has_func_type = true; func->decl.type_var.type = VarType::Index; func->decl.type_var.index = sig_index; - func->decl.sig = ctx->module->func_types[sig_index]->sig; + func->decl.sig = module->func_types[sig_index]->sig; - ctx->module->funcs.push_back(func); + module->funcs.push_back(func); return Result::Ok; } -static Result on_table_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->tables.reserve(ctx->module->num_table_imports + count); +Result BinaryReaderAST::OnTableCount(uint32_t count) { + module->tables.reserve(module->num_table_imports + count); return Result::Ok; } -static Result on_table(uint32_t index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::Table; field->table = new Table(); field->table->elem_limits = *elem_limits; - ctx->module->tables.push_back(field->table); + module->tables.push_back(field->table); return Result::Ok; } -static Result on_memory_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->memories.reserve(ctx->module->num_memory_imports + count); +Result BinaryReaderAST::OnMemoryCount(uint32_t count) { + module->memories.reserve(module->num_memory_imports + count); return Result::Ok; } -static Result on_memory(uint32_t index, - const Limits* page_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::OnMemory(uint32_t index, const Limits* page_limits) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::Memory; field->memory = new Memory(); field->memory->page_limits = *page_limits; - ctx->module->memories.push_back(field->memory); + module->memories.push_back(field->memory); return Result::Ok; } -static Result on_global_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->globals.reserve(ctx->module->num_global_imports + count); +Result BinaryReaderAST::OnGlobalCount(uint32_t count) { + module->globals.reserve(module->num_global_imports + count); return Result::Ok; } -static Result begin_global(uint32_t index, - Type type, - bool mutable_, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::BeginGlobal(uint32_t index, Type type, bool mutable_) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::Global; field->global = new Global(); field->global->type = type; field->global->mutable_ = mutable_; - ctx->module->globals.push_back(field->global); + module->globals.push_back(field->global); return Result::Ok; } -static Result begin_global_init_expr(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(index == ctx->module->globals.size() - 1); - Global* global = ctx->module->globals[index]; - ctx->current_init_expr = &global->init_expr; +Result BinaryReaderAST::BeginGlobalInitExpr(uint32_t index) { + assert(index == module->globals.size() - 1); + Global* global = module->globals[index]; + current_init_expr = &global->init_expr; return Result::Ok; } -static Result end_global_init_expr(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->current_init_expr = nullptr; +Result BinaryReaderAST::EndGlobalInitExpr(uint32_t index) { + current_init_expr = nullptr; return Result::Ok; } -static Result on_export_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->exports.reserve(count); +Result BinaryReaderAST::OnExportCount(uint32_t count) { + module->exports.reserve(count); return Result::Ok; } -static Result on_export(uint32_t index, - ExternalKind kind, - uint32_t item_index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::Export; field->export_ = new Export(); @@ -370,157 +476,135 @@ static Result on_export(uint32_t index, export_->name = dup_string_slice(name); switch (kind) { case ExternalKind::Func: - assert(item_index < ctx->module->funcs.size()); + assert(item_index < module->funcs.size()); break; case ExternalKind::Table: - assert(item_index < ctx->module->tables.size()); + assert(item_index < module->tables.size()); break; case ExternalKind::Memory: - assert(item_index < ctx->module->memories.size()); + assert(item_index < module->memories.size()); break; case ExternalKind::Global: - assert(item_index < ctx->module->globals.size()); + assert(item_index < module->globals.size()); break; } export_->var.type = VarType::Index; export_->var.index = item_index; export_->kind = kind; - ctx->module->exports.push_back(export_); + module->exports.push_back(export_); return Result::Ok; } -static Result on_start_function(uint32_t func_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::OnStartFunction(uint32_t func_index) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::Start; field->start.type = VarType::Index; - assert(func_index < ctx->module->funcs.size()); + assert(func_index < module->funcs.size()); field->start.index = func_index; - ctx->module->start = &field->start; + module->start = &field->start; return Result::Ok; } -static Result on_function_bodies_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(ctx->module->num_func_imports + count == ctx->module->funcs.size()); - WABT_USE(ctx); +Result BinaryReaderAST::OnFunctionBodyCount(uint32_t count) { + assert(module->num_func_imports + count == module->funcs.size()); return Result::Ok; } -static Result begin_function_body(BinaryReaderContext* context, - uint32_t index) { - Context* ctx = static_cast<Context*>(context->user_data); - ctx->current_func = ctx->module->funcs[index]; - push_label(ctx, LabelType::Func, &ctx->current_func->first_expr); +Result BinaryReaderAST::BeginFunctionBody(uint32_t index) { + current_func = module->funcs[index]; + PushLabel(LabelType::Func, ¤t_func->first_expr); return Result::Ok; } -static Result on_local_decl(uint32_t decl_index, - uint32_t count, - Type type, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - TypeVector& types = ctx->current_func->local_types; +Result BinaryReaderAST::OnLocalDecl(uint32_t decl_index, + uint32_t count, + Type type) { + TypeVector& types = current_func->local_types; types.reserve(types.size() + count); for (size_t i = 0; i < count; ++i) types.push_back(type); return Result::Ok; } -static Result on_binary_expr(Opcode opcode, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnBinaryExpr(Opcode opcode) { Expr* expr = Expr::CreateBinary(opcode); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_block_expr(uint32_t num_types, - Type* sig_types, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnBlockExpr(uint32_t num_types, Type* sig_types) { Expr* expr = Expr::CreateBlock(new Block()); expr->block->sig.assign(sig_types, sig_types + num_types); - append_expr(ctx, expr); - push_label(ctx, LabelType::Block, &expr->block->first); + AppendExpr(expr); + PushLabel(LabelType::Block, &expr->block->first); return Result::Ok; } -static Result on_br_expr(uint32_t depth, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnBrExpr(uint32_t depth) { Expr* expr = Expr::CreateBr(Var(depth)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_br_if_expr(uint32_t depth, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnBrIfExpr(uint32_t depth) { Expr* expr = Expr::CreateBrIf(Var(depth)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_br_table_expr(BinaryReaderContext* context, - uint32_t num_targets, - uint32_t* target_depths, - uint32_t default_target_depth) { - Context* ctx = static_cast<Context*>(context->user_data); +Result BinaryReaderAST::OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth) { VarVector* targets = new VarVector(); targets->resize(num_targets); for (uint32_t i = 0; i < num_targets; ++i) { (*targets)[i] = Var(target_depths[i]); } Expr* expr = Expr::CreateBrTable(targets, Var(default_target_depth)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_call_expr(uint32_t func_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(func_index < ctx->module->funcs.size()); +Result BinaryReaderAST::OnCallExpr(uint32_t func_index) { + assert(func_index < module->funcs.size()); Expr* expr = Expr::CreateCall(Var(func_index)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_call_indirect_expr(uint32_t sig_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(sig_index < ctx->module->func_types.size()); +Result BinaryReaderAST::OnCallIndirectExpr(uint32_t sig_index) { + assert(sig_index < module->func_types.size()); Expr* expr = Expr::CreateCallIndirect(Var(sig_index)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_compare_expr(Opcode opcode, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnCompareExpr(Opcode opcode) { Expr* expr = Expr::CreateCompare(opcode); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_convert_expr(Opcode opcode, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnConvertExpr(Opcode opcode) { Expr* expr = Expr::CreateConvert(opcode); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_current_memory_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnCurrentMemoryExpr() { Expr* expr = Expr::CreateCurrentMemory(); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_drop_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnDropExpr() { Expr* expr = Expr::CreateDrop(); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_else_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnElseExpr() { LabelNode* label; - CHECK_RESULT(top_label(ctx, &label)); + CHECK_RESULT(TopLabel(&label)); if (label->label_type != LabelType::If) { - print_error(ctx, "else expression without matching if"); + PrintError("else expression without matching if"); return Result::Error; } LabelNode* parent_label; - CHECK_RESULT(get_label_at(ctx, &parent_label, 1)); + CHECK_RESULT(GetLabelAt(&parent_label, 1)); assert(parent_label->last->type == ExprType::If); label->label_type = LabelType::Else; @@ -529,196 +613,161 @@ static Result on_else_expr(void* user_data) { return Result::Ok; } -static Result on_end_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - return pop_label(ctx); +Result BinaryReaderAST::OnEndExpr() { + return PopLabel(); } -static Result on_f32_const_expr(uint32_t value_bits, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnF32ConstExpr(uint32_t value_bits) { Expr* expr = Expr::CreateConst(Const(Const::F32(), value_bits)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_f64_const_expr(uint64_t value_bits, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnF64ConstExpr(uint64_t value_bits) { Expr* expr = Expr::CreateConst(Const(Const::F64(), value_bits)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_get_global_expr(uint32_t global_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnGetGlobalExpr(uint32_t global_index) { Expr* expr = Expr::CreateGetGlobal(Var(global_index)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_get_local_expr(uint32_t local_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnGetLocalExpr(uint32_t local_index) { Expr* expr = Expr::CreateGetLocal(Var(local_index)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_grow_memory_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnGrowMemoryExpr() { Expr* expr = Expr::CreateGrowMemory(); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_i32_const_expr(uint32_t value, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnI32ConstExpr(uint32_t value) { Expr* expr = Expr::CreateConst(Const(Const::I32(), value)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_i64_const_expr(uint64_t value, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnI64ConstExpr(uint64_t value) { Expr* expr = Expr::CreateConst(Const(Const::I64(), value)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_if_expr(uint32_t num_types, Type* sig_types, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnIfExpr(uint32_t num_types, Type* sig_types) { Expr* expr = Expr::CreateIf(new Block()); expr->if_.true_->sig.assign(sig_types, sig_types + num_types); expr->if_.false_ = nullptr; - append_expr(ctx, expr); - push_label(ctx, LabelType::If, &expr->if_.true_->first); + AppendExpr(expr); + PushLabel(LabelType::If, &expr->if_.true_->first); return Result::Ok; } -static Result on_load_expr(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { Expr* expr = Expr::CreateLoad(opcode, 1 << alignment_log2, offset); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_loop_expr(uint32_t num_types, - Type* sig_types, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnLoopExpr(uint32_t num_types, Type* sig_types) { Expr* expr = Expr::CreateLoop(new Block()); expr->loop->sig.assign(sig_types, sig_types + num_types); - append_expr(ctx, expr); - push_label(ctx, LabelType::Loop, &expr->loop->first); + AppendExpr(expr); + PushLabel(LabelType::Loop, &expr->loop->first); return Result::Ok; } -static Result on_nop_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnNopExpr() { Expr* expr = Expr::CreateNop(); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_return_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnReturnExpr() { Expr* expr = Expr::CreateReturn(); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_select_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnSelectExpr() { Expr* expr = Expr::CreateSelect(); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_set_global_expr(uint32_t global_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnSetGlobalExpr(uint32_t global_index) { Expr* expr = Expr::CreateSetGlobal(Var(global_index)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_set_local_expr(uint32_t local_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnSetLocalExpr(uint32_t local_index) { Expr* expr = Expr::CreateSetLocal(Var(local_index)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_store_expr(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { Expr* expr = Expr::CreateStore(opcode, 1 << alignment_log2, offset); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_tee_local_expr(uint32_t local_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnTeeLocalExpr(uint32_t local_index) { Expr* expr = Expr::CreateTeeLocal(Var(local_index)); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_unary_expr(Opcode opcode, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnUnaryExpr(Opcode opcode) { Expr* expr = Expr::CreateUnary(opcode); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result on_unreachable_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderAST::OnUnreachableExpr() { Expr* expr = Expr::CreateUnreachable(); - return append_expr(ctx, expr); + return AppendExpr(expr); } -static Result end_function_body(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(pop_label(ctx)); - ctx->current_func = nullptr; +Result BinaryReaderAST::EndFunctionBody(uint32_t index) { + CHECK_RESULT(PopLabel()); + current_func = nullptr; return Result::Ok; } -static Result on_elem_segment_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->elem_segments.reserve(count); +Result BinaryReaderAST::OnElemSegmentCount(uint32_t count) { + module->elem_segments.reserve(count); return Result::Ok; } -static Result begin_elem_segment(uint32_t index, - uint32_t table_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::BeginElemSegment(uint32_t index, uint32_t table_index) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::ElemSegment; field->elem_segment = new ElemSegment(); field->elem_segment->table_var.type = VarType::Index; field->elem_segment->table_var.index = table_index; - ctx->module->elem_segments.push_back(field->elem_segment); + module->elem_segments.push_back(field->elem_segment); return Result::Ok; } -static Result begin_elem_segment_init_expr(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(index == ctx->module->elem_segments.size() - 1); - ElemSegment* segment = ctx->module->elem_segments[index]; - ctx->current_init_expr = &segment->offset; +Result BinaryReaderAST::BeginElemSegmentInitExpr(uint32_t index) { + assert(index == module->elem_segments.size() - 1); + ElemSegment* segment = module->elem_segments[index]; + current_init_expr = &segment->offset; return Result::Ok; } -static Result end_elem_segment_init_expr(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->current_init_expr = nullptr; +Result BinaryReaderAST::EndElemSegmentInitExpr(uint32_t index) { + current_init_expr = nullptr; return Result::Ok; } -static Result on_elem_segment_function_index_count(BinaryReaderContext* context, - uint32_t index, - uint32_t count) { - Context* ctx = static_cast<Context*>(context->user_data); - assert(index == ctx->module->elem_segments.size() - 1); - ElemSegment* segment = ctx->module->elem_segments[index]; +Result BinaryReaderAST::OnElemSegmentFunctionIndexCount(uint32_t index, + uint32_t count) { + assert(index == module->elem_segments.size() - 1); + ElemSegment* segment = module->elem_segments[index]; segment->vars.reserve(count); return Result::Ok; } -static Result on_elem_segment_function_index(uint32_t index, - uint32_t func_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(index == ctx->module->elem_segments.size() - 1); - ElemSegment* segment = ctx->module->elem_segments[index]; +Result BinaryReaderAST::OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index) { + assert(index == module->elem_segments.size() - 1); + ElemSegment* segment = module->elem_segments[index]; segment->vars.emplace_back(); Var* var = &segment->vars.back(); var->type = VarType::Index; @@ -726,142 +775,109 @@ static Result on_elem_segment_function_index(uint32_t index, return Result::Ok; } -static Result on_data_segment_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->data_segments.reserve(count); +Result BinaryReaderAST::OnDataSegmentCount(uint32_t count) { + module->data_segments.reserve(count); return Result::Ok; } -static Result begin_data_segment(uint32_t index, - uint32_t memory_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ModuleField* field = append_module_field(ctx->module); +Result BinaryReaderAST::BeginDataSegment(uint32_t index, + uint32_t memory_index) { + ModuleField* field = append_module_field(module); field->type = ModuleFieldType::DataSegment; field->data_segment = new DataSegment(); field->data_segment->memory_var.type = VarType::Index; field->data_segment->memory_var.index = memory_index; - ctx->module->data_segments.push_back(field->data_segment); + module->data_segments.push_back(field->data_segment); return Result::Ok; } -static Result begin_data_segment_init_expr(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(index == ctx->module->data_segments.size() - 1); - DataSegment* segment = ctx->module->data_segments[index]; - ctx->current_init_expr = &segment->offset; +Result BinaryReaderAST::BeginDataSegmentInitExpr(uint32_t index) { + assert(index == module->data_segments.size() - 1); + DataSegment* segment = module->data_segments[index]; + current_init_expr = &segment->offset; return Result::Ok; } -static Result end_data_segment_init_expr(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->current_init_expr = nullptr; +Result BinaryReaderAST::EndDataSegmentInitExpr(uint32_t index) { + current_init_expr = nullptr; return Result::Ok; } -static Result on_data_segment_data(uint32_t index, - const void* data, - uint32_t size, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(index == ctx->module->data_segments.size() - 1); - DataSegment* segment = ctx->module->data_segments[index]; +Result BinaryReaderAST::OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size) { + assert(index == module->data_segments.size() - 1); + DataSegment* segment = module->data_segments[index]; segment->data = new char[size]; segment->size = size; memcpy(segment->data, data, size); return Result::Ok; } -static Result on_function_names_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<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()); +Result BinaryReaderAST::OnFunctionNamesCount(uint32_t count) { + if (count > module->funcs.size()) { + PrintError("expected function name count (%u) <= function count (%" PRIzd + ")", + count, module->funcs.size()); return Result::Error; } return Result::Ok; } -static Result on_function_name(uint32_t index, - StringSlice name, - void* user_data) { +Result BinaryReaderAST::OnFunctionName(uint32_t index, StringSlice name) { if (string_slice_is_empty(&name)) return Result::Ok; - Context* ctx = static_cast<Context*>(user_data); - ctx->module->func_bindings.emplace(string_slice_to_string(name), - Binding(index)); - Func* func = ctx->module->funcs[index]; + module->func_bindings.emplace(string_slice_to_string(name), Binding(index)); + Func* func = module->funcs[index]; func->name = dup_string_slice(name); return Result::Ok; } -static Result on_local_name_local_count(uint32_t index, - uint32_t count, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - Module* module = ctx->module; +Result BinaryReaderAST::OnLocalNameLocalCount(uint32_t index, uint32_t count) { assert(index < module->funcs.size()); Func* func = module->funcs[index]; uint32_t num_params_and_locals = 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); + PrintError("expected local name count (%d) <= local count (%d)", count, + num_params_and_locals); return Result::Error; } return Result::Ok; } -static Result on_init_expr_f32_const_expr(uint32_t index, - uint32_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - *ctx->current_init_expr = Expr::CreateConst(Const(Const::F32(), value)); +Result BinaryReaderAST::OnInitExprF32ConstExpr(uint32_t index, uint32_t value) { + *current_init_expr = Expr::CreateConst(Const(Const::F32(), value)); return Result::Ok; } -static Result on_init_expr_f64_const_expr(uint32_t index, - uint64_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - *ctx->current_init_expr = Expr::CreateConst(Const(Const::F64(), value)); +Result BinaryReaderAST::OnInitExprF64ConstExpr(uint32_t index, uint64_t value) { + *current_init_expr = Expr::CreateConst(Const(Const::F64(), value)); return Result::Ok; } -static Result on_init_expr_get_global_expr(uint32_t index, - uint32_t global_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - *ctx->current_init_expr = Expr::CreateGetGlobal(Var(global_index)); +Result BinaryReaderAST::OnInitExprGetGlobalExpr(uint32_t index, + uint32_t global_index) { + *current_init_expr = Expr::CreateGetGlobal(Var(global_index)); return Result::Ok; } -static Result on_init_expr_i32_const_expr(uint32_t index, - uint32_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - *ctx->current_init_expr = Expr::CreateConst(Const(Const::I32(), value)); +Result BinaryReaderAST::OnInitExprI32ConstExpr(uint32_t index, uint32_t value) { + *current_init_expr = Expr::CreateConst(Const(Const::I32(), value)); return Result::Ok; } -static Result on_init_expr_i64_const_expr(uint32_t index, - uint64_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - *ctx->current_init_expr = Expr::CreateConst(Const(Const::I64(), value)); +Result BinaryReaderAST::OnInitExprI64ConstExpr(uint32_t index, uint64_t value) { + *current_init_expr = Expr::CreateConst(Const(Const::I64(), value)); return Result::Ok; } -static Result on_local_name(uint32_t func_index, - uint32_t local_index, - StringSlice name, - void* user_data) { +Result BinaryReaderAST::OnLocalName(uint32_t func_index, + uint32_t local_index, + StringSlice name) { if (string_slice_is_empty(&name)) return Result::Ok; - Context* ctx = static_cast<Context*>(user_data); - Module* module = ctx->module; Func* func = module->funcs[func_index]; uint32_t num_params = get_num_params(func); BindingHash* bindings; @@ -879,112 +895,15 @@ static Result on_local_name(uint32_t func_index, return Result::Ok; } +} // namespace + Result read_binary_ast(const void* data, size_t size, const ReadBinaryOptions* options, BinaryErrorHandler* error_handler, struct Module* out_module) { - Context ctx; - ctx.error_handler = error_handler; - ctx.module = out_module; - - BinaryReader 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_name_local_count = on_local_name_local_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; - - Result result = read_binary(data, size, &reader, 1, options); + BinaryReaderAST reader(out_module, error_handler); + Result result = read_binary(data, size, &reader, options); return result; } diff --git a/src/binary-reader-interpreter.cc b/src/binary-reader-interpreter.cc index b8948c0a..b22a4472 100644 --- a/src/binary-reader-interpreter.cc +++ b/src/binary-reader-interpreter.cc @@ -23,7 +23,7 @@ #include <vector> -#include "binary-reader.h" +#include "binary-reader-nop.h" #include "interpreter.h" #include "type-checker.h" #include "writer.h" @@ -34,27 +34,6 @@ return Result::Error; \ } while (0) -#define CHECK_LOCAL(ctx, local_index) \ - do { \ - uint32_t max_local_index = \ - (ctx)->current_func->param_and_local_types.size(); \ - if ((local_index) >= max_local_index) { \ - print_error((ctx), "invalid local_index: %d (max %d)", (local_index), \ - max_local_index); \ - return Result::Error; \ - } \ - } while (0) - -#define CHECK_GLOBAL(ctx, global_index) \ - do { \ - uint32_t max_global_index = (ctx)->global_index_mapping.size(); \ - if ((global_index) >= max_global_index) { \ - print_error((ctx), "invalid global_index: %d (max %d)", (global_index), \ - max_global_index); \ - return Result::Error; \ - } \ - } while (0) - namespace wabt { namespace { @@ -72,14 +51,219 @@ struct Label { Label::Label(uint32_t offset, uint32_t fixup_offset) : offset(offset), fixup_offset(fixup_offset) {} -struct Context { - Context(); +struct ElemSegmentInfo { + ElemSegmentInfo(uint32_t* dst, uint32_t func_index) + : dst(dst), func_index(func_index) {} + + uint32_t* dst; + uint32_t func_index; +}; + +struct DataSegmentInfo { + DataSegmentInfo(void* dst_data, const void* src_data, uint32_t size) + : dst_data(dst_data), src_data(src_data), size(size) {} + + void* dst_data; // Not owned. + const void* src_data; // Not owned. + uint32_t size; +}; + +class BinaryReaderInterpreter : public BinaryReaderNop { + public: + BinaryReaderInterpreter(InterpreterEnvironment* env, + DefinedInterpreterModule* module, + size_t istream_offset, + BinaryErrorHandler* error_handler); + + Result Init(); + void StealOutputBuffer(OutputBuffer*); + size_t get_istream_offset() { return istream_offset; } + + // Implement BinaryReader. + virtual bool OnError(const char* message); + + virtual Result EndModule(); + + virtual Result OnTypeCount(uint32_t count); + virtual Result OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types); + + virtual Result OnImportCount(uint32_t count); + virtual Result OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name); + virtual Result OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index); + virtual Result OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits); + virtual Result OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits); + virtual Result OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_); + + virtual Result OnFunctionCount(uint32_t count); + virtual Result OnFunction(uint32_t index, uint32_t sig_index); + + virtual Result OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits); + + virtual Result OnMemory(uint32_t index, const Limits* limits); + + virtual Result OnGlobalCount(uint32_t count); + virtual Result BeginGlobal(uint32_t index, Type type, bool mutable_); + virtual Result EndGlobalInitExpr(uint32_t index); + + virtual Result OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name); + + virtual Result OnStartFunction(uint32_t func_index); + + virtual Result BeginFunctionBody(uint32_t index); + virtual Result OnLocalDeclCount(uint32_t count); + virtual Result OnLocalDecl(uint32_t decl_index, uint32_t count, Type type); + + virtual Result OnBinaryExpr(Opcode opcode); + virtual Result OnBlockExpr(uint32_t num_types, Type* sig_types); + virtual Result OnBrExpr(uint32_t depth); + virtual Result OnBrIfExpr(uint32_t depth); + virtual Result OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth); + virtual Result OnCallExpr(uint32_t func_index); + virtual Result OnCallIndirectExpr(uint32_t sig_index); + virtual Result OnCompareExpr(Opcode opcode); + virtual Result OnConvertExpr(Opcode opcode); + virtual Result OnCurrentMemoryExpr(); + virtual Result OnDropExpr(); + virtual Result OnElseExpr(); + virtual Result OnEndExpr(); + virtual Result OnF32ConstExpr(uint32_t value_bits); + virtual Result OnF64ConstExpr(uint64_t value_bits); + virtual Result OnGetGlobalExpr(uint32_t global_index); + virtual Result OnGetLocalExpr(uint32_t local_index); + virtual Result OnGrowMemoryExpr(); + virtual Result OnI32ConstExpr(uint32_t value); + virtual Result OnI64ConstExpr(uint64_t value); + virtual Result OnIfExpr(uint32_t num_types, Type* sig_types); + virtual Result OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset); + virtual Result OnLoopExpr(uint32_t num_types, Type* sig_types); + virtual Result OnNopExpr(); + virtual Result OnReturnExpr(); + virtual Result OnSelectExpr(); + virtual Result OnSetGlobalExpr(uint32_t global_index); + virtual Result OnSetLocalExpr(uint32_t local_index); + virtual Result OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset); + virtual Result OnTeeLocalExpr(uint32_t local_index); + virtual Result OnUnaryExpr(Opcode opcode); + virtual Result OnUnreachableExpr(); + virtual Result EndFunctionBody(uint32_t index); + + virtual Result EndElemSegmentInitExpr(uint32_t index); + virtual Result OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index); + + virtual Result OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size); + + virtual Result OnInitExprF32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprF64ConstExpr(uint32_t index, uint64_t value); + virtual Result OnInitExprGetGlobalExpr(uint32_t index, uint32_t global_index); + virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprI64ConstExpr(uint32_t index, uint64_t value); + + private: + Label* GetLabel(uint32_t depth); + Label* TopLabel(); + void PushLabel(uint32_t offset, uint32_t fixup_offset); + void PopLabel(); + + bool HandleError(uint32_t offset, const char* message); + void PrintError(const char* format, ...); + static void OnTypecheckerError(const char* msg, void* user_data); + + uint32_t TranslateSigIndexToEnv(uint32_t sig_index); + InterpreterFuncSignature* GetSignatureByEnvIndex(uint32_t sig_index); + InterpreterFuncSignature* GetSignatureByModuleIndex(uint32_t sig_index); + uint32_t TranslateFuncIndexToEnv(uint32_t func_index); + uint32_t TranslateModuleFuncIndexToDefined(uint32_t func_index); + InterpreterFunc* GetFuncByEnvIndex(uint32_t func_index); + InterpreterFunc* GetFuncByModuleIndex(uint32_t func_index); + uint32_t TranslateGlobalIndexToEnv(uint32_t global_index); + InterpreterGlobal* GetGlobalByEnvIndex(uint32_t global_index); + InterpreterGlobal* GetGlobalByModuleIndex(uint32_t global_index); + Type GetGlobalTypeByModuleIndex(uint32_t global_index); + uint32_t TranslateLocalIndex(uint32_t local_index); + Type GetLocalTypeByIndex(InterpreterFunc* func, uint32_t local_index); + + uint32_t GetIstreamOffset(); + + Result EmitDataAt(size_t offset, const void* data, size_t size); + Result EmitData(const void* data, size_t size); + Result EmitOpcode(Opcode opcode); + Result EmitOpcode(InterpreterOpcode opcode); + Result EmitI8(uint8_t value); + Result EmitI32(uint32_t value); + Result EmitI64(uint64_t value); + Result EmitI32At(uint32_t offset, uint32_t value); + Result EmitDropKeep(uint32_t drop, uint8_t keep); + Result AppendFixup(Uint32VectorVector* fixups_vector, uint32_t index); + Result EmitBrOffset(uint32_t depth, uint32_t offset); + Result GetBrDropKeepCount(uint32_t depth, + uint32_t* out_drop_count, + uint32_t* out_keep_count); + Result GetReturnDropKeepCount(uint32_t* out_drop_count, + uint32_t* out_keep_count); + Result EmitBr(uint32_t depth, uint32_t drop_count, uint32_t keep_count); + Result EmitBrTableOffset(uint32_t depth); + Result FixupTopLabel(); + Result EmitFuncOffset(DefinedInterpreterFunc* func, uint32_t func_index); + + Result CheckLocal(uint32_t local_index); + Result CheckGlobal(uint32_t global_index); + Result CheckImportKind(InterpreterImport* import, ExternalKind expected_kind); + Result CheckImportLimits(const Limits* declared_limits, + const Limits* actual_limits); + Result CheckHasMemory(Opcode opcode); + Result CheckAlign(uint32_t alignment_log2, uint32_t natural_alignment); + + Result AppendExport(InterpreterModule* module, + ExternalKind kind, + uint32_t item_index, + StringSlice name); + + PrintErrorCallback MakePrintErrorCallback(); + static void OnHostImportPrintError(const char* msg, void* user_data); - BinaryReader* reader = nullptr; BinaryErrorHandler* error_handler = nullptr; InterpreterEnvironment* env = nullptr; DefinedInterpreterModule* module = nullptr; DefinedInterpreterFunc* current_func = nullptr; + TypeCheckerErrorHandler tc_error_handler; TypeChecker typechecker; std::vector<Label> label_stack; Uint32VectorVector func_fixups; @@ -95,7 +279,13 @@ struct Context { uint32_t num_func_imports = 0; uint32_t num_global_imports = 0; - /* values cached in the Context so they can be shared between callbacks */ + // Changes to linear memory and tables should not apply if a validation error + // occurs; these vectors cache the changes that must be applied after we know + // that there are no validation errors. + std::vector<ElemSegmentInfo> elem_segment_infos; + std::vector<DataSegmentInfo> data_segment_infos; + + /* values cached so they can be shared between callbacks */ InterpreterTypedValue init_expr_value; uint32_t table_offset = 0; bool is_host_import = false; @@ -103,282 +293,286 @@ struct Context { uint32_t import_env_index = 0; }; -Context::Context() { +BinaryReaderInterpreter::BinaryReaderInterpreter( + InterpreterEnvironment* env, + DefinedInterpreterModule* module, + size_t istream_offset, + BinaryErrorHandler* error_handler) + : error_handler(error_handler), + env(env), + module(module), + istream_offset(istream_offset) { WABT_ZERO_MEMORY(istream_writer); + + tc_error_handler.on_error = OnTypecheckerError; + tc_error_handler.user_data = this; + typechecker.error_handler = &tc_error_handler; } -} // namespace +Result BinaryReaderInterpreter::Init() { + return init_mem_writer_existing(&istream_writer, &env->istream); +} + +void BinaryReaderInterpreter::StealOutputBuffer(OutputBuffer* output_buffer) { + steal_mem_writer_output_buffer(&istream_writer, output_buffer); +} -static Label* get_label(Context* ctx, uint32_t depth) { - assert(depth < ctx->label_stack.size()); - return &ctx->label_stack[ctx->label_stack.size() - depth - 1]; +Label* BinaryReaderInterpreter::GetLabel(uint32_t depth) { + assert(depth < label_stack.size()); + return &label_stack[label_stack.size() - depth - 1]; } -static Label* top_label(Context* ctx) { - return get_label(ctx, 0); +Label* BinaryReaderInterpreter::TopLabel() { + return GetLabel(0); } -static bool handle_error(uint32_t offset, const char* message, Context* ctx) { - if (ctx->error_handler->on_error) { - return ctx->error_handler->on_error(offset, message, - ctx->error_handler->user_data); +bool BinaryReaderInterpreter::HandleError(uint32_t offset, + const char* message) { + if (error_handler->on_error) { + return error_handler->on_error(offset, message, error_handler->user_data); } return false; } -static void WABT_PRINTF_FORMAT(2, 3) - print_error(Context* ctx, const char* format, ...) { +void WABT_PRINTF_FORMAT(2, 3) + BinaryReaderInterpreter::PrintError(const char* format, ...) { WABT_SNPRINTF_ALLOCA(buffer, length, format); - handle_error(WABT_INVALID_OFFSET, buffer, ctx); + HandleError(WABT_INVALID_OFFSET, buffer); } -static void on_typechecker_error(const char* msg, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_error(ctx, "%s", msg); +// static +void BinaryReaderInterpreter::OnTypecheckerError(const char* msg, + void* user_data) { + static_cast<BinaryReaderInterpreter*>(user_data)->PrintError("%s", msg); } -static uint32_t translate_sig_index_to_env(Context* ctx, uint32_t sig_index) { - assert(sig_index < ctx->sig_index_mapping.size()); - return ctx->sig_index_mapping[sig_index]; +uint32_t BinaryReaderInterpreter::TranslateSigIndexToEnv(uint32_t sig_index) { + assert(sig_index < sig_index_mapping.size()); + return sig_index_mapping[sig_index]; } -static InterpreterFuncSignature* get_signature_by_env_index( - Context* ctx, +InterpreterFuncSignature* BinaryReaderInterpreter::GetSignatureByEnvIndex( uint32_t sig_index) { - return &ctx->env->sigs[sig_index]; + return &env->sigs[sig_index]; } -static InterpreterFuncSignature* get_signature_by_module_index( - Context* ctx, +InterpreterFuncSignature* BinaryReaderInterpreter::GetSignatureByModuleIndex( uint32_t sig_index) { - return get_signature_by_env_index(ctx, - translate_sig_index_to_env(ctx, sig_index)); + return GetSignatureByEnvIndex(TranslateSigIndexToEnv(sig_index)); } -static uint32_t translate_func_index_to_env(Context* ctx, uint32_t func_index) { - assert(func_index < ctx->func_index_mapping.size()); - return ctx->func_index_mapping[func_index]; +uint32_t BinaryReaderInterpreter::TranslateFuncIndexToEnv(uint32_t func_index) { + assert(func_index < func_index_mapping.size()); + return func_index_mapping[func_index]; } -static uint32_t translate_module_func_index_to_defined(Context* ctx, - uint32_t func_index) { - assert(func_index >= ctx->num_func_imports); - return func_index - ctx->num_func_imports; +uint32_t BinaryReaderInterpreter::TranslateModuleFuncIndexToDefined( + uint32_t func_index) { + assert(func_index >= num_func_imports); + return func_index - num_func_imports; } -static InterpreterFunc* get_func_by_env_index(Context* ctx, - uint32_t func_index) { - return ctx->env->funcs[func_index].get(); +InterpreterFunc* BinaryReaderInterpreter::GetFuncByEnvIndex( + uint32_t func_index) { + return env->funcs[func_index].get(); } -static InterpreterFunc* get_func_by_module_index(Context* ctx, - uint32_t func_index) { - return get_func_by_env_index(ctx, - translate_func_index_to_env(ctx, func_index)); +InterpreterFunc* BinaryReaderInterpreter::GetFuncByModuleIndex( + uint32_t func_index) { + return GetFuncByEnvIndex(TranslateFuncIndexToEnv(func_index)); } -static uint32_t translate_global_index_to_env(Context* ctx, - uint32_t global_index) { - return ctx->global_index_mapping[global_index]; +uint32_t BinaryReaderInterpreter::TranslateGlobalIndexToEnv( + uint32_t global_index) { + return global_index_mapping[global_index]; } -static InterpreterGlobal* get_global_by_env_index(Context* ctx, - uint32_t global_index) { - return &ctx->env->globals[global_index]; +InterpreterGlobal* BinaryReaderInterpreter::GetGlobalByEnvIndex( + uint32_t global_index) { + return &env->globals[global_index]; } -static InterpreterGlobal* get_global_by_module_index(Context* ctx, - uint32_t global_index) { - return get_global_by_env_index( - ctx, translate_global_index_to_env(ctx, global_index)); +InterpreterGlobal* BinaryReaderInterpreter::GetGlobalByModuleIndex( + uint32_t global_index) { + return GetGlobalByEnvIndex(TranslateGlobalIndexToEnv(global_index)); } -static Type get_global_type_by_module_index(Context* ctx, - uint32_t global_index) { - return get_global_by_module_index(ctx, global_index)->typed_value.type; +Type BinaryReaderInterpreter::GetGlobalTypeByModuleIndex( + uint32_t global_index) { + return GetGlobalByModuleIndex(global_index)->typed_value.type; } -static Type get_local_type_by_index(InterpreterFunc* func, - uint32_t local_index) { +Type BinaryReaderInterpreter::GetLocalTypeByIndex(InterpreterFunc* func, + uint32_t local_index) { assert(!func->is_host); return func->as_defined()->param_and_local_types[local_index]; } -static uint32_t get_istream_offset(Context* ctx) { - return ctx->istream_offset; +uint32_t BinaryReaderInterpreter::GetIstreamOffset() { + return istream_offset; } -static Result emit_data_at(Context* ctx, - size_t offset, - const void* data, - size_t size) { - return ctx->istream_writer.base.write_data( - offset, data, size, ctx->istream_writer.base.user_data); +Result BinaryReaderInterpreter::EmitDataAt(size_t offset, + const void* data, + size_t size) { + return istream_writer.base.write_data(offset, data, size, + istream_writer.base.user_data); } -static Result emit_data(Context* ctx, const void* data, size_t size) { - CHECK_RESULT(emit_data_at(ctx, ctx->istream_offset, data, size)); - ctx->istream_offset += size; +Result BinaryReaderInterpreter::EmitData(const void* data, size_t size) { + CHECK_RESULT(EmitDataAt(istream_offset, data, size)); + istream_offset += size; return Result::Ok; } -static Result emit_opcode(Context* ctx, Opcode opcode) { - return emit_data(ctx, &opcode, sizeof(uint8_t)); +Result BinaryReaderInterpreter::EmitOpcode(Opcode opcode) { + return EmitData(&opcode, sizeof(uint8_t)); } -static Result emit_opcode(Context* ctx, InterpreterOpcode opcode) { - return emit_data(ctx, &opcode, sizeof(uint8_t)); +Result BinaryReaderInterpreter::EmitOpcode(InterpreterOpcode opcode) { + return EmitData(&opcode, sizeof(uint8_t)); } -static Result emit_i8(Context* ctx, uint8_t value) { - return emit_data(ctx, &value, sizeof(value)); +Result BinaryReaderInterpreter::EmitI8(uint8_t value) { + return EmitData(&value, sizeof(value)); } -static Result emit_i32(Context* ctx, uint32_t value) { - return emit_data(ctx, &value, sizeof(value)); +Result BinaryReaderInterpreter::EmitI32(uint32_t value) { + return EmitData(&value, sizeof(value)); } -static Result emit_i64(Context* ctx, uint64_t value) { - return emit_data(ctx, &value, sizeof(value)); +Result BinaryReaderInterpreter::EmitI64(uint64_t value) { + return EmitData(&value, sizeof(value)); } -static Result emit_i32_at(Context* ctx, uint32_t offset, uint32_t value) { - return emit_data_at(ctx, offset, &value, sizeof(value)); +Result BinaryReaderInterpreter::EmitI32At(uint32_t offset, uint32_t value) { + return EmitDataAt(offset, &value, sizeof(value)); } -static Result emit_drop_keep(Context* ctx, uint32_t drop, uint8_t keep) { +Result BinaryReaderInterpreter::EmitDropKeep(uint32_t drop, uint8_t keep) { assert(drop != UINT32_MAX); assert(keep <= 1); if (drop > 0) { if (drop == 1 && keep == 0) { - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Drop)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Drop)); } else { - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::DropKeep)); - CHECK_RESULT(emit_i32(ctx, drop)); - CHECK_RESULT(emit_i8(ctx, keep)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::DropKeep)); + CHECK_RESULT(EmitI32(drop)); + CHECK_RESULT(EmitI8(keep)); } } return Result::Ok; } -static Result append_fixup(Context* ctx, - Uint32VectorVector* fixups_vector, - uint32_t index) { +Result BinaryReaderInterpreter::AppendFixup(Uint32VectorVector* fixups_vector, + uint32_t index) { if (index >= fixups_vector->size()) fixups_vector->resize(index + 1); - (*fixups_vector)[index].push_back(get_istream_offset(ctx)); + (*fixups_vector)[index].push_back(GetIstreamOffset()); return Result::Ok; } -static Result emit_br_offset(Context* ctx, uint32_t depth, uint32_t offset) { +Result BinaryReaderInterpreter::EmitBrOffset(uint32_t depth, uint32_t offset) { if (offset == WABT_INVALID_OFFSET) { /* depth_fixups stores the depth counting up from zero, where zero is the * top-level function scope. */ - depth = ctx->label_stack.size() - 1 - depth; - CHECK_RESULT(append_fixup(ctx, &ctx->depth_fixups, depth)); + depth = label_stack.size() - 1 - depth; + CHECK_RESULT(AppendFixup(&depth_fixups, depth)); } - CHECK_RESULT(emit_i32(ctx, offset)); + CHECK_RESULT(EmitI32(offset)); return Result::Ok; } -static Result get_br_drop_keep_count(Context* ctx, - uint32_t depth, - uint32_t* out_drop_count, - uint32_t* out_keep_count) { +Result BinaryReaderInterpreter::GetBrDropKeepCount(uint32_t depth, + uint32_t* out_drop_count, + uint32_t* out_keep_count) { TypeCheckerLabel* label; - CHECK_RESULT(typechecker_get_label(&ctx->typechecker, depth, &label)); + CHECK_RESULT(typechecker_get_label(&typechecker, depth, &label)); *out_keep_count = label->label_type != LabelType::Loop ? label->sig.size() : 0; - if (typechecker_is_unreachable(&ctx->typechecker)) { + if (typechecker_is_unreachable(&typechecker)) { *out_drop_count = 0; } else { *out_drop_count = - (ctx->typechecker.type_stack.size() - label->type_stack_limit) - + (typechecker.type_stack.size() - label->type_stack_limit) - *out_keep_count; } return Result::Ok; } -static Result get_return_drop_keep_count(Context* ctx, - uint32_t* out_drop_count, - uint32_t* out_keep_count) { - if (WABT_FAILED(get_br_drop_keep_count(ctx, ctx->label_stack.size() - 1, - out_drop_count, out_keep_count))) { +Result BinaryReaderInterpreter::GetReturnDropKeepCount( + uint32_t* out_drop_count, + uint32_t* out_keep_count) { + if (WABT_FAILED(GetBrDropKeepCount(label_stack.size() - 1, out_drop_count, + out_keep_count))) { return Result::Error; } - *out_drop_count += ctx->current_func->param_and_local_types.size(); + *out_drop_count += current_func->param_and_local_types.size(); return Result::Ok; } -static Result emit_br(Context* ctx, - uint32_t depth, - uint32_t drop_count, - uint32_t keep_count) { - CHECK_RESULT(emit_drop_keep(ctx, drop_count, keep_count)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Br)); - CHECK_RESULT(emit_br_offset(ctx, depth, get_label(ctx, depth)->offset)); +Result BinaryReaderInterpreter::EmitBr(uint32_t depth, + uint32_t drop_count, + uint32_t keep_count) { + CHECK_RESULT(EmitDropKeep(drop_count, keep_count)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Br)); + CHECK_RESULT(EmitBrOffset(depth, GetLabel(depth)->offset)); return Result::Ok; } -static Result emit_br_table_offset(Context* ctx, uint32_t depth) { +Result BinaryReaderInterpreter::EmitBrTableOffset(uint32_t depth) { uint32_t drop_count, keep_count; - CHECK_RESULT(get_br_drop_keep_count(ctx, depth, &drop_count, &keep_count)); - CHECK_RESULT(emit_br_offset(ctx, depth, get_label(ctx, depth)->offset)); - CHECK_RESULT(emit_i32(ctx, drop_count)); - CHECK_RESULT(emit_i8(ctx, keep_count)); + CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count)); + CHECK_RESULT(EmitBrOffset(depth, GetLabel(depth)->offset)); + CHECK_RESULT(EmitI32(drop_count)); + CHECK_RESULT(EmitI8(keep_count)); return Result::Ok; } -static Result fixup_top_label(Context* ctx) { - uint32_t offset = get_istream_offset(ctx); - uint32_t top = ctx->label_stack.size() - 1; - if (top >= ctx->depth_fixups.size()) { +Result BinaryReaderInterpreter::FixupTopLabel() { + uint32_t offset = GetIstreamOffset(); + uint32_t top = label_stack.size() - 1; + if (top >= depth_fixups.size()) { /* nothing to fixup */ return Result::Ok; } - Uint32Vector& fixups = ctx->depth_fixups[top]; - for (uint32_t fixup: fixups) - CHECK_RESULT(emit_i32_at(ctx, fixup, offset)); + Uint32Vector& fixups = depth_fixups[top]; + for (uint32_t fixup : fixups) + CHECK_RESULT(EmitI32At(fixup, offset)); fixups.clear(); return Result::Ok; } -static Result emit_func_offset(Context* ctx, - DefinedInterpreterFunc* func, - uint32_t func_index) { +Result BinaryReaderInterpreter::EmitFuncOffset(DefinedInterpreterFunc* func, + uint32_t func_index) { if (func->offset == WABT_INVALID_OFFSET) { - uint32_t defined_index = - translate_module_func_index_to_defined(ctx, func_index); - CHECK_RESULT(append_fixup(ctx, &ctx->func_fixups, defined_index)); + uint32_t defined_index = TranslateModuleFuncIndexToDefined(func_index); + CHECK_RESULT(AppendFixup(&func_fixups, defined_index)); } - CHECK_RESULT(emit_i32(ctx, func->offset)); + CHECK_RESULT(EmitI32(func->offset)); return Result::Ok; } -static bool on_error(BinaryReaderContext* ctx, const char* message) { - return handle_error(ctx->offset, message, - static_cast<Context*>(ctx->user_data)); +bool BinaryReaderInterpreter::OnError(const char* message) { + return HandleError(state->offset, message); } -static Result on_signature_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->sig_index_mapping.resize(count); +Result BinaryReaderInterpreter::OnTypeCount(uint32_t count) { + sig_index_mapping.resize(count); for (uint32_t i = 0; i < count; ++i) - ctx->sig_index_mapping[i] = ctx->env->sigs.size() + i; - ctx->env->sigs.resize(ctx->env->sigs.size() + count); + sig_index_mapping[i] = env->sigs.size() + i; + env->sigs.resize(env->sigs.size() + count); return Result::Ok; } -static Result on_signature(uint32_t index, - uint32_t param_count, - Type* param_types, - uint32_t result_count, - Type* result_types, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - InterpreterFuncSignature* sig = get_signature_by_module_index(ctx, index); +Result BinaryReaderInterpreter::OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types) { + InterpreterFuncSignature* sig = GetSignatureByModuleIndex(index); sig->param_types.insert(sig->param_types.end(), param_types, param_types + param_count); sig->result_types.insert(sig->result_types.end(), result_types, @@ -386,85 +580,97 @@ static Result on_signature(uint32_t index, return Result::Ok; } -static Result on_import_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->module->imports.resize(count); +Result BinaryReaderInterpreter::OnImportCount(uint32_t count) { + module->imports.resize(count); return Result::Ok; } -static Result on_import(uint32_t index, - StringSlice module_name, - StringSlice field_name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - InterpreterImport* import = &ctx->module->imports[index]; +Result BinaryReaderInterpreter::OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name) { + InterpreterImport* import = &module->imports[index]; import->module_name = dup_string_slice(module_name); import->field_name = dup_string_slice(field_name); int module_index = - ctx->env->registered_module_bindings.find_index(import->module_name); + env->registered_module_bindings.find_index(import->module_name); if (module_index < 0) { - print_error(ctx, "unknown import module \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(import->module_name)); + PrintError("unknown import module \"" PRIstringslice "\"", + WABT_PRINTF_STRING_SLICE_ARG(import->module_name)); return Result::Error; } - InterpreterModule* module = ctx->env->modules[module_index].get(); + InterpreterModule* module = env->modules[module_index].get(); if (module->is_host) { /* We don't yet know the kind of a host import module, so just assume it * exists for now. We'll fail later (in on_import_* below) if it doesn't * exist). */ - ctx->is_host_import = true; - ctx->host_import_module = module->as_host(); + is_host_import = true; + host_import_module = module->as_host(); } else { InterpreterExport* export_ = get_interpreter_export_by_name(module, &import->field_name); if (!export_) { - print_error(ctx, "unknown module field \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(import->field_name)); + PrintError("unknown module field \"" PRIstringslice "\"", + WABT_PRINTF_STRING_SLICE_ARG(import->field_name)); return Result::Error; } import->kind = export_->kind; - ctx->is_host_import = false; - ctx->import_env_index = export_->index; + is_host_import = false; + import_env_index = export_->index; + } + return Result::Ok; +} + +Result BinaryReaderInterpreter::CheckLocal(uint32_t local_index) { + uint32_t max_local_index = current_func->param_and_local_types.size(); + if (local_index >= max_local_index) { + PrintError("invalid local_index: %d (max %d)", local_index, + max_local_index); + return Result::Error; + } + return Result::Ok; +} + +Result BinaryReaderInterpreter::CheckGlobal(uint32_t global_index) { + uint32_t max_global_index = global_index_mapping.size(); + if (global_index >= max_global_index) { + PrintError("invalid global_index: %d (max %d)", global_index, + max_global_index); + return Result::Error; } return Result::Ok; } -static Result check_import_kind(Context* ctx, - InterpreterImport* import, - ExternalKind expected_kind) { +Result BinaryReaderInterpreter::CheckImportKind(InterpreterImport* import, + ExternalKind expected_kind) { if (import->kind != expected_kind) { - print_error(ctx, "expected import \"" PRIstringslice "." PRIstringslice - "\" to have kind %s, not %s", - WABT_PRINTF_STRING_SLICE_ARG(import->module_name), - WABT_PRINTF_STRING_SLICE_ARG(import->field_name), - get_kind_name(expected_kind), get_kind_name(import->kind)); + PrintError("expected import \"" PRIstringslice "." PRIstringslice + "\" to have kind %s, not %s", + WABT_PRINTF_STRING_SLICE_ARG(import->module_name), + WABT_PRINTF_STRING_SLICE_ARG(import->field_name), + get_kind_name(expected_kind), get_kind_name(import->kind)); return Result::Error; } return Result::Ok; } -static Result check_import_limits(Context* ctx, - const Limits* declared_limits, - const Limits* actual_limits) { +Result BinaryReaderInterpreter::CheckImportLimits(const Limits* declared_limits, + const Limits* actual_limits) { if (actual_limits->initial < declared_limits->initial) { - print_error(ctx, - "actual size (%" PRIu64 ") smaller than declared (%" PRIu64 ")", - actual_limits->initial, declared_limits->initial); + PrintError("actual size (%" PRIu64 ") smaller than declared (%" PRIu64 ")", + actual_limits->initial, declared_limits->initial); return Result::Error; } if (declared_limits->has_max) { if (!actual_limits->has_max) { - print_error(ctx, - "max size (unspecified) larger than declared (%" PRIu64 ")", - declared_limits->max); + PrintError("max size (unspecified) larger than declared (%" PRIu64 ")", + declared_limits->max); return Result::Error; } else if (actual_limits->max > declared_limits->max) { - print_error(ctx, - "max size (%" PRIu64 ") larger than declared (%" PRIu64 ")", - actual_limits->max, declared_limits->max); + PrintError("max size (%" PRIu64 ") larger than declared (%" PRIu64 ")", + actual_limits->max, declared_limits->max); return Result::Error; } } @@ -472,14 +678,13 @@ static Result check_import_limits(Context* ctx, return Result::Ok; } -static Result append_export(Context* ctx, - InterpreterModule* module, - ExternalKind kind, - uint32_t item_index, - StringSlice name) { +Result BinaryReaderInterpreter::AppendExport(InterpreterModule* module, + ExternalKind kind, + uint32_t item_index, + StringSlice name) { if (module->export_bindings.find_index(name) != -1) { - print_error(ctx, "duplicate export \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(name)); + PrintError("duplicate export \"" PRIstringslice "\"", + WABT_PRINTF_STRING_SLICE_ARG(name)); return Result::Error; } @@ -491,1016 +696,820 @@ static Result append_export(Context* ctx, return Result::Ok; } -static void on_host_import_print_error(const char* msg, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_error(ctx, "%s", msg); +// static +void BinaryReaderInterpreter::OnHostImportPrintError(const char* msg, + void* user_data) { + static_cast<BinaryReaderInterpreter*>(user_data)->PrintError("%s", msg); } -static PrintErrorCallback make_print_error_callback(Context* ctx) { +PrintErrorCallback BinaryReaderInterpreter::MakePrintErrorCallback() { PrintErrorCallback result; - result.print_error = on_host_import_print_error; - result.user_data = ctx; + result.print_error = OnHostImportPrintError; + result.user_data = this; return result; } -static Result on_import_func(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t func_index, - uint32_t sig_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - InterpreterImport* import = &ctx->module->imports[import_index]; - import->func.sig_index = translate_sig_index_to_env(ctx, sig_index); +Result BinaryReaderInterpreter::OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index) { + InterpreterImport* import = &module->imports[import_index]; + import->func.sig_index = TranslateSigIndexToEnv(sig_index); uint32_t func_env_index; - if (ctx->is_host_import) { + if (is_host_import) { HostInterpreterFunc* func = new HostInterpreterFunc( import->module_name, import->field_name, import->func.sig_index); - ctx->env->funcs.emplace_back(func); + env->funcs.emplace_back(func); InterpreterHostImportDelegate* host_delegate = - &ctx->host_import_module->import_delegate; - InterpreterFuncSignature* sig = &ctx->env->sigs[func->sig_index]; - CHECK_RESULT(host_delegate->import_func(import, func, sig, - make_print_error_callback(ctx), - host_delegate->user_data)); + &host_import_module->import_delegate; + InterpreterFuncSignature* sig = &env->sigs[func->sig_index]; + CHECK_RESULT(host_delegate->import_func( + import, func, sig, MakePrintErrorCallback(), host_delegate->user_data)); assert(func->callback); - func_env_index = ctx->env->funcs.size() - 1; - append_export(ctx, ctx->host_import_module, ExternalKind::Func, - func_env_index, import->field_name); + func_env_index = env->funcs.size() - 1; + AppendExport(host_import_module, ExternalKind::Func, func_env_index, + import->field_name); } else { - CHECK_RESULT(check_import_kind(ctx, import, ExternalKind::Func)); - InterpreterFunc* func = ctx->env->funcs[ctx->import_env_index].get(); - if (!func_signatures_are_equal(ctx->env, import->func.sig_index, + CHECK_RESULT(CheckImportKind(import, ExternalKind::Func)); + InterpreterFunc* func = env->funcs[import_env_index].get(); + if (!func_signatures_are_equal(env, import->func.sig_index, func->sig_index)) { - print_error(ctx, "import signature mismatch"); + PrintError("import signature mismatch"); return Result::Error; } - func_env_index = ctx->import_env_index; + func_env_index = import_env_index; } - ctx->func_index_mapping.push_back(func_env_index); - ctx->num_func_imports++; + func_index_mapping.push_back(func_env_index); + num_func_imports++; return Result::Ok; } -static Result on_import_table(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t table_index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->module->table_index != WABT_INVALID_INDEX) { - print_error(ctx, "only one table allowed"); +Result BinaryReaderInterpreter::OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits) { + if (module->table_index != WABT_INVALID_INDEX) { + PrintError("only one table allowed"); return Result::Error; } - InterpreterImport* import = &ctx->module->imports[import_index]; + InterpreterImport* import = &module->imports[import_index]; - if (ctx->is_host_import) { - ctx->env->tables.emplace_back(*elem_limits); - InterpreterTable* table = &ctx->env->tables.back(); + if (is_host_import) { + env->tables.emplace_back(*elem_limits); + InterpreterTable* table = &env->tables.back(); InterpreterHostImportDelegate* host_delegate = - &ctx->host_import_module->import_delegate; - CHECK_RESULT(host_delegate->import_table(import, table, - make_print_error_callback(ctx), - host_delegate->user_data)); + &host_import_module->import_delegate; + CHECK_RESULT(host_delegate->import_table( + import, table, MakePrintErrorCallback(), host_delegate->user_data)); - CHECK_RESULT(check_import_limits(ctx, elem_limits, &table->limits)); + CHECK_RESULT(CheckImportLimits(elem_limits, &table->limits)); - ctx->module->table_index = ctx->env->tables.size() - 1; - append_export(ctx, ctx->host_import_module, ExternalKind::Table, - ctx->module->table_index, import->field_name); + module->table_index = env->tables.size() - 1; + AppendExport(host_import_module, ExternalKind::Table, module->table_index, + import->field_name); } else { - CHECK_RESULT(check_import_kind(ctx, import, ExternalKind::Table)); - InterpreterTable* table = &ctx->env->tables[ctx->import_env_index]; - CHECK_RESULT(check_import_limits(ctx, elem_limits, &table->limits)); + CHECK_RESULT(CheckImportKind(import, ExternalKind::Table)); + InterpreterTable* table = &env->tables[import_env_index]; + CHECK_RESULT(CheckImportLimits(elem_limits, &table->limits)); import->table.limits = *elem_limits; - ctx->module->table_index = ctx->import_env_index; + module->table_index = import_env_index; } return Result::Ok; } -static Result on_import_memory(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t memory_index, - const Limits* page_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->module->memory_index != WABT_INVALID_INDEX) { - print_error(ctx, "only one memory allowed"); +Result BinaryReaderInterpreter::OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits) { + if (module->memory_index != WABT_INVALID_INDEX) { + PrintError("only one memory allowed"); return Result::Error; } - InterpreterImport* import = &ctx->module->imports[import_index]; + InterpreterImport* import = &module->imports[import_index]; - if (ctx->is_host_import) { - ctx->env->memories.emplace_back(); - InterpreterMemory* memory = &ctx->env->memories.back(); + if (is_host_import) { + env->memories.emplace_back(); + InterpreterMemory* memory = &env->memories.back(); InterpreterHostImportDelegate* host_delegate = - &ctx->host_import_module->import_delegate; - CHECK_RESULT(host_delegate->import_memory(import, memory, - make_print_error_callback(ctx), - host_delegate->user_data)); + &host_import_module->import_delegate; + CHECK_RESULT(host_delegate->import_memory( + import, memory, MakePrintErrorCallback(), host_delegate->user_data)); - CHECK_RESULT(check_import_limits(ctx, page_limits, &memory->page_limits)); + CHECK_RESULT(CheckImportLimits(page_limits, &memory->page_limits)); - ctx->module->memory_index = ctx->env->memories.size() - 1; - append_export(ctx, ctx->host_import_module, ExternalKind::Memory, - ctx->module->memory_index, import->field_name); + module->memory_index = env->memories.size() - 1; + AppendExport(host_import_module, ExternalKind::Memory, module->memory_index, + import->field_name); } else { - CHECK_RESULT(check_import_kind(ctx, import, ExternalKind::Memory)); - InterpreterMemory* memory = &ctx->env->memories[ctx->import_env_index]; - CHECK_RESULT(check_import_limits(ctx, page_limits, &memory->page_limits)); + CHECK_RESULT(CheckImportKind(import, ExternalKind::Memory)); + InterpreterMemory* memory = &env->memories[import_env_index]; + CHECK_RESULT(CheckImportLimits(page_limits, &memory->page_limits)); import->memory.limits = *page_limits; - ctx->module->memory_index = ctx->import_env_index; + module->memory_index = import_env_index; } return Result::Ok; } -static Result on_import_global(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t global_index, - Type type, - bool mutable_, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - InterpreterImport* import = &ctx->module->imports[import_index]; - - uint32_t global_env_index = ctx->env->globals.size() - 1; - if (ctx->is_host_import) { - ctx->env->globals.emplace_back(InterpreterTypedValue(type), mutable_); - InterpreterGlobal* global = &ctx->env->globals.back(); +Result BinaryReaderInterpreter::OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_) { + InterpreterImport* import = &module->imports[import_index]; + + uint32_t global_env_index = env->globals.size() - 1; + if (is_host_import) { + env->globals.emplace_back(InterpreterTypedValue(type), mutable_); + InterpreterGlobal* global = &env->globals.back(); InterpreterHostImportDelegate* host_delegate = - &ctx->host_import_module->import_delegate; - CHECK_RESULT(host_delegate->import_global(import, global, - make_print_error_callback(ctx), - host_delegate->user_data)); - - global_env_index = ctx->env->globals.size() - 1; - append_export(ctx, ctx->host_import_module, ExternalKind::Global, - global_env_index, import->field_name); + &host_import_module->import_delegate; + CHECK_RESULT(host_delegate->import_global( + import, global, MakePrintErrorCallback(), host_delegate->user_data)); + + global_env_index = env->globals.size() - 1; + AppendExport(host_import_module, ExternalKind::Global, global_env_index, + import->field_name); } else { - CHECK_RESULT(check_import_kind(ctx, import, ExternalKind::Global)); + CHECK_RESULT(CheckImportKind(import, ExternalKind::Global)); // TODO: check type and mutability import->global.type = type; import->global.mutable_ = mutable_; - global_env_index = ctx->import_env_index; + global_env_index = import_env_index; } - ctx->global_index_mapping.push_back(global_env_index); - ctx->num_global_imports++; + global_index_mapping.push_back(global_env_index); + num_global_imports++; return Result::Ok; } -static Result on_function_signatures_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnFunctionCount(uint32_t count) { for (uint32_t i = 0; i < count; ++i) - ctx->func_index_mapping.push_back(ctx->env->funcs.size() + i); - ctx->env->funcs.reserve(ctx->env->funcs.size() + count); - ctx->func_fixups.resize(count); + func_index_mapping.push_back(env->funcs.size() + i); + env->funcs.reserve(env->funcs.size() + count); + func_fixups.resize(count); return Result::Ok; } -static Result on_function_signature(uint32_t index, - uint32_t sig_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnFunction(uint32_t index, uint32_t sig_index) { DefinedInterpreterFunc* func = - new DefinedInterpreterFunc(translate_sig_index_to_env(ctx, sig_index)); - ctx->env->funcs.emplace_back(func); + new DefinedInterpreterFunc(TranslateSigIndexToEnv(sig_index)); + env->funcs.emplace_back(func); return Result::Ok; } -static Result on_table(uint32_t index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->module->table_index != WABT_INVALID_INDEX) { - print_error(ctx, "only one table allowed"); +Result BinaryReaderInterpreter::OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits) { + if (module->table_index != WABT_INVALID_INDEX) { + PrintError("only one table allowed"); return Result::Error; } - ctx->env->tables.emplace_back(*elem_limits); - ctx->module->table_index = ctx->env->tables.size() - 1; + env->tables.emplace_back(*elem_limits); + module->table_index = env->tables.size() - 1; return Result::Ok; } -static Result on_memory(uint32_t index, - const Limits* page_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->module->memory_index != WABT_INVALID_INDEX) { - print_error(ctx, "only one memory allowed"); +Result BinaryReaderInterpreter::OnMemory(uint32_t index, + const Limits* page_limits) { + if (module->memory_index != WABT_INVALID_INDEX) { + PrintError("only one memory allowed"); return Result::Error; } - ctx->env->memories.emplace_back(*page_limits); - ctx->module->memory_index = ctx->env->memories.size() - 1; + env->memories.emplace_back(*page_limits); + module->memory_index = env->memories.size() - 1; return Result::Ok; } -static Result on_global_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnGlobalCount(uint32_t count) { for (uint32_t i = 0; i < count; ++i) - ctx->global_index_mapping.push_back(ctx->env->globals.size() + i); - ctx->env->globals.resize(ctx->env->globals.size() + count); + global_index_mapping.push_back(env->globals.size() + i); + env->globals.resize(env->globals.size() + count); return Result::Ok; } -static Result begin_global(uint32_t index, - Type type, - bool mutable_, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - InterpreterGlobal* global = get_global_by_module_index(ctx, index); +Result BinaryReaderInterpreter::BeginGlobal(uint32_t index, + Type type, + bool mutable_) { + InterpreterGlobal* global = GetGlobalByModuleIndex(index); global->typed_value.type = type; global->mutable_ = mutable_; return Result::Ok; } -static Result end_global_init_expr(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - InterpreterGlobal* global = get_global_by_module_index(ctx, index); - if (ctx->init_expr_value.type != global->typed_value.type) { - print_error(ctx, "type mismatch in global, expected %s but got %s.", - get_type_name(global->typed_value.type), - get_type_name(ctx->init_expr_value.type)); +Result BinaryReaderInterpreter::EndGlobalInitExpr(uint32_t index) { + InterpreterGlobal* global = GetGlobalByModuleIndex(index); + if (init_expr_value.type != global->typed_value.type) { + PrintError("type mismatch in global, expected %s but got %s.", + get_type_name(global->typed_value.type), + get_type_name(init_expr_value.type)); return Result::Error; } - global->typed_value = ctx->init_expr_value; + global->typed_value = init_expr_value; return Result::Ok; } -static Result on_init_expr_f32_const_expr(uint32_t index, - uint32_t value_bits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->init_expr_value.type = Type::F32; - ctx->init_expr_value.value.f32_bits = value_bits; +Result BinaryReaderInterpreter::OnInitExprF32ConstExpr(uint32_t index, + uint32_t value_bits) { + init_expr_value.type = Type::F32; + init_expr_value.value.f32_bits = value_bits; return Result::Ok; } -static Result on_init_expr_f64_const_expr(uint32_t index, - uint64_t value_bits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->init_expr_value.type = Type::F64; - ctx->init_expr_value.value.f64_bits = value_bits; +Result BinaryReaderInterpreter::OnInitExprF64ConstExpr(uint32_t index, + uint64_t value_bits) { + init_expr_value.type = Type::F64; + init_expr_value.value.f64_bits = value_bits; return Result::Ok; } -static Result on_init_expr_get_global_expr(uint32_t index, - uint32_t global_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (global_index >= ctx->num_global_imports) { - print_error(ctx, - "initializer expression can only reference an imported global"); +Result BinaryReaderInterpreter::OnInitExprGetGlobalExpr(uint32_t index, + uint32_t global_index) { + if (global_index >= num_global_imports) { + PrintError("initializer expression can only reference an imported global"); return Result::Error; } - InterpreterGlobal* ref_global = get_global_by_module_index(ctx, global_index); + InterpreterGlobal* ref_global = GetGlobalByModuleIndex(global_index); if (ref_global->mutable_) { - print_error(ctx, - "initializer expression cannot reference a mutable global"); + PrintError("initializer expression cannot reference a mutable global"); return Result::Error; } - ctx->init_expr_value = ref_global->typed_value; + init_expr_value = ref_global->typed_value; return Result::Ok; } -static Result on_init_expr_i32_const_expr(uint32_t index, - uint32_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->init_expr_value.type = Type::I32; - ctx->init_expr_value.value.i32 = value; +Result BinaryReaderInterpreter::OnInitExprI32ConstExpr(uint32_t index, + uint32_t value) { + init_expr_value.type = Type::I32; + init_expr_value.value.i32 = value; return Result::Ok; } -static Result on_init_expr_i64_const_expr(uint32_t index, - uint64_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->init_expr_value.type = Type::I64; - ctx->init_expr_value.value.i64 = value; +Result BinaryReaderInterpreter::OnInitExprI64ConstExpr(uint32_t index, + uint64_t value) { + init_expr_value.type = Type::I64; + init_expr_value.value.i64 = value; return Result::Ok; } -static Result on_export(uint32_t index, - ExternalKind kind, - uint32_t item_index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name) { switch (kind) { case ExternalKind::Func: - item_index = translate_func_index_to_env(ctx, item_index); + item_index = TranslateFuncIndexToEnv(item_index); break; case ExternalKind::Table: - item_index = ctx->module->table_index; + item_index = module->table_index; break; case ExternalKind::Memory: - item_index = ctx->module->memory_index; + item_index = module->memory_index; break; case ExternalKind::Global: { - item_index = translate_global_index_to_env(ctx, item_index); - InterpreterGlobal* global = &ctx->env->globals[item_index]; + item_index = TranslateGlobalIndexToEnv(item_index); + InterpreterGlobal* global = &env->globals[item_index]; if (global->mutable_) { - print_error(ctx, "mutable globals cannot be exported"); + PrintError("mutable globals cannot be exported"); return Result::Error; } break; } } - return append_export(ctx, ctx->module, kind, item_index, name); + return AppendExport(module, kind, item_index, name); } -static Result on_start_function(uint32_t func_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - uint32_t start_func_index = translate_func_index_to_env(ctx, func_index); - InterpreterFunc* start_func = get_func_by_env_index(ctx, start_func_index); - InterpreterFuncSignature* sig = - get_signature_by_env_index(ctx, start_func->sig_index); +Result BinaryReaderInterpreter::OnStartFunction(uint32_t func_index) { + uint32_t start_func_index = TranslateFuncIndexToEnv(func_index); + InterpreterFunc* start_func = GetFuncByEnvIndex(start_func_index); + InterpreterFuncSignature* sig = GetSignatureByEnvIndex(start_func->sig_index); if (sig->param_types.size() != 0) { - print_error(ctx, "start function must be nullary"); + PrintError("start function must be nullary"); return Result::Error; } if (sig->result_types.size() != 0) { - print_error(ctx, "start function must not return anything"); + PrintError("start function must not return anything"); return Result::Error; } - ctx->module->start_func_index = start_func_index; + module->start_func_index = start_func_index; return Result::Ok; } -static Result end_elem_segment_init_expr(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->init_expr_value.type != Type::I32) { - print_error(ctx, "type mismatch in elem segment, expected i32 but got %s", - get_type_name(ctx->init_expr_value.type)); +Result BinaryReaderInterpreter::EndElemSegmentInitExpr(uint32_t index) { + if (init_expr_value.type != Type::I32) { + PrintError("type mismatch in elem segment, expected i32 but got %s", + get_type_name(init_expr_value.type)); return Result::Error; } - ctx->table_offset = ctx->init_expr_value.value.i32; + table_offset = init_expr_value.value.i32; return Result::Ok; } -static Result on_elem_segment_function_index_check(uint32_t index, - uint32_t func_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(ctx->module->table_index != WABT_INVALID_INDEX); - InterpreterTable* table = &ctx->env->tables[ctx->module->table_index]; - if (ctx->table_offset >= table->func_indexes.size()) { - print_error(ctx, - "elem segment offset is out of bounds: %u >= max value %" PRIzd, - ctx->table_offset, table->func_indexes.size()); +Result BinaryReaderInterpreter::OnElemSegmentFunctionIndex( + + uint32_t index, + uint32_t func_index) { + assert(module->table_index != WABT_INVALID_INDEX); + InterpreterTable* table = &env->tables[module->table_index]; + if (table_offset >= table->func_indexes.size()) { + PrintError("elem segment offset is out of bounds: %u >= max value %" PRIzd, + table_offset, table->func_indexes.size()); return Result::Error; } - uint32_t max_func_index = ctx->func_index_mapping.size(); + uint32_t max_func_index = func_index_mapping.size(); if (func_index >= max_func_index) { - print_error(ctx, "invalid func_index: %d (max %d)", func_index, - max_func_index); + PrintError("invalid func_index: %d (max %d)", func_index, max_func_index); return Result::Error; } + elem_segment_infos.emplace_back(&table->func_indexes[table_offset++], + TranslateFuncIndexToEnv(func_index)); return Result::Ok; } -static Result on_elem_segment_function_index(uint32_t index, - uint32_t func_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(ctx->module->table_index != WABT_INVALID_INDEX); - InterpreterTable* table = &ctx->env->tables[ctx->module->table_index]; - table->func_indexes[ctx->table_offset++] = - translate_func_index_to_env(ctx, func_index); - return Result::Ok; -} - -static Result on_data_segment_data_check(uint32_t index, - const void* src_data, - uint32_t size, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - assert(ctx->module->memory_index != WABT_INVALID_INDEX); - InterpreterMemory* memory = &ctx->env->memories[ctx->module->memory_index]; - if (ctx->init_expr_value.type != Type::I32) { - print_error(ctx, "type mismatch in data segment, expected i32 but got %s", - get_type_name(ctx->init_expr_value.type)); +Result BinaryReaderInterpreter::OnDataSegmentData(uint32_t index, + const void* src_data, + uint32_t size) { + assert(module->memory_index != WABT_INVALID_INDEX); + InterpreterMemory* memory = &env->memories[module->memory_index]; + if (init_expr_value.type != Type::I32) { + PrintError("type mismatch in data segment, expected i32 but got %s", + get_type_name(init_expr_value.type)); return Result::Error; } - uint32_t address = ctx->init_expr_value.value.i32; + uint32_t address = init_expr_value.value.i32; uint64_t end_address = static_cast<uint64_t>(address) + static_cast<uint64_t>(size); if (end_address > memory->data.size()) { - print_error(ctx, - "data segment is out of bounds: [%u, %" PRIu64 - ") >= max value %" PRIzd, - address, end_address, memory->data.size()); + PrintError("data segment is out of bounds: [%u, %" PRIu64 + ") >= max value %" PRIzd, + address, end_address, memory->data.size()); return Result::Error; } - return Result::Ok; -} -static Result on_data_segment_data(uint32_t index, - const void* src_data, - uint32_t size, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (size > 0) { - assert(ctx->module->memory_index != WABT_INVALID_INDEX); - InterpreterMemory* memory = &ctx->env->memories[ctx->module->memory_index]; - uint32_t address = ctx->init_expr_value.value.i32; - memcpy(&memory->data[address], src_data, size); - } + if (size > 0) + data_segment_infos.emplace_back(&memory->data[address], src_data, size); + return Result::Ok; } -static void push_label(Context* ctx, uint32_t offset, uint32_t fixup_offset) { - ctx->label_stack.emplace_back(offset, fixup_offset); +void BinaryReaderInterpreter::PushLabel(uint32_t offset, + uint32_t fixup_offset) { + label_stack.emplace_back(offset, fixup_offset); } -static void pop_label(Context* ctx) { - ctx->label_stack.pop_back(); +void BinaryReaderInterpreter::PopLabel() { + label_stack.pop_back(); /* reduce the depth_fixups stack as well, but it may be smaller than * label_stack so only do it conditionally. */ - if (ctx->depth_fixups.size() > ctx->label_stack.size()) { - ctx->depth_fixups.erase(ctx->depth_fixups.begin() + ctx->label_stack.size(), - ctx->depth_fixups.end()); + if (depth_fixups.size() > label_stack.size()) { + depth_fixups.erase(depth_fixups.begin() + label_stack.size(), + depth_fixups.end()); } } -// TODO(binji): remove this when the rest of the code is using std::vector -#define INTERPRETER_TYPE_VECTOR_TO_TYPE_VECTOR(out, in) \ - TypeVector out; \ - { \ - size_t byte_size = (in).size() * sizeof((in)[0]); \ - (out).data = static_cast<decltype((out).data)>(alloca(byte_size)); \ - (out).size = (in).size(); \ - if (byte_size) { \ - memcpy((out).data, (in).data(), byte_size); \ - } \ - } - -static Result begin_function_body(BinaryReaderContext* context, - uint32_t index) { - Context* ctx = static_cast<Context*>(context->user_data); - DefinedInterpreterFunc* func = - get_func_by_module_index(ctx, index)->as_defined(); - InterpreterFuncSignature* sig = - get_signature_by_env_index(ctx, func->sig_index); +Result BinaryReaderInterpreter::BeginFunctionBody(uint32_t index) { + DefinedInterpreterFunc* func = GetFuncByModuleIndex(index)->as_defined(); + InterpreterFuncSignature* sig = GetSignatureByEnvIndex(func->sig_index); - func->offset = get_istream_offset(ctx); + func->offset = GetIstreamOffset(); func->local_decl_count = 0; func->local_count = 0; - ctx->current_func = func; - ctx->depth_fixups.clear(); - ctx->label_stack.clear(); + current_func = func; + depth_fixups.clear(); + label_stack.clear(); /* fixup function references */ - uint32_t defined_index = translate_module_func_index_to_defined(ctx, index); - Uint32Vector& fixups = ctx->func_fixups[defined_index]; - for (uint32_t fixup: fixups) - CHECK_RESULT(emit_i32_at(ctx, fixup, func->offset)); + uint32_t defined_index = TranslateModuleFuncIndexToDefined(index); + Uint32Vector& fixups = func_fixups[defined_index]; + for (uint32_t fixup : fixups) + CHECK_RESULT(EmitI32At(fixup, func->offset)); /* append param types */ - for (Type param_type: sig->param_types) + for (Type param_type : sig->param_types) func->param_and_local_types.push_back(param_type); - CHECK_RESULT( - typechecker_begin_function(&ctx->typechecker, &sig->result_types)); + CHECK_RESULT(typechecker_begin_function(&typechecker, &sig->result_types)); /* push implicit func label (equivalent to return) */ - push_label(ctx, WABT_INVALID_OFFSET, WABT_INVALID_OFFSET); + PushLabel(WABT_INVALID_OFFSET, WABT_INVALID_OFFSET); return Result::Ok; } -static Result end_function_body(uint32_t index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - fixup_top_label(ctx); +Result BinaryReaderInterpreter::EndFunctionBody(uint32_t index) { + FixupTopLabel(); uint32_t drop_count, keep_count; - CHECK_RESULT(get_return_drop_keep_count(ctx, &drop_count, &keep_count)); - CHECK_RESULT(typechecker_end_function(&ctx->typechecker)); - CHECK_RESULT(emit_drop_keep(ctx, drop_count, keep_count)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Return)); - pop_label(ctx); - ctx->current_func = nullptr; + CHECK_RESULT(GetReturnDropKeepCount(&drop_count, &keep_count)); + CHECK_RESULT(typechecker_end_function(&typechecker)); + CHECK_RESULT(EmitDropKeep(drop_count, keep_count)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Return)); + PopLabel(); + current_func = nullptr; return Result::Ok; } -static Result on_local_decl_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->current_func->local_decl_count = count; +Result BinaryReaderInterpreter::OnLocalDeclCount(uint32_t count) { + current_func->local_decl_count = count; return Result::Ok; } -static Result on_local_decl(uint32_t decl_index, - uint32_t count, - Type type, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->current_func->local_count += count; +Result BinaryReaderInterpreter::OnLocalDecl(uint32_t decl_index, + uint32_t count, + Type type) { + current_func->local_count += count; for (uint32_t i = 0; i < count; ++i) - ctx->current_func->param_and_local_types.push_back(type); + current_func->param_and_local_types.push_back(type); - if (decl_index == ctx->current_func->local_decl_count - 1) { + if (decl_index == current_func->local_decl_count - 1) { /* last local declaration, allocate space for all locals. */ - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Alloca)); - CHECK_RESULT(emit_i32(ctx, ctx->current_func->local_count)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Alloca)); + CHECK_RESULT(EmitI32(current_func->local_count)); } return Result::Ok; } -static Result check_has_memory(Context* ctx, Opcode opcode) { - if (ctx->module->memory_index == WABT_INVALID_INDEX) { - print_error(ctx, "%s requires an imported or defined memory.", - get_opcode_name(opcode)); +Result BinaryReaderInterpreter::CheckHasMemory(Opcode opcode) { + if (module->memory_index == WABT_INVALID_INDEX) { + PrintError("%s requires an imported or defined memory.", + get_opcode_name(opcode)); return Result::Error; } return Result::Ok; } -static Result check_align(Context* ctx, - uint32_t alignment_log2, - uint32_t natural_alignment) { +Result BinaryReaderInterpreter::CheckAlign(uint32_t alignment_log2, + uint32_t natural_alignment) { if (alignment_log2 >= 32 || (1U << alignment_log2) > natural_alignment) { - print_error(ctx, "alignment must not be larger than natural alignment (%u)", - natural_alignment); + PrintError("alignment must not be larger than natural alignment (%u)", + natural_alignment); return Result::Error; } return Result::Ok; } -static Result on_unary_expr(Opcode opcode, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_unary(&ctx->typechecker, opcode)); - CHECK_RESULT(emit_opcode(ctx, opcode)); +Result BinaryReaderInterpreter::OnUnaryExpr(Opcode opcode) { + CHECK_RESULT(typechecker_on_unary(&typechecker, opcode)); + CHECK_RESULT(EmitOpcode(opcode)); return Result::Ok; } -static Result on_binary_expr(Opcode opcode, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_binary(&ctx->typechecker, opcode)); - CHECK_RESULT(emit_opcode(ctx, opcode)); +Result BinaryReaderInterpreter::OnBinaryExpr(Opcode opcode) { + CHECK_RESULT(typechecker_on_binary(&typechecker, opcode)); + CHECK_RESULT(EmitOpcode(opcode)); return Result::Ok; } -static Result on_block_expr(uint32_t num_types, - Type* sig_types, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnBlockExpr(uint32_t num_types, + Type* sig_types) { TypeVector sig(sig_types, sig_types + num_types); - CHECK_RESULT(typechecker_on_block(&ctx->typechecker, &sig)); - push_label(ctx, WABT_INVALID_OFFSET, WABT_INVALID_OFFSET); + CHECK_RESULT(typechecker_on_block(&typechecker, &sig)); + PushLabel(WABT_INVALID_OFFSET, WABT_INVALID_OFFSET); return Result::Ok; } -static Result on_loop_expr(uint32_t num_types, - Type* sig_types, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnLoopExpr(uint32_t num_types, + Type* sig_types) { TypeVector sig(sig_types, sig_types + num_types); - CHECK_RESULT(typechecker_on_loop(&ctx->typechecker, &sig)); - push_label(ctx, get_istream_offset(ctx), WABT_INVALID_OFFSET); + CHECK_RESULT(typechecker_on_loop(&typechecker, &sig)); + PushLabel(GetIstreamOffset(), WABT_INVALID_OFFSET); return Result::Ok; } -static Result on_if_expr(uint32_t num_types, Type* sig_types, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnIfExpr(uint32_t num_types, Type* sig_types) { TypeVector sig(sig_types, sig_types + num_types); - CHECK_RESULT(typechecker_on_if(&ctx->typechecker, &sig)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::BrUnless)); - uint32_t fixup_offset = get_istream_offset(ctx); - CHECK_RESULT(emit_i32(ctx, WABT_INVALID_OFFSET)); - push_label(ctx, WABT_INVALID_OFFSET, fixup_offset); + CHECK_RESULT(typechecker_on_if(&typechecker, &sig)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::BrUnless)); + uint32_t fixup_offset = GetIstreamOffset(); + CHECK_RESULT(EmitI32(WABT_INVALID_OFFSET)); + PushLabel(WABT_INVALID_OFFSET, fixup_offset); return Result::Ok; } -static Result on_else_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_else(&ctx->typechecker)); - Label* label = top_label(ctx); +Result BinaryReaderInterpreter::OnElseExpr() { + CHECK_RESULT(typechecker_on_else(&typechecker)); + Label* label = TopLabel(); uint32_t fixup_cond_offset = label->fixup_offset; - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Br)); - label->fixup_offset = get_istream_offset(ctx); - CHECK_RESULT(emit_i32(ctx, WABT_INVALID_OFFSET)); - CHECK_RESULT(emit_i32_at(ctx, fixup_cond_offset, get_istream_offset(ctx))); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Br)); + label->fixup_offset = GetIstreamOffset(); + CHECK_RESULT(EmitI32(WABT_INVALID_OFFSET)); + CHECK_RESULT(EmitI32At(fixup_cond_offset, GetIstreamOffset())); return Result::Ok; } -static Result on_end_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnEndExpr() { TypeCheckerLabel* label; - CHECK_RESULT(typechecker_get_label(&ctx->typechecker, 0, &label)); + CHECK_RESULT(typechecker_get_label(&typechecker, 0, &label)); LabelType label_type = label->label_type; - CHECK_RESULT(typechecker_on_end(&ctx->typechecker)); + CHECK_RESULT(typechecker_on_end(&typechecker)); if (label_type == LabelType::If || label_type == LabelType::Else) { - CHECK_RESULT(emit_i32_at(ctx, top_label(ctx)->fixup_offset, - get_istream_offset(ctx))); + CHECK_RESULT(EmitI32At(TopLabel()->fixup_offset, GetIstreamOffset())); } - fixup_top_label(ctx); - pop_label(ctx); + FixupTopLabel(); + PopLabel(); return Result::Ok; } -static Result on_br_expr(uint32_t depth, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnBrExpr(uint32_t depth) { uint32_t drop_count, keep_count; - CHECK_RESULT(get_br_drop_keep_count(ctx, depth, &drop_count, &keep_count)); - CHECK_RESULT(typechecker_on_br(&ctx->typechecker, depth)); - CHECK_RESULT(emit_br(ctx, depth, drop_count, keep_count)); + CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count)); + CHECK_RESULT(typechecker_on_br(&typechecker, depth)); + CHECK_RESULT(EmitBr(depth, drop_count, keep_count)); return Result::Ok; } -static Result on_br_if_expr(uint32_t depth, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnBrIfExpr(uint32_t depth) { uint32_t drop_count, keep_count; - CHECK_RESULT(typechecker_on_br_if(&ctx->typechecker, depth)); - CHECK_RESULT(get_br_drop_keep_count(ctx, depth, &drop_count, &keep_count)); + CHECK_RESULT(typechecker_on_br_if(&typechecker, depth)); + CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count)); /* flip the br_if so if <cond> is true it can drop values from the stack */ - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::BrUnless)); - uint32_t fixup_br_offset = get_istream_offset(ctx); - CHECK_RESULT(emit_i32(ctx, WABT_INVALID_OFFSET)); - CHECK_RESULT(emit_br(ctx, depth, drop_count, keep_count)); - CHECK_RESULT(emit_i32_at(ctx, fixup_br_offset, get_istream_offset(ctx))); - return Result::Ok; -} - -static Result on_br_table_expr(BinaryReaderContext* context, - uint32_t num_targets, - uint32_t* target_depths, - uint32_t default_target_depth) { - Context* ctx = static_cast<Context*>(context->user_data); - CHECK_RESULT(typechecker_begin_br_table(&ctx->typechecker)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::BrTable)); - CHECK_RESULT(emit_i32(ctx, num_targets)); - uint32_t fixup_table_offset = get_istream_offset(ctx); - CHECK_RESULT(emit_i32(ctx, WABT_INVALID_OFFSET)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::BrUnless)); + uint32_t fixup_br_offset = GetIstreamOffset(); + CHECK_RESULT(EmitI32(WABT_INVALID_OFFSET)); + CHECK_RESULT(EmitBr(depth, drop_count, keep_count)); + CHECK_RESULT(EmitI32At(fixup_br_offset, GetIstreamOffset())); + return Result::Ok; +} + +Result BinaryReaderInterpreter::OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth) { + CHECK_RESULT(typechecker_begin_br_table(&typechecker)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::BrTable)); + CHECK_RESULT(EmitI32(num_targets)); + uint32_t fixup_table_offset = GetIstreamOffset(); + CHECK_RESULT(EmitI32(WABT_INVALID_OFFSET)); /* not necessary for the interpreter, but it makes it easier to disassemble. * This opcode specifies how many bytes of data follow. */ - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Data)); - CHECK_RESULT(emit_i32(ctx, (num_targets + 1) * WABT_TABLE_ENTRY_SIZE)); - CHECK_RESULT(emit_i32_at(ctx, fixup_table_offset, get_istream_offset(ctx))); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Data)); + CHECK_RESULT(EmitI32((num_targets + 1) * WABT_TABLE_ENTRY_SIZE)); + CHECK_RESULT(EmitI32At(fixup_table_offset, GetIstreamOffset())); for (uint32_t i = 0; i <= num_targets; ++i) { uint32_t depth = i != num_targets ? target_depths[i] : default_target_depth; - CHECK_RESULT(typechecker_on_br_table_target(&ctx->typechecker, depth)); - CHECK_RESULT(emit_br_table_offset(ctx, depth)); + CHECK_RESULT(typechecker_on_br_table_target(&typechecker, depth)); + CHECK_RESULT(EmitBrTableOffset(depth)); } - CHECK_RESULT(typechecker_end_br_table(&ctx->typechecker)); + CHECK_RESULT(typechecker_end_br_table(&typechecker)); return Result::Ok; } -static Result on_call_expr(uint32_t func_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - InterpreterFunc* func = get_func_by_module_index(ctx, func_index); - InterpreterFuncSignature* sig = - get_signature_by_env_index(ctx, func->sig_index); - CHECK_RESULT(typechecker_on_call(&ctx->typechecker, &sig->param_types, - &sig->result_types)); +Result BinaryReaderInterpreter::OnCallExpr(uint32_t func_index) { + InterpreterFunc* func = GetFuncByModuleIndex(func_index); + InterpreterFuncSignature* sig = GetSignatureByEnvIndex(func->sig_index); + CHECK_RESULT( + typechecker_on_call(&typechecker, &sig->param_types, &sig->result_types)); if (func->is_host) { - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::CallHost)); - CHECK_RESULT(emit_i32(ctx, translate_func_index_to_env(ctx, func_index))); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::CallHost)); + CHECK_RESULT(EmitI32(TranslateFuncIndexToEnv(func_index))); } else { - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Call)); - CHECK_RESULT(emit_func_offset(ctx, func->as_defined(), func_index)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Call)); + CHECK_RESULT(EmitFuncOffset(func->as_defined(), func_index)); } return Result::Ok; } -static Result on_call_indirect_expr(uint32_t sig_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->module->table_index == WABT_INVALID_INDEX) { - print_error(ctx, "found call_indirect operator, but no table"); +Result BinaryReaderInterpreter::OnCallIndirectExpr(uint32_t sig_index) { + if (module->table_index == WABT_INVALID_INDEX) { + PrintError("found call_indirect operator, but no table"); return Result::Error; } - InterpreterFuncSignature* sig = get_signature_by_module_index(ctx, sig_index); - CHECK_RESULT(typechecker_on_call_indirect( - &ctx->typechecker, &sig->param_types, &sig->result_types)); + InterpreterFuncSignature* sig = GetSignatureByModuleIndex(sig_index); + CHECK_RESULT(typechecker_on_call_indirect(&typechecker, &sig->param_types, + &sig->result_types)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::CallIndirect)); - CHECK_RESULT(emit_i32(ctx, ctx->module->table_index)); - CHECK_RESULT(emit_i32(ctx, translate_sig_index_to_env(ctx, sig_index))); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::CallIndirect)); + CHECK_RESULT(EmitI32(module->table_index)); + CHECK_RESULT(EmitI32(TranslateSigIndexToEnv(sig_index))); return Result::Ok; } -static Result on_drop_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_drop(&ctx->typechecker)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Drop)); +Result BinaryReaderInterpreter::OnCompareExpr(Opcode opcode) { + return OnBinaryExpr(opcode); +} + +Result BinaryReaderInterpreter::OnConvertExpr(Opcode opcode) { + return OnUnaryExpr(opcode); +} + +Result BinaryReaderInterpreter::OnDropExpr() { + CHECK_RESULT(typechecker_on_drop(&typechecker)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Drop)); return Result::Ok; } -static Result on_i32_const_expr(uint32_t value, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_const(&ctx->typechecker, Type::I32)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::I32Const)); - CHECK_RESULT(emit_i32(ctx, value)); +Result BinaryReaderInterpreter::OnI32ConstExpr(uint32_t value) { + CHECK_RESULT(typechecker_on_const(&typechecker, Type::I32)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::I32Const)); + CHECK_RESULT(EmitI32(value)); return Result::Ok; } -static Result on_i64_const_expr(uint64_t value, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_const(&ctx->typechecker, Type::I64)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::I64Const)); - CHECK_RESULT(emit_i64(ctx, value)); +Result BinaryReaderInterpreter::OnI64ConstExpr(uint64_t value) { + CHECK_RESULT(typechecker_on_const(&typechecker, Type::I64)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::I64Const)); + CHECK_RESULT(EmitI64(value)); return Result::Ok; } -static Result on_f32_const_expr(uint32_t value_bits, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_const(&ctx->typechecker, Type::F32)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::F32Const)); - CHECK_RESULT(emit_i32(ctx, value_bits)); +Result BinaryReaderInterpreter::OnF32ConstExpr(uint32_t value_bits) { + CHECK_RESULT(typechecker_on_const(&typechecker, Type::F32)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::F32Const)); + CHECK_RESULT(EmitI32(value_bits)); return Result::Ok; } -static Result on_f64_const_expr(uint64_t value_bits, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_const(&ctx->typechecker, Type::F64)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::F64Const)); - CHECK_RESULT(emit_i64(ctx, value_bits)); +Result BinaryReaderInterpreter::OnF64ConstExpr(uint64_t value_bits) { + CHECK_RESULT(typechecker_on_const(&typechecker, Type::F64)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::F64Const)); + CHECK_RESULT(EmitI64(value_bits)); return Result::Ok; } -static Result on_get_global_expr(uint32_t global_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_GLOBAL(ctx, global_index); - Type type = get_global_type_by_module_index(ctx, global_index); - CHECK_RESULT(typechecker_on_get_global(&ctx->typechecker, type)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::GetGlobal)); - CHECK_RESULT(emit_i32(ctx, translate_global_index_to_env(ctx, global_index))); +Result BinaryReaderInterpreter::OnGetGlobalExpr(uint32_t global_index) { + CHECK_RESULT(CheckGlobal(global_index)); + Type type = GetGlobalTypeByModuleIndex(global_index); + CHECK_RESULT(typechecker_on_get_global(&typechecker, type)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::GetGlobal)); + CHECK_RESULT(EmitI32(TranslateGlobalIndexToEnv(global_index))); return Result::Ok; } -static Result on_set_global_expr(uint32_t global_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_GLOBAL(ctx, global_index); - InterpreterGlobal* global = get_global_by_module_index(ctx, global_index); +Result BinaryReaderInterpreter::OnSetGlobalExpr(uint32_t global_index) { + CHECK_RESULT(CheckGlobal(global_index)); + InterpreterGlobal* global = GetGlobalByModuleIndex(global_index); if (!global->mutable_) { - print_error(ctx, "can't set_global on immutable global at index %u.", - global_index); + PrintError("can't set_global on immutable global at index %u.", + global_index); return Result::Error; } CHECK_RESULT( - typechecker_on_set_global(&ctx->typechecker, global->typed_value.type)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::SetGlobal)); - CHECK_RESULT(emit_i32(ctx, translate_global_index_to_env(ctx, global_index))); + typechecker_on_set_global(&typechecker, global->typed_value.type)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::SetGlobal)); + CHECK_RESULT(EmitI32(TranslateGlobalIndexToEnv(global_index))); return Result::Ok; } -static uint32_t translate_local_index(Context* ctx, uint32_t local_index) { - return ctx->typechecker.type_stack.size() + - ctx->current_func->param_and_local_types.size() - local_index; +uint32_t BinaryReaderInterpreter::TranslateLocalIndex(uint32_t local_index) { + return typechecker.type_stack.size() + + current_func->param_and_local_types.size() - local_index; } -static Result on_get_local_expr(uint32_t local_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_LOCAL(ctx, local_index); - Type type = get_local_type_by_index(ctx->current_func, local_index); +Result BinaryReaderInterpreter::OnGetLocalExpr(uint32_t local_index) { + CHECK_RESULT(CheckLocal(local_index)); + Type type = GetLocalTypeByIndex(current_func, local_index); /* Get the translated index before calling typechecker_on_get_local * because it will update the type stack size. We need the index to be * relative to the old stack size. */ - uint32_t translated_local_index = translate_local_index(ctx, local_index); - CHECK_RESULT(typechecker_on_get_local(&ctx->typechecker, type)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::GetLocal)); - CHECK_RESULT(emit_i32(ctx, translated_local_index)); + uint32_t translated_local_index = TranslateLocalIndex(local_index); + CHECK_RESULT(typechecker_on_get_local(&typechecker, type)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::GetLocal)); + CHECK_RESULT(EmitI32(translated_local_index)); return Result::Ok; } -static Result on_set_local_expr(uint32_t local_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_LOCAL(ctx, local_index); - Type type = get_local_type_by_index(ctx->current_func, local_index); - CHECK_RESULT(typechecker_on_set_local(&ctx->typechecker, type)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::SetLocal)); - CHECK_RESULT(emit_i32(ctx, translate_local_index(ctx, local_index))); +Result BinaryReaderInterpreter::OnSetLocalExpr(uint32_t local_index) { + CHECK_RESULT(CheckLocal(local_index)); + Type type = GetLocalTypeByIndex(current_func, local_index); + CHECK_RESULT(typechecker_on_set_local(&typechecker, type)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::SetLocal)); + CHECK_RESULT(EmitI32(TranslateLocalIndex(local_index))); return Result::Ok; } -static Result on_tee_local_expr(uint32_t local_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_LOCAL(ctx, local_index); - Type type = get_local_type_by_index(ctx->current_func, local_index); - CHECK_RESULT(typechecker_on_tee_local(&ctx->typechecker, type)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::TeeLocal)); - CHECK_RESULT(emit_i32(ctx, translate_local_index(ctx, local_index))); +Result BinaryReaderInterpreter::OnTeeLocalExpr(uint32_t local_index) { + CHECK_RESULT(CheckLocal(local_index)); + Type type = GetLocalTypeByIndex(current_func, local_index); + CHECK_RESULT(typechecker_on_tee_local(&typechecker, type)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::TeeLocal)); + CHECK_RESULT(EmitI32(TranslateLocalIndex(local_index))); return Result::Ok; } -static Result on_grow_memory_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(check_has_memory(ctx, Opcode::GrowMemory)); - CHECK_RESULT(typechecker_on_grow_memory(&ctx->typechecker)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::GrowMemory)); - CHECK_RESULT(emit_i32(ctx, ctx->module->memory_index)); +Result BinaryReaderInterpreter::OnGrowMemoryExpr() { + CHECK_RESULT(CheckHasMemory(Opcode::GrowMemory)); + CHECK_RESULT(typechecker_on_grow_memory(&typechecker)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::GrowMemory)); + CHECK_RESULT(EmitI32(module->memory_index)); return Result::Ok; } -static Result on_load_expr(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(check_has_memory(ctx, opcode)); - CHECK_RESULT( - check_align(ctx, alignment_log2, get_opcode_memory_size(opcode))); - CHECK_RESULT(typechecker_on_load(&ctx->typechecker, opcode)); - CHECK_RESULT(emit_opcode(ctx, opcode)); - CHECK_RESULT(emit_i32(ctx, ctx->module->memory_index)); - CHECK_RESULT(emit_i32(ctx, offset)); +Result BinaryReaderInterpreter::OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { + CHECK_RESULT(CheckHasMemory(opcode)); + CHECK_RESULT(CheckAlign(alignment_log2, get_opcode_memory_size(opcode))); + CHECK_RESULT(typechecker_on_load(&typechecker, opcode)); + CHECK_RESULT(EmitOpcode(opcode)); + CHECK_RESULT(EmitI32(module->memory_index)); + CHECK_RESULT(EmitI32(offset)); return Result::Ok; } -static Result on_store_expr(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(check_has_memory(ctx, opcode)); - CHECK_RESULT( - check_align(ctx, alignment_log2, get_opcode_memory_size(opcode))); - CHECK_RESULT(typechecker_on_store(&ctx->typechecker, opcode)); - CHECK_RESULT(emit_opcode(ctx, opcode)); - CHECK_RESULT(emit_i32(ctx, ctx->module->memory_index)); - CHECK_RESULT(emit_i32(ctx, offset)); +Result BinaryReaderInterpreter::OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { + CHECK_RESULT(CheckHasMemory(opcode)); + CHECK_RESULT(CheckAlign(alignment_log2, get_opcode_memory_size(opcode))); + CHECK_RESULT(typechecker_on_store(&typechecker, opcode)); + CHECK_RESULT(EmitOpcode(opcode)); + CHECK_RESULT(EmitI32(module->memory_index)); + CHECK_RESULT(EmitI32(offset)); return Result::Ok; } -static Result on_current_memory_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(check_has_memory(ctx, Opcode::CurrentMemory)); - CHECK_RESULT(typechecker_on_current_memory(&ctx->typechecker)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::CurrentMemory)); - CHECK_RESULT(emit_i32(ctx, ctx->module->memory_index)); +Result BinaryReaderInterpreter::OnCurrentMemoryExpr() { + CHECK_RESULT(CheckHasMemory(Opcode::CurrentMemory)); + CHECK_RESULT(typechecker_on_current_memory(&typechecker)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::CurrentMemory)); + CHECK_RESULT(EmitI32(module->memory_index)); return Result::Ok; } -static Result on_nop_expr(void* user_data) { +Result BinaryReaderInterpreter::OnNopExpr() { return Result::Ok; } -static Result on_return_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderInterpreter::OnReturnExpr() { uint32_t drop_count, keep_count; - CHECK_RESULT(get_return_drop_keep_count(ctx, &drop_count, &keep_count)); - CHECK_RESULT(typechecker_on_return(&ctx->typechecker)); - CHECK_RESULT(emit_drop_keep(ctx, drop_count, keep_count)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Return)); + CHECK_RESULT(GetReturnDropKeepCount(&drop_count, &keep_count)); + CHECK_RESULT(typechecker_on_return(&typechecker)); + CHECK_RESULT(EmitDropKeep(drop_count, keep_count)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Return)); + return Result::Ok; +} + +Result BinaryReaderInterpreter::OnSelectExpr() { + CHECK_RESULT(typechecker_on_select(&typechecker)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Select)); return Result::Ok; } -static Result on_select_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_select(&ctx->typechecker)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Select)); +Result BinaryReaderInterpreter::OnUnreachableExpr() { + CHECK_RESULT(typechecker_on_unreachable(&typechecker)); + CHECK_RESULT(EmitOpcode(InterpreterOpcode::Unreachable)); return Result::Ok; } -static Result on_unreachable_expr(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - CHECK_RESULT(typechecker_on_unreachable(&ctx->typechecker)); - CHECK_RESULT(emit_opcode(ctx, InterpreterOpcode::Unreachable)); +Result BinaryReaderInterpreter::EndModule() { + for (ElemSegmentInfo& info : elem_segment_infos) { + *info.dst = info.func_index; + } + for (DataSegmentInfo& info : data_segment_infos) { + memcpy(info.dst_data, info.src_data, info.size); + } return Result::Ok; } +} // namespace + Result read_binary_interpreter(InterpreterEnvironment* env, const void* data, size_t size, const ReadBinaryOptions* options, BinaryErrorHandler* error_handler, DefinedInterpreterModule** out_module) { - Context ctx; - BinaryReader reader; - - InterpreterEnvironmentMark mark = mark_interpreter_environment(env); - + size_t istream_offset = env->istream.size; DefinedInterpreterModule* module = - new DefinedInterpreterModule(env->istream.size); - env->modules.emplace_back(module); + new DefinedInterpreterModule(istream_offset); - WABT_ZERO_MEMORY(reader); + BinaryReaderInterpreter reader(env, module, istream_offset, error_handler); + if (WABT_FAILED(reader.Init())) { + delete module; + return Result::Error; + } - ctx.reader = &reader; - ctx.error_handler = error_handler; - ctx.env = env; - ctx.module = module; - ctx.istream_offset = env->istream.size; - CHECK_RESULT(init_mem_writer_existing(&ctx.istream_writer, &env->istream)); + InterpreterEnvironmentMark mark = mark_interpreter_environment(env); + env->modules.emplace_back(module); - TypeCheckerErrorHandler tc_error_handler; - tc_error_handler.on_error = on_typechecker_error; - tc_error_handler.user_data = &ctx; - ctx.typechecker.error_handler = &tc_error_handler; - - 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 = on_table; - reader.on_memory = on_memory; - reader.on_global_count = on_global_count; - reader.begin_global = begin_global; - reader.end_global_init_expr = end_global_init_expr; - reader.on_export = on_export; - reader.on_start_function = on_start_function; - reader.begin_function_body = begin_function_body; - reader.on_local_decl_count = on_local_decl_count; - 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_binary_expr; - reader.on_convert_expr = on_unary_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.end_elem_segment_init_expr = end_elem_segment_init_expr; - reader.on_elem_segment_function_index = on_elem_segment_function_index_check; - reader.on_data_segment_data = on_data_segment_data_check; - 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; - - const uint32_t num_function_passes = 1; - Result result = - read_binary(data, size, &reader, num_function_passes, options); - steal_mem_writer_output_buffer(&ctx.istream_writer, &env->istream); + Result result = read_binary(data, size, &reader, options); + reader.StealOutputBuffer(&env->istream); if (WABT_SUCCEEDED(result)) { - /* Another pass on the read binary to assign data and elem segments. */ - WABT_ZERO_MEMORY(reader); - reader.user_data = &ctx; - reader.on_error = on_error; - reader.end_elem_segment_init_expr = end_elem_segment_init_expr; - reader.on_elem_segment_function_index = on_elem_segment_function_index; - reader.on_data_segment_data = on_data_segment_data; - 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; - - result = read_binary(data, size, &reader, num_function_passes, options); - assert(WABT_SUCCEEDED(result)); - - env->istream.size = ctx.istream_offset; - ctx.module->istream_end = env->istream.size; + env->istream.size = reader.get_istream_offset(); + module->istream_end = env->istream.size; *out_module = module; } else { reset_interpreter_environment_to_mark(env, mark); diff --git a/src/binary-reader-linker.cc b/src/binary-reader-linker.cc index 026c2f9d..40d3c420 100644 --- a/src/binary-reader-linker.cc +++ b/src/binary-reader-linker.cc @@ -18,7 +18,7 @@ #include <vector> -#include "binary-reader.h" +#include "binary-reader-nop.h" #include "wasm-link.h" #define RELOC_SIZE 5 @@ -28,21 +28,74 @@ namespace link { namespace { -struct Context { +class BinaryReaderLinker : public BinaryReaderNop { + public: + explicit BinaryReaderLinker(LinkerInputBinary* binary); + + virtual Result BeginSection(BinarySection section_type, uint32_t size); + + virtual Result BeginCustomSection(uint32_t size, StringSlice section_name); + + virtual Result OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name); + virtual Result OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index); + virtual Result OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_); + + virtual Result OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits); + + virtual Result OnMemory(uint32_t index, const Limits* limits); + + virtual Result OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name); + + virtual Result OnElemSegmentFunctionIndexCount(uint32_t index, + uint32_t count); + + virtual Result BeginDataSegment(uint32_t index, uint32_t memory_index); + virtual Result OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size); + + virtual Result OnFunctionName(uint32_t function_index, + StringSlice function_name); + + virtual Result OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name); + virtual Result OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend); + + virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value); + + private: LinkerInputBinary* binary; - Section* reloc_section; - Section* current_section; + Section* reloc_section = nullptr; + Section* current_section = nullptr; }; -} // namespace +BinaryReaderLinker::BinaryReaderLinker(LinkerInputBinary* binary) + : binary(binary) {} -static Result on_reloc_count(uint32_t count, - BinarySection section_code, - StringSlice section_name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - LinkerInputBinary* binary = ctx->binary; +Result BinaryReaderLinker::OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name) { if (section_code == BinarySection::Custom) { WABT_FATAL("relocation for custom sections not yet supported\n"); } @@ -50,7 +103,7 @@ static Result on_reloc_count(uint32_t count, for (const std::unique_ptr<Section>& section : binary->sections) { if (section->section_code != section_code) continue; - ctx->reloc_section = section.get(); + reloc_section = section.get(); return Result::Ok; } @@ -58,26 +111,22 @@ static Result on_reloc_count(uint32_t count, return Result::Error; } -static Result on_reloc(RelocType type, - uint32_t offset, - uint32_t index, - int32_t addend, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - - if (offset + RELOC_SIZE > ctx->reloc_section->size) { +Result BinaryReaderLinker::OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend) { + if (offset + RELOC_SIZE > reloc_section->size) { WABT_FATAL("invalid relocation offset: %#x\n", offset); } - ctx->reloc_section->relocations.emplace_back(type, offset, index, addend); + reloc_section->relocations.emplace_back(type, offset, index, addend); return Result::Ok; } -static Result on_import(uint32_t index, - StringSlice module_name, - StringSlice field_name, - void* user_data) { +Result BinaryReaderLinker::OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name) { if (!string_slice_eq_cstr(&module_name, WABT_LINK_MODULE_NAME)) { WABT_FATAL("unsupported import module: " PRIstringslice, WABT_PRINTF_STRING_SLICE_ARG(module_name)); @@ -85,50 +134,43 @@ static Result on_import(uint32_t index, return Result::Ok; } -static Result on_import_func(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t global_index, - uint32_t sig_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->binary->function_imports.emplace_back(); - FunctionImport* import = &ctx->binary->function_imports.back(); +Result BinaryReaderLinker::OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + uint32_t sig_index) { + binary->function_imports.emplace_back(); + FunctionImport* import = &binary->function_imports.back(); import->name = field_name; import->sig_index = sig_index; import->active = true; - ctx->binary->active_function_imports++; + binary->active_function_imports++; return Result::Ok; } -static Result on_import_global(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t global_index, - Type type, - bool mutable_, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->binary->global_imports.emplace_back(); - GlobalImport* import = &ctx->binary->global_imports.back(); +Result BinaryReaderLinker::OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_) { + binary->global_imports.emplace_back(); + GlobalImport* import = &binary->global_imports.back(); import->name = field_name; import->type = type; import->mutable_ = mutable_; - ctx->binary->active_global_imports++; + binary->active_global_imports++; return Result::Ok; } -static Result begin_section(BinaryReaderContext* ctx, - BinarySection section_code, - uint32_t size) { - Context* context = static_cast<Context*>(ctx->user_data); - LinkerInputBinary* binary = context->binary; +Result BinaryReaderLinker::BeginSection(BinarySection section_code, + uint32_t size) { Section* sec = new Section(); binary->sections.emplace_back(sec); - context->current_section = sec; + current_section = sec; sec->section_code = section_code; sec->size = size; - sec->offset = ctx->offset; + sec->offset = state->offset; sec->binary = binary; if (sec->section_code != BinarySection::Custom && @@ -143,16 +185,13 @@ static Result begin_section(BinaryReaderContext* ctx, return Result::Ok; } -static Result begin_custom_section(BinaryReaderContext* ctx, - uint32_t size, - StringSlice section_name) { - Context* context = static_cast<Context*>(ctx->user_data); - LinkerInputBinary* binary = context->binary; - Section* sec = context->current_section; - sec->data_custom.name = section_name; +Result BinaryReaderLinker::BeginCustomSection(uint32_t size, + StringSlice section_name) { + Section* sec = current_section; + sec->data.custom.name = section_name; /* Modify section size and offset to not include the name itself. */ - size_t delta = ctx->offset - sec->offset; + size_t delta = state->offset - sec->offset; sec->offset = sec->offset + delta; sec->size = sec->size - delta; sec->payload_offset = sec->offset; @@ -164,7 +203,8 @@ static Result begin_custom_section(BinaryReaderContext* ctx, size_t bytes_read = read_u32_leb128( &binary->data[sec->offset], &binary->data[binary->size], &name_type); - if (static_cast<NameSectionSubsection>(name_type) != NameSectionSubsection::Function) { + if (static_cast<NameSectionSubsection>(name_type) != + NameSectionSubsection::Function) { WABT_FATAL("no function name section"); } @@ -172,14 +212,14 @@ static Result begin_custom_section(BinaryReaderContext* ctx, sec->payload_size -= bytes_read; uint32_t subsection_size; - bytes_read = read_u32_leb128( - &binary->data[sec->offset], &binary->data[binary->size], &subsection_size); + bytes_read = read_u32_leb128(&binary->data[sec->offset], + &binary->data[binary->size], &subsection_size); sec->payload_offset += bytes_read; sec->payload_size -= bytes_read; - bytes_read = read_u32_leb128( - &binary->data[sec->payload_offset], &binary->data[binary->size], &sec->count); + bytes_read = read_u32_leb128(&binary->data[sec->payload_offset], + &binary->data[binary->size], &sec->count); sec->payload_offset += bytes_read; sec->payload_size -= bytes_read; @@ -201,144 +241,97 @@ static Result begin_custom_section(BinaryReaderContext* ctx, return Result::Ok; } -static Result on_table(uint32_t index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { +Result BinaryReaderLinker::OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits) { if (elem_limits->has_max && (elem_limits->max != elem_limits->initial)) WABT_FATAL("Tables with max != initial not supported by wabt-link\n"); - Context* ctx = static_cast<Context*>(user_data); - ctx->binary->table_elem_count = elem_limits->initial; + binary->table_elem_count = elem_limits->initial; return Result::Ok; } -static Result on_elem_segment_function_index_count(BinaryReaderContext* ctx, - uint32_t index, - uint32_t count) { - Context* context = static_cast<Context*>(ctx->user_data); - Section* sec = context->current_section; +Result BinaryReaderLinker::OnElemSegmentFunctionIndexCount(uint32_t index, + uint32_t count) { + Section* sec = current_section; /* Modify the payload to include only the actual function indexes */ - size_t delta = ctx->offset - sec->payload_offset; + size_t delta = state->offset - sec->payload_offset; sec->payload_offset += delta; sec->payload_size -= delta; return Result::Ok; } -static Result on_memory(uint32_t index, - const Limits* page_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - Section* sec = ctx->current_section; - sec->memory_limits = *page_limits; - ctx->binary->memory_page_count = page_limits->initial; +Result BinaryReaderLinker::OnMemory(uint32_t index, const Limits* page_limits) { + Section* sec = current_section; + sec->data.memory_limits = *page_limits; + binary->memory_page_count = page_limits->initial; return Result::Ok; } -static Result begin_data_segment(uint32_t index, - uint32_t memory_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - Section* sec = ctx->current_section; - if (!sec->data_segments) { - sec->data_segments = new std::vector<DataSegment>(); +Result BinaryReaderLinker::BeginDataSegment(uint32_t index, + uint32_t memory_index) { + Section* sec = current_section; + if (!sec->data.data_segments) { + sec->data.data_segments = new std::vector<DataSegment>(); } - sec->data_segments->emplace_back(); - DataSegment& segment = sec->data_segments->back(); + sec->data.data_segments->emplace_back(); + DataSegment& segment = sec->data.data_segments->back(); segment.memory_index = memory_index; return Result::Ok; } -static Result on_init_expr_i32_const_expr(uint32_t index, - uint32_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - Section* sec = ctx->current_section; +Result BinaryReaderLinker::OnInitExprI32ConstExpr(uint32_t index, + uint32_t value) { + Section* sec = current_section; if (sec->section_code != BinarySection::Data) return Result::Ok; - DataSegment& segment = sec->data_segments->back(); + DataSegment& segment = sec->data.data_segments->back(); segment.offset = value; return Result::Ok; } -static Result on_data_segment_data(uint32_t index, - const void* src_data, - uint32_t size, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - Section* sec = ctx->current_section; - DataSegment& segment = sec->data_segments->back(); +Result BinaryReaderLinker::OnDataSegmentData(uint32_t index, + const void* src_data, + uint32_t size) { + Section* sec = current_section; + DataSegment& segment = sec->data.data_segments->back(); segment.data = static_cast<const uint8_t*>(src_data); segment.size = size; return Result::Ok; } -static Result on_export(uint32_t index, - ExternalKind kind, - uint32_t item_index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->binary->exports.emplace_back(); - Export* export_ = &ctx->binary->exports.back(); +Result BinaryReaderLinker::OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name) { + binary->exports.emplace_back(); + Export* export_ = &binary->exports.back(); export_->name = name; export_->kind = kind; export_->index = item_index; return Result::Ok; } -static Result on_function_name(uint32_t index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - while (ctx->binary->debug_names.size() < index) { - ctx->binary->debug_names.emplace_back(); +Result BinaryReaderLinker::OnFunctionName(uint32_t index, StringSlice name) { + while (binary->debug_names.size() < index) { + binary->debug_names.emplace_back(); } - if (ctx->binary->debug_names.size() == index) { - ctx->binary->debug_names.push_back(string_slice_to_string(name)); + if (binary->debug_names.size() == index) { + binary->debug_names.push_back(string_slice_to_string(name)); } return Result::Ok; } -Result read_binary_linker(LinkerInputBinary* input_info, - LinkOptions* options) { - Context context; - WABT_ZERO_MEMORY(context); - context.binary = input_info; - - BinaryReader reader; - WABT_ZERO_MEMORY(reader); - reader.user_data = &context; - reader.begin_section = begin_section; - reader.begin_custom_section = begin_custom_section; - - reader.on_reloc_count = on_reloc_count; - reader.on_reloc = on_reloc; - - reader.on_import = on_import; - reader.on_import_func = on_import_func; - reader.on_import_global = on_import_global; - - reader.on_export = on_export; - - reader.on_table = on_table; - - reader.on_memory = on_memory; - - reader.begin_data_segment = begin_data_segment; - reader.on_init_expr_i32_const_expr = on_init_expr_i32_const_expr; - reader.on_data_segment_data = on_data_segment_data; - - reader.on_elem_segment_function_index_count = - on_elem_segment_function_index_count; +} // namespace - reader.on_function_name = on_function_name; +Result read_binary_linker(LinkerInputBinary* input_info, LinkOptions* options) { + BinaryReaderLinker reader(input_info); ReadBinaryOptions read_options = WABT_READ_BINARY_OPTIONS_DEFAULT; read_options.read_debug_names = true; read_options.log_stream = options->log_stream; - return read_binary(input_info->data, input_info->size, &reader, 1, + return read_binary(input_info->data, input_info->size, &reader, &read_options); } diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc new file mode 100644 index 00000000..6657a3e5 --- /dev/null +++ b/src/binary-reader-logging.cc @@ -0,0 +1,592 @@ +/* + * Copyright 2017 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-logging.h" + +#include <inttypes.h> + +#include "stream.h" + +namespace wabt { + +#define INDENT_SIZE 2 + +#define LOGF_NOINDENT(...) writef(stream, __VA_ARGS__) + +#define LOGF(...) \ + do { \ + WriteIndent(); \ + LOGF_NOINDENT(__VA_ARGS__); \ + } while (0) + +namespace { + +void sprint_limits(char* dst, size_t size, const Limits* limits) { + int result; + if (limits->has_max) { + result = wabt_snprintf(dst, size, "initial: %" PRIu64 ", max: %" PRIu64, + limits->initial, limits->max); + } else { + result = wabt_snprintf(dst, size, "initial: %" PRIu64, limits->initial); + } + WABT_USE(result); + assert(static_cast<size_t>(result) < size); +} + +} // namespace + +BinaryReaderLogging::BinaryReaderLogging(Stream* stream, BinaryReader* forward) + : stream(stream), reader(forward), indent(0) {} + +void BinaryReaderLogging::Indent() { + indent += INDENT_SIZE; +} + +void BinaryReaderLogging::Dedent() { + indent -= INDENT_SIZE; + assert(indent >= 0); +} + +void BinaryReaderLogging::WriteIndent() { + static char s_indent[] = + " " + " "; + static size_t s_indent_len = sizeof(s_indent) - 1; + size_t i = indent; + while (i > s_indent_len) { + write_data(stream, s_indent, s_indent_len, nullptr); + i -= s_indent_len; + } + if (i > 0) { + write_data(stream, s_indent, indent, nullptr); + } +} + +void BinaryReaderLogging::LogTypes(uint32_t type_count, Type* types) { + LOGF_NOINDENT("["); + for (uint32_t i = 0; i < type_count; ++i) { + LOGF_NOINDENT("%s", get_type_name(types[i])); + if (i != type_count - 1) + LOGF_NOINDENT(", "); + } + LOGF_NOINDENT("]"); +} + +bool BinaryReaderLogging::OnError(const char* message) { + return reader->OnError(message); +} + +void BinaryReaderLogging::OnSetState(const State* s) { + BinaryReader::OnSetState(s); + reader->OnSetState(s); +} + +Result BinaryReaderLogging::BeginModule(uint32_t version) { + LOGF("BeginModule(version: %u)\n", version); + Indent(); + return reader->BeginModule(version); +} + +Result BinaryReaderLogging::BeginSection(BinarySection section_type, + uint32_t size) { + return reader->BeginSection(section_type, size); +} + +Result BinaryReaderLogging::BeginCustomSection(uint32_t size, + StringSlice section_name) { + LOGF("BeginCustomSection('" PRIstringslice "', size: %d)\n", + WABT_PRINTF_STRING_SLICE_ARG(section_name), size); + Indent(); + return reader->BeginCustomSection(size, section_name); +} + +Result BinaryReaderLogging::OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types) { + LOGF("OnType(index: %u, params: ", index); + LogTypes(param_count, param_types); + LOGF_NOINDENT(", results: "); + LogTypes(result_count, result_types); + LOGF_NOINDENT(")\n"); + return reader->OnType(index, param_count, param_types, result_count, + result_types); +} + +Result BinaryReaderLogging::OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name) { + LOGF("OnImport(index: %u, module: \"" PRIstringslice + "\", field: \"" PRIstringslice "\")\n", + index, WABT_PRINTF_STRING_SLICE_ARG(module_name), + WABT_PRINTF_STRING_SLICE_ARG(field_name)); + return reader->OnImport(index, module_name, field_name); +} + +Result BinaryReaderLogging::OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index) { + LOGF("OnImportFunc(import_index: %u, func_index: %u, sig_index: %u)\n", + import_index, func_index, sig_index); + return reader->OnImportFunc(import_index, module_name, field_name, func_index, + sig_index); +} + +Result BinaryReaderLogging::OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits) { + char buf[100]; + sprint_limits(buf, sizeof(buf), elem_limits); + LOGF("OnImportTable(import_index: %u, table_index: %u, elem_type: %s, %s)\n", + import_index, table_index, get_type_name(elem_type), buf); + return reader->OnImportTable(import_index, module_name, field_name, + table_index, elem_type, elem_limits); +} + +Result BinaryReaderLogging::OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits) { + char buf[100]; + sprint_limits(buf, sizeof(buf), page_limits); + LOGF("OnImportMemory(import_index: %u, memory_index: %u, %s)\n", import_index, + memory_index, buf); + return reader->OnImportMemory(import_index, module_name, field_name, + memory_index, page_limits); +} + +Result BinaryReaderLogging::OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_) { + LOGF( + "OnImportGlobal(import_index: %u, global_index: %u, type: %s, mutable: " + "%s)\n", + import_index, global_index, get_type_name(type), + mutable_ ? "true" : "false"); + return reader->OnImportGlobal(import_index, module_name, field_name, + global_index, type, mutable_); +} + +Result BinaryReaderLogging::OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits) { + char buf[100]; + sprint_limits(buf, sizeof(buf), elem_limits); + LOGF("OnTable(index: %u, elem_type: %s, %s)\n", index, + get_type_name(elem_type), buf); + return reader->OnTable(index, elem_type, elem_limits); +} + +Result BinaryReaderLogging::OnMemory(uint32_t index, + const Limits* page_limits) { + char buf[100]; + sprint_limits(buf, sizeof(buf), page_limits); + LOGF("OnMemory(index: %u, %s)\n", index, buf); + return reader->OnMemory(index, page_limits); +} + +Result BinaryReaderLogging::BeginGlobal(uint32_t index, + Type type, + bool mutable_) { + LOGF("BeginGlobal(index: %u, type: %s, mutable: %s)\n", index, + get_type_name(type), mutable_ ? "true" : "false"); + return reader->BeginGlobal(index, type, mutable_); +} + +Result BinaryReaderLogging::OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name) { + LOGF("OnExport(index: %u, kind: %s, item_index: %u, name: \"" PRIstringslice + "\")\n", + index, get_kind_name(kind), item_index, + WABT_PRINTF_STRING_SLICE_ARG(name)); + return reader->OnExport(index, kind, item_index, name); +} + +Result BinaryReaderLogging::OnLocalDecl(uint32_t decl_index, + uint32_t count, + Type type) { + LOGF("OnLocalDecl(index: %u, count: %u, type: %s)\n", decl_index, count, + get_type_name(type)); + return reader->OnLocalDecl(decl_index, count, type); +} + +Result BinaryReaderLogging::OnBlockExpr(uint32_t num_types, Type* sig_types) { + LOGF("OnBlockExpr(sig: "); + LogTypes(num_types, sig_types); + LOGF_NOINDENT(")\n"); + return reader->OnBlockExpr(num_types, sig_types); +} + +Result BinaryReaderLogging::OnBrExpr(uint32_t depth) { + LOGF("OnBrExpr(depth: %u)\n", depth); + return reader->OnBrExpr(depth); +} + +Result BinaryReaderLogging::OnBrIfExpr(uint32_t depth) { + LOGF("OnBrIfExpr(depth: %u)\n", depth); + return reader->OnBrIfExpr(depth); +} + +Result BinaryReaderLogging::OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth) { + LOGF("OnBrTableExpr(num_targets: %u, depths: [", num_targets); + for (uint32_t i = 0; i < num_targets; ++i) { + LOGF_NOINDENT("%u", target_depths[i]); + if (i != num_targets - 1) + LOGF_NOINDENT(", "); + } + LOGF_NOINDENT("], default: %u)\n", default_target_depth); + return reader->OnBrTableExpr(num_targets, target_depths, + default_target_depth); +} + +Result BinaryReaderLogging::OnF32ConstExpr(uint32_t value_bits) { + float value; + memcpy(&value, &value_bits, sizeof(value)); + LOGF("OnF32ConstExpr(%g (0x04%x))\n", value, value_bits); + return reader->OnF32ConstExpr(value_bits); +} + +Result BinaryReaderLogging::OnF64ConstExpr(uint64_t value_bits) { + double value; + memcpy(&value, &value_bits, sizeof(value)); + LOGF("OnF64ConstExpr(%g (0x08%" PRIx64 "))\n", value, value_bits); + return reader->OnF64ConstExpr(value_bits); +} + +Result BinaryReaderLogging::OnI32ConstExpr(uint32_t value) { + LOGF("OnI32ConstExpr(%u (0x%x))\n", value, value); + return reader->OnI32ConstExpr(value); +} + +Result BinaryReaderLogging::OnI64ConstExpr(uint64_t value) { + LOGF("OnI64ConstExpr(%" PRIu64 " (0x%" PRIx64 "))\n", value, value); + return reader->OnI64ConstExpr(value); +} + +Result BinaryReaderLogging::OnIfExpr(uint32_t num_types, Type* sig_types) { + LOGF("OnIfExpr(sig: "); + LogTypes(num_types, sig_types); + LOGF_NOINDENT(")\n"); + return reader->OnIfExpr(num_types, sig_types); +} + +Result BinaryReaderLogging::OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { + LOGF("OnLoadExpr(opcode: \"%s\" (%u), align log2: %u, offset: %u)\n", + get_opcode_name(opcode), static_cast<unsigned>(opcode), alignment_log2, + offset); + return reader->OnLoadExpr(opcode, alignment_log2, offset); +} + +Result BinaryReaderLogging::OnLoopExpr(uint32_t num_types, Type* sig_types) { + LOGF("OnLoopExpr(sig: "); + LogTypes(num_types, sig_types); + LOGF_NOINDENT(")\n"); + return reader->OnLoopExpr(num_types, sig_types); +} + +Result BinaryReaderLogging::OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { + LOGF("OnStoreExpr(opcode: \"%s\" (%u), align log2: %u, offset: %u)\n", + get_opcode_name(opcode), static_cast<unsigned>(opcode), alignment_log2, + offset); + return reader->OnStoreExpr(opcode, alignment_log2, offset); +} + +Result BinaryReaderLogging::OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size) { + LOGF("OnDataSegmentData(index:%u, size:%u)\n", index, size); + return reader->OnDataSegmentData(index, data, size); +} + +Result BinaryReaderLogging::OnFunctionNameSubsection(uint32_t index, + uint32_t name_type, + uint32_t subsection_size) { + LOGF("OnFunctionNameSubsection(index:%u, nametype:%u, size:%u)\n", index, + name_type, subsection_size); + return reader->OnFunctionNameSubsection(index, name_type, subsection_size); +} + +Result BinaryReaderLogging::OnFunctionName(uint32_t index, StringSlice name) { + LOGF("OnFunctionName(index: %u, name: \"" PRIstringslice "\")\n", index, + WABT_PRINTF_STRING_SLICE_ARG(name)); + return reader->OnFunctionName(index, name); +} + +Result BinaryReaderLogging::OnLocalNameSubsection(uint32_t index, + uint32_t name_type, + uint32_t subsection_size) { + LOGF("OnLocalNameSubsection(index:%u, nametype:%u, size:%u)\n", index, + name_type, subsection_size); + return reader->OnLocalNameSubsection(index, name_type, subsection_size); +} + +Result BinaryReaderLogging::OnLocalName(uint32_t func_index, + uint32_t local_index, + StringSlice name) { + LOGF("OnLocalName(func_index: %u, local_index: %u, name: \"" PRIstringslice + "\")\n", + func_index, local_index, WABT_PRINTF_STRING_SLICE_ARG(name)); + return reader->OnLocalName(func_index, local_index, name); +} + +Result BinaryReaderLogging::OnInitExprF32ConstExpr(uint32_t index, + uint32_t value_bits) { + float value; + memcpy(&value, &value_bits, sizeof(value)); + LOGF("OnInitExprF32ConstExpr(index: %u, value: %g (0x04%x))\n", index, value, + value_bits); + return reader->OnInitExprF32ConstExpr(index, value_bits); +} + +Result BinaryReaderLogging::OnInitExprF64ConstExpr(uint32_t index, + uint64_t value_bits) { + double value; + memcpy(&value, &value_bits, sizeof(value)); + LOGF("OnInitExprF64ConstExpr(index: %u value: %g (0x08%" PRIx64 "))\n", index, + value, value_bits); + return reader->OnInitExprF64ConstExpr(index, value_bits); +} + +Result BinaryReaderLogging::OnInitExprI32ConstExpr(uint32_t index, + uint32_t value) { + LOGF("OnInitExprI32ConstExpr(index: %u, value: %u)\n", index, value); + return reader->OnInitExprI32ConstExpr(index, value); +} + +Result BinaryReaderLogging::OnInitExprI64ConstExpr(uint32_t index, + uint64_t value) { + LOGF("OnInitExprI64ConstExpr(index: %u, value: %" PRIu64 ")\n", index, value); + return reader->OnInitExprI64ConstExpr(index, value); +} + +Result BinaryReaderLogging::OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name) { + LOGF("OnRelocCount(count: %d, section: %s, section_name: " PRIstringslice + ")\n", + count, get_section_name(section_code), + WABT_PRINTF_STRING_SLICE_ARG(section_name)); + return reader->OnRelocCount(count, section_code, section_name); +} + +Result BinaryReaderLogging::OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend) { + LOGF("OnReloc(type: %s, offset: %u, index: %u, addend: %d)\n", + get_reloc_type_name(type), offset, index, addend); + return reader->OnReloc(type, offset, index, addend); +} + +#define DEFINE_BEGIN(name) \ + Result BinaryReaderLogging::name(uint32_t size) { \ + LOGF(#name "(%u)\n", size); \ + Indent(); \ + return reader->name(size); \ + } + +#define DEFINE_END(name) \ + Result BinaryReaderLogging::name() { \ + Dedent(); \ + LOGF(#name "\n"); \ + return reader->name(); \ + } + +#define DEFINE_UINT32(name) \ + Result BinaryReaderLogging::name(uint32_t value) { \ + LOGF(#name "(%u)\n", value); \ + return reader->name(value); \ + } + +#define DEFINE_UINT32_DESC(name, desc) \ + Result BinaryReaderLogging::name(uint32_t value) { \ + LOGF(#name "(" desc ": %u)\n", value); \ + return reader->name(value); \ + } + +#define DEFINE_UINT32_UINT32(name, desc0, desc1) \ + Result BinaryReaderLogging::name(uint32_t value0, uint32_t value1) { \ + LOGF(#name "(" desc0 ": %u, " desc1 ": %u)\n", value0, value1); \ + return reader->name(value0, value1); \ + } + +#define DEFINE_OPCODE(name) \ + Result BinaryReaderLogging::name(Opcode opcode) { \ + LOGF(#name "(\"%s\" (%u))\n", get_opcode_name(opcode), \ + static_cast<unsigned>(opcode)); \ + return reader->name(opcode); \ + } + +#define DEFINE0(name) \ + Result BinaryReaderLogging::name() { \ + LOGF(#name "\n"); \ + return reader->name(); \ + } + +DEFINE_END(EndModule) + +DEFINE_END(EndCustomSection) + +DEFINE_BEGIN(BeginTypeSection) +DEFINE_UINT32(OnTypeCount) +DEFINE_END(EndTypeSection) + +DEFINE_BEGIN(BeginImportSection) +DEFINE_UINT32(OnImportCount) +DEFINE_END(EndImportSection) + +DEFINE_BEGIN(BeginFunctionSection) +DEFINE_UINT32(OnFunctionCount) +DEFINE_UINT32_UINT32(OnFunction, "index", "sig_index") +DEFINE_END(EndFunctionSection) + +DEFINE_BEGIN(BeginTableSection) +DEFINE_UINT32(OnTableCount) +DEFINE_END(EndTableSection) + +DEFINE_BEGIN(BeginMemorySection) +DEFINE_UINT32(OnMemoryCount) +DEFINE_END(EndMemorySection) + +DEFINE_BEGIN(BeginGlobalSection) +DEFINE_UINT32(OnGlobalCount) +DEFINE_UINT32(BeginGlobalInitExpr) +DEFINE_UINT32(EndGlobalInitExpr) +DEFINE_UINT32(EndGlobal) +DEFINE_END(EndGlobalSection) + +DEFINE_BEGIN(BeginExportSection) +DEFINE_UINT32(OnExportCount) +DEFINE_END(EndExportSection) + +DEFINE_BEGIN(BeginStartSection) +DEFINE_UINT32(OnStartFunction) +DEFINE_END(EndStartSection) + +DEFINE_BEGIN(BeginCodeSection) +DEFINE_UINT32(OnFunctionBodyCount) +DEFINE_UINT32(BeginFunctionBody) +DEFINE_UINT32(EndFunctionBody) +DEFINE_UINT32(OnLocalDeclCount) +DEFINE_OPCODE(OnBinaryExpr) +DEFINE_UINT32_DESC(OnCallExpr, "func_index") +DEFINE_UINT32_DESC(OnCallIndirectExpr, "sig_index") +DEFINE_OPCODE(OnCompareExpr) +DEFINE_OPCODE(OnConvertExpr) +DEFINE0(OnCurrentMemoryExpr) +DEFINE0(OnDropExpr) +DEFINE0(OnElseExpr) +DEFINE0(OnEndExpr) +DEFINE_UINT32_DESC(OnGetGlobalExpr, "index") +DEFINE_UINT32_DESC(OnGetLocalExpr, "index") +DEFINE0(OnGrowMemoryExpr) +DEFINE0(OnNopExpr) +DEFINE0(OnReturnExpr) +DEFINE0(OnSelectExpr) +DEFINE_UINT32_DESC(OnSetGlobalExpr, "index") +DEFINE_UINT32_DESC(OnSetLocalExpr, "index") +DEFINE_UINT32_DESC(OnTeeLocalExpr, "index") +DEFINE0(OnUnreachableExpr) +DEFINE_OPCODE(OnUnaryExpr) +DEFINE_END(EndCodeSection) + +DEFINE_BEGIN(BeginElemSection) +DEFINE_UINT32(OnElemSegmentCount) +DEFINE_UINT32_UINT32(BeginElemSegment, "index", "table_index") +DEFINE_UINT32(BeginElemSegmentInitExpr) +DEFINE_UINT32(EndElemSegmentInitExpr) +DEFINE_UINT32_UINT32(OnElemSegmentFunctionIndexCount, "index", "count") +DEFINE_UINT32_UINT32(OnElemSegmentFunctionIndex, "index", "func_index") +DEFINE_UINT32(EndElemSegment) +DEFINE_END(EndElemSection) + +DEFINE_BEGIN(BeginDataSection) +DEFINE_UINT32(OnDataSegmentCount) +DEFINE_UINT32_UINT32(BeginDataSegment, "index", "memory_index") +DEFINE_UINT32(BeginDataSegmentInitExpr) +DEFINE_UINT32(EndDataSegmentInitExpr) +DEFINE_UINT32(EndDataSegment) +DEFINE_END(EndDataSection) + +DEFINE_BEGIN(BeginNamesSection) +DEFINE_UINT32(OnFunctionNamesCount) +DEFINE_UINT32(OnLocalNameFunctionCount) +DEFINE_UINT32_UINT32(OnLocalNameLocalCount, "index", "count") +DEFINE_END(EndNamesSection) + +DEFINE_BEGIN(BeginRelocSection) +DEFINE_END(EndRelocSection) +DEFINE_UINT32_UINT32(OnInitExprGetGlobalExpr, "index", "global_index") + +// We don't need to log these (the individual opcodes are logged instead), but +// we still need to forward the calls. +Result BinaryReaderLogging::OnOpcode(Opcode opcode) { + return reader->OnOpcode(opcode); +} + +Result BinaryReaderLogging::OnOpcodeBare() { + return reader->OnOpcodeBare(); +} + +Result BinaryReaderLogging::OnOpcodeUint32(uint32_t value) { + return reader->OnOpcodeUint32(value); +} + +Result BinaryReaderLogging::OnOpcodeUint32Uint32(uint32_t value, + uint32_t value2) { + return reader->OnOpcodeUint32Uint32(value, value2); +} + +Result BinaryReaderLogging::OnOpcodeUint64(uint64_t value) { + return reader->OnOpcodeUint64(value); +} + +Result BinaryReaderLogging::OnOpcodeF32(uint32_t value) { + return reader->OnOpcodeF32(value); +} + +Result BinaryReaderLogging::OnOpcodeF64(uint64_t value) { + return reader->OnOpcodeF64(value); +} + +Result BinaryReaderLogging::OnOpcodeBlockSig(uint32_t num_types, + Type* sig_types) { + return reader->OnOpcodeBlockSig(num_types, sig_types); +} + +Result BinaryReaderLogging::OnEndFunc() { + return reader->OnEndFunc(); +} + +} // namespace wabt diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h new file mode 100644 index 00000000..021420cb --- /dev/null +++ b/src/binary-reader-logging.h @@ -0,0 +1,242 @@ +/* + * Copyright 2017 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. + */ + +#ifndef WABT_BINARY_READER_LOGGING_H_ +#define WABT_BINARY_READER_LOGGING_H_ + +#include "binary-reader.h" + +namespace wabt { + +struct Stream; + +class BinaryReaderLogging : public BinaryReader { + public: + BinaryReaderLogging(Stream*, BinaryReader* forward); + + virtual bool OnError(const char* message); + virtual void OnSetState(const State* s); + + virtual Result BeginModule(uint32_t version); + virtual Result EndModule(); + + virtual Result BeginSection(BinarySection section_type, uint32_t size); + + virtual Result BeginCustomSection(uint32_t size, StringSlice section_name); + virtual Result EndCustomSection(); + + virtual Result BeginTypeSection(uint32_t size); + virtual Result OnTypeCount(uint32_t count); + virtual Result OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types); + virtual Result EndTypeSection(); + + virtual Result BeginImportSection(uint32_t size); + virtual Result OnImportCount(uint32_t count); + virtual Result OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name); + virtual Result OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index); + virtual Result OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits); + virtual Result OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits); + virtual Result OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_); + virtual Result EndImportSection(); + + virtual Result BeginFunctionSection(uint32_t size); + virtual Result OnFunctionCount(uint32_t count); + virtual Result OnFunction(uint32_t index, uint32_t sig_index); + virtual Result EndFunctionSection(); + + virtual Result BeginTableSection(uint32_t size); + virtual Result OnTableCount(uint32_t count); + virtual Result OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits); + virtual Result EndTableSection(); + + virtual Result BeginMemorySection(uint32_t size); + virtual Result OnMemoryCount(uint32_t count); + virtual Result OnMemory(uint32_t index, const Limits* limits); + virtual Result EndMemorySection(); + + virtual Result BeginGlobalSection(uint32_t size); + virtual Result OnGlobalCount(uint32_t count); + virtual Result BeginGlobal(uint32_t index, Type type, bool mutable_); + virtual Result BeginGlobalInitExpr(uint32_t index); + virtual Result EndGlobalInitExpr(uint32_t index); + virtual Result EndGlobal(uint32_t index); + virtual Result EndGlobalSection(); + + virtual Result BeginExportSection(uint32_t size); + virtual Result OnExportCount(uint32_t count); + virtual Result OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name); + virtual Result EndExportSection(); + + virtual Result BeginStartSection(uint32_t size); + virtual Result OnStartFunction(uint32_t func_index); + virtual Result EndStartSection(); + + virtual Result BeginCodeSection(uint32_t size); + virtual Result OnFunctionBodyCount(uint32_t count); + virtual Result BeginFunctionBody(uint32_t index); + virtual Result OnLocalDeclCount(uint32_t count); + virtual Result OnLocalDecl(uint32_t decl_index, uint32_t count, Type type); + + virtual Result OnOpcode(Opcode opcode); + virtual Result OnOpcodeBare(); + virtual Result OnOpcodeUint32(uint32_t value); + virtual Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2); + virtual Result OnOpcodeUint64(uint64_t value); + virtual Result OnOpcodeF32(uint32_t value); + virtual Result OnOpcodeF64(uint64_t value); + virtual Result OnOpcodeBlockSig(uint32_t num_types, Type* sig_types); + virtual Result OnBinaryExpr(Opcode opcode); + virtual Result OnBlockExpr(uint32_t num_types, Type* sig_types); + virtual Result OnBrExpr(uint32_t depth); + virtual Result OnBrIfExpr(uint32_t depth); + virtual Result OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth); + virtual Result OnCallExpr(uint32_t func_index); + virtual Result OnCallIndirectExpr(uint32_t sig_index); + virtual Result OnCompareExpr(Opcode opcode); + virtual Result OnConvertExpr(Opcode opcode); + virtual Result OnCurrentMemoryExpr(); + virtual Result OnDropExpr(); + virtual Result OnElseExpr(); + virtual Result OnEndExpr(); + virtual Result OnEndFunc(); + virtual Result OnF32ConstExpr(uint32_t value_bits); + virtual Result OnF64ConstExpr(uint64_t value_bits); + virtual Result OnGetGlobalExpr(uint32_t global_index); + virtual Result OnGetLocalExpr(uint32_t local_index); + virtual Result OnGrowMemoryExpr(); + virtual Result OnI32ConstExpr(uint32_t value); + virtual Result OnI64ConstExpr(uint64_t value); + virtual Result OnIfExpr(uint32_t num_types, Type* sig_types); + virtual Result OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset); + virtual Result OnLoopExpr(uint32_t num_types, Type* sig_types); + virtual Result OnNopExpr(); + virtual Result OnReturnExpr(); + virtual Result OnSelectExpr(); + virtual Result OnSetGlobalExpr(uint32_t global_index); + virtual Result OnSetLocalExpr(uint32_t local_index); + virtual Result OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset); + virtual Result OnTeeLocalExpr(uint32_t local_index); + virtual Result OnUnaryExpr(Opcode opcode); + virtual Result OnUnreachableExpr(); + virtual Result EndFunctionBody(uint32_t index); + virtual Result EndCodeSection(); + + virtual Result BeginElemSection(uint32_t size); + virtual Result OnElemSegmentCount(uint32_t count); + virtual Result BeginElemSegment(uint32_t index, uint32_t table_index); + virtual Result BeginElemSegmentInitExpr(uint32_t index); + virtual Result EndElemSegmentInitExpr(uint32_t index); + virtual Result OnElemSegmentFunctionIndexCount(uint32_t index, + uint32_t count); + virtual Result OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index); + virtual Result EndElemSegment(uint32_t index); + virtual Result EndElemSection(); + + virtual Result BeginDataSection(uint32_t size); + virtual Result OnDataSegmentCount(uint32_t count); + virtual Result BeginDataSegment(uint32_t index, uint32_t memory_index); + virtual Result BeginDataSegmentInitExpr(uint32_t index); + virtual Result EndDataSegmentInitExpr(uint32_t index); + virtual Result OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size); + virtual Result EndDataSegment(uint32_t index); + virtual Result EndDataSection(); + + virtual Result BeginNamesSection(uint32_t size); + virtual Result OnFunctionNameSubsection(uint32_t index, + uint32_t name_type, + uint32_t subsection_size); + virtual Result OnFunctionNamesCount(uint32_t num_functions); + virtual Result OnFunctionName(uint32_t function_index, + StringSlice function_name); + virtual Result OnLocalNameSubsection(uint32_t index, + uint32_t name_type, + uint32_t subsection_size); + virtual Result OnLocalNameFunctionCount(uint32_t num_functions); + virtual Result OnLocalNameLocalCount(uint32_t function_index, + uint32_t num_locals); + virtual Result OnLocalName(uint32_t function_index, + uint32_t local_index, + StringSlice local_name); + virtual Result EndNamesSection(); + + virtual Result BeginRelocSection(uint32_t size); + virtual Result OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name); + virtual Result OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend); + virtual Result EndRelocSection(); + + virtual Result OnInitExprF32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprF64ConstExpr(uint32_t index, uint64_t value); + virtual Result OnInitExprGetGlobalExpr(uint32_t index, uint32_t global_index); + virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprI64ConstExpr(uint32_t index, uint64_t value); + + private: + void Indent(); + void Dedent(); + void WriteIndent(); + void LogTypes(uint32_t type_count, Type* types); + + Stream* stream; + BinaryReader* reader; + int indent; +}; + +} // namespace wabt + +#endif // WABT_BINARY_READER_LOGGING_H_ diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h new file mode 100644 index 00000000..c00614cc --- /dev/null +++ b/src/binary-reader-nop.h @@ -0,0 +1,329 @@ +/* + * 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. + */ + +#ifndef WABT_BINARY_READER_NOP_H_ +#define WABT_BINARY_READER_NOP_H_ + +#include "binary-reader.h" + +namespace wabt { + +class BinaryReaderNop : public BinaryReader { + public: + virtual bool OnError(const char* message) { return false; } + + /* Module */ + virtual Result BeginModule(uint32_t version) { return Result::Ok; } + virtual Result EndModule() { return Result::Ok; } + + virtual Result BeginSection(BinarySection section_type, uint32_t size) { + return Result::Ok; + } + + /* Custom section */ + virtual Result BeginCustomSection(uint32_t size, StringSlice section_name) { + return Result::Ok; + } + virtual Result EndCustomSection() { return Result::Ok; } + + /* Type section */ + virtual Result BeginTypeSection(uint32_t size) { return Result::Ok; } + virtual Result OnTypeCount(uint32_t count) { return Result::Ok; } + virtual Result OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types) { + return Result::Ok; + } + virtual Result EndTypeSection() { return Result::Ok; } + + /* Import section */ + virtual Result BeginImportSection(uint32_t size) { return Result::Ok; } + virtual Result OnImportCount(uint32_t count) { return Result::Ok; } + virtual Result OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name) { + return Result::Ok; + } + virtual Result OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index) { + return Result::Ok; + } + virtual Result OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits) { + return Result::Ok; + } + virtual Result OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits) { + return Result::Ok; + } + virtual Result OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_) { + return Result::Ok; + } + virtual Result EndImportSection() { return Result::Ok; } + + /* Function section */ + virtual Result BeginFunctionSection(uint32_t size) { return Result::Ok; } + virtual Result OnFunctionCount(uint32_t count) { return Result::Ok; } + virtual Result OnFunction(uint32_t index, uint32_t sig_index) { + return Result::Ok; + } + virtual Result EndFunctionSection() { return Result::Ok; } + + /* Table section */ + virtual Result BeginTableSection(uint32_t size) { return Result::Ok; } + virtual Result OnTableCount(uint32_t count) { return Result::Ok; } + virtual Result OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits) { + return Result::Ok; + } + virtual Result EndTableSection() { return Result::Ok; } + + /* Memory section */ + virtual Result BeginMemorySection(uint32_t size) { return Result::Ok; } + virtual Result OnMemoryCount(uint32_t count) { return Result::Ok; } + virtual Result OnMemory(uint32_t index, const Limits* limits) { + return Result::Ok; + } + virtual Result EndMemorySection() { return Result::Ok; } + + /* Global section */ + virtual Result BeginGlobalSection(uint32_t size) { return Result::Ok; } + virtual Result OnGlobalCount(uint32_t count) { return Result::Ok; } + virtual Result BeginGlobal(uint32_t index, Type type, bool mutable_) { + return Result::Ok; + } + virtual Result BeginGlobalInitExpr(uint32_t index) { return Result::Ok; } + virtual Result EndGlobalInitExpr(uint32_t index) { return Result::Ok; } + virtual Result EndGlobal(uint32_t index) { return Result::Ok; } + virtual Result EndGlobalSection() { return Result::Ok; } + + /* Exports section */ + virtual Result BeginExportSection(uint32_t size) { return Result::Ok; } + virtual Result OnExportCount(uint32_t count) { return Result::Ok; } + virtual Result OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name) { + return Result::Ok; + } + virtual Result EndExportSection() { return Result::Ok; } + + /* Start section */ + virtual Result BeginStartSection(uint32_t size) { return Result::Ok; } + virtual Result OnStartFunction(uint32_t func_index) { return Result::Ok; } + virtual Result EndStartSection() { return Result::Ok; } + + /* Code section */ + virtual Result BeginCodeSection(uint32_t size) { return Result::Ok; } + virtual Result OnFunctionBodyCount(uint32_t count) { return Result::Ok; } + virtual Result BeginFunctionBody(uint32_t index) { return Result::Ok; } + virtual Result OnLocalDeclCount(uint32_t count) { return Result::Ok; } + virtual Result OnLocalDecl(uint32_t decl_index, uint32_t count, Type type) { + return Result::Ok; + } + + /* Function expressions; called between BeginFunctionBody and + EndFunctionBody */ + virtual Result OnOpcode(Opcode Opcode) { return Result::Ok; } + virtual Result OnOpcodeBare() { return Result::Ok; } + virtual Result OnOpcodeUint32(uint32_t value) { return Result::Ok; } + virtual Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) { + return Result::Ok; + } + virtual Result OnOpcodeUint64(uint64_t value) { return Result::Ok; } + virtual Result OnOpcodeF32(uint32_t value) { return Result::Ok; } + virtual Result OnOpcodeF64(uint64_t value) { return Result::Ok; } + virtual Result OnOpcodeBlockSig(uint32_t num_types, Type* sig_types) { + return Result::Ok; + } + virtual Result OnBinaryExpr(Opcode opcode) { return Result::Ok; } + virtual Result OnBlockExpr(uint32_t num_types, Type* sig_types) { + return Result::Ok; + } + virtual Result OnBrExpr(uint32_t depth) { return Result::Ok; } + virtual Result OnBrIfExpr(uint32_t depth) { return Result::Ok; } + virtual Result OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth) { + return Result::Ok; + } + virtual Result OnCallExpr(uint32_t func_index) { return Result::Ok; } + virtual Result OnCallIndirectExpr(uint32_t sig_index) { return Result::Ok; } + virtual Result OnCompareExpr(Opcode opcode) { return Result::Ok; } + virtual Result OnConvertExpr(Opcode opcode) { return Result::Ok; } + virtual Result OnCurrentMemoryExpr() { return Result::Ok; } + virtual Result OnDropExpr() { return Result::Ok; } + virtual Result OnElseExpr() { return Result::Ok; } + virtual Result OnEndExpr() { return Result::Ok; } + virtual Result OnEndFunc() { return Result::Ok; } + virtual Result OnF32ConstExpr(uint32_t value_bits) { return Result::Ok; } + virtual Result OnF64ConstExpr(uint64_t value_bits) { return Result::Ok; } + virtual Result OnGetGlobalExpr(uint32_t global_index) { return Result::Ok; } + virtual Result OnGetLocalExpr(uint32_t local_index) { return Result::Ok; } + virtual Result OnGrowMemoryExpr() { return Result::Ok; } + virtual Result OnI32ConstExpr(uint32_t value) { return Result::Ok; } + virtual Result OnI64ConstExpr(uint64_t value) { return Result::Ok; } + virtual Result OnIfExpr(uint32_t num_types, Type* sig_types) { + return Result::Ok; + } + virtual Result OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { + return Result::Ok; + } + virtual Result OnLoopExpr(uint32_t num_types, Type* sig_types) { + return Result::Ok; + } + virtual Result OnNopExpr() { return Result::Ok; } + virtual Result OnReturnExpr() { return Result::Ok; } + virtual Result OnSelectExpr() { return Result::Ok; } + virtual Result OnSetGlobalExpr(uint32_t global_index) { return Result::Ok; } + virtual Result OnSetLocalExpr(uint32_t local_index) { return Result::Ok; } + virtual Result OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { + return Result::Ok; + } + virtual Result OnTeeLocalExpr(uint32_t local_index) { return Result::Ok; } + virtual Result OnUnaryExpr(Opcode opcode) { return Result::Ok; } + virtual Result OnUnreachableExpr() { return Result::Ok; } + virtual Result EndFunctionBody(uint32_t index) { return Result::Ok; } + virtual Result EndCodeSection() { return Result::Ok; } + + /* Elem section */ + virtual Result BeginElemSection(uint32_t size) { return Result::Ok; } + virtual Result OnElemSegmentCount(uint32_t count) { return Result::Ok; } + virtual Result BeginElemSegment(uint32_t index, uint32_t table_index) { + return Result::Ok; + } + virtual Result BeginElemSegmentInitExpr(uint32_t index) { return Result::Ok; } + virtual Result EndElemSegmentInitExpr(uint32_t index) { return Result::Ok; } + virtual Result OnElemSegmentFunctionIndexCount(uint32_t index, + uint32_t count) { + return Result::Ok; + } + virtual Result OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index) { + return Result::Ok; + } + virtual Result EndElemSegment(uint32_t index) { return Result::Ok; } + virtual Result EndElemSection() { return Result::Ok; } + + /* Data section */ + virtual Result BeginDataSection(uint32_t size) { return Result::Ok; } + virtual Result OnDataSegmentCount(uint32_t count) { return Result::Ok; } + virtual Result BeginDataSegment(uint32_t index, uint32_t memory_index) { + return Result::Ok; + } + virtual Result BeginDataSegmentInitExpr(uint32_t index) { return Result::Ok; } + virtual Result EndDataSegmentInitExpr(uint32_t index) { return Result::Ok; } + virtual Result OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size) { + return Result::Ok; + } + virtual Result EndDataSegment(uint32_t index) { return Result::Ok; } + virtual Result EndDataSection() { return Result::Ok; } + + /* Names section */ + virtual Result BeginNamesSection(uint32_t size) { return Result::Ok; } + virtual Result OnFunctionNameSubsection(uint32_t index, + uint32_t name_type, + uint32_t subsection_size) { + return Result::Ok; + } + virtual Result OnFunctionNamesCount(uint32_t num_functions) { + return Result::Ok; + } + virtual Result OnFunctionName(uint32_t function_index, + StringSlice function_name) { + return Result::Ok; + } + virtual Result OnLocalNameSubsection(uint32_t index, + uint32_t name_type, + uint32_t subsection_size) { + return Result::Ok; + } + virtual Result OnLocalNameFunctionCount(uint32_t num_functions) { + return Result::Ok; + } + virtual Result OnLocalNameLocalCount(uint32_t function_index, + uint32_t num_locals) { + return Result::Ok; + } + virtual Result OnLocalName(uint32_t function_index, + uint32_t local_index, + StringSlice local_name) { + return Result::Ok; + } + virtual Result EndNamesSection() { return Result::Ok; } + + /* Reloc section */ + virtual Result BeginRelocSection(uint32_t size) { return Result::Ok; } + virtual Result OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name) { + return Result::Ok; + } + virtual Result OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend) { + return Result::Ok; + } + virtual Result EndRelocSection() { return Result::Ok; } + + /* InitExpr - used by elem, data and global sections; these functions are + * only called between calls to Begin*InitExpr and End*InitExpr */ + virtual Result OnInitExprF32ConstExpr(uint32_t index, uint32_t value) { + return Result::Ok; + } + virtual Result OnInitExprF64ConstExpr(uint32_t index, uint64_t value) { + return Result::Ok; + } + virtual Result OnInitExprGetGlobalExpr(uint32_t index, + uint32_t global_index) { + return Result::Ok; + } + virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value) { + return Result::Ok; + } + virtual Result OnInitExprI64ConstExpr(uint32_t index, uint64_t value) { + return Result::Ok; + } +}; + +} // namespace wabt + +#endif /* WABT_BINARY_READER_H_ */ diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index bb251fa2..c6698289 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -23,7 +23,7 @@ #include <vector> -#include "binary-reader.h" +#include "binary-reader-nop.h" #include "literal.h" namespace wabt { @@ -32,36 +32,48 @@ namespace { typedef std::vector<uint32_t> Uint32Vector; -struct Context { - ObjdumpOptions* options; - Stream* out_stream; - const uint8_t* data; - size_t size; - Opcode current_opcode; - size_t current_opcode_offset; - size_t last_opcode_end; - int indent_level; - bool print_details; - bool header_printed; - int section_found; - +class BinaryReaderObjdumpBase : public BinaryReaderNop { + public: + BinaryReaderObjdumpBase(const uint8_t* data, + size_t size, + ObjdumpOptions* options); + + virtual Result OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name); + virtual Result OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend); + + protected: + bool ShouldPrintDetails(); + void PrintDetails(const char* fmt, ...); + + ObjdumpOptions* options = nullptr; + const uint8_t* data = nullptr; + size_t size = 0; + bool print_details = false; + BinarySection reloc_section = BinarySection::Invalid; uint32_t section_starts[kBinarySectionCount]; - BinarySection reloc_section; - - uint32_t next_reloc; }; -} // namespace +BinaryReaderObjdumpBase::BinaryReaderObjdumpBase(const uint8_t* data, + size_t size, + ObjdumpOptions* options) + : options(options), data(data), size(size) { + WABT_ZERO_MEMORY(section_starts); +} -static bool should_print_details(Context* ctx) { - if (ctx->options->mode != ObjdumpMode::Details) +bool BinaryReaderObjdumpBase::ShouldPrintDetails() { + if (options->mode != ObjdumpMode::Details) return false; - return ctx->print_details; + return print_details; } -static void WABT_PRINTF_FORMAT(2, 3) - print_details(Context* ctx, const char* fmt, ...) { - if (!should_print_details(ctx)) +void WABT_PRINTF_FORMAT(2, 3) + BinaryReaderObjdumpBase::PrintDetails(const char* fmt, ...) { + if (!ShouldPrintDetails()) return; va_list args; va_start(args, fmt); @@ -69,40 +81,224 @@ static void WABT_PRINTF_FORMAT(2, 3) va_end(args); } -static Result begin_section(BinaryReaderContext* ctx, - BinarySection section_code, - uint32_t size) { - Context* context = static_cast<Context*>(ctx->user_data); - context->section_starts[static_cast<size_t>(section_code)] = ctx->offset; +Result BinaryReaderObjdumpBase::OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name) { + reloc_section = section_code; + PrintDetails(" - section: %s\n", get_section_name(section_code)); + return Result::Ok; +} + +Result BinaryReaderObjdumpBase::OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend) { + uint32_t total_offset = + section_starts[static_cast<size_t>(reloc_section)] + offset; + PrintDetails(" - %-18s idx=%#-4x addend=%#-4x offset=%#x(file=%#x)\n", + get_reloc_type_name(type), index, addend, offset, total_offset); + return Result::Ok; +} + +class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase { + public: + BinaryReaderObjdumpPrepass(const uint8_t* data, + size_t size, + ObjdumpOptions* options); + + virtual Result OnFunctionName(uint32_t function_index, + StringSlice function_name); + virtual Result OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend); +}; + +BinaryReaderObjdumpPrepass::BinaryReaderObjdumpPrepass(const uint8_t* data, + size_t size, + ObjdumpOptions* options) + : BinaryReaderObjdumpBase(data, size, options) {} + +Result BinaryReaderObjdumpPrepass::OnFunctionName(uint32_t index, + StringSlice name) { + if (options->mode == ObjdumpMode::Prepass) { + options->function_names.resize(index + 1); + options->function_names[index] = string_slice_to_string(name); + } else { + PrintDetails(" - func[%d] " PRIstringslice "\n", index, + WABT_PRINTF_STRING_SLICE_ARG(name)); + } + return Result::Ok; +} + +Result BinaryReaderObjdumpPrepass::OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend) { + BinaryReaderObjdumpBase::OnReloc(type, offset, index, addend); + if (reloc_section == BinarySection::Code) { + options->code_relocations.emplace_back(type, offset, index, addend); + } + return Result::Ok; +} + +class BinaryReaderObjdump : public BinaryReaderObjdumpBase { + public: + BinaryReaderObjdump(const uint8_t* data, + size_t size, + ObjdumpOptions* options); + + virtual Result BeginModule(uint32_t version); + virtual Result EndModule(); + + virtual Result BeginSection(BinarySection section_type, uint32_t size); + + virtual Result BeginCustomSection(uint32_t size, StringSlice section_name); + + virtual Result OnTypeCount(uint32_t count); + virtual Result OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types); + + virtual Result OnImportCount(uint32_t count); + virtual Result OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index); + virtual Result OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits); + virtual Result OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits); + virtual Result OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_); + + virtual Result OnFunctionCount(uint32_t count); + virtual Result OnFunction(uint32_t index, uint32_t sig_index); + + virtual Result OnTableCount(uint32_t count); + virtual Result OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits); + + virtual Result OnMemoryCount(uint32_t count); + virtual Result OnMemory(uint32_t index, const Limits* limits); + + virtual Result OnGlobalCount(uint32_t count); + virtual Result BeginGlobal(uint32_t index, Type type, bool mutable_); + + virtual Result OnExportCount(uint32_t count); + virtual Result OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name); + + virtual Result OnFunctionBodyCount(uint32_t count); + virtual Result BeginFunctionBody(uint32_t index); + + virtual Result OnOpcode(Opcode Opcode); + virtual Result OnOpcodeBare(); + virtual Result OnOpcodeUint32(uint32_t value); + virtual Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2); + virtual Result OnOpcodeUint64(uint64_t value); + virtual Result OnOpcodeF32(uint32_t value); + virtual Result OnOpcodeF64(uint64_t value); + virtual Result OnOpcodeBlockSig(uint32_t num_types, Type* sig_types); + + virtual Result OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth); + virtual Result OnEndExpr(); + virtual Result OnEndFunc(); + + virtual Result OnElemSegmentCount(uint32_t count); + virtual Result BeginElemSegment(uint32_t index, uint32_t table_index); + virtual Result OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index); + + virtual Result OnDataSegmentCount(uint32_t count); + virtual Result BeginDataSegment(uint32_t index, uint32_t memory_index); + virtual Result OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size); + + virtual Result OnFunctionName(uint32_t function_index, + StringSlice function_name); + virtual Result OnLocalName(uint32_t function_index, + uint32_t local_index, + StringSlice local_name); + + virtual Result OnInitExprF32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprF64ConstExpr(uint32_t index, uint64_t value); + virtual Result OnInitExprGetGlobalExpr(uint32_t index, uint32_t global_index); + virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value); + virtual Result OnInitExprI64ConstExpr(uint32_t index, uint64_t value); + + private: + Result OnCount(uint32_t count); + void LogOpcode(const uint8_t* data, size_t data_size, const char* fmt, ...); + + Stream* out_stream = nullptr; + Opcode current_opcode = Opcode::Unreachable; + size_t current_opcode_offset = 0; + size_t last_opcode_end = 0; + int indent_level = 0; + bool header_printed = false; + int section_found = false; + uint32_t next_reloc = 0; +}; + +BinaryReaderObjdump::BinaryReaderObjdump(const uint8_t* data, + size_t size, + ObjdumpOptions* options) + : BinaryReaderObjdumpBase(data, size, options), + out_stream(init_stdout_stream()) {} + +Result BinaryReaderObjdump::BeginSection(BinarySection section_code, + uint32_t size) { + section_starts[static_cast<size_t>(section_code)] = state->offset; const char* name = get_section_name(section_code); - bool section_match = !context->options->section_name || - !strcasecmp(context->options->section_name, name); + bool section_match = + !options->section_name || !strcasecmp(options->section_name, name); if (section_match) - context->section_found = true; + section_found = true; - switch (context->options->mode) { + switch (options->mode) { case ObjdumpMode::Prepass: break; case ObjdumpMode::Headers: printf("%9s start=%#010" PRIzx " end=%#010" PRIzx " (size=%#010x) ", name, - ctx->offset, ctx->offset + size, size); + state->offset, state->offset + size, size); break; case ObjdumpMode::Details: if (section_match) { if (section_code != BinarySection::Code) printf("%s:\n", name); - context->print_details = true; + print_details = true; } else { - context->print_details = false; + print_details = false; } break; case ObjdumpMode::RawData: if (section_match) { printf("\nContents of section %s:\n", name); - write_memory_dump(context->out_stream, context->data + ctx->offset, - size, ctx->offset, PrintChars::Yes, nullptr, nullptr); + write_memory_dump(out_stream, data + state->offset, size, state->offset, + PrintChars::Yes, nullptr, nullptr); } break; case ObjdumpMode::Disassemble: @@ -111,40 +307,36 @@ static Result begin_section(BinaryReaderContext* ctx, return Result::Ok; } -static Result begin_custom_section(BinaryReaderContext* ctx, - uint32_t size, - StringSlice section_name) { - Context* context = static_cast<Context*>(ctx->user_data); - print_details(context, " - name: \"" PRIstringslice "\"\n", - WABT_PRINTF_STRING_SLICE_ARG(section_name)); - if (context->options->mode == ObjdumpMode::Headers) { +Result BinaryReaderObjdump::BeginCustomSection(uint32_t size, + StringSlice section_name) { + PrintDetails(" - name: \"" PRIstringslice "\"\n", + WABT_PRINTF_STRING_SLICE_ARG(section_name)); + if (options->mode == ObjdumpMode::Headers) { printf("\"" PRIstringslice "\"\n", WABT_PRINTF_STRING_SLICE_ARG(section_name)); } return Result::Ok; } -static Result on_count(uint32_t count, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->options->mode == ObjdumpMode::Headers) { +Result BinaryReaderObjdump::OnCount(uint32_t count) { + if (options->mode == ObjdumpMode::Headers) { printf("count: %d\n", count); } return Result::Ok; } -static Result begin_module(uint32_t version, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->options->print_header) { - const char* basename = strrchr(ctx->options->infile, '/'); +Result BinaryReaderObjdump::BeginModule(uint32_t version) { + if (options->print_header) { + const char* basename = strrchr(options->infile, '/'); if (basename) basename++; else - basename = ctx->options->infile; + basename = options->infile; printf("%s:\tfile format wasm %#08x\n", basename, version); - ctx->header_printed = true; + header_printed = true; } - switch (ctx->options->mode) { + switch (options->mode) { case ObjdumpMode::Headers: printf("\n"); printf("Sections:\n\n"); @@ -165,11 +357,10 @@ static Result begin_module(uint32_t version, void* user_data) { return Result::Ok; } -static Result end_module(void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->options->section_name) { - if (!ctx->section_found) { - printf("Section not found: %s\n", ctx->options->section_name); +Result BinaryReaderObjdump::EndModule() { + if (options->section_name) { + if (!section_found) { + printf("Section not found: %s\n", options->section_name); return Result::Error; } } @@ -177,44 +368,44 @@ static Result end_module(void* user_data) { return Result::Ok; } -static Result on_opcode(BinaryReaderContext* ctx, Opcode opcode) { - Context* context = static_cast<Context*>(ctx->user_data); +Result BinaryReaderObjdump::OnOpcode(Opcode opcode) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; - if (context->options->debug) { + if (options->debug) { const char* opcode_name = get_opcode_name(opcode); - printf("on_opcode: %#" PRIzx ": %s\n", ctx->offset, opcode_name); + printf("on_opcode: %#" PRIzx ": %s\n", state->offset, opcode_name); } - if (context->last_opcode_end) { - if (ctx->offset != context->last_opcode_end + 1) { - uint8_t missing_opcode = ctx->data[context->last_opcode_end]; + if (last_opcode_end) { + if (state->offset != last_opcode_end + 1) { + uint8_t missing_opcode = data[last_opcode_end]; const char* opcode_name = get_opcode_name(static_cast<Opcode>(missing_opcode)); fprintf(stderr, "warning: %#" PRIzx " missing opcode callback at %#" PRIzx " (%#02x=%s)\n", - ctx->offset, context->last_opcode_end + 1, - ctx->data[context->last_opcode_end], opcode_name); + state->offset, last_opcode_end + 1, data[last_opcode_end], + opcode_name); return Result::Error; } } - context->current_opcode_offset = ctx->offset; - context->current_opcode = opcode; + current_opcode_offset = state->offset; + current_opcode = opcode; return Result::Ok; } #define IMMEDIATE_OCTET_COUNT 9 -static void log_opcode(Context* ctx, - const uint8_t* data, - size_t data_size, - const char* fmt, - ...) { - size_t offset = ctx->current_opcode_offset; +void BinaryReaderObjdump::LogOpcode(const uint8_t* data, + size_t data_size, + const char* fmt, + ...) { + size_t offset = current_opcode_offset; // Print binary data printf(" %06" PRIzx ": %02x", offset - 1, - static_cast<unsigned>(ctx->current_opcode)); + static_cast<unsigned>(current_opcode)); for (size_t i = 0; i < data_size && i < IMMEDIATE_OCTET_COUNT; i++, offset++) { printf(" %02x", data[offset]); @@ -225,14 +416,14 @@ static void log_opcode(Context* ctx, printf(" | "); // Print disassemble - int indent_level = ctx->indent_level; - if (ctx->current_opcode == Opcode::Else) + int indent_level = this->indent_level; + if (current_opcode == Opcode::Else) indent_level--; for (int j = 0; j < indent_level; j++) { printf(" "); } - const char* opcode_name = get_opcode_name(ctx->current_opcode); + const char* opcode_name = get_opcode_name(current_opcode); printf("%s", opcode_name); if (fmt) { printf(" "); @@ -244,15 +435,15 @@ static void log_opcode(Context* ctx, printf("\n"); - ctx->last_opcode_end = ctx->current_opcode_offset + data_size; + last_opcode_end = current_opcode_offset + data_size; - if (ctx->options->relocs) { - if (ctx->next_reloc < ctx->options->code_relocations.size()) { - Reloc* reloc = &ctx->options->code_relocations[ctx->next_reloc]; + if (options->relocs) { + if (next_reloc < options->code_relocations.size()) { + Reloc* reloc = &options->code_relocations[next_reloc]; size_t code_start = - ctx->section_starts[static_cast<size_t>(BinarySection::Code)]; + section_starts[static_cast<size_t>(BinarySection::Code)]; size_t abs_offset = code_start + reloc->offset; - if (ctx->last_opcode_end > abs_offset) { + if (last_opcode_end > abs_offset) { printf(" %06" PRIzx ": %-18s %d", abs_offset, get_reloc_type_name(reloc->type), reloc->index); switch (reloc->type) { @@ -265,85 +456,92 @@ static void log_opcode(Context* ctx, break; } printf("\n"); - ctx->next_reloc++; + next_reloc++; } } } } -static Result on_opcode_bare(BinaryReaderContext* ctx) { - Context* context = static_cast<Context*>(ctx->user_data); - log_opcode(context, ctx->data, 0, nullptr); +Result BinaryReaderObjdump::OnOpcodeBare() { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + LogOpcode(data, 0, nullptr); return Result::Ok; } -static Result on_opcode_uint32(BinaryReaderContext* ctx, uint32_t value) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; - log_opcode(context, ctx->data, immediate_len, "%#x", value); +Result BinaryReaderObjdump::OnOpcodeUint32(uint32_t value) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; + LogOpcode(data, immediate_len, "%#x", value); return Result::Ok; } -static Result on_opcode_uint32_uint32(BinaryReaderContext* ctx, - uint32_t value, - uint32_t value2) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; - log_opcode(context, ctx->data, immediate_len, "%lu %lu", value, value2); +Result BinaryReaderObjdump::OnOpcodeUint32Uint32(uint32_t value, + uint32_t value2) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; + LogOpcode(data, immediate_len, "%lu %lu", value, value2); return Result::Ok; } -static Result on_opcode_uint64(BinaryReaderContext* ctx, uint64_t value) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; - log_opcode(context, ctx->data, immediate_len, "%d", value); +Result BinaryReaderObjdump::OnOpcodeUint64(uint64_t value) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; + LogOpcode(data, immediate_len, "%d", value); return Result::Ok; } -static Result on_opcode_f32(BinaryReaderContext* ctx, uint32_t value) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; +Result BinaryReaderObjdump::OnOpcodeF32(uint32_t value) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; char buffer[WABT_MAX_FLOAT_HEX]; write_float_hex(buffer, sizeof(buffer), value); - log_opcode(context, ctx->data, immediate_len, buffer); + LogOpcode(data, immediate_len, buffer); return Result::Ok; } -static Result on_opcode_f64(BinaryReaderContext* ctx, uint64_t value) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; +Result BinaryReaderObjdump::OnOpcodeF64(uint64_t value) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; char buffer[WABT_MAX_DOUBLE_HEX]; write_double_hex(buffer, sizeof(buffer), value); - log_opcode(context, ctx->data, immediate_len, buffer); + LogOpcode(data, immediate_len, buffer); return Result::Ok; } -Result on_br_table_expr(BinaryReaderContext* ctx, - uint32_t num_targets, - uint32_t* target_depths, - uint32_t default_target_depth) { - Context* context = static_cast<Context*>(ctx->user_data); - size_t immediate_len = ctx->offset - context->current_opcode_offset; +Result BinaryReaderObjdump::OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth) { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + size_t immediate_len = state->offset - current_opcode_offset; /* TODO(sbc): Print targets */ - log_opcode(context, ctx->data, immediate_len, nullptr); + LogOpcode(data, immediate_len, nullptr); return Result::Ok; } -static Result on_end_func(void* user_data) { - Context* context = static_cast<Context*>(user_data); - log_opcode(context, nullptr, 0, nullptr); +Result BinaryReaderObjdump::OnEndFunc() { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + LogOpcode(nullptr, 0, nullptr); return Result::Ok; } -static Result on_end_expr(void* user_data) { - Context* context = static_cast<Context*>(user_data); - context->indent_level--; - assert(context->indent_level >= 0); - log_opcode(context, nullptr, 0, nullptr); +Result BinaryReaderObjdump::OnEndExpr() { + if (options->mode != ObjdumpMode::Disassemble) + return Result::Ok; + indent_level--; + assert(indent_level >= 0); + LogOpcode(nullptr, 0, nullptr); return Result::Ok; } -static const char* type_name(Type type) { +const char* type_name(Type type) { switch (type) { case Type::I32: return "i32"; @@ -363,27 +561,26 @@ static const char* type_name(Type type) { } } -static Result on_opcode_block_sig(BinaryReaderContext* ctx, - uint32_t num_types, - Type* sig_types) { - Context* context = static_cast<Context*>(ctx->user_data); +Result BinaryReaderObjdump::OnOpcodeBlockSig(uint32_t num_types, + Type* sig_types) { if (num_types) - log_opcode(context, ctx->data, 1, "%s", type_name(*sig_types)); + LogOpcode(data, 1, "%s", type_name(*sig_types)); else - log_opcode(context, ctx->data, 1, nullptr); - context->indent_level++; + LogOpcode(data, 1, nullptr); + indent_level++; return Result::Ok; } -static Result on_signature(uint32_t index, - uint32_t param_count, - Type* param_types, - uint32_t result_count, - Type* result_types, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderObjdump::OnTypeCount(uint32_t count) { + return OnCount(count); +} - if (!should_print_details(ctx)) +Result BinaryReaderObjdump::OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types) { + if (!ShouldPrintDetails()) return Result::Ok; printf(" - [%d] (", index); for (uint32_t i = 0; i < param_count; i++) { @@ -401,380 +598,245 @@ static Result on_signature(uint32_t index, return Result::Ok; } -static Result on_function_signature(uint32_t index, - uint32_t sig_index, - void* user_data) { - print_details(static_cast<Context*>(user_data), " - func[%d] sig=%d\n", index, - sig_index); +Result BinaryReaderObjdump::OnFunctionCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnFunction(uint32_t index, uint32_t sig_index) { + PrintDetails(" - func[%d] sig=%d\n", index, sig_index); return Result::Ok; } -static Result begin_function_body(BinaryReaderContext* context, - uint32_t index) { - Context* ctx = static_cast<Context*>(context->user_data); +Result BinaryReaderObjdump::OnFunctionBodyCount(uint32_t count) { + return OnCount(count); +} - if (ctx->options->mode == ObjdumpMode::Disassemble) { - if (index < ctx->options->function_names.size() && - !ctx->options->function_names[index].empty()) - printf("%06" PRIzx " <%s>:\n", context->offset, - ctx->options->function_names[index].c_str()); +Result BinaryReaderObjdump::BeginFunctionBody(uint32_t index) { + if (options->mode == ObjdumpMode::Disassemble) { + if (index < options->function_names.size() && + !options->function_names[index].empty()) + printf("%06" PRIzx " <%s>:\n", state->offset, + options->function_names[index].c_str()); else - printf("%06" PRIzx " func[%d]:\n", context->offset, index); + printf("%06" PRIzx " func[%d]:\n", state->offset, index); } - ctx->last_opcode_end = 0; + last_opcode_end = 0; return Result::Ok; } -static Result on_import_func(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t func_index, - uint32_t sig_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, - " - func[%d] sig=%d <- " PRIstringslice "." PRIstringslice "\n", - func_index, sig_index, - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); +Result BinaryReaderObjdump::OnImportCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index) { + PrintDetails(" - func[%d] sig=%d <- " PRIstringslice "." PRIstringslice "\n", + func_index, sig_index, WABT_PRINTF_STRING_SLICE_ARG(module_name), + WABT_PRINTF_STRING_SLICE_ARG(field_name)); return Result::Ok; } -static Result on_import_table(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t table_index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details( - ctx, " - " PRIstringslice "." PRIstringslice - " -> table elem_type=%s init=%" PRId64 " max=%" PRId64 "\n", - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name), - get_type_name(elem_type), elem_limits->initial, elem_limits->max); +Result BinaryReaderObjdump::OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t table_index, + Type elem_type, + const Limits* elem_limits) { + PrintDetails(" - " PRIstringslice "." PRIstringslice + " -> table elem_type=%s init=%" PRId64 " max=%" PRId64 "\n", + WABT_PRINTF_STRING_SLICE_ARG(module_name), + WABT_PRINTF_STRING_SLICE_ARG(field_name), + get_type_name(elem_type), elem_limits->initial, + elem_limits->max); return Result::Ok; } -static Result on_import_memory(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t memory_index, - const Limits* page_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - " PRIstringslice "." PRIstringslice " -> memory\n", - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); +Result BinaryReaderObjdump::OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits) { + PrintDetails(" - " PRIstringslice "." PRIstringslice " -> memory\n", + WABT_PRINTF_STRING_SLICE_ARG(module_name), + WABT_PRINTF_STRING_SLICE_ARG(field_name)); return Result::Ok; } -static Result on_import_global(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t global_index, - Type type, - bool mutable_, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - global[%d] %s mutable=%d <- " PRIstringslice - "." PRIstringslice "\n", - global_index, get_type_name(type), mutable_, - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); - return Result::Ok; -} - -static Result on_memory(uint32_t index, - const Limits* page_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - memory[%d] pages: initial=%" PRId64, index, - page_limits->initial); +Result BinaryReaderObjdump::OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_) { + PrintDetails(" - global[%d] %s mutable=%d <- " PRIstringslice + "." PRIstringslice "\n", + global_index, get_type_name(type), mutable_, + WABT_PRINTF_STRING_SLICE_ARG(module_name), + WABT_PRINTF_STRING_SLICE_ARG(field_name)); + return Result::Ok; +} + +Result BinaryReaderObjdump::OnMemoryCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnMemory(uint32_t index, + const Limits* page_limits) { + PrintDetails(" - memory[%d] pages: initial=%" PRId64, index, + page_limits->initial); if (page_limits->has_max) - print_details(ctx, " max=%" PRId64, page_limits->max); - print_details(ctx, "\n"); + PrintDetails(" max=%" PRId64, page_limits->max); + PrintDetails("\n"); return Result::Ok; } -static Result on_table(uint32_t index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - table[%d] type=%s initial=%" PRId64, index, - get_type_name(elem_type), elem_limits->initial); +Result BinaryReaderObjdump::OnTableCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits) { + PrintDetails(" - table[%d] type=%s initial=%" PRId64, index, + get_type_name(elem_type), elem_limits->initial); if (elem_limits->has_max) - print_details(ctx, " max=%" PRId64, elem_limits->max); - print_details(ctx, "\n"); + PrintDetails(" max=%" PRId64, elem_limits->max); + PrintDetails("\n"); return Result::Ok; } -static Result on_export(uint32_t index, - ExternalKind kind, - uint32_t item_index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - %s[%d] ", get_kind_name(kind), item_index); - print_details(ctx, PRIstringslice, WABT_PRINTF_STRING_SLICE_ARG(name)); - print_details(ctx, "\n"); +Result BinaryReaderObjdump::OnExportCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name) { + PrintDetails(" - %s[%d] ", get_kind_name(kind), item_index); + PrintDetails(PRIstringslice, WABT_PRINTF_STRING_SLICE_ARG(name)); + PrintDetails("\n"); return Result::Ok; } -static Result on_elem_segment_function_index(uint32_t index, - uint32_t func_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - func[%d]\n", func_index); +Result BinaryReaderObjdump::OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index) { + PrintDetails(" - func[%d]\n", func_index); return Result::Ok; } -static Result begin_elem_segment(uint32_t index, - uint32_t table_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - segment[%d] table=%d\n", index, table_index); +Result BinaryReaderObjdump::OnElemSegmentCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::BeginElemSegment(uint32_t index, + uint32_t table_index) { + PrintDetails(" - segment[%d] table=%d\n", index, table_index); return Result::Ok; } -static Result begin_global(uint32_t index, - Type type, - bool mutable_, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - global[%d] %s mutable=%d", index, get_type_name(type), - mutable_); +Result BinaryReaderObjdump::OnGlobalCount(uint32_t count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::BeginGlobal(uint32_t index, + Type type, + bool mutable_) { + PrintDetails(" - global[%d] %s mutable=%d", index, get_type_name(type), + mutable_); return Result::Ok; } -static Result on_init_expr_f32_const_expr(uint32_t index, - uint32_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderObjdump::OnInitExprF32ConstExpr(uint32_t index, + uint32_t value) { char buffer[WABT_MAX_FLOAT_HEX]; write_float_hex(buffer, sizeof(buffer), value); - print_details(ctx, " - init f32=%s\n", buffer); + PrintDetails(" - init f32=%s\n", buffer); return Result::Ok; } -static Result on_init_expr_f64_const_expr(uint32_t index, - uint64_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderObjdump::OnInitExprF64ConstExpr(uint32_t index, + uint64_t value) { char buffer[WABT_MAX_DOUBLE_HEX]; write_float_hex(buffer, sizeof(buffer), value); - print_details(ctx, " - init f64=%s\n", buffer); + PrintDetails(" - init f64=%s\n", buffer); return Result::Ok; } -static Result on_init_expr_get_global_expr(uint32_t index, - uint32_t global_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - init global=%d\n", global_index); +Result BinaryReaderObjdump::OnInitExprGetGlobalExpr(uint32_t index, + uint32_t global_index) { + PrintDetails(" - init global=%d\n", global_index); return Result::Ok; } -static Result on_init_expr_i32_const_expr(uint32_t index, - uint32_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - init i32=%d\n", value); +Result BinaryReaderObjdump::OnInitExprI32ConstExpr(uint32_t index, + uint32_t value) { + PrintDetails(" - init i32=%d\n", value); return Result::Ok; } -static Result on_init_expr_i64_const_expr(uint32_t index, - uint64_t value, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - init i64=%" PRId64 "\n", value); +Result BinaryReaderObjdump::OnInitExprI64ConstExpr(uint32_t index, + uint64_t value) { + PrintDetails(" - init i64=%" PRId64 "\n", value); return Result::Ok; } -static Result on_function_name(uint32_t index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (ctx->options->mode == ObjdumpMode::Prepass) { - ctx->options->function_names.resize(index+1); - ctx->options->function_names[index] = string_slice_to_string(name); - } else { - print_details(ctx, " - func[%d] " PRIstringslice "\n", index, - WABT_PRINTF_STRING_SLICE_ARG(name)); - } +Result BinaryReaderObjdump::OnFunctionName(uint32_t index, StringSlice name) { + PrintDetails(" - func[%d] " PRIstringslice "\n", index, + WABT_PRINTF_STRING_SLICE_ARG(name)); return Result::Ok; } -static Result on_local_name(uint32_t func_index, - uint32_t local_index, - StringSlice name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); +Result BinaryReaderObjdump::OnLocalName(uint32_t func_index, + uint32_t local_index, + StringSlice name) { if (name.length) { - print_details(ctx, " - func[%d] local[%d] " PRIstringslice "\n", func_index, - local_index, WABT_PRINTF_STRING_SLICE_ARG(name)); + PrintDetails(" - func[%d] local[%d] " PRIstringslice "\n", func_index, + local_index, WABT_PRINTF_STRING_SLICE_ARG(name)); } return Result::Ok; } -Result on_reloc_count(uint32_t count, - BinarySection section_code, - StringSlice section_name, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - ctx->reloc_section = section_code; - print_details(ctx, " - section: %s\n", get_section_name(section_code)); - return Result::Ok; -} - -Result on_reloc(RelocType type, - uint32_t offset, - uint32_t index, - int32_t addend, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - uint32_t total_offset = - ctx->section_starts[static_cast<size_t>(ctx->reloc_section)] + offset; - print_details(ctx, " - %-18s idx=%#-4x addend=%#-4x offset=%#x(file=%#x)\n", - get_reloc_type_name(type), index, addend, offset, total_offset); - if (ctx->options->mode == ObjdumpMode::Prepass && - ctx->reloc_section == BinarySection::Code) { - ctx->options->code_relocations.emplace_back(type, offset, index, addend); - } - return Result::Ok; +Result BinaryReaderObjdump::OnDataSegmentCount(uint32_t count) { + return OnCount(count); } -static Result begin_data_segment(uint32_t index, - uint32_t memory_index, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - print_details(ctx, " - memory[%d]", memory_index); +Result BinaryReaderObjdump::BeginDataSegment(uint32_t index, + uint32_t memory_index) { + PrintDetails(" - memory[%d]", memory_index); return Result::Ok; } -static Result on_data_segment_data(uint32_t index, - const void* src_data, - uint32_t size, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (should_print_details(ctx)) { - write_memory_dump(ctx->out_stream, src_data, size, 0, PrintChars::Yes, - " - ", nullptr); +Result BinaryReaderObjdump::OnDataSegmentData(uint32_t index, + const void* src_data, + uint32_t size) { + if (ShouldPrintDetails()) { + write_memory_dump(out_stream, src_data, size, 0, PrintChars::Yes, " - ", + nullptr); } return Result::Ok; } +} // namespace + Result read_binary_objdump(const uint8_t* data, size_t size, ObjdumpOptions* options) { - Context context; - WABT_ZERO_MEMORY(context); - context.header_printed = false; - context.print_details = false; - context.section_found = false; - context.data = data; - context.size = size; - context.options = options; - context.out_stream = init_stdout_stream(); - - BinaryReader reader; - WABT_ZERO_MEMORY(reader); - if (options->mode == ObjdumpMode::Prepass) { - reader.on_function_name = on_function_name; - reader.on_reloc_count = on_reloc_count; - reader.on_reloc = on_reloc; - } else { - reader.begin_module = begin_module; - reader.end_module = end_module; - - reader.begin_section = begin_section; - - // User section - reader.begin_custom_section = begin_custom_section; - - // Signature section - reader.on_signature_count = on_count; - reader.on_signature = on_signature; - - // Import section - reader.on_import_count = on_count; - 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; - - // Function sigs section - reader.on_function_signatures_count = on_count; - reader.on_function_signature = on_function_signature; - - // Table section - reader.on_table_count = on_count; - reader.on_table = on_table; - - // Memory section - reader.on_memory_count = on_count; - reader.on_memory = on_memory; - - // Globl seciont - reader.begin_global = begin_global; - reader.on_global_count = on_count; - - // Export section - reader.on_export_count = on_count; - reader.on_export = on_export; - - // Body section - reader.on_function_bodies_count = on_count; - reader.begin_function_body = begin_function_body; - - // Elems section - reader.begin_elem_segment = begin_elem_segment; - reader.on_elem_segment_count = on_count; - reader.on_elem_segment_function_index = on_elem_segment_function_index; - - // Data section - reader.begin_data_segment = begin_data_segment; - reader.on_data_segment_data = on_data_segment_data; - reader.on_data_segment_count = on_count; - - // Known "User" sections: - // - Names section - reader.on_function_name = on_function_name; - reader.on_local_name = on_local_name; - - reader.on_reloc_count = on_reloc_count; - reader.on_reloc = on_reloc; - - 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; - 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; - } - - if (options->mode == ObjdumpMode::Disassemble) { - reader.on_opcode = on_opcode; - reader.on_opcode_bare = on_opcode_bare; - reader.on_opcode_uint32 = on_opcode_uint32; - reader.on_opcode_uint32_uint32 = on_opcode_uint32_uint32; - reader.on_opcode_uint64 = on_opcode_uint64; - reader.on_opcode_f32 = on_opcode_f32; - reader.on_opcode_f64 = on_opcode_f64; - reader.on_opcode_block_sig = on_opcode_block_sig; - reader.on_end_expr = on_end_expr; - reader.on_end_func = on_end_func; - reader.on_br_table_expr = on_br_table_expr; - } - - reader.user_data = &context; - ReadBinaryOptions read_options = WABT_READ_BINARY_OPTIONS_DEFAULT; read_options.read_debug_names = true; read_options.log_stream = options->log_stream; - return read_binary(data, size, &reader, 1, &read_options); + + if (options->mode == ObjdumpMode::Prepass) { + BinaryReaderObjdumpPrepass reader(data, size, options); + return read_binary(data, size, &reader, &read_options); + } else { + BinaryReaderObjdump reader(data, size, options); + return read_binary(data, size, &reader, &read_options); + } } } // namespace wabt diff --git a/src/binary-reader-opcnt.cc b/src/binary-reader-opcnt.cc index 8e428e1f..61c5dd19 100644 --- a/src/binary-reader-opcnt.cc +++ b/src/binary-reader-opcnt.cc @@ -22,20 +22,34 @@ #include <stdint.h> #include <stdio.h> -#include "binary-reader.h" +#include "binary-reader-nop.h" #include "common.h" namespace wabt { namespace { -struct Context { +class BinaryReaderOpcnt : public BinaryReaderNop { + public: + explicit BinaryReaderOpcnt(OpcntData* data); + + virtual Result OnOpcode(Opcode opcode); + virtual Result OnI32ConstExpr(uint32_t value); + virtual Result OnGetLocalExpr(uint32_t local_index); + virtual Result OnSetLocalExpr(uint32_t local_index); + virtual Result OnTeeLocalExpr(uint32_t local_index); + virtual Result OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset); + virtual Result OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset); + + private: OpcntData* opcnt_data; }; -} // namespace - -static Result add_int_counter_value(IntCounterVector* vec, intmax_t value) { +static Result AddIntCounterValue(IntCounterVector* vec, intmax_t value) { for (IntCounter& counter : *vec) { if (counter.value == value) { ++counter.count; @@ -46,9 +60,9 @@ static Result add_int_counter_value(IntCounterVector* vec, intmax_t value) { return Result::Ok; } -static Result add_int_pair_counter_value(IntPairCounterVector* vec, - intmax_t first, - intmax_t second) { +static Result AddIntPairCounterValue(IntPairCounterVector* vec, + intmax_t first, + intmax_t second) { for (IntPairCounter& pair : *vec) { if (pair.first == first && pair.second == second) { ++pair.count; @@ -59,9 +73,10 @@ static Result add_int_pair_counter_value(IntPairCounterVector* vec, return Result::Ok; } -static Result on_opcode(BinaryReaderContext* context, Opcode opcode) { - Context* ctx = static_cast<Context*>(context->user_data); - IntCounterVector& opcnt_vec = ctx->opcnt_data->opcode_vec; +BinaryReaderOpcnt::BinaryReaderOpcnt(OpcntData* data) : opcnt_data(data) {} + +Result BinaryReaderOpcnt::OnOpcode(Opcode opcode) { + IntCounterVector& opcnt_vec = opcnt_data->opcode_vec; while (static_cast<size_t>(opcode) >= opcnt_vec.size()) { opcnt_vec.emplace_back(opcnt_vec.size(), 0); } @@ -69,69 +84,51 @@ static Result on_opcode(BinaryReaderContext* context, Opcode opcode) { return Result::Ok; } -static Result on_i32_const_expr(uint32_t value, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - return add_int_counter_value(&ctx->opcnt_data->i32_const_vec, - static_cast<int32_t>(value)); +Result BinaryReaderOpcnt::OnI32ConstExpr(uint32_t value) { + return AddIntCounterValue(&opcnt_data->i32_const_vec, + static_cast<int32_t>(value)); } -static Result on_get_local_expr(uint32_t local_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - return add_int_counter_value(&ctx->opcnt_data->get_local_vec, local_index); +Result BinaryReaderOpcnt::OnGetLocalExpr(uint32_t local_index) { + return AddIntCounterValue(&opcnt_data->get_local_vec, local_index); } -static Result on_set_local_expr(uint32_t local_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - return add_int_counter_value(&ctx->opcnt_data->set_local_vec, local_index); +Result BinaryReaderOpcnt::OnSetLocalExpr(uint32_t local_index) { + return AddIntCounterValue(&opcnt_data->set_local_vec, local_index); } -static Result on_tee_local_expr(uint32_t local_index, void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - return add_int_counter_value(&ctx->opcnt_data->tee_local_vec, local_index); +Result BinaryReaderOpcnt::OnTeeLocalExpr(uint32_t local_index) { + return AddIntCounterValue(&opcnt_data->tee_local_vec, local_index); } -static Result on_load_expr(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (opcode == Opcode::I32Load) - return add_int_pair_counter_value(&ctx->opcnt_data->i32_load_vec, - alignment_log2, offset); +Result BinaryReaderOpcnt::OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { + if (opcode == Opcode::I32Load) { + return AddIntPairCounterValue(&opcnt_data->i32_load_vec, alignment_log2, + offset); + } return Result::Ok; } -static Result on_store_expr(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data) { - Context* ctx = static_cast<Context*>(user_data); - if (opcode == Opcode::I32Store) - return add_int_pair_counter_value(&ctx->opcnt_data->i32_store_vec, - alignment_log2, offset); +Result BinaryReaderOpcnt::OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) { + if (opcode == Opcode::I32Store) { + return AddIntPairCounterValue(&opcnt_data->i32_store_vec, alignment_log2, + offset); + } return Result::Ok; } +} // namespace + Result read_binary_opcnt(const void* data, - size_t size, - const struct ReadBinaryOptions* options, - OpcntData* opcnt_data) { - Context ctx; - WABT_ZERO_MEMORY(ctx); - ctx.opcnt_data = opcnt_data; - - BinaryReader reader; - WABT_ZERO_MEMORY(reader); - reader.user_data = &ctx; - reader.on_opcode = on_opcode; - reader.on_i32_const_expr = on_i32_const_expr; - reader.on_get_local_expr = on_get_local_expr; - reader.on_set_local_expr = on_set_local_expr; - reader.on_tee_local_expr = on_tee_local_expr; - reader.on_load_expr = on_load_expr; - reader.on_store_expr = on_store_expr; - - return read_binary(data, size, &reader, 1, options); + size_t size, + const struct ReadBinaryOptions* options, + OpcntData* opcnt_data) { + BinaryReaderOpcnt reader(opcnt_data); + return read_binary(data, size, &reader, options); } } // namespace wabt diff --git a/src/binary-reader.cc b/src/binary-reader.cc index 67ea4672..4ac9c746 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -27,6 +27,7 @@ #include <vector> #include "binary.h" +#include "binary-reader-logging.h" #include "config.h" #include "stream.h" @@ -34,70 +35,17 @@ #include <alloca.h> #endif -#define INDENT_SIZE 2 - -#define INITIAL_PARAM_TYPES_CAPACITY 128 -#define INITIAL_BR_TABLE_TARGET_CAPACITY 1000 - namespace wabt { namespace { -#define CALLBACK_CTX(member, ...) \ - RAISE_ERROR_UNLESS( \ - WABT_SUCCEEDED( \ - ctx->reader->member \ - ? ctx->reader->member(get_user_context(ctx), __VA_ARGS__) \ - : Result::Ok), \ - #member " callback failed") - -#define CALLBACK_CTX0(member) \ - RAISE_ERROR_UNLESS( \ - WABT_SUCCEEDED(ctx->reader->member \ - ? ctx->reader->member(get_user_context(ctx)) \ - : Result::Ok), \ - #member " callback failed") - -#define CALLBACK_SECTION(member, section_size) \ - CALLBACK_CTX(member, section_size) - -#define CALLBACK0(member) \ - RAISE_ERROR_UNLESS( \ - WABT_SUCCEEDED(ctx->reader->member \ - ? ctx->reader->member(ctx->reader->user_data) \ - : Result::Ok), \ - #member " callback failed") - -#define CALLBACK(member, ...) \ - RAISE_ERROR_UNLESS( \ - WABT_SUCCEEDED( \ - ctx->reader->member \ - ? ctx->reader->member(__VA_ARGS__, ctx->reader->user_data) \ - : Result::Ok), \ - #member " callback failed") - -#define FORWARD0(member) \ - return ctx->reader->member ? ctx->reader->member(ctx->reader->user_data) \ - : Result::Ok - -#define FORWARD_CTX0(member) \ - if (!ctx->reader->member) \ - return Result::Ok; \ - BinaryReaderContext new_ctx = *context; \ - new_ctx.user_data = ctx->reader->user_data; \ - return ctx->reader->member(&new_ctx); - -#define FORWARD_CTX(member, ...) \ - if (!ctx->reader->member) \ - return Result::Ok; \ - BinaryReaderContext new_ctx = *context; \ - new_ctx.user_data = ctx->reader->user_data; \ - return ctx->reader->member(&new_ctx, __VA_ARGS__); - -#define FORWARD(member, ...) \ - return ctx->reader->member \ - ? ctx->reader->member(__VA_ARGS__, ctx->reader->user_data) \ - : Result::Ok +#define CALLBACK0(member) \ + RAISE_ERROR_UNLESS(WABT_SUCCEEDED(ctx->reader->member()), \ + #member " callback failed") + +#define CALLBACK(member, ...) \ + RAISE_ERROR_UNLESS(WABT_SUCCEEDED(ctx->reader->member(__VA_ARGS__)), \ + #member " callback failed") #define RAISE_ERROR(...) raise_error(ctx, __VA_ARGS__) @@ -106,12 +54,9 @@ namespace { RAISE_ERROR(__VA_ARGS__); struct Context { - const uint8_t* data = nullptr; - size_t data_size = 0; - size_t offset = 0; size_t read_end = 0; /* Either the section end or data_size. */ - BinaryReaderContext user_ctx; BinaryReader* reader = nullptr; + BinaryReader::State state; jmp_buf error_jmp_buf; TypeVector param_types; std::vector<uint32_t> target_depths; @@ -131,43 +76,26 @@ struct Context { uint32_t num_function_bodies = 0; }; -struct LoggingContext { - Stream* stream; - BinaryReader* reader; - int indent; -}; - } // namespace -static BinaryReaderContext* get_user_context(Context* ctx) { - ctx->user_ctx.user_data = ctx->reader->user_data; - ctx->user_ctx.data = ctx->data; - ctx->user_ctx.size = ctx->data_size; - ctx->user_ctx.offset = ctx->offset; - return &ctx->user_ctx; -} - static void WABT_PRINTF_FORMAT(2, 3) raise_error(Context* ctx, const char* format, ...) { WABT_SNPRINTF_ALLOCA(buffer, length, format); - bool handled = false; - if (ctx->reader->on_error) { - handled = ctx->reader->on_error(get_user_context(ctx), buffer); - } + bool handled = ctx->reader->OnError(buffer); if (!handled) { /* Not great to just print, but we don't want to eat the error either. */ - fprintf(stderr, "*ERROR*: @0x%08zx: %s\n", ctx->offset, buffer); + fprintf(stderr, "*ERROR*: @0x%08zx: %s\n", ctx->state.offset, buffer); } longjmp(ctx->error_jmp_buf, 1); } -#define IN_SIZE(type) \ - if (ctx->offset + sizeof(type) > ctx->read_end) { \ - RAISE_ERROR("unable to read " #type ": %s", desc); \ - } \ - memcpy(out_value, ctx->data + ctx->offset, sizeof(type)); \ - ctx->offset += sizeof(type) +#define IN_SIZE(type) \ + if (ctx->state.offset + sizeof(type) > ctx->read_end) { \ + RAISE_ERROR("unable to read " #type ": %s", desc); \ + } \ + memcpy(out_value, ctx->state.data + ctx->state.offset, sizeof(type)); \ + ctx->state.offset += sizeof(type) static void in_u8(Context* ctx, uint8_t* out_value, const char* desc) { IN_SIZE(uint8_t); @@ -234,12 +162,12 @@ size_t read_u32_leb128(const uint8_t* p, } static void in_u32_leb128(Context* ctx, uint32_t* out_value, const char* desc) { - const uint8_t* p = ctx->data + ctx->offset; - const uint8_t* end = ctx->data + ctx->read_end; + const uint8_t* p = ctx->state.data + ctx->state.offset; + const uint8_t* end = ctx->state.data + ctx->read_end; size_t bytes_read = read_u32_leb128(p, end, out_value); if (!bytes_read) RAISE_ERROR("unable to read u32 leb128: %s", desc); - ctx->offset += bytes_read; + ctx->state.offset += bytes_read; } size_t read_i32_leb128(const uint8_t* p, @@ -279,54 +207,54 @@ size_t read_i32_leb128(const uint8_t* p, } static void in_i32_leb128(Context* ctx, uint32_t* out_value, const char* desc) { - const uint8_t* p = ctx->data + ctx->offset; - const uint8_t* end = ctx->data + ctx->read_end; + const uint8_t* p = ctx->state.data + ctx->state.offset; + const uint8_t* end = ctx->state.data + ctx->read_end; size_t bytes_read = read_i32_leb128(p, end, out_value); if (!bytes_read) RAISE_ERROR("unable to read i32 leb128: %s", desc); - ctx->offset += bytes_read; + ctx->state.offset += bytes_read; } static void in_i64_leb128(Context* ctx, uint64_t* out_value, const char* desc) { - const uint8_t* p = ctx->data + ctx->offset; - const uint8_t* end = ctx->data + ctx->read_end; + const uint8_t* p = ctx->state.data + ctx->state.offset; + const uint8_t* end = ctx->state.data + ctx->read_end; if (p < end && (p[0] & 0x80) == 0) { uint64_t result = LEB128_1(uint64_t); *out_value = SIGN_EXTEND(int64_t, result, 6); - ctx->offset += 1; + ctx->state.offset += 1; } else if (p + 1 < end && (p[1] & 0x80) == 0) { uint64_t result = LEB128_2(uint64_t); *out_value = SIGN_EXTEND(int64_t, result, 13); - ctx->offset += 2; + ctx->state.offset += 2; } else if (p + 2 < end && (p[2] & 0x80) == 0) { uint64_t result = LEB128_3(uint64_t); *out_value = SIGN_EXTEND(int64_t, result, 20); - ctx->offset += 3; + ctx->state.offset += 3; } else if (p + 3 < end && (p[3] & 0x80) == 0) { uint64_t result = LEB128_4(uint64_t); *out_value = SIGN_EXTEND(int64_t, result, 27); - ctx->offset += 4; + ctx->state.offset += 4; } else if (p + 4 < end && (p[4] & 0x80) == 0) { uint64_t result = LEB128_5(uint64_t); *out_value = SIGN_EXTEND(int64_t, result, 34); - ctx->offset += 5; + ctx->state.offset += 5; } else if (p + 5 < end && (p[5] & 0x80) == 0) { uint64_t result = LEB128_6(uint64_t); *out_value = SIGN_EXTEND(int64_t, result, 41); - ctx->offset += 6; + ctx->state.offset += 6; } else if (p + 6 < end && (p[6] & 0x80) == 0) { uint64_t result = LEB128_7(uint64_t); *out_value = SIGN_EXTEND(int64_t, result, 48); - ctx->offset += 7; + ctx->state.offset += 7; } else if (p + 7 < end && (p[7] & 0x80) == 0) { uint64_t result = LEB128_8(uint64_t); *out_value = SIGN_EXTEND(int64_t, result, 55); - ctx->offset += 8; + ctx->state.offset += 8; } else if (p + 8 < end && (p[8] & 0x80) == 0) { uint64_t result = LEB128_9(uint64_t); *out_value = SIGN_EXTEND(int64_t, result, 62); - ctx->offset += 9; + ctx->state.offset += 9; } else if (p + 9 < end && (p[9] & 0x80) == 0) { /* the top bits should be a sign-extension of the sign bit */ bool sign_bit_set = (p[9] & 0x1); @@ -337,7 +265,7 @@ static void in_i64_leb128(Context* ctx, uint64_t* out_value, const char* desc) { } uint64_t result = LEB128_10(uint64_t); *out_value = result; - ctx->offset += 10; + ctx->state.offset += 10; } else { /* past the end */ RAISE_ERROR("unable to read i64 leb128: %s", desc); @@ -371,12 +299,13 @@ static void in_str(Context* ctx, StringSlice* out_str, const char* desc) { uint32_t str_len = 0; in_u32_leb128(ctx, &str_len, "string length"); - if (ctx->offset + str_len > ctx->read_end) + if (ctx->state.offset + str_len > ctx->read_end) RAISE_ERROR("unable to read string: %s", desc); - out_str->start = reinterpret_cast<const char*>(ctx->data) + ctx->offset; + out_str->start = + reinterpret_cast<const char*>(ctx->state.data) + ctx->state.offset; out_str->length = str_len; - ctx->offset += str_len; + ctx->state.offset += str_len; } static void in_bytes(Context* ctx, @@ -386,12 +315,13 @@ static void in_bytes(Context* ctx, uint32_t data_size = 0; in_u32_leb128(ctx, &data_size, "data size"); - if (ctx->offset + data_size > ctx->read_end) + if (ctx->state.offset + data_size > ctx->read_end) RAISE_ERROR("unable to read data: %s", desc); - *out_data = static_cast<const uint8_t*>(ctx->data) + ctx->offset; + *out_data = + static_cast<const uint8_t*>(ctx->state.data) + ctx->state.offset; *out_data_size = data_size; - ctx->offset += data_size; + ctx->state.offset += data_size; } static bool is_valid_external_kind(uint8_t kind) { @@ -431,624 +361,6 @@ static uint32_t num_total_globals(Context* ctx) { return ctx->num_global_imports + ctx->num_globals; } -/* Logging */ - -static void indent(LoggingContext* ctx) { - ctx->indent += INDENT_SIZE; -} - -static void dedent(LoggingContext* ctx) { - ctx->indent -= INDENT_SIZE; - assert(ctx->indent >= 0); -} - -static void write_indent(LoggingContext* ctx) { - static char s_indent[] = - " " - " "; - static size_t s_indent_len = sizeof(s_indent) - 1; - size_t indent = ctx->indent; - while (indent > s_indent_len) { - write_data(ctx->stream, s_indent, s_indent_len, nullptr); - indent -= s_indent_len; - } - if (indent > 0) { - write_data(ctx->stream, s_indent, indent, nullptr); - } -} - -#define LOGF_NOINDENT(...) writef(ctx->stream, __VA_ARGS__) - -#define LOGF(...) \ - do { \ - write_indent(ctx); \ - LOGF_NOINDENT(__VA_ARGS__); \ - } while (0) - -static bool logging_on_error(BinaryReaderContext* context, - const char* message) { - LoggingContext* ctx = static_cast<LoggingContext*>(context->user_data); - // Can't use FORWARD_CTX because it returns Result by default. - if (!ctx->reader->on_error) - return false; - BinaryReaderContext new_ctx = *context; - new_ctx.user_data = ctx->reader->user_data; - return ctx->reader->on_error(&new_ctx, message); -} - -static Result logging_begin_section(BinaryReaderContext* context, - BinarySection section_type, - uint32_t size) { - LoggingContext* ctx = static_cast<LoggingContext*>(context->user_data); - FORWARD_CTX(begin_section, section_type, size); -} - -static Result logging_begin_custom_section(BinaryReaderContext* context, - uint32_t size, - StringSlice section_name) { - LoggingContext* ctx = static_cast<LoggingContext*>(context->user_data); - LOGF("begin_custom_section: '" PRIstringslice "' size=%d\n", - WABT_PRINTF_STRING_SLICE_ARG(section_name), size); - indent(ctx); - FORWARD_CTX(begin_custom_section, size, section_name); -} - -#define LOGGING_BEGIN(name) \ - static Result logging_begin_##name(BinaryReaderContext* context, \ - uint32_t size) { \ - LoggingContext* ctx = static_cast<LoggingContext*>(context->user_data); \ - LOGF("begin_" #name "(%u)\n", size); \ - indent(ctx); \ - FORWARD_CTX(begin_##name, size); \ - } - -#define LOGGING_END(name) \ - static Result logging_end_##name(BinaryReaderContext* context) { \ - LoggingContext* ctx = static_cast<LoggingContext*>(context->user_data); \ - dedent(ctx); \ - LOGF("end_" #name "\n"); \ - FORWARD_CTX0(end_##name); \ - } - -#define LOGGING_UINT32(name) \ - static Result logging_##name(uint32_t value, void* user_data) { \ - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); \ - LOGF(#name "(%u)\n", value); \ - FORWARD(name, value); \ - } - -#define LOGGING_UINT32_CTX(name) \ - static Result logging_##name(BinaryReaderContext* context, uint32_t value) { \ - LoggingContext* ctx = static_cast<LoggingContext*>(context->user_data); \ - LOGF(#name "(%u)\n", value); \ - FORWARD_CTX(name, value); \ - } - -#define LOGGING_UINT32_DESC(name, desc) \ - static Result logging_##name(uint32_t value, void* user_data) { \ - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); \ - LOGF(#name "(" desc ": %u)\n", value); \ - FORWARD(name, value); \ - } - -#define LOGGING_UINT32_UINT32(name, desc0, desc1) \ - static Result logging_##name(uint32_t value0, uint32_t value1, \ - void* user_data) { \ - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); \ - LOGF(#name "(" desc0 ": %u, " desc1 ": %u)\n", value0, value1); \ - FORWARD(name, value0, value1); \ - } - -#define LOGGING_UINT32_UINT32_CTX(name, desc0, desc1) \ - static Result logging_##name(BinaryReaderContext* context, uint32_t value0, \ - uint32_t value1) { \ - LoggingContext* ctx = static_cast<LoggingContext*>(context->user_data); \ - LOGF(#name "(" desc0 ": %u, " desc1 ": %u)\n", value0, value1); \ - FORWARD_CTX(name, value0, value1); \ - } - -#define LOGGING_OPCODE(name) \ - static Result logging_##name(Opcode opcode, void* user_data) { \ - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); \ - LOGF(#name "(\"%s\" (%u))\n", get_opcode_name(opcode), \ - static_cast<unsigned>(opcode)); \ - FORWARD(name, opcode); \ - } - -#define LOGGING0(name) \ - static Result logging_##name(void* user_data) { \ - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); \ - LOGF(#name "\n"); \ - FORWARD0(name); \ - } - -LOGGING_UINT32(begin_module) -LOGGING0(end_module) -LOGGING_END(custom_section) -LOGGING_BEGIN(signature_section) -LOGGING_UINT32(on_signature_count) -LOGGING_END(signature_section) -LOGGING_BEGIN(import_section) -LOGGING_UINT32(on_import_count) -LOGGING_END(import_section) -LOGGING_BEGIN(function_signatures_section) -LOGGING_UINT32(on_function_signatures_count) -LOGGING_UINT32_UINT32(on_function_signature, "index", "sig_index") -LOGGING_END(function_signatures_section) -LOGGING_BEGIN(table_section) -LOGGING_UINT32(on_table_count) -LOGGING_END(table_section) -LOGGING_BEGIN(memory_section) -LOGGING_UINT32(on_memory_count) -LOGGING_END(memory_section) -LOGGING_BEGIN(global_section) -LOGGING_UINT32(on_global_count) -LOGGING_UINT32(begin_global_init_expr) -LOGGING_UINT32(end_global_init_expr) -LOGGING_UINT32(end_global) -LOGGING_END(global_section) -LOGGING_BEGIN(export_section) -LOGGING_UINT32(on_export_count) -LOGGING_END(export_section) -LOGGING_BEGIN(start_section) -LOGGING_UINT32(on_start_function) -LOGGING_END(start_section) -LOGGING_BEGIN(function_bodies_section) -LOGGING_UINT32(on_function_bodies_count) -LOGGING_UINT32_CTX(begin_function_body) -LOGGING_UINT32(end_function_body) -LOGGING_UINT32(on_local_decl_count) -LOGGING_OPCODE(on_binary_expr) -LOGGING_UINT32_DESC(on_call_expr, "func_index") -LOGGING_UINT32_DESC(on_call_import_expr, "import_index") -LOGGING_UINT32_DESC(on_call_indirect_expr, "sig_index") -LOGGING_OPCODE(on_compare_expr) -LOGGING_OPCODE(on_convert_expr) -LOGGING0(on_current_memory_expr) -LOGGING0(on_drop_expr) -LOGGING0(on_else_expr) -LOGGING0(on_end_expr) -LOGGING_UINT32_DESC(on_get_global_expr, "index") -LOGGING_UINT32_DESC(on_get_local_expr, "index") -LOGGING0(on_grow_memory_expr) -LOGGING0(on_nop_expr) -LOGGING0(on_return_expr) -LOGGING0(on_select_expr) -LOGGING_UINT32_DESC(on_set_global_expr, "index") -LOGGING_UINT32_DESC(on_set_local_expr, "index") -LOGGING_UINT32_DESC(on_tee_local_expr, "index") -LOGGING0(on_unreachable_expr) -LOGGING_OPCODE(on_unary_expr) -LOGGING_END(function_bodies_section) -LOGGING_BEGIN(elem_section) -LOGGING_UINT32(on_elem_segment_count) -LOGGING_UINT32_UINT32(begin_elem_segment, "index", "table_index") -LOGGING_UINT32(begin_elem_segment_init_expr) -LOGGING_UINT32(end_elem_segment_init_expr) -LOGGING_UINT32_UINT32_CTX(on_elem_segment_function_index_count, - "index", - "count") -LOGGING_UINT32_UINT32(on_elem_segment_function_index, "index", "func_index") -LOGGING_UINT32(end_elem_segment) -LOGGING_END(elem_section) -LOGGING_BEGIN(data_section) -LOGGING_UINT32(on_data_segment_count) -LOGGING_UINT32_UINT32(begin_data_segment, "index", "memory_index") -LOGGING_UINT32(begin_data_segment_init_expr) -LOGGING_UINT32(end_data_segment_init_expr) -LOGGING_UINT32(end_data_segment) -LOGGING_END(data_section) -LOGGING_BEGIN(names_section) -LOGGING_UINT32(on_function_names_count) -LOGGING_UINT32(on_local_name_function_count) -LOGGING_UINT32_UINT32(on_local_name_local_count, "index", "count") -LOGGING_END(names_section) -LOGGING_BEGIN(reloc_section) -LOGGING_END(reloc_section) -LOGGING_UINT32_UINT32(on_init_expr_get_global_expr, "index", "global_index") - -static void sprint_limits(char* dst, size_t size, const Limits* limits) { - int result; - if (limits->has_max) { - result = wabt_snprintf(dst, size, "initial: %" PRIu64 ", max: %" PRIu64, - limits->initial, limits->max); - } else { - result = wabt_snprintf(dst, size, "initial: %" PRIu64, limits->initial); - } - WABT_USE(result); - assert(static_cast<size_t>(result) < size); -} - -static void log_types(LoggingContext* ctx, uint32_t type_count, Type* types) { - LOGF_NOINDENT("["); - for (uint32_t i = 0; i < type_count; ++i) { - LOGF_NOINDENT("%s", get_type_name(types[i])); - if (i != type_count - 1) - LOGF_NOINDENT(", "); - } - LOGF_NOINDENT("]"); -} - -static Result logging_on_signature(uint32_t index, - uint32_t param_count, - Type* param_types, - uint32_t result_count, - Type* result_types, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_signature(index: %u, params: ", index); - log_types(ctx, param_count, param_types); - LOGF_NOINDENT(", results: "); - log_types(ctx, result_count, result_types); - LOGF_NOINDENT(")\n"); - FORWARD(on_signature, index, param_count, param_types, result_count, - result_types); -} - -static Result logging_on_import(uint32_t index, - StringSlice module_name, - StringSlice field_name, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_import(index: %u, module: \"" PRIstringslice - "\", field: \"" PRIstringslice "\")\n", - index, WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); - FORWARD(on_import, index, module_name, field_name); -} - -static Result logging_on_import_func(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t func_index, - uint32_t sig_index, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_import_func(import_index: %u, func_index: %u, sig_index: %u)\n", - import_index, func_index, sig_index); - FORWARD(on_import_func, import_index, module_name, field_name, - func_index, sig_index); -} - -static Result logging_on_import_table(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t table_index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - char buf[100]; - sprint_limits(buf, sizeof(buf), elem_limits); - LOGF( - "on_import_table(import_index: %u, table_index: %u, elem_type: %s, %s)\n", - import_index, table_index, get_type_name(elem_type), buf); - FORWARD(on_import_table, import_index, module_name, field_name, - table_index, elem_type, elem_limits); -} - -static Result logging_on_import_memory(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t memory_index, - const Limits* page_limits, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - char buf[100]; - sprint_limits(buf, sizeof(buf), page_limits); - LOGF("on_import_memory(import_index: %u, memory_index: %u, %s)\n", - import_index, memory_index, buf); - FORWARD(on_import_memory, import_index, module_name, field_name, - memory_index, page_limits); -} - -static Result logging_on_import_global(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t global_index, - Type type, - bool mutable_, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF( - "on_import_global(import_index: %u, global_index: %u, type: %s, mutable: " - "%s)\n", - import_index, global_index, get_type_name(type), - mutable_ ? "true" : "false"); - FORWARD(on_import_global, import_index, module_name, field_name, - global_index, type, mutable_); -} - -static Result logging_on_table(uint32_t index, - Type elem_type, - const Limits* elem_limits, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - char buf[100]; - sprint_limits(buf, sizeof(buf), elem_limits); - LOGF("on_table(index: %u, elem_type: %s, %s)\n", index, - get_type_name(elem_type), buf); - FORWARD(on_table, index, elem_type, elem_limits); -} - -static Result logging_on_memory(uint32_t index, - const Limits* page_limits, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - char buf[100]; - sprint_limits(buf, sizeof(buf), page_limits); - LOGF("on_memory(index: %u, %s)\n", index, buf); - FORWARD(on_memory, index, page_limits); -} - -static Result logging_begin_global(uint32_t index, - Type type, - bool mutable_, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("begin_global(index: %u, type: %s, mutable: %s)\n", index, - get_type_name(type), mutable_ ? "true" : "false"); - FORWARD(begin_global, index, type, mutable_); -} - -static Result logging_on_export(uint32_t index, - ExternalKind kind, - uint32_t item_index, - StringSlice name, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_export(index: %u, kind: %s, item_index: %u, name: \"" PRIstringslice - "\")\n", - index, get_kind_name(kind), item_index, - WABT_PRINTF_STRING_SLICE_ARG(name)); - FORWARD(on_export, index, kind, item_index, name); -} - -static Result logging_begin_function_body_pass(uint32_t index, - uint32_t pass, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("begin_function_body_pass(index: %u, pass: %u)\n", index, pass); - indent(ctx); - FORWARD(begin_function_body_pass, index, pass); -} - -static Result logging_on_local_decl(uint32_t decl_index, - uint32_t count, - Type type, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_local_decl(index: %u, count: %u, type: %s)\n", decl_index, count, - get_type_name(type)); - FORWARD(on_local_decl, decl_index, count, type); -} - -static Result logging_on_block_expr(uint32_t num_types, - Type* sig_types, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_block_expr(sig: "); - log_types(ctx, num_types, sig_types); - LOGF_NOINDENT(")\n"); - FORWARD(on_block_expr, num_types, sig_types); -} - -static Result logging_on_br_expr(uint32_t depth, void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_br_expr(depth: %u)\n", depth); - FORWARD(on_br_expr, depth); -} - -static Result logging_on_br_if_expr(uint32_t depth, void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_br_if_expr(depth: %u)\n", depth); - FORWARD(on_br_if_expr, depth); -} - -static Result logging_on_br_table_expr(BinaryReaderContext* context, - uint32_t num_targets, - uint32_t* target_depths, - uint32_t default_target_depth) { - LoggingContext* ctx = static_cast<LoggingContext*>(context->user_data); - LOGF("on_br_table_expr(num_targets: %u, depths: [", num_targets); - for (uint32_t i = 0; i < num_targets; ++i) { - LOGF_NOINDENT("%u", target_depths[i]); - if (i != num_targets - 1) - LOGF_NOINDENT(", "); - } - LOGF_NOINDENT("], default: %u)\n", default_target_depth); - FORWARD_CTX(on_br_table_expr, num_targets, target_depths, - default_target_depth); -} - -static Result logging_on_f32_const_expr(uint32_t value_bits, void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - float value; - memcpy(&value, &value_bits, sizeof(value)); - LOGF("on_f32_const_expr(%g (0x04%x))\n", value, value_bits); - FORWARD(on_f32_const_expr, value_bits); -} - -static Result logging_on_f64_const_expr(uint64_t value_bits, void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - double value; - memcpy(&value, &value_bits, sizeof(value)); - LOGF("on_f64_const_expr(%g (0x08%" PRIx64 "))\n", value, value_bits); - FORWARD(on_f64_const_expr, value_bits); -} - -static Result logging_on_i32_const_expr(uint32_t value, void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_i32_const_expr(%u (0x%x))\n", value, value); - FORWARD(on_i32_const_expr, value); -} - -static Result logging_on_i64_const_expr(uint64_t value, void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_i64_const_expr(%" PRIu64 " (0x%" PRIx64 "))\n", value, value); - FORWARD(on_i64_const_expr, value); -} - -static Result logging_on_if_expr(uint32_t num_types, - Type* sig_types, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_if_expr(sig: "); - log_types(ctx, num_types, sig_types); - LOGF_NOINDENT(")\n"); - FORWARD(on_if_expr, num_types, sig_types); -} - -static Result logging_on_load_expr(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_load_expr(opcode: \"%s\" (%u), align log2: %u, offset: %u)\n", - get_opcode_name(opcode), static_cast<unsigned>(opcode), alignment_log2, - offset); - FORWARD(on_load_expr, opcode, alignment_log2, offset); -} - -static Result logging_on_loop_expr(uint32_t num_types, - Type* sig_types, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_loop_expr(sig: "); - log_types(ctx, num_types, sig_types); - LOGF_NOINDENT(")\n"); - FORWARD(on_loop_expr, num_types, sig_types); -} - -static Result logging_on_store_expr(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_store_expr(opcode: \"%s\" (%u), align log2: %u, offset: %u)\n", - get_opcode_name(opcode), static_cast<unsigned>(opcode), alignment_log2, - offset); - FORWARD(on_store_expr, opcode, alignment_log2, offset); -} - -static Result logging_end_function_body_pass(uint32_t index, - uint32_t pass, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - dedent(ctx); - LOGF("end_function_body_pass(index: %u, pass: %u)\n", index, pass); - FORWARD(end_function_body_pass, index, pass); -} - -static Result logging_on_data_segment_data(uint32_t index, - const void* data, - uint32_t size, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_data_segment_data(index:%u, size:%u)\n", index, size); - FORWARD(on_data_segment_data, index, data, size); -} - -static Result logging_on_function_name_subsection(uint32_t index, - uint32_t name_type, - uint32_t subsection_size, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_function_name_subsection(index:%u, nametype:%u, size:%u)\n", index, name_type, subsection_size); - FORWARD(on_function_name_subsection, index, name_type, subsection_size); -} - -static Result logging_on_function_name(uint32_t index, - StringSlice name, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_function_name(index: %u, name: \"" PRIstringslice "\")\n", index, - WABT_PRINTF_STRING_SLICE_ARG(name)); - FORWARD(on_function_name, index, name); -} - -static Result logging_on_local_name_subsection(uint32_t index, - uint32_t name_type, - uint32_t subsection_size, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_local_name_subsection(index:%u, nametype:%u, size:%u)\n", index, name_type, subsection_size); - FORWARD(on_local_name_subsection, index, name_type, subsection_size); -} - -static Result logging_on_local_name(uint32_t func_index, - uint32_t local_index, - StringSlice name, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_local_name(func_index: %u, local_index: %u, name: \"" PRIstringslice - "\")\n", - func_index, local_index, WABT_PRINTF_STRING_SLICE_ARG(name)); - FORWARD(on_local_name, func_index, local_index, name); -} - -static Result logging_on_init_expr_f32_const_expr(uint32_t index, - uint32_t value_bits, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - float value; - memcpy(&value, &value_bits, sizeof(value)); - LOGF("on_init_expr_f32_const_expr(index: %u, value: %g (0x04%x))\n", index, - value, value_bits); - FORWARD(on_init_expr_f32_const_expr, index, value_bits); -} - -static Result logging_on_init_expr_f64_const_expr(uint32_t index, - uint64_t value_bits, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - double value; - memcpy(&value, &value_bits, sizeof(value)); - LOGF("on_init_expr_f64_const_expr(index: %u value: %g (0x08%" PRIx64 "))\n", - index, value, value_bits); - FORWARD(on_init_expr_f64_const_expr, index, value_bits); -} - -static Result logging_on_init_expr_i32_const_expr(uint32_t index, - uint32_t value, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_init_expr_i32_const_expr(index: %u, value: %u)\n", index, value); - FORWARD(on_init_expr_i32_const_expr, index, value); -} - -static Result logging_on_init_expr_i64_const_expr(uint32_t index, - uint64_t value, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_init_expr_i64_const_expr(index: %u, value: %" PRIu64 ")\n", index, - value); - FORWARD(on_init_expr_i64_const_expr, index, value); -} - -static Result logging_on_reloc_count(uint32_t count, - BinarySection section_code, - StringSlice section_name, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_reloc_count(count: %d, section: %s, section_name: " PRIstringslice - ")\n", - count, get_section_name(section_code), - WABT_PRINTF_STRING_SLICE_ARG(section_name)); - FORWARD(on_reloc_count, count, section_code, section_name); -} - -static Result logging_on_reloc(RelocType type, - uint32_t offset, - uint32_t index, - int32_t addend, - void* user_data) { - LoggingContext* ctx = static_cast<LoggingContext*>(user_data); - LOGF("on_reloc(type: %s, offset: %u, index: %u, addend: %d)\n", - get_reloc_type_name(type), offset, index, addend); - FORWARD(on_reloc, type, offset, index, addend); -} - static void read_init_expr(Context* ctx, uint32_t index) { uint8_t opcode; in_u8(ctx, &opcode, "opcode"); @@ -1056,35 +368,35 @@ static void read_init_expr(Context* ctx, uint32_t index) { case Opcode::I32Const: { uint32_t value = 0; in_i32_leb128(ctx, &value, "init_expr i32.const value"); - CALLBACK(on_init_expr_i32_const_expr, index, value); + CALLBACK(OnInitExprI32ConstExpr, index, value); break; } case Opcode::I64Const: { uint64_t value = 0; in_i64_leb128(ctx, &value, "init_expr i64.const value"); - CALLBACK(on_init_expr_i64_const_expr, index, value); + CALLBACK(OnInitExprI64ConstExpr, index, value); break; } case Opcode::F32Const: { uint32_t value_bits = 0; in_f32(ctx, &value_bits, "init_expr f32.const value"); - CALLBACK(on_init_expr_f32_const_expr, index, value_bits); + CALLBACK(OnInitExprF32ConstExpr, index, value_bits); break; } case Opcode::F64Const: { uint64_t value_bits = 0; in_f64(ctx, &value_bits, "init_expr f64.const value"); - CALLBACK(on_init_expr_f64_const_expr, index, value_bits); + CALLBACK(OnInitExprF64ConstExpr, index, value_bits); break; } case Opcode::GetGlobal: { uint32_t global_index; in_u32_leb128(ctx, &global_index, "init_expr get_global index"); - CALLBACK(on_init_expr_get_global_expr, index, global_index); + CALLBACK(OnInitExprGetGlobalExpr, index, global_index); break; } @@ -1164,15 +476,15 @@ static void read_global_header(Context* ctx, static void read_function_body(Context* ctx, uint32_t end_offset) { bool seen_end_opcode = false; - while (ctx->offset < end_offset) { + while (ctx->state.offset < end_offset) { uint8_t opcode_u8; in_u8(ctx, &opcode_u8, "opcode"); Opcode opcode = static_cast<Opcode>(opcode_u8); - CALLBACK_CTX(on_opcode, opcode); + CALLBACK(OnOpcode, opcode); switch (opcode) { case Opcode::Unreachable: - CALLBACK0(on_unreachable_expr); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK0(OnUnreachableExpr); + CALLBACK0(OnOpcodeBare); break; case Opcode::Block: { @@ -1181,8 +493,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { RAISE_ERROR_UNLESS(is_inline_sig_type(sig_type), "expected valid block signature type"); uint32_t num_types = sig_type == Type::Void ? 0 : 1; - CALLBACK(on_block_expr, num_types, &sig_type); - CALLBACK_CTX(on_opcode_block_sig, num_types, &sig_type); + CALLBACK(OnBlockExpr, num_types, &sig_type); + CALLBACK(OnOpcodeBlockSig, num_types, &sig_type); break; } @@ -1192,8 +504,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { RAISE_ERROR_UNLESS(is_inline_sig_type(sig_type), "expected valid block signature type"); uint32_t num_types = sig_type == Type::Void ? 0 : 1; - CALLBACK(on_loop_expr, num_types, &sig_type); - CALLBACK_CTX(on_opcode_block_sig, num_types, &sig_type); + CALLBACK(OnLoopExpr, num_types, &sig_type); + CALLBACK(OnOpcodeBlockSig, num_types, &sig_type); break; } @@ -1203,34 +515,34 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { RAISE_ERROR_UNLESS(is_inline_sig_type(sig_type), "expected valid block signature type"); uint32_t num_types = sig_type == Type::Void ? 0 : 1; - CALLBACK(on_if_expr, num_types, &sig_type); - CALLBACK_CTX(on_opcode_block_sig, num_types, &sig_type); + CALLBACK(OnIfExpr, num_types, &sig_type); + CALLBACK(OnOpcodeBlockSig, num_types, &sig_type); break; } case Opcode::Else: - CALLBACK0(on_else_expr); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK0(OnElseExpr); + CALLBACK0(OnOpcodeBare); break; case Opcode::Select: - CALLBACK0(on_select_expr); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK0(OnSelectExpr); + CALLBACK0(OnOpcodeBare); break; case Opcode::Br: { uint32_t depth; in_u32_leb128(ctx, &depth, "br depth"); - CALLBACK(on_br_expr, depth); - CALLBACK_CTX(on_opcode_uint32, depth); + CALLBACK(OnBrExpr, depth); + CALLBACK(OnOpcodeUint32, depth); break; } case Opcode::BrIf: { uint32_t depth; in_u32_leb128(ctx, &depth, "br_if depth"); - CALLBACK(on_br_if_expr, depth); - CALLBACK_CTX(on_opcode_uint32, depth); + CALLBACK(OnBrIfExpr, depth); + CALLBACK(OnOpcodeUint32, depth); break; } @@ -1252,96 +564,96 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { uint32_t* target_depths = num_targets ? ctx->target_depths.data() : nullptr; - CALLBACK_CTX(on_br_table_expr, num_targets, target_depths, - default_target_depth); + CALLBACK(OnBrTableExpr, num_targets, target_depths, + default_target_depth); break; } case Opcode::Return: - CALLBACK0(on_return_expr); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK0(OnReturnExpr); + CALLBACK0(OnOpcodeBare); break; case Opcode::Nop: - CALLBACK0(on_nop_expr); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK0(OnNopExpr); + CALLBACK0(OnOpcodeBare); break; case Opcode::Drop: - CALLBACK0(on_drop_expr); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK0(OnDropExpr); + CALLBACK0(OnOpcodeBare); break; case Opcode::End: - if (ctx->offset == end_offset) { + if (ctx->state.offset == end_offset) { seen_end_opcode = true; - CALLBACK0(on_end_func); + CALLBACK0(OnEndFunc); } else { - CALLBACK0(on_end_expr); + CALLBACK0(OnEndExpr); } break; case Opcode::I32Const: { uint32_t value = 0; in_i32_leb128(ctx, &value, "i32.const value"); - CALLBACK(on_i32_const_expr, value); - CALLBACK_CTX(on_opcode_uint32, value); + CALLBACK(OnI32ConstExpr, value); + CALLBACK(OnOpcodeUint32, value); break; } case Opcode::I64Const: { uint64_t value = 0; in_i64_leb128(ctx, &value, "i64.const value"); - CALLBACK(on_i64_const_expr, value); - CALLBACK_CTX(on_opcode_uint64, value); + CALLBACK(OnI64ConstExpr, value); + CALLBACK(OnOpcodeUint64, value); break; } case Opcode::F32Const: { uint32_t value_bits = 0; in_f32(ctx, &value_bits, "f32.const value"); - CALLBACK(on_f32_const_expr, value_bits); - CALLBACK_CTX(on_opcode_f32, value_bits); + CALLBACK(OnF32ConstExpr, value_bits); + CALLBACK(OnOpcodeF32, value_bits); break; } case Opcode::F64Const: { uint64_t value_bits = 0; in_f64(ctx, &value_bits, "f64.const value"); - CALLBACK(on_f64_const_expr, value_bits); - CALLBACK_CTX(on_opcode_f64, value_bits); + CALLBACK(OnF64ConstExpr, value_bits); + CALLBACK(OnOpcodeF64, value_bits); break; } case Opcode::GetGlobal: { uint32_t global_index; in_u32_leb128(ctx, &global_index, "get_global global index"); - CALLBACK(on_get_global_expr, global_index); - CALLBACK_CTX(on_opcode_uint32, global_index); + CALLBACK(OnGetGlobalExpr, global_index); + CALLBACK(OnOpcodeUint32, global_index); break; } case Opcode::GetLocal: { uint32_t local_index; in_u32_leb128(ctx, &local_index, "get_local local index"); - CALLBACK(on_get_local_expr, local_index); - CALLBACK_CTX(on_opcode_uint32, local_index); + CALLBACK(OnGetLocalExpr, local_index); + CALLBACK(OnOpcodeUint32, local_index); break; } case Opcode::SetGlobal: { uint32_t global_index; in_u32_leb128(ctx, &global_index, "set_global global index"); - CALLBACK(on_set_global_expr, global_index); - CALLBACK_CTX(on_opcode_uint32, global_index); + CALLBACK(OnSetGlobalExpr, global_index); + CALLBACK(OnOpcodeUint32, global_index); break; } case Opcode::SetLocal: { uint32_t local_index; in_u32_leb128(ctx, &local_index, "set_local local index"); - CALLBACK(on_set_local_expr, local_index); - CALLBACK_CTX(on_opcode_uint32, local_index); + CALLBACK(OnSetLocalExpr, local_index); + CALLBACK(OnOpcodeUint32, local_index); break; } @@ -1350,8 +662,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { in_u32_leb128(ctx, &func_index, "call function index"); RAISE_ERROR_UNLESS(func_index < num_total_funcs(ctx), "invalid call function index"); - CALLBACK(on_call_expr, func_index); - CALLBACK_CTX(on_opcode_uint32, func_index); + CALLBACK(OnCallExpr, func_index); + CALLBACK(OnOpcodeUint32, func_index); break; } @@ -1364,16 +676,16 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { in_u32_leb128(ctx, &reserved, "call_indirect reserved"); RAISE_ERROR_UNLESS(reserved == 0, "call_indirect reserved value must be 0"); - CALLBACK(on_call_indirect_expr, sig_index); - CALLBACK_CTX(on_opcode_uint32_uint32, sig_index, reserved); + CALLBACK(OnCallIndirectExpr, sig_index); + CALLBACK(OnOpcodeUint32Uint32, sig_index, reserved); break; } case Opcode::TeeLocal: { uint32_t local_index; in_u32_leb128(ctx, &local_index, "tee_local local index"); - CALLBACK(on_tee_local_expr, local_index); - CALLBACK_CTX(on_opcode_uint32, local_index); + CALLBACK(OnTeeLocalExpr, local_index); + CALLBACK(OnOpcodeUint32, local_index); break; } @@ -1396,8 +708,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { uint32_t offset; in_u32_leb128(ctx, &offset, "load offset"); - CALLBACK(on_load_expr, opcode, alignment_log2, offset); - CALLBACK_CTX(on_opcode_uint32_uint32, alignment_log2, offset); + CALLBACK(OnLoadExpr, opcode, alignment_log2, offset); + CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset); break; } @@ -1415,8 +727,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { uint32_t offset; in_u32_leb128(ctx, &offset, "store offset"); - CALLBACK(on_store_expr, opcode, alignment_log2, offset); - CALLBACK_CTX(on_opcode_uint32_uint32, alignment_log2, offset); + CALLBACK(OnStoreExpr, opcode, alignment_log2, offset); + CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset); break; } @@ -1425,8 +737,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { in_u32_leb128(ctx, &reserved, "current_memory reserved"); RAISE_ERROR_UNLESS(reserved == 0, "current_memory reserved value must be 0"); - CALLBACK0(on_current_memory_expr); - CALLBACK_CTX(on_opcode_uint32, reserved); + CALLBACK0(OnCurrentMemoryExpr); + CALLBACK(OnOpcodeUint32, reserved); break; } @@ -1435,8 +747,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { in_u32_leb128(ctx, &reserved, "grow_memory reserved"); RAISE_ERROR_UNLESS(reserved == 0, "grow_memory reserved value must be 0"); - CALLBACK0(on_grow_memory_expr); - CALLBACK_CTX(on_opcode_uint32, reserved); + CALLBACK0(OnGrowMemoryExpr); + CALLBACK(OnOpcodeUint32, reserved); break; } @@ -1484,8 +796,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { case Opcode::F64Min: case Opcode::F64Max: case Opcode::F64Copysign: - CALLBACK(on_binary_expr, opcode); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK(OnBinaryExpr, opcode); + CALLBACK0(OnOpcodeBare); break; case Opcode::I32Eq: @@ -1520,8 +832,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { case Opcode::F64Le: case Opcode::F64Gt: case Opcode::F64Ge: - CALLBACK(on_compare_expr, opcode); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK(OnCompareExpr, opcode); + CALLBACK0(OnOpcodeBare); break; case Opcode::I32Clz: @@ -1544,8 +856,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { case Opcode::F64Trunc: case Opcode::F64Nearest: case Opcode::F64Sqrt: - CALLBACK(on_unary_expr, opcode); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK(OnUnaryExpr, opcode); + CALLBACK0(OnOpcodeBare); break; case Opcode::I32TruncSF32: @@ -1575,8 +887,8 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { case Opcode::I64ReinterpretF64: case Opcode::I32Eqz: case Opcode::I64Eqz: - CALLBACK(on_convert_expr, opcode); - CALLBACK_CTX0(on_opcode_bare); + CALLBACK(OnConvertExpr, opcode); + CALLBACK0(OnOpcodeBare); break; default: @@ -1584,7 +896,7 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { static_cast<unsigned>(opcode)); } } - RAISE_ERROR_UNLESS(ctx->offset == end_offset, + RAISE_ERROR_UNLESS(ctx->state.offset == end_offset, "function body longer than given size"); RAISE_ERROR_UNLESS(seen_end_opcode, "function body must end with END opcode"); } @@ -1592,17 +904,17 @@ static void read_function_body(Context* ctx, uint32_t end_offset) { static void read_custom_section(Context* ctx, uint32_t section_size) { StringSlice section_name; in_str(ctx, §ion_name, "section name"); - CALLBACK_CTX(begin_custom_section, section_size, section_name); + CALLBACK(BeginCustomSection, section_size, section_name); bool name_section_ok = ctx->last_known_section >= BinarySection::Import; if (ctx->options->read_debug_names && name_section_ok && strncmp(section_name.start, WABT_BINARY_SECTION_NAME, section_name.length) == 0) { - CALLBACK_SECTION(begin_names_section, section_size); + CALLBACK(BeginNamesSection, section_size); uint32_t i = 0; size_t previous_read_end = ctx->read_end; uint32_t previous_subsection_type = 0; - while (ctx->offset < ctx->read_end) { + while (ctx->state.offset < ctx->read_end) { uint32_t name_type; uint32_t subsection_size; in_u32_leb128(ctx, &name_type, "name type"); @@ -1614,74 +926,74 @@ static void read_custom_section(Context* ctx, uint32_t section_size) { } previous_subsection_type = name_type; in_u32_leb128(ctx, &subsection_size, "subsection size"); - size_t subsection_end = ctx->offset + subsection_size; + size_t subsection_end = ctx->state.offset + subsection_size; if (subsection_end > ctx->read_end) RAISE_ERROR("invalid sub-section size: extends past end"); ctx->read_end = subsection_end; switch (static_cast<NameSectionSubsection>(name_type)) { case NameSectionSubsection::Function: - CALLBACK(on_function_name_subsection, i, name_type, subsection_size); + CALLBACK(OnFunctionNameSubsection, i, name_type, subsection_size); if (subsection_size) { uint32_t num_names; in_u32_leb128(ctx, &num_names, "name count"); - CALLBACK(on_function_names_count, num_names); + CALLBACK(OnFunctionNamesCount, num_names); for (uint32_t j = 0; j < num_names; ++j) { uint32_t function_index; StringSlice function_name; in_u32_leb128(ctx, &function_index, "function index"); in_str(ctx, &function_name, "function name"); - CALLBACK(on_function_name, function_index, function_name); + CALLBACK(OnFunctionName, function_index, function_name); } } break; case NameSectionSubsection::Local: - CALLBACK(on_local_name_subsection, i, name_type, subsection_size); + CALLBACK(OnLocalNameSubsection, i, name_type, subsection_size); if (subsection_size) { uint32_t num_funcs; in_u32_leb128(ctx, &num_funcs, "function count"); - CALLBACK(on_local_name_function_count, num_funcs); + CALLBACK(OnLocalNameFunctionCount, num_funcs); for (uint32_t j = 0; j < num_funcs; ++j) { uint32_t function_index; in_u32_leb128(ctx, &function_index, "function index"); uint32_t num_locals; in_u32_leb128(ctx, &num_locals, "local count"); - CALLBACK(on_local_name_local_count, function_index, num_locals); + CALLBACK(OnLocalNameLocalCount, function_index, num_locals); for (uint32_t k = 0; k < num_locals; ++k) { uint32_t local_index; StringSlice local_name; in_u32_leb128(ctx, &local_index, "named index"); in_str(ctx, &local_name, "name"); - CALLBACK(on_local_name, function_index, local_index, local_name); + CALLBACK(OnLocalName, function_index, local_index, local_name); } } } break; default: /* unknown subsection, skip it */ - ctx->offset = subsection_end; + ctx->state.offset = subsection_end; break; } ++i; - if (ctx->offset != subsection_end) { + if (ctx->state.offset != subsection_end) { RAISE_ERROR("unfinished sub-section (expected end: 0x%" PRIzx ")", subsection_end); } ctx->read_end = previous_read_end; } - CALLBACK_CTX0(end_names_section); + CALLBACK0(EndNamesSection); } else if (strncmp(section_name.start, WABT_BINARY_SECTION_RELOC, strlen(WABT_BINARY_SECTION_RELOC)) == 0) { - CALLBACK_SECTION(begin_reloc_section, section_size); + CALLBACK(BeginRelocSection, section_size); uint32_t num_relocs, section; in_u32_leb128(ctx, §ion, "section"); WABT_ZERO_MEMORY(section_name); if (static_cast<BinarySection>(section) == BinarySection::Custom) in_str(ctx, §ion_name, "section name"); in_u32_leb128(ctx, &num_relocs, "relocation count"); - CALLBACK(on_reloc_count, num_relocs, static_cast<BinarySection>(section), + CALLBACK(OnRelocCount, num_relocs, static_cast<BinarySection>(section), section_name); for (uint32_t i = 0; i < num_relocs; ++i) { uint32_t reloc_type, offset, index, addend = 0; @@ -1698,20 +1010,20 @@ static void read_custom_section(Context* ctx, uint32_t section_size) { default: break; } - CALLBACK(on_reloc, type, offset, index, addend); + CALLBACK(OnReloc, type, offset, index, addend); } - CALLBACK_CTX0(end_reloc_section); + CALLBACK0(EndRelocSection); } else { /* This is an unknown custom section, skip it. */ - ctx->offset = ctx->read_end; + ctx->state.offset = ctx->read_end; } - CALLBACK_CTX0(end_custom_section); + CALLBACK0(EndCustomSection); } static void read_type_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_signature_section, section_size); + CALLBACK(BeginTypeSection, section_size); in_u32_leb128(ctx, &ctx->num_signatures, "type count"); - CALLBACK(on_signature_count, ctx->num_signatures); + CALLBACK(OnTypeCount, ctx->num_signatures); for (uint32_t i = 0; i < ctx->num_signatures; ++i) { Type form; @@ -1747,16 +1059,15 @@ static void read_type_section(Context* ctx, uint32_t section_size) { Type* param_types = num_params ? ctx->param_types.data() : nullptr; - CALLBACK(on_signature, i, num_params, param_types, num_results, - &result_type); + CALLBACK(OnType, i, num_params, param_types, num_results, &result_type); } - CALLBACK_CTX0(end_signature_section); + CALLBACK0(EndTypeSection); } static void read_import_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_import_section, section_size); + CALLBACK(BeginImportSection, section_size); in_u32_leb128(ctx, &ctx->num_imports, "import count"); - CALLBACK(on_import_count, ctx->num_imports); + CALLBACK(OnImportCount, ctx->num_imports); for (uint32_t i = 0; i < ctx->num_imports; ++i) { StringSlice module_name; in_str(ctx, &module_name, "import module name"); @@ -1771,8 +1082,8 @@ static void read_import_section(Context* ctx, uint32_t section_size) { in_u32_leb128(ctx, &sig_index, "import signature index"); RAISE_ERROR_UNLESS(sig_index < ctx->num_signatures, "invalid import signature index"); - CALLBACK(on_import, i, module_name, field_name); - CALLBACK(on_import_func, i, module_name, field_name, + CALLBACK(OnImport, i, module_name, field_name); + CALLBACK(OnImportFunc, i, module_name, field_name, ctx->num_func_imports, sig_index); ctx->num_func_imports++; break; @@ -1782,8 +1093,8 @@ static void read_import_section(Context* ctx, uint32_t section_size) { Type elem_type; Limits elem_limits; read_table(ctx, &elem_type, &elem_limits); - CALLBACK(on_import, i, module_name, field_name); - CALLBACK(on_import_table, i, module_name, field_name, + CALLBACK(OnImport, i, module_name, field_name); + CALLBACK(OnImportTable, i, module_name, field_name, ctx->num_table_imports, elem_type, &elem_limits); ctx->num_table_imports++; break; @@ -1792,8 +1103,8 @@ static void read_import_section(Context* ctx, uint32_t section_size) { case ExternalKind::Memory: { Limits page_limits; read_memory(ctx, &page_limits); - CALLBACK(on_import, i, module_name, field_name); - CALLBACK(on_import_memory, i, module_name, field_name, + CALLBACK(OnImport, i, module_name, field_name); + CALLBACK(OnImportMemory, i, module_name, field_name, ctx->num_memory_imports, &page_limits); ctx->num_memory_imports++; break; @@ -1803,8 +1114,8 @@ static void read_import_section(Context* ctx, uint32_t section_size) { Type type; bool mutable_; read_global_header(ctx, &type, &mutable_); - CALLBACK(on_import, i, module_name, field_name); - CALLBACK(on_import_global, i, module_name, field_name, + CALLBACK(OnImport, i, module_name, field_name); + CALLBACK(OnImportGlobal, i, module_name, field_name, ctx->num_global_imports, type, mutable_); ctx->num_global_imports++; break; @@ -1814,76 +1125,76 @@ static void read_import_section(Context* ctx, uint32_t section_size) { RAISE_ERROR("invalid import kind: %d", kind); } } - CALLBACK_CTX0(end_import_section); + CALLBACK0(EndImportSection); } static void read_function_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_function_signatures_section, section_size); + CALLBACK(BeginFunctionSection, section_size); in_u32_leb128(ctx, &ctx->num_function_signatures, "function signature count"); - CALLBACK(on_function_signatures_count, ctx->num_function_signatures); + CALLBACK(OnFunctionCount, ctx->num_function_signatures); for (uint32_t i = 0; i < ctx->num_function_signatures; ++i) { uint32_t func_index = ctx->num_func_imports + i; uint32_t sig_index; in_u32_leb128(ctx, &sig_index, "function signature index"); RAISE_ERROR_UNLESS(sig_index < ctx->num_signatures, "invalid function signature index: %d", sig_index); - CALLBACK(on_function_signature, func_index, sig_index); + CALLBACK(OnFunction, func_index, sig_index); } - CALLBACK_CTX0(end_function_signatures_section); + CALLBACK0(EndFunctionSection); } static void read_table_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_table_section, section_size); + CALLBACK(BeginTableSection, section_size); in_u32_leb128(ctx, &ctx->num_tables, "table count"); RAISE_ERROR_UNLESS(ctx->num_tables <= 1, "table count (%d) must be 0 or 1", ctx->num_tables); - CALLBACK(on_table_count, ctx->num_tables); + CALLBACK(OnTableCount, ctx->num_tables); for (uint32_t i = 0; i < ctx->num_tables; ++i) { uint32_t table_index = ctx->num_table_imports + i; Type elem_type; Limits elem_limits; read_table(ctx, &elem_type, &elem_limits); - CALLBACK(on_table, table_index, elem_type, &elem_limits); + CALLBACK(OnTable, table_index, elem_type, &elem_limits); } - CALLBACK_CTX0(end_table_section); + CALLBACK0(EndTableSection); } static void read_memory_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_memory_section, section_size); + CALLBACK(BeginMemorySection, section_size); in_u32_leb128(ctx, &ctx->num_memories, "memory count"); RAISE_ERROR_UNLESS(ctx->num_memories <= 1, "memory count must be 0 or 1"); - CALLBACK(on_memory_count, ctx->num_memories); + CALLBACK(OnMemoryCount, ctx->num_memories); for (uint32_t i = 0; i < ctx->num_memories; ++i) { uint32_t memory_index = ctx->num_memory_imports + i; Limits page_limits; read_memory(ctx, &page_limits); - CALLBACK(on_memory, memory_index, &page_limits); + CALLBACK(OnMemory, memory_index, &page_limits); } - CALLBACK_CTX0(end_memory_section); + CALLBACK0(EndMemorySection); } static void read_global_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_global_section, section_size); + CALLBACK(BeginGlobalSection, section_size); in_u32_leb128(ctx, &ctx->num_globals, "global count"); - CALLBACK(on_global_count, ctx->num_globals); + CALLBACK(OnGlobalCount, ctx->num_globals); for (uint32_t i = 0; i < ctx->num_globals; ++i) { uint32_t global_index = ctx->num_global_imports + i; Type global_type; bool mutable_; read_global_header(ctx, &global_type, &mutable_); - CALLBACK(begin_global, global_index, global_type, mutable_); - CALLBACK(begin_global_init_expr, global_index); + CALLBACK(BeginGlobal, global_index, global_type, mutable_); + CALLBACK(BeginGlobalInitExpr, global_index); read_init_expr(ctx, global_index); - CALLBACK(end_global_init_expr, global_index); - CALLBACK(end_global, global_index); + CALLBACK(EndGlobalInitExpr, global_index); + CALLBACK(EndGlobal, global_index); } - CALLBACK_CTX0(end_global_section); + CALLBACK0(EndGlobalSection); } static void read_export_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_export_section, section_size); + CALLBACK(BeginExportSection, section_size); in_u32_leb128(ctx, &ctx->num_exports, "export count"); - CALLBACK(on_export_count, ctx->num_exports); + CALLBACK(OnExportCount, ctx->num_exports); for (uint32_t i = 0; i < ctx->num_exports; ++i) { StringSlice name; in_str(ctx, &name, "export item name"); @@ -1914,70 +1225,70 @@ static void read_export_section(Context* ctx, uint32_t section_size) { break; } - CALLBACK(on_export, i, static_cast<ExternalKind>(external_kind), item_index, + CALLBACK(OnExport, i, static_cast<ExternalKind>(external_kind), item_index, name); } - CALLBACK_CTX0(end_export_section); + CALLBACK0(EndExportSection); } static void read_start_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_start_section, section_size); + CALLBACK(BeginStartSection, section_size); uint32_t func_index; in_u32_leb128(ctx, &func_index, "start function index"); RAISE_ERROR_UNLESS(func_index < num_total_funcs(ctx), "invalid start function index"); - CALLBACK(on_start_function, func_index); - CALLBACK_CTX0(end_start_section); + CALLBACK(OnStartFunction, func_index); + CALLBACK0(EndStartSection); } static void read_elem_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_elem_section, section_size); + CALLBACK(BeginElemSection, section_size); uint32_t num_elem_segments; in_u32_leb128(ctx, &num_elem_segments, "elem segment count"); - CALLBACK(on_elem_segment_count, num_elem_segments); + CALLBACK(OnElemSegmentCount, num_elem_segments); RAISE_ERROR_UNLESS(num_elem_segments == 0 || num_total_tables(ctx) > 0, "elem section without table section"); for (uint32_t i = 0; i < num_elem_segments; ++i) { uint32_t table_index; in_u32_leb128(ctx, &table_index, "elem segment table index"); - CALLBACK(begin_elem_segment, i, table_index); - CALLBACK(begin_elem_segment_init_expr, i); + CALLBACK(BeginElemSegment, i, table_index); + CALLBACK(BeginElemSegmentInitExpr, i); read_init_expr(ctx, i); - CALLBACK(end_elem_segment_init_expr, i); + CALLBACK(EndElemSegmentInitExpr, i); uint32_t num_function_indexes; in_u32_leb128(ctx, &num_function_indexes, "elem segment function index count"); - CALLBACK_CTX(on_elem_segment_function_index_count, i, num_function_indexes); + CALLBACK(OnElemSegmentFunctionIndexCount, i, num_function_indexes); for (uint32_t j = 0; j < num_function_indexes; ++j) { uint32_t func_index; in_u32_leb128(ctx, &func_index, "elem segment function index"); - CALLBACK(on_elem_segment_function_index, i, func_index); + CALLBACK(OnElemSegmentFunctionIndex, i, func_index); } - CALLBACK(end_elem_segment, i); + CALLBACK(EndElemSegment, i); } - CALLBACK_CTX0(end_elem_section); + CALLBACK0(EndElemSection); } static void read_code_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_function_bodies_section, section_size); + CALLBACK(BeginCodeSection, section_size); in_u32_leb128(ctx, &ctx->num_function_bodies, "function body count"); RAISE_ERROR_UNLESS(ctx->num_function_signatures == ctx->num_function_bodies, "function signature count != function body count"); - CALLBACK(on_function_bodies_count, ctx->num_function_bodies); + CALLBACK(OnFunctionBodyCount, ctx->num_function_bodies); for (uint32_t i = 0; i < ctx->num_function_bodies; ++i) { uint32_t func_index = ctx->num_func_imports + i; - uint32_t func_offset = ctx->offset; - ctx->offset = func_offset; - CALLBACK_CTX(begin_function_body, func_index); + uint32_t func_offset = ctx->state.offset; + ctx->state.offset = func_offset; + CALLBACK(BeginFunctionBody, func_index); uint32_t body_size; in_u32_leb128(ctx, &body_size, "function body size"); - uint32_t body_start_offset = ctx->offset; + uint32_t body_start_offset = ctx->state.offset; uint32_t end_offset = body_start_offset + body_size; uint32_t num_local_decls; in_u32_leb128(ctx, &num_local_decls, "local declaration count"); - CALLBACK(on_local_decl_count, num_local_decls); + CALLBACK(OnLocalDeclCount, num_local_decls); for (uint32_t k = 0; k < num_local_decls; ++k) { uint32_t num_local_types; in_u32_leb128(ctx, &num_local_types, "local type count"); @@ -1985,50 +1296,50 @@ static void read_code_section(Context* ctx, uint32_t section_size) { in_type(ctx, &local_type, "local type"); RAISE_ERROR_UNLESS(is_concrete_type(local_type), "expected valid local type"); - CALLBACK(on_local_decl, k, num_local_types, local_type); + CALLBACK(OnLocalDecl, k, num_local_types, local_type); } read_function_body(ctx, end_offset); - CALLBACK(end_function_body, func_index); + CALLBACK(EndFunctionBody, func_index); } - CALLBACK_CTX0(end_function_bodies_section); + CALLBACK0(EndCodeSection); } static void read_data_section(Context* ctx, uint32_t section_size) { - CALLBACK_SECTION(begin_data_section, section_size); + CALLBACK(BeginDataSection, section_size); uint32_t num_data_segments; in_u32_leb128(ctx, &num_data_segments, "data segment count"); - CALLBACK(on_data_segment_count, num_data_segments); + CALLBACK(OnDataSegmentCount, num_data_segments); RAISE_ERROR_UNLESS(num_data_segments == 0 || num_total_memories(ctx) > 0, "data section without memory section"); for (uint32_t i = 0; i < num_data_segments; ++i) { uint32_t memory_index; in_u32_leb128(ctx, &memory_index, "data segment memory index"); - CALLBACK(begin_data_segment, i, memory_index); - CALLBACK(begin_data_segment_init_expr, i); + CALLBACK(BeginDataSegment, i, memory_index); + CALLBACK(BeginDataSegmentInitExpr, i); read_init_expr(ctx, i); - CALLBACK(end_data_segment_init_expr, i); + CALLBACK(EndDataSegmentInitExpr, i); uint32_t data_size; const void* data; in_bytes(ctx, &data, &data_size, "data segment data"); - CALLBACK(on_data_segment_data, i, data, data_size); - CALLBACK(end_data_segment, i); + CALLBACK(OnDataSegmentData, i, data, data_size); + CALLBACK(EndDataSegment, i); } - CALLBACK_CTX0(end_data_section); + CALLBACK0(EndDataSection); } static void read_sections(Context* ctx) { - while (ctx->offset < ctx->data_size) { + while (ctx->state.offset < ctx->state.size) { uint32_t section_code; uint32_t section_size; /* Temporarily reset read_end to the full data size so the next section * can be read. */ - ctx->read_end = ctx->data_size; + ctx->read_end = ctx->state.size; in_u32_leb128(ctx, §ion_code, "section code"); in_u32_leb128(ctx, §ion_size, "section size"); - ctx->read_end = ctx->offset + section_size; + ctx->read_end = ctx->state.offset + section_size; if (section_code >= kBinarySectionCount) { RAISE_ERROR("invalid section code: %u; max is %u", section_code, kBinarySectionCount - 1); @@ -2036,7 +1347,7 @@ static void read_sections(Context* ctx) { BinarySection section = static_cast<BinarySection>(section_code); - if (ctx->read_end > ctx->data_size) + if (ctx->read_end > ctx->state.size) RAISE_ERROR("invalid section size: extends past end"); if (ctx->last_known_section != BinarySection::Invalid && @@ -2045,7 +1356,7 @@ static void read_sections(Context* ctx) { RAISE_ERROR("section %s out of order", get_section_name(section)); } - CALLBACK_CTX(begin_section, section, section_size); + CALLBACK(BeginSection, section, section_size); #define V(Name, name, code) \ case BinarySection::Name: \ @@ -2062,7 +1373,7 @@ static void read_sections(Context* ctx) { #undef V - if (ctx->offset != ctx->read_end) { + if (ctx->state.offset != ctx->read_end) { RAISE_ERROR("unfinished section (expected end: 0x%" PRIzx ")", ctx->read_end); } @@ -2075,175 +1386,14 @@ static void read_sections(Context* ctx) { Result read_binary(const void* data, size_t size, BinaryReader* reader, - uint32_t num_function_passes, const ReadBinaryOptions* options) { - LoggingContext logging_context; - WABT_ZERO_MEMORY(logging_context); - logging_context.reader = reader; - logging_context.stream = options->log_stream; - - BinaryReader logging_reader; - WABT_ZERO_MEMORY(logging_reader); - logging_reader.user_data = &logging_context; - - logging_reader.on_error = logging_on_error; - logging_reader.begin_section = logging_begin_section; - logging_reader.begin_module = logging_begin_module; - logging_reader.end_module = logging_end_module; - - logging_reader.begin_custom_section = logging_begin_custom_section; - logging_reader.end_custom_section = logging_end_custom_section; - - logging_reader.begin_signature_section = logging_begin_signature_section; - logging_reader.on_signature_count = logging_on_signature_count; - logging_reader.on_signature = logging_on_signature; - logging_reader.end_signature_section = logging_end_signature_section; - - logging_reader.begin_import_section = logging_begin_import_section; - logging_reader.on_import_count = logging_on_import_count; - logging_reader.on_import = logging_on_import; - logging_reader.on_import_func = logging_on_import_func; - logging_reader.on_import_table = logging_on_import_table; - logging_reader.on_import_memory = logging_on_import_memory; - logging_reader.on_import_global = logging_on_import_global; - logging_reader.end_import_section = logging_end_import_section; - - logging_reader.begin_function_signatures_section = - logging_begin_function_signatures_section; - logging_reader.on_function_signatures_count = - logging_on_function_signatures_count; - logging_reader.on_function_signature = logging_on_function_signature; - logging_reader.end_function_signatures_section = - logging_end_function_signatures_section; - - logging_reader.begin_table_section = logging_begin_table_section; - logging_reader.on_table_count = logging_on_table_count; - logging_reader.on_table = logging_on_table; - logging_reader.end_table_section = logging_end_table_section; - - logging_reader.begin_memory_section = logging_begin_memory_section; - logging_reader.on_memory_count = logging_on_memory_count; - logging_reader.on_memory = logging_on_memory; - logging_reader.end_memory_section = logging_end_memory_section; - - logging_reader.begin_global_section = logging_begin_global_section; - logging_reader.on_global_count = logging_on_global_count; - logging_reader.begin_global = logging_begin_global; - logging_reader.begin_global_init_expr = logging_begin_global_init_expr; - logging_reader.end_global_init_expr = logging_end_global_init_expr; - logging_reader.end_global = logging_end_global; - logging_reader.end_global_section = logging_end_global_section; - - logging_reader.begin_export_section = logging_begin_export_section; - logging_reader.on_export_count = logging_on_export_count; - logging_reader.on_export = logging_on_export; - logging_reader.end_export_section = logging_end_export_section; - - logging_reader.begin_start_section = logging_begin_start_section; - logging_reader.on_start_function = logging_on_start_function; - logging_reader.end_start_section = logging_end_start_section; - - logging_reader.begin_function_bodies_section = - logging_begin_function_bodies_section; - logging_reader.on_function_bodies_count = logging_on_function_bodies_count; - logging_reader.begin_function_body_pass = logging_begin_function_body_pass; - logging_reader.begin_function_body = logging_begin_function_body; - logging_reader.on_local_decl_count = logging_on_local_decl_count; - logging_reader.on_local_decl = logging_on_local_decl; - logging_reader.on_binary_expr = logging_on_binary_expr; - logging_reader.on_block_expr = logging_on_block_expr; - logging_reader.on_br_expr = logging_on_br_expr; - logging_reader.on_br_if_expr = logging_on_br_if_expr; - logging_reader.on_br_table_expr = logging_on_br_table_expr; - logging_reader.on_call_expr = logging_on_call_expr; - logging_reader.on_call_import_expr = logging_on_call_import_expr; - logging_reader.on_call_indirect_expr = logging_on_call_indirect_expr; - logging_reader.on_compare_expr = logging_on_compare_expr; - logging_reader.on_convert_expr = logging_on_convert_expr; - logging_reader.on_drop_expr = logging_on_drop_expr; - logging_reader.on_else_expr = logging_on_else_expr; - logging_reader.on_end_expr = logging_on_end_expr; - logging_reader.on_f32_const_expr = logging_on_f32_const_expr; - logging_reader.on_f64_const_expr = logging_on_f64_const_expr; - logging_reader.on_get_global_expr = logging_on_get_global_expr; - logging_reader.on_get_local_expr = logging_on_get_local_expr; - logging_reader.on_grow_memory_expr = logging_on_grow_memory_expr; - logging_reader.on_i32_const_expr = logging_on_i32_const_expr; - logging_reader.on_i64_const_expr = logging_on_i64_const_expr; - logging_reader.on_if_expr = logging_on_if_expr; - logging_reader.on_load_expr = logging_on_load_expr; - logging_reader.on_loop_expr = logging_on_loop_expr; - logging_reader.on_current_memory_expr = logging_on_current_memory_expr; - logging_reader.on_nop_expr = logging_on_nop_expr; - logging_reader.on_return_expr = logging_on_return_expr; - logging_reader.on_select_expr = logging_on_select_expr; - logging_reader.on_set_global_expr = logging_on_set_global_expr; - logging_reader.on_set_local_expr = logging_on_set_local_expr; - logging_reader.on_store_expr = logging_on_store_expr; - logging_reader.on_tee_local_expr = logging_on_tee_local_expr; - logging_reader.on_unary_expr = logging_on_unary_expr; - logging_reader.on_unreachable_expr = logging_on_unreachable_expr; - logging_reader.end_function_body = logging_end_function_body; - logging_reader.end_function_body_pass = logging_end_function_body_pass; - logging_reader.end_function_bodies_section = - logging_end_function_bodies_section; - - logging_reader.begin_elem_section = logging_begin_elem_section; - logging_reader.on_elem_segment_count = logging_on_elem_segment_count; - logging_reader.begin_elem_segment = logging_begin_elem_segment; - logging_reader.begin_elem_segment_init_expr = - logging_begin_elem_segment_init_expr; - logging_reader.end_elem_segment_init_expr = - logging_end_elem_segment_init_expr; - logging_reader.on_elem_segment_function_index_count = - logging_on_elem_segment_function_index_count; - logging_reader.on_elem_segment_function_index = - logging_on_elem_segment_function_index; - logging_reader.end_elem_segment = logging_end_elem_segment; - logging_reader.end_elem_section = logging_end_elem_section; - - logging_reader.begin_data_section = logging_begin_data_section; - logging_reader.on_data_segment_count = logging_on_data_segment_count; - logging_reader.begin_data_segment = logging_begin_data_segment; - logging_reader.begin_data_segment_init_expr = - logging_begin_data_segment_init_expr; - logging_reader.end_data_segment_init_expr = - logging_end_data_segment_init_expr; - logging_reader.on_data_segment_data = logging_on_data_segment_data; - logging_reader.end_data_segment = logging_end_data_segment; - logging_reader.end_data_section = logging_end_data_section; - - logging_reader.begin_names_section = logging_begin_names_section; - logging_reader.on_function_name_subsection = logging_on_function_name_subsection; - logging_reader.on_function_names_count = logging_on_function_names_count; - logging_reader.on_function_name = logging_on_function_name; - logging_reader.on_local_name_subsection = logging_on_local_name_subsection; - logging_reader.on_local_name_function_count = logging_on_local_name_function_count; - logging_reader.on_local_name_local_count = logging_on_local_name_local_count; - logging_reader.on_local_name = logging_on_local_name; - logging_reader.end_names_section = logging_end_names_section; - - logging_reader.begin_reloc_section = logging_begin_reloc_section; - logging_reader.on_reloc_count = logging_on_reloc_count; - logging_reader.on_reloc = logging_on_reloc; - logging_reader.end_reloc_section = logging_end_reloc_section; - - logging_reader.on_init_expr_f32_const_expr = - logging_on_init_expr_f32_const_expr; - logging_reader.on_init_expr_f64_const_expr = - logging_on_init_expr_f64_const_expr; - logging_reader.on_init_expr_get_global_expr = - logging_on_init_expr_get_global_expr; - logging_reader.on_init_expr_i32_const_expr = - logging_on_init_expr_i32_const_expr; - logging_reader.on_init_expr_i64_const_expr = - logging_on_init_expr_i64_const_expr; - + BinaryReaderLogging logging_reader(options->log_stream, reader); Context context; /* all the macros assume a Context* named ctx */ Context* ctx = &context; - ctx->data = static_cast<const uint8_t*>(data); - ctx->data_size = ctx->read_end = size; + ctx->state.data = static_cast<const uint8_t*>(data); + ctx->state.size = ctx->read_end = size; + ctx->state.offset = 0; ctx->reader = options->log_stream ? &logging_reader : reader; ctx->options = options; ctx->last_known_section = BinarySection::Invalid; @@ -2252,6 +1402,8 @@ Result read_binary(const void* data, return Result::Error; } + ctx->reader->OnSetState(&ctx->state); + uint32_t magic; in_u32(ctx, &magic, "magic"); RAISE_ERROR_UNLESS(magic == WABT_BINARY_MAGIC, "bad magic value"); @@ -2261,9 +1413,9 @@ Result read_binary(const void* data, "bad wasm file version: %#x (expected %#x)", version, WABT_BINARY_VERSION); - CALLBACK(begin_module, version); + CALLBACK(BeginModule, version); read_sections(ctx); - CALLBACK0(end_module); + CALLBACK0(EndModule); return Result::Ok; } diff --git a/src/binary-reader.h b/src/binary-reader.h index df7e8071..55ac8dd2 100644 --- a/src/binary-reader.h +++ b/src/binary-reader.h @@ -33,303 +33,244 @@ struct ReadBinaryOptions { bool read_debug_names; }; -struct BinaryReaderContext { - const uint8_t* data; - size_t size; - size_t offset; - void* user_data; -}; - -struct BinaryReader { - void* user_data; - - bool (*on_error)(BinaryReaderContext* ctx, const char* message); - - /* module */ - Result (*begin_module)(uint32_t version, void* user_data); - Result (*end_module)(void* user_data); - - Result (*begin_section)(BinaryReaderContext* ctx, - BinarySection section_type, - uint32_t size); - - /* custom section */ - Result (*begin_custom_section)(BinaryReaderContext* ctx, - uint32_t size, - StringSlice section_name); - Result (*end_custom_section)(BinaryReaderContext* ctx); - - /* signatures section */ - /* TODO(binji): rename to "type" section */ - Result (*begin_signature_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_signature_count)(uint32_t count, void* user_data); - Result (*on_signature)(uint32_t index, - uint32_t param_count, - Type* param_types, - uint32_t result_count, - Type* result_types, - void* user_data); - Result (*end_signature_section)(BinaryReaderContext* ctx); - - /* import section */ - Result (*begin_import_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_import_count)(uint32_t count, void* user_data); - Result (*on_import)(uint32_t index, - StringSlice module_name, - StringSlice field_name, - void* user_data); - Result (*on_import_func)(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t func_index, - uint32_t sig_index, - void* user_data); - Result (*on_import_table)(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t table_index, - Type elem_type, - const Limits* elem_limits, - void* user_data); - Result (*on_import_memory)(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t memory_index, - const Limits* page_limits, - void* user_data); - Result (*on_import_global)(uint32_t import_index, - StringSlice module_name, - StringSlice field_name, - uint32_t global_index, - Type type, - bool mutable_, - void* user_data); - Result (*end_import_section)(BinaryReaderContext* ctx); - - /* function signatures section */ - /* TODO(binji): rename to "function" section */ - Result (*begin_function_signatures_section)(BinaryReaderContext* ctx, - uint32_t size); - Result (*on_function_signatures_count)(uint32_t count, void* user_data); - Result (*on_function_signature)(uint32_t index, - uint32_t sig_index, - void* user_data); - Result (*end_function_signatures_section)(BinaryReaderContext* ctx); - - /* table section */ - Result (*begin_table_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_table_count)(uint32_t count, void* user_data); - Result (*on_table)(uint32_t index, - Type elem_type, - const Limits* elem_limits, - void* user_data); - Result (*end_table_section)(BinaryReaderContext* ctx); - - /* memory section */ - Result (*begin_memory_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_memory_count)(uint32_t count, void* user_data); - Result (*on_memory)(uint32_t index, const Limits* limits, void* user_data); - Result (*end_memory_section)(BinaryReaderContext* ctx); - - /* global section */ - Result (*begin_global_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_global_count)(uint32_t count, void* user_data); - Result (*begin_global)(uint32_t index, - Type type, - bool mutable_, - void* user_data); - Result (*begin_global_init_expr)(uint32_t index, void* user_data); - Result (*end_global_init_expr)(uint32_t index, void* user_data); - Result (*end_global)(uint32_t index, void* user_data); - Result (*end_global_section)(BinaryReaderContext* ctx); - - /* exports section */ - Result (*begin_export_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_export_count)(uint32_t count, void* user_data); - Result (*on_export)(uint32_t index, - ExternalKind kind, - uint32_t item_index, - StringSlice name, - void* user_data); - Result (*end_export_section)(BinaryReaderContext* ctx); - - /* start section */ - Result (*begin_start_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_start_function)(uint32_t func_index, void* user_data); - Result (*end_start_section)(BinaryReaderContext* ctx); - - /* function bodies section */ - /* TODO(binji): rename to code section */ - Result (*begin_function_bodies_section)(BinaryReaderContext* ctx, - uint32_t size); - Result (*on_function_bodies_count)(uint32_t count, void* user_data); - Result (*begin_function_body_pass)(uint32_t index, - uint32_t pass, - void* user_data); - Result (*begin_function_body)(BinaryReaderContext* ctx, uint32_t index); - Result (*on_local_decl_count)(uint32_t count, void* user_data); - Result (*on_local_decl)(uint32_t decl_index, - uint32_t count, - Type type, - void* user_data); - - /* function expressions; called between begin_function_body and - end_function_body */ - Result (*on_opcode)(BinaryReaderContext* ctx, Opcode Opcode); - Result (*on_opcode_bare)(BinaryReaderContext* ctx); - Result (*on_opcode_uint32)(BinaryReaderContext* ctx, uint32_t value); - Result (*on_opcode_uint32_uint32)(BinaryReaderContext* ctx, - uint32_t value, - uint32_t value2); - Result (*on_opcode_uint64)(BinaryReaderContext* ctx, uint64_t value); - Result (*on_opcode_f32)(BinaryReaderContext* ctx, uint32_t value); - Result (*on_opcode_f64)(BinaryReaderContext* ctx, uint64_t value); - Result (*on_opcode_block_sig)(BinaryReaderContext* ctx, - uint32_t num_types, - Type* sig_types); - Result (*on_binary_expr)(Opcode opcode, void* user_data); - Result (*on_block_expr)(uint32_t num_types, Type* sig_types, void* user_data); - Result (*on_br_expr)(uint32_t depth, void* user_data); - Result (*on_br_if_expr)(uint32_t depth, void* user_data); - Result (*on_br_table_expr)(BinaryReaderContext* ctx, - uint32_t num_targets, - uint32_t* target_depths, - uint32_t default_target_depth); - Result (*on_call_expr)(uint32_t func_index, void* user_data); - Result (*on_call_import_expr)(uint32_t import_index, void* user_data); - Result (*on_call_indirect_expr)(uint32_t sig_index, void* user_data); - Result (*on_compare_expr)(Opcode opcode, void* user_data); - Result (*on_convert_expr)(Opcode opcode, void* user_data); - Result (*on_drop_expr)(void* user_data); - Result (*on_else_expr)(void* user_data); - Result (*on_end_expr)(void* user_data); - Result (*on_end_func)(void* user_data); - Result (*on_f32_const_expr)(uint32_t value_bits, void* user_data); - Result (*on_f64_const_expr)(uint64_t value_bits, void* user_data); - Result (*on_get_global_expr)(uint32_t global_index, void* user_data); - Result (*on_get_local_expr)(uint32_t local_index, void* user_data); - Result (*on_grow_memory_expr)(void* user_data); - Result (*on_i32_const_expr)(uint32_t value, void* user_data); - Result (*on_i64_const_expr)(uint64_t value, void* user_data); - Result (*on_if_expr)(uint32_t num_types, Type* sig_types, void* user_data); - Result (*on_load_expr)(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data); - Result (*on_loop_expr)(uint32_t num_types, Type* sig_types, void* user_data); - Result (*on_current_memory_expr)(void* user_data); - Result (*on_nop_expr)(void* user_data); - Result (*on_return_expr)(void* user_data); - Result (*on_select_expr)(void* user_data); - Result (*on_set_global_expr)(uint32_t global_index, void* user_data); - Result (*on_set_local_expr)(uint32_t local_index, void* user_data); - Result (*on_store_expr)(Opcode opcode, - uint32_t alignment_log2, - uint32_t offset, - void* user_data); - Result (*on_tee_local_expr)(uint32_t local_index, void* user_data); - Result (*on_unary_expr)(Opcode opcode, void* user_data); - Result (*on_unreachable_expr)(void* user_data); - Result (*end_function_body)(uint32_t index, void* user_data); - Result (*end_function_body_pass)(uint32_t index, - uint32_t pass, - void* user_data); - Result (*end_function_bodies_section)(BinaryReaderContext* ctx); - - /* elem section */ - Result (*begin_elem_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_elem_segment_count)(uint32_t count, void* user_data); - Result (*begin_elem_segment)(uint32_t index, +class BinaryReader { + public: + struct State { + const uint8_t* data; + size_t size; + size_t offset; + }; + + virtual ~BinaryReader() {} + + virtual bool OnError(const char* message) = 0; + virtual void OnSetState(const State* s) { state = s; } + + /* Module */ + virtual Result BeginModule(uint32_t version) = 0; + virtual Result EndModule() = 0; + + virtual Result BeginSection(BinarySection section_type, uint32_t size) = 0; + + /* Custom section */ + virtual Result BeginCustomSection(uint32_t size, + StringSlice section_name) = 0; + virtual Result EndCustomSection() = 0; + + /* Type section */ + virtual Result BeginTypeSection(uint32_t size) = 0; + virtual Result OnTypeCount(uint32_t count) = 0; + virtual Result OnType(uint32_t index, + uint32_t param_count, + Type* param_types, + uint32_t result_count, + Type* result_types) = 0; + virtual Result EndTypeSection() = 0; + + /* Import section */ + virtual Result BeginImportSection(uint32_t size) = 0; + virtual Result OnImportCount(uint32_t count) = 0; + virtual Result OnImport(uint32_t index, + StringSlice module_name, + StringSlice field_name) = 0; + virtual Result OnImportFunc(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t func_index, + uint32_t sig_index) = 0; + virtual Result OnImportTable(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, uint32_t table_index, - void* user_data); - Result (*begin_elem_segment_init_expr)(uint32_t index, void* user_data); - Result (*end_elem_segment_init_expr)(uint32_t index, void* user_data); - Result (*on_elem_segment_function_index_count)(BinaryReaderContext* ctx, - uint32_t index, - uint32_t count); - Result (*on_elem_segment_function_index)(uint32_t index, - uint32_t func_index, - void* user_data); - Result (*end_elem_segment)(uint32_t index, void* user_data); - Result (*end_elem_section)(BinaryReaderContext* ctx); - - /* data section */ - Result (*begin_data_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_data_segment_count)(uint32_t count, void* user_data); - Result (*begin_data_segment)(uint32_t index, - uint32_t memory_index, - void* user_data); - Result (*begin_data_segment_init_expr)(uint32_t index, void* user_data); - Result (*end_data_segment_init_expr)(uint32_t index, void* user_data); - Result (*on_data_segment_data)(uint32_t index, - const void* data, - uint32_t size, - void* user_data); - Result (*end_data_segment)(uint32_t index, void* user_data); - Result (*end_data_section)(BinaryReaderContext* ctx); - - /* names section */ - Result (*begin_names_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_function_name_subsection)(uint32_t index, - uint32_t name_type, - uint32_t subsection_size, - void* user_data); - Result (*on_function_names_count)(uint32_t num_functions, - void* user_data); - Result (*on_function_name)(uint32_t function_index, - StringSlice function_name, - void* user_data); - Result (*on_local_name_subsection)(uint32_t index, - uint32_t name_type, - uint32_t subsection_size, - void* user_data); - Result (*on_local_name_function_count)(uint32_t num_functions, - void* user_data); - Result (*on_local_name_local_count)(uint32_t function_index, - uint32_t num_locals, - void* user_data); - Result (*on_local_name)(uint32_t function_index, - uint32_t local_index, - StringSlice local_name, - void* user_data); - Result (*end_names_section)(BinaryReaderContext* ctx); - - /* names section */ - Result (*begin_reloc_section)(BinaryReaderContext* ctx, uint32_t size); - Result (*on_reloc_count)(uint32_t count, - BinarySection section_code, - StringSlice section_name, - void* user_data); - Result (*on_reloc)(RelocType type, - uint32_t offset, - uint32_t index, - int32_t addend, - void* user_data); - Result (*end_reloc_section)(BinaryReaderContext* ctx); - - /* init_expr - used by elem, data and global sections; these functions are - * only called between calls to begin_*_init_expr and end_*_init_expr */ - Result (*on_init_expr_f32_const_expr)(uint32_t index, - uint32_t value, - void* user_data); - Result (*on_init_expr_f64_const_expr)(uint32_t index, - uint64_t value, - void* user_data); - Result (*on_init_expr_get_global_expr)(uint32_t index, - uint32_t global_index, - void* user_data); - Result (*on_init_expr_i32_const_expr)(uint32_t index, - uint32_t value, - void* user_data); - Result (*on_init_expr_i64_const_expr)(uint32_t index, - uint64_t value, - void* user_data); + Type elem_type, + const Limits* elem_limits) = 0; + virtual Result OnImportMemory(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t memory_index, + const Limits* page_limits) = 0; + virtual Result OnImportGlobal(uint32_t import_index, + StringSlice module_name, + StringSlice field_name, + uint32_t global_index, + Type type, + bool mutable_) = 0; + virtual Result EndImportSection() = 0; + + /* Function section */ + virtual Result BeginFunctionSection(uint32_t size) = 0; + virtual Result OnFunctionCount(uint32_t count) = 0; + virtual Result OnFunction(uint32_t index, uint32_t sig_index) = 0; + virtual Result EndFunctionSection() = 0; + + /* Table section */ + virtual Result BeginTableSection(uint32_t size) = 0; + virtual Result OnTableCount(uint32_t count) = 0; + virtual Result OnTable(uint32_t index, + Type elem_type, + const Limits* elem_limits) = 0; + virtual Result EndTableSection() = 0; + + /* Memory section */ + virtual Result BeginMemorySection(uint32_t size) = 0; + virtual Result OnMemoryCount(uint32_t count) = 0; + virtual Result OnMemory(uint32_t index, const Limits* limits) = 0; + virtual Result EndMemorySection() = 0; + + /* Global section */ + virtual Result BeginGlobalSection(uint32_t size) = 0; + virtual Result OnGlobalCount(uint32_t count) = 0; + virtual Result BeginGlobal(uint32_t index, Type type, bool mutable_) = 0; + virtual Result BeginGlobalInitExpr(uint32_t index) = 0; + virtual Result EndGlobalInitExpr(uint32_t index) = 0; + virtual Result EndGlobal(uint32_t index) = 0; + virtual Result EndGlobalSection() = 0; + + /* Exports section */ + virtual Result BeginExportSection(uint32_t size) = 0; + virtual Result OnExportCount(uint32_t count) = 0; + virtual Result OnExport(uint32_t index, + ExternalKind kind, + uint32_t item_index, + StringSlice name) = 0; + virtual Result EndExportSection() = 0; + + /* Start section */ + virtual Result BeginStartSection(uint32_t size) = 0; + virtual Result OnStartFunction(uint32_t func_index) = 0; + virtual Result EndStartSection() = 0; + + /* Code section */ + virtual Result BeginCodeSection(uint32_t size) = 0; + virtual Result OnFunctionBodyCount(uint32_t count) = 0; + virtual Result BeginFunctionBody(uint32_t index) = 0; + virtual Result OnLocalDeclCount(uint32_t count) = 0; + virtual Result OnLocalDecl(uint32_t decl_index, + uint32_t count, + Type type) = 0; + + /* Function expressions; called between BeginFunctionBody and + EndFunctionBody */ + virtual Result OnOpcode(Opcode Opcode) = 0; + virtual Result OnOpcodeBare() = 0; + virtual Result OnOpcodeUint32(uint32_t value) = 0; + virtual Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) = 0; + virtual Result OnOpcodeUint64(uint64_t value) = 0; + virtual Result OnOpcodeF32(uint32_t value) = 0; + virtual Result OnOpcodeF64(uint64_t value) = 0; + virtual Result OnOpcodeBlockSig(uint32_t num_types, Type* sig_types) = 0; + virtual Result OnBinaryExpr(Opcode opcode) = 0; + virtual Result OnBlockExpr(uint32_t num_types, Type* sig_types) = 0; + virtual Result OnBrExpr(uint32_t depth) = 0; + virtual Result OnBrIfExpr(uint32_t depth) = 0; + virtual Result OnBrTableExpr(uint32_t num_targets, + uint32_t* target_depths, + uint32_t default_target_depth) = 0; + virtual Result OnCallExpr(uint32_t func_index) = 0; + virtual Result OnCallIndirectExpr(uint32_t sig_index) = 0; + virtual Result OnCompareExpr(Opcode opcode) = 0; + virtual Result OnConvertExpr(Opcode opcode) = 0; + virtual Result OnCurrentMemoryExpr() = 0; + virtual Result OnDropExpr() = 0; + virtual Result OnElseExpr() = 0; + virtual Result OnEndExpr() = 0; + virtual Result OnEndFunc() = 0; + virtual Result OnF32ConstExpr(uint32_t value_bits) = 0; + virtual Result OnF64ConstExpr(uint64_t value_bits) = 0; + virtual Result OnGetGlobalExpr(uint32_t global_index) = 0; + virtual Result OnGetLocalExpr(uint32_t local_index) = 0; + virtual Result OnGrowMemoryExpr() = 0; + virtual Result OnI32ConstExpr(uint32_t value) = 0; + virtual Result OnI64ConstExpr(uint64_t value) = 0; + virtual Result OnIfExpr(uint32_t num_types, Type* sig_types) = 0; + virtual Result OnLoadExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) = 0; + virtual Result OnLoopExpr(uint32_t num_types, Type* sig_types) = 0; + virtual Result OnNopExpr() = 0; + virtual Result OnReturnExpr() = 0; + virtual Result OnSelectExpr() = 0; + virtual Result OnSetGlobalExpr(uint32_t global_index) = 0; + virtual Result OnSetLocalExpr(uint32_t local_index) = 0; + virtual Result OnStoreExpr(Opcode opcode, + uint32_t alignment_log2, + uint32_t offset) = 0; + virtual Result OnTeeLocalExpr(uint32_t local_index) = 0; + virtual Result OnUnaryExpr(Opcode opcode) = 0; + virtual Result OnUnreachableExpr() = 0; + virtual Result EndFunctionBody(uint32_t index) = 0; + virtual Result EndCodeSection() = 0; + + /* Elem section */ + virtual Result BeginElemSection(uint32_t size) = 0; + virtual Result OnElemSegmentCount(uint32_t count) = 0; + virtual Result BeginElemSegment(uint32_t index, uint32_t table_index) = 0; + virtual Result BeginElemSegmentInitExpr(uint32_t index) = 0; + virtual Result EndElemSegmentInitExpr(uint32_t index) = 0; + virtual Result OnElemSegmentFunctionIndexCount(uint32_t index, + uint32_t count) = 0; + virtual Result OnElemSegmentFunctionIndex(uint32_t index, + uint32_t func_index) = 0; + virtual Result EndElemSegment(uint32_t index) = 0; + virtual Result EndElemSection() = 0; + + /* Data section */ + virtual Result BeginDataSection(uint32_t size) = 0; + virtual Result OnDataSegmentCount(uint32_t count) = 0; + virtual Result BeginDataSegment(uint32_t index, uint32_t memory_index) = 0; + virtual Result BeginDataSegmentInitExpr(uint32_t index) = 0; + virtual Result EndDataSegmentInitExpr(uint32_t index) = 0; + virtual Result OnDataSegmentData(uint32_t index, + const void* data, + uint32_t size) = 0; + virtual Result EndDataSegment(uint32_t index) = 0; + virtual Result EndDataSection() = 0; + + /* Names section */ + virtual Result BeginNamesSection(uint32_t size) = 0; + virtual Result OnFunctionNameSubsection(uint32_t index, + uint32_t name_type, + uint32_t subsection_size) = 0; + virtual Result OnFunctionNamesCount(uint32_t num_functions) = 0; + virtual Result OnFunctionName(uint32_t function_index, + StringSlice function_name) = 0; + virtual Result OnLocalNameSubsection(uint32_t index, + uint32_t name_type, + uint32_t subsection_size) = 0; + virtual Result OnLocalNameFunctionCount(uint32_t num_functions) = 0; + virtual Result OnLocalNameLocalCount(uint32_t function_index, + uint32_t num_locals) = 0; + virtual Result OnLocalName(uint32_t function_index, + uint32_t local_index, + StringSlice local_name) = 0; + virtual Result EndNamesSection() = 0; + + /* Reloc section */ + virtual Result BeginRelocSection(uint32_t size) = 0; + virtual Result OnRelocCount(uint32_t count, + BinarySection section_code, + StringSlice section_name) = 0; + virtual Result OnReloc(RelocType type, + uint32_t offset, + uint32_t index, + int32_t addend) = 0; + virtual Result EndRelocSection() = 0; + + /* InitExpr - used by elem, data and global sections; these functions are + * only called between calls to Begin*InitExpr and End*InitExpr */ + virtual Result OnInitExprF32ConstExpr(uint32_t index, uint32_t value) = 0; + virtual Result OnInitExprF64ConstExpr(uint32_t index, uint64_t value) = 0; + virtual Result OnInitExprGetGlobalExpr(uint32_t index, + uint32_t global_index) = 0; + virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value) = 0; + virtual Result OnInitExprI64ConstExpr(uint32_t index, uint64_t value) = 0; + + const State* state = nullptr; }; Result read_binary(const void* data, size_t size, BinaryReader* reader, - uint32_t num_function_passes, const ReadBinaryOptions* options); size_t read_u32_leb128(const uint8_t* ptr, diff --git a/src/tools/wasm-link.cc b/src/tools/wasm-link.cc index 4fbce6bc..602fdcec 100644 --- a/src/tools/wasm-link.cc +++ b/src/tools/wasm-link.cc @@ -128,11 +128,13 @@ Section::Section() payload_size(0), payload_offset(0), count(0), - output_payload_offset(0) {} + output_payload_offset(0) { + WABT_ZERO_MEMORY(data); +} Section::~Section() { if (section_code == BinarySection::Data) { - delete data_segments; + delete data.data_segments; } } @@ -359,7 +361,7 @@ static void write_memory_section(Context* ctx, limits.has_max = true; for (size_t i = 0; i < sections.size(); i++) { Section* sec = sections[i]; - limits.initial += sec->memory_limits.initial; + limits.initial += sec->data.memory_limits.initial; } limits.max = limits.initial; write_limits(stream, &limits); @@ -466,8 +468,8 @@ static void write_data_section(Context* ctx, write_u32_leb128(stream, total_count, "data segment count"); for (size_t i = 0; i < sections.size(); i++) { Section* sec = sections[i]; - for (size_t j = 0; j < sec->data_segments->size(); j++) { - const DataSegment& segment = (*sec->data_segments)[j]; + for (size_t j = 0; j < sec->data.data_segments->size(); j++) { + const DataSegment& segment = (*sec->data.data_segments)[j]; write_data_segment(stream, segment, sec->binary->memory_page_offset * WABT_PAGE_SIZE); } diff --git a/src/wasm-link.h b/src/wasm-link.h index 6ddbe148..cb978de0 100644 --- a/src/wasm-link.h +++ b/src/wasm-link.h @@ -83,12 +83,12 @@ struct Section { union { /* CUSTOM section data */ - SectionDataCustom data_custom; + SectionDataCustom custom; /* DATA section data */ std::vector<DataSegment>* data_segments; /* MEMORY section data */ Limits memory_limits; - }; + } data; /* The offset at which this section appears within the combined output * section. */ |