/* * 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 "wabt/binary-reader-ir.h" #include #include #include #include #include #include #include #include "wabt/binary-reader-nop.h" #include "wabt/cast.h" #include "wabt/common.h" #include "wabt/ir.h" namespace wabt { namespace { struct LabelNode { LabelNode(LabelType, ExprList* exprs, Expr* context = nullptr); LabelType label_type; ExprList* exprs; Expr* context; }; LabelNode::LabelNode(LabelType label_type, ExprList* exprs, Expr* context) : label_type(label_type), exprs(exprs), context(context) {} class CodeMetadataExprQueue { private: struct Entry { Func* func; std::deque> func_queue; Entry(Func* f) : func(f) {} }; std::deque entries; public: CodeMetadataExprQueue() {} void push_func(Func* f) { entries.emplace_back(f); } void push_metadata(std::unique_ptr meta) { assert(!entries.empty()); entries.back().func_queue.push_back(std::move(meta)); } std::unique_ptr pop_match(Func* f, Offset offset) { std::unique_ptr ret; if (entries.empty()) { return ret; } auto& current_entry = entries.front(); if (current_entry.func != f) return ret; if (current_entry.func_queue.empty()) { entries.pop_front(); return ret; } auto& current_metadata = current_entry.func_queue.front(); if (current_metadata->loc.offset + current_entry.func->loc.offset != offset) { return ret; } current_metadata->loc = Location(offset); ret = std::move(current_metadata); current_entry.func_queue.pop_front(); return ret; } }; class BinaryReaderIR : public BinaryReaderNop { static constexpr size_t kMaxNestingDepth = 16384; // max depth of label stack static constexpr size_t kMaxFunctionLocals = 50000; // matches V8 static constexpr size_t kMaxFunctionParams = 1000; // matches V8 static constexpr size_t kMaxFunctionResults = 1000; // matches V8 public: BinaryReaderIR(Module* out_module, const char* filename, Errors* errors); bool OnError(const Error&) override; Result OnTypeCount(Index count) override; Result OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, Type* result_types) override; Result OnStructType(Index index, Index field_count, TypeMut* fields) override; Result OnArrayType(Index index, TypeMut field) override; Result OnImportCount(Index count) override; Result OnImportFunc(Index import_index, std::string_view module_name, std::string_view field_name, Index func_index, Index sig_index) override; Result OnImportTable(Index import_index, std::string_view module_name, std::string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) override; Result OnImportMemory(Index import_index, std::string_view module_name, std::string_view field_name, Index memory_index, const Limits* page_limits) override; Result OnImportGlobal(Index import_index, std::string_view module_name, std::string_view field_name, Index global_index, Type type, bool mutable_) override; Result OnImportTag(Index import_index, std::string_view module_name, std::string_view field_name, Index tag_index, Index sig_index) override; Result OnFunctionCount(Index count) override; Result OnFunction(Index index, Index sig_index) override; Result OnTableCount(Index count) override; Result OnTable(Index index, Type elem_type, const Limits* elem_limits) override; Result OnMemoryCount(Index count) override; Result OnMemory(Index index, const Limits* limits) override; Result OnGlobalCount(Index count) override; Result BeginGlobal(Index index, Type type, bool mutable_) override; Result BeginGlobalInitExpr(Index index) override; Result EndGlobalInitExpr(Index index) override; Result OnExportCount(Index count) override; Result OnExport(Index index, ExternalKind kind, Index item_index, std::string_view name) override; Result OnStartFunction(Index func_index) override; Result OnFunctionBodyCount(Index count) override; Result BeginFunctionBody(Index index, Offset size) override; Result OnLocalDecl(Index decl_index, Index count, Type type) override; Result OnOpcode(Opcode opcode) override; Result OnAtomicLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnAtomicStoreExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnAtomicRmwExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnAtomicRmwCmpxchgExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnAtomicWaitExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnAtomicFenceExpr(uint32_t consistency_model) override; Result OnAtomicNotifyExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnBinaryExpr(Opcode opcode) override; Result OnBlockExpr(Type sig_type) override; Result OnBrExpr(Index depth) override; Result OnBrIfExpr(Index depth) override; Result OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) override; Result OnCallExpr(Index func_index) override; Result OnCatchExpr(Index tag_index) override; Result OnCatchAllExpr() override; Result OnCallIndirectExpr(Index sig_index, Index table_index) override; Result OnCallRefExpr() override; Result OnReturnCallExpr(Index func_index) override; Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override; Result OnCompareExpr(Opcode opcode) override; Result OnConvertExpr(Opcode opcode) override; Result OnDelegateExpr(Index depth) override; Result OnDropExpr() override; Result OnElseExpr() override; Result OnEndExpr() override; Result OnF32ConstExpr(uint32_t value_bits) override; Result OnF64ConstExpr(uint64_t value_bits) override; Result OnV128ConstExpr(v128 value_bits) override; Result OnGlobalGetExpr(Index global_index) override; Result OnGlobalSetExpr(Index global_index) override; Result OnI32ConstExpr(uint32_t value) override; Result OnI64ConstExpr(uint64_t value) override; Result OnIfExpr(Type sig_type) override; Result OnLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnLocalGetExpr(Index local_index) override; Result OnLocalSetExpr(Index local_index) override; Result OnLocalTeeExpr(Index local_index) override; Result OnLoopExpr(Type sig_type) override; Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override; Result OnDataDropExpr(Index segment_index) override; Result OnMemoryFillExpr(Index memidx) override; Result OnMemoryGrowExpr(Index memidx) override; Result OnMemoryInitExpr(Index segment_index, Index memidx) override; Result OnMemorySizeExpr(Index memidx) override; Result OnTableCopyExpr(Index dst_index, Index src_index) override; Result OnElemDropExpr(Index segment_index) override; Result OnTableInitExpr(Index segment_index, Index table_index) override; Result OnTableGetExpr(Index table_index) override; Result OnTableSetExpr(Index table_index) override; Result OnTableGrowExpr(Index table_index) override; Result OnTableSizeExpr(Index table_index) override; Result OnTableFillExpr(Index table_index) override; Result OnRefFuncExpr(Index func_index) override; Result OnRefNullExpr(Type type) override; Result OnRefIsNullExpr() override; Result OnNopExpr() override; Result OnRethrowExpr(Index depth) override; Result OnReturnExpr() override; Result OnSelectExpr(Index result_count, Type* result_types) override; Result OnStoreExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnThrowExpr(Index tag_index) override; Result OnTryExpr(Type sig_type) override; Result OnUnaryExpr(Opcode opcode) override; Result OnTernaryExpr(Opcode opcode) override; Result OnUnreachableExpr() override; Result EndFunctionBody(Index index) override; Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override; Result OnSimdLoadLaneExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset, uint64_t value) override; Result OnSimdStoreLaneExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset, uint64_t value) override; Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override; Result OnLoadSplatExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnLoadZeroExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) override; Result OnElemSegmentCount(Index count) override; Result BeginElemSegment(Index index, Index table_index, uint8_t flags) override; Result BeginElemSegmentInitExpr(Index index) override; Result EndElemSegmentInitExpr(Index index) override; Result OnElemSegmentElemType(Index index, Type elem_type) override; Result OnElemSegmentElemExprCount(Index index, Index count) override; Result OnElemSegmentElemExpr_RefNull(Index segment_index, Type type) override; Result OnElemSegmentElemExpr_RefFunc(Index segment_index, Index func_index) override; Result OnDataSegmentCount(Index count) override; Result BeginDataSegment(Index index, Index memory_index, uint8_t flags) override; Result BeginDataSegmentInitExpr(Index index) override; Result EndDataSegmentInitExpr(Index index) override; Result OnDataSegmentData(Index index, const void* data, Address size) override; Result OnModuleName(std::string_view module_name) override; Result OnFunctionNamesCount(Index num_functions) override; Result OnFunctionName(Index function_index, std::string_view function_name) override; Result OnLocalNameLocalCount(Index function_index, Index num_locals) override; Result OnLocalName(Index function_index, Index local_index, std::string_view local_name) override; Result OnNameEntry(NameSectionSubsection type, Index index, std::string_view name) override; Result BeginTagSection(Offset size) override { return Result::Ok; } Result OnTagCount(Index count) override { return Result::Ok; } Result OnTagType(Index index, Index sig_index) override; Result EndTagSection() override { return Result::Ok; } Result OnDataSymbol(Index index, uint32_t flags, std::string_view name, Index segment, uint32_t offset, uint32_t size) override; Result OnFunctionSymbol(Index index, uint32_t flags, std::string_view name, Index func_index) override; Result OnGlobalSymbol(Index index, uint32_t flags, std::string_view name, Index global_index) override; Result OnSectionSymbol(Index index, uint32_t flags, Index section_index) override; /* Code Metadata sections */ Result BeginCodeMetadataSection(std::string_view name, Offset size) override; Result OnCodeMetadataFuncCount(Index count) override; Result OnCodeMetadataCount(Index function_index, Index count) override; Result OnCodeMetadata(Offset offset, const void* data, Address size) override; Result OnTagSymbol(Index index, uint32_t flags, std::string_view name, Index tag_index) override; Result OnTableSymbol(Index index, uint32_t flags, std::string_view name, Index table_index) override; private: Location GetLocation() const; void PrintError(const char* format, ...); Result PushLabel(LabelType label_type, ExprList* first, Expr* context = nullptr); Result BeginInitExpr(ExprList* init_expr); Result EndInitExpr(); Result PopLabel(); Result GetLabelAt(LabelNode** label, Index depth); Result TopLabel(LabelNode** label); Result TopLabelExpr(LabelNode** label, Expr** expr); Result AppendExpr(std::unique_ptr expr); Result AppendCatch(Catch&& catch_); void SetFuncDeclaration(FuncDeclaration* decl, Var var); void SetBlockDeclaration(BlockDeclaration* decl, Type sig_type); Result SetMemoryName(Index index, std::string_view name); Result SetTableName(Index index, std::string_view name); Result SetFunctionName(Index index, std::string_view name); Result SetTypeName(Index index, std::string_view name); Result SetGlobalName(Index index, std::string_view name); Result SetDataSegmentName(Index index, std::string_view name); Result SetElemSegmentName(Index index, std::string_view name); Result SetTagName(Index index, std::string_view name); std::string GetUniqueName(BindingHash* bindings, const std::string& original_name); Errors* errors_ = nullptr; Module* module_ = nullptr; Func* current_func_ = nullptr; std::vector label_stack_; const char* filename_; CodeMetadataExprQueue code_metadata_queue_; std::string_view current_metadata_name_; }; BinaryReaderIR::BinaryReaderIR(Module* out_module, const char* filename, Errors* errors) : errors_(errors), module_(out_module), filename_(filename) {} Location BinaryReaderIR::GetLocation() const { Location loc; loc.filename = filename_; loc.offset = state->offset; return loc; } void WABT_PRINTF_FORMAT(2, 3) BinaryReaderIR::PrintError(const char* format, ...) { WABT_SNPRINTF_ALLOCA(buffer, length, format); errors_->emplace_back(ErrorLevel::Error, Location(kInvalidOffset), buffer); } Result BinaryReaderIR::PushLabel(LabelType label_type, ExprList* first, Expr* context) { if (label_stack_.size() >= kMaxNestingDepth) { PrintError("label stack exceeds max nesting depth"); return Result::Error; } label_stack_.emplace_back(label_type, first, context); return Result::Ok; } Result BinaryReaderIR::PopLabel() { if (label_stack_.size() == 0) { PrintError("popping empty label stack"); return Result::Error; } label_stack_.pop_back(); return Result::Ok; } Result BinaryReaderIR::GetLabelAt(LabelNode** label, Index depth) { if (depth >= label_stack_.size()) { PrintError("accessing stack depth: %" PRIindex " >= 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::TopLabelExpr(LabelNode** label, Expr** expr) { CHECK_RESULT(TopLabel(label)); LabelNode* parent_label; CHECK_RESULT(GetLabelAt(&parent_label, 1)); if (parent_label->exprs->empty()) { PrintError("TopLabelExpr: parent label has empty expr list"); return Result::Error; } *expr = &parent_label->exprs->back(); return Result::Ok; } Result BinaryReaderIR::AppendExpr(std::unique_ptr expr) { expr->loc = GetLocation(); LabelNode* label; CHECK_RESULT(TopLabel(&label)); label->exprs->push_back(std::move(expr)); return Result::Ok; } void BinaryReaderIR::SetFuncDeclaration(FuncDeclaration* decl, Var var) { decl->has_func_type = true; decl->type_var = var; if (auto* func_type = module_->GetFuncType(var)) { decl->sig = func_type->sig; } } void BinaryReaderIR::SetBlockDeclaration(BlockDeclaration* decl, Type sig_type) { if (sig_type.IsIndex()) { Index type_index = sig_type.GetIndex(); SetFuncDeclaration(decl, Var(type_index, GetLocation())); } else { decl->has_func_type = false; decl->sig.param_types.clear(); decl->sig.result_types = sig_type.GetInlineVector(); } } std::string BinaryReaderIR::GetUniqueName(BindingHash* bindings, const std::string& orig_name) { int counter = 1; std::string unique_name = orig_name; while (bindings->count(unique_name) != 0) { unique_name = orig_name + "." + std::to_string(counter++); } return unique_name; } bool BinaryReaderIR::OnError(const Error& error) { errors_->push_back(error); return true; } Result BinaryReaderIR::OnTypeCount(Index count) { WABT_TRY module_->types.reserve(count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::OnFuncType(Index index, Index param_count, Type* param_types, Index result_count, Type* result_types) { if (param_count > kMaxFunctionParams) { PrintError("FuncType param count exceeds maximum value"); return Result::Error; } if (result_count > kMaxFunctionResults) { PrintError("FuncType result count exceeds maximum value"); return Result::Error; } auto field = std::make_unique(GetLocation()); auto func_type = std::make_unique(); func_type->sig.param_types.assign(param_types, param_types + param_count); func_type->sig.result_types.assign(result_types, result_types + result_count); field->type = std::move(func_type); module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::OnStructType(Index index, Index field_count, TypeMut* fields) { auto field = std::make_unique(GetLocation()); auto struct_type = std::make_unique(); struct_type->fields.resize(field_count); for (Index i = 0; i < field_count; ++i) { struct_type->fields[i].type = fields[i].type; struct_type->fields[i].mutable_ = fields[i].mutable_; } field->type = std::move(struct_type); module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::OnArrayType(Index index, TypeMut type_mut) { auto field = std::make_unique(GetLocation()); auto array_type = std::make_unique(); array_type->field.type = type_mut.type; array_type->field.mutable_ = type_mut.mutable_; field->type = std::move(array_type); module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::OnImportCount(Index count) { WABT_TRY module_->imports.reserve(count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::OnImportFunc(Index import_index, std::string_view module_name, std::string_view field_name, Index func_index, Index sig_index) { auto import = std::make_unique(); import->module_name = module_name; import->field_name = field_name; SetFuncDeclaration(&import->func.decl, Var(sig_index, GetLocation())); module_->AppendField( std::make_unique(std::move(import), GetLocation())); return Result::Ok; } Result BinaryReaderIR::OnImportTable(Index import_index, std::string_view module_name, std::string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) { auto import = std::make_unique(); import->module_name = module_name; import->field_name = field_name; import->table.elem_limits = *elem_limits; import->table.elem_type = elem_type; module_->AppendField( std::make_unique(std::move(import), GetLocation())); return Result::Ok; } Result BinaryReaderIR::OnImportMemory(Index import_index, std::string_view module_name, std::string_view field_name, Index memory_index, const Limits* page_limits) { auto import = std::make_unique(); import->module_name = module_name; import->field_name = field_name; import->memory.page_limits = *page_limits; module_->AppendField( std::make_unique(std::move(import), GetLocation())); return Result::Ok; } Result BinaryReaderIR::OnImportGlobal(Index import_index, std::string_view module_name, std::string_view field_name, Index global_index, Type type, bool mutable_) { auto import = std::make_unique(); import->module_name = module_name; import->field_name = field_name; import->global.type = type; import->global.mutable_ = mutable_; module_->AppendField( std::make_unique(std::move(import), GetLocation())); return Result::Ok; } Result BinaryReaderIR::OnImportTag(Index import_index, std::string_view module_name, std::string_view field_name, Index tag_index, Index sig_index) { auto import = std::make_unique(); import->module_name = module_name; import->field_name = field_name; SetFuncDeclaration(&import->tag.decl, Var(sig_index, GetLocation())); module_->AppendField( std::make_unique(std::move(import), GetLocation())); return Result::Ok; } Result BinaryReaderIR::OnFunctionCount(Index count) { WABT_TRY module_->funcs.reserve(module_->num_func_imports + count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::OnFunction(Index index, Index sig_index) { auto field = std::make_unique(GetLocation()); Func& func = field->func; SetFuncDeclaration(&func.decl, Var(sig_index, GetLocation())); module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::OnTableCount(Index count) { WABT_TRY module_->tables.reserve(module_->num_table_imports + count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::OnTable(Index index, Type elem_type, const Limits* elem_limits) { auto field = std::make_unique(GetLocation()); Table& table = field->table; table.elem_limits = *elem_limits; table.elem_type = elem_type; module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::OnMemoryCount(Index count) { WABT_TRY module_->memories.reserve(module_->num_memory_imports + count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::OnMemory(Index index, const Limits* page_limits) { auto field = std::make_unique(GetLocation()); Memory& memory = field->memory; memory.page_limits = *page_limits; module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::OnGlobalCount(Index count) { WABT_TRY module_->globals.reserve(module_->num_global_imports + count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::BeginGlobal(Index index, Type type, bool mutable_) { auto field = std::make_unique(GetLocation()); Global& global = field->global; global.type = type; global.mutable_ = mutable_; module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::BeginGlobalInitExpr(Index index) { assert(index == module_->globals.size() - 1); Global* global = module_->globals[index]; return BeginInitExpr(&global->init_expr); } Result BinaryReaderIR::EndGlobalInitExpr(Index index) { return EndInitExpr(); } Result BinaryReaderIR::OnExportCount(Index count) { WABT_TRY module_->exports.reserve(count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::OnExport(Index index, ExternalKind kind, Index item_index, std::string_view name) { auto field = std::make_unique(GetLocation()); Export& export_ = field->export_; export_.name = name; export_.var = Var(item_index, GetLocation()); export_.kind = kind; module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::OnStartFunction(Index func_index) { Var start(func_index, GetLocation()); module_->AppendField( std::make_unique(start, GetLocation())); return Result::Ok; } Result BinaryReaderIR::OnFunctionBodyCount(Index count) { // Can hit this case on a malformed module if we don't stop on first error. if (module_->num_func_imports + count != module_->funcs.size()) { PrintError( "number of imported func + func count in code section does not match " "actual number of funcs in module"); return Result::Error; } return Result::Ok; } Result BinaryReaderIR::BeginFunctionBody(Index index, Offset size) { current_func_ = module_->funcs[index]; current_func_->loc = GetLocation(); return PushLabel(LabelType::Func, ¤t_func_->exprs); } Result BinaryReaderIR::OnLocalDecl(Index decl_index, Index count, Type type) { current_func_->local_types.AppendDecl(type, count); if (current_func_->GetNumLocals() > kMaxFunctionLocals) { PrintError("function local count exceeds maximum value"); return Result::Error; } return Result::Ok; } Result BinaryReaderIR::OnOpcode(Opcode opcode) { std::unique_ptr metadata = code_metadata_queue_.pop_match(current_func_, GetLocation().offset - 1); if (metadata) { return AppendExpr(std::move(metadata)); } return Result::Ok; } Result BinaryReaderIR::OnAtomicLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnAtomicStoreExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnAtomicRmwExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnAtomicRmwCmpxchgExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnAtomicWaitExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnAtomicFenceExpr(uint32_t consistency_model) { return AppendExpr(std::make_unique(consistency_model)); } Result BinaryReaderIR::OnAtomicNotifyExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnBinaryExpr(Opcode opcode) { return AppendExpr(std::make_unique(opcode)); } Result BinaryReaderIR::OnBlockExpr(Type sig_type) { auto expr = std::make_unique(); SetBlockDeclaration(&expr->block.decl, sig_type); ExprList* expr_list = &expr->block.exprs; CHECK_RESULT(AppendExpr(std::move(expr))); return PushLabel(LabelType::Block, expr_list); } Result BinaryReaderIR::OnBrExpr(Index depth) { return AppendExpr(std::make_unique(Var(depth, GetLocation()))); } Result BinaryReaderIR::OnBrIfExpr(Index depth) { return AppendExpr(std::make_unique(Var(depth, GetLocation()))); } Result BinaryReaderIR::OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) { auto expr = std::make_unique(); expr->default_target = Var(default_target_depth, GetLocation()); expr->targets.resize(num_targets); for (Index i = 0; i < num_targets; ++i) { expr->targets[i] = Var(target_depths[i], GetLocation()); } return AppendExpr(std::move(expr)); } Result BinaryReaderIR::OnCallExpr(Index func_index) { return AppendExpr(std::make_unique(Var(func_index, GetLocation()))); } Result BinaryReaderIR::OnCallIndirectExpr(Index sig_index, Index table_index) { auto expr = std::make_unique(); SetFuncDeclaration(&expr->decl, Var(sig_index, GetLocation())); expr->table = Var(table_index, GetLocation()); return AppendExpr(std::move(expr)); } Result BinaryReaderIR::OnCallRefExpr() { return AppendExpr(std::make_unique()); } Result BinaryReaderIR::OnReturnCallExpr(Index func_index) { return AppendExpr( std::make_unique(Var(func_index, GetLocation()))); } Result BinaryReaderIR::OnReturnCallIndirectExpr(Index sig_index, Index table_index) { auto expr = std::make_unique(); SetFuncDeclaration(&expr->decl, Var(sig_index, GetLocation())); expr->table = Var(table_index, GetLocation()); return AppendExpr(std::move(expr)); } Result BinaryReaderIR::OnCompareExpr(Opcode opcode) { return AppendExpr(std::make_unique(opcode)); } Result BinaryReaderIR::OnConvertExpr(Opcode opcode) { return AppendExpr(std::make_unique(opcode)); } Result BinaryReaderIR::OnDropExpr() { return AppendExpr(std::make_unique()); } Result BinaryReaderIR::OnElseExpr() { LabelNode* label; Expr* expr; CHECK_RESULT(TopLabelExpr(&label, &expr)); if (label->label_type == LabelType::If) { auto* if_expr = cast(expr); if_expr->true_.end_loc = GetLocation(); label->exprs = &if_expr->false_; label->label_type = LabelType::Else; } else { PrintError("else expression without matching if"); return Result::Error; } return Result::Ok; } Result BinaryReaderIR::OnEndExpr() { if (label_stack_.size() > 1) { LabelNode* label; Expr* expr; CHECK_RESULT(TopLabelExpr(&label, &expr)); switch (label->label_type) { case LabelType::Block: cast(expr)->block.end_loc = GetLocation(); break; case LabelType::Loop: cast(expr)->block.end_loc = GetLocation(); break; case LabelType::If: cast(expr)->true_.end_loc = GetLocation(); break; case LabelType::Else: cast(expr)->false_end_loc = GetLocation(); break; case LabelType::Try: cast(expr)->block.end_loc = GetLocation(); break; case LabelType::InitExpr: case LabelType::Func: case LabelType::Catch: break; } } return PopLabel(); } Result BinaryReaderIR::OnF32ConstExpr(uint32_t value_bits) { return AppendExpr( std::make_unique(Const::F32(value_bits, GetLocation()))); } Result BinaryReaderIR::OnF64ConstExpr(uint64_t value_bits) { return AppendExpr( std::make_unique(Const::F64(value_bits, GetLocation()))); } Result BinaryReaderIR::OnV128ConstExpr(v128 value_bits) { return AppendExpr( std::make_unique(Const::V128(value_bits, GetLocation()))); } Result BinaryReaderIR::OnGlobalGetExpr(Index global_index) { return AppendExpr( std::make_unique(Var(global_index, GetLocation()))); } Result BinaryReaderIR::OnLocalGetExpr(Index local_index) { return AppendExpr( std::make_unique(Var(local_index, GetLocation()))); } Result BinaryReaderIR::OnI32ConstExpr(uint32_t value) { return AppendExpr( std::make_unique(Const::I32(value, GetLocation()))); } Result BinaryReaderIR::OnI64ConstExpr(uint64_t value) { return AppendExpr( std::make_unique(Const::I64(value, GetLocation()))); } Result BinaryReaderIR::OnIfExpr(Type sig_type) { auto expr = std::make_unique(); SetBlockDeclaration(&expr->true_.decl, sig_type); ExprList* expr_list = &expr->true_.exprs; CHECK_RESULT(AppendExpr(std::move(expr))); return PushLabel(LabelType::If, expr_list); } Result BinaryReaderIR::OnLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnLoopExpr(Type sig_type) { auto expr = std::make_unique(); SetBlockDeclaration(&expr->block.decl, sig_type); ExprList* expr_list = &expr->block.exprs; CHECK_RESULT(AppendExpr(std::move(expr))); return PushLabel(LabelType::Loop, expr_list); } Result BinaryReaderIR::OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) { return AppendExpr(std::make_unique( Var(srcmemidx, GetLocation()), Var(destmemidx, GetLocation()))); } Result BinaryReaderIR::OnDataDropExpr(Index segment) { return AppendExpr( std::make_unique(Var(segment, GetLocation()))); } Result BinaryReaderIR::OnMemoryFillExpr(Index memidx) { return AppendExpr( std::make_unique(Var(memidx, GetLocation()))); } Result BinaryReaderIR::OnMemoryGrowExpr(Index memidx) { return AppendExpr( std::make_unique(Var(memidx, GetLocation()))); } Result BinaryReaderIR::OnMemoryInitExpr(Index segment, Index memidx) { return AppendExpr(std::make_unique( Var(segment, GetLocation()), Var(memidx, GetLocation()))); } Result BinaryReaderIR::OnMemorySizeExpr(Index memidx) { return AppendExpr( std::make_unique(Var(memidx, GetLocation()))); } Result BinaryReaderIR::OnTableCopyExpr(Index dst_index, Index src_index) { return AppendExpr(std::make_unique( Var(dst_index, GetLocation()), Var(src_index, GetLocation()))); } Result BinaryReaderIR::OnElemDropExpr(Index segment) { return AppendExpr( std::make_unique(Var(segment, GetLocation()))); } Result BinaryReaderIR::OnTableInitExpr(Index segment, Index table_index) { return AppendExpr(std::make_unique( Var(segment, GetLocation()), Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableGetExpr(Index table_index) { return AppendExpr( std::make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableSetExpr(Index table_index) { return AppendExpr( std::make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableGrowExpr(Index table_index) { return AppendExpr( std::make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableSizeExpr(Index table_index) { return AppendExpr( std::make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableFillExpr(Index table_index) { return AppendExpr( std::make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnRefFuncExpr(Index func_index) { return AppendExpr( std::make_unique(Var(func_index, GetLocation()))); } Result BinaryReaderIR::OnRefNullExpr(Type type) { return AppendExpr(std::make_unique(type)); } Result BinaryReaderIR::OnRefIsNullExpr() { return AppendExpr(std::make_unique()); } Result BinaryReaderIR::OnNopExpr() { return AppendExpr(std::make_unique()); } Result BinaryReaderIR::OnRethrowExpr(Index depth) { return AppendExpr(std::make_unique(Var(depth, GetLocation()))); } Result BinaryReaderIR::OnReturnExpr() { return AppendExpr(std::make_unique()); } Result BinaryReaderIR::OnSelectExpr(Index result_count, Type* result_types) { TypeVector results; results.assign(result_types, result_types + result_count); return AppendExpr(std::make_unique(results)); } Result BinaryReaderIR::OnGlobalSetExpr(Index global_index) { return AppendExpr( std::make_unique(Var(global_index, GetLocation()))); } Result BinaryReaderIR::OnLocalSetExpr(Index local_index) { return AppendExpr( std::make_unique(Var(local_index, GetLocation()))); } Result BinaryReaderIR::OnStoreExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnThrowExpr(Index tag_index) { return AppendExpr(std::make_unique(Var(tag_index, GetLocation()))); } Result BinaryReaderIR::OnLocalTeeExpr(Index local_index) { return AppendExpr( std::make_unique(Var(local_index, GetLocation()))); } Result BinaryReaderIR::OnTryExpr(Type sig_type) { auto expr_ptr = std::make_unique(); // Save expr so it can be used below, after expr_ptr has been moved. TryExpr* expr = expr_ptr.get(); ExprList* expr_list = &expr->block.exprs; SetBlockDeclaration(&expr->block.decl, sig_type); CHECK_RESULT(AppendExpr(std::move(expr_ptr))); return PushLabel(LabelType::Try, expr_list, expr); } Result BinaryReaderIR::AppendCatch(Catch&& catch_) { LabelNode* label = nullptr; CHECK_RESULT(TopLabel(&label)); if (label->label_type != LabelType::Try) { PrintError("catch not inside try block"); return Result::Error; } auto* try_ = cast(label->context); if (catch_.IsCatchAll() && !try_->catches.empty() && try_->catches.back().IsCatchAll()) { PrintError("only one catch_all allowed in try block"); return Result::Error; } if (try_->kind == TryKind::Plain) { try_->kind = TryKind::Catch; } else if (try_->kind != TryKind::Catch) { PrintError("catch not allowed in try-delegate"); return Result::Error; } try_->catches.push_back(std::move(catch_)); label->exprs = &try_->catches.back().exprs; return Result::Ok; } Result BinaryReaderIR::OnCatchExpr(Index except_index) { return AppendCatch(Catch(Var(except_index, GetLocation()))); } Result BinaryReaderIR::OnCatchAllExpr() { return AppendCatch(Catch(GetLocation())); } Result BinaryReaderIR::OnDelegateExpr(Index depth) { LabelNode* label = nullptr; CHECK_RESULT(TopLabel(&label)); if (label->label_type != LabelType::Try) { PrintError("delegate not inside try block"); return Result::Error; } auto* try_ = cast(label->context); if (try_->kind == TryKind::Plain) { try_->kind = TryKind::Delegate; } else if (try_->kind != TryKind::Delegate) { PrintError("delegate not allowed in try-catch"); return Result::Error; } try_->delegate_target = Var(depth, GetLocation()); PopLabel(); return Result::Ok; } Result BinaryReaderIR::OnUnaryExpr(Opcode opcode) { return AppendExpr(std::make_unique(opcode)); } Result BinaryReaderIR::OnTernaryExpr(Opcode opcode) { return AppendExpr(std::make_unique(opcode)); } Result BinaryReaderIR::OnUnreachableExpr() { return AppendExpr(std::make_unique()); } Result BinaryReaderIR::EndFunctionBody(Index index) { current_func_ = nullptr; if (!label_stack_.empty()) { PrintError("function %" PRIindex " missing end marker", index); return Result::Error; } return Result::Ok; } Result BinaryReaderIR::OnSimdLaneOpExpr(Opcode opcode, uint64_t value) { return AppendExpr(std::make_unique(opcode, value)); } Result BinaryReaderIR::OnSimdLoadLaneExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset, uint64_t value) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset, value)); } Result BinaryReaderIR::OnSimdStoreLaneExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset, uint64_t value) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset, value)); } Result BinaryReaderIR::OnSimdShuffleOpExpr(Opcode opcode, v128 value) { return AppendExpr(std::make_unique(opcode, value)); } Result BinaryReaderIR::OnLoadSplatExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnLoadZeroExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { return AppendExpr(std::make_unique( opcode, Var(memidx, GetLocation()), 1 << alignment_log2, offset)); } Result BinaryReaderIR::OnElemSegmentCount(Index count) { WABT_TRY module_->elem_segments.reserve(count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::BeginElemSegment(Index index, Index table_index, uint8_t flags) { auto field = std::make_unique(GetLocation()); ElemSegment& elem_segment = field->elem_segment; elem_segment.table_var = Var(table_index, GetLocation()); if ((flags & SegDeclared) == SegDeclared) { elem_segment.kind = SegmentKind::Declared; } else if ((flags & SegPassive) == SegPassive) { elem_segment.kind = SegmentKind::Passive; } else { elem_segment.kind = SegmentKind::Active; } module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::BeginInitExpr(ExprList* expr) { return PushLabel(LabelType::InitExpr, expr); } Result BinaryReaderIR::BeginElemSegmentInitExpr(Index index) { assert(index == module_->elem_segments.size() - 1); ElemSegment* segment = module_->elem_segments[index]; return BeginInitExpr(&segment->offset); } Result BinaryReaderIR::EndInitExpr() { if (!label_stack_.empty()) { PrintError("init expression missing end marker"); return Result::Error; } return Result::Ok; } Result BinaryReaderIR::EndElemSegmentInitExpr(Index index) { return EndInitExpr(); } Result BinaryReaderIR::OnElemSegmentElemType(Index index, Type elem_type) { assert(index == module_->elem_segments.size() - 1); ElemSegment* segment = module_->elem_segments[index]; segment->elem_type = elem_type; return Result::Ok; } Result BinaryReaderIR::OnElemSegmentElemExprCount(Index index, Index count) { assert(index == module_->elem_segments.size() - 1); ElemSegment* segment = module_->elem_segments[index]; WABT_TRY segment->elem_exprs.reserve(count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::OnElemSegmentElemExpr_RefNull(Index segment_index, Type type) { assert(segment_index == module_->elem_segments.size() - 1); ElemSegment* segment = module_->elem_segments[segment_index]; Location loc = GetLocation(); ExprList init_expr; init_expr.push_back(std::make_unique(type, loc)); segment->elem_exprs.push_back(std::move(init_expr)); return Result::Ok; } Result BinaryReaderIR::OnElemSegmentElemExpr_RefFunc(Index segment_index, Index func_index) { assert(segment_index == module_->elem_segments.size() - 1); ElemSegment* segment = module_->elem_segments[segment_index]; Location loc = GetLocation(); ExprList init_expr; init_expr.push_back(std::make_unique(Var(func_index, loc), loc)); segment->elem_exprs.push_back(std::move(init_expr)); return Result::Ok; } Result BinaryReaderIR::OnDataSegmentCount(Index count) { WABT_TRY module_->data_segments.reserve(count); WABT_CATCH_BAD_ALLOC return Result::Ok; } Result BinaryReaderIR::BeginDataSegment(Index index, Index memory_index, uint8_t flags) { auto field = std::make_unique(GetLocation()); DataSegment& data_segment = field->data_segment; data_segment.memory_var = Var(memory_index, GetLocation()); if ((flags & SegPassive) == SegPassive) { data_segment.kind = SegmentKind::Passive; } else { data_segment.kind = SegmentKind::Active; } module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::BeginDataSegmentInitExpr(Index index) { assert(index == module_->data_segments.size() - 1); DataSegment* segment = module_->data_segments[index]; return BeginInitExpr(&segment->offset); } Result BinaryReaderIR::EndDataSegmentInitExpr(Index index) { return EndInitExpr(); } Result BinaryReaderIR::OnDataSegmentData(Index index, const void* data, Address size) { assert(index == module_->data_segments.size() - 1); DataSegment* segment = module_->data_segments[index]; segment->data.resize(size); if (size > 0) { memcpy(segment->data.data(), data, size); } return Result::Ok; } Result BinaryReaderIR::OnFunctionNamesCount(Index count) { if (count > module_->funcs.size()) { PrintError("expected function name count (%" PRIindex ") <= function count (%" PRIzd ")", count, module_->funcs.size()); return Result::Error; } return Result::Ok; } static std::string MakeDollarName(std::string_view name) { return std::string("$") + std::string(name); } Result BinaryReaderIR::OnModuleName(std::string_view name) { if (name.empty()) { return Result::Ok; } module_->name = MakeDollarName(name); return Result::Ok; } Result BinaryReaderIR::SetGlobalName(Index index, std::string_view name) { if (name.empty()) { return Result::Ok; } if (index >= module_->globals.size()) { PrintError("invalid global index: %" PRIindex, index); return Result::Error; } Global* glob = module_->globals[index]; std::string dollar_name = GetUniqueName(&module_->global_bindings, MakeDollarName(name)); glob->name = dollar_name; module_->global_bindings.emplace(dollar_name, Binding(index)); return Result::Ok; } Result BinaryReaderIR::SetFunctionName(Index index, std::string_view name) { if (name.empty()) { return Result::Ok; } if (index >= module_->funcs.size()) { PrintError("invalid function index: %" PRIindex, index); return Result::Error; } Func* func = module_->funcs[index]; std::string dollar_name = GetUniqueName(&module_->func_bindings, MakeDollarName(name)); func->name = dollar_name; module_->func_bindings.emplace(dollar_name, Binding(index)); return Result::Ok; } Result BinaryReaderIR::SetTypeName(Index index, std::string_view name) { if (name.empty()) { return Result::Ok; } if (index >= module_->types.size()) { PrintError("invalid type index: %" PRIindex, index); return Result::Error; } TypeEntry* type = module_->types[index]; std::string dollar_name = GetUniqueName(&module_->type_bindings, MakeDollarName(name)); type->name = dollar_name; module_->type_bindings.emplace(dollar_name, Binding(index)); return Result::Ok; } Result BinaryReaderIR::SetTableName(Index index, std::string_view name) { if (name.empty()) { return Result::Ok; } if (index >= module_->tables.size()) { PrintError("invalid table index: %" PRIindex, index); return Result::Error; } Table* table = module_->tables[index]; std::string dollar_name = GetUniqueName(&module_->table_bindings, MakeDollarName(name)); table->name = dollar_name; module_->table_bindings.emplace(dollar_name, Binding(index)); return Result::Ok; } Result BinaryReaderIR::SetDataSegmentName(Index index, std::string_view name) { if (name.empty()) { return Result::Ok; } if (index >= module_->data_segments.size()) { PrintError("invalid data segment index: %" PRIindex, index); return Result::Error; } DataSegment* segment = module_->data_segments[index]; std::string dollar_name = GetUniqueName(&module_->data_segment_bindings, MakeDollarName(name)); segment->name = dollar_name; module_->data_segment_bindings.emplace(dollar_name, Binding(index)); return Result::Ok; } Result BinaryReaderIR::SetElemSegmentName(Index index, std::string_view name) { if (name.empty()) { return Result::Ok; } if (index >= module_->elem_segments.size()) { PrintError("invalid elem segment index: %" PRIindex, index); return Result::Error; } ElemSegment* segment = module_->elem_segments[index]; std::string dollar_name = GetUniqueName(&module_->elem_segment_bindings, MakeDollarName(name)); segment->name = dollar_name; module_->elem_segment_bindings.emplace(dollar_name, Binding(index)); return Result::Ok; } Result BinaryReaderIR::SetMemoryName(Index index, std::string_view name) { if (name.empty()) { return Result::Ok; } if (index >= module_->memories.size()) { PrintError("invalid memory index: %" PRIindex, index); return Result::Error; } Memory* memory = module_->memories[index]; std::string dollar_name = GetUniqueName(&module_->memory_bindings, MakeDollarName(name)); memory->name = dollar_name; module_->memory_bindings.emplace(dollar_name, Binding(index)); return Result::Ok; } Result BinaryReaderIR::SetTagName(Index index, std::string_view name) { if (name.empty()) { return Result::Ok; } if (index >= module_->tags.size()) { PrintError("invalid tag index: %" PRIindex, index); return Result::Error; } Tag* tag = module_->tags[index]; std::string dollar_name = GetUniqueName(&module_->tag_bindings, MakeDollarName(name)); tag->name = dollar_name; module_->tag_bindings.emplace(dollar_name, Binding(index)); return Result::Ok; } Result BinaryReaderIR::OnFunctionName(Index index, std::string_view name) { return SetFunctionName(index, name); } Result BinaryReaderIR::OnNameEntry(NameSectionSubsection type, Index index, std::string_view name) { switch (type) { // TODO(sbc): remove OnFunctionName in favor of just using // OnNameEntry so that this works case NameSectionSubsection::Function: case NameSectionSubsection::Local: case NameSectionSubsection::Module: case NameSectionSubsection::Label: break; case NameSectionSubsection::Type: SetTypeName(index, name); break; case NameSectionSubsection::Tag: SetTagName(index, name); break; case NameSectionSubsection::Global: SetGlobalName(index, name); break; case NameSectionSubsection::Table: SetTableName(index, name); break; case NameSectionSubsection::DataSegment: SetDataSegmentName(index, name); break; case NameSectionSubsection::Memory: SetMemoryName(index, name); break; case NameSectionSubsection::ElemSegment: SetElemSegmentName(index, name); break; } return Result::Ok; } Result BinaryReaderIR::OnLocalNameLocalCount(Index index, Index count) { assert(index < module_->funcs.size()); Func* func = module_->funcs[index]; Index num_params_and_locals = func->GetNumParamsAndLocals(); if (count > num_params_and_locals) { PrintError("expected local name count (%" PRIindex ") <= local count (%" PRIindex ")", count, num_params_and_locals); return Result::Error; } return Result::Ok; } Result BinaryReaderIR::BeginCodeMetadataSection(std::string_view name, Offset size) { current_metadata_name_ = name; return Result::Ok; } Result BinaryReaderIR::OnCodeMetadataFuncCount(Index count) { return Result::Ok; } Result BinaryReaderIR::OnCodeMetadataCount(Index function_index, Index count) { code_metadata_queue_.push_func(module_->funcs[function_index]); return Result::Ok; } Result BinaryReaderIR::OnCodeMetadata(Offset offset, const void* data, Address size) { std::vector data_(static_cast(data), static_cast(data) + size); auto meta = std::make_unique(current_metadata_name_, std::move(data_)); meta->loc.offset = offset; code_metadata_queue_.push_metadata(std::move(meta)); return Result::Ok; } Result BinaryReaderIR::OnLocalName(Index func_index, Index local_index, std::string_view name) { if (name.empty()) { return Result::Ok; } Func* func = module_->funcs[func_index]; func->bindings.emplace(GetUniqueName(&func->bindings, MakeDollarName(name)), Binding(local_index)); return Result::Ok; } Result BinaryReaderIR::OnTagType(Index index, Index sig_index) { auto field = std::make_unique(GetLocation()); Tag& tag = field->tag; SetFuncDeclaration(&tag.decl, Var(sig_index, GetLocation())); module_->AppendField(std::move(field)); return Result::Ok; } Result BinaryReaderIR::OnDataSymbol(Index index, uint32_t flags, std::string_view name, Index segment, uint32_t offset, uint32_t size) { if (name.empty()) { return Result::Ok; } if (flags & WABT_SYMBOL_FLAG_UNDEFINED) { // Refers to data in another file, `segment` not valid. return Result::Ok; } if (offset) { // If it is pointing into the data segment, then it's not really naming // the whole segment. return Result::Ok; } if (segment >= module_->data_segments.size()) { PrintError("invalid data segment index: %" PRIindex, segment); return Result::Error; } DataSegment* seg = module_->data_segments[segment]; std::string dollar_name = GetUniqueName(&module_->data_segment_bindings, MakeDollarName(name)); seg->name = dollar_name; module_->data_segment_bindings.emplace(dollar_name, Binding(segment)); return Result::Ok; } Result BinaryReaderIR::OnFunctionSymbol(Index index, uint32_t flags, std::string_view name, Index func_index) { if (name.empty()) { return Result::Ok; } if (func_index >= module_->funcs.size()) { PrintError("invalid function index: %" PRIindex, func_index); return Result::Error; } Func* func = module_->funcs[func_index]; if (!func->name.empty()) { // The name section has already named this function. return Result::Ok; } std::string dollar_name = GetUniqueName(&module_->func_bindings, MakeDollarName(name)); func->name = dollar_name; module_->func_bindings.emplace(dollar_name, Binding(func_index)); return Result::Ok; } Result BinaryReaderIR::OnGlobalSymbol(Index index, uint32_t flags, std::string_view name, Index global_index) { return SetGlobalName(global_index, name); } Result BinaryReaderIR::OnSectionSymbol(Index index, uint32_t flags, Index section_index) { return Result::Ok; } Result BinaryReaderIR::OnTagSymbol(Index index, uint32_t flags, std::string_view name, Index tag_index) { if (name.empty()) { return Result::Ok; } if (tag_index >= module_->tags.size()) { PrintError("invalid tag index: %" PRIindex, tag_index); return Result::Error; } Tag* tag = module_->tags[tag_index]; std::string dollar_name = GetUniqueName(&module_->tag_bindings, MakeDollarName(name)); tag->name = dollar_name; module_->tag_bindings.emplace(dollar_name, Binding(tag_index)); return Result::Ok; } Result BinaryReaderIR::OnTableSymbol(Index index, uint32_t flags, std::string_view name, Index table_index) { return SetTableName(table_index, name); } } // end anonymous namespace Result ReadBinaryIr(const char* filename, const void* data, size_t size, const ReadBinaryOptions& options, Errors* errors, Module* out_module) { BinaryReaderIR reader(out_module, filename, errors); return ReadBinary(data, size, &reader, options); } } // namespace wabt