diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/ir.cc | 47 | ||||
-rw-r--r-- | src/ir.h | 7 | ||||
-rw-r--r-- | src/opcode.h | 1 | ||||
-rw-r--r-- | src/tracing.cc | 70 | ||||
-rw-r--r-- | src/tracing.h | 73 | ||||
-rw-r--r-- | src/wat-writer.cc | 71 | ||||
-rw-r--r-- | test/desugar/fold-catch.txt | 28 | ||||
-rw-r--r-- | test/desugar/fold-export-throw.txt | 21 | ||||
-rw-r--r-- | test/desugar/fold-try-as-argument.txt | 36 | ||||
-rw-r--r-- | test/desugar/fold-try.txt | 28 |
11 files changed, 377 insertions, 6 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ae2b326..8910670d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -264,6 +264,7 @@ add_library(libwabt STATIC src/literal.cc src/option-parser.cc src/stream.cc + src/tracing.cc src/utf8.cc src/writer.cc ) @@ -19,8 +19,55 @@ #include <cassert> #include <cstddef> +namespace { + +const char* ExprTypeName[] = { + "Binary", + "Block", + "Br", + "BrIf", + "BrTable", + "Call", + "CallIndirect", + "Compare", + "Const", + "Convert", + "CurrentMemory", + "Drop", + "GetGlobal", + "GetLocal", + "GrowMemory", + "If", + "Load", + "Loop", + "Nop", + "Rethrow", + "Return", + "Select", + "SetGlobal", + "SetLocal", + "Store", + "TeeLocal", + "Throw", + "TryBlock", + "Unary", + "Unreachable" +}; + +} // end of anonymous namespace + namespace wabt { +const char* GetExprTypeName(ExprType type) { + static_assert(WABT_ENUM_COUNT(ExprType) == WABT_ARRAY_SIZE(ExprTypeName), + "Malformed ExprTypeName array"); + return ExprTypeName[size_t(type)]; +} + +const char* GetExprTypeName(const Expr& expr) { + return GetExprTypeName(expr.type); +} + bool FuncSignature::operator==(const FuncSignature& rhs) const { return param_types == rhs.param_types && result_types == rhs.result_types; } @@ -120,8 +120,13 @@ enum class ExprType { TryBlock, Unary, Unreachable, + + First = Binary, + Last = Unreachable }; +const char* GetExprTypeName(ExprType type); + typedef TypeVector BlockSignature; class Expr; @@ -167,6 +172,8 @@ class Expr { explicit Expr(ExprType); }; +const char* GetExprTypeName(const Expr& expr); + template <ExprType TypeEnum> class ExprMixin : public Expr { public: diff --git a/src/opcode.h b/src/opcode.h index ce2cd13b..8ae7e160 100644 --- a/src/opcode.h +++ b/src/opcode.h @@ -45,7 +45,6 @@ struct Opcode { operator Enum() const { return enum_; } static Opcode FromCode(uint32_t); - uint32_t GetCode() const { return GetInfo().code; } const char* GetName() const { return GetInfo().name; } Type GetResultType() const { return GetInfo().result_type; } diff --git a/src/tracing.cc b/src/tracing.cc new file mode 100644 index 00000000..f4669894 --- /dev/null +++ b/src/tracing.cc @@ -0,0 +1,70 @@ +/* + * Copyright 2017 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define WABT_TRACING 1 +#include "tracing.h" + +namespace { + +size_t indent = 0; +const char* indent_text = " "; + +void Fill() { + for (size_t i = 0; i < indent; ++i) + fputs(indent_text, stderr); +} + +void Indent() { + Fill(); + ++indent; +} + +void Dedent() { + if (indent) + --indent; + Fill(); +} + +} // end of anonymous namespace + +namespace wabt { + +// static + +TraceScope::TraceScope(const char* method) : method_(method) { + PrintEnter(method); + PrintNewline(); +} + +TraceScope::~TraceScope() { + Dedent(); + fputs("<- ", stderr); + fputs(method_, stderr); + fputc('\n', stderr); +} + +void TraceScope::PrintEnter(const char* method) { + Indent(); + fputs("-> ", stderr); + fputs(method, stderr); + fputs("(", stderr); +} + +void TraceScope::PrintNewline() { + fputs(")\n", stderr); +} + +} // end of namespace wabt diff --git a/src/tracing.h b/src/tracing.h new file mode 100644 index 00000000..f1e741c5 --- /dev/null +++ b/src/tracing.h @@ -0,0 +1,73 @@ +/* + * Copyright 2017 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WABT_TRACING_H_ +#define WABT_TRACING_H_ + +// Provides a simple tracing class that automatically generates enter/exit +// messages using the scope of the instance. +// +// It also assumes that this file is only included in .cc files. +// Immediately before the inclusion of this file, there is a define of +// for WABT_TRACING, defining whether tracing should be compiled in for +// that source file. + +#ifndef WABT_TRACING +#define WABT_TRACING 0 +#endif + +#include "common.h" + +namespace wabt { + +#if WABT_TRACING + +// Scoped class that automatically prints enter("->") and exit("<-") +// lines, indented by trace level. +struct TraceScope { + WABT_DISALLOW_COPY_AND_ASSIGN(TraceScope); + TraceScope() = delete; + TraceScope(const char* method); + template<typename... Args> + TraceScope(const char* method, const char* format, Args... args) + : method_(method) { + PrintEnter(method); + fprintf(stderr, format, args...); + PrintNewline(); + } + ~TraceScope(); + + private: + const char* method_; + void PrintEnter(const char* method); + void PrintNewline(); +}; + +#define WABT_TRACE(method_name) TraceScope _func_(#method_name) + +#define WABT_TRACE_ARGS(method_name, format, ...) \ + TraceScope _func_(#method_name, format, __VA_ARGS__) + +#else + +#define WABT_TRACE(method) +#define WABT_TRACE_ARGS(method_name, format, ...) + +#endif + +} // end namespace wabt + +#endif // WABT_TRACING_H_ diff --git a/src/wat-writer.cc b/src/wat-writer.cc index 9b411b8a..5f5cd05c 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -33,6 +33,9 @@ #include "stream.h" #include "writer.h" +#define WABT_TRACING 0 +#include "tracing.h" + #define INDENT_SIZE 2 #define NO_FORCE_NEWLINE 0 #define FORCE_NEWLINE 1 @@ -62,7 +65,14 @@ enum class NextChar { }; struct ExprTree { - explicit ExprTree(const Expr* expr) : expr(expr) {} + explicit ExprTree(const Expr* expr = nullptr) : expr(expr) {} + // For debugging. + std::string describe() const { + std::string result("ExprTree("); + if (expr) + result.append(GetExprTypeName(*expr)); + return result + ")"; + } const Expr* expr; std::vector<ExprTree> children; @@ -465,6 +475,7 @@ void WatWriter::WriteConst(const Const* const_) { } void WatWriter::WriteExpr(const Expr* expr) { + WABT_TRACE_ARGS(WriteExpr, "%s", GetExprTypeName(*expr)); switch (expr->type) { case ExprType::Binary: WritePutsNewline(cast<BinaryExpr>(expr)->opcode.GetName()); @@ -647,13 +658,14 @@ void WatWriter::WriteExpr(const Expr* expr) { break; default: - fprintf(stderr, "bad expr type: %d\n", static_cast<int>(expr->type)); + fprintf(stderr, "bad expr type: %s\n", GetExprTypeName(*expr)); assert(0); break; } } void WatWriter::WriteExprList(const Expr* first) { + WABT_TRACE(WriteExprList); for (const Expr* expr = first; expr; expr = expr->next) WriteExpr(expr); } @@ -699,6 +711,7 @@ Index WatWriter::GetFuncSigResultCount(const Var* var) { } void WatWriter::WriteFoldedExpr(const Expr* expr) { + WABT_TRACE_ARGS(WriteFoldedExpr, "%s", GetExprTypeName(*expr)); switch (expr->type) { case ExprType::Binary: case ExprType::Compare: @@ -776,18 +789,37 @@ void WatWriter::WriteFoldedExpr(const Expr* expr) { PushExpr(expr, current_func_->decl.sig.result_types.size(), 1); break; + case ExprType::Rethrow: + PushExpr(expr, 0, 0); + break; + case ExprType::Select: PushExpr(expr, 3, 1); break; + case ExprType::Throw: { + auto throw_ = cast<ThrowExpr>(expr); + Index operand_count = 0; + if (Exception* except = module_->GetExcept(throw_->var)) { + operand_count = except->sig.size(); + } + PushExpr(expr, operand_count, 0); + break; + } + + case ExprType::TryBlock: + PushExpr(expr, 0, cast<TryExpr>(expr)->block->sig.size()); + break; + default: - fprintf(stderr, "bad expr type: %d\n", static_cast<int>(expr->type)); + fprintf(stderr, "bad expr type: %s\n", GetExprTypeName(*expr)); assert(0); break; } } void WatWriter::WriteFoldedExprList(const Expr* first) { + WABT_TRACE(WriteFoldedExprList); for (const Expr* expr = first; expr; expr = expr->next) WriteFoldedExpr(expr); } @@ -795,13 +827,15 @@ void WatWriter::WriteFoldedExprList(const Expr* first) { void WatWriter::PushExpr(const Expr* expr, Index operand_count, Index result_count) { + WABT_TRACE_ARGS(PushExpr, "%s, %" PRIindex ", %" PRIindex "", + GetExprTypeName(*expr), operand_count, result_count); if (operand_count <= expr_tree_stack_.size()) { auto last_operand = expr_tree_stack_.end(); auto first_operand = last_operand - operand_count; ExprTree tree(expr); std::move(first_operand, last_operand, std::back_inserter(tree.children)); expr_tree_stack_.erase(first_operand, last_operand); - expr_tree_stack_.push_back(std::move(tree)); + expr_tree_stack_.emplace_back(tree); if (result_count == 0) FlushExprTreeStack(); } else { @@ -811,6 +845,7 @@ void WatWriter::PushExpr(const Expr* expr, } void WatWriter::FlushExprTree(const ExprTree& expr_tree) { + WABT_TRACE_ARGS(FlushExprTree, "%s", GetExprTypeName(*expr_tree.expr)); switch (expr_tree.expr->type) { case ExprType::Block: WritePuts("(", NextChar::None); @@ -850,6 +885,31 @@ void WatWriter::FlushExprTree(const ExprTree& expr_tree) { break; } + case ExprType::TryBlock: { + auto try_ = cast<TryExpr>(expr_tree.expr); + WritePuts("(", NextChar::None); + WriteBeginBlock(LabelType::Try, try_->block, + Opcode::Try_Opcode.GetName()); + WriteFoldedExprList(try_->block->first); + FlushExprTreeStack(); + for (const Catch* catch_ : try_->catches) { + WritePuts("(", NextChar::None); + if (catch_->IsCatchAll()) { + WritePutsNewline(Opcode::CatchAll_Opcode.GetName()); + } else { + WritePutsSpace(Opcode::Catch_Opcode.GetName()); + WriteVar(&catch_->var, NextChar::Newline); + } + Indent(); + label_stack_.back().label_type = LabelType::Catch; + WriteFoldedExprList(catch_->first); + FlushExprTreeStack(); + WriteCloseNewline(); + } + WriteCloseNewline(); + break; + } + default: { WritePuts("(", NextChar::None); WriteExpr(expr_tree.expr); @@ -862,8 +922,9 @@ void WatWriter::FlushExprTree(const ExprTree& expr_tree) { } void WatWriter::FlushExprTreeVector(const std::vector<ExprTree>& expr_trees) { + WABT_TRACE_ARGS(FlushExprTreeVector, "%zu", expr_trees.size()); for (auto expr_tree : expr_trees) - FlushExprTree(expr_tree); + FlushExprTree(expr_tree); } void WatWriter::FlushExprTreeStack() { diff --git a/test/desugar/fold-catch.txt b/test/desugar/fold-catch.txt new file mode 100644 index 00000000..186783bb --- /dev/null +++ b/test/desugar/fold-catch.txt @@ -0,0 +1,28 @@ +;;; TOOL: wast-desugar +;;; FLAGS: --future-exceptions --fold-expr +(module + (except $ex i32) + (func (result i32) + try $try1 (result i32) + nop + i32.const 7 + catch $ex + i32.const 9 + catch_all + i32.const 11 + end + ) +) +(;; STDOUT ;;; +(module + (except $ex i32) + (type (;0;) (func (result i32))) + (func (;0;) (result i32) + (try $try1 (result i32) + (nop) + (i32.const 7) + (catch $ex + (i32.const 9)) + (catch_all + (i32.const 11))))) +;;; STDOUT ;;) diff --git a/test/desugar/fold-export-throw.txt b/test/desugar/fold-export-throw.txt new file mode 100644 index 00000000..553cc18e --- /dev/null +++ b/test/desugar/fold-export-throw.txt @@ -0,0 +1,21 @@ +;;; TOOL: wast-desugar +;;; FLAGS: --future-exceptions --fold-exprs +(module + (except $ex i32) + (export "except" (except $ex)) + (func (result i32) + (i32.const 5) + (i32.const 7) + (throw $ex) + ) +) +(;; STDOUT ;;; +(module + (except $ex i32) + (export "except" (except $ex)) + (type (;0;) (func (result i32))) + (func (;0;) (result i32) + (i32.const 5) + (throw $ex + (i32.const 7)))) +;;; STDOUT ;;) diff --git a/test/desugar/fold-try-as-argument.txt b/test/desugar/fold-try-as-argument.txt new file mode 100644 index 00000000..db5aadad --- /dev/null +++ b/test/desugar/fold-try-as-argument.txt @@ -0,0 +1,36 @@ +;;; TOOL: wast-desugar +;;; FLAGS: --future-exceptions --fold-expr +(module + (except $ex i32) + (func (result i32) + i32.const 1 + try $try1 (result i32) + nop + i32.const 7 + catch $ex + nop + catch_all + rethrow $try1 + end + i32.add + i32.const 8 + i32.sub + ) +) +(;; STDOUT ;;; +(module + (except $ex i32) + (type (;0;) (func (result i32))) + (func (;0;) (result i32) + (i32.sub + (i32.add + (i32.const 1) + (try $try1 (result i32) + (nop) + (i32.const 7) + (catch $ex + (nop)) + (catch_all + (rethrow $try1)))) + (i32.const 8)))) +;;; STDOUT ;;) diff --git a/test/desugar/fold-try.txt b/test/desugar/fold-try.txt new file mode 100644 index 00000000..7da0954d --- /dev/null +++ b/test/desugar/fold-try.txt @@ -0,0 +1,28 @@ +;;; TOOL: wast-desugar +;;; FLAGS: --future-exceptions --fold-expr +(module + (except $ex i32) + (func (result i32) + try $try1 (result i32) + nop + i32.const 7 + catch $ex + nop + catch_all + rethrow $try1 + end + ) +) +(;; STDOUT ;;; +(module + (except $ex i32) + (type (;0;) (func (result i32))) + (func (;0;) (result i32) + (try $try1 (result i32) + (nop) + (i32.const 7) + (catch $ex + (nop)) + (catch_all + (rethrow $try1))))) +;;; STDOUT ;;) |