diff options
Diffstat (limited to 'src/ast-writer.cc')
-rw-r--r-- | src/ast-writer.cc | 706 |
1 files changed, 370 insertions, 336 deletions
diff --git a/src/ast-writer.cc b/src/ast-writer.cc index d7ec12e4..306da811 100644 --- a/src/ast-writer.cc +++ b/src/ast-writer.cc @@ -58,302 +58,339 @@ enum class NextChar { ForceNewline, }; -struct Context { - explicit Context(Writer* writer) : stream(writer) {} - - Stream stream; - Result result = Result::Ok; - int indent = 0; - NextChar next_char = NextChar::None; - int depth = 0; - std::vector<std::string> index_to_name; - - int func_index = 0; - int global_index = 0; - int export_index = 0; - int table_index = 0; - int memory_index = 0; - int func_type_index = 0; +class ASTWriter { + public: + ASTWriter(Writer* writer) : stream_(writer) {} + + Result WriteModule(const Module* module); + + private: + void Indent(); + void Dedent(); + void WriteIndent(); + void WriteNextChar(); + void WriteDataWithNextChar(const void* src, size_t size); + void Writef(const char* format, ...); + void WritePutc(char c); + void WritePuts(const char* s, NextChar next_char); + void WritePutsSpace(const char* s); + void WritePutsNewline(const char* s); + void WriteNewline(bool force); + void WriteOpen(const char* name, NextChar next_char); + void WriteOpenNewline(const char* name); + void WriteOpenSpace(const char* name); + void WriteClose(NextChar next_char); + void WriteCloseNewline(); + void WriteCloseSpace(); + void WriteString(const std::string& str, NextChar next_char); + void WriteStringSlice(const StringSlice* str, NextChar next_char); + bool WriteStringSliceOpt(const StringSlice* str, NextChar next_char); + void WriteStringSliceOrIndex(const StringSlice* str, + uint32_t index, + NextChar next_char); + void WriteQuotedData(const void* data, size_t length); + void WriteQuotedStringSlice(const StringSlice* str, NextChar next_char); + void WriteVar(const Var* var, NextChar next_char); + void WriteBrVar(const Var* var, NextChar next_char); + void WriteType(Type type, NextChar next_char); + void WriteTypes(const TypeVector& types, const char* name); + void WriteFuncSigSpace(const FuncSignature* func_sig); + void WriteBeginBlock(const Block* block, const char* text); + void WriteEndBlock(); + void WriteBlock(const Block* block, const char* start_text); + void WriteConst(const Const* const_); + void WriteExpr(const Expr* expr); + void WriteExprList(const Expr* first); + void WriteInitExpr(const Expr* expr); + void WriteTypeBindings(const char* prefix, + const Func* func, + const TypeVector& types, + const BindingHash& bindings); + void WriteFunc(const Module* module, const Func* func); + void WriteBeginGlobal(const Global* global); + void WriteGlobal(const Global* global); + void WriteLimits(const Limits* limits); + void WriteTable(const Table* table); + void WriteElemSegment(const ElemSegment* segment); + void WriteMemory(const Memory* memory); + void WriteDataSegment(const DataSegment* segment); + void WriteImport(const Import* import); + void WriteExport(const Export* export_); + void WriteFuncType(const FuncType* func_type); + void WriteStartFunction(const Var* start); + + Stream stream_; + Result result_ = Result::Ok; + int indent_ = 0; + NextChar next_char_ = NextChar::None; + int depth_ = 0; + std::vector<std::string> index_to_name_; + + int func_index_ = 0; + int global_index_ = 0; + int table_index_ = 0; + int memory_index_ = 0; + int func_type_index_ = 0; }; } // namespace -static void indent(Context* ctx) { - ctx->indent += INDENT_SIZE; +void ASTWriter::Indent() { + indent_ += INDENT_SIZE; } -static void dedent(Context* ctx) { - ctx->indent -= INDENT_SIZE; - assert(ctx->indent >= 0); +void ASTWriter::Dedent() { + indent_ -= INDENT_SIZE; + assert(indent_ >= 0); } -static void write_indent(Context* ctx) { +void ASTWriter::WriteIndent() { static char s_indent[] = " " " "; static size_t s_indent_len = sizeof(s_indent) - 1; - size_t indent = ctx->indent; - while (indent > s_indent_len) { - ctx->stream.WriteData(s_indent, s_indent_len); + size_t indent = indent_; + while (static_cast<size_t>(indent_) > s_indent_len) { + stream_.WriteData(s_indent, s_indent_len); indent -= s_indent_len; } if (indent > 0) { - ctx->stream.WriteData(s_indent, indent); + stream_.WriteData(s_indent, indent); } } -static void write_next_char(Context* ctx) { - switch (ctx->next_char) { +void ASTWriter::WriteNextChar() { + switch (next_char_) { case NextChar::Space: - ctx->stream.WriteChar(' '); + stream_.WriteChar(' '); break; case NextChar::Newline: case NextChar::ForceNewline: - ctx->stream.WriteChar('\n'); - write_indent(ctx); + stream_.WriteChar('\n'); + WriteIndent(); break; default: case NextChar::None: break; } - ctx->next_char = NextChar::None; + next_char_ = NextChar::None; } -static void write_data_with_next_char(Context* ctx, - const void* src, - size_t size) { - write_next_char(ctx); - ctx->stream.WriteData(src, size); +void ASTWriter::WriteDataWithNextChar(const void* src, size_t size) { + WriteNextChar(); + stream_.WriteData(src, size); } -static void WABT_PRINTF_FORMAT(2, 3) - writef(Context* ctx, const char* format, ...) { +void WABT_PRINTF_FORMAT(2, 3) ASTWriter::Writef(const char* format, ...) { WABT_SNPRINTF_ALLOCA(buffer, length, format); /* default to following space */ - write_data_with_next_char(ctx, buffer, length); - ctx->next_char = NextChar::Space; + WriteDataWithNextChar(buffer, length); + next_char_ = NextChar::Space; } -static void write_putc(Context* ctx, char c) { - ctx->stream.WriteChar(c); +void ASTWriter::WritePutc(char c) { + stream_.WriteChar(c); } -static void write_puts(Context* ctx, const char* s, NextChar next_char) { +void ASTWriter::WritePuts(const char* s, NextChar next_char) { size_t len = strlen(s); - write_data_with_next_char(ctx, s, len); - ctx->next_char = next_char; + WriteDataWithNextChar(s, len); + next_char_ = next_char; } -static void write_puts_space(Context* ctx, const char* s) { - write_puts(ctx, s, NextChar::Space); +void ASTWriter::WritePutsSpace(const char* s) { + WritePuts(s, NextChar::Space); } -static void write_puts_newline(Context* ctx, const char* s) { - write_puts(ctx, s, NextChar::Newline); +void ASTWriter::WritePutsNewline(const char* s) { + WritePuts(s, NextChar::Newline); } -static void write_newline(Context* ctx, bool force) { - if (ctx->next_char == NextChar::ForceNewline) - write_next_char(ctx); - ctx->next_char = force ? NextChar::ForceNewline : NextChar::Newline; +void ASTWriter::WriteNewline(bool force) { + if (next_char_ == NextChar::ForceNewline) + WriteNextChar(); + next_char_ = force ? NextChar::ForceNewline : NextChar::Newline; } -static void write_open(Context* ctx, const char* name, NextChar next_char) { - write_puts(ctx, "(", NextChar::None); - write_puts(ctx, name, next_char); - indent(ctx); +void ASTWriter::WriteOpen(const char* name, NextChar next_char) { + WritePuts("(", NextChar::None); + WritePuts(name, next_char); + Indent(); } -static void write_open_newline(Context* ctx, const char* name) { - write_open(ctx, name, NextChar::Newline); +void ASTWriter::WriteOpenNewline(const char* name) { + WriteOpen(name, NextChar::Newline); } -static void write_open_space(Context* ctx, const char* name) { - write_open(ctx, name, NextChar::Space); +void ASTWriter::WriteOpenSpace(const char* name) { + WriteOpen(name, NextChar::Space); } -static void write_close(Context* ctx, NextChar next_char) { - if (ctx->next_char != NextChar::ForceNewline) - ctx->next_char = NextChar::None; - dedent(ctx); - write_puts(ctx, ")", next_char); +void ASTWriter::WriteClose(NextChar next_char) { + if (next_char_ != NextChar::ForceNewline) + next_char_ = NextChar::None; + Dedent(); + WritePuts(")", next_char); } -static void write_close_newline(Context* ctx) { - write_close(ctx, NextChar::Newline); +void ASTWriter::WriteCloseNewline() { + WriteClose(NextChar::Newline); } -static void write_close_space(Context* ctx) { - write_close(ctx, NextChar::Space); +void ASTWriter::WriteCloseSpace() { + WriteClose(NextChar::Space); } -static void write_string(Context* ctx, - const std::string& str, - NextChar next_char) { - write_puts(ctx, str.c_str(), next_char); +void ASTWriter::WriteString(const std::string& str, NextChar next_char) { + WritePuts(str.c_str(), next_char); } -static void write_string_slice(Context* ctx, - const StringSlice* str, - NextChar next_char) { - writef(ctx, PRIstringslice, WABT_PRINTF_STRING_SLICE_ARG(*str)); - ctx->next_char = next_char; +void ASTWriter::WriteStringSlice(const StringSlice* str, NextChar next_char) { + Writef(PRIstringslice, WABT_PRINTF_STRING_SLICE_ARG(*str)); + next_char_ = next_char; } -static bool write_string_slice_opt(Context* ctx, - const StringSlice* str, - NextChar next_char) { +bool ASTWriter::WriteStringSliceOpt(const StringSlice* str, + NextChar next_char) { if (str->start) - write_string_slice(ctx, str, next_char); + WriteStringSlice(str, next_char); return !!str->start; } -static void write_string_slice_or_index(Context* ctx, - const StringSlice* str, +void ASTWriter::WriteStringSliceOrIndex(const StringSlice* str, uint32_t index, NextChar next_char) { if (str->start) - write_string_slice(ctx, str, next_char); + WriteStringSlice(str, next_char); else - writef(ctx, "(;%u;)", index); + Writef("(;%u;)", index); } -static void write_quoted_data(Context* ctx, const void* data, size_t length) { +void ASTWriter::WriteQuotedData(const void* data, size_t length) { const uint8_t* u8_data = static_cast<const uint8_t*>(data); static const char s_hexdigits[] = "0123456789abcdef"; - write_next_char(ctx); - write_putc(ctx, '\"'); + WriteNextChar(); + WritePutc('\"'); for (size_t i = 0; i < length; ++i) { uint8_t c = u8_data[i]; if (s_is_char_escaped[c]) { - write_putc(ctx, '\\'); - write_putc(ctx, s_hexdigits[c >> 4]); - write_putc(ctx, s_hexdigits[c & 0xf]); + WritePutc('\\'); + WritePutc(s_hexdigits[c >> 4]); + WritePutc(s_hexdigits[c & 0xf]); } else { - write_putc(ctx, c); + WritePutc(c); } } - write_putc(ctx, '\"'); - ctx->next_char = NextChar::Space; + WritePutc('\"'); + next_char_ = NextChar::Space; } -static void write_quoted_string_slice(Context* ctx, - const StringSlice* str, - NextChar next_char) { - write_quoted_data(ctx, str->start, str->length); - ctx->next_char = next_char; +void ASTWriter::WriteQuotedStringSlice(const StringSlice* str, + NextChar next_char) { + WriteQuotedData(str->start, str->length); + next_char_ = next_char; } -static void write_var(Context* ctx, const Var* var, NextChar next_char) { +void ASTWriter::WriteVar(const Var* var, NextChar next_char) { if (var->type == VarType::Index) { - writef(ctx, "%" PRId64, var->index); - ctx->next_char = next_char; + Writef("%" PRId64, var->index); + next_char_ = next_char; } else { - write_string_slice(ctx, &var->name, next_char); + WriteStringSlice(&var->name, next_char); } } -static void write_br_var(Context* ctx, const Var* var, NextChar next_char) { +void ASTWriter::WriteBrVar(const Var* var, NextChar next_char) { if (var->type == VarType::Index) { - writef(ctx, "%" PRId64 " (;@%" PRId64 ";)", var->index, - ctx->depth - var->index - 1); - ctx->next_char = next_char; + Writef("%" PRId64 " (;@%" PRId64 ";)", var->index, + depth_ - var->index - 1); + next_char_ = next_char; } else { - write_string_slice(ctx, &var->name, next_char); + WriteStringSlice(&var->name, next_char); } } -static void write_type(Context* ctx, Type type, NextChar next_char) { +void ASTWriter::WriteType(Type type, NextChar next_char) { const char* type_name = get_type_name(type); assert(type_name); - write_puts(ctx, type_name, next_char); + WritePuts(type_name, next_char); } -static void write_types(Context* ctx, - const TypeVector& types, - const char* name) { +void ASTWriter::WriteTypes(const TypeVector& types, const char* name) { if (types.size()) { if (name) - write_open_space(ctx, name); + WriteOpenSpace(name); for (Type type: types) - write_type(ctx, type, NextChar::Space); + WriteType(type, NextChar::Space); if (name) - write_close_space(ctx); + WriteCloseSpace(); } } -static void write_func_sig_space(Context* ctx, const FuncSignature* func_sig) { - write_types(ctx, func_sig->param_types, "param"); - write_types(ctx, func_sig->result_types, "result"); +void ASTWriter::WriteFuncSigSpace(const FuncSignature* func_sig) { + WriteTypes(func_sig->param_types, "param"); + WriteTypes(func_sig->result_types, "result"); } -static void write_expr_list(Context* ctx, const Expr* first); - -static void write_expr(Context* ctx, const Expr* expr); - -static void write_begin_block(Context* ctx, - const Block* block, - const char* text) { - write_puts_space(ctx, text); - bool has_label = write_string_slice_opt(ctx, &block->label, NextChar::Space); - write_types(ctx, block->sig, nullptr); +void ASTWriter::WriteBeginBlock(const Block* block, const char* text) { + WritePutsSpace(text); + bool has_label = WriteStringSliceOpt(&block->label, NextChar::Space); + WriteTypes(block->sig, nullptr); if (!has_label) - writef(ctx, " ;; label = @%d", ctx->depth); - write_newline(ctx, FORCE_NEWLINE); - ctx->depth++; - indent(ctx); + Writef(" ;; label = @%d", depth_); + WriteNewline(FORCE_NEWLINE); + depth_++; + Indent(); } -static void write_end_block(Context* ctx) { - dedent(ctx); - ctx->depth--; - write_puts_newline(ctx, get_opcode_name(Opcode::End)); +void ASTWriter::WriteEndBlock() { + Dedent(); + depth_--; + WritePutsNewline(get_opcode_name(Opcode::End)); } -static void write_block(Context* ctx, - const Block* block, - const char* start_text) { - write_begin_block(ctx, block, start_text); - write_expr_list(ctx, block->first); - write_end_block(ctx); +void ASTWriter::WriteBlock(const Block* block, const char* start_text) { + WriteBeginBlock(block, start_text); + WriteExprList(block->first); + WriteEndBlock(); } -static void write_const(Context* ctx, const Const* const_) { +void ASTWriter::WriteConst(const Const* const_) { switch (const_->type) { case Type::I32: - write_puts_space(ctx, get_opcode_name(Opcode::I32Const)); - writef(ctx, "%d", static_cast<int32_t>(const_->u32)); - write_newline(ctx, NO_FORCE_NEWLINE); + WritePutsSpace(get_opcode_name(Opcode::I32Const)); + Writef("%d", static_cast<int32_t>(const_->u32)); + WriteNewline(NO_FORCE_NEWLINE); break; case Type::I64: - write_puts_space(ctx, get_opcode_name(Opcode::I64Const)); - writef(ctx, "%" PRId64, static_cast<int64_t>(const_->u64)); - write_newline(ctx, NO_FORCE_NEWLINE); + WritePutsSpace(get_opcode_name(Opcode::I64Const)); + Writef("%" PRId64, static_cast<int64_t>(const_->u64)); + WriteNewline(NO_FORCE_NEWLINE); break; case Type::F32: { - write_puts_space(ctx, get_opcode_name(Opcode::F32Const)); + WritePutsSpace(get_opcode_name(Opcode::F32Const)); char buffer[128]; write_float_hex(buffer, 128, const_->f32_bits); - write_puts_space(ctx, buffer); + WritePutsSpace(buffer); float f32; memcpy(&f32, &const_->f32_bits, sizeof(f32)); - writef(ctx, "(;=%g;)", f32); - write_newline(ctx, NO_FORCE_NEWLINE); + Writef("(;=%g;)", f32); + WriteNewline(NO_FORCE_NEWLINE); break; } case Type::F64: { - write_puts_space(ctx, get_opcode_name(Opcode::F64Const)); + WritePutsSpace(get_opcode_name(Opcode::F64Const)); char buffer[128]; write_double_hex(buffer, 128, const_->f64_bits); - write_puts_space(ctx, buffer); + WritePutsSpace(buffer); double f64; memcpy(&f64, &const_->f64_bits, sizeof(f64)); - writef(ctx, "(;=%g;)", f64); - write_newline(ctx, NO_FORCE_NEWLINE); + Writef("(;=%g;)", f64); + WriteNewline(NO_FORCE_NEWLINE); break; } @@ -363,146 +400,146 @@ static void write_const(Context* ctx, const Const* const_) { } } -static void write_expr(Context* ctx, const Expr* expr) { +void ASTWriter::WriteExpr(const Expr* expr) { switch (expr->type) { case ExprType::Binary: - write_puts_newline(ctx, get_opcode_name(expr->binary.opcode)); + WritePutsNewline(get_opcode_name(expr->binary.opcode)); break; case ExprType::Block: - write_block(ctx, expr->block, get_opcode_name(Opcode::Block)); + WriteBlock(expr->block, get_opcode_name(Opcode::Block)); break; case ExprType::Br: - write_puts_space(ctx, get_opcode_name(Opcode::Br)); - write_br_var(ctx, &expr->br.var, NextChar::Newline); + WritePutsSpace(get_opcode_name(Opcode::Br)); + WriteBrVar(&expr->br.var, NextChar::Newline); break; case ExprType::BrIf: - write_puts_space(ctx, get_opcode_name(Opcode::BrIf)); - write_br_var(ctx, &expr->br_if.var, NextChar::Newline); + WritePutsSpace(get_opcode_name(Opcode::BrIf)); + WriteBrVar(&expr->br_if.var, NextChar::Newline); break; case ExprType::BrTable: { - write_puts_space(ctx, get_opcode_name(Opcode::BrTable)); + WritePutsSpace(get_opcode_name(Opcode::BrTable)); for (const Var& var : *expr->br_table.targets) - write_br_var(ctx, &var, NextChar::Space); - write_br_var(ctx, &expr->br_table.default_target, NextChar::Newline); + WriteBrVar(&var, NextChar::Space); + WriteBrVar(&expr->br_table.default_target, NextChar::Newline); break; } case ExprType::Call: - write_puts_space(ctx, get_opcode_name(Opcode::Call)); - write_var(ctx, &expr->call.var, NextChar::Newline); + WritePutsSpace(get_opcode_name(Opcode::Call)); + WriteVar(&expr->call.var, NextChar::Newline); break; case ExprType::CallIndirect: - write_puts_space(ctx, get_opcode_name(Opcode::CallIndirect)); - write_var(ctx, &expr->call_indirect.var, NextChar::Newline); + WritePutsSpace(get_opcode_name(Opcode::CallIndirect)); + WriteVar(&expr->call_indirect.var, NextChar::Newline); break; case ExprType::Compare: - write_puts_newline(ctx, get_opcode_name(expr->compare.opcode)); + WritePutsNewline(get_opcode_name(expr->compare.opcode)); break; case ExprType::Const: - write_const(ctx, &expr->const_); + WriteConst(&expr->const_); break; case ExprType::Convert: - write_puts_newline(ctx, get_opcode_name(expr->convert.opcode)); + WritePutsNewline(get_opcode_name(expr->convert.opcode)); break; case ExprType::Drop: - write_puts_newline(ctx, get_opcode_name(Opcode::Drop)); + WritePutsNewline(get_opcode_name(Opcode::Drop)); break; case ExprType::GetGlobal: - write_puts_space(ctx, get_opcode_name(Opcode::GetGlobal)); - write_var(ctx, &expr->get_global.var, NextChar::Newline); + WritePutsSpace(get_opcode_name(Opcode::GetGlobal)); + WriteVar(&expr->get_global.var, NextChar::Newline); break; case ExprType::GetLocal: - write_puts_space(ctx, get_opcode_name(Opcode::GetLocal)); - write_var(ctx, &expr->get_local.var, NextChar::Newline); + WritePutsSpace(get_opcode_name(Opcode::GetLocal)); + WriteVar(&expr->get_local.var, NextChar::Newline); break; case ExprType::GrowMemory: - write_puts_newline(ctx, get_opcode_name(Opcode::GrowMemory)); + WritePutsNewline(get_opcode_name(Opcode::GrowMemory)); break; case ExprType::If: - write_begin_block(ctx, expr->if_.true_, get_opcode_name(Opcode::If)); - write_expr_list(ctx, expr->if_.true_->first); + WriteBeginBlock(expr->if_.true_, get_opcode_name(Opcode::If)); + WriteExprList(expr->if_.true_->first); if (expr->if_.false_) { - dedent(ctx); - write_puts_space(ctx, get_opcode_name(Opcode::Else)); - indent(ctx); - write_newline(ctx, FORCE_NEWLINE); - write_expr_list(ctx, expr->if_.false_); + Dedent(); + WritePutsSpace(get_opcode_name(Opcode::Else)); + Indent(); + WriteNewline(FORCE_NEWLINE); + WriteExprList(expr->if_.false_); } - write_end_block(ctx); + WriteEndBlock(); break; case ExprType::Load: - write_puts_space(ctx, get_opcode_name(expr->load.opcode)); + WritePutsSpace(get_opcode_name(expr->load.opcode)); if (expr->load.offset) - writef(ctx, "offset=%" PRIu64, expr->load.offset); + Writef("offset=%" PRIu64, expr->load.offset); if (!is_naturally_aligned(expr->load.opcode, expr->load.align)) - writef(ctx, "align=%u", expr->load.align); - write_newline(ctx, NO_FORCE_NEWLINE); + Writef("align=%u", expr->load.align); + WriteNewline(NO_FORCE_NEWLINE); break; case ExprType::Loop: - write_block(ctx, expr->loop, get_opcode_name(Opcode::Loop)); + WriteBlock(expr->loop, get_opcode_name(Opcode::Loop)); break; case ExprType::CurrentMemory: - write_puts_newline(ctx, get_opcode_name(Opcode::CurrentMemory)); + WritePutsNewline(get_opcode_name(Opcode::CurrentMemory)); break; case ExprType::Nop: - write_puts_newline(ctx, get_opcode_name(Opcode::Nop)); + WritePutsNewline(get_opcode_name(Opcode::Nop)); break; case ExprType::Return: - write_puts_newline(ctx, get_opcode_name(Opcode::Return)); + WritePutsNewline(get_opcode_name(Opcode::Return)); break; case ExprType::Select: - write_puts_newline(ctx, get_opcode_name(Opcode::Select)); + WritePutsNewline(get_opcode_name(Opcode::Select)); break; case ExprType::SetGlobal: - write_puts_space(ctx, get_opcode_name(Opcode::SetGlobal)); - write_var(ctx, &expr->set_global.var, NextChar::Newline); + WritePutsSpace(get_opcode_name(Opcode::SetGlobal)); + WriteVar(&expr->set_global.var, NextChar::Newline); break; case ExprType::SetLocal: - write_puts_space(ctx, get_opcode_name(Opcode::SetLocal)); - write_var(ctx, &expr->set_local.var, NextChar::Newline); + WritePutsSpace(get_opcode_name(Opcode::SetLocal)); + WriteVar(&expr->set_local.var, NextChar::Newline); break; case ExprType::Store: - write_puts_space(ctx, get_opcode_name(expr->store.opcode)); + WritePutsSpace(get_opcode_name(expr->store.opcode)); if (expr->store.offset) - writef(ctx, "offset=%" PRIu64, expr->store.offset); + Writef("offset=%" PRIu64, expr->store.offset); if (!is_naturally_aligned(expr->store.opcode, expr->store.align)) - writef(ctx, "align=%u", expr->store.align); - write_newline(ctx, NO_FORCE_NEWLINE); + Writef("align=%u", expr->store.align); + WriteNewline(NO_FORCE_NEWLINE); break; case ExprType::TeeLocal: - write_puts_space(ctx, get_opcode_name(Opcode::TeeLocal)); - write_var(ctx, &expr->tee_local.var, NextChar::Newline); + WritePutsSpace(get_opcode_name(Opcode::TeeLocal)); + WriteVar(&expr->tee_local.var, NextChar::Newline); break; case ExprType::Unary: - write_puts_newline(ctx, get_opcode_name(expr->unary.opcode)); + WritePutsNewline(get_opcode_name(expr->unary.opcode)); break; case ExprType::Unreachable: - write_puts_newline(ctx, get_opcode_name(Opcode::Unreachable)); + WritePutsNewline(get_opcode_name(Opcode::Unreachable)); break; default: @@ -512,27 +549,26 @@ static void write_expr(Context* ctx, const Expr* expr) { } } -static void write_expr_list(Context* ctx, const Expr* first) { +void ASTWriter::WriteExprList(const Expr* first) { for (const Expr* expr = first; expr; expr = expr->next) - write_expr(ctx, expr); + WriteExpr(expr); } -static void write_init_expr(Context* ctx, const Expr* expr) { +void ASTWriter::WriteInitExpr(const Expr* expr) { if (expr) { - write_puts(ctx, "(", NextChar::None); - write_expr(ctx, expr); + WritePuts("(", NextChar::None); + WriteExpr(expr); /* clear the next char, so we don't write a newline after the expr */ - ctx->next_char = NextChar::None; - write_puts(ctx, ")", NextChar::Space); + next_char_ = NextChar::None; + WritePuts(")", NextChar::Space); } } -static void write_type_bindings(Context* ctx, - const char* prefix, - const Func* func, - const TypeVector& types, - const BindingHash& bindings) { - make_type_binding_reverse_mapping(types, bindings, &ctx->index_to_name); +void ASTWriter::WriteTypeBindings(const char* prefix, + const Func* func, + const TypeVector& types, + const BindingHash& bindings) { + make_type_binding_reverse_mapping(types, bindings, &index_to_name_); /* named params/locals must be specified by themselves, but nameless * params/locals can be compressed, e.g.: @@ -542,212 +578,210 @@ static void write_type_bindings(Context* ctx, bool is_open = false; for (size_t i = 0; i < types.size(); ++i) { if (!is_open) { - write_open_space(ctx, prefix); + WriteOpenSpace(prefix); is_open = true; } - const std::string& name = ctx->index_to_name[i]; + const std::string& name = index_to_name_[i]; if (!name.empty()) - write_string(ctx, name, NextChar::Space); - write_type(ctx, types[i], NextChar::Space); + WriteString(name, NextChar::Space); + WriteType(types[i], NextChar::Space); if (!name.empty()) { - write_close_space(ctx); + WriteCloseSpace(); is_open = false; } } if (is_open) - write_close_space(ctx); + WriteCloseSpace(); } -static void write_func(Context* ctx, const Module* module, const Func* func) { - write_open_space(ctx, "func"); - write_string_slice_or_index(ctx, &func->name, ctx->func_index++, - NextChar::Space); +void ASTWriter::WriteFunc(const Module* module, const Func* func) { + WriteOpenSpace("func"); + WriteStringSliceOrIndex(&func->name, func_index_++, NextChar::Space); if (decl_has_func_type(&func->decl)) { - write_open_space(ctx, "type"); - write_var(ctx, &func->decl.type_var, NextChar::None); - write_close_space(ctx); + WriteOpenSpace("type"); + WriteVar(&func->decl.type_var, NextChar::None); + WriteCloseSpace(); } - write_type_bindings(ctx, "param", func, func->decl.sig.param_types, - func->param_bindings); - write_types(ctx, func->decl.sig.result_types, "result"); - write_newline(ctx, NO_FORCE_NEWLINE); + WriteTypeBindings("param", func, func->decl.sig.param_types, + func->param_bindings); + WriteTypes(func->decl.sig.result_types, "result"); + WriteNewline(NO_FORCE_NEWLINE); if (func->local_types.size()) { - write_type_bindings(ctx, "local", func, func->local_types, - func->local_bindings); + WriteTypeBindings("local", func, func->local_types, func->local_bindings); } - write_newline(ctx, NO_FORCE_NEWLINE); - ctx->depth = 1; /* for the implicit "return" label */ - write_expr_list(ctx, func->first_expr); - write_close_newline(ctx); + WriteNewline(NO_FORCE_NEWLINE); + depth_ = 1; /* for the implicit "return" label */ + WriteExprList(func->first_expr); + WriteCloseNewline(); } -static void write_begin_global(Context* ctx, const Global* global) { - write_open_space(ctx, "global"); - write_string_slice_or_index(ctx, &global->name, ctx->global_index++, +void ASTWriter::WriteBeginGlobal(const Global* global) { + WriteOpenSpace("global"); + WriteStringSliceOrIndex(&global->name, global_index_++, NextChar::Space); if (global->mutable_) { - write_open_space(ctx, "mut"); - write_type(ctx, global->type, NextChar::Space); - write_close_space(ctx); + WriteOpenSpace("mut"); + WriteType(global->type, NextChar::Space); + WriteCloseSpace(); } else { - write_type(ctx, global->type, NextChar::Space); + WriteType(global->type, NextChar::Space); } } -static void write_global(Context* ctx, const Global* global) { - write_begin_global(ctx, global); - write_init_expr(ctx, global->init_expr); - write_close_newline(ctx); +void ASTWriter::WriteGlobal(const Global* global) { + WriteBeginGlobal(global); + WriteInitExpr(global->init_expr); + WriteCloseNewline(); } -static void write_limits(Context* ctx, const Limits* limits) { - writef(ctx, "%" PRIu64, limits->initial); +void ASTWriter::WriteLimits(const Limits* limits) { + Writef("%" PRIu64, limits->initial); if (limits->has_max) - writef(ctx, "%" PRIu64, limits->max); + Writef("%" PRIu64, limits->max); } -static void write_table(Context* ctx, const Table* table) { - write_open_space(ctx, "table"); - write_string_slice_or_index(ctx, &table->name, ctx->table_index++, +void ASTWriter::WriteTable(const Table* table) { + WriteOpenSpace("table"); + WriteStringSliceOrIndex(&table->name, table_index_++, NextChar::Space); - write_limits(ctx, &table->elem_limits); - write_puts_space(ctx, "anyfunc"); - write_close_newline(ctx); + WriteLimits(&table->elem_limits); + WritePutsSpace("anyfunc"); + WriteCloseNewline(); } -static void write_elem_segment(Context* ctx, const ElemSegment* segment) { - write_open_space(ctx, "elem"); - write_init_expr(ctx, segment->offset); +void ASTWriter::WriteElemSegment(const ElemSegment* segment) { + WriteOpenSpace("elem"); + WriteInitExpr(segment->offset); for (const Var& var : segment->vars) - write_var(ctx, &var, NextChar::Space); - write_close_newline(ctx); + WriteVar(&var, NextChar::Space); + WriteCloseNewline(); } -static void write_memory(Context* ctx, const Memory* memory) { - write_open_space(ctx, "memory"); - write_string_slice_or_index(ctx, &memory->name, ctx->memory_index++, +void ASTWriter::WriteMemory(const Memory* memory) { + WriteOpenSpace("memory"); + WriteStringSliceOrIndex(&memory->name, memory_index_++, NextChar::Space); - write_limits(ctx, &memory->page_limits); - write_close_newline(ctx); + WriteLimits(&memory->page_limits); + WriteCloseNewline(); } -static void write_data_segment(Context* ctx, const DataSegment* segment) { - write_open_space(ctx, "data"); - write_init_expr(ctx, segment->offset); - write_quoted_data(ctx, segment->data, segment->size); - write_close_newline(ctx); +void ASTWriter::WriteDataSegment(const DataSegment* segment) { + WriteOpenSpace("data"); + WriteInitExpr(segment->offset); + WriteQuotedData(segment->data, segment->size); + WriteCloseNewline(); } -static void write_import(Context* ctx, const Import* import) { - write_open_space(ctx, "import"); - write_quoted_string_slice(ctx, &import->module_name, NextChar::Space); - write_quoted_string_slice(ctx, &import->field_name, NextChar::Space); +void ASTWriter::WriteImport(const Import* import) { + WriteOpenSpace("import"); + WriteQuotedStringSlice(&import->module_name, NextChar::Space); + WriteQuotedStringSlice(&import->field_name, NextChar::Space); switch (import->kind) { case ExternalKind::Func: - write_open_space(ctx, "func"); - write_string_slice_or_index(ctx, &import->func->name, ctx->func_index++, + WriteOpenSpace("func"); + WriteStringSliceOrIndex(&import->func->name, func_index_++, NextChar::Space); if (decl_has_func_type(&import->func->decl)) { - write_open_space(ctx, "type"); - write_var(ctx, &import->func->decl.type_var, NextChar::None); - write_close_space(ctx); + WriteOpenSpace("type"); + WriteVar(&import->func->decl.type_var, NextChar::None); + WriteCloseSpace(); } else { - write_func_sig_space(ctx, &import->func->decl.sig); + WriteFuncSigSpace(&import->func->decl.sig); } - write_close_space(ctx); + WriteCloseSpace(); break; case ExternalKind::Table: - write_table(ctx, import->table); + WriteTable(import->table); break; case ExternalKind::Memory: - write_memory(ctx, import->memory); + WriteMemory(import->memory); break; case ExternalKind::Global: - write_begin_global(ctx, import->global); - write_close_space(ctx); + WriteBeginGlobal(import->global); + WriteCloseSpace(); break; } - write_close_newline(ctx); + WriteCloseNewline(); } -static void write_export(Context* ctx, const Export* export_) { +void ASTWriter::WriteExport(const Export* export_) { static const char* s_kind_names[] = {"func", "table", "memory", "global"}; WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(s_kind_names) == kExternalKindCount); - write_open_space(ctx, "export"); - write_quoted_string_slice(ctx, &export_->name, NextChar::Space); + WriteOpenSpace("export"); + WriteQuotedStringSlice(&export_->name, NextChar::Space); assert(static_cast<size_t>(export_->kind) < WABT_ARRAY_SIZE(s_kind_names)); - write_open_space(ctx, s_kind_names[static_cast<size_t>(export_->kind)]); - write_var(ctx, &export_->var, NextChar::Space); - write_close_space(ctx); - write_close_newline(ctx); + WriteOpenSpace(s_kind_names[static_cast<size_t>(export_->kind)]); + WriteVar(&export_->var, NextChar::Space); + WriteCloseSpace(); + WriteCloseNewline(); } -static void write_func_type(Context* ctx, const FuncType* func_type) { - write_open_space(ctx, "type"); - write_string_slice_or_index(ctx, &func_type->name, ctx->func_type_index++, - NextChar::Space); - write_open_space(ctx, "func"); - write_func_sig_space(ctx, &func_type->sig); - write_close_space(ctx); - write_close_newline(ctx); +void ASTWriter::WriteFuncType(const FuncType* func_type) { + WriteOpenSpace("type"); + WriteStringSliceOrIndex(&func_type->name, func_type_index_++, + NextChar::Space); + WriteOpenSpace("func"); + WriteFuncSigSpace(&func_type->sig); + WriteCloseSpace(); + WriteCloseNewline(); } -static void write_start_function(Context* ctx, const Var* start) { - write_open_space(ctx, "start"); - write_var(ctx, start, NextChar::None); - write_close_newline(ctx); +void ASTWriter::WriteStartFunction(const Var* start) { + WriteOpenSpace("start"); + WriteVar(start, NextChar::None); + WriteCloseNewline(); } -static void write_module(Context* ctx, const Module* module) { - write_open_newline(ctx, "module"); +Result ASTWriter::WriteModule(const Module* module) { + WriteOpenNewline("module"); for (const ModuleField* field = module->first_field; field; field = field->next) { switch (field->type) { case ModuleFieldType::Func: - write_func(ctx, module, field->func); + WriteFunc(module, field->func); break; case ModuleFieldType::Global: - write_global(ctx, field->global); + WriteGlobal(field->global); break; case ModuleFieldType::Import: - write_import(ctx, field->import); + WriteImport(field->import); break; case ModuleFieldType::Export: - write_export(ctx, field->export_); + WriteExport(field->export_); break; case ModuleFieldType::Table: - write_table(ctx, field->table); + WriteTable(field->table); break; case ModuleFieldType::ElemSegment: - write_elem_segment(ctx, field->elem_segment); + WriteElemSegment(field->elem_segment); break; case ModuleFieldType::Memory: - write_memory(ctx, field->memory); + WriteMemory(field->memory); break; case ModuleFieldType::DataSegment: - write_data_segment(ctx, field->data_segment); + WriteDataSegment(field->data_segment); break; case ModuleFieldType::FuncType: - write_func_type(ctx, field->func_type); + WriteFuncType(field->func_type); break; case ModuleFieldType::Start: - write_start_function(ctx, &field->start); + WriteStartFunction(&field->start); break; } } - write_close_newline(ctx); + WriteCloseNewline(); /* force the newline to be written */ - write_next_char(ctx); + WriteNextChar(); + return result_; } Result write_ast(Writer* writer, const Module* module) { - Context ctx(writer); - write_module(&ctx, module); - return ctx.result; + ASTWriter ast_writer(writer); + return ast_writer.WriteModule(module); } } // namespace wabt |