summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast-writer.cc17
-rw-r--r--src/ast-writer.h4
-rw-r--r--src/binary-reader-interpreter.cc34
-rw-r--r--src/binary-reader-linker.h4
-rw-r--r--src/binary-reader-logging.cc8
-rw-r--r--src/binary-reader-logging.h2
-rw-r--r--src/binary-reader-objdump.cc12
-rw-r--r--src/binary-reader.h4
-rw-r--r--src/binary-writer-spec.cc100
-rw-r--r--src/binary-writer-spec.h2
-rw-r--r--src/binary-writer.cc121
-rw-r--r--src/binary-writer.h35
-rw-r--r--src/interpreter.cc296
-rw-r--r--src/interpreter.h10
-rw-r--r--src/stream.cc164
-rw-r--r--src/stream.h178
-rw-r--r--src/tools/wasm-interp.cc23
-rw-r--r--src/tools/wasm-link.cc136
-rw-r--r--src/tools/wasm2wast.cc24
-rw-r--r--src/tools/wasmdump.cc9
-rw-r--r--src/tools/wasmopcodecnt.cc8
-rw-r--r--src/tools/wast-desugar.cc13
-rw-r--r--src/tools/wast2wasm.cc27
-rw-r--r--src/writer.cc209
-rw-r--r--src/writer.h85
25 files changed, 715 insertions, 810 deletions
diff --git a/src/ast-writer.cc b/src/ast-writer.cc
index a688d004..d7ec12e4 100644
--- a/src/ast-writer.cc
+++ b/src/ast-writer.cc
@@ -59,7 +59,7 @@ enum class NextChar {
};
struct Context {
- Context() { WABT_ZERO_MEMORY(stream); }
+ explicit Context(Writer* writer) : stream(writer) {}
Stream stream;
Result result = Result::Ok;
@@ -94,22 +94,22 @@ static void write_indent(Context* ctx) {
static size_t s_indent_len = sizeof(s_indent) - 1;
size_t indent = ctx->indent;
while (indent > s_indent_len) {
- write_data(&ctx->stream, s_indent, s_indent_len, nullptr);
+ ctx->stream.WriteData(s_indent, s_indent_len);
indent -= s_indent_len;
}
if (indent > 0) {
- write_data(&ctx->stream, s_indent, indent, nullptr);
+ ctx->stream.WriteData(s_indent, indent);
}
}
static void write_next_char(Context* ctx) {
switch (ctx->next_char) {
case NextChar::Space:
- write_data(&ctx->stream, " ", 1, nullptr);
+ ctx->stream.WriteChar(' ');
break;
case NextChar::Newline:
case NextChar::ForceNewline:
- write_data(&ctx->stream, "\n", 1, nullptr);
+ ctx->stream.WriteChar('\n');
write_indent(ctx);
break;
@@ -124,7 +124,7 @@ static void write_data_with_next_char(Context* ctx,
const void* src,
size_t size) {
write_next_char(ctx);
- write_data(&ctx->stream, src, size, nullptr);
+ ctx->stream.WriteData(src, size);
}
static void WABT_PRINTF_FORMAT(2, 3)
@@ -136,7 +136,7 @@ static void WABT_PRINTF_FORMAT(2, 3)
}
static void write_putc(Context* ctx, char c) {
- write_data(&ctx->stream, &c, 1, nullptr);
+ ctx->stream.WriteChar(c);
}
static void write_puts(Context* ctx, const char* s, NextChar next_char) {
@@ -745,8 +745,7 @@ static void write_module(Context* ctx, const Module* module) {
}
Result write_ast(Writer* writer, const Module* module) {
- Context ctx;
- init_stream(&ctx.stream, writer, nullptr);
+ Context ctx(writer);
write_module(&ctx, module);
return ctx.result;
}
diff --git a/src/ast-writer.h b/src/ast-writer.h
index 950e640e..79bf2c76 100644
--- a/src/ast-writer.h
+++ b/src/ast-writer.h
@@ -22,9 +22,9 @@
namespace wabt {
struct Module;
-struct Writer;
+class Writer;
-Result write_ast(struct Writer*, const struct Module*);
+Result write_ast(Writer*, const Module*);
} // namespace wabt
diff --git a/src/binary-reader-interpreter.cc b/src/binary-reader-interpreter.cc
index b22a4472..db5f9719 100644
--- a/src/binary-reader-interpreter.cc
+++ b/src/binary-reader-interpreter.cc
@@ -75,8 +75,7 @@ class BinaryReaderInterpreter : public BinaryReaderNop {
size_t istream_offset,
BinaryErrorHandler* error_handler);
- Result Init();
- void StealOutputBuffer(OutputBuffer*);
+ std::unique_ptr<OutputBuffer> ReleaseOutputBuffer();
size_t get_istream_offset() { return istream_offset; }
// Implement BinaryReader.
@@ -301,20 +300,15 @@ BinaryReaderInterpreter::BinaryReaderInterpreter(
: error_handler(error_handler),
env(env),
module(module),
+ istream_writer(std::move(env->istream)),
istream_offset(istream_offset) {
- WABT_ZERO_MEMORY(istream_writer);
-
tc_error_handler.on_error = OnTypecheckerError;
tc_error_handler.user_data = this;
typechecker.error_handler = &tc_error_handler;
}
-Result BinaryReaderInterpreter::Init() {
- return init_mem_writer_existing(&istream_writer, &env->istream);
-}
-
-void BinaryReaderInterpreter::StealOutputBuffer(OutputBuffer* output_buffer) {
- steal_mem_writer_output_buffer(&istream_writer, output_buffer);
+std::unique_ptr<OutputBuffer> BinaryReaderInterpreter::ReleaseOutputBuffer() {
+ return istream_writer.ReleaseOutputBuffer();
}
Label* BinaryReaderInterpreter::GetLabel(uint32_t depth) {
@@ -415,8 +409,7 @@ uint32_t BinaryReaderInterpreter::GetIstreamOffset() {
Result BinaryReaderInterpreter::EmitDataAt(size_t offset,
const void* data,
size_t size) {
- return istream_writer.base.write_data(offset, data, size,
- istream_writer.base.user_data);
+ return istream_writer.WriteData(offset, data, size);
}
Result BinaryReaderInterpreter::EmitData(const void* data, size_t size) {
@@ -1492,24 +1485,21 @@ Result read_binary_interpreter(InterpreterEnvironment* env,
const ReadBinaryOptions* options,
BinaryErrorHandler* error_handler,
DefinedInterpreterModule** out_module) {
- size_t istream_offset = env->istream.size;
+ size_t istream_offset = env->istream->data.size();
DefinedInterpreterModule* module =
new DefinedInterpreterModule(istream_offset);
- BinaryReaderInterpreter reader(env, module, istream_offset, error_handler);
- if (WABT_FAILED(reader.Init())) {
- delete module;
- return Result::Error;
- }
-
+ // Need to mark before constructing the reader since it takes ownership of
+ // env->istream, which makes env->istream == nullptr.
InterpreterEnvironmentMark mark = mark_interpreter_environment(env);
+ BinaryReaderInterpreter reader(env, module, istream_offset, error_handler);
env->modules.emplace_back(module);
Result result = read_binary(data, size, &reader, options);
- reader.StealOutputBuffer(&env->istream);
+ env->istream = reader.ReleaseOutputBuffer();
if (WABT_SUCCEEDED(result)) {
- env->istream.size = reader.get_istream_offset();
- module->istream_end = env->istream.size;
+ env->istream->data.resize(reader.get_istream_offset());
+ module->istream_end = env->istream->data.size();
*out_module = module;
} else {
reset_interpreter_environment_to_mark(env, mark);
diff --git a/src/binary-reader-linker.h b/src/binary-reader-linker.h
index 5a543bb3..0ffb7e42 100644
--- a/src/binary-reader-linker.h
+++ b/src/binary-reader-linker.h
@@ -22,14 +22,14 @@
namespace wabt {
-struct Stream;
+class Stream;
namespace link {
struct LinkerInputBinary;
struct LinkOptions {
- struct Stream* log_stream;
+ Stream* log_stream;
};
Result read_binary_linker(struct LinkerInputBinary* input_info,
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc
index 6657a3e5..093c9c07 100644
--- a/src/binary-reader-logging.cc
+++ b/src/binary-reader-logging.cc
@@ -24,7 +24,7 @@ namespace wabt {
#define INDENT_SIZE 2
-#define LOGF_NOINDENT(...) writef(stream, __VA_ARGS__)
+#define LOGF_NOINDENT(...) stream->Writef(__VA_ARGS__)
#define LOGF(...) \
do { \
@@ -64,14 +64,14 @@ void BinaryReaderLogging::WriteIndent() {
static char s_indent[] =
" "
" ";
- static size_t s_indent_len = sizeof(s_indent) - 1;
+ static const size_t s_indent_len = sizeof(s_indent) - 1;
size_t i = indent;
while (i > s_indent_len) {
- write_data(stream, s_indent, s_indent_len, nullptr);
+ stream->WriteData(s_indent, s_indent_len);
i -= s_indent_len;
}
if (i > 0) {
- write_data(stream, s_indent, indent, nullptr);
+ stream->WriteData(s_indent, indent);
}
}
diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h
index 021420cb..374095f8 100644
--- a/src/binary-reader-logging.h
+++ b/src/binary-reader-logging.h
@@ -21,7 +21,7 @@
namespace wabt {
-struct Stream;
+class Stream;
class BinaryReaderLogging : public BinaryReader {
public:
diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc
index b086c55b..a57ec1bb 100644
--- a/src/binary-reader-objdump.cc
+++ b/src/binary-reader-objdump.cc
@@ -485,14 +485,14 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
void PrintDetails(const char* fmt, ...);
Result OnCount(uint32_t count);
- Stream* out_stream;
+ std::unique_ptr<FileStream> out_stream;
};
BinaryReaderObjdump::BinaryReaderObjdump(const uint8_t* data,
size_t size,
ObjdumpOptions* options)
: BinaryReaderObjdumpBase(data, size, options),
- out_stream(init_stdout_stream()) {}
+ out_stream(FileStream::CreateStdout()) {}
Result BinaryReaderObjdump::BeginCustomSection(uint32_t size,
StringSlice section_name) {
@@ -533,8 +533,8 @@ Result BinaryReaderObjdump::BeginSection(BinarySection section_code,
case ObjdumpMode::RawData:
if (section_match) {
printf("\nContents of section %s:\n", name);
- write_memory_dump(out_stream, data + state->offset, size, state->offset,
- PrintChars::Yes, nullptr, nullptr);
+ out_stream->WriteMemoryDump(data + state->offset, size, state->offset,
+ nullptr, nullptr, PrintChars::Yes);
}
break;
case ObjdumpMode::Prepass:
@@ -807,8 +807,8 @@ Result BinaryReaderObjdump::OnDataSegmentData(uint32_t index,
const void* src_data,
uint32_t size) {
if (ShouldPrintDetails()) {
- write_memory_dump(out_stream, src_data, size, 0, PrintChars::Yes, " - ",
- nullptr);
+ out_stream->WriteMemoryDump(src_data, size, 0, " - ", nullptr,
+ PrintChars::Yes);
}
return Result::Ok;
}
diff --git a/src/binary-reader.h b/src/binary-reader.h
index 55ac8dd2..1c2f2780 100644
--- a/src/binary-reader.h
+++ b/src/binary-reader.h
@@ -28,8 +28,10 @@
namespace wabt {
+class Stream;
+
struct ReadBinaryOptions {
- struct Stream* log_stream;
+ Stream* log_stream;
bool read_debug_names;
};
diff --git a/src/binary-writer-spec.cc b/src/binary-writer-spec.cc
index d87fe820..ed726475 100644
--- a/src/binary-writer-spec.cc
+++ b/src/binary-writer-spec.cc
@@ -31,8 +31,7 @@ namespace wabt {
namespace {
struct Context {
- MemoryWriter json_writer;
- Stream json_stream;
+ MemoryStream json_stream;
StringSlice source_filename;
StringSlice module_filename_noext;
bool write_modules; /* Whether to write the modules files. */
@@ -111,28 +110,28 @@ static char* get_module_filename(Context* ctx) {
}
static void write_string(Context* ctx, const char* s) {
- writef(&ctx->json_stream, "\"%s\"", s);
+ ctx->json_stream.Writef("\"%s\"", s);
}
static void write_key(Context* ctx, const char* key) {
- writef(&ctx->json_stream, "\"%s\": ", key);
+ ctx->json_stream.Writef("\"%s\": ", key);
}
static void write_separator(Context* ctx) {
- writef(&ctx->json_stream, ", ");
+ ctx->json_stream.Writef(", ");
}
static void write_escaped_string_slice(Context* ctx, StringSlice ss) {
- write_char(&ctx->json_stream, '"');
+ ctx->json_stream.WriteChar('"');
for (size_t i = 0; i < ss.length; ++i) {
uint8_t c = ss.start[i];
if (c < 0x20 || c == '\\' || c == '"') {
- writef(&ctx->json_stream, "\\u%04x", c);
+ ctx->json_stream.Writef("\\u%04x", c);
} else {
- write_char(&ctx->json_stream, c);
+ ctx->json_stream.WriteChar(c);
}
}
- write_char(&ctx->json_stream, '"');
+ ctx->json_stream.WriteChar('"');
}
static void write_command_type(Context* ctx, const Command& command) {
@@ -161,25 +160,25 @@ static void write_command_type(Context* ctx, const Command& command) {
static void write_location(Context* ctx, const Location* loc) {
write_key(ctx, "line");
- writef(&ctx->json_stream, "%d", loc->line);
+ ctx->json_stream.Writef("%d", loc->line);
}
static void write_var(Context* ctx, const Var* var) {
if (var->type == VarType::Index)
- writef(&ctx->json_stream, "\"%" PRIu64 "\"", var->index);
+ ctx->json_stream.Writef("\"%" PRIu64 "\"", var->index);
else
write_escaped_string_slice(ctx, var->name);
}
static void write_type_object(Context* ctx, Type type) {
- writef(&ctx->json_stream, "{");
+ ctx->json_stream.Writef("{");
write_key(ctx, "type");
write_string(ctx, get_type_name(type));
- writef(&ctx->json_stream, "}");
+ ctx->json_stream.Writef("}");
}
static void write_const(Context* ctx, const Const* const_) {
- writef(&ctx->json_stream, "{");
+ ctx->json_stream.Writef("{");
write_key(ctx, "type");
/* Always write the values as strings, even though they may be representable
@@ -189,14 +188,14 @@ static void write_const(Context* ctx, const Const* const_) {
write_string(ctx, "i32");
write_separator(ctx);
write_key(ctx, "value");
- writef(&ctx->json_stream, "\"%u\"", const_->u32);
+ ctx->json_stream.Writef("\"%u\"", const_->u32);
break;
case Type::I64:
write_string(ctx, "i64");
write_separator(ctx);
write_key(ctx, "value");
- writef(&ctx->json_stream, "\"%" PRIu64 "\"", const_->u64);
+ ctx->json_stream.Writef("\"%" PRIu64 "\"", const_->u64);
break;
case Type::F32: {
@@ -204,7 +203,7 @@ static void write_const(Context* ctx, const Const* const_) {
write_string(ctx, "f32");
write_separator(ctx);
write_key(ctx, "value");
- writef(&ctx->json_stream, "\"%u\"", const_->f32_bits);
+ ctx->json_stream.Writef("\"%u\"", const_->f32_bits);
break;
}
@@ -213,7 +212,7 @@ static void write_const(Context* ctx, const Const* const_) {
write_string(ctx, "f64");
write_separator(ctx);
write_key(ctx, "value");
- writef(&ctx->json_stream, "\"%" PRIu64 "\"", const_->f64_bits);
+ ctx->json_stream.Writef("\"%" PRIu64 "\"", const_->f64_bits);
break;
}
@@ -221,23 +220,23 @@ static void write_const(Context* ctx, const Const* const_) {
assert(0);
}
- writef(&ctx->json_stream, "}");
+ ctx->json_stream.Writef("}");
}
static void write_const_vector(Context* ctx, const ConstVector& consts) {
- writef(&ctx->json_stream, "[");
+ ctx->json_stream.Writef("[");
for (size_t i = 0; i < consts.size(); ++i) {
const Const* const_ = &consts[i];
write_const(ctx, const_);
if (i != consts.size() - 1)
write_separator(ctx);
}
- writef(&ctx->json_stream, "]");
+ ctx->json_stream.Writef("]");
}
static void write_action(Context* ctx, const Action* action) {
write_key(ctx, "action");
- writef(&ctx->json_stream, "{");
+ ctx->json_stream.Writef("{");
write_key(ctx, "type");
if (action->type == ActionType::Invoke) {
write_string(ctx, "invoke");
@@ -261,7 +260,7 @@ static void write_action(Context* ctx, const Action* action) {
write_key(ctx, "field");
write_escaped_string_slice(ctx, action->name);
}
- writef(&ctx->json_stream, "}");
+ ctx->json_stream.Writef("}");
}
static void write_action_result_type(Context* ctx,
@@ -269,7 +268,7 @@ static void write_action_result_type(Context* ctx,
const Action* action) {
const Module* module = get_module_by_var(script, &action->module_var);
const Export* export_;
- writef(&ctx->json_stream, "[");
+ ctx->json_stream.Writef("[");
switch (action->type) {
case ActionType::Invoke: {
export_ = get_export_by_name(module, &action->name);
@@ -289,19 +288,15 @@ static void write_action_result_type(Context* ctx,
break;
}
}
- writef(&ctx->json_stream, "]");
+ ctx->json_stream.Writef("]");
}
static void write_module(Context* ctx, char* filename, const Module* module) {
MemoryWriter writer;
- Result result = init_mem_writer(&writer);
- if (WABT_SUCCEEDED(result)) {
- WriteBinaryOptions options = ctx->spec_options->write_binary_options;
- result = write_binary_module(&writer.base, module, &options);
- if (WABT_SUCCEEDED(result) && ctx->write_modules)
- result = write_output_buffer_to_file(&writer.buf, filename);
- close_mem_writer(&writer);
- }
+ WriteBinaryOptions options = ctx->spec_options->write_binary_options;
+ Result result = write_binary_module(&writer, module, &options);
+ if (WABT_SUCCEEDED(result) && ctx->write_modules)
+ result = writer.output_buffer().WriteToFile(filename);
ctx->result = result;
}
@@ -312,15 +307,13 @@ static void write_raw_module(Context* ctx,
if (raw_module->type == RawModuleType::Text) {
write_module(ctx, filename, raw_module->text);
} else if (ctx->write_modules) {
- FileStream stream;
- Result result = init_file_writer(&stream.writer, filename);
- if (WABT_SUCCEEDED(result)) {
- init_stream(&stream.base, &stream.writer.base, nullptr);
- write_data(&stream.base, raw_module->binary.data, raw_module->binary.size,
- "");
- close_file_writer(&stream.writer);
+ FileStream stream(filename);
+ if (stream.is_open()) {
+ stream.WriteData(raw_module->binary.data, raw_module->binary.size);
+ ctx->result = stream.result();
+ } else {
+ ctx->result = Result::Error;
}
- ctx->result = result;
}
}
@@ -340,9 +333,9 @@ static void write_invalid_module(Context* ctx,
}
static void write_commands(Context* ctx, Script* script) {
- writef(&ctx->json_stream, "{\"source_filename\": ");
+ ctx->json_stream.Writef("{\"source_filename\": ");
write_escaped_string_slice(ctx, ctx->source_filename);
- writef(&ctx->json_stream, ",\n \"commands\": [\n");
+ ctx->json_stream.Writef(",\n \"commands\": [\n");
int last_module_index = -1;
for (size_t i = 0; i < script->commands.size(); ++i) {
const Command& command = *script->commands[i].get();
@@ -352,9 +345,9 @@ static void write_commands(Context* ctx, Script* script) {
if (i != 0)
write_separator(ctx);
- writef(&ctx->json_stream, "\n");
+ ctx->json_stream.Writef("\n");
- writef(&ctx->json_stream, " {");
+ ctx->json_stream.Writef(" {");
write_command_type(ctx, command);
write_separator(ctx);
@@ -474,9 +467,9 @@ static void write_commands(Context* ctx, Script* script) {
break;
}
- writef(&ctx->json_stream, "}");
+ ctx->json_stream.Writef("}");
}
- writef(&ctx->json_stream, "]}\n");
+ ctx->json_stream.Writef("]}\n");
}
Result write_binary_spec_script(Script* script,
@@ -484,7 +477,6 @@ Result write_binary_spec_script(Script* script,
const WriteBinarySpecOptions* spec_options) {
assert(source_filename);
Context ctx;
- WABT_ZERO_MEMORY(ctx);
ctx.spec_options = spec_options;
ctx.result = Result::Ok;
ctx.source_filename.start = source_filename;
@@ -494,15 +486,9 @@ Result write_binary_spec_script(Script* script,
: source_filename);
ctx.write_modules = !!ctx.spec_options->json_filename;
- Result result = init_mem_writer(&ctx.json_writer);
- if (WABT_SUCCEEDED(result)) {
- init_stream(&ctx.json_stream, &ctx.json_writer.base, nullptr);
- write_commands(&ctx, script);
- if (ctx.spec_options->json_filename) {
- write_output_buffer_to_file(&ctx.json_writer.buf,
- ctx.spec_options->json_filename);
- }
- close_mem_writer(&ctx.json_writer);
+ write_commands(&ctx, script);
+ if (ctx.spec_options->json_filename) {
+ ctx.json_stream.WriteToFile(ctx.spec_options->json_filename);
}
return ctx.result;
diff --git a/src/binary-writer-spec.h b/src/binary-writer-spec.h
index 974af5fd..9cc6b2ea 100644
--- a/src/binary-writer-spec.h
+++ b/src/binary-writer-spec.h
@@ -23,8 +23,6 @@
namespace wabt {
-struct Writer;
-
#define WABT_WRITE_BINARY_SPEC_OPTIONS_DEFAULT \
{ nullptr, WABT_WRITE_BINARY_OPTIONS_DEFAULT }
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index 8c7d9be4..8e4b383f 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -59,10 +59,9 @@ RelocSection::RelocSection(const char* name, BinarySection code)
struct Context {
WABT_DISALLOW_COPY_AND_ASSIGN(Context);
- Context();
+ Context(Writer* writer, const WriteBinaryOptions* options);
Stream stream;
- Stream* log_stream = nullptr;
const WriteBinaryOptions* options = nullptr;
std::vector<RelocSection> reloc_sections;
@@ -78,9 +77,8 @@ struct Context {
size_t last_subsection_payload_offset = 0;
};
-Context::Context() {
- WABT_ZERO_MEMORY(stream);
-}
+Context::Context(Writer* writer, const WriteBinaryOptions* options)
+ : stream(writer, options->log_stream), options(options) {}
} // namespace
@@ -94,11 +92,11 @@ static uint8_t log2_u32(uint32_t x) {
}
static void write_header(Context* ctx, const char* name, int index) {
- if (ctx->log_stream) {
+ if (ctx->stream.has_log_stream()) {
if (index == PRINT_HEADER_NO_INDEX) {
- writef(ctx->log_stream, "; %s\n", name);
+ ctx->stream.log_stream().Writef("; %s\n", name);
} else {
- writef(ctx->log_stream, "; %s %d\n", name, index);
+ ctx->stream.log_stream().Writef("; %s %d\n", name, index);
}
}
}
@@ -131,7 +129,7 @@ uint32_t write_u32_leb128_at(Stream* stream,
uint32_t i = 0;
LEB128_LOOP_UNTIL(value == 0);
uint32_t length = i;
- write_data_at(stream, offset, data, length, PrintChars::No, desc);
+ stream->WriteDataAt(offset, data, length, desc, PrintChars::No);
return length;
}
@@ -155,19 +153,19 @@ uint32_t write_fixed_u32_leb128_at(Stream* stream,
uint8_t data[MAX_U32_LEB128_BYTES];
uint32_t length =
write_fixed_u32_leb128_raw(data, data + MAX_U32_LEB128_BYTES, value);
- write_data_at(stream, offset, data, length, PrintChars::No, desc);
+ stream->WriteDataAt(offset, data, length, desc, PrintChars::No);
return length;
}
void write_u32_leb128(Stream* stream, uint32_t value, const char* desc) {
- uint32_t length = write_u32_leb128_at(stream, stream->offset, value, desc);
- stream->offset += length;
+ uint32_t length = write_u32_leb128_at(stream, stream->offset(), value, desc);
+ stream->AddOffset(length);
}
void write_fixed_u32_leb128(Stream* stream, uint32_t value, const char* desc) {
uint32_t length =
- write_fixed_u32_leb128_at(stream, stream->offset, value, desc);
- stream->offset += length;
+ write_fixed_u32_leb128_at(stream, stream->offset(), value, desc);
+ stream->AddOffset(length);
}
void write_i32_leb128(Stream* stream, int32_t value, const char* desc) {
@@ -179,8 +177,7 @@ void write_i32_leb128(Stream* stream, int32_t value, const char* desc) {
LEB128_LOOP_UNTIL(value == 0 && !(byte & 0x40));
uint32_t length = i;
- write_data_at(stream, stream->offset, data, length, PrintChars::No, desc);
- stream->offset += length;
+ stream->WriteData(data, length, desc);
}
static void write_i64_leb128(Stream* stream, int64_t value, const char* desc) {
@@ -192,8 +189,7 @@ static void write_i64_leb128(Stream* stream, int64_t value, const char* desc) {
LEB128_LOOP_UNTIL(value == 0 && !(byte & 0x40));
int length = i;
- write_data_at(stream, stream->offset, data, length, PrintChars::No, desc);
- stream->offset += length;
+ stream->WriteData(data, length, desc);
}
#undef LEB128_LOOP_UNTIL
@@ -213,10 +209,10 @@ static uint32_t write_u32_leb128_space(Context* ctx,
const char* desc) {
assert(leb_size_guess <= MAX_U32_LEB128_BYTES);
uint8_t data[MAX_U32_LEB128_BYTES] = {0};
- uint32_t result = ctx->stream.offset;
+ uint32_t result = ctx->stream.offset();
uint32_t bytes_to_write =
ctx->options->canonicalize_lebs ? leb_size_guess : MAX_U32_LEB128_BYTES;
- write_data(&ctx->stream, data, bytes_to_write, desc);
+ ctx->stream.WriteData(data, bytes_to_write, desc);
return result;
}
@@ -225,17 +221,17 @@ static void write_fixup_u32_leb128_size(Context* ctx,
uint32_t leb_size_guess,
const char* desc) {
if (ctx->options->canonicalize_lebs) {
- uint32_t size = ctx->stream.offset - offset - leb_size_guess;
+ uint32_t size = ctx->stream.offset() - offset - leb_size_guess;
uint32_t leb_size = size_u32_leb128(size);
if (leb_size != leb_size_guess) {
uint32_t src_offset = offset + leb_size_guess;
uint32_t dst_offset = offset + leb_size;
- move_data(&ctx->stream, dst_offset, src_offset, size);
+ ctx->stream.MoveData(dst_offset, src_offset, size);
}
write_u32_leb128_at(&ctx->stream, offset, size, desc);
- ctx->stream.offset += leb_size - leb_size_guess;
+ ctx->stream.AddOffset(leb_size - leb_size_guess);
} else {
- uint32_t size = ctx->stream.offset - offset - MAX_U32_LEB128_BYTES;
+ uint32_t size = ctx->stream.offset() - offset - MAX_U32_LEB128_BYTES;
write_fixed_u32_leb128_at(&ctx->stream, offset, size, desc);
}
}
@@ -243,15 +239,14 @@ static void write_fixup_u32_leb128_size(Context* ctx,
void write_str(Stream* stream,
const char* s,
size_t length,
- PrintChars print_chars,
- const char* desc) {
+ const char* desc,
+ PrintChars print_chars) {
write_u32_leb128(stream, length, "string length");
- write_data_at(stream, stream->offset, s, length, print_chars, desc);
- stream->offset += length;
+ stream->WriteData(s, length, desc, print_chars);
}
void write_opcode(Stream* stream, Opcode opcode) {
- write_u8_enum(stream, opcode, get_opcode_name(opcode));
+ stream->WriteU8Enum(opcode, get_opcode_name(opcode));
}
void write_type(Stream* stream, Type type) {
@@ -266,7 +261,7 @@ static void write_inline_signature_type(Stream* stream,
write_type(stream, sig[0]);
} else {
/* this is currently unrepresentable */
- write_u8(stream, 0xff, "INVALID INLINE SIGNATURE");
+ stream->WriteU8(0xff, "INVALID INLINE SIGNATURE");
}
}
@@ -278,12 +273,12 @@ static void begin_known_section(Context* ctx,
wabt_snprintf(desc, sizeof(desc), "section \"%s\" (%u)",
get_section_name(section_code), static_cast<unsigned>(section_code));
write_header(ctx, desc, PRINT_HEADER_NO_INDEX);
- write_u8_enum(&ctx->stream, section_code, "section code");
+ ctx->stream.WriteU8Enum(section_code, "section code");
ctx->last_section_type = section_code;
ctx->last_section_leb_size_guess = leb_size_guess;
ctx->last_section_offset =
write_u32_leb128_space(ctx, leb_size_guess, "section size (guess)");
- ctx->last_section_payload_offset = ctx->stream.offset;
+ ctx->last_section_payload_offset = ctx->stream.offset();
}
static void begin_custom_section(Context* ctx,
@@ -293,14 +288,14 @@ static void begin_custom_section(Context* ctx,
char desc[100];
wabt_snprintf(desc, sizeof(desc), "section \"%s\"", name);
write_header(ctx, desc, PRINT_HEADER_NO_INDEX);
- write_u8_enum(&ctx->stream, BinarySection::Custom, "custom section code");
+ ctx->stream.WriteU8Enum(BinarySection::Custom, "custom section code");
ctx->last_section_type = BinarySection::Custom;
ctx->last_section_leb_size_guess = leb_size_guess;
ctx->last_section_offset =
write_u32_leb128_space(ctx, leb_size_guess, "section size (guess)");
- ctx->last_section_payload_offset = ctx->stream.offset;
- write_str(&ctx->stream, name, strlen(name), PrintChars::Yes,
- "custom section name");
+ ctx->last_section_payload_offset = ctx->stream.offset();
+ write_str(&ctx->stream, name, strlen(name), "custom section name",
+ PrintChars::Yes);
}
static void end_section(Context* ctx) {
@@ -318,7 +313,7 @@ static void begin_subsection(Context* ctx,
ctx->last_subsection_leb_size_guess = leb_size_guess;
ctx->last_subsection_offset =
write_u32_leb128_space(ctx, leb_size_guess, "subsection size (guess)");
- ctx->last_subsection_payload_offset = ctx->stream.offset;
+ ctx->last_subsection_payload_offset = ctx->stream.offset();
}
static void end_subsection(Context* ctx) {
@@ -349,7 +344,7 @@ static void add_reloc(Context* ctx, RelocType reloc_type, uint32_t index) {
}
// Add a new relocation to the curent reloc section
- size_t offset = ctx->stream.offset - ctx->last_section_payload_offset;
+ size_t offset = ctx->stream.offset() - ctx->last_section_payload_offset;
ctx->current_reloc_section->relocations.emplace_back(reloc_type, offset,
index);
}
@@ -433,11 +428,11 @@ static void write_expr(Context* ctx,
break;
case Type::F32:
write_opcode(&ctx->stream, Opcode::F32Const);
- write_u32(&ctx->stream, expr->const_.f32_bits, "f32 literal");
+ ctx->stream.WriteU32(expr->const_.f32_bits, "f32 literal");
break;
case Type::F64:
write_opcode(&ctx->stream, Opcode::F64Const);
- write_u64(&ctx->stream, expr->const_.f64_bits, "f64 literal");
+ ctx->stream.WriteU64(expr->const_.f64_bits, "f64 literal");
break;
default:
assert(0);
@@ -484,7 +479,7 @@ static void write_expr(Context* ctx,
write_opcode(&ctx->stream, expr->load.opcode);
uint32_t align =
get_opcode_alignment(expr->load.opcode, expr->load.align);
- write_u8(&ctx->stream, log2_u32(align), "alignment");
+ ctx->stream.WriteU8(log2_u32(align), "alignment");
write_u32_leb128(&ctx->stream, expr->load.offset, "load offset");
break;
}
@@ -520,7 +515,7 @@ static void write_expr(Context* ctx,
write_opcode(&ctx->stream, expr->store.opcode);
uint32_t align =
get_opcode_alignment(expr->store.opcode, expr->store.align);
- write_u8(&ctx->stream, log2_u32(align), "alignment");
+ ctx->stream.WriteU8(log2_u32(align), "alignment");
write_u32_leb128(&ctx->stream, expr->store.offset, "store offset");
break;
}
@@ -624,7 +619,7 @@ static void write_memory(Context* ctx, const Memory* memory) {
static void write_global_header(Context* ctx, const Global* global) {
write_type(&ctx->stream, global->type);
- write_u8(&ctx->stream, global->mutable_, "global mutability");
+ ctx->stream.WriteU8(global->mutable_, "global mutability");
}
static void write_reloc_section(Context* ctx, RelocSection* reloc_section) {
@@ -656,8 +651,8 @@ static void write_reloc_section(Context* ctx, RelocSection* reloc_section) {
}
static Result write_module(Context* ctx, const Module* module) {
- write_u32(&ctx->stream, WABT_BINARY_MAGIC, "WASM_BINARY_MAGIC");
- write_u32(&ctx->stream, WABT_BINARY_VERSION, "WASM_BINARY_VERSION");
+ ctx->stream.WriteU32(WABT_BINARY_MAGIC, "WASM_BINARY_MAGIC");
+ ctx->stream.WriteU32(WABT_BINARY_VERSION, "WASM_BINARY_VERSION");
if (module->func_types.size()) {
begin_known_section(ctx, BinarySection::Type, LEB_SECTION_SIZE_GUESS);
@@ -689,12 +684,12 @@ static Result write_module(Context* ctx, const Module* module) {
const Import* import = module->imports[i];
write_header(ctx, "import header", i);
write_str(&ctx->stream, import->module_name.start,
- import->module_name.length, PrintChars::Yes,
- "import module name");
+ import->module_name.length, "import module name",
+ PrintChars::Yes);
write_str(&ctx->stream, import->field_name.start,
- import->field_name.length, PrintChars::Yes,
- "import field name");
- write_u8_enum(&ctx->stream, import->kind, "import kind");
+ import->field_name.length, "import field name",
+ PrintChars::Yes);
+ ctx->stream.WriteU8Enum(import->kind, "import kind");
switch (import->kind) {
case ExternalKind::Func:
write_u32_leb128(&ctx->stream, get_func_type_index_by_decl(
@@ -778,8 +773,8 @@ static Result write_module(Context* ctx, const Module* module) {
for (const Export* export_ : module->exports) {
write_str(&ctx->stream, export_->name.start, export_->name.length,
- PrintChars::Yes, "export name");
- write_u8_enum(&ctx->stream, export_->kind, "export kind");
+ "export name", PrintChars::Yes);
+ ctx->stream.WriteU8Enum(export_->kind, "export kind");
switch (export_->kind) {
case ExternalKind::Func: {
int index = get_func_index_by_var(module, &export_->var);
@@ -867,8 +862,7 @@ static Result write_module(Context* ctx, const Module* module) {
write_init_expr(ctx, module, segment->offset);
write_u32_leb128(&ctx->stream, segment->size, "data segment size");
write_header(ctx, "data segment data", i);
- write_data(&ctx->stream, segment->data, segment->size,
- "data segment data");
+ ctx->stream.WriteData(segment->data, segment->size, "data segment data");
}
end_section(ctx);
}
@@ -896,8 +890,8 @@ static Result write_module(Context* ctx, const Module* module) {
continue;
write_u32_leb128(&ctx->stream, i, "function index");
wabt_snprintf(desc, sizeof(desc), "func name %" PRIzd, i);
- write_str(&ctx->stream, func->name.start, func->name.length,
- PrintChars::Yes, desc);
+ write_str(&ctx->stream, func->name.start, func->name.length, desc,
+ PrintChars::Yes);
}
end_subsection(ctx);
}
@@ -921,8 +915,8 @@ static Result write_module(Context* ctx, const Module* module) {
const std::string& name = index_to_name[j];
wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, j);
write_u32_leb128(&ctx->stream, j, "local index");
- write_str(&ctx->stream, name.data(), name.length(), PrintChars::Yes,
- desc);
+ write_str(&ctx->stream, name.data(), name.length(), desc,
+ PrintChars::Yes);
}
make_type_binding_reverse_mapping(func->local_types, func->local_bindings,
@@ -931,8 +925,8 @@ static Result write_module(Context* ctx, const Module* module) {
const std::string& name = index_to_name[j];
wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, num_params + j);
write_u32_leb128(&ctx->stream, num_params + j, "local index");
- write_str(&ctx->stream, name.data(), name.length(), PrintChars::Yes,
- desc);
+ write_str(&ctx->stream, name.data(), name.length(), desc,
+ PrintChars::Yes);
}
}
end_subsection(ctx);
@@ -945,16 +939,13 @@ static Result write_module(Context* ctx, const Module* module) {
}
}
- return ctx->stream.result;
+ return ctx->stream.result();
}
Result write_binary_module(Writer* writer,
const Module* module,
const WriteBinaryOptions* options) {
- Context ctx;
- ctx.options = options;
- ctx.log_stream = options->log_stream;
- init_stream(&ctx.stream, writer, ctx.log_stream);
+ Context ctx(writer, options);
return write_module(&ctx, module);
}
diff --git a/src/binary-writer.h b/src/binary-writer.h
index 830f0d9b..0b131b7f 100644
--- a/src/binary-writer.h
+++ b/src/binary-writer.h
@@ -22,37 +22,32 @@
namespace wabt {
+class Writer;
struct Module;
struct Script;
-struct Writer;
-struct Stream;
#define WABT_WRITE_BINARY_OPTIONS_DEFAULT \
{ nullptr, true, false, false }
struct WriteBinaryOptions {
- struct Stream* log_stream;
+ Stream* log_stream;
bool canonicalize_lebs;
bool relocatable;
bool write_debug_names;
};
-Result write_binary_module(struct Writer*,
- const struct Module*,
- const WriteBinaryOptions*);
+Result write_binary_module(Writer*, const Module*, const WriteBinaryOptions*);
/* returns the length of the leb128 */
uint32_t u32_leb128_length(uint32_t value);
-void write_u32_leb128(struct Stream* stream, uint32_t value, const char* desc);
+void write_u32_leb128(Stream* stream, uint32_t value, const char* desc);
-void write_i32_leb128(struct Stream* stream, int32_t value, const char* desc);
+void write_i32_leb128(Stream* stream, int32_t value, const char* desc);
-void write_fixed_u32_leb128(struct Stream* stream,
- uint32_t value,
- const char* desc);
+void write_fixed_u32_leb128(Stream* stream, uint32_t value, const char* desc);
-uint32_t write_fixed_u32_leb128_at(struct Stream* stream,
+uint32_t write_fixed_u32_leb128_at(Stream* stream,
uint32_t offset,
uint32_t value,
const char* desc);
@@ -61,26 +56,26 @@ uint32_t write_fixed_u32_leb128_raw(uint8_t* data,
uint8_t* end,
uint32_t value);
-void write_type(struct Stream* stream, Type type);
+void write_type(Stream* stream, Type type);
-void write_str(struct Stream* stream,
+void write_str(Stream* stream,
const char* s,
size_t length,
- PrintChars print_chars,
- const char* desc);
+ const char* desc,
+ PrintChars print_chars = PrintChars::No);
-void write_opcode(struct Stream* stream, Opcode opcode);
+void write_opcode(Stream* stream, Opcode opcode);
-void write_limits(struct Stream* stream, const Limits* limits);
+void write_limits(Stream* stream, const Limits* limits);
/* Convenience functions for writing enums as LEB128s. */
template <typename T>
-void write_u32_leb128_enum(struct Stream* stream, T value, const char* desc) {
+void write_u32_leb128_enum(Stream* stream, T value, const char* desc) {
write_u32_leb128(stream, static_cast<uint32_t>(value), desc);
}
template <typename T>
-void write_i32_leb128_enum(struct Stream* stream, T value, const char* desc) {
+void write_i32_leb128_enum(Stream* stream, T value, const char* desc) {
write_i32_leb128(stream, static_cast<int32_t>(value), desc);
}
diff --git a/src/interpreter.cc b/src/interpreter.cc
index 98e58b30..ba56db94 100644
--- a/src/interpreter.cc
+++ b/src/interpreter.cc
@@ -25,8 +25,6 @@
#include "stream.h"
-#define INITIAL_ISTREAM_CAPACITY (64 * 1024)
-
namespace wabt {
static const char* s_interpreter_opcode_name[256];
@@ -57,10 +55,8 @@ static const char* get_interpreter_opcode_name(InterpreterOpcode opcode) {
return s_interpreter_opcode_name[static_cast<int>(opcode)];
}
-InterpreterEnvironment::InterpreterEnvironment() {
- WABT_ZERO_MEMORY(istream);
- init_output_buffer(&istream, INITIAL_ISTREAM_CAPACITY);
-}
+InterpreterEnvironment::InterpreterEnvironment()
+ : istream(new OutputBuffer()) {}
InterpreterThread::InterpreterThread()
: env(nullptr),
@@ -156,10 +152,6 @@ DefinedInterpreterModule::DefinedInterpreterModule(size_t istream_start)
HostInterpreterModule::HostInterpreterModule(const StringSlice& name)
: InterpreterModule(name, true) {}
-void destroy_interpreter_environment(InterpreterEnvironment* env) {
- destroy_output_buffer(&env->istream);
-}
-
InterpreterEnvironmentMark mark_interpreter_environment(
InterpreterEnvironment* env) {
InterpreterEnvironmentMark mark;
@@ -170,7 +162,7 @@ InterpreterEnvironmentMark mark_interpreter_environment(
mark.memories_size = env->memories.size();
mark.tables_size = env->tables.size();
mark.globals_size = env->globals.size();
- mark.istream_size = env->istream.size;
+ mark.istream_size = env->istream->data.size();
return mark;
}
@@ -203,7 +195,7 @@ void reset_interpreter_environment_to_mark(InterpreterEnvironment* env,
env->tables.erase(env->tables.begin() + mark.tables_size, env->tables.end());
env->globals.erase(env->globals.begin() + mark.globals_size,
env->globals.end());
- env->istream.size = mark.istream_size;
+ env->istream->data.resize(mark.istream_size);
}
HostInterpreterModule* append_host_module(InterpreterEnvironment* env,
@@ -567,8 +559,7 @@ DEFINE_BITCAST(bitcast_u64_to_f64, uint64_t, double)
MEM_TYPE_##mem_type value; \
TRAP_IF(offset + sizeof(value) > memory->data.size(), \
MemoryAccessOutOfBounds); \
- void* src = static_cast<void*>(memory->data.data() + \
- static_cast<uint32_t>(offset)); \
+ void* src = memory->data.data() + static_cast<uint32_t>(offset); \
memcpy(&value, src, sizeof(MEM_TYPE_##mem_type)); \
PUSH_##type(static_cast<MEM_TYPE_EXTEND_##type##_##mem_type>(value)); \
} while (0)
@@ -581,8 +572,7 @@ DEFINE_BITCAST(bitcast_u64_to_f64, uint64_t, double)
MEM_TYPE_##mem_type src = static_cast<MEM_TYPE_##mem_type>(value); \
TRAP_IF(offset + sizeof(src) > memory->data.size(), \
MemoryAccessOutOfBounds); \
- void* dst = static_cast<void*>(memory->data.data() + \
- static_cast<uint32_t>(offset)); \
+ void* dst = memory->data.data() + static_cast<uint32_t>(offset); \
memcpy(dst, &src, sizeof(MEM_TYPE_##mem_type)); \
} while (0)
@@ -820,7 +810,7 @@ InterpreterResult run_interpreter(InterpreterThread* thread,
InterpreterEnvironment* env = thread->env;
- const uint8_t* istream = reinterpret_cast<const uint8_t*>(env->istream.start);
+ const uint8_t* istream = env->istream->data.data();
const uint8_t* pc = &istream[thread->pc];
for (uint32_t i = 0; i < num_instructions; ++i) {
InterpreterOpcode opcode = static_cast<InterpreterOpcode>(*pc++);
@@ -1712,42 +1702,40 @@ exit_loop:
}
void trace_pc(InterpreterThread* thread, Stream* stream) {
- const uint8_t* istream =
- reinterpret_cast<const uint8_t*>(thread->env->istream.start);
+ const uint8_t* istream = thread->env->istream->data.data();
const uint8_t* pc = &istream[thread->pc];
size_t value_stack_depth =
thread->value_stack_top - thread->value_stack.data();
size_t call_stack_depth = thread->call_stack_top - thread->call_stack.data();
- writef(stream, "#%" PRIzd ". %4" PRIzd ": V:%-3" PRIzd "| ", call_stack_depth,
- pc - reinterpret_cast<uint8_t*>(thread->env->istream.start),
- value_stack_depth);
+ stream->Writef("#%" PRIzd ". %4" PRIzd ": V:%-3" PRIzd "| ", call_stack_depth,
+ pc - thread->env->istream->data.data(), value_stack_depth);
InterpreterOpcode opcode = static_cast<InterpreterOpcode>(*pc++);
switch (opcode) {
case InterpreterOpcode::Select:
- writef(stream, "%s %u, %" PRIu64 ", %" PRIu64 "\n",
- get_interpreter_opcode_name(opcode), PICK(3).i32, PICK(2).i64,
- PICK(1).i64);
+ stream->Writef("%s %u, %" PRIu64 ", %" PRIu64 "\n",
+ get_interpreter_opcode_name(opcode), PICK(3).i32,
+ PICK(2).i64, PICK(1).i64);
break;
case InterpreterOpcode::Br:
- writef(stream, "%s @%u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc));
+ stream->Writef("%s @%u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc));
break;
case InterpreterOpcode::BrIf:
- writef(stream, "%s @%u, %u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc), TOP().i32);
+ stream->Writef("%s @%u, %u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc), TOP().i32);
break;
case InterpreterOpcode::BrTable: {
uint32_t num_targets = read_u32_at(pc);
uint32_t table_offset = read_u32_at(pc + 4);
VALUE_TYPE_I32 key = TOP().i32;
- writef(stream, "%s %u, $#%u, table:$%u\n",
- get_interpreter_opcode_name(opcode), key, num_targets,
- table_offset);
+ stream->Writef("%s %u, $#%u, table:$%u\n",
+ get_interpreter_opcode_name(opcode), key, num_targets,
+ table_offset);
break;
}
@@ -1755,62 +1743,62 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::Return:
case InterpreterOpcode::Unreachable:
case InterpreterOpcode::Drop:
- writef(stream, "%s\n", get_interpreter_opcode_name(opcode));
+ stream->Writef("%s\n", get_interpreter_opcode_name(opcode));
break;
case InterpreterOpcode::CurrentMemory: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- memory_index);
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ memory_index);
break;
}
case InterpreterOpcode::I32Const:
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc));
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc));
break;
case InterpreterOpcode::I64Const:
- writef(stream, "%s $%" PRIu64 "\n", get_interpreter_opcode_name(opcode),
- read_u64_at(pc));
+ stream->Writef("%s $%" PRIu64 "\n", get_interpreter_opcode_name(opcode),
+ read_u64_at(pc));
break;
case InterpreterOpcode::F32Const:
- writef(stream, "%s $%g\n", get_interpreter_opcode_name(opcode),
- bitcast_u32_to_f32(read_u32_at(pc)));
+ stream->Writef("%s $%g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u32_to_f32(read_u32_at(pc)));
break;
case InterpreterOpcode::F64Const:
- writef(stream, "%s $%g\n", get_interpreter_opcode_name(opcode),
- bitcast_u64_to_f64(read_u64_at(pc)));
+ stream->Writef("%s $%g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u64_to_f64(read_u64_at(pc)));
break;
case InterpreterOpcode::GetLocal:
case InterpreterOpcode::GetGlobal:
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc));
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc));
break;
case InterpreterOpcode::SetLocal:
case InterpreterOpcode::SetGlobal:
case InterpreterOpcode::TeeLocal:
- writef(stream, "%s $%u, %u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc), TOP().i32);
+ stream->Writef("%s $%u, %u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc), TOP().i32);
break;
case InterpreterOpcode::Call:
- writef(stream, "%s @%u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc));
+ stream->Writef("%s @%u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc));
break;
case InterpreterOpcode::CallIndirect:
- writef(stream, "%s $%u, %u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc), TOP().i32);
+ stream->Writef("%s $%u, %u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc), TOP().i32);
break;
case InterpreterOpcode::CallHost:
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc));
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc));
break;
case InterpreterOpcode::I32Load8S:
@@ -1828,8 +1816,8 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::F32Load:
case InterpreterOpcode::F64Load: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u:%u+$%u\n", get_interpreter_opcode_name(opcode),
- memory_index, TOP().i32, read_u32_at(pc));
+ stream->Writef("%s $%u:%u+$%u\n", get_interpreter_opcode_name(opcode),
+ memory_index, TOP().i32, read_u32_at(pc));
break;
}
@@ -1837,8 +1825,8 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::I32Store16:
case InterpreterOpcode::I32Store: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u:%u+$%u, %u\n", get_interpreter_opcode_name(opcode),
- memory_index, PICK(2).i32, read_u32_at(pc), PICK(1).i32);
+ stream->Writef("%s $%u:%u+$%u, %u\n", get_interpreter_opcode_name(opcode),
+ memory_index, PICK(2).i32, read_u32_at(pc), PICK(1).i32);
break;
}
@@ -1847,32 +1835,32 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::I64Store32:
case InterpreterOpcode::I64Store: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u:%u+$%u, %" PRIu64 "\n",
- get_interpreter_opcode_name(opcode), memory_index, PICK(2).i32,
- read_u32_at(pc), PICK(1).i64);
+ stream->Writef("%s $%u:%u+$%u, %" PRIu64 "\n",
+ get_interpreter_opcode_name(opcode), memory_index,
+ PICK(2).i32, read_u32_at(pc), PICK(1).i64);
break;
}
case InterpreterOpcode::F32Store: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u:%u+$%u, %g\n", get_interpreter_opcode_name(opcode),
- memory_index, PICK(2).i32, read_u32_at(pc),
- bitcast_u32_to_f32(PICK(1).f32_bits));
+ stream->Writef("%s $%u:%u+$%u, %g\n", get_interpreter_opcode_name(opcode),
+ memory_index, PICK(2).i32, read_u32_at(pc),
+ bitcast_u32_to_f32(PICK(1).f32_bits));
break;
}
case InterpreterOpcode::F64Store: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u:%u+$%u, %g\n", get_interpreter_opcode_name(opcode),
- memory_index, PICK(2).i32, read_u32_at(pc),
- bitcast_u64_to_f64(PICK(1).f64_bits));
+ stream->Writef("%s $%u:%u+$%u, %g\n", get_interpreter_opcode_name(opcode),
+ memory_index, PICK(2).i32, read_u32_at(pc),
+ bitcast_u64_to_f64(PICK(1).f64_bits));
break;
}
case InterpreterOpcode::GrowMemory: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u:%u\n", get_interpreter_opcode_name(opcode),
- memory_index, TOP().i32);
+ stream->Writef("%s $%u:%u\n", get_interpreter_opcode_name(opcode),
+ memory_index, TOP().i32);
break;
}
@@ -1901,15 +1889,15 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::I32GeU:
case InterpreterOpcode::I32Rotr:
case InterpreterOpcode::I32Rotl:
- writef(stream, "%s %u, %u\n", get_interpreter_opcode_name(opcode),
- PICK(2).i32, PICK(1).i32);
+ stream->Writef("%s %u, %u\n", get_interpreter_opcode_name(opcode),
+ PICK(2).i32, PICK(1).i32);
break;
case InterpreterOpcode::I32Clz:
case InterpreterOpcode::I32Ctz:
case InterpreterOpcode::I32Popcnt:
case InterpreterOpcode::I32Eqz:
- writef(stream, "%s %u\n", get_interpreter_opcode_name(opcode), TOP().i32);
+ stream->Writef("%s %u\n", get_interpreter_opcode_name(opcode), TOP().i32);
break;
case InterpreterOpcode::I64Add:
@@ -1937,16 +1925,17 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::I64GeU:
case InterpreterOpcode::I64Rotr:
case InterpreterOpcode::I64Rotl:
- writef(stream, "%s %" PRIu64 ", %" PRIu64 "\n",
- get_interpreter_opcode_name(opcode), PICK(2).i64, PICK(1).i64);
+ stream->Writef("%s %" PRIu64 ", %" PRIu64 "\n",
+ get_interpreter_opcode_name(opcode), PICK(2).i64,
+ PICK(1).i64);
break;
case InterpreterOpcode::I64Clz:
case InterpreterOpcode::I64Ctz:
case InterpreterOpcode::I64Popcnt:
case InterpreterOpcode::I64Eqz:
- writef(stream, "%s %" PRIu64 "\n", get_interpreter_opcode_name(opcode),
- TOP().i64);
+ stream->Writef("%s %" PRIu64 "\n", get_interpreter_opcode_name(opcode),
+ TOP().i64);
break;
case InterpreterOpcode::F32Add:
@@ -1962,8 +1951,9 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::F32Le:
case InterpreterOpcode::F32Gt:
case InterpreterOpcode::F32Ge:
- writef(stream, "%s %g, %g\n", get_interpreter_opcode_name(opcode),
- bitcast_u32_to_f32(PICK(2).i32), bitcast_u32_to_f32(PICK(1).i32));
+ stream->Writef("%s %g, %g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u32_to_f32(PICK(2).i32),
+ bitcast_u32_to_f32(PICK(1).i32));
break;
case InterpreterOpcode::F32Abs:
@@ -1973,8 +1963,8 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::F32Trunc:
case InterpreterOpcode::F32Nearest:
case InterpreterOpcode::F32Sqrt:
- writef(stream, "%s %g\n", get_interpreter_opcode_name(opcode),
- bitcast_u32_to_f32(TOP().i32));
+ stream->Writef("%s %g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u32_to_f32(TOP().i32));
break;
case InterpreterOpcode::F64Add:
@@ -1990,8 +1980,9 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::F64Le:
case InterpreterOpcode::F64Gt:
case InterpreterOpcode::F64Ge:
- writef(stream, "%s %g, %g\n", get_interpreter_opcode_name(opcode),
- bitcast_u64_to_f64(PICK(2).i64), bitcast_u64_to_f64(PICK(1).i64));
+ stream->Writef("%s %g, %g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u64_to_f64(PICK(2).i64),
+ bitcast_u64_to_f64(PICK(1).i64));
break;
case InterpreterOpcode::F64Abs:
@@ -2001,8 +1992,8 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::F64Trunc:
case InterpreterOpcode::F64Nearest:
case InterpreterOpcode::F64Sqrt:
- writef(stream, "%s %g\n", get_interpreter_opcode_name(opcode),
- bitcast_u64_to_f64(TOP().i64));
+ stream->Writef("%s %g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u64_to_f64(TOP().i64));
break;
case InterpreterOpcode::I32TruncSF32:
@@ -2011,8 +2002,8 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::I64TruncUF32:
case InterpreterOpcode::F64PromoteF32:
case InterpreterOpcode::I32ReinterpretF32:
- writef(stream, "%s %g\n", get_interpreter_opcode_name(opcode),
- bitcast_u32_to_f32(TOP().i32));
+ stream->Writef("%s %g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u32_to_f32(TOP().i32));
break;
case InterpreterOpcode::I32TruncSF64:
@@ -2021,8 +2012,8 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::I64TruncUF64:
case InterpreterOpcode::F32DemoteF64:
case InterpreterOpcode::I64ReinterpretF64:
- writef(stream, "%s %g\n", get_interpreter_opcode_name(opcode),
- bitcast_u64_to_f64(TOP().i64));
+ stream->Writef("%s %g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u64_to_f64(TOP().i64));
break;
case InterpreterOpcode::I32WrapI64:
@@ -2031,8 +2022,8 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::F64ConvertSI64:
case InterpreterOpcode::F64ConvertUI64:
case InterpreterOpcode::F64ReinterpretI64:
- writef(stream, "%s %" PRIu64 "\n", get_interpreter_opcode_name(opcode),
- TOP().i64);
+ stream->Writef("%s %" PRIu64 "\n", get_interpreter_opcode_name(opcode),
+ TOP().i64);
break;
case InterpreterOpcode::I64ExtendSI32:
@@ -2042,22 +2033,22 @@ void trace_pc(InterpreterThread* thread, Stream* stream) {
case InterpreterOpcode::F32ReinterpretI32:
case InterpreterOpcode::F64ConvertSI32:
case InterpreterOpcode::F64ConvertUI32:
- writef(stream, "%s %u\n", get_interpreter_opcode_name(opcode), TOP().i32);
+ stream->Writef("%s %u\n", get_interpreter_opcode_name(opcode), TOP().i32);
break;
case InterpreterOpcode::Alloca:
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc));
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc));
break;
case InterpreterOpcode::BrUnless:
- writef(stream, "%s @%u, %u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc), TOP().i32);
+ stream->Writef("%s @%u, %u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc), TOP().i32);
break;
case InterpreterOpcode::DropKeep:
- writef(stream, "%s $%u $%u\n", get_interpreter_opcode_name(opcode),
- read_u32_at(pc), *(pc + 4));
+ stream->Writef("%s $%u $%u\n", get_interpreter_opcode_name(opcode),
+ read_u32_at(pc), *(pc + 4));
break;
case InterpreterOpcode::Data:
@@ -2077,38 +2068,38 @@ void disassemble(InterpreterEnvironment* env,
uint32_t to) {
/* TODO(binji): mark function entries */
/* TODO(binji): track value stack size */
- if (from >= env->istream.size)
+ if (from >= env->istream->data.size())
return;
- if (to > env->istream.size)
- to = env->istream.size;
- const uint8_t* istream = reinterpret_cast<const uint8_t*>(env->istream.start);
+ to = std::min<uint32_t>(to, env->istream->data.size());
+ const uint8_t* istream = env->istream->data.data();
const uint8_t* pc = &istream[from];
while (static_cast<uint32_t>(pc - istream) < to) {
- writef(stream, "%4" PRIzd "| ", pc - istream);
+ stream->Writef("%4" PRIzd "| ", pc - istream);
InterpreterOpcode opcode = static_cast<InterpreterOpcode>(*pc++);
switch (opcode) {
case InterpreterOpcode::Select:
- writef(stream, "%s %%[-3], %%[-2], %%[-1]\n",
- get_interpreter_opcode_name(opcode));
+ stream->Writef("%s %%[-3], %%[-2], %%[-1]\n",
+ get_interpreter_opcode_name(opcode));
break;
case InterpreterOpcode::Br:
- writef(stream, "%s @%u\n", get_interpreter_opcode_name(opcode),
- read_u32(&pc));
+ stream->Writef("%s @%u\n", get_interpreter_opcode_name(opcode),
+ read_u32(&pc));
break;
case InterpreterOpcode::BrIf:
- writef(stream, "%s @%u, %%[-1]\n", get_interpreter_opcode_name(opcode),
- read_u32(&pc));
+ stream->Writef("%s @%u, %%[-1]\n", get_interpreter_opcode_name(opcode),
+ read_u32(&pc));
break;
case InterpreterOpcode::BrTable: {
uint32_t num_targets = read_u32(&pc);
uint32_t table_offset = read_u32(&pc);
- writef(stream, "%s %%[-1], $#%u, table:$%u\n",
- get_interpreter_opcode_name(opcode), num_targets, table_offset);
+ stream->Writef("%s %%[-1], $#%u, table:$%u\n",
+ get_interpreter_opcode_name(opcode), num_targets,
+ table_offset);
break;
}
@@ -2116,64 +2107,65 @@ void disassemble(InterpreterEnvironment* env,
case InterpreterOpcode::Return:
case InterpreterOpcode::Unreachable:
case InterpreterOpcode::Drop:
- writef(stream, "%s\n", get_interpreter_opcode_name(opcode));
+ stream->Writef("%s\n", get_interpreter_opcode_name(opcode));
break;
case InterpreterOpcode::CurrentMemory: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- memory_index);
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ memory_index);
break;
}
case InterpreterOpcode::I32Const:
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- read_u32(&pc));
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ read_u32(&pc));
break;
case InterpreterOpcode::I64Const:
- writef(stream, "%s $%" PRIu64 "\n", get_interpreter_opcode_name(opcode),
- read_u64(&pc));
+ stream->Writef("%s $%" PRIu64 "\n", get_interpreter_opcode_name(opcode),
+ read_u64(&pc));
break;
case InterpreterOpcode::F32Const:
- writef(stream, "%s $%g\n", get_interpreter_opcode_name(opcode),
- bitcast_u32_to_f32(read_u32(&pc)));
+ stream->Writef("%s $%g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u32_to_f32(read_u32(&pc)));
break;
case InterpreterOpcode::F64Const:
- writef(stream, "%s $%g\n", get_interpreter_opcode_name(opcode),
- bitcast_u64_to_f64(read_u64(&pc)));
+ stream->Writef("%s $%g\n", get_interpreter_opcode_name(opcode),
+ bitcast_u64_to_f64(read_u64(&pc)));
break;
case InterpreterOpcode::GetLocal:
case InterpreterOpcode::GetGlobal:
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- read_u32(&pc));
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ read_u32(&pc));
break;
case InterpreterOpcode::SetLocal:
case InterpreterOpcode::SetGlobal:
case InterpreterOpcode::TeeLocal:
- writef(stream, "%s $%u, %%[-1]\n", get_interpreter_opcode_name(opcode),
- read_u32(&pc));
+ stream->Writef("%s $%u, %%[-1]\n", get_interpreter_opcode_name(opcode),
+ read_u32(&pc));
break;
case InterpreterOpcode::Call:
- writef(stream, "%s @%u\n", get_interpreter_opcode_name(opcode),
- read_u32(&pc));
+ stream->Writef("%s @%u\n", get_interpreter_opcode_name(opcode),
+ read_u32(&pc));
break;
case InterpreterOpcode::CallIndirect: {
uint32_t table_index = read_u32(&pc);
- writef(stream, "%s $%u:%u, %%[-1]\n",
- get_interpreter_opcode_name(opcode), table_index, read_u32(&pc));
+ stream->Writef("%s $%u:%u, %%[-1]\n",
+ get_interpreter_opcode_name(opcode), table_index,
+ read_u32(&pc));
break;
}
case InterpreterOpcode::CallHost:
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- read_u32(&pc));
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ read_u32(&pc));
break;
case InterpreterOpcode::I32Load8S:
@@ -2191,9 +2183,9 @@ void disassemble(InterpreterEnvironment* env,
case InterpreterOpcode::F32Load:
case InterpreterOpcode::F64Load: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u:%%[-1]+$%u\n",
- get_interpreter_opcode_name(opcode), memory_index,
- read_u32(&pc));
+ stream->Writef("%s $%u:%%[-1]+$%u\n",
+ get_interpreter_opcode_name(opcode), memory_index,
+ read_u32(&pc));
break;
}
@@ -2207,9 +2199,9 @@ void disassemble(InterpreterEnvironment* env,
case InterpreterOpcode::F32Store:
case InterpreterOpcode::F64Store: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s %%[-2]+$%u, $%u:%%[-1]\n",
- get_interpreter_opcode_name(opcode), memory_index,
- read_u32(&pc));
+ stream->Writef("%s %%[-2]+$%u, $%u:%%[-1]\n",
+ get_interpreter_opcode_name(opcode), memory_index,
+ read_u32(&pc));
break;
}
@@ -2289,8 +2281,8 @@ void disassemble(InterpreterEnvironment* env,
case InterpreterOpcode::F64Le:
case InterpreterOpcode::F64Gt:
case InterpreterOpcode::F64Ge:
- writef(stream, "%s %%[-2], %%[-1]\n",
- get_interpreter_opcode_name(opcode));
+ stream->Writef("%s %%[-2], %%[-1]\n",
+ get_interpreter_opcode_name(opcode));
break;
case InterpreterOpcode::I32Clz:
@@ -2340,50 +2332,50 @@ void disassemble(InterpreterEnvironment* env,
case InterpreterOpcode::F32ReinterpretI32:
case InterpreterOpcode::F64ConvertSI32:
case InterpreterOpcode::F64ConvertUI32:
- writef(stream, "%s %%[-1]\n", get_interpreter_opcode_name(opcode));
+ stream->Writef("%s %%[-1]\n", get_interpreter_opcode_name(opcode));
break;
case InterpreterOpcode::GrowMemory: {
uint32_t memory_index = read_u32(&pc);
- writef(stream, "%s $%u:%%[-1]\n", get_interpreter_opcode_name(opcode),
- memory_index);
+ stream->Writef("%s $%u:%%[-1]\n", get_interpreter_opcode_name(opcode),
+ memory_index);
break;
}
case InterpreterOpcode::Alloca:
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- read_u32(&pc));
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ read_u32(&pc));
break;
case InterpreterOpcode::BrUnless:
- writef(stream, "%s @%u, %%[-1]\n", get_interpreter_opcode_name(opcode),
- read_u32(&pc));
+ stream->Writef("%s @%u, %%[-1]\n", get_interpreter_opcode_name(opcode),
+ read_u32(&pc));
break;
case InterpreterOpcode::DropKeep: {
uint32_t drop = read_u32(&pc);
uint32_t keep = *pc++;
- writef(stream, "%s $%u $%u\n", get_interpreter_opcode_name(opcode),
- drop, keep);
+ stream->Writef("%s $%u $%u\n", get_interpreter_opcode_name(opcode),
+ drop, keep);
break;
}
case InterpreterOpcode::Data: {
uint32_t num_bytes = read_u32(&pc);
- writef(stream, "%s $%u\n", get_interpreter_opcode_name(opcode),
- num_bytes);
+ stream->Writef("%s $%u\n", get_interpreter_opcode_name(opcode),
+ num_bytes);
/* for now, the only reason this is emitted is for br_table, so display
* it as a list of table entries */
if (num_bytes % WABT_TABLE_ENTRY_SIZE == 0) {
uint32_t num_entries = num_bytes / WABT_TABLE_ENTRY_SIZE;
for (uint32_t i = 0; i < num_entries; ++i) {
- writef(stream, "%4" PRIzd "| ", pc - istream);
+ stream->Writef("%4" PRIzd "| ", pc - istream);
uint32_t offset;
uint32_t drop;
uint8_t keep;
read_table_entry_at(pc, &offset, &drop, &keep);
- writef(stream, " entry %d: offset: %u drop: %u keep: %u\n", i,
- offset, drop, keep);
+ stream->Writef(" entry %d: offset: %u drop: %u keep: %u\n", i,
+ offset, drop, keep);
pc += WABT_TABLE_ENTRY_SIZE;
}
} else {
diff --git a/src/interpreter.h b/src/interpreter.h
index 28b15b33..8f4143fe 100644
--- a/src/interpreter.h
+++ b/src/interpreter.h
@@ -28,7 +28,7 @@
namespace wabt {
-struct Stream;
+class Stream;
#define FOREACH_INTERPRETER_RESULT(V) \
V(Ok, "ok") \
@@ -334,7 +334,7 @@ struct InterpreterEnvironment {
std::vector<InterpreterMemory> memories;
std::vector<InterpreterTable> tables;
std::vector<InterpreterGlobal> globals;
- OutputBuffer istream;
+ std::unique_ptr<OutputBuffer> istream;
BindingHash module_bindings;
BindingHash registered_module_bindings;
};
@@ -387,13 +387,13 @@ InterpreterResult call_host(InterpreterThread* thread,
InterpreterResult run_interpreter(InterpreterThread* thread,
uint32_t num_instructions,
uint32_t* call_stack_return_top);
-void trace_pc(InterpreterThread* thread, struct Stream* stream);
+void trace_pc(InterpreterThread* thread, Stream* stream);
void disassemble(InterpreterEnvironment* env,
- struct Stream* stream,
+ Stream* stream,
uint32_t from,
uint32_t to);
void disassemble_module(InterpreterEnvironment* env,
- struct Stream* stream,
+ Stream* stream,
InterpreterModule* module);
InterpreterExport* get_interpreter_export_by_name(InterpreterModule* module,
diff --git a/src/stream.cc b/src/stream.cc
index 12510e93..0e1b5c43 100644
--- a/src/stream.cc
+++ b/src/stream.cc
@@ -24,140 +24,110 @@
namespace wabt {
-static FileStream s_stdout_stream;
-static FileStream s_stderr_stream;
-
-void init_stream(Stream* stream, Writer* writer, Stream* log_stream) {
- stream->writer = writer;
- stream->offset = 0;
- stream->result = Result::Ok;
- stream->log_stream = log_stream;
+Stream::Stream(Writer* writer, Stream* log_stream)
+ : writer_(writer),
+ offset_(0),
+ result_(Result::Ok),
+ log_stream_(log_stream) {}
+
+void Stream::AddOffset(ssize_t delta) {
+ offset_ += delta;
}
-void init_file_stream_from_existing(FileStream* stream, FILE* file) {
- init_file_writer_existing(&stream->writer, file);
- init_stream(&stream->base, &stream->writer.base, nullptr);
-}
-
-Stream* init_stdout_stream(void) {
- init_file_stream_from_existing(&s_stdout_stream, stdout);
- return &s_stdout_stream.base;
-}
-
-Stream* init_stderr_stream(void) {
- init_file_stream_from_existing(&s_stderr_stream, stderr);
- return &s_stderr_stream.base;
-}
-
-void write_data_at(Stream* stream,
- size_t offset,
- const void* src,
- size_t size,
- PrintChars print_chars,
- const char* desc) {
- if (WABT_FAILED(stream->result))
+void Stream::WriteDataAt(size_t at,
+ const void* src,
+ size_t size,
+ const char* desc,
+ PrintChars print_chars) {
+ if (WABT_FAILED(result_))
return;
- if (stream->log_stream) {
- write_memory_dump(stream->log_stream, src, size, offset, print_chars,
- nullptr, desc);
- }
- if (stream->writer->write_data) {
- stream->result = stream->writer->write_data(offset, src, size,
- stream->writer->user_data);
+ if (log_stream_) {
+ log_stream_->WriteMemoryDump(src, size, at, nullptr, desc, print_chars);
}
+ result_ = writer_->WriteData(at, src, size);
}
-void write_data(Stream* stream,
- const void* src,
- size_t size,
- const char* desc) {
- write_data_at(stream, stream->offset, src, size, PrintChars::No, desc);
- stream->offset += size;
+void Stream::WriteData(const void* src,
+ size_t size,
+ const char* desc,
+ PrintChars print_chars) {
+ WriteDataAt(offset_, src, size, desc, print_chars);
+ offset_ += size;
}
-void move_data(Stream* stream,
- size_t dst_offset,
- size_t src_offset,
- size_t size) {
- if (WABT_FAILED(stream->result))
+void Stream::MoveData(size_t dst_offset, size_t src_offset, size_t size) {
+ if (WABT_FAILED(result_))
return;
- if (stream->log_stream) {
- writef(stream->log_stream, "; move data: [%" PRIzx ", %" PRIzx
- ") -> [%" PRIzx ", %" PRIzx ")\n",
- src_offset, src_offset + size, dst_offset, dst_offset + size);
- }
- if (stream->writer->write_data) {
- stream->result = stream->writer->move_data(dst_offset, src_offset, size,
- stream->writer->user_data);
+ if (log_stream_) {
+ log_stream_->Writef(
+ "; 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);
}
-void writef(Stream* stream, const char* format, ...) {
+void Stream::Writef(const char* format, ...) {
WABT_SNPRINTF_ALLOCA(buffer, length, format);
- write_data(stream, buffer, length, nullptr);
-}
-
-void write_u8(Stream* stream, uint32_t value, const char* desc) {
- assert(value <= UINT8_MAX);
- uint8_t value8 = value;
- write_data_at(stream, stream->offset, &value8, sizeof(value8), PrintChars::No,
- desc);
- stream->offset += sizeof(value8);
-}
-
-void write_u32(Stream* stream, uint32_t value, const char* desc) {
- write_data_at(stream, stream->offset, &value, sizeof(value), PrintChars::No,
- desc);
- stream->offset += sizeof(value);
-}
-
-void write_u64(Stream* stream, uint64_t value, const char* desc) {
- write_data_at(stream, stream->offset, &value, sizeof(value), PrintChars::No,
- desc);
- stream->offset += sizeof(value);
+ WriteData(buffer, length);
}
-void write_memory_dump(Stream* stream,
- const void* start,
- size_t size,
- size_t offset,
- PrintChars print_chars,
- const char* prefix,
- const char* desc) {
+void Stream::WriteMemoryDump(const void* start,
+ size_t size,
+ size_t offset,
+ const char* prefix,
+ const char* desc,
+ PrintChars print_chars) {
const uint8_t* p = static_cast<const uint8_t*>(start);
const uint8_t* end = p + size;
while (p < end) {
const uint8_t* line = p;
const uint8_t* line_end = p + DUMP_OCTETS_PER_LINE;
if (prefix)
- writef(stream, "%s", prefix);
- writef(stream, "%07" PRIzx ": ", reinterpret_cast<intptr_t>(p) -
- reinterpret_cast<intptr_t>(start) +
- offset);
+ Writef("%s", prefix);
+ Writef("%07" PRIzx ": ", reinterpret_cast<intptr_t>(p) -
+ reinterpret_cast<intptr_t>(start) + offset);
while (p < line_end) {
for (int i = 0; i < DUMP_OCTETS_PER_GROUP; ++i, ++p) {
if (p < end) {
- writef(stream, "%02x", *p);
+ Writef("%02x", *p);
} else {
- write_char(stream, ' ');
- write_char(stream, ' ');
+ WriteChar(' ');
+ WriteChar(' ');
}
}
- write_char(stream, ' ');
+ WriteChar(' ');
}
if (print_chars == PrintChars::Yes) {
- write_char(stream, ' ');
+ WriteChar(' ');
p = line;
for (int i = 0; i < DUMP_OCTETS_PER_LINE && p < end; ++i, ++p)
- write_char(stream, isprint(*p) ? *p : '.');
+ WriteChar(isprint(*p) ? *p : '.');
}
/* if there are multiple lines, only print the desc on the last one */
if (p >= end && desc)
- writef(stream, " ; %s", desc);
- write_char(stream, '\n');
+ Writef(" ; %s", desc);
+ WriteChar('\n');
}
}
+MemoryStream::MemoryStream() : Stream(&writer_) {}
+
+FileStream::FileStream(const char* filename)
+ : Stream(&writer_), writer_(filename) {}
+
+FileStream::FileStream(FILE* file) : Stream(&writer_), writer_(file) {}
+
+// static
+std::unique_ptr<FileStream> FileStream::CreateStdout() {
+ return std::unique_ptr<FileStream>(new FileStream(stdout));
+}
+
+// static
+std::unique_ptr<FileStream> FileStream::CreateStderr() {
+ return std::unique_ptr<FileStream>(new FileStream(stderr));
+}
+
+
} // namespace wabt
diff --git a/src/stream.h b/src/stream.h
index 8e027333..a43c5c12 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -17,26 +17,14 @@
#ifndef WABT_STREAM_H_
#define WABT_STREAM_H_
-#include <stdio.h>
+#include <cassert>
+#include <memory>
#include "common.h"
#include "writer.h"
namespace wabt {
-struct Stream {
- Writer* writer;
- size_t offset;
- Result result;
- /* if non-null, log all writes to this stream */
- struct Stream* log_stream;
-};
-
-struct FileStream {
- Stream base;
- FileWriter writer;
-};
-
/* whether to display the ASCII characters in the debug output for
* write_memory */
enum class PrintChars {
@@ -44,55 +32,127 @@ enum class PrintChars {
Yes = 1,
};
-void init_stream(Stream* stream, Writer* writer, Stream* log_stream);
-void init_file_stream_from_existing(FileStream* stream, FILE* file);
-Stream* init_stdout_stream(void);
-Stream* init_stderr_stream(void);
+class Stream {
+ public:
+ Stream(Writer* writer, Stream* log_stream = nullptr);
+
+ size_t offset() { return offset_; }
+ Result result() { return result_; }
+
+ void set_log_stream(Stream* stream) {
+ assert(stream);
+ log_stream_ = stream;
+ }
-/* helper functions for writing to a Stream. the |desc| parameter is
- * optional, and will be appended to the log stream if |stream.log_stream| is
- * non-null. */
-void write_data_at(Stream*,
- size_t offset,
+ Stream& log_stream() {
+ assert(log_stream_);
+ return *log_stream_;
+ }
+
+ bool has_log_stream() const { return log_stream_ != nullptr; }
+
+ void AddOffset(ssize_t delta);
+
+ void WriteData(const void* src,
+ size_t size,
+ const char* desc = nullptr,
+ PrintChars = PrintChars::No);
+ void MoveData(size_t dst_offset, size_t src_offset, size_t size);
+
+ void WriteDataAt(size_t offset,
const void* src,
size_t size,
- PrintChars print_chars,
- const char* desc);
-void write_data(Stream*, const void* src, size_t size, const char* desc);
-void move_data(Stream*, size_t dst_offset, size_t src_offset, size_t size);
-
-void WABT_PRINTF_FORMAT(2, 3) writef(Stream*, const char* format, ...);
-/* specified as uint32_t instead of uint8_t so we can check if the value given
- * is in range before wrapping */
-void write_u8(Stream*, uint32_t value, const char* desc);
-void write_u32(Stream*, uint32_t value, const char* desc);
-void write_u64(Stream*, uint64_t value, const char* desc);
-
-static WABT_INLINE void write_char(Stream* stream, char c) {
- write_u8(stream, c, nullptr);
-}
-
-/* dump memory as text, similar to the xxd format */
-void write_memory_dump(Stream*,
- const void* start,
+ const char* desc = nullptr,
+ PrintChars = PrintChars::No);
+
+ void WABT_PRINTF_FORMAT(2, 3) Writef(const char* format, ...);
+
+ // Specified as uint32_t instead of uint8_t so we can check if the value
+ // given is in range before wrapping.
+ void WriteU8(uint32_t value,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ assert(value <= UINT8_MAX);
+ Write(static_cast<uint8_t>(value), desc, print_chars);
+ }
+ void WriteU32(uint32_t value,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ Write(value, desc, print_chars);
+ }
+ void WriteU64(uint64_t value,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ Write(value, desc, print_chars);
+ }
+ void WriteChar(char c,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ WriteU8(c, desc, print_chars);
+ }
+
+ // Dump memory as text, similar to the xxd format.
+ void WriteMemoryDump(const void* start,
size_t size,
- size_t offset,
- PrintChars print_chars,
- const char* prefix,
- const char* desc);
-
-static WABT_INLINE void write_output_buffer_memory_dump(
- Stream* stream,
- struct OutputBuffer* buf) {
- write_memory_dump(stream, buf->start, buf->size, 0, PrintChars::No, nullptr,
- nullptr);
-}
-
-/* Helper function for writing enums as u8. */
-template <typename T>
-void write_u8_enum(Stream* stream, T value, const char* desc) {
- write_u8(stream, static_cast<uint32_t>(value), desc);
-}
+ size_t offset = 0,
+ const char* prefix = nullptr,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No);
+
+ // Convenience functions for writing enums.
+ template <typename T>
+ void WriteU8Enum(T value,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ WriteU8(static_cast<uint32_t>(value), desc, print_chars);
+ }
+
+ 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_;
+};
+
+class MemoryStream : public Stream {
+ public:
+ MemoryStream();
+
+ MemoryWriter& writer() { return writer_; }
+
+ std::unique_ptr<OutputBuffer> ReleaseOutputBuffer() {
+ return writer_.ReleaseOutputBuffer();
+ }
+
+ Result WriteToFile(const char* filename) {
+ return writer_.output_buffer().WriteToFile(filename);
+ }
+
+ private:
+ MemoryWriter writer_;
+};
+
+class FileStream : public Stream {
+ public:
+ explicit FileStream(const char* filename);
+ explicit FileStream(FILE*);
+
+ FileWriter& writer() { return writer_; }
+
+ static std::unique_ptr<FileStream> CreateStdout();
+ static std::unique_ptr<FileStream> CreateStderr();
+
+ bool is_open() const { return writer_.is_open(); }
+
+ private:
+ FileWriter writer_;
+};
} // namespace wabt
diff --git a/src/tools/wasm-interp.cc b/src/tools/wasm-interp.cc
index 643fc3fa..a90ba77a 100644
--- a/src/tools/wasm-interp.cc
+++ b/src/tools/wasm-interp.cc
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <algorithm>
+#include <memory>
#include <vector>
#include "binary-reader.h"
@@ -47,12 +48,11 @@ static InterpreterThreadOptions s_thread_options =
static bool s_trace;
static bool s_spec;
static bool s_run_all_exports;
-static Stream* s_stdout_stream;
static BinaryErrorHandler s_error_handler = WABT_BINARY_ERROR_HANDLER_DEFAULT;
-static FileWriter s_log_stream_writer;
-static Stream s_log_stream;
+static std::unique_ptr<FileStream> s_log_stream;
+static std::unique_ptr<FileStream> s_stdout_stream;
#define NOPE HasArgument::No
#define YEP HasArgument::Yes
@@ -117,9 +117,8 @@ static void on_option(struct OptionParser* parser,
switch (option->id) {
case FLAG_VERBOSE:
s_verbose++;
- init_file_writer_existing(&s_log_stream_writer, stdout);
- init_stream(&s_log_stream, &s_log_stream_writer.base, nullptr);
- s_read_binary_options.log_stream = &s_log_stream;
+ s_log_stream = FileStream::CreateStdout();
+ s_read_binary_options.log_stream = s_log_stream.get();
break;
case FLAG_HELP:
@@ -284,7 +283,7 @@ static InterpreterResult run_defined_function(InterpreterThread* thread,
uint32_t* call_stack_return_top = thread->call_stack_top;
while (iresult == InterpreterResult::Ok) {
if (s_trace)
- trace_pc(thread, s_stdout_stream);
+ trace_pc(thread, s_stdout_stream.get());
iresult = run_interpreter(thread, quantum, call_stack_return_top);
}
if (iresult != InterpreterResult::Returned)
@@ -444,7 +443,7 @@ static Result read_module(const char* module_filename,
if (WABT_SUCCEEDED(result)) {
if (s_verbose)
- disassemble_module(env, s_stdout_stream, *out_module);
+ disassemble_module(env, s_stdout_stream.get(), *out_module);
}
delete[] data;
}
@@ -598,12 +597,11 @@ static Result read_and_run_module(const char* module_filename) {
print_interpreter_result("error running start function", iresult);
}
}
- destroy_interpreter_environment(&env);
return result;
}
/* An extremely simple JSON parser that only knows how to parse the expected
- * format from wast2wabt. */
+ * format from wast2wasm. */
struct Context {
Context()
: last_module(nullptr),
@@ -1150,7 +1148,6 @@ static Result on_assert_malformed_command(Context* ctx,
}
delete[] path;
- destroy_interpreter_environment(&env);
destroy_custom_error_handler(error_handler);
return result;
}
@@ -1234,7 +1231,6 @@ static Result on_assert_invalid_command(Context* ctx,
}
delete[] path;
- destroy_interpreter_environment(&env);
destroy_custom_error_handler(error_handler);
return result;
}
@@ -1615,7 +1611,6 @@ static Result parse_commands(Context* ctx) {
}
static void destroy_context(Context* ctx) {
- destroy_interpreter_environment(&ctx->env);
delete[] ctx->json_data;
}
@@ -1646,7 +1641,7 @@ int main(int argc, char** argv) {
init_stdio();
parse_options(argc, argv);
- s_stdout_stream = init_stdout_stream();
+ s_stdout_stream = FileStream::CreateStdout();
Result result;
if (s_spec) {
diff --git a/src/tools/wasm-link.cc b/src/tools/wasm-link.cc
index 3e61a3a7..7ecfb71d 100644
--- a/src/tools/wasm-link.cc
+++ b/src/tools/wasm-link.cc
@@ -56,16 +56,13 @@ static bool s_debug;
static bool s_relocatable;
static const char* s_outfile = "a.wasm";
static std::vector<std::string> s_infiles;
-static FileWriter s_log_stream_writer;
-static Stream s_log_stream;
+static std::unique_ptr<FileStream> s_log_stream;
struct Context {
WABT_DISALLOW_COPY_AND_ASSIGN(Context);
- Context() {
- WABT_ZERO_MEMORY(stream);
- }
+ Context() {}
- Stream stream;
+ MemoryStream stream;
std::vector<std::unique_ptr<LinkerInputBinary>> inputs;
ssize_t current_section_payload_offset = 0;
};
@@ -76,8 +73,7 @@ static void on_option(struct OptionParser* parser,
switch (option->id) {
case FLAG_DEBUG:
s_debug = true;
- init_file_writer_existing(&s_log_stream_writer, stdout);
- init_stream(&s_log_stream, &s_log_stream_writer.base, nullptr);
+ s_log_stream = FileStream::CreateStdout();
break;
case FLAG_OUTPUT:
@@ -165,7 +161,7 @@ static uint32_t relocate_func_index(LinkerInputBinary* binary,
/* locally declared function call */
offset = binary->function_index_offset;
if (s_debug)
- writef(&s_log_stream, "func reloc %d + %d\n", function_index, offset);
+ s_log_stream->Writef("func reloc %d + %d\n", function_index, offset);
} else {
/* imported function call */
FunctionImport* import = &binary->function_imports[function_index];
@@ -173,15 +169,14 @@ static uint32_t relocate_func_index(LinkerInputBinary* binary,
function_index = import->foreign_index;
offset = import->foreign_binary->function_index_offset;
if (s_debug)
- writef(&s_log_stream,
- "reloc for disabled import. new index = %d + %d\n",
- function_index, offset);
+ s_log_stream->Writef("reloc for disabled import. new index = %d + %d\n",
+ function_index, offset);
} else {
uint32_t new_index = import->relocated_function_index;
if (s_debug)
- writef(&s_log_stream,
- "reloc for active import. old index = %d, new index = %d\n",
- function_index, new_index);
+ s_log_stream->Writef(
+ "reloc for active import. old index = %d, new index = %d\n",
+ function_index, new_index);
return new_index;
}
}
@@ -236,9 +231,10 @@ static void apply_relocations(Section* section) {
if (!section->relocations.size())
return;
- if (s_debug)
- writef(&s_log_stream, "apply_relocations: %s\n",
- get_section_name(section->section_code));
+ if (s_debug) {
+ s_log_stream->Writef("apply_relocations: %s\n",
+ get_section_name(section->section_code));
+ }
/* Perform relocations in-place */
for (Reloc& reloc: section->relocations) {
@@ -250,36 +246,36 @@ static void write_section_payload(Context* ctx, Section* sec) {
assert(ctx->current_section_payload_offset != -1);
sec->output_payload_offset =
- ctx->stream.offset - ctx->current_section_payload_offset;
+ ctx->stream.offset() - ctx->current_section_payload_offset;
uint8_t* payload = &sec->binary->data[sec->payload_offset];
- write_data(&ctx->stream, payload, sec->payload_size, "section content");
+ ctx->stream.WriteData(payload, sec->payload_size, "section content");
}
static void write_c_str(Stream* stream, const char* str, const char* desc) {
- write_str(stream, str, strlen(str), PrintChars::Yes, desc);
+ write_str(stream, str, strlen(str), desc, PrintChars::Yes);
}
static void write_slice(Stream* stream, StringSlice str, const char* desc) {
- write_str(stream, str.start, str.length, PrintChars::Yes, desc);
+ write_str(stream, str.start, str.length, desc, PrintChars::Yes);
}
static void write_string(Stream* stream,
const std::string& str,
const char* desc) {
- write_str(stream, str.data(), str.length(), PrintChars::Yes, desc);
+ write_str(stream, str.data(), str.length(), desc, PrintChars::Yes);
}
-#define WRITE_UNKNOWN_SIZE(STREAM) \
- { \
- uint32_t fixup_offset = (STREAM)->offset; \
- write_fixed_u32_leb128(STREAM, 0, "unknown size"); \
- ctx->current_section_payload_offset = (STREAM)->offset; \
- uint32_t start = (STREAM)->offset;
+#define WRITE_UNKNOWN_SIZE(STREAM) \
+ { \
+ uint32_t fixup_offset = (STREAM)->offset(); \
+ write_fixed_u32_leb128(STREAM, 0, "unknown size"); \
+ ctx->current_section_payload_offset = (STREAM)->offset(); \
+ uint32_t start = (STREAM)->offset();
-#define FIXUP_SIZE(STREAM) \
- write_fixed_u32_leb128_at(STREAM, fixup_offset, (STREAM)->offset - start, \
- "fixup size"); \
+#define FIXUP_SIZE(STREAM) \
+ write_fixed_u32_leb128_at(STREAM, fixup_offset, (STREAM)->offset() - start, \
+ "fixup size"); \
}
static void write_table_section(Context* ctx,
@@ -317,7 +313,7 @@ static void write_export_section(Context* ctx) {
for (const std::unique_ptr<LinkerInputBinary>& binary : ctx->inputs) {
for (const Export& export_ : binary->exports) {
write_slice(stream, export_.name, "export name");
- write_u8_enum(stream, export_.kind, "export kind");
+ stream->WriteU8Enum(export_.kind, "export kind");
uint32_t index = export_.index;
switch (export_.kind) {
case ExternalKind::Func:
@@ -351,7 +347,7 @@ static void write_elem_section(Context* ctx,
write_opcode(&ctx->stream, Opcode::End);
write_u32_leb128(stream, total_elem_count, "num elements");
- ctx->current_section_payload_offset = stream->offset;
+ ctx->current_section_payload_offset = stream->offset();
for (Section* section : sections) {
apply_relocations(section);
@@ -386,7 +382,7 @@ static void write_function_import(Context* ctx,
uint32_t offset) {
write_c_str(&ctx->stream, WABT_LINK_MODULE_NAME, "import module name");
write_slice(&ctx->stream, import->name, "import field name");
- write_u8_enum(&ctx->stream, ExternalKind::Func, "import kind");
+ ctx->stream.WriteU8Enum(ExternalKind::Func, "import kind");
write_u32_leb128(&ctx->stream, import->sig_index + offset,
"import signature index");
}
@@ -394,9 +390,9 @@ static void write_function_import(Context* ctx,
static void write_global_import(Context* ctx, GlobalImport* import) {
write_c_str(&ctx->stream, WABT_LINK_MODULE_NAME, "import module name");
write_slice(&ctx->stream, import->name, "import field name");
- write_u8_enum(&ctx->stream, ExternalKind::Global, "import kind");
+ ctx->stream.WriteU8Enum(ExternalKind::Global, "import kind");
write_type(&ctx->stream, import->type);
- write_u8(&ctx->stream, import->mutable_, "global mutability");
+ ctx->stream.WriteU8(import->mutable_, "global mutability");
}
static void write_import_section(Context* ctx) {
@@ -468,7 +464,7 @@ static void write_data_segment(Stream* stream,
write_u32_leb128(stream, segment.offset + offset, "offset");
write_opcode(stream, Opcode::End);
write_u32_leb128(stream, segment.size, "segment size");
- write_data(stream, segment.data, segment.size, "segment data");
+ stream->WriteData(segment.data, segment.size, "segment data");
}
static void write_data_section(Context* ctx,
@@ -508,11 +504,11 @@ static void write_names_section(Context* ctx) {
return;
Stream* stream = &ctx->stream;
- write_u8_enum(stream, BinarySection::Custom, "section code");
+ stream->WriteU8Enum(BinarySection::Custom, "section code");
WRITE_UNKNOWN_SIZE(stream);
write_c_str(stream, "name", "custom section name");
- write_u8_enum(stream, NameSectionSubsection::Function, "subsection code");
+ stream->WriteU8Enum(NameSectionSubsection::Function, "subsection code");
WRITE_UNKNOWN_SIZE(stream);
write_u32_leb128(stream, total_count, "element count");
for (const std::unique_ptr<LinkerInputBinary>& binary: ctx->inputs) {
@@ -553,7 +549,7 @@ static void write_reloc_section(Context* ctx,
WABT_BINARY_SECTION_RELOC, get_section_name(section_code));
Stream* stream = &ctx->stream;
- write_u8_enum(stream, BinarySection::Custom, "section code");
+ stream->WriteU8Enum(BinarySection::Custom, "section code");
WRITE_UNKNOWN_SIZE(stream);
write_c_str(stream, section_name, "reloc section name");
write_u32_leb128_enum(&ctx->stream, section_code, "reloc section");
@@ -604,7 +600,7 @@ static bool write_combined_section(Context* ctx,
total_count += sec->count;
}
- write_u8_enum(&ctx->stream, section_code, "section code");
+ ctx->stream.WriteU8Enum(section_code, "section code");
ctx->current_section_payload_offset = -1;
switch (section_code) {
@@ -637,7 +633,7 @@ static bool write_combined_section(Context* ctx,
Stream* stream = &ctx->stream;
write_u32_leb128(stream, total_size, "section size");
write_u32_leb128(stream, total_count, "element count");
- ctx->current_section_payload_offset = ctx->stream.offset;
+ ctx->current_section_payload_offset = ctx->stream.offset();
for (Section* sec: sections) {
apply_relocations(sec);
write_section_payload(ctx, sec);
@@ -777,8 +773,8 @@ static void write_binary(Context* ctx) {
}
/* Write the final binary */
- write_u32(&ctx->stream, WABT_BINARY_MAGIC, "WABT_BINARY_MAGIC");
- write_u32(&ctx->stream, WABT_BINARY_VERSION, "WABT_BINARY_VERSION");
+ ctx->stream.WriteU32(WABT_BINARY_MAGIC, "WABT_BINARY_MAGIC");
+ ctx->stream.WriteU32(WABT_BINARY_VERSION, "WABT_BINARY_VERSION");
/* Write known sections first */
for (size_t i = FIRST_KNOWN_SECTION; i < kBinarySectionCount; i++) {
@@ -797,47 +793,39 @@ static void dump_reloc_offsets(Context* ctx) {
if (s_debug) {
for (uint32_t i = 0; i < ctx->inputs.size(); i++) {
LinkerInputBinary* binary = ctx->inputs[i].get();
- writef(&s_log_stream, "Relocation info for: %s\n", binary->filename);
- writef(&s_log_stream, " - type index offset : %d\n",
- binary->type_index_offset);
- writef(&s_log_stream, " - mem page offset : %d\n",
- binary->memory_page_offset);
- writef(&s_log_stream, " - function index offset : %d\n",
- binary->function_index_offset);
- writef(&s_log_stream, " - global index offset : %d\n",
- binary->global_index_offset);
- writef(&s_log_stream, " - imported function offset: %d\n",
- binary->imported_function_index_offset);
- writef(&s_log_stream, " - imported global offset : %d\n",
- binary->imported_global_index_offset);
+ s_log_stream->Writef("Relocation info for: %s\n", binary->filename);
+ s_log_stream->Writef(" - type index offset : %d\n",
+ binary->type_index_offset);
+ s_log_stream->Writef(" - mem page offset : %d\n",
+ binary->memory_page_offset);
+ s_log_stream->Writef(" - function index offset : %d\n",
+ binary->function_index_offset);
+ s_log_stream->Writef(" - global index offset : %d\n",
+ binary->global_index_offset);
+ s_log_stream->Writef(" - imported function offset: %d\n",
+ binary->imported_function_index_offset);
+ s_log_stream->Writef(" - imported global offset : %d\n",
+ binary->imported_global_index_offset);
}
}
}
static Result perform_link(Context* ctx) {
- MemoryWriter writer;
- WABT_ZERO_MEMORY(writer);
- if (WABT_FAILED(init_mem_writer(&writer)))
- WABT_FATAL("unable to open memory writer for writing\n");
-
- Stream* log_stream = nullptr;
- if (s_debug)
- log_stream = &s_log_stream;
-
- if (s_debug)
- writef(&s_log_stream, "writing file: %s\n", s_outfile);
+ if (s_debug) {
+ ctx->stream.set_log_stream(s_log_stream.get());
+ s_log_stream->Writef("writing file: %s\n", s_outfile);
+ }
calculate_reloc_offsets(ctx);
resolve_symbols(ctx);
calculate_reloc_offsets(ctx);
dump_reloc_offsets(ctx);
- init_stream(&ctx->stream, &writer.base, log_stream);
write_binary(ctx);
- if (WABT_FAILED(write_output_buffer_to_file(&writer.buf, s_outfile)))
+ if (WABT_FAILED(ctx->stream.WriteToFile(s_outfile))) {
WABT_FATAL("error writing linked output to file\n");
+ }
- close_mem_writer(&writer);
return Result::Ok;
}
@@ -852,7 +840,7 @@ int main(int argc, char** argv) {
for (size_t i = 0; i < s_infiles.size(); i++) {
const std::string& input_filename = s_infiles[i];
if (s_debug)
- writef(&s_log_stream, "reading file: %s\n", input_filename.c_str());
+ s_log_stream->Writef("reading file: %s\n", input_filename.c_str());
char* data;
size_t size;
result = read_file(input_filename.c_str(), &data, &size);
@@ -863,7 +851,7 @@ int main(int argc, char** argv) {
context.inputs.emplace_back(b);
LinkOptions options = { NULL };
if (s_debug)
- options.log_stream = &s_log_stream;
+ options.log_stream = s_log_stream.get();
result = read_binary_linker(b, &options);
if (WABT_FAILED(result))
WABT_FATAL("error parsing file: %s\n", input_filename.c_str());
diff --git a/src/tools/wasm2wast.cc b/src/tools/wasm2wast.cc
index d885f740..e826c3b8 100644
--- a/src/tools/wasm2wast.cc
+++ b/src/tools/wasm2wast.cc
@@ -38,11 +38,8 @@ static const char* s_infile;
static const char* s_outfile;
static ReadBinaryOptions s_read_binary_options = {nullptr, true};
static bool s_generate_names;
-
static BinaryErrorHandler s_error_handler = WABT_BINARY_ERROR_HANDLER_DEFAULT;
-
-static FileWriter s_log_stream_writer;
-static Stream s_log_stream;
+static std::unique_ptr<FileStream> s_log_stream;
#define NOPE HasArgument::No
#define YEP HasArgument::Yes
@@ -86,9 +83,8 @@ static void on_option(struct OptionParser* parser,
switch (option->id) {
case FLAG_VERBOSE:
s_verbose++;
- init_file_writer_existing(&s_log_stream_writer, stdout);
- init_stream(&s_log_stream, &s_log_stream_writer.base, nullptr);
- s_read_binary_options.log_stream = &s_log_stream;
+ s_log_stream = FileStream::CreateStdout();
+ s_read_binary_options.log_stream = s_log_stream.get();
break;
case FLAG_HELP:
@@ -160,17 +156,9 @@ int main(int argc, char** argv) {
}
if (WABT_SUCCEEDED(result)) {
- FileWriter file_writer;
- if (s_outfile) {
- result = init_file_writer(&file_writer, s_outfile);
- } else {
- init_file_writer_existing(&file_writer, stdout);
- }
-
- if (WABT_SUCCEEDED(result)) {
- result = write_ast(&file_writer.base, &module);
- close_file_writer(&file_writer);
- }
+ FileWriter writer(s_outfile ? FileWriter(s_outfile)
+ : FileWriter(stdout));
+ result = write_ast(&writer, &module);
}
}
delete[] data;
diff --git a/src/tools/wasmdump.cc b/src/tools/wasmdump.cc
index 25d227fb..8ed207ce 100644
--- a/src/tools/wasmdump.cc
+++ b/src/tools/wasmdump.cc
@@ -67,8 +67,8 @@ static Option s_options[] = {
WABT_STATIC_ASSERT(NUM_FLAGS == WABT_ARRAY_SIZE(s_options));
static ObjdumpOptions s_objdump_options;
-static FileWriter s_log_stream_writer;
-static Stream s_log_stream;
+
+static std::unique_ptr<FileStream> s_log_stream;
static void on_argument(struct OptionParser* parser, const char* argument) {
s_objdump_options.infile = argument;
@@ -88,9 +88,8 @@ static void on_option(struct OptionParser* parser,
case FLAG_DEBUG:
s_objdump_options.debug = true;
- init_file_writer_existing(&s_log_stream_writer, stdout);
- init_stream(&s_log_stream, &s_log_stream_writer.base, nullptr);
- s_objdump_options.log_stream = &s_log_stream;
+ s_log_stream = FileStream::CreateStdout();
+ s_objdump_options.log_stream = s_log_stream.get();
break;
case FLAG_DISASSEMBLE:
diff --git a/src/tools/wasmopcodecnt.cc b/src/tools/wasmopcodecnt.cc
index 89009aca..332bb442 100644
--- a/src/tools/wasmopcodecnt.cc
+++ b/src/tools/wasmopcodecnt.cc
@@ -43,8 +43,7 @@ static const char* s_separator = ": ";
static ReadBinaryOptions s_read_binary_options =
WABT_READ_BINARY_OPTIONS_DEFAULT;
-static FileWriter s_log_stream_writer;
-static Stream s_log_stream;
+static std::unique_ptr<FileStream> s_log_stream;
#define NOPE HasArgument::No
#define YEP HasArgument::Yes
@@ -85,9 +84,8 @@ static void on_option(struct OptionParser* parser,
switch (option->id) {
case FLAG_VERBOSE:
s_verbose++;
- init_file_writer_existing(&s_log_stream_writer, stdout);
- init_stream(&s_log_stream, &s_log_stream_writer.base, nullptr);
- s_read_binary_options.log_stream = &s_log_stream;
+ s_log_stream = FileStream::CreateStdout();
+ s_read_binary_options.log_stream = s_log_stream.get();
break;
case FLAG_HELP:
diff --git a/src/tools/wast-desugar.cc b/src/tools/wast-desugar.cc
index 74fbf0b2..51e12cb1 100644
--- a/src/tools/wast-desugar.cc
+++ b/src/tools/wast-desugar.cc
@@ -149,17 +149,8 @@ int main(int argc, char** argv) {
result = apply_names(module);
if (WABT_SUCCEEDED(result)) {
- FileWriter file_writer;
- if (s_outfile) {
- result = init_file_writer(&file_writer, s_outfile);
- } else {
- init_file_writer_existing(&file_writer, stdout);
- }
-
- if (WABT_SUCCEEDED(result)) {
- result = write_ast(&file_writer.base, module);
- close_file_writer(&file_writer);
- }
+ FileWriter writer(s_outfile ? FileWriter(s_outfile) : FileWriter(stdout));
+ result = write_ast(&writer, module);
}
}
diff --git a/src/tools/wast2wasm.cc b/src/tools/wast2wasm.cc
index 26248c6e..a9f0e9dc 100644
--- a/src/tools/wast2wasm.cc
+++ b/src/tools/wast2wasm.cc
@@ -50,7 +50,7 @@ static bool s_validate = true;
static SourceErrorHandler s_error_handler =
WABT_SOURCE_ERROR_HANDLER_DEFAULT;
-static FileStream s_log_stream;
+static std::unique_ptr<FileStream> s_log_stream;
#define NOPE HasArgument::No
#define YEP HasArgument::Yes
@@ -114,7 +114,8 @@ static void on_option(struct OptionParser* parser,
switch (option->id) {
case FLAG_VERBOSE:
s_verbose++;
- s_write_binary_options.log_stream = &s_log_stream.base;
+ s_log_stream = FileStream::CreateStdout();
+ s_write_binary_options.log_stream = s_log_stream.get();
break;
case FLAG_HELP:
@@ -179,22 +180,23 @@ static void parse_options(int argc, char** argv) {
}
static void write_buffer_to_file(const char* filename,
- OutputBuffer* buffer) {
+ const OutputBuffer& buffer) {
if (s_dump_module) {
if (s_verbose)
- writef(&s_log_stream.base, ";; dump\n");
- write_output_buffer_memory_dump(&s_log_stream.base, buffer);
+ s_log_stream->Writef(";; dump\n");
+ if (!buffer.data.empty()) {
+ s_log_stream->WriteMemoryDump(buffer.data.data(), buffer.data.size());
+ }
}
if (filename) {
- write_output_buffer_to_file(buffer, filename);
+ buffer.WriteToFile(filename);
}
}
int main(int argc, char** argv) {
init_stdio();
- init_file_stream_from_existing(&s_log_stream, stdout);
parse_options(argc, argv);
AstLexer* lexer = new_ast_file_lexer(s_infile);
@@ -219,21 +221,16 @@ int main(int argc, char** argv) {
&s_write_binary_spec_options);
} else {
MemoryWriter writer;
- WABT_ZERO_MEMORY(writer);
- if (WABT_FAILED(init_mem_writer(&writer)))
- WABT_FATAL("unable to open memory writer for writing\n");
-
Module* module = get_first_module(script);
if (module) {
- result = write_binary_module(&writer.base, module,
- &s_write_binary_options);
+ result =
+ write_binary_module(&writer, module, &s_write_binary_options);
} else {
WABT_FATAL("no module found\n");
}
if (WABT_SUCCEEDED(result))
- write_buffer_to_file(s_outfile, &writer.buf);
- close_mem_writer(&writer);
+ write_buffer_to_file(s_outfile, writer.output_buffer());
}
}
}
diff --git a/src/writer.cc b/src/writer.cc
index 8e24abc0..a408ff32 100644
--- a/src/writer.cc
+++ b/src/writer.cc
@@ -22,177 +22,136 @@
#include <stdio.h>
#include <stdlib.h>
+#include <utility>
+
#define ERROR0(msg) fprintf(stderr, "%s:%d: " msg, __FILE__, __LINE__)
#define ERROR(fmt, ...) \
fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__)
-#define INITIAL_OUTPUT_BUFFER_CAPACITY (64 * 1024)
-
namespace wabt {
-static Result write_data_to_file(size_t offset,
- const void* data,
- size_t size,
- void* user_data) {
- if (size == 0)
- return Result::Ok;
- FileWriter* writer = static_cast<FileWriter*>(user_data);
- if (offset != writer->offset) {
- if (fseek(writer->file, offset, SEEK_SET) != 0) {
- ERROR("fseek offset=%" PRIzd " failed, errno=%d\n", size, errno);
- return Result::Error;
- }
- writer->offset = offset;
- }
- if (fwrite(data, size, 1, writer->file) != 1) {
- ERROR("fwrite size=%" PRIzd " failed, errno=%d\n", size, errno);
+Result OutputBuffer::WriteToFile(const char* filename) const {
+ FILE* file = fopen(filename, "wb");
+ if (!file) {
+ ERROR("unable to open %s for writing\n", filename);
return Result::Error;
}
- writer->offset += size;
- return Result::Ok;
-}
-static Result move_data_in_file(size_t dst_offset,
- size_t src_offset,
- size_t size,
- void* user_data) {
- if (size == 0)
+ if (data.empty()) {
return Result::Ok;
- /* TODO(binji): implement if needed. */
- ERROR0("move_data_in_file not implemented!\n");
- return Result::Error;
-}
-
-void init_file_writer_existing(FileWriter* writer, FILE* file) {
- WABT_ZERO_MEMORY(*writer);
- writer->file = file;
- writer->offset = 0;
- writer->base.user_data = writer;
- writer->base.write_data = write_data_to_file;
- writer->base.move_data = move_data_in_file;
-}
+ }
-Result init_file_writer(FileWriter* writer, const char* filename) {
- FILE* file = fopen(filename, "wb");
- if (!file) {
- ERROR("fopen name=\"%s\" failed, errno=%d\n", filename, errno);
+ 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);
return Result::Error;
}
- init_file_writer_existing(writer, file);
+ fclose(file);
return Result::Ok;
}
-void close_file_writer(FileWriter* writer) {
- fclose(writer->file);
-}
+MemoryWriter::MemoryWriter() : buf_(new OutputBuffer()) {}
-void init_output_buffer(OutputBuffer* buf, size_t initial_capacity) {
- assert(initial_capacity != 0);
- buf->start = new char[initial_capacity]();
- buf->size = 0;
- buf->capacity = initial_capacity;
-}
+MemoryWriter::MemoryWriter(std::unique_ptr<OutputBuffer> buf)
+ : buf_(std::move(buf)) {}
-static void ensure_output_buffer_capacity(OutputBuffer* buf,
- size_t ensure_capacity) {
- if (ensure_capacity > buf->capacity) {
- assert(buf->capacity != 0);
- size_t new_capacity = buf->capacity * 2;
- while (new_capacity < ensure_capacity)
- new_capacity *= 2;
- char* new_data = new char [new_capacity];
- memcpy(new_data, buf->start, buf->capacity);
- memset(new_data + buf->capacity, 0, new_capacity - buf->capacity);
- delete [] buf->start;
- buf->start = new_data;
- buf->capacity = new_capacity;
- }
+std::unique_ptr<OutputBuffer> MemoryWriter::ReleaseOutputBuffer() {
+ return std::move(buf_);
}
-static Result write_data_to_output_buffer(size_t offset,
- const void* data,
- size_t size,
- void* user_data) {
- MemoryWriter* writer = static_cast<MemoryWriter*>(user_data);
- size_t end = offset + size;
- ensure_output_buffer_capacity(&writer->buf, end);
- memcpy(writer->buf.start + offset, data, size);
- if (end > writer->buf.size)
- writer->buf.size = end;
+Result MemoryWriter::WriteData(size_t dst_offset,
+ const void* src,
+ size_t size) {
+ 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;
}
-static Result move_data_in_output_buffer(size_t dst_offset,
- size_t src_offset,
- size_t size,
- void* user_data) {
- MemoryWriter* writer = static_cast<MemoryWriter*>(user_data);
+Result MemoryWriter::MoveData(size_t dst_offset,
+ size_t src_offset,
+ size_t size) {
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;
- ensure_output_buffer_capacity(&writer->buf, end);
- void* dst = reinterpret_cast<void*>(
- reinterpret_cast<size_t>(writer->buf.start) + dst_offset);
- void* src = reinterpret_cast<void*>(
- reinterpret_cast<size_t>(writer->buf.start) + src_offset);
+ 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);
- if (end > writer->buf.size)
- writer->buf.size = end;
return Result::Ok;
}
-Result init_mem_writer(MemoryWriter* writer) {
- WABT_ZERO_MEMORY(*writer);
- writer->base.user_data = writer;
- writer->base.write_data = write_data_to_output_buffer;
- writer->base.move_data = move_data_in_output_buffer;
- init_output_buffer(&writer->buf, INITIAL_OUTPUT_BUFFER_CAPACITY);
- return Result::Ok;
+FileWriter::FileWriter(FILE* file)
+ : file_(file), offset_(0), should_close_(false) {}
+
+FileWriter::FileWriter(const char* filename)
+ : file_(nullptr), offset_(0), should_close_(false) {
+ file_ = fopen(filename, "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, errno);
+ }
}
-Result init_mem_writer_existing(MemoryWriter* writer, OutputBuffer* buf) {
- WABT_ZERO_MEMORY(*writer);
- writer->base.user_data = writer;
- writer->base.write_data = write_data_to_output_buffer;
- writer->base.move_data = move_data_in_output_buffer;
- writer->buf = *buf;
- /* Clear buffer, since ownership has passed to the writer. */
- WABT_ZERO_MEMORY(*buf);
- return Result::Ok;
+FileWriter::FileWriter(FileWriter&& other) {
+ *this = std::move(other);
}
-void steal_mem_writer_output_buffer(MemoryWriter* writer,
- OutputBuffer* out_buf) {
- *out_buf = writer->buf;
- writer->buf.start = nullptr;
- writer->buf.size = 0;
- writer->buf.capacity = 0;
+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;
}
-void close_mem_writer(MemoryWriter* writer) {
- destroy_output_buffer(&writer->buf);
+FileWriter::~FileWriter() {
+ // We don't want to close existing files (stdout/sterr, for example).
+ if (should_close_) {
+ fclose(file_);
+ }
}
-Result write_output_buffer_to_file(OutputBuffer* buf, const char* filename) {
- FILE* file = fopen(filename, "wb");
- if (!file) {
- ERROR("unable to open %s for writing\n", filename);
+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;
}
-
- ssize_t bytes = fwrite(buf->start, 1, buf->size, file);
- if (bytes < 0 || static_cast<size_t>(bytes) != buf->size) {
- ERROR("failed to write %" PRIzd " bytes to %s\n", buf->size, filename);
+ if (fwrite(data, size, 1, file_) != 1) {
+ ERROR("fwrite size=%" PRIzd " failed, errno=%d\n", size, errno);
return Result::Error;
}
-
- fclose(file);
+ offset_ += size;
return Result::Ok;
}
-void destroy_output_buffer(OutputBuffer* buf) {
- delete[] buf->start;
+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
index 19d70948..ecb4aeb7 100644
--- a/src/writer.h
+++ b/src/writer.h
@@ -21,54 +21,61 @@
#include "common.h"
-namespace wabt {
+#include <memory>
+#include <vector>
-struct Writer {
- void* user_data;
- Result (*write_data)(size_t offset,
- const void* data,
- size_t size,
- void* user_data);
- Result (*move_data)(size_t dst_offset,
- size_t src_offset,
- size_t size,
- void* user_data);
-};
+namespace wabt {
struct OutputBuffer {
- char* start;
- size_t size;
- size_t capacity;
+ Result WriteToFile(const char* filename) const;
+
+ std::vector<uint8_t> data;
};
-struct MemoryWriter {
- Writer base;
- OutputBuffer buf;
+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;
};
-struct FileWriter {
- Writer base;
- FILE* file;
- size_t offset;
+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_;
};
-/* FileWriter */
-Result init_file_writer(FileWriter* writer, const char* filename);
-void init_file_writer_existing(FileWriter* writer, FILE* file);
-void close_file_writer(FileWriter* writer);
-
-/* MemoryWriter */
-Result init_mem_writer(MemoryWriter* writer);
-/* Passes ownership of the buffer to writer */
-Result init_mem_writer_existing(MemoryWriter* writer, OutputBuffer* buf);
-void steal_mem_writer_output_buffer(MemoryWriter* writer,
- OutputBuffer* out_buf);
-void close_mem_writer(MemoryWriter* writer);
-
-/* OutputBuffer */
-void init_output_buffer(OutputBuffer* buf, size_t initial_capacity);
-Result write_output_buffer_to_file(OutputBuffer* buf, const char* filename);
-void destroy_output_buffer(OutputBuffer* buf);
+class FileWriter : public Writer {
+ WABT_DISALLOW_COPY_AND_ASSIGN(FileWriter);
+
+ public:
+ explicit FileWriter(const char* 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