diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader-ir.cc | 104 | ||||
-rw-r--r-- | src/binary-reader-logging.cc | 46 | ||||
-rw-r--r-- | src/binary-reader-logging.h | 9 | ||||
-rw-r--r-- | src/binary-reader-nop.h | 27 | ||||
-rw-r--r-- | src/binary-reader-objdump.cc | 175 | ||||
-rw-r--r-- | src/binary-reader.cc | 123 | ||||
-rw-r--r-- | src/binary-reader.h | 11 | ||||
-rw-r--r-- | src/interp/binary-reader-interp.cc | 182 | ||||
-rw-r--r-- | src/interp/interp.h | 1 |
9 files changed, 298 insertions, 380 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 6d3478c6..74d047af 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -259,15 +259,6 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnTagType(Index index, Index sig_index) override; Result EndTagSection() override { return Result::Ok; } - Result OnInitExprF32ConstExpr(Index index, uint32_t value) override; - Result OnInitExprF64ConstExpr(Index index, uint64_t value) override; - Result OnInitExprV128ConstExpr(Index index, v128 value) override; - Result OnInitExprGlobalGetExpr(Index index, Index global_index) override; - Result OnInitExprI32ConstExpr(Index index, uint32_t value) override; - Result OnInitExprI64ConstExpr(Index index, uint64_t value) override; - Result OnInitExprRefNull(Index index, Type type) override; - Result OnInitExprRefFunc(Index index, Index func_index) override; - Result OnDataSymbol(Index index, uint32_t flags, string_view name, Index segment, uint32_t offset, uint32_t size) override; Result OnFunctionSymbol(Index index, uint32_t flags, string_view name, @@ -289,6 +280,7 @@ class BinaryReaderIR : public BinaryReaderNop { void PushLabel(LabelType label_type, ExprList* first, Expr* context = nullptr); + Result EndInitExpr(); Result PopLabel(); Result GetLabelAt(LabelNode** label, Index depth); Result TopLabel(LabelNode** label); @@ -313,6 +305,7 @@ class BinaryReaderIR : public BinaryReaderNop { Func* current_func_ = nullptr; std::vector<LabelNode> label_stack_; ExprList* current_init_expr_ = nullptr; + bool current_init_expr_ended_ = false; const char* filename_; }; @@ -375,9 +368,13 @@ Result BinaryReaderIR::TopLabelExpr(LabelNode** label, Expr** expr) { Result BinaryReaderIR::AppendExpr(std::unique_ptr<Expr> expr) { expr->loc = GetLocation(); - LabelNode* label; - CHECK_RESULT(TopLabel(&label)); - label->exprs->push_back(std::move(expr)); + if (current_init_expr_) { + current_init_expr_->push_back(std::move(expr)); + } else { + LabelNode* label; + CHECK_RESULT(TopLabel(&label)); + label->exprs->push_back(std::move(expr)); + } return Result::Ok; } @@ -611,12 +608,12 @@ Result BinaryReaderIR::BeginGlobalInitExpr(Index index) { assert(index == module_->globals.size() - 1); Global* global = module_->globals[index]; current_init_expr_ = &global->init_expr; + current_init_expr_ended_ = false; return Result::Ok; } Result BinaryReaderIR::EndGlobalInitExpr(Index index) { - current_init_expr_ = nullptr; - return Result::Ok; + return EndInitExpr(); } Result BinaryReaderIR::OnExportCount(Index count) { @@ -803,6 +800,11 @@ Result BinaryReaderIR::OnElseExpr() { } Result BinaryReaderIR::OnEndExpr() { + if (current_init_expr_) { + assert(!current_init_expr_ended_); + current_init_expr_ended_ = true; + return Result::Ok; + } if (label_stack_.size() > 1) { LabelNode* label; Expr* expr; @@ -1157,14 +1159,26 @@ Result BinaryReaderIR::BeginElemSegmentInitExpr(Index index) { assert(index == module_->elem_segments.size() - 1); ElemSegment* segment = module_->elem_segments[index]; current_init_expr_ = &segment->offset; + current_init_expr_ended_ = false; return Result::Ok; } -Result BinaryReaderIR::EndElemSegmentInitExpr(Index index) { +Result BinaryReaderIR::EndInitExpr() { + // This logic is currently duplicated in binary-reader-interp.cpp. + // TODO(sbc): Find a way to do this validation in SharedValidator instead. + if (!current_init_expr_ended_) { + PrintError("expected END opcode after initializer expression"); + return Result::Error; + } current_init_expr_ = nullptr; + current_init_expr_ended_ = false; 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]; @@ -1229,12 +1243,12 @@ Result BinaryReaderIR::BeginDataSegmentInitExpr(Index index) { assert(index == module_->data_segments.size() - 1); DataSegment* segment = module_->data_segments[index]; current_init_expr_ = &segment->offset; + current_init_expr_ended_ = false; return Result::Ok; } Result BinaryReaderIR::EndDataSegmentInitExpr(Index index) { - current_init_expr_ = nullptr; - return Result::Ok; + return EndInitExpr(); } Result BinaryReaderIR::OnDataSegmentData(Index index, @@ -1416,62 +1430,6 @@ Result BinaryReaderIR::OnLocalNameLocalCount(Index index, Index count) { return Result::Ok; } -Result BinaryReaderIR::OnInitExprF32ConstExpr(Index index, uint32_t value) { - Location loc = GetLocation(); - current_init_expr_->push_back( - MakeUnique<ConstExpr>(Const::F32(value, loc), loc)); - return Result::Ok; -} - -Result BinaryReaderIR::OnInitExprF64ConstExpr(Index index, uint64_t value) { - Location loc = GetLocation(); - current_init_expr_->push_back( - MakeUnique<ConstExpr>(Const::F64(value, loc), loc)); - return Result::Ok; -} - -Result BinaryReaderIR::OnInitExprV128ConstExpr(Index index, v128 value) { - Location loc = GetLocation(); - current_init_expr_->push_back( - MakeUnique<ConstExpr>(Const::V128(value, loc), loc)); - return Result::Ok; -} - -Result BinaryReaderIR::OnInitExprGlobalGetExpr(Index index, - Index global_index) { - Location loc = GetLocation(); - current_init_expr_->push_back( - MakeUnique<GlobalGetExpr>(Var(global_index, loc), loc)); - return Result::Ok; -} - -Result BinaryReaderIR::OnInitExprI32ConstExpr(Index index, uint32_t value) { - Location loc = GetLocation(); - current_init_expr_->push_back( - MakeUnique<ConstExpr>(Const::I32(value, loc), loc)); - return Result::Ok; -} - -Result BinaryReaderIR::OnInitExprI64ConstExpr(Index index, uint64_t value) { - Location loc = GetLocation(); - current_init_expr_->push_back( - MakeUnique<ConstExpr>(Const::I64(value, loc), loc)); - return Result::Ok; -} - -Result BinaryReaderIR::OnInitExprRefNull(Index index, Type type) { - Location loc = GetLocation(); - current_init_expr_->push_back(MakeUnique<RefNullExpr>(type, loc)); - return Result::Ok; -} - -Result BinaryReaderIR::OnInitExprRefFunc(Index index, Index func_index) { - Location loc = GetLocation(); - current_init_expr_->push_back( - MakeUnique<RefFuncExpr>(Var(func_index, loc), loc)); - return Result::Ok; -} - Result BinaryReaderIR::OnLocalName(Index func_index, Index local_index, string_view name) { diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index 6e0779a5..d9ae7dd7 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -491,48 +491,6 @@ Result BinaryReaderLogging::OnNameEntry(NameSectionSubsection type, return reader_->OnNameEntry(type, index, name); } -Result BinaryReaderLogging::OnInitExprF32ConstExpr(Index index, - uint32_t value_bits) { - float value; - memcpy(&value, &value_bits, sizeof(value)); - LOGF("OnInitExprF32ConstExpr(index: %" PRIindex ", value: %g (0x04%x))\n", - index, value, value_bits); - return reader_->OnInitExprF32ConstExpr(index, value_bits); -} - -Result BinaryReaderLogging::OnInitExprF64ConstExpr(Index index, - uint64_t value_bits) { - double value; - memcpy(&value, &value_bits, sizeof(value)); - LOGF("OnInitExprF64ConstExpr(index: %" PRIindex " value: %g (0x08%" PRIx64 - "))\n", - index, value, value_bits); - return reader_->OnInitExprF64ConstExpr(index, value_bits); -} - -Result BinaryReaderLogging::OnInitExprV128ConstExpr(Index index, - v128 value_bits) { - LOGF("OnInitExprV128ConstExpr(index: %" PRIindex - " value: ( 0x%08x 0x%08x 0x%08x 0x%08x))\n", - index, value_bits.u32(0), value_bits.u32(1), value_bits.u32(2), - value_bits.u32(3)); - return reader_->OnInitExprV128ConstExpr(index, value_bits); -} - -Result BinaryReaderLogging::OnInitExprI32ConstExpr(Index index, - uint32_t value) { - LOGF("OnInitExprI32ConstExpr(index: %" PRIindex ", value: %u)\n", index, - value); - return reader_->OnInitExprI32ConstExpr(index, value); -} - -Result BinaryReaderLogging::OnInitExprI64ConstExpr(Index index, - uint64_t value) { - LOGF("OnInitExprI64ConstExpr(index: %" PRIindex ", value: %" PRIu64 ")\n", - index, value); - return reader_->OnInitExprI64ConstExpr(index, value); -} - Result BinaryReaderLogging::OnDylinkInfo(uint32_t mem_size, uint32_t mem_align, uint32_t table_size, @@ -907,10 +865,6 @@ DEFINE_END(EndNamesSection) DEFINE_BEGIN(BeginRelocSection) DEFINE_END(EndRelocSection) -DEFINE_INDEX_INDEX(OnInitExprGlobalGetExpr, "index", "global_index") -DEFINE_INDEX_TYPE(OnInitExprRefNull) -DEFINE_INDEX_INDEX(OnInitExprRefFunc, "index", "func_index") - DEFINE_BEGIN(BeginDylinkSection) DEFINE_INDEX(OnDylinkNeededCount) DEFINE_INDEX(OnDylinkExportCount) diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h index d1531b35..c722181b 100644 --- a/src/binary-reader-logging.h +++ b/src/binary-reader-logging.h @@ -382,15 +382,6 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnTagType(Index index, Index sig_index) override; Result EndTagSection() override; - Result OnInitExprF32ConstExpr(Index index, uint32_t value) override; - Result OnInitExprF64ConstExpr(Index index, uint64_t value) override; - Result OnInitExprV128ConstExpr(Index index, v128 value) override; - Result OnInitExprGlobalGetExpr(Index index, Index global_index) override; - Result OnInitExprI32ConstExpr(Index index, uint32_t value) override; - Result OnInitExprI64ConstExpr(Index index, uint64_t value) override; - Result OnInitExprRefNull(Index index, Type type) override; - Result OnInitExprRefFunc(Index index, Index func_index) override; - private: void Indent(); void Dedent(); diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h index 6bad926b..f3aae0e2 100644 --- a/src/binary-reader-nop.h +++ b/src/binary-reader-nop.h @@ -549,33 +549,6 @@ class BinaryReaderNop : public BinaryReaderDelegate { return Result::Ok; } Result EndLinkingSection() override { return Result::Ok; } - - /* InitExpr - used by elem, data and global sections; these functions are - * only called between calls to Begin*InitExpr and End*InitExpr */ - Result OnInitExprF32ConstExpr(Index index, uint32_t value) override { - return Result::Ok; - } - Result OnInitExprF64ConstExpr(Index index, uint64_t value) override { - return Result::Ok; - } - Result OnInitExprV128ConstExpr(Index index, v128 value) override { - return Result::Ok; - } - Result OnInitExprGlobalGetExpr(Index index, Index global_index) override { - return Result::Ok; - } - Result OnInitExprI32ConstExpr(Index index, uint32_t value) override { - return Result::Ok; - } - Result OnInitExprI64ConstExpr(Index index, uint64_t value) override { - return Result::Ok; - } - Result OnInitExprRefNull(Index index, Type type) override { - return Result::Ok; - } - Result OnInitExprRefFunc(Index index, Index func_index) override { - return Result::Ok; - } }; } // namespace wabt diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index 4689b1e5..51ad0694 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -462,6 +462,7 @@ class BinaryReaderObjdumpDisassemble : public BinaryReaderObjdumpBase { std::string BlockSigToString(Type type) const; Result BeginFunctionBody(Index index, Offset size) override; + Result EndFunctionBody(Index index) override; Result OnLocalDeclCount(Index count) override; Result OnLocalDecl(Index decl_index, Index count, Type type) override; @@ -495,6 +496,7 @@ class BinaryReaderObjdumpDisassemble : public BinaryReaderObjdumpBase { int indent_level = 0; Index next_reloc = 0; Index local_index_ = 0; + bool in_function_body = false; }; std::string BinaryReaderObjdumpDisassemble::BlockSigToString(Type type) const { @@ -508,6 +510,9 @@ std::string BinaryReaderObjdumpDisassemble::BlockSigToString(Type type) const { } Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) { + if (!in_function_body) { + return Result::Ok; + } if (options_->debug) { const char* opcode_name = opcode.GetName(); err_stream_->Writef("on_opcode: %#" PRIzx ": %s\n", state->offset, @@ -535,6 +540,9 @@ Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) { #define IMMEDIATE_OCTET_COUNT 9 Result BinaryReaderObjdumpDisassemble::OnLocalDeclCount(Index count) { + if (!in_function_body) { + return Result::Ok; + } local_index_ = 0; current_opcode_offset = state->offset; return Result::Ok; @@ -543,6 +551,9 @@ Result BinaryReaderObjdumpDisassemble::OnLocalDeclCount(Index count) { Result BinaryReaderObjdumpDisassemble::OnLocalDecl(Index decl_index, Index count, Type type) { + if (!in_function_body) { + return Result::Ok; + } Offset offset = current_opcode_offset; size_t data_size = state->offset - offset; @@ -572,6 +583,10 @@ Result BinaryReaderObjdumpDisassemble::OnLocalDecl(Index decl_index, void BinaryReaderObjdumpDisassemble::LogOpcode(size_t data_size, const char* fmt, ...) { + // BinaryReaderObjdumpDisassemble is only used to disassembly function bodies + // so this should never be called for instructions outside of function bodies + // (i.e. init expresions). + assert(in_function_body); const Offset opcode_size = current_opcode.GetLength(); const Offset total_size = opcode_size + data_size; // current_opcode_offset has already read past this opcode; rewind it by the @@ -642,11 +657,17 @@ void BinaryReaderObjdumpDisassemble::LogOpcode(size_t data_size, } Result BinaryReaderObjdumpDisassemble::OnOpcodeBare() { + if (!in_function_body) { + return Result::Ok; + } LogOpcode(0, nullptr); return Result::Ok; } Result BinaryReaderObjdumpDisassemble::OnOpcodeIndex(Index value) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; string_view name; if (current_opcode == Opcode::Call && @@ -666,12 +687,18 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeIndex(Index value) { Result BinaryReaderObjdumpDisassemble::OnOpcodeIndexIndex(Index value, Index value2) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; LogOpcode(immediate_len, "%" PRIindex " %" PRIindex, value, value2); return Result::Ok; } Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32(uint32_t value) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; string_view name; if (current_opcode == Opcode::DataDrop && @@ -686,6 +713,8 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32(uint32_t value) { Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) { + if (!in_function_body) + return Result::Ok; Offset immediate_len = state->offset - current_opcode_offset; string_view name; if (current_opcode == Opcode::MemoryInit && @@ -702,18 +731,27 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeUint32Uint32Uint32( uint32_t value, uint32_t value2, uint32_t value3) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; LogOpcode(immediate_len, "%u %u %u", value, value2, value3); return Result::Ok; } Result BinaryReaderObjdumpDisassemble::OnOpcodeUint64(uint64_t value) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; LogOpcode(immediate_len, "%" PRId64, value); return Result::Ok; } Result BinaryReaderObjdumpDisassemble::OnOpcodeF32(uint32_t value) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; char buffer[WABT_MAX_FLOAT_HEX]; WriteFloatHex(buffer, sizeof(buffer), value); @@ -722,6 +760,9 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeF32(uint32_t value) { } Result BinaryReaderObjdumpDisassemble::OnOpcodeF64(uint64_t value) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; char buffer[WABT_MAX_DOUBLE_HEX]; WriteDoubleHex(buffer, sizeof(buffer), value); @@ -730,6 +771,9 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeF64(uint64_t value) { } Result BinaryReaderObjdumpDisassemble::OnOpcodeV128(v128 value) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; // v128 is always dumped as i32x4: LogOpcode(immediate_len, "0x%08x 0x%08x 0x%08x 0x%08x", value.u32(0), @@ -738,6 +782,9 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeV128(v128 value) { } Result BinaryReaderObjdumpDisassemble::OnOpcodeType(Type type) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; LogOpcode(immediate_len, type.GetRefKindName()); return Result::Ok; @@ -747,6 +794,9 @@ Result BinaryReaderObjdumpDisassemble::OnBrTableExpr( Index num_targets, Index* target_depths, Index default_target_depth) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; std::string buffer = std::string(); @@ -760,6 +810,9 @@ Result BinaryReaderObjdumpDisassemble::OnBrTableExpr( } Result BinaryReaderObjdumpDisassemble::OnDelegateExpr(Index depth) { + if (!in_function_body) { + return Result::Ok; + } // Because `delegate` ends the block we need to dedent here, and // we don't need to dedent it in LogOpcode. if (indent_level > 0) { @@ -769,6 +822,9 @@ Result BinaryReaderObjdumpDisassemble::OnDelegateExpr(Index depth) { } Result BinaryReaderObjdumpDisassemble::OnEndExpr() { + if (!in_function_body) { + return Result::Ok; + } if (indent_level > 0) { indent_level--; } @@ -787,10 +843,20 @@ Result BinaryReaderObjdumpDisassemble::BeginFunctionBody(Index index, printf(":\n"); last_opcode_end = 0; + in_function_body = true; + return Result::Ok; +} + +Result BinaryReaderObjdumpDisassemble::EndFunctionBody(Index index) { + assert(in_function_body); + in_function_body = false; return Result::Ok; } Result BinaryReaderObjdumpDisassemble::OnOpcodeBlockSig(Type sig_type) { + if (!in_function_body) { + return Result::Ok; + } Offset immediate_len = state->offset - current_opcode_offset; if (sig_type != Type::Void) { LogOpcode(immediate_len, "%s", BlockSigToString(sig_type).c_str()); @@ -964,15 +1030,6 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Index index, string_view name) override; - Result OnInitExprF32ConstExpr(Index index, uint32_t value) override; - Result OnInitExprF64ConstExpr(Index index, uint64_t value) override; - Result OnInitExprV128ConstExpr(Index index, v128 value) override; - Result OnInitExprGlobalGetExpr(Index index, Index global_index) override; - Result OnInitExprI32ConstExpr(Index index, uint32_t value) override; - Result OnInitExprI64ConstExpr(Index index, uint64_t value) override; - Result OnInitExprRefNull(Index index, Type type) override; - Result OnInitExprRefFunc(Index index, Index func_index) override; - Result OnDylinkInfo(uint32_t mem_size, uint32_t mem_align_log2, uint32_t table_size, @@ -1034,6 +1091,12 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result OnTagCount(Index count) override; Result OnTagType(Index index, Index sig_index) override; + Result OnI32ConstExpr(uint32_t value) override; + Result OnI64ConstExpr(uint64_t value) override; + Result OnF32ConstExpr(uint32_t value) override; + Result OnF64ConstExpr(uint64_t value) override; + Result OnGlobalGetExpr(Index global_index) override; + private: Result InitExprToConstOffset(const InitExpr& expr, uint64_t* out_offset); Result HandleInitExpr(const InitExpr& expr); @@ -1058,6 +1121,11 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Index data_mem_index_ = 0; uint64_t data_offset_ = 0; uint64_t elem_offset_ = 0; + + bool ReadingInitExpr() { + return reading_elem_init_expr_ || reading_data_init_expr_ || + reading_global_init_expr_; + } }; BinaryReaderObjdump::BinaryReaderObjdump(const uint8_t* data, @@ -1609,63 +1677,54 @@ Result BinaryReaderObjdump::HandleInitExpr(const InitExpr& expr) { } } -Result BinaryReaderObjdump::OnInitExprF32ConstExpr(Index index, - uint32_t value) { - InitExpr expr; - expr.type = InitExprType::F32; - expr.value.f32 = value; - return HandleInitExpr(expr); -} - -Result BinaryReaderObjdump::OnInitExprF64ConstExpr(Index index, - uint64_t value) { - InitExpr expr; - expr.type = InitExprType::F64; - expr.value.f64 = value; - return HandleInitExpr(expr); -} - -Result BinaryReaderObjdump::OnInitExprV128ConstExpr(Index index, v128 value) { - InitExpr expr; - expr.type = InitExprType::V128; - expr.value.v128_v = value; - return HandleInitExpr(expr); -} - -Result BinaryReaderObjdump::OnInitExprGlobalGetExpr(Index index, - Index global_index) { - InitExpr expr; - expr.type = InitExprType::Global; - expr.value.index = global_index; - return HandleInitExpr(expr); +Result BinaryReaderObjdump::OnI32ConstExpr(uint32_t value) { + if (ReadingInitExpr()) { + InitExpr expr; + expr.type = InitExprType::I32; + expr.value.i32 = value; + return HandleInitExpr(expr); + } + return Result::Ok; } -Result BinaryReaderObjdump::OnInitExprI32ConstExpr(Index index, - uint32_t value) { - InitExpr expr; - expr.type = InitExprType::I32; - expr.value.i32 = value; - return HandleInitExpr(expr); +Result BinaryReaderObjdump::OnI64ConstExpr(uint64_t value) { + if (ReadingInitExpr()) { + InitExpr expr; + expr.type = InitExprType::I64; + expr.value.i64 = value; + return HandleInitExpr(expr); + } + return Result::Ok; } -Result BinaryReaderObjdump::OnInitExprI64ConstExpr(Index index, - uint64_t value) { - InitExpr expr; - expr.type = InitExprType::I64; - expr.value.i64 = value; - return HandleInitExpr(expr); +Result BinaryReaderObjdump::OnF32ConstExpr(uint32_t value) { + if (ReadingInitExpr()) { + InitExpr expr; + expr.type = InitExprType::F32; + expr.value.f32 = value; + return HandleInitExpr(expr); + } + return Result::Ok; } -Result BinaryReaderObjdump::OnInitExprRefNull(Index index, Type type) { - InitExpr expr; - expr.type = InitExprType::NullRef; - expr.value.type = type; - return HandleInitExpr(expr); +Result BinaryReaderObjdump::OnF64ConstExpr(uint64_t value) { + if (ReadingInitExpr()) { + InitExpr expr; + expr.type = InitExprType::F64; + expr.value.f64 = value; + return HandleInitExpr(expr); + } + return Result::Ok; } -Result BinaryReaderObjdump::OnInitExprRefFunc(Index index, Index func_index) { - InitExpr expr{InitExprType::FuncRef, {func_index}}; - return HandleInitExpr(expr); +Result BinaryReaderObjdump::OnGlobalGetExpr(Index global_index) { + if (ReadingInitExpr()) { + InitExpr expr; + expr.type = InitExprType::Global; + expr.value.index = global_index; + return HandleInitExpr(expr); + } + return Result::Ok; } Result BinaryReaderObjdump::OnModuleName(string_view name) { diff --git a/src/binary-reader.cc b/src/binary-reader.cc index c146c7ec..e0775430 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -119,7 +119,7 @@ class BinaryReader { Index NumTotalFuncs(); - Result ReadInitExpr(Index index, Type required = Type::Any) WABT_WARN_UNUSED; + Result ReadInitExpr(Index index) WABT_WARN_UNUSED; Result ReadTable(Type* out_elem_type, Limits* out_elem_limits) WABT_WARN_UNUSED; Result ReadMemory(Limits* out_page_limits) WABT_WARN_UNUSED; @@ -129,6 +129,11 @@ class BinaryReader { Index memory, const char* desc) WABT_WARN_UNUSED; Result ReadFunctionBody(Offset end_offset) WABT_WARN_UNUSED; + // ReadInstructions either until and END instruction, or until + // the given end_offset. + Result ReadInstructions(bool stop_on_end, + Offset end_offset, + Opcode* final_opcode) WABT_WARN_UNUSED; Result ReadNameSection(Offset section_size) WABT_WARN_UNUSED; Result ReadRelocSection(Offset section_size) WABT_WARN_UNUSED; Result ReadDylinkSection(Offset section_size) WABT_WARN_UNUSED; @@ -487,91 +492,9 @@ Index BinaryReader::NumTotalFuncs() { return num_func_imports_ + num_function_signatures_; } -Result BinaryReader::ReadInitExpr(Index index, Type required) { - Opcode opcode; - CHECK_RESULT(ReadOpcode(&opcode, "opcode")); - ERROR_UNLESS_OPCODE_ENABLED(opcode); - - switch (opcode) { - case Opcode::I32Const: { - uint32_t value = 0; - CHECK_RESULT(ReadS32Leb128(&value, "init_expr i32.const value")); - CALLBACK(OnInitExprI32ConstExpr, index, value); - break; - } - - case Opcode::I64Const: { - uint64_t value = 0; - CHECK_RESULT(ReadS64Leb128(&value, "init_expr i64.const value")); - CALLBACK(OnInitExprI64ConstExpr, index, value); - break; - } - - case Opcode::F32Const: { - uint32_t value_bits = 0; - CHECK_RESULT(ReadF32(&value_bits, "init_expr f32.const value")); - CALLBACK(OnInitExprF32ConstExpr, index, value_bits); - break; - } - - case Opcode::F64Const: { - uint64_t value_bits = 0; - CHECK_RESULT(ReadF64(&value_bits, "init_expr f64.const value")); - CALLBACK(OnInitExprF64ConstExpr, index, value_bits); - break; - } - - case Opcode::V128Const: { - v128 value_bits; - ZeroMemory(value_bits); - CHECK_RESULT(ReadV128(&value_bits, "init_expr v128.const value")); - CALLBACK(OnInitExprV128ConstExpr, index, value_bits); - break; - } - - case Opcode::GlobalGet: { - Index global_index; - CHECK_RESULT(ReadIndex(&global_index, "init_expr global.get index")); - CALLBACK(OnInitExprGlobalGetExpr, index, global_index); - break; - } - - case Opcode::RefNull: { - Type type; - CHECK_RESULT(ReadRefType(&type, "ref.null type")); - CALLBACK(OnInitExprRefNull, index, type); - break; - } - - case Opcode::RefFunc: { - Index func_index; - CHECK_RESULT(ReadIndex(&func_index, "init_expr ref.func index")); - CALLBACK(OnInitExprRefFunc, index, func_index); - break; - } - - case Opcode::End: - return Result::Ok; - - default: - return ReportUnexpectedOpcode(opcode, "in initializer expression"); - } - - if (required == Type::I32 && opcode != Opcode::I32Const && - opcode != Opcode::GlobalGet) { - PrintError("expected i32 init_expr"); - return Result::Error; - } - if (required == Type::I64 && opcode != Opcode::I64Const && - opcode != Opcode::GlobalGet) { - PrintError("expected i64 init_expr"); - return Result::Error; - } - - CHECK_RESULT(ReadOpcode(&opcode, "opcode")); - ERROR_UNLESS(opcode == Opcode::End, - "expected END opcode after initializer expression"); - return Result::Ok; +Result BinaryReader::ReadInitExpr(Index index) { + // Read instructions until END opcode is reached. + return ReadInstructions(/*stop_on_end=*/true, read_end_, NULL); } Result BinaryReader::ReadTable(Type* out_elem_type, Limits* out_elem_limits) { @@ -672,12 +595,27 @@ Result BinaryReader::ReadAddress(Address* out_value, } Result BinaryReader::ReadFunctionBody(Offset end_offset) { - bool seen_end_opcode = false; + Opcode final_opcode(Opcode::Invalid); + CHECK_RESULT( + ReadInstructions(/*stop_on_end=*/false, end_offset, &final_opcode)); + ERROR_UNLESS(state_.offset == end_offset, + "function body longer than given size"); + ERROR_UNLESS(final_opcode == Opcode::End, + "function body must end with END opcode"); + return Result::Ok; +} + +Result BinaryReader::ReadInstructions(bool stop_on_end, + Offset end_offset, + Opcode* final_opcode) { while (state_.offset < end_offset) { Opcode opcode; CHECK_RESULT(ReadOpcode(&opcode, "opcode")); CALLBACK(OnOpcode, opcode); ERROR_UNLESS_OPCODE_ENABLED(opcode); + if (final_opcode) { + *final_opcode = opcode; + } switch (opcode) { case Opcode::Unreachable: @@ -801,8 +739,8 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) { case Opcode::End: CALLBACK0(OnEndExpr); - if (state_.offset == end_offset) { - seen_end_opcode = true; + if (stop_on_end) { + return Result::Ok; } break; @@ -1823,9 +1761,6 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) { return ReportUnexpectedOpcode(opcode); } } - ERROR_UNLESS(state_.offset == end_offset, - "function body longer than given size"); - ERROR_UNLESS(seen_end_opcode, "function body must end with END opcode"); return Result::Ok; } @@ -2616,7 +2551,7 @@ Result BinaryReader::ReadElemSection(Offset section_size) { if (!(flags & SegPassive)) { CALLBACK(BeginElemSegmentInitExpr, i); - CHECK_RESULT(ReadInitExpr(i, Type::I32)); + CHECK_RESULT(ReadInitExpr(i)); CALLBACK(EndElemSegmentInitExpr, i); } @@ -2733,7 +2668,7 @@ Result BinaryReader::ReadDataSection(Offset section_size) { if (!(flags & SegPassive)) { ERROR_UNLESS(memories.size() > 0, "no memory to copy data to"); CALLBACK(BeginDataSegmentInitExpr, i); - CHECK_RESULT(ReadInitExpr(i, memories[0].IndexType())); + CHECK_RESULT(ReadInitExpr(i)); CALLBACK(EndDataSegmentInitExpr, i); } diff --git a/src/binary-reader.h b/src/binary-reader.h index 65095791..d000dd9b 100644 --- a/src/binary-reader.h +++ b/src/binary-reader.h @@ -460,17 +460,6 @@ class BinaryReaderDelegate { virtual Result OnTagType(Index index, Index sig_index) = 0; virtual Result EndTagSection() = 0; - /* InitExpr - used by elem, data and global sections; these functions are - * only called between calls to Begin*InitExpr and End*InitExpr */ - virtual Result OnInitExprF32ConstExpr(Index index, uint32_t value) = 0; - virtual Result OnInitExprF64ConstExpr(Index index, uint64_t value) = 0; - virtual Result OnInitExprV128ConstExpr(Index index, v128 value) = 0; - virtual Result OnInitExprGlobalGetExpr(Index index, Index global_index) = 0; - virtual Result OnInitExprI32ConstExpr(Index index, uint32_t value) = 0; - virtual Result OnInitExprI64ConstExpr(Index index, uint64_t value) = 0; - virtual Result OnInitExprRefNull(Index index, Type type) = 0; - virtual Result OnInitExprRefFunc(Index index, Index func_index) = 0; - const State* state = nullptr; }; diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index 659e14e3..40e85fd5 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -132,6 +132,7 @@ class BinaryReaderInterp : public BinaryReaderNop { 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 OnTagCount(Index count) override; @@ -255,6 +256,7 @@ class BinaryReaderInterp : public BinaryReaderNop { 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; @@ -263,6 +265,7 @@ class BinaryReaderInterp : public BinaryReaderNop { Index func_index) override; Result OnDataCount(Index count) override; + Result BeginDataSegmentInitExpr(Index index) override; Result EndDataSegmentInitExpr(Index index) override; Result BeginDataSegment(Index index, Index memory_index, @@ -271,15 +274,6 @@ class BinaryReaderInterp : public BinaryReaderNop { const void* data, Address size) override; - Result OnInitExprF32ConstExpr(Index index, uint32_t value) override; - Result OnInitExprF64ConstExpr(Index index, uint64_t value) override; - Result OnInitExprV128ConstExpr(Index index, v128 value) override; - Result OnInitExprGlobalGetExpr(Index index, Index global_index) override; - Result OnInitExprI32ConstExpr(Index index, uint32_t value) override; - Result OnInitExprI64ConstExpr(Index index, uint64_t value) override; - Result OnInitExprRefNull(Index index, Type type) override; - Result OnInitExprRefFunc(Index index, Index func_index) override; - private: Label* GetLabel(Index depth); Label* GetNearestTryLabel(Index depth); @@ -303,6 +297,11 @@ class BinaryReaderInterp : public BinaryReaderNop { Index keep_extra, Index* out_drop_count, Index* out_keep_count); + Result BeginInitExpr(); + Result EndInitExpr(); + Result CheckEmptyInitExpr(); + Result CheckNotInitExpr(); + void EmitBr(Index depth, Index drop_count, Index keep_count, @@ -325,6 +324,7 @@ class BinaryReaderInterp : public BinaryReaderNop { FixupMap depth_fixups_; FixupMap func_fixups_; + bool reading_init_expr_ = false; InitExpr init_expr_; u32 local_decl_count_; u32 local_count_; @@ -620,7 +620,47 @@ Result BinaryReaderInterp::BeginGlobal(Index index, Type type, bool mutable_) { return Result::Ok; } +Result BinaryReaderInterp::BeginGlobalInitExpr(Index index) { + return BeginInitExpr(); +} + +Result BinaryReaderInterp::EndInitExpr() { + assert(reading_init_expr_); + reading_init_expr_ = false; + if (!init_expr_.ended) { + PrintError("expected END opcode after initializer expression"); + return Result::Error; + } + return Result::Ok; +} + +Result BinaryReaderInterp::BeginInitExpr() { + assert(!reading_init_expr_); + reading_init_expr_ = true; + init_expr_.kind = InitExprKind::None; + init_expr_.ended = false; + return Result::Ok; +} + +Result BinaryReaderInterp::CheckEmptyInitExpr() { + assert(reading_init_expr_); + if (init_expr_.kind != InitExprKind::None) { + PrintError("expected END opcode after initializer expression"); + return Result::Error; + } + return Result::Ok; +} + +Result BinaryReaderInterp::CheckNotInitExpr() { + if (reading_init_expr_) { + PrintError("Unepxected opcode in init expr"); + return Result::Error; + } + return Result::Ok; +} + Result BinaryReaderInterp::EndGlobalInitExpr(Index index) { + CHECK_RESULT(EndInitExpr()); switch (init_expr_.kind) { case InitExprKind::I32: CHECK_RESULT(validator_.OnGlobalInitExpr_Const(loc, ValueType::I32)); @@ -666,58 +706,6 @@ Result BinaryReaderInterp::EndGlobalInitExpr(Index index) { return Result::Ok; } -Result BinaryReaderInterp::OnInitExprF32ConstExpr(Index index, - uint32_t value_bits) { - init_expr_.kind = InitExprKind::F32; - init_expr_.f32_ = Bitcast<f32>(value_bits); - return Result::Ok; -} - -Result BinaryReaderInterp::OnInitExprF64ConstExpr(Index index, - uint64_t value_bits) { - init_expr_.kind = InitExprKind::F64; - init_expr_.f64_ = Bitcast<f64>(value_bits); - return Result::Ok; -} - -Result BinaryReaderInterp::OnInitExprV128ConstExpr(Index index, - v128 value_bits) { - init_expr_.kind = InitExprKind::V128; - init_expr_.v128_ = Bitcast<v128>(value_bits); - return Result::Ok; -} - -Result BinaryReaderInterp::OnInitExprGlobalGetExpr(Index index, - Index global_index) { - init_expr_.kind = InitExprKind::GlobalGet; - init_expr_.index_ = global_index; - return Result::Ok; -} - -Result BinaryReaderInterp::OnInitExprI32ConstExpr(Index index, uint32_t value) { - init_expr_.kind = InitExprKind::I32; - init_expr_.i32_ = value; - return Result::Ok; -} - -Result BinaryReaderInterp::OnInitExprI64ConstExpr(Index index, uint64_t value) { - init_expr_.kind = InitExprKind::I64; - init_expr_.i64_ = value; - return Result::Ok; -} - -Result BinaryReaderInterp::OnInitExprRefNull(Index index, Type type) { - init_expr_.kind = InitExprKind::RefNull; - init_expr_.type_ = type; - return Result::Ok; -} - -Result BinaryReaderInterp::OnInitExprRefFunc(Index index, Index func_index) { - init_expr_.kind = InitExprKind::RefFunc; - init_expr_.index_ = func_index; - return Result::Ok; -} - Result BinaryReaderInterp::OnTagCount(Index count) { module_.tags.reserve(count); return Result::Ok; @@ -777,7 +765,12 @@ Result BinaryReaderInterp::BeginElemSegment(Index index, return Result::Ok; } +Result BinaryReaderInterp::BeginElemSegmentInitExpr(Index index) { + return BeginInitExpr(); +} + Result BinaryReaderInterp::EndElemSegmentInitExpr(Index index) { + CHECK_RESULT(EndInitExpr()); switch (init_expr_.kind) { case InitExprKind::I32: CHECK_RESULT(validator_.OnElemSegmentInitExpr_Const(loc, ValueType::I32)); @@ -834,7 +827,12 @@ Result BinaryReaderInterp::OnDataCount(Index count) { return Result::Ok; } +Result BinaryReaderInterp::BeginDataSegmentInitExpr(Index index) { + return BeginInitExpr(); +} + Result BinaryReaderInterp::EndDataSegmentInitExpr(Index index) { + CHECK_RESULT(EndInitExpr()); switch (init_expr_.kind) { case InitExprKind::I32: CHECK_RESULT(validator_.OnDataSegmentInitExpr_Const(loc, ValueType::I32)); @@ -960,7 +958,7 @@ Index BinaryReaderInterp::num_func_imports() const { } Result BinaryReaderInterp::OnOpcode(Opcode opcode) { - if (func_ == nullptr || label_stack_.empty()) { + if ((func_ == nullptr || label_stack_.empty()) && !reading_init_expr_) { PrintError("Unexpected instruction after end of function"); return Result::Error; } @@ -968,12 +966,14 @@ Result BinaryReaderInterp::OnOpcode(Opcode opcode) { } Result BinaryReaderInterp::OnUnaryExpr(Opcode opcode) { + CHECK_RESULT(CheckNotInitExpr()); CHECK_RESULT(validator_.OnUnary(loc, opcode)); istream_.Emit(opcode); return Result::Ok; } Result BinaryReaderInterp::OnTernaryExpr(Opcode opcode) { + CHECK_RESULT(CheckNotInitExpr()); CHECK_RESULT(validator_.OnTernary(loc, opcode)); istream_.Emit(opcode); return Result::Ok; @@ -1100,6 +1100,14 @@ Result BinaryReaderInterp::OnElseExpr() { } Result BinaryReaderInterp::OnEndExpr() { + if (reading_init_expr_) { + if (init_expr_.ended) { + PrintError("duplicate END opcode init initializer expression"); + return Result::Error; + } + init_expr_.ended = true; + return Result::Ok; + } if (label_stack_.size() == 1) { return Result::Ok; } @@ -1263,41 +1271,78 @@ Result BinaryReaderInterp::OnDropExpr() { Result BinaryReaderInterp::OnI32ConstExpr(uint32_t value) { CHECK_RESULT(validator_.OnConst(loc, Type::I32)); + if (reading_init_expr_) { + CHECK_RESULT(CheckEmptyInitExpr()); + init_expr_.kind = InitExprKind::I32; + init_expr_.i32_ = value; + return Result::Ok; + } istream_.Emit(Opcode::I32Const, value); return Result::Ok; } Result BinaryReaderInterp::OnI64ConstExpr(uint64_t value) { CHECK_RESULT(validator_.OnConst(loc, Type::I64)); + if (reading_init_expr_) { + CHECK_RESULT(CheckEmptyInitExpr()); + init_expr_.kind = InitExprKind::I64; + init_expr_.i64_ = value; + return Result::Ok; + } istream_.Emit(Opcode::I64Const, value); return Result::Ok; } Result BinaryReaderInterp::OnF32ConstExpr(uint32_t value_bits) { CHECK_RESULT(validator_.OnConst(loc, Type::F32)); + if (reading_init_expr_) { + CHECK_RESULT(CheckEmptyInitExpr()); + init_expr_.kind = InitExprKind::F32; + init_expr_.f32_ = Bitcast<f32>(value_bits); + return Result::Ok; + } istream_.Emit(Opcode::F32Const, value_bits); return Result::Ok; } Result BinaryReaderInterp::OnF64ConstExpr(uint64_t value_bits) { CHECK_RESULT(validator_.OnConst(loc, Type::F64)); + if (reading_init_expr_) { + CHECK_RESULT(CheckEmptyInitExpr()); + init_expr_.kind = InitExprKind::F64; + init_expr_.f64_ = Bitcast<f64>(value_bits); + return Result::Ok; + } istream_.Emit(Opcode::F64Const, value_bits); return Result::Ok; } Result BinaryReaderInterp::OnV128ConstExpr(v128 value_bits) { CHECK_RESULT(validator_.OnConst(loc, Type::V128)); + if (reading_init_expr_) { + CHECK_RESULT(CheckEmptyInitExpr()); + init_expr_.kind = InitExprKind::V128; + init_expr_.v128_ = Bitcast<v128>(value_bits); + return Result::Ok; + } istream_.Emit(Opcode::V128Const, value_bits); return Result::Ok; } Result BinaryReaderInterp::OnGlobalGetExpr(Index global_index) { + if (reading_init_expr_) { + CHECK_RESULT(CheckEmptyInitExpr()); + init_expr_.kind = InitExprKind::GlobalGet; + init_expr_.index_ = global_index; + return Result::Ok; + } CHECK_RESULT(validator_.OnGlobalGet(loc, Var(global_index))); istream_.Emit(Opcode::GlobalGet, global_index); return Result::Ok; } Result BinaryReaderInterp::OnGlobalSetExpr(Index global_index) { + CHECK_RESULT(CheckNotInitExpr()); CHECK_RESULT(validator_.OnGlobalSet(loc, Var(global_index))); istream_.Emit(Opcode::GlobalSet, global_index); return Result::Ok; @@ -1383,6 +1428,12 @@ Result BinaryReaderInterp::OnTableFillExpr(Index table_index) { } Result BinaryReaderInterp::OnRefFuncExpr(Index func_index) { + if (reading_init_expr_) { + CHECK_RESULT(CheckEmptyInitExpr()); + init_expr_.kind = InitExprKind::RefFunc; + init_expr_.index_ = func_index; + return Result::Ok; + } CHECK_RESULT(validator_.OnRefFunc(loc, Var(func_index))); istream_.Emit(Opcode::RefFunc, func_index); return Result::Ok; @@ -1390,6 +1441,12 @@ Result BinaryReaderInterp::OnRefFuncExpr(Index func_index) { Result BinaryReaderInterp::OnRefNullExpr(Type type) { CHECK_RESULT(validator_.OnRefNull(loc, type)); + if (reading_init_expr_) { + CHECK_RESULT(CheckEmptyInitExpr()); + init_expr_.kind = InitExprKind::RefNull; + init_expr_.type_ = type; + return Result::Ok; + } istream_.Emit(Opcode::RefNull); return Result::Ok; } @@ -1401,6 +1458,7 @@ Result BinaryReaderInterp::OnRefIsNullExpr() { } Result BinaryReaderInterp::OnNopExpr() { + CHECK_RESULT(CheckNotInitExpr()); CHECK_RESULT(validator_.OnNop(loc)); return Result::Ok; } diff --git a/src/interp/interp.h b/src/interp/interp.h index 34a220c7..0247d48a 100644 --- a/src/interp/interp.h +++ b/src/interp/interp.h @@ -109,6 +109,7 @@ enum class InitExprKind { struct InitExpr { InitExprKind kind; + bool ended = false; union { u32 i32_; u64 i64_; |