| /* |
| * 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 |