diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader-interpreter.cc | 13 | ||||
-rw-r--r-- | src/binary-writer-spec.cc | 5 | ||||
-rw-r--r-- | src/binary-writer-spec.h | 1 | ||||
-rw-r--r-- | src/binary-writer.cc | 321 | ||||
-rw-r--r-- | src/binary-writer.h | 4 | ||||
-rw-r--r-- | src/emscripten-helpers.cc | 18 | ||||
-rw-r--r-- | src/interpreter.h | 4 | ||||
-rw-r--r-- | src/stream.cc | 152 | ||||
-rw-r--r-- | src/stream.h | 60 | ||||
-rw-r--r-- | src/tools/wasm-link.cc | 1 | ||||
-rw-r--r-- | src/tools/wasm-objdump.cc | 1 | ||||
-rw-r--r-- | src/tools/wasm2wast.cc | 7 | ||||
-rw-r--r-- | src/tools/wast-desugar.cc | 5 | ||||
-rw-r--r-- | src/tools/wast2wasm.cc | 9 | ||||
-rw-r--r-- | src/wat-writer.cc | 23 | ||||
-rw-r--r-- | src/wat-writer.h | 4 | ||||
-rw-r--r-- | src/writer.cc | 164 | ||||
-rw-r--r-- | src/writer.h | 84 |
18 files changed, 382 insertions, 494 deletions
diff --git a/src/binary-reader-interpreter.cc b/src/binary-reader-interpreter.cc index 4cac588f..8cf4effa 100644 --- a/src/binary-reader-interpreter.cc +++ b/src/binary-reader-interpreter.cc @@ -26,8 +26,8 @@ #include "src/cast.h" #include "src/error-handler.h" #include "src/interpreter.h" +#include "src/stream.h" #include "src/type-checker.h" -#include "src/writer.h" namespace wabt { @@ -265,7 +265,7 @@ class BinaryReaderInterpreter : public BinaryReaderNop { std::vector<Label> label_stack; IstreamOffsetVectorVector func_fixups; IstreamOffsetVectorVector depth_fixups; - MemoryWriter istream_writer; + MemoryStream istream_; IstreamOffset istream_offset = 0; /* mappings from module index space to env index space; this won't just be a * translation, because imported values will be resolved as well */ @@ -295,14 +295,14 @@ BinaryReaderInterpreter::BinaryReaderInterpreter( : error_handler(error_handler), env(env), module(module), - istream_writer(std::move(istream)), - istream_offset(istream_writer.output_buffer().size()) { + istream_(std::move(istream)), + istream_offset(istream_.output_buffer().size()) { typechecker.set_error_callback( [this](const char* msg) { PrintError("%s", msg); }); } std::unique_ptr<OutputBuffer> BinaryReaderInterpreter::ReleaseOutputBuffer() { - return istream_writer.ReleaseOutputBuffer(); + return istream_.ReleaseOutputBuffer(); } Label* BinaryReaderInterpreter::GetLabel(Index depth) { @@ -374,7 +374,8 @@ IstreamOffset BinaryReaderInterpreter::GetIstreamOffset() { wabt::Result BinaryReaderInterpreter::EmitDataAt(IstreamOffset offset, const void* data, IstreamOffset size) { - return istream_writer.WriteData(offset, data, size); + istream_.WriteDataAt(offset, data, size); + return istream_.result(); } wabt::Result BinaryReaderInterpreter::EmitData(const void* data, diff --git a/src/binary-writer-spec.cc b/src/binary-writer-spec.cc index d8cfd175..1c585780 100644 --- a/src/binary-writer-spec.cc +++ b/src/binary-writer-spec.cc @@ -27,7 +27,6 @@ #include "src/ir.h" #include "src/stream.h" #include "src/string-view.h" -#include "src/writer.h" namespace wabt { @@ -304,8 +303,8 @@ void BinaryWriterSpec::WriteActionResultType(const Script& script, } void BinaryWriterSpec::WriteModule(string_view filename, const Module& module) { - MemoryStream memory_stream; - result_ = WriteBinaryModule(&memory_stream.writer(), &module, + MemoryStream memory_stream(spec_options_->log_stream); + result_ = WriteBinaryModule(&memory_stream, &module, &spec_options_->write_binary_options); if (Succeeded(result_) && write_modules_) result_ = memory_stream.WriteToFile(filename); diff --git a/src/binary-writer-spec.h b/src/binary-writer-spec.h index 3d39c289..e939752e 100644 --- a/src/binary-writer-spec.h +++ b/src/binary-writer-spec.h @@ -24,6 +24,7 @@ namespace wabt { struct WriteBinarySpecOptions { + Stream* log_stream = nullptr; const char* json_filename = nullptr; WriteBinaryOptions write_binary_options; }; diff --git a/src/binary-writer.cc b/src/binary-writer.cc index 7eec73b6..6fc94893 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -31,7 +31,6 @@ #include "src/leb128.h" #include "src/stream.h" #include "src/string-view.h" -#include "src/writer.h" #define PRINT_HEADER_NO_INDEX -1 #define MAX_U32_LEB128_BYTES 5 @@ -101,7 +100,7 @@ class BinaryWriter { WABT_DISALLOW_COPY_AND_ASSIGN(BinaryWriter); public: - BinaryWriter(Writer*, const WriteBinaryOptions* options); + BinaryWriter(Stream*, const WriteBinaryOptions* options); Result WriteModule(const Module* module); @@ -138,7 +137,7 @@ class BinaryWriter { void WriteExceptType(const TypeVector* except_types); void WriteRelocSection(const RelocSection* reloc_section); - Stream stream_; + Stream* stream_; const WriteBinaryOptions* options_ = nullptr; std::vector<RelocSection> reloc_sections_; @@ -163,15 +162,15 @@ static uint8_t log2_u32(uint32_t x) { return result; } -BinaryWriter::BinaryWriter(Writer* writer, const WriteBinaryOptions* options) - : stream_(writer, options->log_stream), options_(options) {} +BinaryWriter::BinaryWriter(Stream* stream, const WriteBinaryOptions* options) + : stream_(stream), options_(options) {} void BinaryWriter::WriteHeader(const char* name, int index) { - if (stream_.has_log_stream()) { + if (stream_->has_log_stream()) { if (index == PRINT_HEADER_NO_INDEX) { - stream_.log_stream().Writef("; %s\n", name); + stream_->log_stream().Writef("; %s\n", name); } else { - stream_.log_stream().Writef("; %s %d\n", name, index); + stream_->log_stream().Writef("; %s %d\n", name, index); } } } @@ -181,10 +180,10 @@ Offset BinaryWriter::WriteU32Leb128Space(Offset leb_size_guess, const char* desc) { assert(leb_size_guess <= MAX_U32_LEB128_BYTES); uint8_t data[MAX_U32_LEB128_BYTES] = {0}; - Offset result = stream_.offset(); + Offset result = stream_->offset(); Offset bytes_to_write = options_->canonicalize_lebs ? leb_size_guess : MAX_U32_LEB128_BYTES; - stream_.WriteData(data, bytes_to_write, desc); + stream_->WriteData(data, bytes_to_write, desc); return result; } @@ -192,20 +191,20 @@ Offset BinaryWriter::WriteFixupU32Leb128Size(Offset offset, Offset leb_size_guess, const char* desc) { if (options_->canonicalize_lebs) { - Offset size = stream_.offset() - offset - leb_size_guess; + Offset size = stream_->offset() - offset - leb_size_guess; Offset leb_size = U32Leb128Length(size); Offset delta = leb_size - leb_size_guess; if (delta != 0) { Offset src_offset = offset + leb_size_guess; Offset dst_offset = offset + leb_size; - stream_.MoveData(dst_offset, src_offset, size); + stream_->MoveData(dst_offset, src_offset, size); } - WriteU32Leb128At(&stream_, offset, size, desc); - stream_.AddOffset(delta); + WriteU32Leb128At(stream_, offset, size, desc); + stream_->AddOffset(delta); return delta; } else { - Offset size = stream_.offset() - offset - MAX_U32_LEB128_BYTES; - WriteFixedU32Leb128At(&stream_, offset, size, desc); + Offset size = stream_->offset() - offset - MAX_U32_LEB128_BYTES; + WriteFixedU32Leb128At(stream_, offset, size, desc); return 0; } } @@ -230,12 +229,12 @@ void BinaryWriter::BeginKnownSection(BinarySection section_code, GetSectionName(section_code), static_cast<unsigned>(section_code)); WriteHeader(desc, PRINT_HEADER_NO_INDEX); - stream_.WriteU8Enum(section_code, "section code"); + stream_->WriteU8Enum(section_code, "section code"); last_section_type_ = section_code; last_section_leb_size_guess_ = leb_size_guess; last_section_offset_ = WriteU32Leb128Space(leb_size_guess, "section size (guess)"); - last_section_payload_offset_ = stream_.offset(); + last_section_payload_offset_ = stream_->offset(); } void BinaryWriter::BeginCustomSection(const char* name, size_t leb_size_guess) { @@ -243,13 +242,13 @@ void BinaryWriter::BeginCustomSection(const char* name, size_t leb_size_guess) { char desc[100]; wabt_snprintf(desc, sizeof(desc), "section \"%s\"", name); WriteHeader(desc, PRINT_HEADER_NO_INDEX); - stream_.WriteU8Enum(BinarySection::Custom, "custom section code"); + stream_->WriteU8Enum(BinarySection::Custom, "custom section code"); last_section_type_ = BinarySection::Custom; last_section_leb_size_guess_ = leb_size_guess; last_section_offset_ = WriteU32Leb128Space(leb_size_guess, "section size (guess)"); - last_section_payload_offset_ = stream_.offset(); - WriteStr(&stream_, name, "custom section name", PrintChars::Yes); + last_section_payload_offset_ = stream_->offset(); + WriteStr(stream_, name, "custom section name", PrintChars::Yes); } void BinaryWriter::EndSection() { @@ -268,7 +267,7 @@ void BinaryWriter::BeginSubsection(const char* name, size_t leb_size_guess) { last_subsection_leb_size_guess_ = leb_size_guess; last_subsection_offset_ = WriteU32Leb128Space(leb_size_guess, "subsection size (guess)"); - last_subsection_payload_offset_ = stream_.offset(); + last_subsection_payload_offset_ = stream_->offset(); } void BinaryWriter::EndSubsection() { @@ -297,7 +296,7 @@ void BinaryWriter::AddReloc(RelocType reloc_type, Index index) { } // Add a new relocation to the curent reloc section - size_t offset = stream_.offset() - last_section_payload_offset_; + size_t offset = stream_->offset() - last_section_payload_offset_; current_reloc_section_->relocations.emplace_back(reloc_type, offset, index); } @@ -306,9 +305,9 @@ void BinaryWriter::WriteU32Leb128WithReloc(Index index, RelocType reloc_type) { if (options_->relocatable) { AddReloc(reloc_type, index); - WriteFixedU32Leb128(&stream_, index, desc); + WriteFixedU32Leb128(stream_, index, desc); } else { - WriteU32Leb128(&stream_, index, desc); + WriteU32Leb128(stream_, index, desc); } } @@ -329,73 +328,73 @@ void BinaryWriter::WriteExpr(const Module* module, const Expr* expr) { switch (expr->type()) { case ExprType::Binary: - WriteOpcode(&stream_, cast<BinaryExpr>(expr)->opcode); + WriteOpcode(stream_, cast<BinaryExpr>(expr)->opcode); break; case ExprType::Block: - WriteOpcode(&stream_, Opcode::Block); - write_inline_signature_type(&stream_, cast<BlockExpr>(expr)->block.sig); + WriteOpcode(stream_, Opcode::Block); + write_inline_signature_type(stream_, cast<BlockExpr>(expr)->block.sig); WriteExprList(module, func, cast<BlockExpr>(expr)->block.exprs); - WriteOpcode(&stream_, Opcode::End); + WriteOpcode(stream_, Opcode::End); break; case ExprType::Br: - WriteOpcode(&stream_, Opcode::Br); - WriteU32Leb128(&stream_, GetLabelVarDepth(&cast<BrExpr>(expr)->var), + WriteOpcode(stream_, Opcode::Br); + WriteU32Leb128(stream_, GetLabelVarDepth(&cast<BrExpr>(expr)->var), "break depth"); break; case ExprType::BrIf: - WriteOpcode(&stream_, Opcode::BrIf); - WriteU32Leb128(&stream_, GetLabelVarDepth(&cast<BrIfExpr>(expr)->var), + WriteOpcode(stream_, Opcode::BrIf); + WriteU32Leb128(stream_, GetLabelVarDepth(&cast<BrIfExpr>(expr)->var), "break depth"); break; case ExprType::BrTable: { auto br_table_expr = cast<BrTableExpr>(expr); - WriteOpcode(&stream_, Opcode::BrTable); - WriteU32Leb128(&stream_, br_table_expr->targets.size(), "num targets"); + WriteOpcode(stream_, Opcode::BrTable); + WriteU32Leb128(stream_, br_table_expr->targets.size(), "num targets"); Index depth; for (const Var& var : br_table_expr->targets) { depth = GetLabelVarDepth(&var); - WriteU32Leb128(&stream_, depth, "break depth"); + WriteU32Leb128(stream_, depth, "break depth"); } depth = GetLabelVarDepth(&br_table_expr->default_target); - WriteU32Leb128(&stream_, depth, "break depth for default"); + WriteU32Leb128(stream_, depth, "break depth for default"); break; } case ExprType::Call: { Index index = module->GetFuncIndex(cast<CallExpr>(expr)->var); - WriteOpcode(&stream_, Opcode::Call); + WriteOpcode(stream_, Opcode::Call); WriteU32Leb128WithReloc(index, "function index", RelocType::FuncIndexLEB); break; } case ExprType::CallIndirect: { Index index = module->GetFuncTypeIndex(cast<CallIndirectExpr>(expr)->var); - WriteOpcode(&stream_, Opcode::CallIndirect); + WriteOpcode(stream_, Opcode::CallIndirect); WriteU32Leb128WithReloc(index, "signature index", RelocType::TypeIndexLEB); - WriteU32Leb128(&stream_, 0, "call_indirect reserved"); + WriteU32Leb128(stream_, 0, "call_indirect reserved"); break; } case ExprType::Compare: - WriteOpcode(&stream_, cast<CompareExpr>(expr)->opcode); + WriteOpcode(stream_, cast<CompareExpr>(expr)->opcode); break; case ExprType::Const: { const Const& const_ = cast<ConstExpr>(expr)->const_; switch (const_.type) { case Type::I32: { - WriteOpcode(&stream_, Opcode::I32Const); - WriteS32Leb128(&stream_, const_.u32, "i32 literal"); + WriteOpcode(stream_, Opcode::I32Const); + WriteS32Leb128(stream_, const_.u32, "i32 literal"); break; } case Type::I64: - WriteOpcode(&stream_, Opcode::I64Const); - WriteS64Leb128(&stream_, const_.u64, "i64 literal"); + WriteOpcode(stream_, Opcode::I64Const); + WriteS64Leb128(stream_, const_.u64, "i64 literal"); break; case Type::F32: - WriteOpcode(&stream_, Opcode::F32Const); - stream_.WriteU32(const_.f32_bits, "f32 literal"); + WriteOpcode(stream_, Opcode::F32Const); + stream_->WriteU32(const_.f32_bits, "f32 literal"); break; case Type::F64: - WriteOpcode(&stream_, Opcode::F64Const); - stream_.WriteU64(const_.f64_bits, "f64 literal"); + WriteOpcode(stream_, Opcode::F64Const); + stream_->WriteU64(const_.f64_bits, "f64 literal"); break; default: assert(0); @@ -403,125 +402,125 @@ void BinaryWriter::WriteExpr(const Module* module, break; } case ExprType::Convert: - WriteOpcode(&stream_, cast<ConvertExpr>(expr)->opcode); + WriteOpcode(stream_, cast<ConvertExpr>(expr)->opcode); break; case ExprType::CurrentMemory: - WriteOpcode(&stream_, Opcode::CurrentMemory); - WriteU32Leb128(&stream_, 0, "current_memory reserved"); + WriteOpcode(stream_, Opcode::CurrentMemory); + WriteU32Leb128(stream_, 0, "current_memory reserved"); break; case ExprType::Drop: - WriteOpcode(&stream_, Opcode::Drop); + WriteOpcode(stream_, Opcode::Drop); break; case ExprType::GetGlobal: { Index index = module->GetGlobalIndex(cast<GetGlobalExpr>(expr)->var); - WriteOpcode(&stream_, Opcode::GetGlobal); + WriteOpcode(stream_, Opcode::GetGlobal); WriteU32Leb128WithReloc(index, "global index", RelocType::GlobalIndexLEB); break; } case ExprType::GetLocal: { Index index = GetLocalIndex(func, cast<GetLocalExpr>(expr)->var); - WriteOpcode(&stream_, Opcode::GetLocal); - WriteU32Leb128(&stream_, index, "local index"); + WriteOpcode(stream_, Opcode::GetLocal); + WriteU32Leb128(stream_, index, "local index"); break; } case ExprType::GrowMemory: - WriteOpcode(&stream_, Opcode::GrowMemory); - WriteU32Leb128(&stream_, 0, "grow_memory reserved"); + WriteOpcode(stream_, Opcode::GrowMemory); + WriteU32Leb128(stream_, 0, "grow_memory reserved"); break; case ExprType::If: { auto if_expr = cast<IfExpr>(expr); - WriteOpcode(&stream_, Opcode::If); - write_inline_signature_type(&stream_, if_expr->true_.sig); + WriteOpcode(stream_, Opcode::If); + write_inline_signature_type(stream_, if_expr->true_.sig); WriteExprList(module, func, if_expr->true_.exprs); if (!if_expr->false_.empty()) { - WriteOpcode(&stream_, Opcode::Else); + WriteOpcode(stream_, Opcode::Else); WriteExprList(module, func, if_expr->false_); } - WriteOpcode(&stream_, Opcode::End); + WriteOpcode(stream_, Opcode::End); break; } case ExprType::Load: { auto load_expr = cast<LoadExpr>(expr); - WriteOpcode(&stream_, load_expr->opcode); + WriteOpcode(stream_, load_expr->opcode); Address align = load_expr->opcode.GetAlignment(load_expr->align); - stream_.WriteU8(log2_u32(align), "alignment"); - WriteU32Leb128(&stream_, load_expr->offset, "load offset"); + stream_->WriteU8(log2_u32(align), "alignment"); + WriteU32Leb128(stream_, load_expr->offset, "load offset"); break; } case ExprType::Loop: - WriteOpcode(&stream_, Opcode::Loop); - write_inline_signature_type(&stream_, cast<LoopExpr>(expr)->block.sig); + WriteOpcode(stream_, Opcode::Loop); + write_inline_signature_type(stream_, cast<LoopExpr>(expr)->block.sig); WriteExprList(module, func, cast<LoopExpr>(expr)->block.exprs); - WriteOpcode(&stream_, Opcode::End); + WriteOpcode(stream_, Opcode::End); break; case ExprType::Nop: - WriteOpcode(&stream_, Opcode::Nop); + WriteOpcode(stream_, Opcode::Nop); break; case ExprType::Rethrow: - WriteOpcode(&stream_, Opcode::Rethrow); - WriteU32Leb128(&stream_, GetLabelVarDepth(&cast<RethrowExpr>(expr)->var), + WriteOpcode(stream_, Opcode::Rethrow); + WriteU32Leb128(stream_, GetLabelVarDepth(&cast<RethrowExpr>(expr)->var), "rethrow depth"); break; case ExprType::Return: - WriteOpcode(&stream_, Opcode::Return); + WriteOpcode(stream_, Opcode::Return); break; case ExprType::Select: - WriteOpcode(&stream_, Opcode::Select); + WriteOpcode(stream_, Opcode::Select); break; case ExprType::SetGlobal: { Index index = module->GetGlobalIndex(cast<SetGlobalExpr>(expr)->var); - WriteOpcode(&stream_, Opcode::SetGlobal); + WriteOpcode(stream_, Opcode::SetGlobal); WriteU32Leb128WithReloc(index, "global index", RelocType::GlobalIndexLEB); break; } case ExprType::SetLocal: { Index index = GetLocalIndex(func, cast<SetLocalExpr>(expr)->var); - WriteOpcode(&stream_, Opcode::SetLocal); - WriteU32Leb128(&stream_, index, "local index"); + WriteOpcode(stream_, Opcode::SetLocal); + WriteU32Leb128(stream_, index, "local index"); break; } case ExprType::Store: { auto store_expr = cast<StoreExpr>(expr); - WriteOpcode(&stream_, store_expr->opcode); + WriteOpcode(stream_, store_expr->opcode); Address align = store_expr->opcode.GetAlignment(store_expr->align); - stream_.WriteU8(log2_u32(align), "alignment"); - WriteU32Leb128(&stream_, store_expr->offset, "store offset"); + stream_->WriteU8(log2_u32(align), "alignment"); + WriteU32Leb128(stream_, store_expr->offset, "store offset"); break; } case ExprType::TeeLocal: { Index index = GetLocalIndex(func, cast<TeeLocalExpr>(expr)->var); - WriteOpcode(&stream_, Opcode::TeeLocal); - WriteU32Leb128(&stream_, index, "local index"); + WriteOpcode(stream_, Opcode::TeeLocal); + WriteU32Leb128(stream_, index, "local index"); break; } case ExprType::Throw: - WriteOpcode(&stream_, Opcode::Throw); - WriteU32Leb128(&stream_, GetExceptVarDepth(&cast<ThrowExpr>(expr)->var), + WriteOpcode(stream_, Opcode::Throw); + WriteU32Leb128(stream_, GetExceptVarDepth(&cast<ThrowExpr>(expr)->var), "throw exception"); break; case ExprType::TryBlock: { auto try_expr = cast<TryExpr>(expr); - WriteOpcode(&stream_, Opcode::Try); - write_inline_signature_type(&stream_, try_expr->block.sig); + WriteOpcode(stream_, Opcode::Try); + write_inline_signature_type(stream_, try_expr->block.sig); WriteExprList(module, func, try_expr->block.exprs); for (const Catch& catch_ : try_expr->catches) { if (catch_.IsCatchAll()) { - WriteOpcode(&stream_, Opcode::CatchAll); + WriteOpcode(stream_, Opcode::CatchAll); } else { - WriteOpcode(&stream_, Opcode::Catch); - WriteU32Leb128(&stream_, GetExceptVarDepth(&catch_.var), + WriteOpcode(stream_, Opcode::Catch); + WriteU32Leb128(stream_, GetExceptVarDepth(&catch_.var), "catch exception"); } WriteExprList(module, func, catch_.exprs); } - WriteOpcode(&stream_, Opcode::End); + WriteOpcode(stream_, Opcode::End); break; } case ExprType::Unary: - WriteOpcode(&stream_, cast<UnaryExpr>(expr)->opcode); + WriteOpcode(stream_, cast<UnaryExpr>(expr)->opcode); break; case ExprType::Unreachable: - WriteOpcode(&stream_, Opcode::Unreachable); + WriteOpcode(stream_, Opcode::Unreachable); break; } } @@ -535,14 +534,14 @@ void BinaryWriter::WriteExprList(const Module* module, void BinaryWriter::WriteInitExpr(const Module* module, const ExprList& expr) { WriteExprList(module, nullptr, expr); - WriteOpcode(&stream_, Opcode::End); + WriteOpcode(stream_, Opcode::End); } void BinaryWriter::WriteFuncLocals(const Module* module, const Func* func, const TypeVector& local_types) { if (local_types.size() == 0) { - WriteU32Leb128(&stream_, 0, "local decl count"); + WriteU32Leb128(stream_, 0, "local decl count"); return; } @@ -564,7 +563,7 @@ void BinaryWriter::WriteFuncLocals(const Module* module, } /* loop through again to write everything out */ - WriteU32Leb128(&stream_, local_decl_count, "local decl count"); + WriteU32Leb128(stream_, local_decl_count, "local decl count"); current_type = GET_LOCAL_TYPE(FIRST_LOCAL_INDEX); Index local_type_count = 1; for (Index i = FIRST_LOCAL_INDEX + 1; i <= LAST_LOCAL_INDEX; ++i) { @@ -573,8 +572,8 @@ void BinaryWriter::WriteFuncLocals(const Module* module, if (current_type == type) { local_type_count++; } else { - WriteU32Leb128(&stream_, local_type_count, "local type count"); - WriteType(&stream_, current_type); + WriteU32Leb128(stream_, local_type_count, "local type count"); + WriteType(stream_, current_type); local_type_count = 1; current_type = type; } @@ -584,27 +583,27 @@ void BinaryWriter::WriteFuncLocals(const Module* module, void BinaryWriter::WriteFunc(const Module* module, const Func* func) { WriteFuncLocals(module, func, func->local_types); WriteExprList(module, func, func->exprs); - WriteOpcode(&stream_, Opcode::End); + WriteOpcode(stream_, Opcode::End); } void BinaryWriter::WriteTable(const Table* table) { - WriteType(&stream_, Type::Anyfunc); - WriteLimits(&stream_, &table->elem_limits); + WriteType(stream_, Type::Anyfunc); + WriteLimits(stream_, &table->elem_limits); } void BinaryWriter::WriteMemory(const Memory* memory) { - WriteLimits(&stream_, &memory->page_limits); + WriteLimits(stream_, &memory->page_limits); } void BinaryWriter::WriteGlobalHeader(const Global* global) { - WriteType(&stream_, global->type); - stream_.WriteU8(global->mutable_, "global mutability"); + WriteType(stream_, global->type); + stream_->WriteU8(global->mutable_, "global mutability"); } void BinaryWriter::WriteExceptType(const TypeVector* except_types) { - WriteU32Leb128(&stream_, except_types->size(), "exception type count"); + WriteU32Leb128(stream_, except_types->size(), "exception type count"); for (Type ty : *except_types) - WriteType(&stream_, ty); + WriteType(stream_, ty); } void BinaryWriter::WriteRelocSection(const RelocSection* reloc_section) { @@ -612,19 +611,19 @@ void BinaryWriter::WriteRelocSection(const RelocSection* reloc_section) { wabt_snprintf(section_name, sizeof(section_name), "%s.%s", WABT_BINARY_SECTION_RELOC, reloc_section->name); BeginCustomSection(section_name, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, reloc_section->section_code, "reloc section type"); + WriteU32Leb128(stream_, reloc_section->section_code, "reloc section type"); const std::vector<Reloc>& relocs = reloc_section->relocations; - WriteU32Leb128(&stream_, relocs.size(), "num relocs"); + WriteU32Leb128(stream_, relocs.size(), "num relocs"); for (const Reloc& reloc : relocs) { - WriteU32Leb128(&stream_, reloc.type, "reloc type"); - WriteU32Leb128(&stream_, reloc.offset, "reloc offset"); - WriteU32Leb128(&stream_, reloc.index, "reloc index"); + WriteU32Leb128(stream_, reloc.type, "reloc type"); + WriteU32Leb128(stream_, reloc.offset, "reloc offset"); + WriteU32Leb128(stream_, reloc.index, "reloc index"); switch (reloc.type) { case RelocType::MemoryAddressLEB: case RelocType::MemoryAddressSLEB: case RelocType::MemoryAddressI32: - WriteU32Leb128(&stream_, reloc.addend, "reloc addend"); + WriteU32Leb128(stream_, reloc.addend, "reloc addend"); break; default: break; @@ -635,46 +634,46 @@ void BinaryWriter::WriteRelocSection(const RelocSection* reloc_section) { } Result BinaryWriter::WriteModule(const Module* module) { - stream_.WriteU32(WABT_BINARY_MAGIC, "WASM_BINARY_MAGIC"); - stream_.WriteU32(WABT_BINARY_VERSION, "WASM_BINARY_VERSION"); + stream_->WriteU32(WABT_BINARY_MAGIC, "WASM_BINARY_MAGIC"); + stream_->WriteU32(WABT_BINARY_VERSION, "WASM_BINARY_VERSION"); if (module->func_types.size()) { BeginKnownSection(BinarySection::Type, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, module->func_types.size(), "num types"); + WriteU32Leb128(stream_, module->func_types.size(), "num types"); for (size_t i = 0; i < module->func_types.size(); ++i) { const FuncType* func_type = module->func_types[i]; const FuncSignature* sig = &func_type->sig; WriteHeader("type", i); - WriteType(&stream_, Type::Func); + WriteType(stream_, Type::Func); Index num_params = sig->param_types.size(); Index num_results = sig->result_types.size(); - WriteU32Leb128(&stream_, num_params, "num params"); + WriteU32Leb128(stream_, num_params, "num params"); for (size_t j = 0; j < num_params; ++j) - WriteType(&stream_, sig->param_types[j]); + WriteType(stream_, sig->param_types[j]); - WriteU32Leb128(&stream_, num_results, "num results"); + WriteU32Leb128(stream_, num_results, "num results"); for (size_t j = 0; j < num_results; ++j) - WriteType(&stream_, sig->result_types[j]); + WriteType(stream_, sig->result_types[j]); } EndSection(); } if (module->imports.size()) { BeginKnownSection(BinarySection::Import, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, module->imports.size(), "num imports"); + WriteU32Leb128(stream_, module->imports.size(), "num imports"); for (size_t i = 0; i < module->imports.size(); ++i) { const Import* import = module->imports[i]; WriteHeader("import header", i); - WriteStr(&stream_, import->module_name, "import module name", + WriteStr(stream_, import->module_name, "import module name", PrintChars::Yes); - WriteStr(&stream_, import->field_name, "import field name", + WriteStr(stream_, import->field_name, "import field name", PrintChars::Yes); - stream_.WriteU8Enum(import->kind(), "import kind"); + stream_->WriteU8Enum(import->kind(), "import kind"); switch (import->kind()) { case ExternalKind::Func: - WriteU32Leb128(&stream_, module->GetFuncTypeIndex( + WriteU32Leb128(stream_, module->GetFuncTypeIndex( cast<FuncImport>(import)->func.decl), "import signature index"); break; @@ -703,14 +702,14 @@ Result BinaryWriter::WriteModule(const Module* module) { Index num_funcs = module->funcs.size() - module->num_func_imports; if (num_funcs) { BeginKnownSection(BinarySection::Function, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, num_funcs, "num functions"); + WriteU32Leb128(stream_, num_funcs, "num functions"); for (size_t i = 0; i < num_funcs; ++i) { const Func* func = module->funcs[i + module->num_func_imports]; char desc[100]; wabt_snprintf(desc, sizeof(desc), "function %" PRIzd " signature index", i); - WriteU32Leb128(&stream_, module->GetFuncTypeIndex(func->decl), desc); + WriteU32Leb128(stream_, module->GetFuncTypeIndex(func->decl), desc); } EndSection(); } @@ -719,7 +718,7 @@ Result BinaryWriter::WriteModule(const Module* module) { Index num_tables = module->tables.size() - module->num_table_imports; if (num_tables) { BeginKnownSection(BinarySection::Table, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, num_tables, "num tables"); + WriteU32Leb128(stream_, num_tables, "num tables"); for (size_t i = 0; i < num_tables; ++i) { const Table* table = module->tables[i + module->num_table_imports]; WriteHeader("table", i); @@ -732,7 +731,7 @@ Result BinaryWriter::WriteModule(const Module* module) { Index num_memories = module->memories.size() - module->num_memory_imports; if (num_memories) { BeginKnownSection(BinarySection::Memory, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, num_memories, "num memories"); + WriteU32Leb128(stream_, num_memories, "num memories"); for (size_t i = 0; i < num_memories; ++i) { const Memory* memory = module->memories[i + module->num_memory_imports]; WriteHeader("memory", i); @@ -745,7 +744,7 @@ Result BinaryWriter::WriteModule(const Module* module) { Index num_globals = module->globals.size() - module->num_global_imports; if (num_globals) { BeginKnownSection(BinarySection::Global, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, num_globals, "num globals"); + WriteU32Leb128(stream_, num_globals, "num globals"); for (size_t i = 0; i < num_globals; ++i) { const Global* global = module->globals[i + module->num_global_imports]; @@ -757,35 +756,35 @@ Result BinaryWriter::WriteModule(const Module* module) { if (module->exports.size()) { BeginKnownSection(BinarySection::Export, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, module->exports.size(), "num exports"); + WriteU32Leb128(stream_, module->exports.size(), "num exports"); for (const Export* export_ : module->exports) { - WriteStr(&stream_, export_->name, "export name", PrintChars::Yes); - stream_.WriteU8Enum(export_->kind, "export kind"); + WriteStr(stream_, export_->name, "export name", PrintChars::Yes); + stream_->WriteU8Enum(export_->kind, "export kind"); switch (export_->kind) { case ExternalKind::Func: { Index index = module->GetFuncIndex(export_->var); - WriteU32Leb128(&stream_, index, "export func index"); + WriteU32Leb128(stream_, index, "export func index"); break; } case ExternalKind::Table: { Index index = module->GetTableIndex(export_->var); - WriteU32Leb128(&stream_, index, "export table index"); + WriteU32Leb128(stream_, index, "export table index"); break; } case ExternalKind::Memory: { Index index = module->GetMemoryIndex(export_->var); - WriteU32Leb128(&stream_, index, "export memory index"); + WriteU32Leb128(stream_, index, "export memory index"); break; } case ExternalKind::Global: { Index index = module->GetGlobalIndex(export_->var); - WriteU32Leb128(&stream_, index, "export global index"); + WriteU32Leb128(stream_, index, "export global index"); break; } case ExternalKind::Except: { Index index = module->GetExceptIndex(export_->var); - WriteU32Leb128(&stream_, index, "export exception index"); + WriteU32Leb128(stream_, index, "export exception index"); break; } } @@ -797,21 +796,21 @@ Result BinaryWriter::WriteModule(const Module* module) { Index start_func_index = module->GetFuncIndex(*module->start); if (start_func_index != kInvalidIndex) { BeginKnownSection(BinarySection::Start, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, start_func_index, "start func index"); + WriteU32Leb128(stream_, start_func_index, "start func index"); EndSection(); } } if (module->elem_segments.size()) { BeginKnownSection(BinarySection::Elem, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, module->elem_segments.size(), "num elem segments"); + WriteU32Leb128(stream_, module->elem_segments.size(), "num elem segments"); for (size_t i = 0; i < module->elem_segments.size(); ++i) { ElemSegment* segment = module->elem_segments[i]; Index table_index = module->GetTableIndex(segment->table_var); WriteHeader("elem segment header", i); - WriteU32Leb128(&stream_, table_index, "table index"); + WriteU32Leb128(stream_, table_index, "table index"); WriteInitExpr(module, segment->offset); - WriteU32Leb128(&stream_, segment->vars.size(), "num function indices"); + WriteU32Leb128(stream_, segment->vars.size(), "num function indices"); for (const Var& var : segment->vars) { Index index = module->GetFuncIndex(var); WriteU32Leb128WithReloc(index, "function index", @@ -825,7 +824,7 @@ Result BinaryWriter::WriteModule(const Module* module) { Index num_exceptions = module->excepts.size() - module->num_except_imports; if (num_exceptions) { BeginCustomSection("exception", LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, num_exceptions, "exception count"); + WriteU32Leb128(stream_, num_exceptions, "exception count"); for (Index i = module->num_except_imports; i < num_exceptions; ++i) { WriteExceptType(&module->excepts[i]->sig); } @@ -834,7 +833,7 @@ Result BinaryWriter::WriteModule(const Module* module) { if (num_funcs) { BeginKnownSection(BinarySection::Code, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, num_funcs, "num functions"); + WriteU32Leb128(stream_, num_funcs, "num functions"); for (size_t i = 0; i < num_funcs; ++i) { WriteHeader("function body", i); @@ -853,16 +852,16 @@ Result BinaryWriter::WriteModule(const Module* module) { if (module->data_segments.size()) { BeginKnownSection(BinarySection::Data, LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, module->data_segments.size(), "num data segments"); + WriteU32Leb128(stream_, module->data_segments.size(), "num data segments"); for (size_t i = 0; i < module->data_segments.size(); ++i) { const DataSegment* segment = module->data_segments[i]; WriteHeader("data segment header", i); Index memory_index = module->GetMemoryIndex(segment->memory_var); - WriteU32Leb128(&stream_, memory_index, "memory index"); + WriteU32Leb128(stream_, memory_index, "memory index"); WriteInitExpr(module, segment->offset); - WriteU32Leb128(&stream_, segment->data.size(), "data segment size"); + WriteU32Leb128(stream_, segment->data.size(), "data segment size"); WriteHeader("data segment data", i); - stream_.WriteData(segment->data, "data segment data"); + stream_->WriteData(segment->data, "data segment data"); } EndSection(); } @@ -880,41 +879,41 @@ Result BinaryWriter::WriteModule(const Module* module) { } if (named_functions > 0) { - WriteU32Leb128(&stream_, 1, "function name type"); + WriteU32Leb128(stream_, 1, "function name type"); BeginSubsection("function name subsection", LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, named_functions, "num functions"); + WriteU32Leb128(stream_, named_functions, "num functions"); for (size_t i = 0; i < module->funcs.size(); ++i) { const Func* func = module->funcs[i]; if (func->name.empty()) continue; - WriteU32Leb128(&stream_, i, "function index"); + WriteU32Leb128(stream_, i, "function index"); wabt_snprintf(desc, sizeof(desc), "func name %" PRIzd, i); - WriteDebugName(&stream_, func->name, desc); + WriteDebugName(stream_, func->name, desc); } EndSubsection(); } - WriteU32Leb128(&stream_, 2, "local name type"); + WriteU32Leb128(stream_, 2, "local name type"); BeginSubsection("local name subsection", LEB_SECTION_SIZE_GUESS); - WriteU32Leb128(&stream_, module->funcs.size(), "num functions"); + WriteU32Leb128(stream_, module->funcs.size(), "num functions"); for (size_t i = 0; i < module->funcs.size(); ++i) { const Func* func = module->funcs[i]; Index num_params = func->GetNumParams(); Index num_locals = func->local_types.size(); Index num_params_and_locals = func->GetNumParamsAndLocals(); - WriteU32Leb128(&stream_, i, "function index"); - WriteU32Leb128(&stream_, num_params_and_locals, "num locals"); + WriteU32Leb128(stream_, i, "function index"); + WriteU32Leb128(stream_, num_params_and_locals, "num locals"); MakeTypeBindingReverseMapping(func->decl.sig.param_types, func->param_bindings, &index_to_name); for (size_t j = 0; j < num_params; ++j) { const std::string& name = index_to_name[j]; wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, j); - WriteU32Leb128(&stream_, j, "local index"); - WriteDebugName(&stream_, name, desc); + WriteU32Leb128(stream_, j, "local index"); + WriteDebugName(stream_, name, desc); } MakeTypeBindingReverseMapping(func->local_types, func->local_bindings, @@ -922,8 +921,8 @@ Result BinaryWriter::WriteModule(const Module* module) { for (size_t j = 0; j < num_locals; ++j) { const std::string& name = index_to_name[j]; wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, num_params + j); - WriteU32Leb128(&stream_, num_params + j, "local index"); - WriteDebugName(&stream_, name, desc); + WriteU32Leb128(stream_, num_params + j, "local index"); + WriteDebugName(stream_, name, desc); } } EndSubsection(); @@ -936,15 +935,15 @@ Result BinaryWriter::WriteModule(const Module* module) { } } - return stream_.result(); + return stream_->result(); } } // end anonymous namespace -Result WriteBinaryModule(Writer* writer, +Result WriteBinaryModule(Stream* stream, const Module* module, const WriteBinaryOptions* options) { - BinaryWriter binary_writer(writer, options); + BinaryWriter binary_writer(stream, options); return binary_writer.WriteModule(module); } diff --git a/src/binary-writer.h b/src/binary-writer.h index 1dff83fa..aae02d3c 100644 --- a/src/binary-writer.h +++ b/src/binary-writer.h @@ -23,18 +23,16 @@ namespace wabt { -class Writer; struct Module; struct Script; struct WriteBinaryOptions { - Stream* log_stream = nullptr; bool canonicalize_lebs = true; bool relocatable = false; bool write_debug_names = false; }; -Result WriteBinaryModule(Writer*, const Module*, const WriteBinaryOptions*); +Result WriteBinaryModule(Stream*, const Module*, const WriteBinaryOptions*); void WriteType(Stream* stream, Type type); diff --git a/src/emscripten-helpers.cc b/src/emscripten-helpers.cc index 4d80b230..48513fdd 100644 --- a/src/emscripten-helpers.cc +++ b/src/emscripten-helpers.cc @@ -35,7 +35,6 @@ #include "src/wast-lexer.h" #include "src/wast-parser.h" #include "src/wat-writer.h" -#include "src/writer.h" struct WabtParseWastResult { wabt::Result result; @@ -78,7 +77,6 @@ WabtReadBinaryResult* wabt_read_binary( int read_debug_names, wabt::ErrorHandlerBuffer* error_handler) { wabt::ReadBinaryOptions options; - options.log_stream = nullptr; options.read_debug_names = read_debug_names; WabtReadBinaryResult* result = new WabtReadBinaryResult(); @@ -128,18 +126,17 @@ WabtWriteModuleResult* wabt_write_binary_module(wabt::Module* module, int canonicalize_lebs, int relocatable, int write_debug_names) { - wabt::MemoryStream stream; + wabt::MemoryStream log_stream; wabt::WriteBinaryOptions options; - options.log_stream = log ? &stream : nullptr; options.canonicalize_lebs = canonicalize_lebs; options.relocatable = relocatable; options.write_debug_names = write_debug_names; - wabt::MemoryWriter writer; + wabt::MemoryStream stream(log ? &log_stream : nullptr); WabtWriteModuleResult* result = new WabtWriteModuleResult(); - result->result = WriteBinaryModule(&writer, module, &options); + result->result = WriteBinaryModule(&stream, module, &options); if (result->result == wabt::Result::Ok) { - result->buffer = writer.ReleaseOutputBuffer(); + result->buffer = stream.ReleaseOutputBuffer(); result->log_buffer = log ? stream.ReleaseOutputBuffer() : nullptr; } return result; @@ -148,16 +145,15 @@ WabtWriteModuleResult* wabt_write_binary_module(wabt::Module* module, WabtWriteModuleResult* wabt_write_text_module(wabt::Module* module, int fold_exprs, int inline_export) { - wabt::MemoryStream stream; wabt::WriteWatOptions options; options.fold_exprs = fold_exprs; options.inline_export = inline_export; - wabt::MemoryWriter writer; + wabt::MemoryStream stream; WabtWriteModuleResult* result = new WabtWriteModuleResult(); - result->result = WriteWat(&writer, module, &options); + result->result = WriteWat(&stream, module, &options); if (result->result == wabt::Result::Ok) { - result->buffer = writer.ReleaseOutputBuffer(); + result->buffer = stream.ReleaseOutputBuffer(); } return result; } diff --git a/src/interpreter.h b/src/interpreter.h index 6db47fc4..8466bb2d 100644 --- a/src/interpreter.h +++ b/src/interpreter.h @@ -26,12 +26,10 @@ #include "src/binding-hash.h" #include "src/common.h" #include "src/opcode.h" -#include "src/writer.h" +#include "src/stream.h" namespace wabt { -class Stream; - namespace interpreter { #define FOREACH_INTERPRETER_RESULT(V) \ diff --git a/src/stream.cc b/src/stream.cc index e976e82a..90d4e913 100644 --- a/src/stream.cc +++ b/src/stream.cc @@ -18,17 +18,19 @@ #include <cassert> #include <cctype> +#include <cerrno> #define DUMP_OCTETS_PER_LINE 16 #define DUMP_OCTETS_PER_GROUP 2 +#define ERROR0(msg) fprintf(stderr, "%s:%d: " msg, __FILE__, __LINE__) +#define ERROR(fmt, ...) \ + fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__) + namespace wabt { -Stream::Stream(Writer* writer, Stream* log_stream) - : writer_(writer), - offset_(0), - result_(Result::Ok), - log_stream_(log_stream) {} +Stream::Stream(Stream* log_stream) + : offset_(0), result_(Result::Ok), log_stream_(log_stream) {} void Stream::AddOffset(ssize_t delta) { offset_ += delta; @@ -44,7 +46,7 @@ void Stream::WriteDataAt(size_t at, if (log_stream_) { log_stream_->WriteMemoryDump(src, size, at, print_chars, nullptr, desc); } - result_ = writer_->WriteData(at, src, size); + result_ = WriteDataImpl(at, src, size); } void Stream::WriteData(const void* src, @@ -63,7 +65,7 @@ void Stream::MoveData(size_t dst_offset, size_t src_offset, size_t size) { "; move data: [%" PRIzx ", %" PRIzx ") -> [%" PRIzx ", %" PRIzx ")\n", src_offset, src_offset + size, dst_offset, dst_offset + size); } - result_ = writer_->MoveData(dst_offset, src_offset, size); + result_ = MoveDataImpl(dst_offset, src_offset, size); } void Stream::Writef(const char* format, ...) { @@ -112,21 +114,143 @@ void Stream::WriteMemoryDump(const void* start, } } -MemoryStream::MemoryStream() : Stream(&writer_) {} +Result OutputBuffer::WriteToFile(string_view filename) const { + std::string filename_str = filename.to_string(); + FILE* file = fopen(filename_str.c_str(), "wb"); + if (!file) { + ERROR("unable to open %s for writing\n", filename_str.c_str()); + return Result::Error; + } + + if (data.empty()) { + fclose(file); + return Result::Ok; + } + + ssize_t bytes = fwrite(data.data(), 1, data.size(), file); + if (bytes < 0 || static_cast<size_t>(bytes) != data.size()) { + ERROR("failed to write %" PRIzd " bytes to %s\n", data.size(), + filename_str.c_str()); + fclose(file); + return Result::Error; + } + + fclose(file); + return Result::Ok; +} + +MemoryStream::MemoryStream(Stream* log_stream) + : Stream(log_stream), buf_(new OutputBuffer()) {} + +MemoryStream::MemoryStream(std::unique_ptr<OutputBuffer>&& buf, + Stream* log_stream) + : Stream(log_stream), buf_(std::move(buf)) {} + +std::unique_ptr<OutputBuffer> MemoryStream::ReleaseOutputBuffer() { + return std::move(buf_); +} + +Result MemoryStream::WriteDataImpl(size_t dst_offset, + const void* src, + size_t size) { + if (size == 0) + return Result::Ok; + size_t end = dst_offset + size; + if (end > buf_->data.size()) { + buf_->data.resize(end); + } + uint8_t* dst = &buf_->data[dst_offset]; + memcpy(dst, src, size); + return Result::Ok; +} + +Result MemoryStream::MoveDataImpl(size_t dst_offset, + size_t src_offset, + size_t size) { + if (size == 0) + return Result::Ok; + size_t src_end = src_offset + size; + size_t dst_end = dst_offset + size; + size_t end = src_end > dst_end ? src_end : dst_end; + if (end > buf_->data.size()) { + buf_->data.resize(end); + } + + uint8_t* dst = &buf_->data[dst_offset]; + uint8_t* src = &buf_->data[src_offset]; + memmove(dst, src, size); + return Result::Ok; +} + +FileStream::FileStream(string_view filename, Stream* log_stream) + : Stream(log_stream), file_(nullptr), offset_(0), should_close_(false) { + std::string filename_str = filename.to_string(); + file_ = fopen(filename_str.c_str(), "wb"); -FileStream::FileStream(string_view filename) - : Stream(&writer_), writer_(filename) {} + // TODO(binji): this is pretty cheesy, should come up with a better API. + if (file_) { + should_close_ = true; + } else { + ERROR("fopen name=\"%s\" failed, errno=%d\n", filename_str.c_str(), errno); + } +} -FileStream::FileStream(FILE* file) : Stream(&writer_), writer_(file) {} +FileStream::FileStream(FILE* file, Stream* log_stream) + : Stream(log_stream), file_(file), offset_(0), should_close_(false) {} -FileStream::FileStream(FileStream&& other) - : Stream(&writer_), writer_(std::move(other.writer_)) {} +FileStream::FileStream(FileStream&& other) { + *this = std::move(other); +} FileStream& FileStream::operator=(FileStream&& other) { - writer_ = std::move(other.writer_); + file_ = other.file_; + offset_ = other.offset_; + should_close_ = other.should_close_; + other.file_ = nullptr; + other.offset_ = 0; + other.should_close_ = false; return *this; } +FileStream::~FileStream() { + // We don't want to close existing files (stdout/sterr, for example). + if (should_close_) { + fclose(file_); + } +} + +Result FileStream::WriteDataImpl(size_t at, const void* data, size_t size) { + if (!file_) + return Result::Error; + if (size == 0) + return Result::Ok; + if (at != offset_) { + if (fseek(file_, at, SEEK_SET) != 0) { + ERROR("fseek offset=%" PRIzd " failed, errno=%d\n", size, errno); + return Result::Error; + } + offset_ = at; + } + if (fwrite(data, size, 1, file_) != 1) { + ERROR("fwrite size=%" PRIzd " failed, errno=%d\n", size, errno); + return Result::Error; + } + offset_ += size; + return Result::Ok; +} + +Result FileStream::MoveDataImpl(size_t dst_offset, + size_t src_offset, + size_t size) { + if (!file_) + return Result::Error; + if (size == 0) + return Result::Ok; + // TODO(binji): implement if needed. + ERROR0("FileWriter::MoveData not implemented!\n"); + return Result::Error; +} + // static std::unique_ptr<FileStream> FileStream::CreateStdout() { return std::unique_ptr<FileStream>(new FileStream(stdout)); diff --git a/src/stream.h b/src/stream.h index 666d830b..5fa3443d 100644 --- a/src/stream.h +++ b/src/stream.h @@ -22,7 +22,6 @@ #include <vector> #include "src/common.h" -#include "src/writer.h" namespace wabt { @@ -35,7 +34,7 @@ enum class PrintChars { class Stream { public: - Stream(Writer* writer, Stream* log_stream = nullptr); + Stream(Stream* log_stream = nullptr); size_t offset() { return offset_; } Result result() { return result_; } @@ -117,55 +116,82 @@ class Stream { WriteU8(static_cast<uint32_t>(value), desc, print_chars); } + protected: + virtual Result WriteDataImpl(size_t offset, + const void* data, + size_t size) = 0; + virtual Result MoveDataImpl(size_t dst_offset, + size_t src_offset, + size_t size) = 0; + private: template <typename T> void Write(const T& data, const char* desc, PrintChars print_chars) { WriteData(&data, sizeof(data), desc, print_chars); } - Writer* writer_; // Not owned. size_t offset_; Result result_; // Not owned. If non-null, log all writes to this stream. Stream* log_stream_; }; +struct OutputBuffer { + Result WriteToFile(string_view filename) const; + + size_t size() const { return data.size(); } + + std::vector<uint8_t> data; +}; + class MemoryStream : public Stream { public: WABT_DISALLOW_COPY_AND_ASSIGN(MemoryStream); - MemoryStream(); + explicit MemoryStream(Stream* log_stream = nullptr); + explicit MemoryStream(std::unique_ptr<OutputBuffer>&&, + Stream* log_stream = nullptr); - MemoryWriter& writer() { return writer_; } - - std::unique_ptr<OutputBuffer> ReleaseOutputBuffer() { - return writer_.ReleaseOutputBuffer(); - } + OutputBuffer& output_buffer() { return *buf_; } + std::unique_ptr<OutputBuffer> ReleaseOutputBuffer(); Result WriteToFile(string_view filename) { - return writer_.output_buffer().WriteToFile(filename); + return buf_->WriteToFile(filename); } + protected: + Result WriteDataImpl(size_t offset, const void* data, size_t size) override; + Result MoveDataImpl(size_t dst_offset, + size_t src_offset, + size_t size) override; + private: - MemoryWriter writer_; + std::unique_ptr<OutputBuffer> buf_; }; class FileStream : public Stream { public: WABT_DISALLOW_COPY_AND_ASSIGN(FileStream); - explicit FileStream(string_view filename); - explicit FileStream(FILE*); + explicit FileStream(string_view filename, Stream* log_stream = nullptr); + explicit FileStream(FILE*, Stream* log_stream = nullptr); FileStream(FileStream&&); FileStream& operator=(FileStream&&); - - FileWriter& writer() { return writer_; } + ~FileStream(); static std::unique_ptr<FileStream> CreateStdout(); static std::unique_ptr<FileStream> CreateStderr(); - bool is_open() const { return writer_.is_open(); } + bool is_open() const { return file_ != nullptr; } + + protected: + Result WriteDataImpl(size_t offset, const void* data, size_t size) override; + Result MoveDataImpl(size_t dst_offset, + size_t src_offset, + size_t size) override; private: - FileWriter writer_; + FILE* file_; + size_t offset_; + bool should_close_; }; } // namespace wabt diff --git a/src/tools/wasm-link.cc b/src/tools/wasm-link.cc index 5d6350c4..d3c7c20f 100644 --- a/src/tools/wasm-link.cc +++ b/src/tools/wasm-link.cc @@ -25,7 +25,6 @@ #include "src/leb128.h" #include "src/option-parser.h" #include "src/stream.h" -#include "src/writer.h" #include "src/binary-reader-linker.h" #define FIRST_KNOWN_SECTION static_cast<size_t>(BinarySection::Type) diff --git a/src/tools/wasm-objdump.cc b/src/tools/wasm-objdump.cc index 578f5c31..64ecef6d 100644 --- a/src/tools/wasm-objdump.cc +++ b/src/tools/wasm-objdump.cc @@ -22,7 +22,6 @@ #include "src/feature.h" #include "src/option-parser.h" #include "src/stream.h" -#include "src/writer.h" #include "src/binary-reader.h" #include "src/binary-reader-objdump.h" diff --git a/src/tools/wasm2wast.cc b/src/tools/wasm2wast.cc index 213324ff..8b2957fa 100644 --- a/src/tools/wasm2wast.cc +++ b/src/tools/wasm2wast.cc @@ -31,7 +31,6 @@ #include "src/validator.h" #include "src/wast-lexer.h" #include "src/wat-writer.h" -#include "src/writer.h" using namespace wabt; @@ -125,9 +124,9 @@ int ProgramMain(int argc, char** argv) { } if (Succeeded(result)) { - FileWriter writer(!s_outfile.empty() ? FileWriter(s_outfile.c_str()) - : FileWriter(stdout)); - result = WriteWat(&writer, &module, &s_write_wat_options); + FileStream stream(!s_outfile.empty() ? FileStream(s_outfile.c_str()) + : FileStream(stdout)); + result = WriteWat(&stream, &module, &s_write_wat_options); } } } diff --git a/src/tools/wast-desugar.cc b/src/tools/wast-desugar.cc index ad989fcc..03bdc4b8 100644 --- a/src/tools/wast-desugar.cc +++ b/src/tools/wast-desugar.cc @@ -32,7 +32,6 @@ #include "src/stream.h" #include "src/wast-parser.h" #include "src/wat-writer.h" -#include "src/writer.h" using namespace wabt; @@ -104,8 +103,8 @@ int ProgramMain(int argc, char** argv) { result = ApplyNames(module); if (Succeeded(result)) { - FileWriter writer(s_outfile ? FileWriter(s_outfile) : FileWriter(stdout)); - result = WriteWat(&writer, module, &s_write_wat_options); + FileStream stream(s_outfile ? FileStream(s_outfile) : FileStream(stdout)); + result = WriteWat(&stream, module, &s_write_wat_options); } } diff --git a/src/tools/wast2wasm.cc b/src/tools/wast2wasm.cc index 3f6d0a1f..bed3437f 100644 --- a/src/tools/wast2wasm.cc +++ b/src/tools/wast2wasm.cc @@ -34,7 +34,6 @@ #include "src/stream.h" #include "src/validator.h" #include "src/wast-parser.h" -#include "src/writer.h" using namespace wabt; @@ -76,7 +75,6 @@ static void ParseOptions(int argc, char* argv[]) { parser.AddOption('v', "verbose", "Use multiple times for more info", []() { s_verbose++; s_log_stream = FileStream::CreateStdout(); - s_write_binary_options.log_stream = s_log_stream.get(); }); parser.AddHelpOption(); parser.AddOption("debug-parser", "Turn on debugging the parser of wast files", @@ -149,21 +147,22 @@ int ProgramMain(int argc, char** argv) { if (Succeeded(result)) { if (s_spec) { WriteBinarySpecOptions write_binary_spec_options; + write_binary_spec_options.log_stream = s_log_stream.get(); write_binary_spec_options.json_filename = s_outfile; write_binary_spec_options.write_binary_options = s_write_binary_options; result = WriteBinarySpecScript(script.get(), s_infile, &write_binary_spec_options); } else { - MemoryWriter writer; + MemoryStream stream(s_log_stream.get()); const Module* module = script->GetFirstModule(); if (module) { - result = WriteBinaryModule(&writer, module, &s_write_binary_options); + result = WriteBinaryModule(&stream, module, &s_write_binary_options); } else { WABT_FATAL("no module found\n"); } if (Succeeded(result)) - WriteBufferToFile(s_outfile, writer.output_buffer()); + WriteBufferToFile(s_outfile, stream.output_buffer()); } } } diff --git a/src/wat-writer.cc b/src/wat-writer.cc index c674645a..47c60d3c 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -31,7 +31,6 @@ #include "src/ir.h" #include "src/literal.h" #include "src/stream.h" -#include "src/writer.h" #define WABT_TRACING 0 #include "src/tracing.h" @@ -91,8 +90,8 @@ struct Label { class WatWriter { public: - WatWriter(Writer* writer, const WriteWatOptions* options) - : options_(options), stream_(writer) {} + WatWriter(Stream* stream, const WriteWatOptions* options) + : options_(options), stream_(stream) {} Result WriteModule(const Module& module); @@ -175,7 +174,7 @@ class WatWriter { const WriteWatOptions* options_ = nullptr; const Module* module_ = nullptr; const Func* current_func_ = nullptr; - Stream stream_; + Stream* stream_; Result result_ = Result::Ok; int indent_ = 0; NextChar next_char_ = NextChar::None; @@ -208,22 +207,22 @@ void WatWriter::WriteIndent() { static size_t s_indent_len = sizeof(s_indent) - 1; size_t to_write = indent_; while (to_write >= s_indent_len) { - stream_.WriteData(s_indent, s_indent_len); + stream_->WriteData(s_indent, s_indent_len); to_write -= s_indent_len; } if (to_write > 0) { - stream_.WriteData(s_indent, to_write); + stream_->WriteData(s_indent, to_write); } } void WatWriter::WriteNextChar() { switch (next_char_) { case NextChar::Space: - stream_.WriteChar(' '); + stream_->WriteChar(' '); break; case NextChar::Newline: case NextChar::ForceNewline: - stream_.WriteChar('\n'); + stream_->WriteChar('\n'); WriteIndent(); break; case NextChar::None: @@ -234,7 +233,7 @@ void WatWriter::WriteNextChar() { void WatWriter::WriteDataWithNextChar(const void* src, size_t size) { WriteNextChar(); - stream_.WriteData(src, size); + stream_->WriteData(src, size); } void WABT_PRINTF_FORMAT(2, 3) WatWriter::Writef(const char* format, ...) { @@ -245,7 +244,7 @@ void WABT_PRINTF_FORMAT(2, 3) WatWriter::Writef(const char* format, ...) { } void WatWriter::WritePutc(char c) { - stream_.WriteChar(c); + stream_->WriteChar(c); } void WatWriter::WritePuts(const char* s, NextChar next_char) { @@ -1231,10 +1230,10 @@ void WatWriter::WriteInlineExport(const Export* export_) { } // end anonymous namespace -Result WriteWat(Writer* writer, +Result WriteWat(Stream* stream, const Module* module, const WriteWatOptions* options) { - WatWriter wat_writer(writer, options); + WatWriter wat_writer(stream, options); return wat_writer.WriteModule(*module); } diff --git a/src/wat-writer.h b/src/wat-writer.h index a8ec8a5c..c99fc3f4 100644 --- a/src/wat-writer.h +++ b/src/wat-writer.h @@ -22,14 +22,14 @@ namespace wabt { struct Module; -class Writer; +class Stream; struct WriteWatOptions { bool fold_exprs = false; // Write folded expressions. bool inline_export = false; }; -Result WriteWat(Writer*, const Module*, const WriteWatOptions*); +Result WriteWat(Stream*, const Module*, const WriteWatOptions*); } // namespace wabt diff --git a/src/writer.cc b/src/writer.cc deleted file mode 100644 index 319ddb7f..00000000 --- a/src/writer.cc +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 "src/writer.h" - -#include <cassert> -#include <cerrno> -#include <cstdio> -#include <cstdlib> -#include <utility> - -#define ERROR0(msg) fprintf(stderr, "%s:%d: " msg, __FILE__, __LINE__) -#define ERROR(fmt, ...) \ - fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__) - -namespace wabt { - -Result OutputBuffer::WriteToFile(string_view filename) const { - std::string filename_str = filename.to_string(); - FILE* file = fopen(filename_str.c_str(), "wb"); - if (!file) { - ERROR("unable to open %s for writing\n", filename_str.c_str()); - return Result::Error; - } - - if (data.empty()) { - fclose(file); - return Result::Ok; - } - - ssize_t bytes = fwrite(data.data(), 1, data.size(), file); - if (bytes < 0 || static_cast<size_t>(bytes) != data.size()) { - ERROR("failed to write %" PRIzd " bytes to %s\n", data.size(), - filename_str.c_str()); - fclose(file); - return Result::Error; - } - - fclose(file); - return Result::Ok; -} - -MemoryWriter::MemoryWriter() : buf_(new OutputBuffer()) {} - -MemoryWriter::MemoryWriter(std::unique_ptr<OutputBuffer> buf) - : buf_(std::move(buf)) {} - -std::unique_ptr<OutputBuffer> MemoryWriter::ReleaseOutputBuffer() { - return std::move(buf_); -} - -Result MemoryWriter::WriteData(size_t dst_offset, - const void* src, - size_t size) { - if (size == 0) - return Result::Ok; - size_t end = dst_offset + size; - if (end > buf_->data.size()) { - buf_->data.resize(end); - } - uint8_t* dst = &buf_->data[dst_offset]; - memcpy(dst, src, size); - return Result::Ok; -} - -Result MemoryWriter::MoveData(size_t dst_offset, - size_t src_offset, - size_t size) { - if (size == 0) - return Result::Ok; - size_t src_end = src_offset + size; - size_t dst_end = dst_offset + size; - size_t end = src_end > dst_end ? src_end : dst_end; - if (end > buf_->data.size()) { - buf_->data.resize(end); - } - - uint8_t* dst = &buf_->data[dst_offset]; - uint8_t* src = &buf_->data[src_offset]; - memmove(dst, src, size); - return Result::Ok; -} - -FileWriter::FileWriter(FILE* file) - : file_(file), offset_(0), should_close_(false) {} - -FileWriter::FileWriter(string_view filename) - : file_(nullptr), offset_(0), should_close_(false) { - std::string filename_str = filename.to_string(); - file_ = fopen(filename_str.c_str(), "wb"); - - // TODO(binji): this is pretty cheesy, should come up with a better API. - if (file_) { - should_close_ = true; - } else { - ERROR("fopen name=\"%s\" failed, errno=%d\n", filename_str.c_str(), errno); - } -} - -FileWriter::FileWriter(FileWriter&& other) { - *this = std::move(other); -} - -FileWriter& FileWriter::operator=(FileWriter&& other) { - file_ = other.file_; - offset_ = other.offset_; - should_close_ = other.should_close_; - other.file_ = nullptr; - other.offset_ = 0; - other.should_close_ = false; - return *this; -} - -FileWriter::~FileWriter() { - // We don't want to close existing files (stdout/sterr, for example). - if (should_close_) { - fclose(file_); - } -} - -Result FileWriter::WriteData(size_t at, const void* data, size_t size) { - if (!file_) - return Result::Error; - if (size == 0) - return Result::Ok; - if (at != offset_) { - if (fseek(file_, at, SEEK_SET) != 0) { - ERROR("fseek offset=%" PRIzd " failed, errno=%d\n", size, errno); - return Result::Error; - } - offset_ = at; - } - if (fwrite(data, size, 1, file_) != 1) { - ERROR("fwrite size=%" PRIzd " failed, errno=%d\n", size, errno); - return Result::Error; - } - offset_ += size; - return Result::Ok; -} - -Result FileWriter::MoveData(size_t dst_offset, size_t src_offset, size_t size) { - if (!file_) - return Result::Error; - if (size == 0) - return Result::Ok; - // TODO(binji): implement if needed. - ERROR0("FileWriter::MoveData not implemented!\n"); - return Result::Error; -} - -} // namespace wabt diff --git a/src/writer.h b/src/writer.h deleted file mode 100644 index 2d199ee4..00000000 --- a/src/writer.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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. - */ - -#ifndef WABT_WRITER_H_ -#define WABT_WRITER_H_ - -#include <stdio.h> - -#include "src/common.h" - -#include <memory> -#include <vector> - -namespace wabt { - -struct OutputBuffer { - Result WriteToFile(string_view filename) const; - - size_t size() const { return data.size(); } - - std::vector<uint8_t> data; -}; - -class Writer { - public: - virtual ~Writer() {} - virtual Result WriteData(size_t offset, const void* data, size_t size) = 0; - virtual Result MoveData(size_t dst_offset, - size_t src_offset, - size_t size) = 0; -}; - -class MemoryWriter : public Writer { - public: - MemoryWriter(); - explicit MemoryWriter(std::unique_ptr<OutputBuffer>); - - OutputBuffer& output_buffer() { return *buf_; } - std::unique_ptr<OutputBuffer> ReleaseOutputBuffer(); - - virtual Result WriteData(size_t offset, const void* data, size_t size); - virtual Result MoveData(size_t dst_offset, size_t src_offset, size_t size); - - private: - std::unique_ptr<OutputBuffer> buf_; -}; - -class FileWriter : public Writer { - WABT_DISALLOW_COPY_AND_ASSIGN(FileWriter); - - public: - explicit FileWriter(string_view filename); - explicit FileWriter(FILE* file); - FileWriter(FileWriter&&); - FileWriter& operator=(FileWriter&&); - ~FileWriter(); - - bool is_open() const { return file_ != nullptr; } - - virtual Result WriteData(size_t offset, const void* data, size_t size); - virtual Result MoveData(size_t dst_offset, size_t src_offset, size_t size); - - private: - FILE* file_; - size_t offset_; - bool should_close_; -}; - -} // namespace wabt - -#endif /* WABT_WRITER_H_ */ |