diff options
Diffstat (limited to 'src/passes/Print.cpp')
-rw-r--r-- | src/passes/Print.cpp | 148 |
1 files changed, 91 insertions, 57 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 5eea38bdc..43ddc954c 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -32,14 +32,17 @@ struct PrintSExpression : public Visitor<PrintSExpression> { const char *maybeSpace; const char *maybeNewLine; - bool fullAST = false; // whether to not elide nodes in output when possible - // (like implicit blocks) + bool full = false; // whether to not elide nodes in output when possible + // (like implicit blocks) and to emit types Module* currModule = nullptr; Function* currFunction = nullptr; PrintSExpression(std::ostream& o) : o(o) { setMinify(false); + if (getenv("BINARYEN_PRINT_FULL")) { + full = std::stoi(getenv("BINARYEN_PRINT_FULL")); + } } void setMinify(bool minify_) { @@ -48,7 +51,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> { maybeNewLine = minify ? "" : "\n"; } - void setFullAST(bool fullAST_) { fullAST = fullAST_; } + void setFull(bool full_) { full = full_; } void incIndent() { if (minify) return; @@ -64,6 +67,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } void printFullLine(Expression *expression) { !minify && doIndent(o, indent); + if (full) { + o << "[" << printWasmType(expression->type) << "] "; + } visit(expression); o << maybeNewLine; } @@ -79,10 +85,6 @@ struct PrintSExpression : public Visitor<PrintSExpression> { return name; } - Name printableGlobal(Index index) { - return currModule->getGlobal(index)->name; - } - std::ostream& printName(Name name) { // we need to quote names if they have tricky chars if (strpbrk(name.str, "()")) { @@ -99,6 +101,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { while (1) { if (stack.size() > 0) doIndent(o, indent); stack.push_back(curr); + if (full) { + o << "[" << printWasmType(curr->type) << "] "; + } printOpening(o, "block"); if (curr->name.is()) { o << ' '; @@ -135,13 +140,13 @@ struct PrintSExpression : public Visitor<PrintSExpression> { incIndent(); printFullLine(curr->condition); // ifTrue and False have implict blocks, avoid printing them if possible - if (!fullAST && curr->ifTrue->is<Block>() && curr->ifTrue->dynCast<Block>()->name.isNull() && curr->ifTrue->dynCast<Block>()->list.size() == 1) { + if (!full && curr->ifTrue->is<Block>() && curr->ifTrue->dynCast<Block>()->name.isNull() && curr->ifTrue->dynCast<Block>()->list.size() == 1) { printFullLine(curr->ifTrue->dynCast<Block>()->list.back()); } else { printFullLine(curr->ifTrue); } if (curr->ifFalse) { - if (!fullAST && curr->ifFalse->is<Block>() && curr->ifFalse->dynCast<Block>()->name.isNull() && curr->ifFalse->dynCast<Block>()->list.size() == 1) { + if (!full && curr->ifFalse->is<Block>() && curr->ifFalse->dynCast<Block>()->name.isNull() && curr->ifFalse->dynCast<Block>()->list.size() == 1) { printFullLine(curr->ifFalse->dynCast<Block>()->list.back()); } else { printFullLine(curr->ifFalse); @@ -151,16 +156,12 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } void visitLoop(Loop *curr) { printOpening(o, "loop"); - if (curr->out.is()) { - o << ' ' << curr->out; - assert(curr->in.is()); // if just one is printed, it must be the in - } - if (curr->in.is()) { - o << ' ' << curr->in; + if (curr->name.is()) { + o << ' ' << curr->name; } incIndent(); auto block = curr->body->dynCast<Block>(); - if (!fullAST && block && block->name.isNull()) { + if (!full && block && block->name.isNull()) { // wasm spec has loops containing children directly, while our ast // has a single child for simplicity. print out the optimal form. for (auto expression : block->list) { @@ -229,26 +230,33 @@ struct PrintSExpression : public Visitor<PrintSExpression> { void visitCallIndirect(CallIndirect *curr) { printOpening(o, "call_indirect ") << curr->fullType; incIndent(); - printFullLine(curr->target); for (auto operand : curr->operands) { printFullLine(operand); } + printFullLine(curr->target); decIndent(); } void visitGetLocal(GetLocal *curr) { printOpening(o, "get_local ") << printableLocal(curr->index) << ')'; } void visitSetLocal(SetLocal *curr) { - printOpening(o, "set_local ") << printableLocal(curr->index); + if (curr->isTee()) { + printOpening(o, "tee_local "); + } else { + printOpening(o, "set_local "); + } + o << printableLocal(curr->index); incIndent(); printFullLine(curr->value); decIndent(); } void visitGetGlobal(GetGlobal *curr) { - printOpening(o, "get_global ") << printableGlobal(curr->index) << ')'; + printOpening(o, "get_global "); + printName(curr->name) << ')'; } void visitSetGlobal(SetGlobal *curr) { - printOpening(o, "set_global ") << printableGlobal(curr->index); + printOpening(o, "set_global "); + printName(curr->name); incIndent(); printFullLine(curr->value); decIndent(); @@ -281,7 +289,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } void visitStore(Store *curr) { o << '('; - prepareColor(o) << printWasmType(curr->type) << ".store"; + prepareColor(o) << printWasmType(curr->valueType) << ".store"; if (curr->bytes < 4 || (curr->type == i64 && curr->bytes < 8)) { if (curr->bytes == 1) { o << '8'; @@ -466,9 +474,16 @@ struct PrintSExpression : public Visitor<PrintSExpression> { printFullLine(curr->condition); decIndent(); } + void visitDrop(Drop *curr) { + o << '('; + prepareColor(o) << "drop"; + incIndent(); + printFullLine(curr->value); + decIndent(); + } void visitReturn(Return *curr) { printOpening(o, "return"); - if (!curr->value || curr->value->is<Nop>()) { + if (!curr->value) { // avoid a new line just for the parens o << ')'; return; @@ -499,11 +514,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { printMinorOpening(o, "unreachable") << ')'; } // Module-level visitors - void visitFunctionType(FunctionType *curr, bool full=false) { - if (full) { - printOpening(o, "type") << ' '; - printName(curr->name) << " (func"; - } + void visitFunctionType(FunctionType *curr, Name* internalName = nullptr) { + o << "(func"; + if (internalName) o << ' ' << *internalName; if (curr->params.size() > 0) { o << maybeSpace; printMinorOpening(o, "param"); @@ -516,27 +529,39 @@ struct PrintSExpression : public Visitor<PrintSExpression> { o << maybeSpace; printMinorOpening(o, "result ") << printWasmType(curr->result) << ')'; } - if (full) { - o << "))"; - } + o << ")"; } void visitImport(Import *curr) { printOpening(o, "import "); - printName(curr->name) << ' '; printText(o, curr->module.str) << ' '; - printText(o, curr->base.str); - if (curr->type) visitFunctionType(curr->type); + printText(o, curr->base.str) << ' '; + switch (curr->kind) { + case Export::Function: if (curr->functionType) visitFunctionType(curr->functionType, &curr->name); break; + case Export::Table: o << "(table " << curr->name << ")"; break; + case Export::Memory: o << "(memory " << curr->name << ")"; break; + case Export::Global: o << "(global " << curr->name << ' ' << printWasmType(curr->globalType) << ")"; break; + default: WASM_UNREACHABLE(); + } o << ')'; } void visitExport(Export *curr) { printOpening(o, "export "); - printText(o, curr->name.str) << ' '; - printName(curr->value) << ')'; + printText(o, curr->name.str) << " ("; + switch (curr->kind) { + case Export::Function: o << "func"; break; + case Export::Table: o << "table"; break; + case Export::Memory: o << "memory"; break; + case Export::Global: o << "global"; break; + default: WASM_UNREACHABLE(); + } + o << ' '; + printName(curr->value) << "))"; } void visitGlobal(Global *curr) { printOpening(o, "global "); - printName(curr->name) << ' ' << printWasmType(curr->type); - printFullLine(curr->init); + printName(curr->name) << ' '; + o << printWasmType(curr->type) << ' '; + visit(curr->init); o << ')'; } void visitFunction(Function *curr) { @@ -564,7 +589,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } // It is ok to emit a block here, as a function can directly contain a list, even if our // ast avoids that for simplicity. We can just do that optimization here.. - if (!fullAST && curr->body->is<Block>() && curr->body->cast<Block>()->name.isNull()) { + if (!full && curr->body->is<Block>() && curr->body->cast<Block>()->name.isNull()) { Block* block = curr->body->cast<Block>(); for (auto item : block->list) { printFullLine(item); @@ -575,7 +600,8 @@ struct PrintSExpression : public Visitor<PrintSExpression> { decIndent(); } void visitTable(Table *curr) { - printOpening(o, "table") << ' ' << curr->initial; + printOpening(o, "table") << ' '; + o << curr->initial; if (curr->max && curr->max != Table::kMaxSize) o << ' ' << curr->max; o << " anyfunc)\n"; doIndent(o, indent); @@ -589,15 +615,12 @@ struct PrintSExpression : public Visitor<PrintSExpression> { o << ')'; } } - void visitModule(Module *curr) { - currModule = curr; - printOpening(o, "module", true); - incIndent(); - doIndent(o, indent); - printOpening(o, "memory") << ' ' << curr->memory.initial; - if (curr->memory.max && curr->memory.max != Memory::kMaxSize) o << ' ' << curr->memory.max; + void visitMemory(Memory* curr) { + printOpening(o, "memory") << ' '; + o << curr->initial; + if (curr->max && curr->max != Memory::kMaxSize) o << ' ' << curr->max; o << ")\n"; - for (auto segment : curr->memory.segments) { + for (auto segment : curr->segments) { doIndent(o, indent); printOpening(o, "data ", true); visit(segment.offset); @@ -624,12 +647,13 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } o << "\")\n"; } - if (curr->memory.exportName.is()) { - doIndent(o, indent); - printOpening(o, "export "); - printText(o, curr->memory.exportName.str) << " memory)"; - o << maybeNewLine; - } + } + void visitModule(Module *curr) { + currModule = curr; + printOpening(o, "module", true); + incIndent(); + doIndent(o, indent); + visitMemory(&curr->memory); if (curr->start.is()) { doIndent(o, indent); printOpening(o, "start") << ' ' << curr->start << ')'; @@ -637,8 +661,10 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } for (auto& child : curr->functionTypes) { doIndent(o, indent); - visitFunctionType(child.get(), true); - o << maybeNewLine; + printOpening(o, "type") << ' '; + printName(child->name) << ' '; + visitFunctionType(child.get()); + o << ")" << maybeNewLine; } for (auto& child : curr->imports) { doIndent(o, indent); @@ -707,7 +733,7 @@ public: void run(PassRunner* runner, Module* module) override { PrintSExpression print(o); - print.setFullAST(true); + print.setFull(true); print.visitModule(module); } }; @@ -718,9 +744,17 @@ Pass *createFullPrinterPass() { // Print individual expressions -std::ostream& WasmPrinter::printExpression(Expression* expression, std::ostream& o, bool minify) { +std::ostream& WasmPrinter::printExpression(Expression* expression, std::ostream& o, bool minify, bool full) { + if (!expression) { + o << "(null expression)"; + return o; + } PrintSExpression print(o); print.setMinify(minify); + if (full) { + print.setFull(true); + o << "[" << printWasmType(expression->type) << "] "; + } print.visit(expression); return o; } |