diff options
Diffstat (limited to 'src/binary-reader-ir.cc')
-rw-r--r-- | src/binary-reader-ir.cc | 908 |
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, ¤t_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 |