diff options
author | Ben Smith <binjimin@gmail.com> | 2017-03-30 14:17:29 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-30 14:17:29 -0700 |
commit | ca9ccccd10d1975eb117dd9ce05a189270f2fb01 (patch) | |
tree | 91bd0c8d5fb961fb5287eb77b0a34c199ac07357 /src/binary-reader-interpreter.cc | |
parent | 2e9e6ce3f5f4ccf2983338fb5353013d2a5bb94d (diff) | |
download | wabt-ca9ccccd10d1975eb117dd9ce05a189270f2fb01.tar.gz wabt-ca9ccccd10d1975eb117dd9ce05a189270f2fb01.tar.bz2 wabt-ca9ccccd10d1975eb117dd9ce05a189270f2fb01.zip |
Use classes + virtual functions for BinaryReader (#376)
This adds a few new classes:
* BinaryReader: the abstract base class
* BinaryReaderNop: implements all of BinaryReader, but does nothing
* BinaryReaderLogging: logs calls through BinaryReader, and forwards to
another BinaryReader
Typically this means we can remove the Context structs from these
implementations, since that data can just move into the BinaryReader
subclasses.
I also took the opportunity to rename the new member functions to
MixedCase instead of snake_case, since that's more common in C++.
Diffstat (limited to 'src/binary-reader-interpreter.cc')
-rw-r--r-- | src/binary-reader-interpreter.cc | 1763 |
1 files changed, 886 insertions, 877 deletions
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); |