summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Print.cpp933
-rw-r--r--src/passes/StackIR.cpp26
-rw-r--r--src/pretty_printing.h15
-rw-r--r--src/shell-interface.h2
-rw-r--r--src/wasm-printing.h14
-rw-r--r--src/wasm-stack.h45
-rw-r--r--src/wasm/literal.cpp3
-rw-r--r--test/passes/O1_print-stack-ir.txt29
-rw-r--r--test/passes/O2_precompute-propagate_print-stack-ir.txt16
-rw-r--r--test/passes/O2_print-stack-ir.txt31
-rw-r--r--test/passes/O3_print-stack-ir.txt27
-rw-r--r--test/passes/Os_print-stack-ir.txt27
-rw-r--r--test/passes/fuzz-exec.txt20
-rw-r--r--test/passes/fuzz-exec_O.txt8
-rw-r--r--test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt1200
-rw-r--r--test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt47
-rw-r--r--test/passes/ssa_fuzz-exec.txt4
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