summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-02-29 16:25:26 -0800
committerAlon Zakai <alonzakai@gmail.com>2016-02-29 16:25:26 -0800
commit11c52f9ca64ccec0d8db6dac22247c8b0eed503f (patch)
tree4180fa47f0e96727d760983f78a805113b277df0
parent84aa340d56ca3bf8b3ae9a2ea3ba4990f975977e (diff)
parent654feec8e99413bd989ede7143fcf5a9c67c9db6 (diff)
downloadbinaryen-11c52f9ca64ccec0d8db6dac22247c8b0eed503f.tar.gz
binaryen-11c52f9ca64ccec0d8db6dac22247c8b0eed503f.tar.bz2
binaryen-11c52f9ca64ccec0d8db6dac22247c8b0eed503f.zip
Merge pull request #204 from mbebenita/print-compact
Compact printing.
-rwxr-xr-xauto_update_tests.py4
-rwxr-xr-xcheck.py27
-rw-r--r--src/pass.h1
-rw-r--r--src/passes/Print.cpp162
-rw-r--r--src/pretty_printing.h12
-rw-r--r--src/wasm-printing.h2
-rw-r--r--test/print/min.minified.txt55
-rw-r--r--test/print/min.txt54
-rw-r--r--test/print/min.wast (renamed from test/print/min.minified.wast)0
9 files changed, 187 insertions, 130 deletions
diff --git a/auto_update_tests.py b/auto_update_tests.py
index 939d8d278..5c2c37dcb 100755
--- a/auto_update_tests.py
+++ b/auto_update_tests.py
@@ -52,6 +52,10 @@ for t in sorted(os.listdir(os.path.join('test', 'print'))):
print ' ', ' '.join(cmd)
actual, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
open(os.path.join('test', 'print', wasm + '.txt'), 'w').write(actual)
+ cmd = [os.path.join('bin', 'binaryen-shell'), os.path.join('test', 'print', t), '--print-minified']
+ print ' ', ' '.join(cmd)
+ actual, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ open(os.path.join('test', 'print', wasm + '.minified.txt'), 'w').write(actual)
for t in sorted(os.listdir(os.path.join('test', 'passes'))):
if t.endswith('.wast'):
diff --git a/check.py b/check.py
index 45fd08b15..6e767c292 100755
--- a/check.py
+++ b/check.py
@@ -225,6 +225,24 @@ def binary_format_check(wast, verify_final_result=True):
return 'ab.wast'
+def minify_check(wast, verify_final_result=True):
+ # checks we can parse minified output
+
+ print ' (minify check)'
+ cmd = [os.path.join('bin', 'binaryen-shell'), wast, '--print-minified']
+ print ' ', ' '.join(cmd)
+ subprocess.check_call([os.path.join('bin', 'binaryen-shell'), wast, '--print-minified'], stdout=open('a.wasm', 'w'), stderr=subprocess.PIPE)
+ assert os.path.exists('a.wasm')
+ subprocess.check_call([os.path.join('bin', 'binaryen-shell'), 'a.wasm', '--print-minified'], stdout=open('b.wasm', 'w'), stderr=subprocess.PIPE)
+ assert os.path.exists('b.wasm')
+ if verify_final_result:
+ expected = open('a.wasm').read()
+ actual = open('b.wasm').read()
+ if actual != expected:
+ fail(actual, expected)
+ if os.path.exists('a.wasm'): os.unlink('a.wasm')
+ if os.path.exists('b.wasm'): os.unlink('b.wasm')
+
# tests
print '[ checking --help is useful... ]\n'
@@ -289,11 +307,15 @@ print '\n[ checking binaryen-shell parsing & printing... ]\n'
for t in sorted(os.listdir(os.path.join('test', 'print'))):
if t.endswith('.wast'):
print '..', t
- name = os.path.basename(t).replace('.wast', '')
+ wasm = os.path.basename(t).replace('.wast', '')
cmd = [os.path.join('bin', 'binaryen-shell'), os.path.join('test', 'print', t), '--print']
print ' ', ' '.join(cmd)
actual, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
- fail_if_not_identical(actual, open(os.path.join('test', 'print', name + '.txt')).read())
+ fail_if_not_identical(actual, open(os.path.join('test', 'print', wasm + '.txt')).read())
+ cmd = [os.path.join('bin', 'binaryen-shell'), os.path.join('test', 'print', t), '--print-minified']
+ print ' ', ' '.join(cmd)
+ actual, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ fail_if_not_identical(actual, open(os.path.join('test', 'print', wasm + '.minified.txt')).read())
print '\n[ checking binaryen-shell passes... ]\n'
@@ -324,6 +346,7 @@ for t in tests:
fail(actual, expected)
binary_format_check(t)
+ minify_check(t)
print '\n[ checking binaryen-shell spec testcases... ]\n'
diff --git a/src/pass.h b/src/pass.h
index 53b486e41..41ef30b90 100644
--- a/src/pass.h
+++ b/src/pass.h
@@ -156,6 +156,7 @@ private:
// Prints out a module
class Printer : public Pass {
+protected:
std::ostream& o;
public:
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 3e886074d..3c3cdd659 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -26,33 +26,51 @@ namespace wasm {
struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
std::ostream& o;
unsigned indent;
+ bool minify;
+ const char *maybeSpace;
+ const char *maybeNewLine;
- PrintSExpression(std::ostream& o) : o(o), indent(0) {}
+ PrintSExpression(std::ostream& o, bool minify = false)
+ : o(o), indent(0), minify(minify) {
+ maybeSpace = minify ? "" : " ";
+ maybeNewLine = minify ? "" : "\n";
+ }
+ void incIndent() {
+ if (minify) return;
+ o << '\n';
+ indent++;
+ }
+ void decIndent() {
+ if (!minify) {
+ indent--;
+ doIndent(o, indent);
+ }
+ o << ')';
+ }
void printFullLine(Expression *expression) {
- doIndent(o, indent);
+ !minify && doIndent(o, indent);
visit(expression);
- o << '\n';
+ o << maybeNewLine;
}
-
void visitBlock(Block *curr) {
printOpening(o, "block");
if (curr->name.is()) {
o << ' ' << curr->name;
}
- incIndent(o, indent);
+ incIndent();
for (auto expression : curr->list) {
printFullLine(expression);
}
- decIndent(o, indent);
+ decIndent();
}
void visitIf(If *curr) {
printOpening(o, curr->ifFalse ? "if_else" : "if");
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->condition);
printFullLine(curr->ifTrue);
if (curr->ifFalse) printFullLine(curr->ifFalse);
- decIndent(o, indent);
+ decIndent();
}
void visitLoop(Loop *curr) {
printOpening(o, "loop");
@@ -63,7 +81,7 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
if (curr->in.is()) {
o << ' ' << curr->in;
}
- incIndent(o, indent);
+ incIndent();
auto block = curr->body->dyn_cast<Block>();
if (block && block->name.isNull()) {
// wasm spec has loops containing children directly, while our ast
@@ -74,12 +92,12 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
} else {
printFullLine(curr->body);
}
- decIndent(o, indent);
+ decIndent();
}
void visitBreak(Break *curr) {
if (curr->condition) {
printOpening(o, "br_if ") << curr->name;
- incIndent(o, indent);
+ incIndent();
} else {
printOpening(o, "br ") << curr->name;
if (!curr->value || curr->value->is<Nop>()) {
@@ -87,18 +105,18 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
o << ")";
return;
}
- incIndent(o, indent);
+ incIndent();
}
if (curr->value && !curr->value->is<Nop>()) printFullLine(curr->value);
if (curr->condition) {
printFullLine(curr->condition);
}
- decIndent(o, indent);
+ decIndent();
}
void visitSwitch(Switch *curr) {
printOpening(o, "tableswitch ");
if (curr->name.is()) o << curr->name;
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->value);
doIndent(o, indent) << "(table";
std::set<Name> caseNames;
@@ -106,29 +124,30 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
caseNames.insert(c.name);
}
for (auto& t : curr->targets) {
- o << " (" << (caseNames.count(t) == 0 ? "br" : "case") << " " << (t.is() ? t : curr->default_) << ")";
+ o << maybeSpace << "(" << (caseNames.count(t) == 0 ? "br" : "case") << " " << (t.is() ? t : curr->default_) << ")";
}
o << ")";
if (curr->default_.is()) o << " (" << (caseNames.count(curr->default_) == 0 ? "br" : "case") << " " << curr->default_ << ")";
- o << "\n";
+ o << maybeNewLine;
for (auto& c : curr->cases) {
doIndent(o, indent);
printMinorOpening(o, "case ") << c.name;
- incIndent(o, indent);
+ incIndent();
printFullLine(c.body);
- decIndent(o, indent) << '\n';
+ decIndent();
+ o << maybeNewLine;
}
- decIndent(o, indent);
+ decIndent();
}
void printCallBody(Call* curr) {
o << curr->target;
if (curr->operands.size() > 0) {
- incIndent(o, indent);
+ incIndent();
for (auto operand : curr->operands) {
printFullLine(operand);
}
- decIndent(o, indent);
+ decIndent();
} else {
o << ')';
}
@@ -144,21 +163,21 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
}
void visitCallIndirect(CallIndirect *curr) {
printOpening(o, "call_indirect ") << curr->fullType->name;
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->target);
for (auto operand : curr->operands) {
printFullLine(operand);
}
- decIndent(o, indent);
+ decIndent();
}
void visitGetLocal(GetLocal *curr) {
printOpening(o, "get_local ") << curr->name << ')';
}
void visitSetLocal(SetLocal *curr) {
printOpening(o, "set_local ") << curr->name;
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->value);
- decIndent(o, indent);
+ decIndent();
}
void visitLoad(Load *curr) {
o << '(';
@@ -182,9 +201,9 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
if (curr->align != curr->bytes) {
o << " align=" << curr->align;
}
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->ptr);
- decIndent(o, indent);
+ decIndent();
}
void visitStore(Store *curr) {
o << '(';
@@ -207,10 +226,10 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
if (curr->align != curr->bytes) {
o << " align=" << curr->align;
}
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->ptr);
printFullLine(curr->value);
- decIndent(o, indent);
+ decIndent();
}
void visitConst(Const *curr) {
o << curr->value;
@@ -246,9 +265,9 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
case ReinterpretInt: o << "reinterpret/" << (curr->type == f64 ? "i64" : "i32"); break;
default: abort();
}
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->value);
- decIndent(o, indent);
+ decIndent();
}
void visitBinary(Binary *curr) {
o << '(';
@@ -288,19 +307,19 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
default: abort();
}
restoreNormalColor(o);
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->left);
printFullLine(curr->right);
- decIndent(o, indent);
+ decIndent();
}
void visitSelect(Select *curr) {
o << '(';
prepareColor(o) << printWasmType(curr->type) << ".select";
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->ifTrue);
printFullLine(curr->ifFalse);
printFullLine(curr->condition);
- decIndent(o, indent);
+ decIndent();
}
void visitReturn(Return *curr) {
printOpening(o, "return");
@@ -309,9 +328,9 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
o << ")";
return;
}
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->value);
- decIndent(o, indent);
+ decIndent();
}
void visitHost(Host *curr) {
switch (curr->op) {
@@ -319,9 +338,9 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
case MemorySize: printOpening(o, "memory_size") << ')'; break;
case GrowMemory: {
printOpening(o, "grow_memory");
- incIndent(o, indent);
+ incIndent();
printFullLine(curr->operands[0]);
- decIndent(o, indent);
+ decIndent();
break;
}
case HasFeature: printOpening(o, "hasfeature ") << curr->nameOperand << ')'; break;
@@ -340,7 +359,7 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
printOpening(o, "type") << ' ' << curr->name << " (func";
}
if (curr->params.size() > 0) {
- o << ' ';
+ o << maybeSpace;
printMinorOpening(o, "param");
for (auto& param : curr->params) {
o << ' ' << printWasmType(param);
@@ -348,11 +367,11 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
o << ')';
}
if (curr->result != none) {
- o << ' ';
+ o << maybeSpace;
printMinorOpening(o, "result ") << printWasmType(curr->result) << ')';
}
if (full) {
- o << "))";;
+ o << "))";
}
}
void visitImport(Import *curr) {
@@ -369,22 +388,23 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
void visitFunction(Function *curr) {
printOpening(o, "func ", true) << curr->name;
if (curr->type.is()) {
- o << " (type " << curr->type << ')';
+ o << maybeSpace << "(type " << curr->type << ')';
}
if (curr->params.size() > 0) {
for (auto& param : curr->params) {
- o << ' ';
+ o << maybeSpace;
printMinorOpening(o, "param ") << param.name << ' ' << printWasmType(param.type) << ")";
}
}
if (curr->result != none) {
- o << ' ';
+ o << maybeSpace;
printMinorOpening(o, "result ") << printWasmType(curr->result) << ")";
}
- incIndent(o, indent);
+ incIndent();
for (auto& local : curr->locals) {
doIndent(o, indent);
- printMinorOpening(o, "local ") << local.name << ' ' << printWasmType(local.type) << ")\n";
+ printMinorOpening(o, "local ") << local.name << ' ' << printWasmType(local.type) << ")";
+ 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..
@@ -396,7 +416,7 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
} else {
printFullLine(curr->body);
}
- decIndent(o, indent);
+ decIndent();
}
void visitTable(Table *curr) {
printOpening(o, "table");
@@ -407,12 +427,13 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
}
void visitModule(Module *curr) {
printOpening(o, "module", true);
- incIndent(o, indent);
+ incIndent();
doIndent(o, indent);
printOpening(o, "memory") << " " << curr->memory.initial;
if (curr->memory.max && curr->memory.max != (uint32_t)-1) o << " " << curr->memory.max;
for (auto segment : curr->memory.segments) {
- o << "\n (segment " << segment.offset << " \"";
+ o << maybeNewLine;
+ o << (minify ? "" : " ") << "(segment " << segment.offset << " \"";
for (size_t i = 0; i < segment.size; i++) {
unsigned char c = segment.data[i];
switch (c) {
@@ -435,38 +456,40 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
}
o << "\")";
}
- o << (curr->memory.segments.size() > 0 ? "\n " : "") << ")\n";
+ o << ((curr->memory.segments.size() > 0 && !minify) ? "\n " : "") << ")";
+ o << maybeNewLine;
if (curr->start.is()) {
doIndent(o, indent);
- printOpening(o, "start") << " " << curr->start << ")\n";
+ printOpening(o, "start") << " " << curr->start << ")";
+ o << maybeNewLine;
}
for (auto& child : curr->functionTypes) {
doIndent(o, indent);
visitFunctionType(child, true);
- o << '\n';
+ o << maybeNewLine;
}
for (auto& child : curr->imports) {
doIndent(o, indent);
visitImport(child);
- o << '\n';
+ o << maybeNewLine;
}
for (auto& child : curr->exports) {
doIndent(o, indent);
visitExport(child);
- o << '\n';
+ o << maybeNewLine;
}
if (curr->table.names.size() > 0) {
doIndent(o, indent);
visitTable(&curr->table);
- o << '\n';
+ o << maybeNewLine;
}
for (auto& child : curr->functions) {
doIndent(o, indent);
visitFunction(child);
- o << '\n';
+ o << maybeNewLine;
}
- decIndent(o, indent);
- o << '\n';
+ decIndent();
+ o << maybeNewLine;
}
};
@@ -479,10 +502,27 @@ void Printer::run(PassRunner* runner, Module* module) {
static RegisterPass<Printer> registerPass("print", "print in s-expression format");
+// Prints out a minified module
+class MinifiedPrinter : public Printer {
+ public:
+ MinifiedPrinter() : Printer() {}
+ MinifiedPrinter(std::ostream& o) : Printer(o) {}
+
+ void run(PassRunner* runner, Module* module) override;
+};
+
+void MinifiedPrinter::run(PassRunner* runner, Module* module) {
+ PrintSExpression print(o, true);
+ print.visitModule(module);
+}
+
+
+static RegisterPass<MinifiedPrinter> registerMinifyPass("print-minified", "print in minified s-expression format");
+
// Print individual expressions
-std::ostream& printWasm(Expression* expression, std::ostream& o) {
- PrintSExpression print(o);
+std::ostream& printWasm(Expression* expression, std::ostream& o, bool minify = false) {
+ PrintSExpression print(o, minify);
print.visit(expression);
return o;
}
diff --git a/src/pretty_printing.h b/src/pretty_printing.h
index f0a233d69..9dec22ca3 100644
--- a/src/pretty_printing.h
+++ b/src/pretty_printing.h
@@ -32,18 +32,6 @@ inline std::ostream &doIndent(std::ostream &o, unsigned indent) {
return o;
}
-inline std::ostream &incIndent(std::ostream &o, unsigned& indent) {
- o << '\n';
- indent++;
- return o;
-}
-
-inline std::ostream &decIndent(std::ostream &o, unsigned& indent) {
- indent--;
- doIndent(o, indent);
- return o << ')';
-}
-
inline std::ostream &prepareMajorColor(std::ostream &o) {
Colors::red(o);
Colors::bold(o);
diff --git a/src/wasm-printing.h b/src/wasm-printing.h
index 6d8ed7c8a..5b47a38bb 100644
--- a/src/wasm-printing.h
+++ b/src/wasm-printing.h
@@ -29,7 +29,7 @@ inline std::ostream& printWasm(Module* module, std::ostream& o) {
return o;
}
-extern std::ostream& printWasm(Expression* expression, std::ostream& o);
+extern std::ostream& printWasm(Expression* expression, std::ostream& o, bool minify = false);
}
diff --git a/test/print/min.minified.txt b/test/print/min.minified.txt
index b66f98c30..5ecab5959 100644
--- a/test/print/min.minified.txt
+++ b/test/print/min.minified.txt
@@ -1,54 +1 @@
-(module
- (memory 16777216 16777216)
- (export "floats" $floats)
- (func $floats (param $f f32) (result f32)
- (local $t f32)
- (f32.add
- (get_local $t)
- (get_local $f)
- )
- )
- (func $neg (param $k i32) (param $p i32)
- (local $n f32)
- (set_local $n
- (f32.neg
- (block $block0
- (i32.store
- (get_local $k)
- (get_local $p)
- )
- (f32.load
- (get_local $k)
- )
- )
- )
- )
- )
- (func $littleswitch (param $x i32) (result i32)
- (block $topmost
- (tableswitch $switch$0
- (i32.sub
- (get_local $x)
- (i32.const 1)
- )
- (table (case $switch-case$1) (case $switch-case$2)) (case $switch-case$1)
- (case $switch-case$1
- (br $topmost
- (i32.const 1)
- )
- )
- (case $switch-case$2
- (br $topmost
- (i32.const 2)
- )
- )
- )
- (i32.const 0)
- )
- )
- (func $f1 (param $i1 i32) (param $i2 i32) (param $i3 i32) (result i32)
- (block $topmost
- (get_local $i3)
- )
- )
-)
+(module(memory 16777216 16777216)(export "floats" $floats)(func $floats(param $f f32)(result f32)(local $t f32)(f32.add(get_local $t)(get_local $f)))(func $neg(param $k i32)(param $p i32)(local $n f32)(set_local $n(f32.neg(block $block0(i32.store(get_local $k)(get_local $p))(f32.load(get_local $k))))))(func $littleswitch(param $x i32)(result i32)(block $topmost(tableswitch $switch$0(i32.sub(get_local $x)(i32.const 1))(table(case $switch-case$1)(case $switch-case$2)) (case $switch-case$1)(case $switch-case$1(br $topmost(i32.const 1)))(case $switch-case$2(br $topmost(i32.const 2))))(i32.const 0)))(func $f1(param $i1 i32)(param $i2 i32)(param $i3 i32)(result i32)(block $topmost(get_local $i3)))) \ No newline at end of file
diff --git a/test/print/min.txt b/test/print/min.txt
new file mode 100644
index 000000000..b66f98c30
--- /dev/null
+++ b/test/print/min.txt
@@ -0,0 +1,54 @@
+(module
+ (memory 16777216 16777216)
+ (export "floats" $floats)
+ (func $floats (param $f f32) (result f32)
+ (local $t f32)
+ (f32.add
+ (get_local $t)
+ (get_local $f)
+ )
+ )
+ (func $neg (param $k i32) (param $p i32)
+ (local $n f32)
+ (set_local $n
+ (f32.neg
+ (block $block0
+ (i32.store
+ (get_local $k)
+ (get_local $p)
+ )
+ (f32.load
+ (get_local $k)
+ )
+ )
+ )
+ )
+ )
+ (func $littleswitch (param $x i32) (result i32)
+ (block $topmost
+ (tableswitch $switch$0
+ (i32.sub
+ (get_local $x)
+ (i32.const 1)
+ )
+ (table (case $switch-case$1) (case $switch-case$2)) (case $switch-case$1)
+ (case $switch-case$1
+ (br $topmost
+ (i32.const 1)
+ )
+ )
+ (case $switch-case$2
+ (br $topmost
+ (i32.const 2)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ )
+ (func $f1 (param $i1 i32) (param $i2 i32) (param $i3 i32) (result i32)
+ (block $topmost
+ (get_local $i3)
+ )
+ )
+)
diff --git a/test/print/min.minified.wast b/test/print/min.wast
index 35ea01ace..35ea01ace 100644
--- a/test/print/min.minified.wast
+++ b/test/print/min.wast