diff options
-rw-r--r-- | src/passes/Print.cpp | 933 | ||||
-rw-r--r-- | src/passes/StackIR.cpp | 26 | ||||
-rw-r--r-- | src/pretty_printing.h | 15 | ||||
-rw-r--r-- | src/shell-interface.h | 2 | ||||
-rw-r--r-- | src/wasm-printing.h | 14 | ||||
-rw-r--r-- | src/wasm-stack.h | 45 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 3 | ||||
-rw-r--r-- | test/passes/O1_print-stack-ir.txt | 29 | ||||
-rw-r--r-- | test/passes/O2_precompute-propagate_print-stack-ir.txt | 16 | ||||
-rw-r--r-- | test/passes/O2_print-stack-ir.txt | 31 | ||||
-rw-r--r-- | test/passes/O3_print-stack-ir.txt | 27 | ||||
-rw-r--r-- | test/passes/Os_print-stack-ir.txt | 27 | ||||
-rw-r--r-- | test/passes/fuzz-exec.txt | 20 | ||||
-rw-r--r-- | test/passes/fuzz-exec_O.txt | 8 | ||||
-rw-r--r-- | test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt | 1200 | ||||
-rw-r--r-- | test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt | 47 | ||||
-rw-r--r-- | test/passes/ssa_fuzz-exec.txt | 4 |
17 files changed, 1380 insertions, 1067 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index dfdfa46d4..28e7cc34f 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -20,6 +20,7 @@ #include <wasm.h> #include <wasm-printing.h> +#include <wasm-stack.h> #include <pass.h> #include <pretty_printing.h> #include <ir/module-utils.h> @@ -33,294 +34,108 @@ static bool isFullForced() { return false; } -struct PrintSExpression : public Visitor<PrintSExpression> { - std::ostream& o; - unsigned indent = 0; - - bool minify; - const char *maybeSpace; - const char *maybeNewLine; - - 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; - Function::DebugLocation lastPrintedLocation; - - std::unordered_map<Name, Index> functionIndexes; - - PrintSExpression(std::ostream& o) : o(o) { - setMinify(false); - if (!full) full = isFullForced(); +static std::ostream& printName(Name name, std::ostream& o) { + // we need to quote names if they have tricky chars + if (strpbrk(name.str, "()")) { + o << '"' << name << '"'; + } else { + o << name; } + return o; +} - void visit(Expression* curr) { - if (currFunction) { - // show an annotation, if there is one - auto& debugLocations = currFunction->debugLocations; - auto iter = debugLocations.find(curr); - if (iter != debugLocations.end()) { - auto fileName = currModule->debugInfoFileNames[iter->second.fileIndex]; - if (lastPrintedLocation != iter->second) { - lastPrintedLocation = iter->second; - o << ";;@ " << fileName << ":" << iter->second.lineNumber << ":" << iter->second.columnNumber << '\n'; - doIndent(o, indent); - } - } - } - Visitor<PrintSExpression>::visit(curr); +static Name printableLocal(Index index, Function* func) { + Name name; + if (func) { + name = func->getLocalNameOrDefault(index); } - - void setMinify(bool minify_) { - minify = minify_; - maybeSpace = minify ? "" : " "; - maybeNewLine = minify ? "" : "\n"; + if (!name.is()) { + name = Name::fromInt(index); } + return name; +} - void setFull(bool full_) { full = full_; } - - void incIndent() { - if (minify) return; - o << '\n'; - indent++; - } - void decIndent() { - if (!minify) { - indent--; - doIndent(o, indent); - } - o << ')'; - } - void printFullLine(Expression *expression) { - !minify && doIndent(o, indent); - if (full) { - o << "[" << printType(expression->type) << "] "; - } - visit(expression); - o << maybeNewLine; - } - Name printableLocal(Index index) { - Name name; - if (currFunction) { - name = currFunction->getLocalNameOrDefault(index); - } - if (!name.is()) { - name = Name::fromInt(index); - } - return name; - } +// Prints the internal contents of an expression: everything but +// the children. +struct PrintExpressionContents : public Visitor<PrintExpressionContents> { + Function* currFunction = nullptr; + std::ostream& o; - std::ostream& printName(Name name) { - // we need to quote names if they have tricky chars - if (strpbrk(name.str, "()")) { - o << '"' << name << '"'; - } else { - o << name; - } - return o; - } + PrintExpressionContents(Function* currFunction, std::ostream& o) : + currFunction(currFunction), o(o) {} - void visitBlock(Block *curr) { - // special-case Block, because Block nesting (in their first element) can be incredibly deep - std::vector<Block*> stack; - while (1) { - if (stack.size() > 0) doIndent(o, indent); - stack.push_back(curr); - if (full) { - o << "[" << printType(curr->type) << "] "; - } - printOpening(o, "block"); - if (curr->name.is()) { - o << ' '; - printName(curr->name); - } - if (isConcreteType(curr->type)) { - o << " (result " << printType(curr->type) << ')'; - } - incIndent(); - if (curr->list.size() > 0 && curr->list[0]->is<Block>()) { - // recurse into the first element - curr = curr->list[0]->cast<Block>(); - continue; - } else { - break; // that's all we can recurse, start to unwind - } - } - auto* top = stack.back(); - while (stack.size() > 0) { - curr = stack.back(); - stack.pop_back(); - auto& list = curr->list; - for (size_t i = 0; i < list.size(); i++) { - if (curr != top && i == 0) { - // one of the block recursions we already handled - decIndent(); - if (full) { - o << " ;; end block"; - auto* child = list[0]->cast<Block>(); - if (child->name.is()) { - o << ' ' << child->name; - } - } - o << '\n'; - continue; - } - printFullLine(list[i]); - } + void visitBlock(Block* curr) { + printMedium(o, "block"); + if (curr->name.is()) { + o << ' '; + printName(curr->name, o); } - decIndent(); - if (full) { - o << " ;; end block"; - if (curr->name.is()) { - o << ' ' << curr->name; - } + if (isConcreteType(curr->type)) { + o << " (result " << printType(curr->type) << ')'; } } - void visitIf(If *curr) { - printOpening(o, "if"); + void visitIf(If* curr) { + printMedium(o, "if"); if (isConcreteType(curr->type)) { o << " (result " << printType(curr->type) << ')'; } - incIndent(); - printFullLine(curr->condition); - // ifTrue and False have implict blocks, avoid printing them if possible - 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 (!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); - } - } - decIndent(); - if (full) { - o << " ;; end if"; - } } - void visitLoop(Loop *curr) { - printOpening(o, "loop"); + void visitLoop(Loop* curr) { + printMedium(o, "loop"); if (curr->name.is()) { o << ' ' << curr->name; } if (isConcreteType(curr->type)) { o << " (result " << printType(curr->type) << ')'; } - incIndent(); - auto block = curr->body->dynCast<Block>(); - 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) { - printFullLine(expression); - } - } else { - printFullLine(curr->body); - } - decIndent(); - if (full) { - o << " ;; end loop"; - if (curr->name.is()) { - o << ' ' << curr->name; - } - } } - void visitBreak(Break *curr) { + void visitBreak(Break* curr) { if (curr->condition) { - printOpening(o, "br_if "); - printName(curr->name); - incIndent(); + printMedium(o, "br_if "); } else { - printOpening(o, "br "); - printName(curr->name); - if (!curr->value || curr->value->is<Nop>()) { - // avoid a new line just for the parens - o << ')'; - return; - } - incIndent(); - } - if (curr->value && !curr->value->is<Nop>()) printFullLine(curr->value); - if (curr->condition) { - printFullLine(curr->condition); + printMedium(o, "br "); } - decIndent(); + printName(curr->name, o); } - void visitSwitch(Switch *curr) { - printOpening(o, "br_table"); + void visitSwitch(Switch* curr) { + printMedium(o, "br_table"); for (auto& t : curr->targets) { o << ' ' << t; } o << ' ' << curr->default_; - incIndent(); - if (curr->value && !curr->value->is<Nop>()) printFullLine(curr->value); - printFullLine(curr->condition); - decIndent(); } - - template<typename CallBase> - void printCallBody(CallBase* curr) { - printName(curr->target); - if (curr->operands.size() > 0) { - incIndent(); - for (auto operand : curr->operands) { - printFullLine(operand); - } - decIndent(); - } else { - o << ')'; - } - } - - void visitCall(Call *curr) { - printOpening(o, "call "); - printCallBody(curr); + void visitCall(Call* curr) { + printMedium(o, "call "); + printName(curr->target, o); } - void visitCallImport(CallImport *curr) { - printOpening(o, "call "); - printCallBody(curr); + void visitCallImport(CallImport* curr) { + printMedium(o, "call "); + printName(curr->target, o); } - void visitCallIndirect(CallIndirect *curr) { - printOpening(o, "call_indirect (type ") << curr->fullType << ')'; - incIndent(); - for (auto operand : curr->operands) { - printFullLine(operand); - } - printFullLine(curr->target); - decIndent(); + void visitCallIndirect(CallIndirect* curr) { + printMedium(o, "call_indirect (type ") << curr->fullType << ')'; } - void visitGetLocal(GetLocal *curr) { - printOpening(o, "get_local ") << printableLocal(curr->index) << ')'; + void visitGetLocal(GetLocal* curr) { + printMedium(o, "get_local ") << printableLocal(curr->index, currFunction); } - void visitSetLocal(SetLocal *curr) { + void visitSetLocal(SetLocal* curr) { if (curr->isTee()) { - printOpening(o, "tee_local "); + printMedium(o, "tee_local "); } else { - printOpening(o, "set_local "); + printMedium(o, "set_local "); } - o << printableLocal(curr->index); - incIndent(); - printFullLine(curr->value); - decIndent(); + o << printableLocal(curr->index, currFunction); } - void visitGetGlobal(GetGlobal *curr) { - printOpening(o, "get_global "); - printName(curr->name) << ')'; + void visitGetGlobal(GetGlobal* curr) { + printMedium(o, "get_global "); + printName(curr->name, o); } - void visitSetGlobal(SetGlobal *curr) { - printOpening(o, "set_global "); - printName(curr->name); - incIndent(); - printFullLine(curr->value); - decIndent(); + void visitSetGlobal(SetGlobal* curr) { + printMedium(o, "set_global "); + printName(curr->name, o); } - void visitLoad(Load *curr) { - o << '('; + void visitLoad(Load* curr) { prepareColor(o) << printType(curr->type); if (curr->isAtomic) o << ".atomic"; o << ".load"; @@ -343,12 +158,8 @@ struct PrintSExpression : public Visitor<PrintSExpression> { if (curr->align != curr->bytes) { o << " align=" << curr->align; } - incIndent(); - printFullLine(curr->ptr); - decIndent(); } - void visitStore(Store *curr) { - o << '('; + void visitStore(Store* curr) { prepareColor(o) << printType(curr->valueType); if (curr->isAtomic) o << ".atomic"; o << ".store"; @@ -370,10 +181,6 @@ struct PrintSExpression : public Visitor<PrintSExpression> { if (curr->align != curr->bytes) { o << " align=" << curr->align; } - incIndent(); - printFullLine(curr->ptr); - printFullLine(curr->value); - decIndent(); } static void printRMWSize(std::ostream& o, Type type, uint8_t bytes) { prepareColor(o) << printType(type) << ".atomic.rmw"; @@ -394,7 +201,6 @@ struct PrintSExpression : public Visitor<PrintSExpression> { o << '.'; } void visitAtomicRMW(AtomicRMW* curr) { - o << '('; prepareColor(o); printRMWSize(o, curr->type, curr->bytes); switch (curr->op) { @@ -409,13 +215,8 @@ struct PrintSExpression : public Visitor<PrintSExpression> { if (curr->offset) { o << " offset=" << curr->offset; } - incIndent(); - printFullLine(curr->ptr); - printFullLine(curr->value); - decIndent(); } void visitAtomicCmpxchg(AtomicCmpxchg* curr) { - o << '('; prepareColor(o); printRMWSize(o, curr->type, curr->bytes); o << "cmpxchg"; @@ -423,41 +224,24 @@ struct PrintSExpression : public Visitor<PrintSExpression> { if (curr->offset) { o << " offset=" << curr->offset; } - incIndent(); - printFullLine(curr->ptr); - printFullLine(curr->expected); - printFullLine(curr->replacement); - decIndent(); } void visitAtomicWait(AtomicWait* curr) { - o << '(' ; prepareColor(o); o << printType(curr->expectedType) << ".wait"; if (curr->offset) { o << " offset=" << curr->offset; } - restoreNormalColor(o); - incIndent(); - printFullLine(curr->ptr); - printFullLine(curr->expected); - printFullLine(curr->timeout); - decIndent(); } void visitAtomicWake(AtomicWake* curr) { - printOpening(o, "wake"); + printMedium(o, "wake"); if (curr->offset) { o << " offset=" << curr->offset; } - incIndent(); - printFullLine(curr->ptr); - printFullLine(curr->wakeCount); - decIndent(); } - void visitConst(Const *curr) { + void visitConst(Const* curr) { o << curr->value; } - void visitUnary(Unary *curr) { - o << '('; + void visitUnary(Unary* curr) { prepareColor(o); switch (curr->op) { case ClzInt32: o << "i32.clz"; break; @@ -514,12 +298,8 @@ struct PrintSExpression : public Visitor<PrintSExpression> { case ExtendS32Int64: o << "i64.extend32_s"; break; default: abort(); } - incIndent(); - printFullLine(curr->value); - decIndent(); } - void visitBinary(Binary *curr) { - o << '('; + void visitBinary(Binary* curr) { prepareColor(o); switch (curr->op) { case AddInt32: o << "i32.add"; break; @@ -605,28 +385,375 @@ struct PrintSExpression : public Visitor<PrintSExpression> { default: abort(); } restoreNormalColor(o); + } + void visitSelect(Select* curr) { + prepareColor(o) << "select"; + } + void visitDrop(Drop* curr) { + printMedium(o, "drop"); + } + void visitReturn(Return* curr) { + printMedium(o, "return"); + } + void visitHost(Host* curr) { + switch (curr->op) { + case PageSize: printMedium(o, "pagesize"); break; + case CurrentMemory: printMedium(o, "current_memory"); break; + case GrowMemory: printMedium(o, "grow_memory"); break; + case HasFeature: printMedium(o, "hasfeature ") << curr->nameOperand; break; + default: WASM_UNREACHABLE(); + } + } + void visitNop(Nop* curr) { + printMinor(o, "nop"); + } + void visitUnreachable(Unreachable* curr) { + printMinor(o, "unreachable"); + } +}; + +// Prints an expression in s-expr format, including both the +// internal contents and the nested children. +struct PrintSExpression : public Visitor<PrintSExpression> { + std::ostream& o; + unsigned indent = 0; + + bool minify; + const char *maybeSpace; + const char *maybeNewLine; + + bool full = false; // whether to not elide nodes in output when possible + // (like implicit blocks) and to emit types + bool printStackIR = false; // whether to print stack IR if it is present + // (if false, and Stack IR is there, we just + // note it exists) + + Module* currModule = nullptr; + Function* currFunction = nullptr; + Function::DebugLocation lastPrintedLocation; + + std::unordered_map<Name, Index> functionIndexes; + + PrintSExpression(std::ostream& o) : o(o) { + setMinify(false); + if (!full) full = isFullForced(); + } + + void visit(Expression* curr) { + if (currFunction) { + // show an annotation, if there is one + auto& debugLocations = currFunction->debugLocations; + auto iter = debugLocations.find(curr); + if (iter != debugLocations.end()) { + auto fileName = currModule->debugInfoFileNames[iter->second.fileIndex]; + if (lastPrintedLocation != iter->second) { + lastPrintedLocation = iter->second; + o << ";;@ " << fileName << ":" << iter->second.lineNumber << ":" << iter->second.columnNumber << '\n'; + doIndent(o, indent); + } + } + } + Visitor<PrintSExpression>::visit(curr); + } + + void setMinify(bool minify_) { + minify = minify_; + maybeSpace = minify ? "" : " "; + maybeNewLine = minify ? "" : "\n"; + } + + void setFull(bool full_) { full = full_; } + + void incIndent() { + if (minify) return; + o << '\n'; + indent++; + } + void decIndent() { + if (!minify) { + indent--; + doIndent(o, indent); + } + o << ')'; + } + void printFullLine(Expression *expression) { + !minify && doIndent(o, indent); + if (full) { + o << "[" << printType(expression->type) << "] "; + } + visit(expression); + o << maybeNewLine; + } + + void visitBlock(Block* curr) { + // special-case Block, because Block nesting (in their first element) can be incredibly deep + std::vector<Block*> stack; + while (1) { + if (stack.size() > 0) doIndent(o, indent); + stack.push_back(curr); + if (full) { + o << "[" << printType(curr->type) << "] "; + } + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + if (curr->list.size() > 0 && curr->list[0]->is<Block>()) { + // recurse into the first element + curr = curr->list[0]->cast<Block>(); + continue; + } else { + break; // that's all we can recurse, start to unwind + } + } + auto* top = stack.back(); + while (stack.size() > 0) { + curr = stack.back(); + stack.pop_back(); + auto& list = curr->list; + for (size_t i = 0; i < list.size(); i++) { + if (curr != top && i == 0) { + // one of the block recursions we already handled + decIndent(); + if (full) { + o << " ;; end block"; + auto* child = list[0]->cast<Block>(); + if (child->name.is()) { + o << ' ' << child->name; + } + } + o << '\n'; + continue; + } + printFullLine(list[i]); + } + } + decIndent(); + if (full) { + o << " ;; end block"; + if (curr->name.is()) { + o << ' ' << curr->name; + } + } + } + void visitIf(If* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->condition); + // ifTrue and False have implict blocks, avoid printing them if possible + 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 (!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); + } + } + decIndent(); + if (full) { + o << " ;; end if"; + } + } + void visitLoop(Loop* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + auto block = curr->body->dynCast<Block>(); + 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) { + printFullLine(expression); + } + } else { + printFullLine(curr->body); + } + decIndent(); + if (full) { + o << " ;; end loop"; + if (curr->name.is()) { + o << ' ' << curr->name; + } + } + } + void visitBreak(Break* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + if (curr->condition) { + incIndent(); + } else { + if (!curr->value || curr->value->is<Nop>()) { + // avoid a new line just for the parens + o << ')'; + return; + } + incIndent(); + } + if (curr->value && !curr->value->is<Nop>()) printFullLine(curr->value); + if (curr->condition) { + printFullLine(curr->condition); + } + decIndent(); + } + void visitSwitch(Switch* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + if (curr->value && !curr->value->is<Nop>()) printFullLine(curr->value); + printFullLine(curr->condition); + decIndent(); + } + + template<typename CallBase> + void printCallOperands(CallBase* curr) { + if (curr->operands.size() > 0) { + incIndent(); + for (auto operand : curr->operands) { + printFullLine(operand); + } + decIndent(); + } else { + o << ')'; + } + } + + void visitCall(Call* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + printCallOperands(curr); + } + void visitCallImport(CallImport* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + printCallOperands(curr); + } + void visitCallIndirect(CallIndirect* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + for (auto operand : curr->operands) { + printFullLine(operand); + } + printFullLine(curr->target); + decIndent(); + } + void visitGetLocal(GetLocal* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitSetLocal(SetLocal* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitGetGlobal(GetGlobal* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitSetGlobal(SetGlobal* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitLoad(Load* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + decIndent(); + } + void visitStore(Store* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->value); + decIndent(); + } + void visitAtomicRMW(AtomicRMW* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->value); + decIndent(); + } + void visitAtomicCmpxchg(AtomicCmpxchg* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->expected); + printFullLine(curr->replacement); + decIndent(); + } + void visitAtomicWait(AtomicWait* curr) { + o << '(' ; + PrintExpressionContents(currFunction, o).visit(curr); + restoreNormalColor(o); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->expected); + printFullLine(curr->timeout); + decIndent(); + } + void visitAtomicWake(AtomicWake* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->wakeCount); + decIndent(); + } + void visitConst(Const* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitUnary(Unary* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitBinary(Binary* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); incIndent(); printFullLine(curr->left); printFullLine(curr->right); decIndent(); } - void visitSelect(Select *curr) { + void visitSelect(Select* curr) { o << '('; - prepareColor(o) << "select"; + PrintExpressionContents(currFunction, o).visit(curr); incIndent(); printFullLine(curr->ifTrue); printFullLine(curr->ifFalse); printFullLine(curr->condition); decIndent(); } - void visitDrop(Drop *curr) { - printOpening(o, "drop"); + void visitDrop(Drop* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); incIndent(); printFullLine(curr->value); decIndent(); } - void visitReturn(Return *curr) { - printOpening(o, "return"); + void visitReturn(Return* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); if (!curr->value) { // avoid a new line just for the parens o << ')'; @@ -636,34 +763,44 @@ struct PrintSExpression : public Visitor<PrintSExpression> { printFullLine(curr->value); decIndent(); } - void visitHost(Host *curr) { + void visitHost(Host* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); switch (curr->op) { - case PageSize: printOpening(o, "pagesize") << ')'; break; - case CurrentMemory: printOpening(o, "current_memory") << ')'; break; case GrowMemory: { - printOpening(o, "grow_memory"); incIndent(); printFullLine(curr->operands[0]); decIndent(); break; } - case HasFeature: printOpening(o, "hasfeature ") << curr->nameOperand << ')'; break; - default: abort(); + case HasFeature: { + o << curr->nameOperand; + o << ')'; + break; + } + default: { + o << ')'; + } } } - void visitNop(Nop *curr) { - printMinorOpening(o, "nop") << ')'; + void visitNop(Nop* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; } - void visitUnreachable(Unreachable *curr) { - printMinorOpening(o, "unreachable") << ')'; + void visitUnreachable(Unreachable* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; } // Module-level visitors - void visitFunctionType(FunctionType *curr, Name* internalName = nullptr) { + void visitFunctionType(FunctionType* curr, Name* internalName = nullptr) { o << "(func"; if (internalName) o << ' ' << *internalName; if (curr->params.size() > 0) { o << maybeSpace; - printMinorOpening(o, "param"); + o << '('; + printMinor(o, "param"); for (auto& param : curr->params) { o << ' ' << printType(param); } @@ -671,12 +808,14 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } if (curr->result != none) { o << maybeSpace; - printMinorOpening(o, "result ") << printType(curr->result) << ')'; + o << '('; + printMinor(o, "result ") << printType(curr->result) << ')'; } o << ")"; } - void visitImport(Import *curr) { - printOpening(o, "import "); + void visitImport(Import* curr) { + o << '('; + printMedium(o, "import "); printText(o, curr->module.str) << ' '; printText(o, curr->base.str) << ' '; switch (curr->kind) { @@ -688,8 +827,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } o << ')'; } - void visitExport(Export *curr) { - printOpening(o, "export "); + void visitExport(Export* curr) { + o << '('; + printMedium(o, "export "); printText(o, curr->name.str) << " ("; switch (curr->kind) { case ExternalKind::Function: o << "func"; break; @@ -699,11 +839,12 @@ struct PrintSExpression : public Visitor<PrintSExpression> { default: WASM_UNREACHABLE(); } o << ' '; - printName(curr->value) << "))"; + printName(curr->value, o) << "))"; } - void visitGlobal(Global *curr) { - printOpening(o, "global "); - printName(curr->name) << ' '; + void visitGlobal(Global* curr) { + o << '('; + printMedium(o, "global "); + printName(curr->name, o) << ' '; if (curr->mutable_) { o << "(mut " << printType(curr->type) << ") "; } else { @@ -712,11 +853,12 @@ struct PrintSExpression : public Visitor<PrintSExpression> { visit(curr->init); o << ')'; } - void visitFunction(Function *curr) { + void visitFunction(Function* curr) { currFunction = curr; lastPrintedLocation = { 0, 0, 0 }; - printOpening(o, "func ", true); - printName(curr->name); + o << '('; + printMajor(o, "func "); + printName(curr->name, o); if (currModule && !minify) { // emit the function index in a comment if (functionIndexes.empty()) { @@ -734,38 +876,48 @@ struct PrintSExpression : public Visitor<PrintSExpression> { if (curr->params.size() > 0) { for (size_t i = 0; i < curr->params.size(); i++) { o << maybeSpace; - printMinorOpening(o, "param ") << printableLocal(i) << ' ' << printType(curr->getLocalType(i)) << ')'; + o << '('; + printMinor(o, "param ") << printableLocal(i, currFunction) << ' ' << printType(curr->getLocalType(i)) << ')'; } } if (curr->result != none) { o << maybeSpace; - printMinorOpening(o, "result ") << printType(curr->result) << ')'; + o << '('; + printMinor(o, "result ") << printType(curr->result) << ')'; } incIndent(); for (size_t i = curr->getVarIndexBase(); i < curr->getNumLocals(); i++) { doIndent(o, indent); - printMinorOpening(o, "local ") << printableLocal(i) << ' ' << printType(curr->getLocalType(i)) << ')'; + o << '('; + printMinor(o, "local ") << printableLocal(i, currFunction) << ' ' << printType(curr->getLocalType(i)) << ')'; o << maybeNewLine; } - // 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 (!full && curr->body->is<Block>() && curr->body->cast<Block>()->name.isNull()) { - Block* block = curr->body->cast<Block>(); - for (auto item : block->list) { - printFullLine(item); + // Print the body. + if (!printStackIR || !curr->stackIR) { + // 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 (!full && curr->body->is<Block>() && curr->body->cast<Block>()->name.isNull()) { + Block* block = curr->body->cast<Block>(); + for (auto item : block->list) { + printFullLine(item); + } + } else { + printFullLine(curr->body); } } else { - printFullLine(curr->body); + // Print the stack IR. + WasmPrinter::printStackIR(curr->stackIR.get(), o, curr); } decIndent(); } void printTableHeader(Table* curr) { - printOpening(o, "table") << ' '; + o << '('; + printMedium(o, "table") << ' '; o << curr->initial; if (curr->hasMax()) o << ' ' << curr->max; o << " anyfunc)"; } - void visitTable(Table *curr) { + void visitTable(Table* curr) { if (!curr->exists) return; // if table wasn't imported, declare it if (!curr->imported) { @@ -777,19 +929,24 @@ struct PrintSExpression : public Visitor<PrintSExpression> { // Don't print empty segments if (segment.data.empty()) continue; doIndent(o, indent); - printOpening(o, "elem ", true); + o << '('; + printMajor(o, "elem "); visit(segment.offset); for (auto name : segment.data) { o << ' '; - printName(name); + printName(name, o); } o << ")\n"; } } void printMemoryHeader(Memory* curr) { - printOpening(o, "memory") << ' '; - printName(curr->name) << ' '; - if (curr->shared) printOpening(o, "shared "); + o << '('; + printMedium(o, "memory") << ' '; + printName(curr->name, o) << ' '; + if (curr->shared) { + o << '('; + printMedium(o, "shared "); + } o << curr->initial; if (curr->hasMax()) o << ' ' << curr->max; if (curr->shared) o << ")"; @@ -805,7 +962,8 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } for (auto segment : curr->segments) { doIndent(o, indent); - printOpening(o, "data ", true); + o << '('; + printMajor(o, "data "); visit(segment.offset); o << " \""; for (size_t i = 0; i < segment.data.size(); i++) { @@ -831,14 +989,16 @@ struct PrintSExpression : public Visitor<PrintSExpression> { o << "\")\n"; } } - void visitModule(Module *curr) { + void visitModule(Module* curr) { currModule = curr; - printOpening(o, "module", true); + o << '('; + printMajor(o, "module"); incIndent(); for (auto& child : curr->functionTypes) { doIndent(o, indent); - printOpening(o, "type") << ' '; - printName(child->name) << ' '; + o << '('; + printMedium(o, "type") << ' '; + printName(child->name, o) << ' '; visitFunctionType(child.get()); o << ")" << maybeNewLine; } @@ -863,7 +1023,8 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } if (curr->start.is()) { doIndent(o, indent); - printOpening(o, "start") << ' ' << curr->start << ')'; + o << '('; + printMedium(o, "start") << ' ' << curr->start << ')'; o << maybeNewLine; } for (auto& child : curr->functions) { @@ -939,6 +1100,24 @@ Pass *createFullPrinterPass() { return new FullPrinter(); } +// Print Stack IR (if present) + +class PrintStackIR : public Printer { +public: + PrintStackIR() : Printer() {} + PrintStackIR(std::ostream* o) : Printer(o) {} + + void run(PassRunner* runner, Module* module) override { + PrintSExpression print(o); + print.printStackIR = true; + print.visitModule(module); + } +}; + +Pass* createPrintStackIRPass() { + return new PrintStackIR(); +} + // Print individual expressions std::ostream& WasmPrinter::printModule(Module* module, std::ostream& o) { @@ -969,4 +1148,78 @@ std::ostream& WasmPrinter::printExpression(Expression* expression, std::ostream& return o; } +std::ostream& WasmPrinter::printStackInst(StackInst* inst, std::ostream& o, Function* func) { + switch (inst->op) { + case StackInst::Basic: { + PrintExpressionContents(func, o).visit(inst->origin); + break; + } + case StackInst::BlockBegin: + case StackInst::IfBegin: + case StackInst::LoopBegin: { + o << getExpressionName(inst->origin); + break; + } + case StackInst::BlockEnd: + case StackInst::IfEnd: + case StackInst::LoopEnd: { + o << "end (" << printType(inst->type) << ')'; + break; + } + case StackInst::IfElse: { + o << "else"; + break; + } + default: WASM_UNREACHABLE(); + } + return o; +} + +std::ostream& WasmPrinter::printStackIR(StackIR* ir, std::ostream& o, Function* func) { + size_t indent = func ? 2 : 0; + auto doIndent = [&indent, &o]() { + for (size_t j = 0; j < indent; j++) { + o << ' '; + } + }; + for (Index i = 0; i < (*ir).size(); i++) { + auto* inst = (*ir)[i]; + if (!inst) continue; + switch (inst->op) { + case StackInst::Basic: { + doIndent(); + PrintExpressionContents(func, o).visit(inst->origin); + break; + } + case StackInst::BlockBegin: + case StackInst::IfBegin: + case StackInst::LoopBegin: { + doIndent(); + PrintExpressionContents(func, o).visit(inst->origin); + indent++; + break; + } + case StackInst::BlockEnd: + case StackInst::IfEnd: + case StackInst::LoopEnd: { + indent--; + doIndent(); + o << "end"; + break; + } + case StackInst::IfElse: { + indent--; + doIndent(); + o << "else"; + indent++; + doIndent(); + break; + } + default: WASM_UNREACHABLE(); + } + std::cout << '\n'; + } + return o; +} + } // namespace wasm diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp index 43c95608e..3772500c4 100644 --- a/src/passes/StackIR.cpp +++ b/src/passes/StackIR.cpp @@ -71,32 +71,6 @@ Pass* createGenerateStackIRPass() { return new GenerateStackIR(); } -// Print (for debugging purposes) - -struct PrintStackIR : public WalkerPass<PostWalker<PrintStackIR>> { - // Not parallel: this pass is just for testing and debugging; keep the output - // sorted by function order. - bool isFunctionParallel() override { return false; } - - Pass* create() override { return new PrintStackIR; } - - bool modifiesBinaryenIR() override { return false; } - - void doWalkFunction(Function* func) { - std::cout << func->name << ":\n"; - if (func->stackIR) { - std::cout << *func->stackIR; - } else { - std::cout << " (no stack ir)"; - } - std::cout << '\n'; - } -}; - -Pass* createPrintStackIRPass() { - return new PrintStackIR(); -} - // Optimize class StackIROptimizer { diff --git a/src/pretty_printing.h b/src/pretty_printing.h index f1ba944f4..c5d755dcc 100644 --- a/src/pretty_printing.h +++ b/src/pretty_printing.h @@ -62,16 +62,21 @@ inline std::ostream& printText(std::ostream &o, const char *str) { return o << '"'; } -inline std::ostream& printOpening(std::ostream &o, const char *str, bool major=false) { - o << '('; - major ? prepareMajorColor(o) : prepareColor(o); +inline std::ostream& printMajor(std::ostream &o, const char *str, bool major=false) { + prepareMajorColor(o); o << str; restoreNormalColor(o); return o; } -inline std::ostream& printMinorOpening(std::ostream &o, const char *str) { - o << '('; +inline std::ostream& printMedium(std::ostream &o, const char *str, bool major=false) { + prepareColor(o); + o << str; + restoreNormalColor(o); + return o; +} + +inline std::ostream& printMinor(std::ostream &o, const char *str) { prepareMinorColor(o); o << str; restoreNormalColor(o); diff --git a/src/shell-interface.h b/src/shell-interface.h index 0a98ce05a..5b01b4be6 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -138,7 +138,7 @@ struct ShellExternalInterface final : ModuleInstance::ExternalInterface { Literal callImport(Import *import, LiteralList& arguments) override { if (import->module == SPECTEST && import->base == PRINT) { for (auto argument : arguments) { - std::cout << argument << '\n'; + std::cout << '(' << argument << ')' << '\n'; } return Literal(); } else if (import->module == ENV && import->base == EXIT) { diff --git a/src/wasm-printing.h b/src/wasm-printing.h index 936c118ee..d3327aa4c 100644 --- a/src/wasm-printing.h +++ b/src/wasm-printing.h @@ -30,9 +30,13 @@ struct WasmPrinter { static std::ostream& printModule(Module* module); static std::ostream& printExpression(Expression* expression, std::ostream& o, bool minify = false, bool full = false); + + static std::ostream& printStackInst(StackInst* inst, std::ostream& o, Function* func=nullptr); + + static std::ostream& printStackIR(StackIR* ir, std::ostream& o, Function* func=nullptr); }; -} +} // namespace wasm namespace std { @@ -44,6 +48,14 @@ inline std::ostream& operator<<(std::ostream& o, wasm::Expression& expression) { return wasm::WasmPrinter::printExpression(&expression, o); } +inline std::ostream& operator<<(std::ostream& o, wasm::StackInst& inst) { + return wasm::WasmPrinter::printStackInst(&inst, o); } +inline std::ostream& operator<<(std::ostream& o, wasm::StackIR& ir) { + return wasm::WasmPrinter::printStackIR(&ir, o); +} + +} // namespace std + #endif // wasm_wasm_printing_h diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 8648148b6..fffc0ce45 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -70,51 +70,6 @@ public: // e.g. wasm has no unreachable blocks, they must be none }; -} // namespace wasm - -namespace std { - -inline std::ostream& operator<<(std::ostream& o, wasm::StackInst& inst) { - switch (inst.op) { - case wasm::StackInst::Basic: { - std::cout << wasm::getExpressionName(inst.origin) << " (" << wasm::printType(inst.type) << ')'; - break; - } - case wasm::StackInst::BlockBegin: - case wasm::StackInst::IfBegin: - case wasm::StackInst::LoopBegin: { - std::cout << wasm::getExpressionName(inst.origin); - break; - } - case wasm::StackInst::BlockEnd: - case wasm::StackInst::IfEnd: - case wasm::StackInst::LoopEnd: { - std::cout << "end (" << wasm::printType(inst.type) << ')'; - break; - } - case wasm::StackInst::IfElse: { - std::cout << "else"; - break; - } - default: WASM_UNREACHABLE(); - } - return o; -} - -inline std::ostream& operator<<(std::ostream& o, wasm::StackIR& insts) { - wasm::Index index = 0; - for (wasm::Index i = 0; i < insts.size(); i++) { - auto* inst = insts[i]; - if (!inst) continue; - std::cout << index++ << ' ' << *inst << '\n'; - } - return o; -} - -} // namespace std - -namespace wasm { - // // StackWriter: Writes out binary format stack machine code for a Binaryen IR expression // diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index e68dd5d5f..032b3f7f8 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -168,7 +168,6 @@ void Literal::printDouble(std::ostream& o, double d) { } std::ostream& operator<<(std::ostream& o, Literal literal) { - o << '('; prepareMinorColor(o) << printType(literal.type) << ".const "; switch (literal.type) { case none: o << "?"; break; @@ -179,7 +178,7 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { default: WASM_UNREACHABLE(); } restoreNormalColor(o); - return o << ')'; + return o; } Literal Literal::countLeadingZeroes() const { diff --git a/test/passes/O1_print-stack-ir.txt b/test/passes/O1_print-stack-ir.txt index ab3bf9255..503842124 100644 --- a/test/passes/O1_print-stack-ir.txt +++ b/test/passes/O1_print-stack-ir.txt @@ -1,5 +1,30 @@ -$stacky-help: - (no stack ir) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (; 0 ;) (type $0) (param $0 i32) (result i32) + (local $1 i32) + (i32.add + (call $stacky-help + (i32.const 0) + ) + (block (result i32) + (set_local $1 + (call $stacky-help + (i32.const 1) + ) + ) + (drop + (call $stacky-help + (i32.const 2) + ) + ) + (i32.eqz + (get_local $1) + ) + ) + ) + ) +) (module (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) diff --git a/test/passes/O2_precompute-propagate_print-stack-ir.txt b/test/passes/O2_precompute-propagate_print-stack-ir.txt index 6c3ee8ee1..909e81b85 100644 --- a/test/passes/O2_precompute-propagate_print-stack-ir.txt +++ b/test/passes/O2_precompute-propagate_print-stack-ir.txt @@ -1,5 +1,17 @@ -$0: - (no stack ir) +(module + (type $0 (func (param i32 i32 i32 i64) (result i64))) + (export "func" (func $0)) + (func $0 (; 0 ;) (type $0) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i64) (result i64) + (local $4 i32) + (block $label$1 + (set_local $3 + (i64.const 2147483647) + ) + (nop) + ) + (i64.const 2147483647) + ) +) (module (type $0 (func (param i32 i32 i32 i64) (result i64))) (export "func" (func $0)) diff --git a/test/passes/O2_print-stack-ir.txt b/test/passes/O2_print-stack-ir.txt index aa2a91528..9cbb43bf2 100644 --- a/test/passes/O2_print-stack-ir.txt +++ b/test/passes/O2_print-stack-ir.txt @@ -1,16 +1,21 @@ -$stacky-help: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 set_local (none) -5 const (i32) -6 call (i32) -7 drop (none) -8 get_local (i32) -9 unary (i32) -10 binary (i32) - +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (; 0 ;) (; has Stack IR ;) (type $0) (param $0 i32) (result i32) + (local $1 i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + set_local $1 + i32.const 2 + call $stacky-help + drop + get_local $1 + i32.eqz + i32.add + ) +) (module (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) diff --git a/test/passes/O3_print-stack-ir.txt b/test/passes/O3_print-stack-ir.txt index ca1cc46ba..3d56f1c0d 100644 --- a/test/passes/O3_print-stack-ir.txt +++ b/test/passes/O3_print-stack-ir.txt @@ -1,14 +1,19 @@ -$stacky-help: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 const (i32) -5 call (i32) -6 drop (none) -7 unary (i32) -8 binary (i32) - +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (; 0 ;) (; has Stack IR ;) (type $0) (param $0 i32) (result i32) + (local $1 i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + i32.const 2 + call $stacky-help + drop + i32.eqz + i32.add + ) +) (module (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) diff --git a/test/passes/Os_print-stack-ir.txt b/test/passes/Os_print-stack-ir.txt index ca1cc46ba..3d56f1c0d 100644 --- a/test/passes/Os_print-stack-ir.txt +++ b/test/passes/Os_print-stack-ir.txt @@ -1,14 +1,19 @@ -$stacky-help: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 const (i32) -5 call (i32) -6 drop (none) -7 unary (i32) -8 binary (i32) - +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (; 0 ;) (; has Stack IR ;) (type $0) (param $0 i32) (result i32) + (local $1 i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + i32.const 2 + call $stacky-help + drop + i32.eqz + i32.add + ) +) (module (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) diff --git a/test/passes/fuzz-exec.txt b/test/passes/fuzz-exec.txt index 926803150..0c1186bc7 100644 --- a/test/passes/fuzz-exec.txt +++ b/test/passes/fuzz-exec.txt @@ -1,8 +1,8 @@ -[fuzz-exec] note result: $a => (i32.const -69) -[fuzz-exec] note result: $b => (i32.const -31768) -[fuzz-exec] note result: $c => (i64.const -69) -[fuzz-exec] note result: $d => (i64.const -31768) -[fuzz-exec] note result: $e => (i64.const -2146649112) +[fuzz-exec] note result: $a => i32.const -69 +[fuzz-exec] note result: $b => i32.const -31768 +[fuzz-exec] note result: $c => i64.const -69 +[fuzz-exec] note result: $d => i64.const -31768 +[fuzz-exec] note result: $e => i64.const -2146649112 [fuzz-exec] 5 results noted (module (type $0 (func (result i32))) @@ -38,11 +38,11 @@ ) ) ) -[fuzz-exec] note result: $a => (i32.const -69) -[fuzz-exec] note result: $b => (i32.const -31768) -[fuzz-exec] note result: $c => (i64.const -69) -[fuzz-exec] note result: $d => (i64.const -31768) -[fuzz-exec] note result: $e => (i64.const -2146649112) +[fuzz-exec] note result: $a => i32.const -69 +[fuzz-exec] note result: $b => i32.const -31768 +[fuzz-exec] note result: $c => i64.const -69 +[fuzz-exec] note result: $d => i64.const -31768 +[fuzz-exec] note result: $e => i64.const -2146649112 [fuzz-exec] 5 results noted [fuzz-exec] comparing $a [fuzz-exec] comparing $b diff --git a/test/passes/fuzz-exec_O.txt b/test/passes/fuzz-exec_O.txt index dd90a838c..76141fcc5 100644 --- a/test/passes/fuzz-exec_O.txt +++ b/test/passes/fuzz-exec_O.txt @@ -1,5 +1,5 @@ -[fuzz-exec] note result: $func_0 => (none.const ?) -[fuzz-exec] note result: $func_1 => (none.const ?) +[fuzz-exec] note result: $func_0 => none.const ? +[fuzz-exec] note result: $func_1 => none.const ? [fuzz-exec] 2 results noted (module (type $0 (func (result i64))) @@ -23,8 +23,8 @@ ) ) ) -[fuzz-exec] note result: $func_0 => (none.const ?) -[fuzz-exec] note result: $func_1 => (none.const ?) +[fuzz-exec] note result: $func_0 => none.const ? +[fuzz-exec] note result: $func_1 => none.const ? [fuzz-exec] 2 results noted [fuzz-exec] comparing $func_0 [fuzz-exec] comparing $func_1 diff --git a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt b/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt index 11c33366c..627f5bd19 100644 --- a/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt +++ b/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt @@ -1,573 +1,633 @@ -$big_negative: -0 const (f64) -1 set_local (none) -2 const (f64) -3 set_local (none) -4 const (f64) -5 set_local (none) -6 const (f64) -7 set_local (none) -8 const (f64) -9 set_local (none) - -$importedDoubles: -0 block -1 const (i32) -2 load (f64) -3 const (i32) -4 load (f64) -5 binary (f64) -6 const (i32) -7 load (f64) -8 unary (f64) -9 binary (f64) -10 const (i32) -11 load (f64) -12 unary (f64) -13 binary (f64) -14 set_local (none) -15 const (i32) -16 load (i32) -17 const (i32) -18 binary (i32) -19 if -20 const (f64) -21 break (unreachable) -22 end (none) -23 const (i32) -24 load (f64) -25 const (f64) -26 binary (i32) -27 if -28 const (f64) -29 break (unreachable) -30 end (none) -31 const (f64) -32 end (f64) - -$doubleCompares: -0 block -1 get_local (f64) -2 const (f64) -3 binary (i32) -4 if -5 const (f64) -6 break (unreachable) -7 end (none) -8 get_local (f64) -9 const (f64) -10 binary (i32) -11 if -12 const (f64) -13 break (unreachable) -14 end (none) -15 get_local (i32) -16 const (i32) -17 binary (i32) -18 if -19 const (f64) -20 break (unreachable) -21 end (none) -22 get_local (f64) -23 get_local (f64) -24 binary (i32) -25 if -26 get_local (f64) -27 break (unreachable) -28 end (none) -29 get_local (f64) -30 end (f64) - -$intOps: -0 get_local (i32) -1 const (i32) -2 binary (i32) - -$hexLiterals: -0 const (i32) -1 const (i32) -2 binary (i32) -3 const (i32) -4 binary (i32) -5 drop (none) - -$conversions: -0 get_local (f64) -1 call_import (i32) -2 set_local (none) -3 get_local (i32) -4 unary (f64) -5 set_local (none) -6 get_local (i32) -7 const (i32) -8 binary (i32) -9 unary (f64) -10 set_local (none) - -$seq: -0 const (f64) -1 drop (none) -2 const (f64) -3 const (f64) -4 drop (none) -5 const (f64) -6 binary (f64) -7 set_local (none) - -$switcher: -0 block -1 block -2 block -3 block -4 get_local (i32) -5 const (i32) -6 binary (i32) -7 switch (unreachable) -8 end (none) -9 const (i32) -10 break (unreachable) -11 end (none) -12 const (i32) -13 break (unreachable) -14 end (none) -15 nop (none) -16 block -17 block -18 block -19 get_local (i32) -20 const (i32) -21 binary (i32) -22 switch (unreachable) -23 end (none) -24 const (i32) -25 break (unreachable) -26 end (none) -27 const (i32) -28 break (unreachable) -29 end (none) -30 nop (none) -31 block -32 block -33 block -34 block -35 block -36 block -37 get_local (i32) -38 const (i32) -39 binary (i32) -40 switch (unreachable) -41 end (none) -42 break (unreachable) -43 end (none) -44 break (unreachable) -45 end (none) -46 block -47 loop -48 break (unreachable) -49 end (none) -50 unreachable (unreachable) -51 end (none) -52 end (none) -53 loop -54 break (unreachable) -55 end (none) -56 unreachable (unreachable) -57 end (none) -58 nop (none) -59 end (none) -60 const (i32) -61 end (i32) - -$blocker: -0 block -1 break (unreachable) -2 end (none) - -$frem: -0 const (f64) -1 const (f64) -2 call_import (f64) - -$big_uint_div_u: -0 const (i32) -1 const (i32) -2 binary (i32) -3 const (i32) -4 binary (i32) - -$fr: -0 get_local (f64) -1 unary (f32) -2 drop (none) -3 get_local (f32) -4 drop (none) -5 const (f32) -6 drop (none) -7 const (f32) -8 drop (none) -9 const (f32) -10 drop (none) -11 const (f32) -12 drop (none) - -$negZero: -0 const (f64) - -$abs: -0 const (i32) -1 set_local (none) -2 const (i32) -3 get_local (i32) -4 binary (i32) -5 get_local (i32) -6 get_local (i32) -7 const (i32) -8 binary (i32) -9 select (i32) -10 set_local (none) -11 const (f64) -12 unary (f64) -13 set_local (none) -14 const (f32) -15 unary (f32) -16 set_local (none) - -$neg: -0 get_local (f32) -1 unary (f32) -2 const (i32) -3 const (i32) -4 binary (i32) -5 const (i32) -6 binary (i32) -7 call_indirect (none) - -$cneg: -0 get_local (f32) -1 const (i32) -2 const (i32) -3 binary (i32) -4 const (i32) -5 binary (i32) -6 call_indirect (none) - -$___syscall_ret: -0 get_local (i32) -1 const (i32) -2 binary (i32) -3 const (i32) -4 binary (i32) -5 drop (none) - -$z: -0 nop (none) - -$w: -0 nop (none) - -$block_and_after: -0 block -1 const (i32) -2 drop (none) -3 break (unreachable) -4 end (none) -5 const (i32) - -$loop-roundtrip: -0 loop -1 get_local (f64) -2 drop (none) -3 get_local (f64) -4 end (f64) - -$big-i64: -0 const (i64) - -$i64-store32: -0 get_local (i32) -1 get_local (i64) -2 store (none) - -$return-unreachable: -0 const (i32) -1 return (unreachable) - -$unreachable-block: -0 const (i32) -1 drop (none) -2 const (i32) -3 return (unreachable) - -$unreachable-block-toplevel: -0 const (i32) -1 drop (none) -2 const (i32) -3 return (unreachable) - -$unreachable-block0: -0 const (i32) -1 return (unreachable) - -$unreachable-block0-toplevel: -0 const (i32) -1 return (unreachable) - -$unreachable-block-with-br: -0 block -1 const (i32) -2 drop (none) -3 break (unreachable) -4 end (none) -5 const (i32) - -$unreachable-if: -0 const (i32) -1 if -2 const (i32) -3 return (unreachable) -4 else -5 const (i32) -6 return (unreachable) -7 end (none) -8 unreachable (unreachable) - -$unreachable-if-toplevel: -0 const (i32) -1 if -2 const (i32) -3 return (unreachable) -4 else -5 const (i32) -6 return (unreachable) -7 end (none) -8 unreachable (unreachable) - -$unreachable-loop: -0 loop -1 nop (none) -2 const (i32) -3 return (unreachable) -4 end (none) -5 unreachable (unreachable) - -$unreachable-loop0: -0 loop -1 const (i32) -2 return (unreachable) -3 end (none) -4 unreachable (unreachable) - -$unreachable-loop-toplevel: -0 loop -1 nop (none) -2 const (i32) -3 return (unreachable) -4 end (none) -5 unreachable (unreachable) - -$unreachable-loop0-toplevel: -0 loop -1 const (i32) -2 return (unreachable) -3 end (none) -4 unreachable (unreachable) - -$unreachable-ifs: -0 unreachable (unreachable) - -$unreachable-if-arm: -0 const (i32) -1 if -2 nop (none) -3 else -4 unreachable (unreachable) -5 end (none) - -$local-to-stack: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 drop (none) - -$local-to-stack-1: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 drop (none) -5 unary (i32) - -$local-to-stack-1b: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 drop (none) -5 const (i32) -6 binary (i32) - -$local-to-stack-1c-no: -0 const (i32) -1 call (i32) -2 set_local (none) -3 const (i32) -4 call (i32) -5 drop (none) -6 const (i32) -7 get_local (i32) -8 binary (i32) - -$local-to-stack-2-no: -0 const (i32) -1 call (i32) -2 set_local (none) -3 const (i32) -4 call (i32) -5 drop (none) -6 get_local (i32) -7 get_local (i32) -8 binary (i32) - -$local-to-stack-3-no: -0 const (i32) -1 if -2 const (i32) -3 call (i32) -4 set_local (none) -5 else -6 const (i32) -7 call (i32) -8 set_local (none) -9 end (none) -10 const (i32) -11 call (i32) -12 drop (none) -13 get_local (i32) - -$local-to-stack-multi-4: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 drop (none) -5 drop (none) -6 const (i32) -7 call (i32) -8 const (i32) -9 call (i32) -10 drop (none) - -$local-to-stack-multi-5: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 drop (none) -5 drop (none) -6 const (i32) -7 call (i32) -8 const (i32) -9 call (i32) -10 drop (none) - -$local-to-stack-multi-6-justone: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 drop (none) -5 drop (none) -6 const (i32) -7 call (i32) -8 set_local (none) -9 const (i32) -10 call (i32) -11 drop (none) -12 get_local (i32) -13 get_local (i32) -14 binary (i32) - -$local-to-stack-multi-7-justone: -0 const (i32) -1 call (i32) -2 set_local (none) -3 const (i32) -4 call (i32) -5 drop (none) -6 get_local (i32) -7 get_local (i32) -8 binary (i32) -9 drop (none) -10 const (i32) -11 call (i32) -12 const (i32) -13 call (i32) -14 drop (none) - -$local-to-stack-overlapping-multi-8-no: -0 const (i32) -1 call (i32) -2 set_local (none) -3 const (i32) -4 call (i32) -5 const (i32) -6 call (i32) -7 drop (none) -8 get_local (i32) -9 binary (i32) - -$local-to-stack-overlapping-multi-9-yes: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 const (i32) -5 call (i32) -6 drop (none) -7 binary (i32) - -$local-to-stack-through-control-flow: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 const (i32) -5 if -6 nop (none) -7 end (none) -8 drop (none) -9 const (i32) -10 call (i32) -11 block -12 break (unreachable) -13 end (none) -14 drop (none) -15 drop (none) - -$local-to-stack-in-control-flow: -0 const (i32) -1 if -2 const (i32) -3 call (i32) -4 drop (none) -5 else -6 const (i32) -7 call (i32) -8 drop (none) -9 end (none) - -$remove-block: -0 const (i32) -1 call (i32) -2 const (i32) -3 call (i32) -4 const (i32) -5 call (i32) -6 drop (none) -7 unary (i32) -8 binary (i32) - +(module + (type $FUNCSIG$vf (func (param f32))) + (type $FUNCSIG$v (func)) + (type $FUNCSIG$id (func (param f64) (result i32))) + (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) + (type $4 (func (result f64))) + (type $5 (func (result i32))) + (type $6 (func (param i32) (result i32))) + (type $7 (func (param f64) (result f64))) + (type $8 (func (result i64))) + (type $9 (func (param i32 i64))) + (import "env" "_emscripten_asm_const_vi" (func $_emscripten_asm_const_vi)) + (import "asm2wasm" "f64-to-int" (func $f64-to-int (param f64) (result i32))) + (import "asm2wasm" "f64-rem" (func $f64-rem (param f64 f64) (result f64))) + (table 10 anyfunc) + (elem (i32.const 0) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) + (memory $0 4096 4096) + (data (i32.const 1026) "\14\00") + (export "big_negative" (func $big_negative)) + (func $big_negative (; 3 ;) (; has Stack IR ;) (type $FUNCSIG$v) + (local $temp f64) + f64.const -2147483648 + set_local $temp + f64.const -2147483648 + set_local $temp + f64.const -21474836480 + set_local $temp + f64.const 0.039625 + set_local $temp + f64.const -0.039625 + set_local $temp + ) + (func $importedDoubles (; 4 ;) (; has Stack IR ;) (type $4) (result f64) + (local $temp f64) + block $topmost (result f64) + i32.const 8 + f64.load + i32.const 16 + f64.load + f64.add + i32.const 16 + f64.load + f64.neg + f64.add + i32.const 8 + f64.load + f64.neg + f64.add + set_local $temp + i32.const 24 + i32.load + i32.const 0 + i32.gt_s + if + f64.const -3.4 + br $topmost + end + i32.const 32 + f64.load + f64.const 0 + f64.gt + if + f64.const 5.6 + br $topmost + end + f64.const 1.2 + end + ) + (func $doubleCompares (; 5 ;) (; has Stack IR ;) (type $FUNCSIG$ddd) (param $x f64) (param $y f64) (result f64) + (local $t f64) + (local $Int f64) + (local $Double i32) + block $topmost (result f64) + get_local $x + f64.const 0 + f64.gt + if + f64.const 1.2 + br $topmost + end + get_local $Int + f64.const 0 + f64.gt + if + f64.const -3.4 + br $topmost + end + get_local $Double + i32.const 0 + i32.gt_s + if + f64.const 5.6 + br $topmost + end + get_local $x + get_local $y + f64.lt + if + get_local $x + br $topmost + end + get_local $y + end + ) + (func $intOps (; 6 ;) (; has Stack IR ;) (type $5) (result i32) + (local $x i32) + get_local $x + i32.const 0 + i32.eq + ) + (func $hexLiterals (; 7 ;) (; has Stack IR ;) (type $FUNCSIG$v) + i32.const 0 + i32.const 313249263 + i32.add + i32.const -19088752 + i32.add + drop + ) + (func $conversions (; 8 ;) (; has Stack IR ;) (type $FUNCSIG$v) + (local $i i32) + (local $d f64) + get_local $d + call $f64-to-int + set_local $i + get_local $i + f64.convert_s/i32 + set_local $d + get_local $i + i32.const 0 + i32.shr_u + f64.convert_u/i32 + set_local $d + ) + (func $seq (; 9 ;) (; has Stack IR ;) (type $FUNCSIG$v) + (local $J f64) + f64.const 0.1 + drop + f64.const 5.1 + f64.const 3.2 + drop + f64.const 4.2 + f64.sub + set_local $J + ) + (func $switcher (; 10 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + block $topmost (result i32) + block $switch-default$3 + block $switch-case$2 + block $switch-case$1 + get_local $x + i32.const 1 + i32.sub + br_table $switch-case$1 $switch-case$2 $switch-default$3 + end + i32.const 1 + br $topmost + end + i32.const 2 + br $topmost + end + nop + block $switch-default$7 + block $switch-case$6 + block $switch-case$5 + get_local $x + i32.const 5 + i32.sub + br_table $switch-case$6 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-case$5 $switch-default$7 + end + i32.const 121 + br $topmost + end + i32.const 51 + br $topmost + end + nop + block $label$break$Lout + block $switch-default$16 + block $switch-case$15 + block $switch-case$12 + block $switch-case$9 + block $switch-case$8 + get_local $x + i32.const 2 + i32.sub + br_table $switch-case$15 $switch-default$16 $switch-default$16 $switch-case$12 $switch-default$16 $switch-default$16 $switch-default$16 $switch-default$16 $switch-case$9 $switch-default$16 $switch-case$8 $switch-default$16 + end + br $label$break$Lout + end + br $label$break$Lout + end + block $while-out$10 + loop $while-in$11 + br $while-out$10 + end + unreachable + end + end + loop $while-in$14 + br $label$break$Lout + end + unreachable + end + nop + end + i32.const 0 + end + ) + (func $blocker (; 11 ;) (; has Stack IR ;) (type $FUNCSIG$v) + block $label$break$L + br $label$break$L + end + ) + (func $frem (; 12 ;) (; has Stack IR ;) (type $4) (result f64) + f64.const 5.5 + f64.const 1.2 + call $f64-rem + ) + (func $big_uint_div_u (; 13 ;) (; has Stack IR ;) (type $5) (result i32) + (local $x i32) + i32.const -1 + i32.const 2 + i32.div_u + i32.const -1 + i32.and + ) + (func $fr (; 14 ;) (; has Stack IR ;) (type $FUNCSIG$vf) (param $x f32) + (local $y f32) + (local $z f64) + get_local $z + f32.demote/f64 + drop + get_local $y + drop + f32.const 5 + drop + f32.const 0 + drop + f32.const 5 + drop + f32.const 0 + drop + ) + (func $negZero (; 15 ;) (; has Stack IR ;) (type $4) (result f64) + f64.const -0 + ) + (func $abs (; 16 ;) (; has Stack IR ;) (type $FUNCSIG$v) + (local $x i32) + (local $y f64) + (local $z f32) + (local $asm2wasm_i32_temp i32) + i32.const 0 + set_local $asm2wasm_i32_temp + i32.const 0 + get_local $asm2wasm_i32_temp + i32.sub + get_local $asm2wasm_i32_temp + get_local $asm2wasm_i32_temp + i32.const 0 + i32.lt_s + select + set_local $x + f64.const 0 + f64.abs + set_local $y + f32.const 0 + f32.abs + set_local $z + ) + (func $neg (; 17 ;) (; has Stack IR ;) (type $FUNCSIG$v) + (local $x f32) + get_local $x + f32.neg + i32.const 1 + i32.const 7 + i32.and + i32.const 8 + i32.add + call_indirect (type $FUNCSIG$vf) + ) + (func $cneg (; 18 ;) (; has Stack IR ;) (type $FUNCSIG$vf) (param $x f32) + get_local $x + i32.const 1 + i32.const 7 + i32.and + i32.const 8 + i32.add + call_indirect (type $FUNCSIG$vf) + ) + (func $___syscall_ret (; 19 ;) (; has Stack IR ;) (type $FUNCSIG$v) + (local $$0 i32) + get_local $$0 + i32.const 0 + i32.shr_u + i32.const -4096 + i32.gt_u + drop + ) + (func $z (; 20 ;) (; has Stack IR ;) (type $FUNCSIG$v) + nop + ) + (func $w (; 21 ;) (; has Stack IR ;) (type $FUNCSIG$v) + nop + ) + (func $block_and_after (; 22 ;) (; has Stack IR ;) (type $5) (result i32) + block $waka + i32.const 1 + drop + br $waka + end + i32.const 0 + ) + (func $loop-roundtrip (; 23 ;) (; has Stack IR ;) (type $7) (param $0 f64) (result f64) + loop $loop-in1 (result f64) + get_local $0 + drop + get_local $0 + end + ) + (func $big-i64 (; 24 ;) (; has Stack IR ;) (type $8) (result i64) + i64.const -9218868437227405313 + ) + (func $i64-store32 (; 25 ;) (; has Stack IR ;) (type $9) (param $0 i32) (param $1 i64) + get_local $0 + get_local $1 + i64.store32 + ) + (func $return-unreachable (; 26 ;) (; has Stack IR ;) (type $5) (result i32) + i32.const 1 + return + ) + (func $unreachable-block (; 27 ;) (; has Stack IR ;) (type $5) (result i32) + i32.const 1 + drop + i32.const 2 + return + ) + (func $unreachable-block-toplevel (; 28 ;) (; has Stack IR ;) (type $5) (result i32) + i32.const 1 + drop + i32.const 2 + return + ) + (func $unreachable-block0 (; 29 ;) (; has Stack IR ;) (type $5) (result i32) + i32.const 2 + return + ) + (func $unreachable-block0-toplevel (; 30 ;) (; has Stack IR ;) (type $5) (result i32) + i32.const 2 + return + ) + (func $unreachable-block-with-br (; 31 ;) (; has Stack IR ;) (type $5) (result i32) + block $block + i32.const 1 + drop + br $block + end + i32.const 1 + ) + (func $unreachable-if (; 32 ;) (; has Stack IR ;) (type $5) (result i32) + i32.const 3 + if + i32.const 2 + return + else + i32.const 1 + return + end + unreachable + ) + (func $unreachable-if-toplevel (; 33 ;) (; has Stack IR ;) (type $5) (result i32) + i32.const 3 + if + i32.const 2 + return + else + i32.const 1 + return + end + unreachable + ) + (func $unreachable-loop (; 34 ;) (; has Stack IR ;) (type $5) (result i32) + loop $loop-in + nop + i32.const 1 + return + end + unreachable + ) + (func $unreachable-loop0 (; 35 ;) (; has Stack IR ;) (type $5) (result i32) + loop $loop-in + i32.const 1 + return + end + unreachable + ) + (func $unreachable-loop-toplevel (; 36 ;) (; has Stack IR ;) (type $5) (result i32) + loop $loop-in + nop + i32.const 1 + return + end + unreachable + ) + (func $unreachable-loop0-toplevel (; 37 ;) (; has Stack IR ;) (type $5) (result i32) + loop $loop-in + i32.const 1 + return + end + unreachable + ) + (func $unreachable-ifs (; 38 ;) (; has Stack IR ;) (type $FUNCSIG$v) + unreachable + ) + (func $unreachable-if-arm (; 39 ;) (; has Stack IR ;) (type $FUNCSIG$v) + i32.const 1 + if + nop + else + unreachable + end + ) + (func $local-to-stack (; 40 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp i32) + i32.const 1 + call $local-to-stack + i32.const 2 + call $local-to-stack + drop + ) + (func $local-to-stack-1 (; 41 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp i32) + i32.const 1 + call $local-to-stack + i32.const 2 + call $local-to-stack + drop + i32.eqz + ) + (func $local-to-stack-1b (; 42 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp i32) + i32.const 1 + call $local-to-stack + i32.const 2 + call $local-to-stack + drop + i32.const 3 + i32.add + ) + (func $local-to-stack-1c-no (; 43 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp i32) + i32.const 1 + call $local-to-stack + set_local $temp + i32.const 2 + call $local-to-stack + drop + i32.const 3 + get_local $temp + i32.add + ) + (func $local-to-stack-2-no (; 44 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp i32) + i32.const 1 + call $local-to-stack + set_local $temp + i32.const 2 + call $local-to-stack + drop + get_local $temp + get_local $temp + i32.add + ) + (func $local-to-stack-3-no (; 45 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp i32) + i32.const 1 + if + i32.const 1 + call $local-to-stack + set_local $temp + else + i32.const 2 + call $local-to-stack + set_local $temp + end + i32.const 3 + call $local-to-stack + drop + get_local $temp + ) + (func $local-to-stack-multi-4 (; 46 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp1 i32) + (local $temp2 i32) + i32.const 1 + call $local-to-stack-multi-4 + i32.const 2 + call $local-to-stack-multi-4 + drop + drop + i32.const 3 + call $local-to-stack-multi-4 + i32.const 4 + call $local-to-stack-multi-4 + drop + ) + (func $local-to-stack-multi-5 (; 47 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp1 i32) + (local $temp2 i32) + i32.const 1 + call $local-to-stack-multi-4 + i32.const 2 + call $local-to-stack-multi-4 + drop + drop + i32.const 3 + call $local-to-stack-multi-4 + i32.const 4 + call $local-to-stack-multi-4 + drop + ) + (func $local-to-stack-multi-6-justone (; 48 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp1 i32) + (local $temp2 i32) + i32.const 1 + call $local-to-stack-multi-4 + i32.const 2 + call $local-to-stack-multi-4 + drop + drop + i32.const 3 + call $local-to-stack-multi-4 + set_local $temp2 + i32.const 4 + call $local-to-stack-multi-4 + drop + get_local $temp2 + get_local $temp2 + i32.add + ) + (func $local-to-stack-multi-7-justone (; 49 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp1 i32) + (local $temp2 i32) + i32.const 1 + call $local-to-stack-multi-4 + set_local $temp1 + i32.const 2 + call $local-to-stack-multi-4 + drop + get_local $temp1 + get_local $temp1 + i32.add + drop + i32.const 3 + call $local-to-stack-multi-4 + i32.const 4 + call $local-to-stack-multi-4 + drop + ) + (func $local-to-stack-overlapping-multi-8-no (; 50 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp1 i32) + (local $temp2 i32) + i32.const 1 + call $local-to-stack-multi-4 + set_local $temp1 + i32.const 1 + call $local-to-stack-multi-4 + i32.const 3 + call $local-to-stack-multi-4 + drop + get_local $temp1 + i32.add + ) + (func $local-to-stack-overlapping-multi-9-yes (; 51 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp1 i32) + (local $temp2 i32) + i32.const 1 + call $local-to-stack-multi-4 + i32.const 1 + call $local-to-stack-multi-4 + i32.const 3 + call $local-to-stack-multi-4 + drop + i32.add + ) + (func $local-to-stack-through-control-flow (; 52 ;) (; has Stack IR ;) (type $FUNCSIG$v) + (local $temp1 i32) + (local $temp2 i32) + i32.const 0 + call $local-to-stack-multi-4 + i32.const 1 + call $local-to-stack-multi-4 + i32.const 0 + if + nop + end + drop + i32.const 2 + call $local-to-stack-multi-4 + block $block + br $block + end + drop + drop + ) + (func $local-to-stack-in-control-flow (; 53 ;) (; has Stack IR ;) (type $FUNCSIG$v) + (local $temp1 i32) + i32.const 0 + if + i32.const 0 + call $local-to-stack-multi-4 + drop + else + i32.const 1 + call $local-to-stack-multi-4 + drop + end + ) + (func $remove-block (; 54 ;) (; has Stack IR ;) (type $6) (param $x i32) (result i32) + (local $temp i32) + i32.const 0 + call $remove-block + i32.const 1 + call $remove-block + i32.const 2 + call $remove-block + drop + i32.eqz + i32.add + ) +) (module (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$v (func)) diff --git a/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt b/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt index 126b2926e..7b3facd98 100644 --- a/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt +++ b/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt @@ -1,25 +1,28 @@ -$0: -0 block -1 block -2 loop -3 block -4 unreachable (unreachable) -5 unreachable (unreachable) -6 end (none) -7 unreachable (unreachable) -8 set_local (unreachable) -9 unreachable (unreachable) -10 unreachable (unreachable) -11 end (none) -12 unreachable (unreachable) -13 unreachable (unreachable) -14 unreachable (unreachable) -15 end (none) -16 unreachable (unreachable) -17 break (unreachable) -18 unreachable (unreachable) -19 end (none) - +(module + (type $0 (func (param i64))) + (func $0 (; 0 ;) (; has Stack IR ;) (type $0) (param $var$0 i64) + block $label$1 + block $label$2 + loop $label$3 + block $label$4 + unreachable + unreachable + end + unreachable + tee_local $var$0 + unreachable + unreachable + end + unreachable + unreachable + unreachable + end + unreachable + br_if $label$1 + unreachable + end + ) +) (module (type $0 (func (param i64))) (func $0 (; 0 ;) (; has Stack IR ;) (type $0) (param $var$0 i64) diff --git a/test/passes/ssa_fuzz-exec.txt b/test/passes/ssa_fuzz-exec.txt index 7f4917dff..ad5724351 100644 --- a/test/passes/ssa_fuzz-exec.txt +++ b/test/passes/ssa_fuzz-exec.txt @@ -1,4 +1,4 @@ -[fuzz-exec] note result: $func_0 => (i32.const 16384) +[fuzz-exec] note result: $func_0 => i32.const 16384 [fuzz-exec] 1 results noted (module (type $0 (func (result i32))) @@ -125,7 +125,7 @@ ) ) ) -[fuzz-exec] note result: $func_0 => (i32.const 16384) +[fuzz-exec] note result: $func_0 => i32.const 16384 [fuzz-exec] 1 results noted [fuzz-exec] comparing $func_0 [fuzz-exec] 1 results match |