summaryrefslogtreecommitdiff
path: root/src/binary-reader-interpreter.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/binary-reader-interpreter.cc')
-rw-r--r--src/binary-reader-interpreter.cc1763
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);