diff --git a/include/wabt/binary-reader-ir.h b/include/wabt/binary-reader-ir.h index 4de0ee7099..da4da30c3a 100644 --- a/include/wabt/binary-reader-ir.h +++ b/include/wabt/binary-reader-ir.h @@ -32,6 +32,11 @@ Result ReadBinaryIr(const char* filename, Errors*, Module* out_module); -} // namespace wabt +class OpcodeRawExpr; +Result ExtractOpcodeRawExpr(OpcodeRawExpr& expr, + Module& module, + const ReadBinaryOptions& options); + +} // namespace wabt #endif /* WABT_BINARY_READER_IR_H_ */ diff --git a/include/wabt/binary-reader-logging.h b/include/wabt/binary-reader-logging.h index 4a031f74bb..a9f6828ac4 100644 --- a/include/wabt/binary-reader-logging.h +++ b/include/wabt/binary-reader-logging.h @@ -188,6 +188,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnDropExpr() override; Result OnElseExpr() override; Result OnEndExpr() override; + Result OnSkipFunctionBodyExpr(std::vector& opcode_buffer) override; Result OnF32ConstExpr(uint32_t value_bits) override; Result OnF64ConstExpr(uint64_t value_bits) override; Result OnV128ConstExpr(v128 value_bits) override; diff --git a/include/wabt/binary-reader-nop.h b/include/wabt/binary-reader-nop.h index fdb7d14a41..6b314ee362 100644 --- a/include/wabt/binary-reader-nop.h +++ b/include/wabt/binary-reader-nop.h @@ -259,6 +259,9 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnDropExpr() override { return Result::Ok; } Result OnElseExpr() override { return Result::Ok; } Result OnEndExpr() override { return Result::Ok; } + Result OnSkipFunctionBodyExpr(std::vector& opcode_buffer) override { + return Result::Ok; + } Result OnF32ConstExpr(uint32_t value_bits) override { return Result::Ok; } Result OnF64ConstExpr(uint64_t value_bits) override { return Result::Ok; } Result OnV128ConstExpr(v128 value_bits) override { return Result::Ok; } diff --git a/include/wabt/binary-reader.h b/include/wabt/binary-reader.h index 94b19c1100..fc96059cd0 100644 --- a/include/wabt/binary-reader.h +++ b/include/wabt/binary-reader.h @@ -264,6 +264,8 @@ class BinaryReaderDelegate { virtual Result OnDropExpr() = 0; virtual Result OnElseExpr() = 0; virtual Result OnEndExpr() = 0; + virtual Result OnSkipFunctionBodyExpr( + std::vector& opcode_buffer) = 0; virtual Result OnF32ConstExpr(uint32_t value_bits) = 0; virtual Result OnF64ConstExpr(uint64_t value_bits) = 0; virtual Result OnV128ConstExpr(v128 value_bits) = 0; @@ -511,6 +513,12 @@ Result ReadBinary(const void* data, BinaryReaderDelegate* reader, const ReadBinaryOptions& options); +Result ExtractFunctionBody(const void* data, + size_t size, + Location& loc, + BinaryReaderDelegate* delegate, + const ReadBinaryOptions& options); + size_t ReadU32Leb128(const uint8_t* ptr, const uint8_t* end, uint32_t* out_value); diff --git a/include/wabt/binary-writer.h b/include/wabt/binary-writer.h index dedba1bdcf..d4dd14e28f 100644 --- a/include/wabt/binary-writer.h +++ b/include/wabt/binary-writer.h @@ -46,6 +46,11 @@ struct WriteBinaryOptions { Result WriteBinaryModule(Stream*, const Module*, const WriteBinaryOptions&); +class OpcodeRawExpr; +Result PackOpcodeRawExpr(OpcodeRawExpr& expr, + Module& module, + const WriteBinaryOptions& options); + void WriteType(Stream* stream, Type type, const char* desc = nullptr); void WriteStr(Stream* stream, diff --git a/include/wabt/common.h b/include/wabt/common.h index e1411b4870..58734e0fc4 100644 --- a/include/wabt/common.h +++ b/include/wabt/common.h @@ -196,7 +196,7 @@ enum class LabelType { Try, TryTable, Catch, - + ExtractFunc, First = Func, Last = Catch, }; diff --git a/include/wabt/expr-visitor.h b/include/wabt/expr-visitor.h index 5be7879391..58a3b80bd6 100644 --- a/include/wabt/expr-visitor.h +++ b/include/wabt/expr-visitor.h @@ -43,6 +43,7 @@ class ExprVisitor { Try, TryTable, Catch, + OpcodeRaw }; Result HandleDefaultState(Expr*); @@ -141,6 +142,7 @@ class ExprVisitor::Delegate { virtual Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) = 0; virtual Result OnLoadSplatExpr(LoadSplatExpr*) = 0; virtual Result OnLoadZeroExpr(LoadZeroExpr*) = 0; + virtual Result OnOpcodeRawExpr(OpcodeRawExpr*) = 0; }; class ExprVisitor::DelegateNop : public ExprVisitor::Delegate { @@ -222,6 +224,7 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate { Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override { return Result::Ok; } Result OnLoadSplatExpr(LoadSplatExpr*) override { return Result::Ok; } Result OnLoadZeroExpr(LoadZeroExpr*) override { return Result::Ok; } + Result OnOpcodeRawExpr(OpcodeRawExpr*) override { return Result::Ok; } }; } // namespace wabt diff --git a/include/wabt/ir.h b/include/wabt/ir.h index 25264bcd91..c3dcc26a0b 100644 --- a/include/wabt/ir.h +++ b/include/wabt/ir.h @@ -429,7 +429,8 @@ enum class ExprType { Unreachable, First = AtomicLoad, - Last = Unreachable + Last = Unreachable, + OpCodeRaw = Last + 1, // virtual type }; const char* GetExprTypeName(ExprType type); @@ -839,6 +840,22 @@ class AtomicFenceExpr : public ExprMixin { uint32_t consistency_model; }; +class OpcodeRawExpr : public ExprMixin { + public: + explicit OpcodeRawExpr(std::vector&& in_opcode_buffer, + FuncSignature& in_func_sig, + const Location& loc = Location()) + : ExprMixin(loc), + opcode_buffer(std::move(in_opcode_buffer)), + is_extracted(false), + func_sig(&in_func_sig) {} + + std::vector opcode_buffer; + bool is_extracted; + ExprList extracted_exprs; + const FuncSignature* func_sig; +}; + struct Tag { explicit Tag(std::string_view name) : name(name) {} diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 2029b0f7c4..8756ed0a4f 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -28,9 +28,24 @@ #include "wabt/cast.h" #include "wabt/common.h" #include "wabt/ir.h" - +#ifdef WABT_OVERRIDE_ALLOC_EXPR +extern void* operator new(size_t size, wabt::Module* m); +#endif namespace wabt { +#ifdef WABT_OVERRIDE_ALLOC_EXPR +template +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 + typename std::__unique_if<_Tp>::__unique_single + wabt_expr_make_unique(_Args&&... __args) { + // static_assert(sizeof(_Tp) <= 128); + return std::unique_ptr<_Tp>(new (static_cast(nullptr)) + _Tp(std::forward<_Args>(__args)...)); +} +#else +#define wabt_expr_make_unique std::make_unique +#endif + namespace { struct LabelNode { @@ -168,6 +183,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnFunctionBodyCount(Index count) override; Result BeginFunctionBody(Index index, Offset size) override; + Result BeginExtractFunctionBody(ExprList& extracted_list, Expr* context); Result OnLocalDecl(Index decl_index, Index count, Type type) override; Result OnOpcode(Opcode opcode) override; @@ -216,6 +232,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnDropExpr() override; Result OnElseExpr() override; Result OnEndExpr() override; + Result OnSkipFunctionBodyExpr(std::vector& opcode_buffer) override; Result OnF32ConstExpr(uint32_t value_bits) override; Result OnF64ConstExpr(uint64_t value_bits) override; Result OnV128ConstExpr(v128 value_bits) override; @@ -801,6 +818,11 @@ Result BinaryReaderIR::BeginFunctionBody(Index index, Offset size) { return PushLabel(LabelType::Func, ¤t_func_->exprs); } +Result BinaryReaderIR::BeginExtractFunctionBody(ExprList& extracted_list, + Expr* context) { + return PushLabel(LabelType::ExtractFunc, &extracted_list, context); +} + Result BinaryReaderIR::OnLocalDecl(Index decl_index, Index count, Type type) { current_func_->local_types.AppendDecl(type, count); @@ -829,7 +851,7 @@ Result BinaryReaderIR::OnAtomicLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } @@ -837,7 +859,7 @@ Result BinaryReaderIR::OnAtomicStoreExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } @@ -845,7 +867,7 @@ Result BinaryReaderIR::OnAtomicRmwExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } @@ -853,7 +875,7 @@ Result BinaryReaderIR::OnAtomicRmwCmpxchgExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } @@ -861,28 +883,28 @@ Result BinaryReaderIR::OnAtomicWaitExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } Result BinaryReaderIR::OnAtomicFenceExpr(uint32_t consistency_model) { - return AppendExpr(std::make_unique(consistency_model)); + return AppendExpr(wabt_expr_make_unique(consistency_model)); } Result BinaryReaderIR::OnAtomicNotifyExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } Result BinaryReaderIR::OnBinaryExpr(Opcode opcode) { - return AppendExpr(std::make_unique(opcode)); + return AppendExpr(wabt_expr_make_unique(opcode)); } Result BinaryReaderIR::OnBlockExpr(Type sig_type) { - auto expr = std::make_unique(); + auto expr = wabt_expr_make_unique(); SetBlockDeclaration(&expr->block.decl, sig_type); ExprList* expr_list = &expr->block.exprs; CHECK_RESULT(AppendExpr(std::move(expr))); @@ -890,17 +912,17 @@ Result BinaryReaderIR::OnBlockExpr(Type sig_type) { } Result BinaryReaderIR::OnBrExpr(Index depth) { - return AppendExpr(std::make_unique(Var(depth, GetLocation()))); + return AppendExpr(wabt_expr_make_unique(Var(depth, GetLocation()))); } Result BinaryReaderIR::OnBrIfExpr(Index depth) { - return AppendExpr(std::make_unique(Var(depth, GetLocation()))); + return AppendExpr(wabt_expr_make_unique(Var(depth, GetLocation()))); } Result BinaryReaderIR::OnBrTableExpr(Index num_targets, Index* target_depths, Index default_target_depth) { - auto expr = std::make_unique(); + auto expr = wabt_expr_make_unique(); expr->default_target = Var(default_target_depth, GetLocation()); expr->targets.resize(num_targets); for (Index i = 0; i < num_targets; ++i) { @@ -910,18 +932,19 @@ Result BinaryReaderIR::OnBrTableExpr(Index num_targets, } Result BinaryReaderIR::OnCallExpr(Index func_index) { - return AppendExpr(std::make_unique(Var(func_index, GetLocation()))); + return AppendExpr( + wabt_expr_make_unique(Var(func_index, GetLocation()))); } Result BinaryReaderIR::OnCallIndirectExpr(Index sig_index, Index table_index) { - auto expr = std::make_unique(); + auto expr = wabt_expr_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()); + return AppendExpr(wabt_expr_make_unique()); } Result BinaryReaderIR::OnReturnCallExpr(Index func_index) { @@ -931,7 +954,7 @@ Result BinaryReaderIR::OnReturnCallExpr(Index func_index) { current_func_->features_used.tailcall = true; } return AppendExpr( - std::make_unique(Var(func_index, GetLocation()))); + wabt_expr_make_unique(Var(func_index, GetLocation()))); } Result BinaryReaderIR::OnReturnCallIndirectExpr(Index sig_index, @@ -941,7 +964,7 @@ Result BinaryReaderIR::OnReturnCallIndirectExpr(Index sig_index, // expression (outside a function) current_func_->features_used.tailcall = true; } - auto expr = std::make_unique(); + auto expr = wabt_expr_make_unique(); SetFuncDeclaration(&expr->decl, Var(sig_index, GetLocation())); expr->table = Var(table_index, GetLocation()); FuncType* type = module_->GetFuncType(Var(sig_index, GetLocation())); @@ -952,15 +975,15 @@ Result BinaryReaderIR::OnReturnCallIndirectExpr(Index sig_index, } Result BinaryReaderIR::OnCompareExpr(Opcode opcode) { - return AppendExpr(std::make_unique(opcode)); + return AppendExpr(wabt_expr_make_unique(opcode)); } Result BinaryReaderIR::OnConvertExpr(Opcode opcode) { - return AppendExpr(std::make_unique(opcode)); + return AppendExpr(wabt_expr_make_unique(opcode)); } Result BinaryReaderIR::OnDropExpr() { - return AppendExpr(std::make_unique()); + return AppendExpr(wabt_expr_make_unique()); } Result BinaryReaderIR::OnElseExpr() { @@ -1009,6 +1032,7 @@ Result BinaryReaderIR::OnEndExpr() { case LabelType::InitExpr: case LabelType::Func: case LabelType::Catch: + case LabelType::ExtractFunc: break; } } @@ -1016,43 +1040,54 @@ Result BinaryReaderIR::OnEndExpr() { return PopLabel(); } +Result BinaryReaderIR::OnSkipFunctionBodyExpr( + std::vector& opcode_buffer) { + Result result_append = AppendExpr(wabt_expr_make_unique( + std::move(opcode_buffer), current_func_->decl.sig, GetLocation())); + Result result_pop = PopLabel(); + + return (result_append == Result::Ok && result_pop == Result::Ok) + ? Result::Ok + : Result::Error; +} + Result BinaryReaderIR::OnF32ConstExpr(uint32_t value_bits) { return AppendExpr( - std::make_unique(Const::F32(value_bits, GetLocation()))); + wabt_expr_make_unique(Const::F32(value_bits, GetLocation()))); } Result BinaryReaderIR::OnF64ConstExpr(uint64_t value_bits) { return AppendExpr( - std::make_unique(Const::F64(value_bits, GetLocation()))); + wabt_expr_make_unique(Const::F64(value_bits, GetLocation()))); } Result BinaryReaderIR::OnV128ConstExpr(v128 value_bits) { return AppendExpr( - std::make_unique(Const::V128(value_bits, GetLocation()))); + wabt_expr_make_unique(Const::V128(value_bits, GetLocation()))); } Result BinaryReaderIR::OnGlobalGetExpr(Index global_index) { return AppendExpr( - std::make_unique(Var(global_index, GetLocation()))); + wabt_expr_make_unique(Var(global_index, GetLocation()))); } Result BinaryReaderIR::OnLocalGetExpr(Index local_index) { return AppendExpr( - std::make_unique(Var(local_index, GetLocation()))); + wabt_expr_make_unique(Var(local_index, GetLocation()))); } Result BinaryReaderIR::OnI32ConstExpr(uint32_t value) { return AppendExpr( - std::make_unique(Const::I32(value, GetLocation()))); + wabt_expr_make_unique(Const::I32(value, GetLocation()))); } Result BinaryReaderIR::OnI64ConstExpr(uint64_t value) { return AppendExpr( - std::make_unique(Const::I64(value, GetLocation()))); + wabt_expr_make_unique(Const::I64(value, GetLocation()))); } Result BinaryReaderIR::OnIfExpr(Type sig_type) { - auto expr = std::make_unique(); + auto expr = wabt_expr_make_unique(); SetBlockDeclaration(&expr->true_.decl, sig_type); ExprList* expr_list = &expr->true_.exprs; CHECK_RESULT(AppendExpr(std::move(expr))); @@ -1063,12 +1098,12 @@ Result BinaryReaderIR::OnLoadExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } Result BinaryReaderIR::OnLoopExpr(Type sig_type) { - auto expr = std::make_unique(); + auto expr = wabt_expr_make_unique(); SetBlockDeclaration(&expr->block.decl, sig_type); ExprList* expr_list = &expr->block.exprs; CHECK_RESULT(AppendExpr(std::move(expr))); @@ -1076,129 +1111,131 @@ Result BinaryReaderIR::OnLoopExpr(Type sig_type) { } Result BinaryReaderIR::OnMemoryCopyExpr(Index destmemidx, Index srcmemidx) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( Var(destmemidx, GetLocation()), Var(srcmemidx, GetLocation()))); } Result BinaryReaderIR::OnDataDropExpr(Index segment) { return AppendExpr( - std::make_unique(Var(segment, GetLocation()))); + wabt_expr_make_unique(Var(segment, GetLocation()))); } Result BinaryReaderIR::OnMemoryFillExpr(Index memidx) { return AppendExpr( - std::make_unique(Var(memidx, GetLocation()))); + wabt_expr_make_unique(Var(memidx, GetLocation()))); } Result BinaryReaderIR::OnMemoryGrowExpr(Index memidx) { return AppendExpr( - std::make_unique(Var(memidx, GetLocation()))); + wabt_expr_make_unique(Var(memidx, GetLocation()))); } Result BinaryReaderIR::OnMemoryInitExpr(Index segment, Index memidx) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( Var(segment, GetLocation()), Var(memidx, GetLocation()))); } Result BinaryReaderIR::OnMemorySizeExpr(Index memidx) { return AppendExpr( - std::make_unique(Var(memidx, GetLocation()))); + wabt_expr_make_unique(Var(memidx, GetLocation()))); } Result BinaryReaderIR::OnTableCopyExpr(Index dst_index, Index src_index) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( Var(dst_index, GetLocation()), Var(src_index, GetLocation()))); } Result BinaryReaderIR::OnElemDropExpr(Index segment) { return AppendExpr( - std::make_unique(Var(segment, GetLocation()))); + wabt_expr_make_unique(Var(segment, GetLocation()))); } Result BinaryReaderIR::OnTableInitExpr(Index segment, Index table_index) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( Var(segment, GetLocation()), Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableGetExpr(Index table_index) { return AppendExpr( - std::make_unique(Var(table_index, GetLocation()))); + wabt_expr_make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableSetExpr(Index table_index) { return AppendExpr( - std::make_unique(Var(table_index, GetLocation()))); + wabt_expr_make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableGrowExpr(Index table_index) { return AppendExpr( - std::make_unique(Var(table_index, GetLocation()))); + wabt_expr_make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableSizeExpr(Index table_index) { return AppendExpr( - std::make_unique(Var(table_index, GetLocation()))); + wabt_expr_make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnTableFillExpr(Index table_index) { return AppendExpr( - std::make_unique(Var(table_index, GetLocation()))); + wabt_expr_make_unique(Var(table_index, GetLocation()))); } Result BinaryReaderIR::OnRefFuncExpr(Index func_index) { module_->used_func_refs.insert(func_index); return AppendExpr( - std::make_unique(Var(func_index, GetLocation()))); + wabt_expr_make_unique(Var(func_index, GetLocation()))); } Result BinaryReaderIR::OnRefNullExpr(Type type) { module_->features_used.exceptions |= (type == Type::ExnRef); - return AppendExpr(std::make_unique(type)); + return AppendExpr(wabt_expr_make_unique(type)); } Result BinaryReaderIR::OnRefIsNullExpr() { - return AppendExpr(std::make_unique()); + return AppendExpr(wabt_expr_make_unique()); } Result BinaryReaderIR::OnNopExpr() { - return AppendExpr(std::make_unique()); + return AppendExpr(wabt_expr_make_unique()); } Result BinaryReaderIR::OnRethrowExpr(Index depth) { - return AppendExpr(std::make_unique(Var(depth, GetLocation()))); + return AppendExpr( + wabt_expr_make_unique(Var(depth, GetLocation()))); } Result BinaryReaderIR::OnReturnExpr() { - return AppendExpr(std::make_unique()); + return AppendExpr(wabt_expr_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)); + return AppendExpr(wabt_expr_make_unique(results)); } Result BinaryReaderIR::OnGlobalSetExpr(Index global_index) { return AppendExpr( - std::make_unique(Var(global_index, GetLocation()))); + wabt_expr_make_unique(Var(global_index, GetLocation()))); } Result BinaryReaderIR::OnLocalSetExpr(Index local_index) { return AppendExpr( - std::make_unique(Var(local_index, GetLocation()))); + wabt_expr_make_unique(Var(local_index, GetLocation()))); } Result BinaryReaderIR::OnStoreExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } Result BinaryReaderIR::OnThrowExpr(Index tag_index) { module_->features_used.exceptions = true; - return AppendExpr(std::make_unique(Var(tag_index, GetLocation()))); + return AppendExpr( + wabt_expr_make_unique(Var(tag_index, GetLocation()))); } Result BinaryReaderIR::OnThrowRefExpr() { @@ -1208,11 +1245,11 @@ Result BinaryReaderIR::OnThrowRefExpr() { Result BinaryReaderIR::OnLocalTeeExpr(Index local_index) { return AppendExpr( - std::make_unique(Var(local_index, GetLocation()))); + wabt_expr_make_unique(Var(local_index, GetLocation()))); } Result BinaryReaderIR::OnTryExpr(Type sig_type) { - auto expr_ptr = std::make_unique(); + auto expr_ptr = wabt_expr_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; @@ -1261,7 +1298,7 @@ Result BinaryReaderIR::OnCatchAllExpr() { Result BinaryReaderIR::OnTryTableExpr(Type sig_type, const CatchClauseVector& catches) { - auto expr_ptr = std::make_unique(); + auto expr_ptr = wabt_expr_make_unique(); TryTableExpr* expr = expr_ptr.get(); expr->catches.reserve(catches.size()); SetBlockDeclaration(&expr->block.decl, sig_type); @@ -1305,15 +1342,15 @@ Result BinaryReaderIR::OnDelegateExpr(Index depth) { } Result BinaryReaderIR::OnUnaryExpr(Opcode opcode) { - return AppendExpr(std::make_unique(opcode)); + return AppendExpr(wabt_expr_make_unique(opcode)); } Result BinaryReaderIR::OnTernaryExpr(Opcode opcode) { - return AppendExpr(std::make_unique(opcode)); + return AppendExpr(wabt_expr_make_unique(opcode)); } Result BinaryReaderIR::OnUnreachableExpr() { - return AppendExpr(std::make_unique()); + return AppendExpr(wabt_expr_make_unique()); } Result BinaryReaderIR::EndFunctionBody(Index index) { @@ -1326,7 +1363,7 @@ Result BinaryReaderIR::EndFunctionBody(Index index) { } Result BinaryReaderIR::OnSimdLaneOpExpr(Opcode opcode, uint64_t value) { - return AppendExpr(std::make_unique(opcode, value)); + return AppendExpr(wabt_expr_make_unique(opcode, value)); } Result BinaryReaderIR::OnSimdLoadLaneExpr(Opcode opcode, @@ -1334,7 +1371,7 @@ Result BinaryReaderIR::OnSimdLoadLaneExpr(Opcode opcode, Address alignment_log2, Address offset, uint64_t value) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset, value)); } @@ -1344,20 +1381,20 @@ Result BinaryReaderIR::OnSimdStoreLaneExpr(Opcode opcode, Address alignment_log2, Address offset, uint64_t value) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset, value)); } Result BinaryReaderIR::OnSimdShuffleOpExpr(Opcode opcode, v128 value) { - return AppendExpr(std::make_unique(opcode, value)); + return AppendExpr(wabt_expr_make_unique(opcode, value)); } Result BinaryReaderIR::OnLoadSplatExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } @@ -1365,7 +1402,7 @@ Result BinaryReaderIR::OnLoadZeroExpr(Opcode opcode, Index memidx, Address alignment_log2, Address offset) { - return AppendExpr(std::make_unique( + return AppendExpr(wabt_expr_make_unique( opcode, Var(memidx, GetLocation()), 1ull << alignment_log2, offset)); } @@ -1712,8 +1749,8 @@ Result BinaryReaderIR::OnCodeMetadata(Offset offset, Address size) { std::vector data_(static_cast(data), static_cast(data) + size); - auto meta = std::make_unique(current_metadata_name_, - std::move(data_)); + auto meta = wabt_expr_make_unique(current_metadata_name_, + std::move(data_)); meta->loc.offset = offset; code_metadata_queue_.push_metadata(std::move(meta)); return Result::Ok; @@ -1857,4 +1894,23 @@ Result ReadBinaryIr(const char* filename, return ReadBinary(data, size, &reader, options); } +Result ExtractOpcodeRawExpr(OpcodeRawExpr& expr, + Module& module, + const ReadBinaryOptions& options) { + if (expr.is_extracted) { + return Result::Ok; + } + Errors errors; + BinaryReaderIR reader(&module, expr.loc.filename.data(), &errors); + CHECK_RESULT(reader.BeginExtractFunctionBody(expr.extracted_exprs, nullptr)); + Result result = + ExtractFunctionBody(expr.opcode_buffer.data(), expr.opcode_buffer.size(), + expr.loc, &reader, options); + if (Succeeded(result)) { + expr.is_extracted = true; + expr.opcode_buffer.clear(); + } + return result; +} + } // namespace wabt diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index 0c13622576..fcebc1158c 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -851,6 +851,11 @@ DEFINE_INDEX_DESC(OnDelegateExpr, "depth"); DEFINE0(OnDropExpr) DEFINE0(OnElseExpr) DEFINE0(OnEndExpr) +Result BinaryReaderLogging::OnSkipFunctionBodyExpr( + std::vector& opcode_buffer) { + LOGF("OnSkipFunctionBodyExpr length: %lu\n", opcode_buffer.size()); + return reader_->OnSkipFunctionBodyExpr(opcode_buffer); +} DEFINE_INDEX_DESC(OnGlobalGetExpr, "index") DEFINE_INDEX_DESC(OnGlobalSetExpr, "index") DEFINE_LOAD_STORE_OPCODE(OnLoadExpr); diff --git a/src/binary-reader.cc b/src/binary-reader.cc index e1859a1c31..00bf2be1d5 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -72,6 +72,11 @@ namespace { class BinaryReader { public: + friend Result wabt::ExtractFunctionBody(const void* data, + size_t size, + Location& loc, + BinaryReaderDelegate* delegate, + const ReadBinaryOptions& options); struct ReadModuleOptions { bool stop_on_first_error; }; @@ -162,6 +167,7 @@ class BinaryReader { [[nodiscard]] Result ReadFunctionBody(Offset end_offset); // ReadInstructions reads until end_offset or the nesting depth reaches zero. [[nodiscard]] Result ReadInstructions(Offset end_offset, const char* context); + [[nodiscard]] Result ReadSkippedFunctionBody(Offset end_offset); [[nodiscard]] Result ReadNameSection(Offset section_size); [[nodiscard]] Result ReadRelocSection(Offset section_size); [[nodiscard]] Result ReadDylinkSection(Offset section_size); @@ -1939,6 +1945,22 @@ Result BinaryReader::ReadInstructions(Offset end_offset, const char* context) { return Result::Error; } +Result BinaryReader::ReadSkippedFunctionBody(Offset end_offset) { +#ifdef WABT_KEEP_OPCODE_WHEN_SKIP_FUNC_BODY + std::vector opcode_buffer(end_offset - state_.offset); + memcpy(opcode_buffer.data(), state_.data + state_.offset, + opcode_buffer.size()); + CALLBACK(OnSkipFunctionBodyExpr, opcode_buffer); + state_.offset = end_offset; +#else + // old version with OnEndExpr + state_.offset = end_offset; + CALLBACK0(OnEndExpr); +#endif + + return Result::Ok; +} + Result BinaryReader::ReadNameSection(Offset section_size) { CALLBACK(BeginNamesSection, section_size); Index i = 0; @@ -2887,7 +2909,7 @@ Result BinaryReader::ReadCodeSection(Offset section_size) { CALLBACK(EndLocalDecls); if (options_.skip_function_bodies) { - state_.offset = end_offset; + CHECK_RESULT(ReadSkippedFunctionBody(end_offset)); } else { CHECK_RESULT(ReadFunctionBody(end_offset)); } @@ -3142,4 +3164,16 @@ Result ReadBinary(const void* data, BinaryReader::ReadModuleOptions{options.stop_on_first_error}); } +Result ExtractFunctionBody(const void* data, + size_t size, + Location& loc, + BinaryReaderDelegate* delegate, + const ReadBinaryOptions& options) { + BinaryReader reader(static_cast(data) - loc.offset, + size + loc.offset, delegate, options); + reader.state_.offset = loc.offset; + return reader.ReadInstructions(reader.state_.offset + size, + "extract function body"); +} + } // namespace wabt diff --git a/src/binary-writer.cc b/src/binary-writer.cc index 600154b941..42797ad2c4 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -384,6 +384,9 @@ class BinaryWriter { WABT_DISALLOW_COPY_AND_ASSIGN(BinaryWriter); public: + friend Result wabt::PackOpcodeRawExpr(OpcodeRawExpr& expr, + Module& module, + const WriteBinaryOptions& options); BinaryWriter(Stream*, const WriteBinaryOptions& options, const Module* module); @@ -1150,6 +1153,17 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { a.entries.emplace_back(code_offset, meta_expr->data); break; } + case ExprType::OpCodeRaw: { + auto* opcode_raw_expr = cast(expr); + if (opcode_raw_expr->is_extracted) { + WriteExprList(func, opcode_raw_expr->extracted_exprs); + } else { + auto& opcode_buffer = opcode_raw_expr->opcode_buffer; + // Opcode::End 0x0b + assert(opcode_buffer[opcode_buffer.size() - 1] == 0x0b); + stream_->WriteData(opcode_buffer.data(), opcode_buffer.size() - 1); + } + } } } @@ -1854,4 +1868,30 @@ Result WriteBinaryModule(Stream* stream, return binary_writer.WriteModule(); } +Result PackOpcodeRawExpr(OpcodeRawExpr& expr, + Module& module, + const WriteBinaryOptions& options) { + if (!expr.is_extracted) { + return Result::Ok; + } + + MemoryStream stream; + BinaryWriter binary_writer(&stream, options, &module); + + binary_writer.WriteExprList(nullptr, expr.extracted_exprs); + WriteOpcode(&stream, Opcode::End); + auto& ob = stream.output_buffer(); + + if (ob.data.size()) { + expr.opcode_buffer = std::move(ob.data); + stream.ReleaseOutputBuffer(); + expr.is_extracted = false; + expr.extracted_exprs.clear(); + return Result::Ok; + } else { + stream.ReleaseOutputBuffer(); + return Result::Error; + } +} + } // namespace wabt diff --git a/src/c-writer.cc b/src/c-writer.cc index 0e96d5e892..8d939e11fd 100644 --- a/src/c-writer.cc +++ b/src/c-writer.cc @@ -4267,6 +4267,8 @@ void CWriter::Write(const ExprList& exprs) { case ExprType::AtomicWait: case ExprType::AtomicNotify: case ExprType::CallRef: + case ExprType::OpCodeRaw: + UNIMPLEMENTED("..."); break; } diff --git a/src/expr-visitor.cc b/src/expr-visitor.cc index 217d45cc01..f11d501c9f 100644 --- a/src/expr-visitor.cc +++ b/src/expr-visitor.cc @@ -149,6 +149,21 @@ Result ExprVisitor::VisitExpr(Expr* root_expr) { } break; } + case State::OpcodeRaw: { + auto opcode_raw_expr = cast(expr); + // ERROR_UNLESS(opcode_raw_expr->is_extracted, "opcode_raw could not + // compile when in visiting") + if (opcode_raw_expr->is_extracted) { + auto& iter = expr_iter_stack_.back(); + if (iter != opcode_raw_expr->extracted_exprs.end()) { + PushDefault(&*iter++); + } else { + PopExprlist(); + } + } + + break; + } } } @@ -449,6 +464,17 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) { case ExprType::Unreachable: CHECK_RESULT(delegate_->OnUnreachableExpr(cast(expr))); break; + case ExprType::OpCodeRaw: { + auto opcode_raw_expr = cast(expr); + CHECK_RESULT(delegate_->OnOpcodeRawExpr(opcode_raw_expr)); + + if (opcode_raw_expr->is_extracted) { + PushExprlist(State::OpcodeRaw, expr, opcode_raw_expr->extracted_exprs); + } else { + // just skip + } + break; + } } return Result::Ok; diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc index 7e9b8d5e14..183b393736 100644 --- a/src/interp/binary-reader-interp.cc +++ b/src/interp/binary-reader-interp.cc @@ -197,6 +197,7 @@ class BinaryReaderInterp : public BinaryReaderNop { Result OnDropExpr() override; Result OnElseExpr() override; Result OnEndExpr() override; + Result OnSkipFunctionBodyExpr(std::vector& opcode_buffer) override; Result OnF32ConstExpr(uint32_t value_bits) override; Result OnF64ConstExpr(uint64_t value_bits) override; Result OnV128ConstExpr(v128 value_bits) override; @@ -1088,6 +1089,12 @@ Result BinaryReaderInterp::OnEndExpr() { return Result::Ok; } +Result BinaryReaderInterp::OnSkipFunctionBodyExpr( + std::vector& opcode_buffer) { + PopLabel(); + return Result::Ok; +} + Result BinaryReaderInterp::OnBrExpr(Index depth) { Index drop_count, keep_count, catch_drop_count; CHECK_RESULT(GetBrDropKeepCount(depth, &drop_count, &keep_count)); diff --git a/src/ir-util.cc b/src/ir-util.cc index 5266a26457..ee229cbeae 100644 --- a/src/ir-util.cc +++ b/src/ir-util.cc @@ -272,6 +272,8 @@ ModuleContext::Arities ModuleContext::GetExprArity(const Expr& expr) const { case ExprType::SimdShuffleOp: return {2, 1}; + case ExprType::OpCodeRaw: + return {0, cast(&expr)->func_sig->GetNumResults()}; } WABT_UNREACHABLE; diff --git a/src/validator.cc b/src/validator.cc index 8ccfa4072f..333b8ab0f0 100644 --- a/src/validator.cc +++ b/src/validator.cc @@ -166,6 +166,7 @@ class Validator : public ExprVisitor::Delegate { Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override; Result OnLoadSplatExpr(LoadSplatExpr*) override; Result OnLoadZeroExpr(LoadZeroExpr*) override; + Result OnOpcodeRawExpr(OpcodeRawExpr* expr) override; private: Type GetDeclarationType(const FuncDeclaration&); @@ -688,6 +689,11 @@ Result Validator::OnLoadZeroExpr(LoadZeroExpr* expr) { return Result::Ok; } +Result Validator::OnOpcodeRawExpr(OpcodeRawExpr* expr) { + // data read from original wasm file, so just return OK; + return Result::Ok; +} + Validator::Validator(Errors* errors, const Module* module, const ValidateOptions& options) diff --git a/src/wat-writer.cc b/src/wat-writer.cc index f19e3c3c86..faad06894e 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -622,6 +622,7 @@ class WatWriter::ExprVisitorDelegate : public ExprVisitor::Delegate { Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override; Result OnLoadSplatExpr(LoadSplatExpr*) override; Result OnLoadZeroExpr(LoadZeroExpr*) override; + Result OnOpcodeRawExpr(OpcodeRawExpr*) override; private: WatWriter* writer_; @@ -1156,6 +1157,11 @@ Result WatWriter::ExprVisitorDelegate::OnLoadZeroExpr(LoadZeroExpr* expr) { return Result::Ok; } +Result WatWriter::ExprVisitorDelegate::OnOpcodeRawExpr(OpcodeRawExpr* expr) { + // WatWriter can't run in skip_function_bodies mode + return Result::Error; +} + void WatWriter::WriteExpr(const Expr* expr) { WABT_TRACE(WriteExprList); ExprVisitorDelegate delegate(this);