summaryrefslogtreecommitdiff
path: root/src/binary-reader-ir.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/binary-reader-ir.cc')
-rw-r--r--src/binary-reader-ir.cc908
1 files changed, 908 insertions, 0 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
new file mode 100644
index 00000000..b39dd89b
--- /dev/null
+++ b/src/binary-reader-ir.cc
@@ -0,0 +1,908 @@
+/*
+ * Copyright 2016 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "binary-reader-ir.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <vector>
+
+#include "binary-error-handler.h"
+#include "binary-reader-nop.h"
+#include "common.h"
+#include "ir.h"
+
+#define CHECK_RESULT(expr) \
+ do { \
+ if (WABT_FAILED(expr)) \
+ return Result::Error; \
+ } while (0)
+
+namespace wabt {
+
+namespace {
+
+struct LabelNode {
+ LabelNode(LabelType, Expr** first);
+
+ LabelType label_type;
+ Expr** first;
+ Expr* last;
+};
+
+LabelNode::LabelNode(LabelType label_type, Expr** first)
+ : label_type(label_type), first(first), last(nullptr) {}
+
+class BinaryReaderIR : public BinaryReaderNop {
+ public:
+ BinaryReaderIR(Module* out_module, BinaryErrorHandler* error_handler);
+
+ virtual bool OnError(const char* message);
+
+ virtual Result OnTypeCount(uint32_t count);
+ virtual Result OnType(uint32_t index,
+ uint32_t param_count,
+ Type* param_types,
+ uint32_t result_count,
+ Type* result_types);
+
+ virtual Result OnImportCount(uint32_t count);
+ virtual Result OnImport(uint32_t index,
+ StringSlice module_name,
+ StringSlice field_name);
+ virtual Result OnImportFunc(uint32_t import_index,
+ StringSlice module_name,
+ StringSlice field_name,
+ uint32_t func_index,
+ uint32_t sig_index);
+ virtual Result OnImportTable(uint32_t import_index,
+ StringSlice module_name,
+ StringSlice field_name,
+ uint32_t table_index,
+ Type elem_type,
+ const Limits* elem_limits);
+ virtual Result OnImportMemory(uint32_t import_index,
+ StringSlice module_name,
+ StringSlice field_name,
+ uint32_t memory_index,
+ const Limits* page_limits);
+ virtual Result OnImportGlobal(uint32_t import_index,
+ StringSlice module_name,
+ StringSlice field_name,
+ uint32_t global_index,
+ Type type,
+ bool mutable_);
+
+ virtual Result OnFunctionCount(uint32_t count);
+ virtual Result OnFunction(uint32_t index, uint32_t sig_index);
+
+ virtual Result OnTableCount(uint32_t count);
+ virtual Result OnTable(uint32_t index,
+ Type elem_type,
+ const Limits* elem_limits);
+
+ virtual Result OnMemoryCount(uint32_t count);
+ virtual Result OnMemory(uint32_t index, const Limits* limits);
+
+ virtual Result OnGlobalCount(uint32_t count);
+ virtual Result BeginGlobal(uint32_t index, Type type, bool mutable_);
+ virtual Result BeginGlobalInitExpr(uint32_t index);
+ virtual Result EndGlobalInitExpr(uint32_t index);
+
+ virtual Result OnExportCount(uint32_t count);
+ virtual Result OnExport(uint32_t index,
+ ExternalKind kind,
+ uint32_t item_index,
+ StringSlice name);
+
+ virtual Result OnStartFunction(uint32_t func_index);
+
+ virtual Result OnFunctionBodyCount(uint32_t count);
+ virtual Result BeginFunctionBody(uint32_t index);
+ virtual Result OnLocalDecl(uint32_t decl_index, uint32_t count, Type type);
+
+ virtual Result OnBinaryExpr(Opcode opcode);
+ virtual Result OnBlockExpr(uint32_t num_types, Type* sig_types);
+ virtual Result OnBrExpr(uint32_t depth);
+ virtual Result OnBrIfExpr(uint32_t depth);
+ virtual Result OnBrTableExpr(uint32_t num_targets,
+ uint32_t* target_depths,
+ uint32_t default_target_depth);
+ virtual Result OnCallExpr(uint32_t func_index);
+ virtual Result OnCallIndirectExpr(uint32_t sig_index);
+ virtual Result OnCompareExpr(Opcode opcode);
+ virtual Result OnConvertExpr(Opcode opcode);
+ virtual Result OnDropExpr();
+ virtual Result OnElseExpr();
+ virtual Result OnEndExpr();
+ virtual Result OnF32ConstExpr(uint32_t value_bits);
+ virtual Result OnF64ConstExpr(uint64_t value_bits);
+ virtual Result OnGetGlobalExpr(uint32_t global_index);
+ virtual Result OnGetLocalExpr(uint32_t local_index);
+ virtual Result OnGrowMemoryExpr();
+ virtual Result OnI32ConstExpr(uint32_t value);
+ virtual Result OnI64ConstExpr(uint64_t value);
+ virtual Result OnIfExpr(uint32_t num_types, Type* sig_types);
+ virtual Result OnLoadExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ uint32_t offset);
+ virtual Result OnLoopExpr(uint32_t num_types, Type* sig_types);
+ virtual Result OnCurrentMemoryExpr();
+ virtual Result OnNopExpr();
+ virtual Result OnReturnExpr();
+ virtual Result OnSelectExpr();
+ virtual Result OnSetGlobalExpr(uint32_t global_index);
+ virtual Result OnSetLocalExpr(uint32_t local_index);
+ virtual Result OnStoreExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ uint32_t offset);
+ virtual Result OnTeeLocalExpr(uint32_t local_index);
+ virtual Result OnUnaryExpr(Opcode opcode);
+ virtual Result OnUnreachableExpr();
+ virtual Result EndFunctionBody(uint32_t index);
+
+ virtual Result OnElemSegmentCount(uint32_t count);
+ virtual Result BeginElemSegment(uint32_t index, uint32_t table_index);
+ virtual Result BeginElemSegmentInitExpr(uint32_t index);
+ virtual Result EndElemSegmentInitExpr(uint32_t index);
+ virtual Result OnElemSegmentFunctionIndexCount(uint32_t index,
+ uint32_t count);
+ virtual Result OnElemSegmentFunctionIndex(uint32_t index,
+ uint32_t func_index);
+
+ virtual Result OnDataSegmentCount(uint32_t count);
+ virtual Result BeginDataSegment(uint32_t index, uint32_t memory_index);
+ virtual Result BeginDataSegmentInitExpr(uint32_t index);
+ virtual Result EndDataSegmentInitExpr(uint32_t index);
+ virtual Result OnDataSegmentData(uint32_t index,
+ const void* data,
+ uint32_t size);
+
+ virtual Result OnFunctionNamesCount(uint32_t num_functions);
+ virtual Result OnFunctionName(uint32_t function_index,
+ StringSlice function_name);
+ virtual Result OnLocalNameLocalCount(uint32_t function_index,
+ uint32_t num_locals);
+ virtual Result OnLocalName(uint32_t function_index,
+ uint32_t local_index,
+ StringSlice local_name);
+
+ virtual Result OnInitExprF32ConstExpr(uint32_t index, uint32_t value);
+ virtual Result OnInitExprF64ConstExpr(uint32_t index, uint64_t value);
+ virtual Result OnInitExprGetGlobalExpr(uint32_t index, uint32_t global_index);
+ virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value);
+ virtual Result OnInitExprI64ConstExpr(uint32_t index, uint64_t value);
+
+ private:
+ bool HandleError(uint32_t offset, const char* message);
+ void PrintError(const char* format, ...);
+ void PushLabel(LabelType label_type, Expr** first);
+ Result PopLabel();
+ Result GetLabelAt(LabelNode** label, uint32_t depth);
+ Result TopLabel(LabelNode** label);
+ Result AppendExpr(Expr* expr);
+
+ BinaryErrorHandler* error_handler = nullptr;
+ Module* module = nullptr;
+
+ Func* current_func = nullptr;
+ std::vector<LabelNode> label_stack;
+ uint32_t max_depth = 0;
+ Expr** current_init_expr = nullptr;
+};
+
+BinaryReaderIR::BinaryReaderIR(Module* out_module,
+ BinaryErrorHandler* error_handler)
+ : error_handler(error_handler), module(out_module) {}
+
+void WABT_PRINTF_FORMAT(2, 3) BinaryReaderIR::PrintError(const char* format,
+ ...) {
+ WABT_SNPRINTF_ALLOCA(buffer, length, format);
+ HandleError(WABT_UNKNOWN_OFFSET, buffer);
+}
+
+void BinaryReaderIR::PushLabel(LabelType label_type, Expr** first) {
+ max_depth++;
+ label_stack.emplace_back(label_type, first);
+}
+
+Result BinaryReaderIR::PopLabel() {
+ if (label_stack.size() == 0) {
+ PrintError("popping empty label stack");
+ return Result::Error;
+ }
+
+ max_depth--;
+ label_stack.pop_back();
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::GetLabelAt(LabelNode** label, uint32_t depth) {
+ if (depth >= label_stack.size()) {
+ PrintError("accessing stack depth: %u >= max: %" PRIzd, depth,
+ label_stack.size());
+ return Result::Error;
+ }
+
+ *label = &label_stack[label_stack.size() - depth - 1];
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::TopLabel(LabelNode** label) {
+ return GetLabelAt(label, 0);
+}
+
+Result BinaryReaderIR::AppendExpr(Expr* expr) {
+ LabelNode* label;
+ if (WABT_FAILED(TopLabel(&label))) {
+ delete expr;
+ return Result::Error;
+ }
+ if (*label->first) {
+ label->last->next = expr;
+ label->last = expr;
+ } else {
+ *label->first = label->last = expr;
+ }
+ return Result::Ok;
+}
+
+bool BinaryReaderIR::HandleError(uint32_t offset, const char* message) {
+ return error_handler->OnError(offset, message);
+}
+
+bool BinaryReaderIR::OnError(const char* message) {
+ return HandleError(state->offset, message);
+}
+
+Result BinaryReaderIR::OnTypeCount(uint32_t count) {
+ module->func_types.reserve(count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnType(uint32_t index,
+ uint32_t param_count,
+ Type* param_types,
+ uint32_t result_count,
+ Type* result_types) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::FuncType;
+ field->func_type = new FuncType();
+
+ FuncType* func_type = field->func_type;
+ func_type->sig.param_types.assign(param_types, param_types + param_count);
+ func_type->sig.result_types.assign(result_types, result_types + result_count);
+ module->func_types.push_back(func_type);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnImportCount(uint32_t count) {
+ module->imports.reserve(count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnImport(uint32_t index,
+ StringSlice module_name,
+ StringSlice field_name) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::Import;
+ field->import = new Import();
+
+ Import* import = field->import;
+ import->module_name = dup_string_slice(module_name);
+ import->field_name = dup_string_slice(field_name);
+ module->imports.push_back(import);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnImportFunc(uint32_t import_index,
+ StringSlice module_name,
+ StringSlice field_name,
+ uint32_t func_index,
+ uint32_t sig_index) {
+ assert(import_index == module->imports.size() - 1);
+ Import* import = module->imports[import_index];
+
+ import->kind = ExternalKind::Func;
+ import->func = new Func();
+ import->func->decl.has_func_type = true;
+ import->func->decl.type_var.type = VarType::Index;
+ import->func->decl.type_var.index = sig_index;
+ import->func->decl.sig = module->func_types[sig_index]->sig;
+
+ module->funcs.push_back(import->func);
+ module->num_func_imports++;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnImportTable(uint32_t import_index,
+ StringSlice module_name,
+ StringSlice field_name,
+ uint32_t table_index,
+ Type elem_type,
+ const Limits* elem_limits) {
+ assert(import_index == module->imports.size() - 1);
+ Import* import = module->imports[import_index];
+ import->kind = ExternalKind::Table;
+ import->table = new Table();
+ import->table->elem_limits = *elem_limits;
+ module->tables.push_back(import->table);
+ module->num_table_imports++;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnImportMemory(uint32_t import_index,
+ StringSlice module_name,
+ StringSlice field_name,
+ uint32_t memory_index,
+ const Limits* page_limits) {
+ assert(import_index == module->imports.size() - 1);
+ Import* import = module->imports[import_index];
+ import->kind = ExternalKind::Memory;
+ import->memory = new Memory();
+ import->memory->page_limits = *page_limits;
+ module->memories.push_back(import->memory);
+ module->num_memory_imports++;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnImportGlobal(uint32_t import_index,
+ StringSlice module_name,
+ StringSlice field_name,
+ uint32_t global_index,
+ Type type,
+ bool mutable_) {
+ assert(import_index == module->imports.size() - 1);
+ Import* import = module->imports[import_index];
+ import->kind = ExternalKind::Global;
+ import->global = new Global();
+ import->global->type = type;
+ import->global->mutable_ = mutable_;
+ module->globals.push_back(import->global);
+ module->num_global_imports++;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnFunctionCount(uint32_t count) {
+ module->funcs.reserve(module->num_func_imports + count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnFunction(uint32_t index, uint32_t sig_index) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::Func;
+ field->func = new Func();
+
+ Func* func = field->func;
+ func->decl.has_func_type = true;
+ func->decl.type_var.type = VarType::Index;
+ func->decl.type_var.index = sig_index;
+ func->decl.sig = module->func_types[sig_index]->sig;
+
+ module->funcs.push_back(func);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnTableCount(uint32_t count) {
+ module->tables.reserve(module->num_table_imports + count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnTable(uint32_t index,
+ Type elem_type,
+ const Limits* elem_limits) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::Table;
+ field->table = new Table();
+ field->table->elem_limits = *elem_limits;
+ module->tables.push_back(field->table);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnMemoryCount(uint32_t count) {
+ module->memories.reserve(module->num_memory_imports + count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnMemory(uint32_t index, const Limits* page_limits) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::Memory;
+ field->memory = new Memory();
+ field->memory->page_limits = *page_limits;
+ module->memories.push_back(field->memory);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnGlobalCount(uint32_t count) {
+ module->globals.reserve(module->num_global_imports + count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::BeginGlobal(uint32_t index, Type type, bool mutable_) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::Global;
+ field->global = new Global();
+ field->global->type = type;
+ field->global->mutable_ = mutable_;
+ module->globals.push_back(field->global);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::BeginGlobalInitExpr(uint32_t index) {
+ assert(index == module->globals.size() - 1);
+ Global* global = module->globals[index];
+ current_init_expr = &global->init_expr;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::EndGlobalInitExpr(uint32_t index) {
+ current_init_expr = nullptr;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnExportCount(uint32_t count) {
+ module->exports.reserve(count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnExport(uint32_t index,
+ ExternalKind kind,
+ uint32_t item_index,
+ StringSlice name) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::Export;
+ field->export_ = new Export();
+
+ Export* export_ = field->export_;
+ export_->name = dup_string_slice(name);
+ switch (kind) {
+ case ExternalKind::Func:
+ assert(item_index < module->funcs.size());
+ break;
+ case ExternalKind::Table:
+ assert(item_index < module->tables.size());
+ break;
+ case ExternalKind::Memory:
+ assert(item_index < module->memories.size());
+ break;
+ case ExternalKind::Global:
+ assert(item_index < module->globals.size());
+ break;
+ }
+ export_->var.type = VarType::Index;
+ export_->var.index = item_index;
+ export_->kind = kind;
+ module->exports.push_back(export_);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnStartFunction(uint32_t func_index) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::Start;
+
+ field->start.type = VarType::Index;
+ assert(func_index < module->funcs.size());
+ field->start.index = func_index;
+
+ module->start = &field->start;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnFunctionBodyCount(uint32_t count) {
+ assert(module->num_func_imports + count == module->funcs.size());
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::BeginFunctionBody(uint32_t index) {
+ current_func = module->funcs[index];
+ PushLabel(LabelType::Func, &current_func->first_expr);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnLocalDecl(uint32_t decl_index,
+ uint32_t count,
+ Type type) {
+ TypeVector& types = current_func->local_types;
+ types.reserve(types.size() + count);
+ for (size_t i = 0; i < count; ++i)
+ types.push_back(type);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnBinaryExpr(Opcode opcode) {
+ Expr* expr = Expr::CreateBinary(opcode);
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnBlockExpr(uint32_t num_types, Type* sig_types) {
+ Expr* expr = Expr::CreateBlock(new Block());
+ expr->block->sig.assign(sig_types, sig_types + num_types);
+ AppendExpr(expr);
+ PushLabel(LabelType::Block, &expr->block->first);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnBrExpr(uint32_t depth) {
+ Expr* expr = Expr::CreateBr(Var(depth));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnBrIfExpr(uint32_t depth) {
+ Expr* expr = Expr::CreateBrIf(Var(depth));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnBrTableExpr(uint32_t num_targets,
+ uint32_t* target_depths,
+ uint32_t default_target_depth) {
+ VarVector* targets = new VarVector();
+ targets->resize(num_targets);
+ for (uint32_t i = 0; i < num_targets; ++i) {
+ (*targets)[i] = Var(target_depths[i]);
+ }
+ Expr* expr = Expr::CreateBrTable(targets, Var(default_target_depth));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnCallExpr(uint32_t func_index) {
+ assert(func_index < module->funcs.size());
+ Expr* expr = Expr::CreateCall(Var(func_index));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnCallIndirectExpr(uint32_t sig_index) {
+ assert(sig_index < module->func_types.size());
+ Expr* expr = Expr::CreateCallIndirect(Var(sig_index));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnCompareExpr(Opcode opcode) {
+ Expr* expr = Expr::CreateCompare(opcode);
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnConvertExpr(Opcode opcode) {
+ Expr* expr = Expr::CreateConvert(opcode);
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnCurrentMemoryExpr() {
+ Expr* expr = Expr::CreateCurrentMemory();
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnDropExpr() {
+ Expr* expr = Expr::CreateDrop();
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnElseExpr() {
+ LabelNode* label;
+ CHECK_RESULT(TopLabel(&label));
+ if (label->label_type != LabelType::If) {
+ PrintError("else expression without matching if");
+ return Result::Error;
+ }
+
+ LabelNode* parent_label;
+ CHECK_RESULT(GetLabelAt(&parent_label, 1));
+ assert(parent_label->last->type == ExprType::If);
+
+ label->label_type = LabelType::Else;
+ label->first = &parent_label->last->if_.false_;
+ label->last = nullptr;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnEndExpr() {
+ return PopLabel();
+}
+
+Result BinaryReaderIR::OnF32ConstExpr(uint32_t value_bits) {
+ Expr* expr = Expr::CreateConst(Const(Const::F32(), value_bits));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnF64ConstExpr(uint64_t value_bits) {
+ Expr* expr = Expr::CreateConst(Const(Const::F64(), value_bits));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnGetGlobalExpr(uint32_t global_index) {
+ Expr* expr = Expr::CreateGetGlobal(Var(global_index));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnGetLocalExpr(uint32_t local_index) {
+ Expr* expr = Expr::CreateGetLocal(Var(local_index));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnGrowMemoryExpr() {
+ Expr* expr = Expr::CreateGrowMemory();
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnI32ConstExpr(uint32_t value) {
+ Expr* expr = Expr::CreateConst(Const(Const::I32(), value));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnI64ConstExpr(uint64_t value) {
+ Expr* expr = Expr::CreateConst(Const(Const::I64(), value));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnIfExpr(uint32_t num_types, Type* sig_types) {
+ Expr* expr = Expr::CreateIf(new Block());
+ expr->if_.true_->sig.assign(sig_types, sig_types + num_types);
+ expr->if_.false_ = nullptr;
+ AppendExpr(expr);
+ PushLabel(LabelType::If, &expr->if_.true_->first);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnLoadExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ uint32_t offset) {
+ Expr* expr = Expr::CreateLoad(opcode, 1 << alignment_log2, offset);
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnLoopExpr(uint32_t num_types, Type* sig_types) {
+ Expr* expr = Expr::CreateLoop(new Block());
+ expr->loop->sig.assign(sig_types, sig_types + num_types);
+ AppendExpr(expr);
+ PushLabel(LabelType::Loop, &expr->loop->first);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnNopExpr() {
+ Expr* expr = Expr::CreateNop();
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnReturnExpr() {
+ Expr* expr = Expr::CreateReturn();
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnSelectExpr() {
+ Expr* expr = Expr::CreateSelect();
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnSetGlobalExpr(uint32_t global_index) {
+ Expr* expr = Expr::CreateSetGlobal(Var(global_index));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnSetLocalExpr(uint32_t local_index) {
+ Expr* expr = Expr::CreateSetLocal(Var(local_index));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnStoreExpr(Opcode opcode,
+ uint32_t alignment_log2,
+ uint32_t offset) {
+ Expr* expr = Expr::CreateStore(opcode, 1 << alignment_log2, offset);
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnTeeLocalExpr(uint32_t local_index) {
+ Expr* expr = Expr::CreateTeeLocal(Var(local_index));
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnUnaryExpr(Opcode opcode) {
+ Expr* expr = Expr::CreateUnary(opcode);
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::OnUnreachableExpr() {
+ Expr* expr = Expr::CreateUnreachable();
+ return AppendExpr(expr);
+}
+
+Result BinaryReaderIR::EndFunctionBody(uint32_t index) {
+ CHECK_RESULT(PopLabel());
+ current_func = nullptr;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnElemSegmentCount(uint32_t count) {
+ module->elem_segments.reserve(count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::BeginElemSegment(uint32_t index, uint32_t table_index) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::ElemSegment;
+ field->elem_segment = new ElemSegment();
+ field->elem_segment->table_var.type = VarType::Index;
+ field->elem_segment->table_var.index = table_index;
+ module->elem_segments.push_back(field->elem_segment);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::BeginElemSegmentInitExpr(uint32_t index) {
+ assert(index == module->elem_segments.size() - 1);
+ ElemSegment* segment = module->elem_segments[index];
+ current_init_expr = &segment->offset;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::EndElemSegmentInitExpr(uint32_t index) {
+ current_init_expr = nullptr;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnElemSegmentFunctionIndexCount(uint32_t index,
+ uint32_t count) {
+ assert(index == module->elem_segments.size() - 1);
+ ElemSegment* segment = module->elem_segments[index];
+ segment->vars.reserve(count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnElemSegmentFunctionIndex(uint32_t index,
+ uint32_t func_index) {
+ assert(index == module->elem_segments.size() - 1);
+ ElemSegment* segment = module->elem_segments[index];
+ segment->vars.emplace_back();
+ Var* var = &segment->vars.back();
+ var->type = VarType::Index;
+ var->index = func_index;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnDataSegmentCount(uint32_t count) {
+ module->data_segments.reserve(count);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::BeginDataSegment(uint32_t index,
+ uint32_t memory_index) {
+ ModuleField* field = append_module_field(module);
+ field->type = ModuleFieldType::DataSegment;
+ field->data_segment = new DataSegment();
+ field->data_segment->memory_var.type = VarType::Index;
+ field->data_segment->memory_var.index = memory_index;
+ module->data_segments.push_back(field->data_segment);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::BeginDataSegmentInitExpr(uint32_t index) {
+ assert(index == module->data_segments.size() - 1);
+ DataSegment* segment = module->data_segments[index];
+ current_init_expr = &segment->offset;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::EndDataSegmentInitExpr(uint32_t index) {
+ current_init_expr = nullptr;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnDataSegmentData(uint32_t index,
+ const void* data,
+ uint32_t size) {
+ assert(index == module->data_segments.size() - 1);
+ DataSegment* segment = module->data_segments[index];
+ segment->data = new char[size];
+ segment->size = size;
+ memcpy(segment->data, data, size);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnFunctionNamesCount(uint32_t count) {
+ if (count > module->funcs.size()) {
+ PrintError("expected function name count (%u) <= function count (%" PRIzd
+ ")",
+ count, module->funcs.size());
+ return Result::Error;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnFunctionName(uint32_t index, StringSlice name) {
+ if (string_slice_is_empty(&name))
+ return Result::Ok;
+
+ module->func_bindings.emplace(string_slice_to_string(name), Binding(index));
+ Func* func = module->funcs[index];
+ func->name = dup_string_slice(name);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnLocalNameLocalCount(uint32_t index, uint32_t count) {
+ assert(index < module->funcs.size());
+ Func* func = module->funcs[index];
+ uint32_t num_params_and_locals = get_num_params_and_locals(func);
+ if (count > num_params_and_locals) {
+ PrintError("expected local name count (%d) <= local count (%d)", count,
+ num_params_and_locals);
+ return Result::Error;
+ }
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnInitExprF32ConstExpr(uint32_t index, uint32_t value) {
+ *current_init_expr = Expr::CreateConst(Const(Const::F32(), value));
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnInitExprF64ConstExpr(uint32_t index, uint64_t value) {
+ *current_init_expr = Expr::CreateConst(Const(Const::F64(), value));
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnInitExprGetGlobalExpr(uint32_t index,
+ uint32_t global_index) {
+ *current_init_expr = Expr::CreateGetGlobal(Var(global_index));
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnInitExprI32ConstExpr(uint32_t index, uint32_t value) {
+ *current_init_expr = Expr::CreateConst(Const(Const::I32(), value));
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnInitExprI64ConstExpr(uint32_t index, uint64_t value) {
+ *current_init_expr = Expr::CreateConst(Const(Const::I64(), value));
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnLocalName(uint32_t func_index,
+ uint32_t local_index,
+ StringSlice name) {
+ if (string_slice_is_empty(&name))
+ return Result::Ok;
+
+ Func* func = module->funcs[func_index];
+ uint32_t num_params = get_num_params(func);
+ BindingHash* bindings;
+ uint32_t index;
+ if (local_index < num_params) {
+ /* param name */
+ bindings = &func->param_bindings;
+ index = local_index;
+ } else {
+ /* local name */
+ bindings = &func->local_bindings;
+ index = local_index - num_params;
+ }
+ bindings->emplace(string_slice_to_string(name), Binding(index));
+ return Result::Ok;
+}
+
+} // namespace
+
+Result read_binary_ir(const void* data,
+ size_t size,
+ const ReadBinaryOptions* options,
+ BinaryErrorHandler* error_handler,
+ struct Module* out_module) {
+ BinaryReaderIR reader(out_module, error_handler);
+ Result result = read_binary(data, size, &reader, options);
+ return result;
+}
+
+} // namespace wabt