From 9d3801039d2e2f9738d2c4829ee59aa047da1cc6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Jul 2016 11:44:18 -0700 Subject: rename binaryen-shell to wasm-shell --- src/tools/wasm-shell.cpp | 267 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 src/tools/wasm-shell.cpp (limited to 'src/tools/wasm-shell.cpp') diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp new file mode 100644 index 000000000..27fa6cd50 --- /dev/null +++ b/src/tools/wasm-shell.cpp @@ -0,0 +1,267 @@ +/* + * Copyright 2015 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// A WebAssembly shell, loads a .wast file (WebAssembly in S-Expression format) +// and executes it. This provides similar functionality as the reference +// interpreter, like assert_* calls, so it can run the spec test suite. +// + +#include + +#include "pass.h" +#include "shell-interface.h" +#include "support/command-line.h" +#include "support/file.h" +#include "wasm-interpreter.h" +#include "wasm-printing.h" +#include "wasm-s-parser.h" +#include "wasm-validator.h" + +using namespace cashew; +using namespace wasm; + +// +// An invocation into a module +// + +struct Invocation { + ModuleInstance* instance; + IString name; + LiteralList arguments; + + Invocation(Element& invoke, ModuleInstance* instance, SExpressionWasmBuilder& builder) : instance(instance) { + assert(invoke[0]->str() == INVOKE); + name = invoke[1]->str(); + for (size_t j = 2; j < invoke.size(); j++) { + Expression* argument = builder.parseExpression(*invoke[j]); + arguments.push_back(argument->dynCast()->value); + } + } + + Literal invoke() { + return instance->callExport(name, arguments); + } +}; + +static void verify_result(Literal a, Literal b) { + if (a == b) return; + // accept equal nans if equal in all bits + assert(a.type == b.type); + if (a.type == f32) { + assert(a.reinterpreti32() == b.reinterpreti32()); + } else if (a.type == f64) { + assert(a.reinterpreti64() == b.reinterpreti64()); + } else { + abort(); + } +} + +static void run_asserts(size_t* i, bool* checked, Module* wasm, + Element* root, + std::unique_ptr* builder, + Name entry) { + std::unique_ptr interface; + std::unique_ptr instance; + if (wasm) { + interface = wasm::make_unique(); // prefix make_unique to work around visual studio bugs + instance = wasm::make_unique(*wasm, interface.get()); + if (entry.is()) { + Function* function = wasm->getFunction(entry); + if (!function) { + std::cerr << "Unknown entry " << entry << std::endl; + } else { + LiteralList arguments; + for (WasmType param : function->params) { + arguments.push_back(Literal(param)); + } + try { + instance->callExport(entry, arguments); + } catch (ExitException&) { + } + } + } + } + while (*i < root->size()) { + Element& curr = *(*root)[*i]; + IString id = curr[0]->str(); + if (id == MODULE) break; + *checked = true; + Colors::red(std::cerr); + std::cerr << *i << '/' << (root->size() - 1); + Colors::green(std::cerr); + std::cerr << " CHECKING: "; + Colors::normal(std::cerr); + std::cerr << curr; + Colors::green(std::cerr); + std::cerr << " [line: " << curr.line << "]\n"; + Colors::normal(std::cerr); + if (id == ASSERT_INVALID) { + // a module invalidity test + Module wasm; + bool invalid = false; + std::unique_ptr builder; + try { + builder = std::unique_ptr( + new SExpressionWasmBuilder(wasm, *curr[1]) + ); + } catch (const ParseException&) { + invalid = true; + } + if (!invalid) { + // maybe parsed ok, but otherwise incorrect + invalid = !WasmValidator().validate(wasm); + } + assert(invalid); + } else if (id == INVOKE) { + assert(wasm); + Invocation invocation(curr, instance.get(), *builder->get()); + invocation.invoke(); + } else { + // an invoke test + assert(wasm); + bool trapped = false; + WASM_UNUSED(trapped); + Literal result; + try { + Invocation invocation(*curr[1], instance.get(), *builder->get()); + result = invocation.invoke(); + } catch (const TrapException&) { + trapped = true; + } + if (id == ASSERT_RETURN) { + assert(!trapped); + if (curr.size() >= 3) { + Literal expected = builder->get() + ->parseExpression(*curr[2]) + ->dynCast() + ->value; + std::cerr << "seen " << result << ", expected " << expected << '\n'; + verify_result(expected, result); + } else { + Literal expected; + std::cerr << "seen " << result << ", expected " << expected << '\n'; + verify_result(expected, result); + } + } + if (id == ASSERT_TRAP) assert(trapped); + } + *i += 1; + } +} + +// +// main +// + +int main(int argc, const char* argv[]) { + Name entry; + std::vector passes; + + Options options("wasm-shell", "Execute .wast files"); + options + .add("--output", "-o", "Output file (stdout if not specified)", + Options::Arguments::One, + [](Options* o, const std::string& argument) { + o->extra["output"] = argument; + Colors::disable(); + }) + .add( + "--entry", "-e", "call the entry point after parsing the module", + Options::Arguments::One, + [&entry](Options*, const std::string& argument) { entry = argument; }) + .add("", "-O", "execute default optimization passes", + Options::Arguments::Zero, + [&passes](Options*, const std::string&) { + passes.push_back("O"); + }) + .add_positional("INFILE", Options::Arguments::One, + [](Options* o, const std::string& argument) { + o->extra["infile"] = argument; + }); + for (const auto& p : PassRegistry::get()->getRegisteredNames()) { + options.add( + std::string("--") + p, "", PassRegistry::get()->getPassDescription(p), + Options::Arguments::Zero, + [&passes, p](Options*, const std::string&) { passes.push_back(p); }); + } + options.parse(argc, argv); + + auto input(read_file>(options.extra["infile"], Flags::Text, options.debug ? Flags::Debug : Flags::Release)); + + std::unique_ptr output; + if (options.extra.count("output") > 0) { + output = wasm::make_unique(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release); + } + + bool checked = false; + + try { + if (options.debug) std::cerr << "parsing text to s-expressions...\n"; + SExpressionParser parser(input.data()); + Element& root = *parser.root; + + // A .wast may have multiple modules, with some asserts after them + size_t i = 0; + while (i < root.size()) { + Element& curr = *root[i]; + IString id = curr[0]->str(); + if (id == MODULE) { + if (options.debug) std::cerr << "parsing s-expressions to wasm...\n"; + Module wasm; + std::unique_ptr builder; + builder = wasm::make_unique(wasm, *root[i]); + i++; + assert(WasmValidator().validate(wasm)); + + MixedArena moreModuleAllocations; + + if (passes.size() > 0) { + if (options.debug) std::cerr << "running passes...\n"; + PassRunner passRunner(&wasm); + if (options.debug) passRunner.setDebug(true); + for (auto& passName : passes) { + if (passName == "O") { + passRunner.addDefaultOptimizationPasses(); + } else { + passRunner.add(passName); + } + } + passRunner.run(); + assert(WasmValidator().validate(wasm)); + } + + run_asserts(&i, &checked, &wasm, &root, &builder, entry); + + if (output) { + WasmPrinter::printModule(&wasm, output->getStream()); + } + } else { + run_asserts(&i, &checked, nullptr, &root, nullptr, entry); + } + } + } catch (ParseException& p) { + p.dump(std::cerr); + abort(); + } + + if (checked) { + Colors::green(std::cerr); + Colors::bold(std::cerr); + std::cerr << "all checks passed.\n"; + Colors::normal(std::cerr); + } +} -- cgit v1.2.3 From 9e2f21c9aa1993325b5a7043d206e2baf07e9180 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Jul 2016 12:15:20 -0700 Subject: separate wasm-opt out from wasm-shell: opt optimizes, shell runs wast shell tests --- CMakeLists.txt | 11 +++++ auto_update_tests.py | 12 ++++-- check.py | 86 ++++++++++----------------------------- scripts/support.py | 57 ++++++++++++++++++++++++++ src/tools/wasm-as.cpp | 2 +- src/tools/wasm-opt.cpp | 102 +++++++++++++++++++++++++++++++++++++++++++++++ src/tools/wasm-shell.cpp | 45 --------------------- test/waterfall | 2 +- 8 files changed, 201 insertions(+), 116 deletions(-) create mode 100644 src/tools/wasm-opt.cpp (limited to 'src/tools/wasm-shell.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index 10120844e..38b2df763 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,6 +120,17 @@ SET_PROPERTY(TARGET wasm-shell PROPERTY CXX_STANDARD 11) SET_PROPERTY(TARGET wasm-shell PROPERTY CXX_STANDARD_REQUIRED ON) INSTALL(TARGETS wasm-shell DESTINATION bin) +SET(wasm-opt_SOURCES + src/tools/wasm-opt.cpp + src/wasm.cpp +) +ADD_EXECUTABLE(wasm-opt + ${wasm-opt_SOURCES}) +TARGET_LINK_LIBRARIES(wasm-opt asmjs emscripten-optimizer ${all_passes} support) +SET_PROPERTY(TARGET wasm-opt PROPERTY CXX_STANDARD 11) +SET_PROPERTY(TARGET wasm-opt PROPERTY CXX_STANDARD_REQUIRED ON) +INSTALL(TARGETS wasm-opt DESTINATION bin) + SET(asm2wasm_SOURCES src/tools/asm2wasm.cpp src/wasm.cpp diff --git a/auto_update_tests.py b/auto_update_tests.py index 9505c2dc4..3b6c9bf24 100755 --- a/auto_update_tests.py +++ b/auto_update_tests.py @@ -2,6 +2,8 @@ import os, sys, subprocess, difflib +from scripts.support import run_command, split_wast + print '[ processing and updating testcases... ]\n' for asm in sorted(os.listdir('test')): @@ -68,9 +70,13 @@ for t in sorted(os.listdir(os.path.join('test', 'passes'))): print '..', t passname = os.path.basename(t).replace('.wast', '') opts = ['-O'] if passname == 'O' else ['--' + p for p in passname.split('_')] - cmd = [os.path.join('bin', 'wasm-shell')] + opts + [os.path.join('test', 'passes', t), '--print'] - print ' ', ' '.join(cmd) - actual, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + t = os.path.join('test', 'passes', t) + actual = '' + for module, asserts in split_wast(t): + assert len(asserts) == 0 + open('split.wast', 'w').write(module) + cmd = [os.path.join('bin', 'wasm-opt')] + opts + ['split.wast', '--print'] + actual += run_command(cmd) open(os.path.join('test', 'passes', passname + '.txt'), 'w').write(actual) print '\n[ checking binary format testcases... ]\n' diff --git a/check.py b/check.py index 4e6cd5e52..fb86721ea 100755 --- a/check.py +++ b/check.py @@ -17,7 +17,7 @@ import os, shutil, sys, subprocess, difflib, json, time, urllib2 import scripts.storage -import scripts.support +from scripts.support import run_command, split_wast interpreter = None requested = [] @@ -155,13 +155,6 @@ def delete_from_orbit(filename): # removes a file if it exists, using any and al except: pass -def run_command(cmd, expected_status=0, stderr=None): - print 'executing: ', ' '.join(cmd) - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr) - out, err = proc.communicate() - if proc.returncode != expected_status: raise Exception(('run_command failed', err)) - return out - def fail(actual, expected): raise Exception("incorrect output, diff:\n\n%s" % ( ''.join([a.rstrip()+'\n' for a in difflib.unified_diff(expected.split('\n'), actual.split('\n'), fromfile='expected', tofile='actual')])[:] @@ -193,50 +186,6 @@ if not has_vanilla_emcc: # check utilities -def split_wast(wast): - # .wast files can contain multiple modules, and assertions for each one. - # this splits out a wast into [(module, assertions), ..] - # we ignore module invalidity tests here. - wast = open(wast).read() - ret = [] - def to_end(j): - depth = 1 - while depth > 0 and j < len(wast): - if wast[j] == '"': - j = wast.find('"', j + 1) - elif wast[j] == '(': - depth += 1 - elif wast[j] == ')': - depth -= 1 - elif wast[j] == ';' and wast[j+1] == ';': - j = wast.find('\n', j) - j += 1 - return j - i = 0 - while i >= 0: - start = wast.find('(', i) - if start >= 0 and wast[start+1] == ';': - # block comment - i = wast.find(';)', start+2) - assert i > 0, wast[start:] - i += 2 - continue - skip = wast.find(';', i) - if skip >= 0 and skip < start and skip + 1 < len(wast): - if wast[skip+1] == ';': - i = wast.find('\n', i) + 1 - continue - if start < 0: break - i = to_end(start + 1) - chunk = wast[start:i] - if chunk.startswith('(module'): - ret += [(chunk, [])] - elif chunk.startswith('(assert_invalid'): - continue - elif chunk.startswith(('(assert', '(invoke')): - ret[-1][1].append(chunk) - return ret - def binary_format_check(wast, verify_final_result=True): # checks we can convert the wast to binary and back @@ -270,11 +219,11 @@ def minify_check(wast, verify_final_result=True): # checks we can parse minified output print ' (minify check)' - cmd = [os.path.join('bin', 'wasm-shell'), wast, '--print-minified'] + cmd = [os.path.join('bin', 'wasm-opt'), wast, '--print-minified'] print ' ', ' '.join(cmd) - subprocess.check_call([os.path.join('bin', 'wasm-shell'), wast, '--print-minified'], stdout=open('a.wasm', 'w'), stderr=subprocess.PIPE) + subprocess.check_call([os.path.join('bin', 'wasm-opt'), wast, '--print-minified'], stdout=open('a.wasm', 'w'), stderr=subprocess.PIPE) assert os.path.exists('a.wasm') - subprocess.check_call([os.path.join('bin', 'wasm-shell'), 'a.wasm', '--print-minified'], stdout=open('b.wasm', 'w'), stderr=subprocess.PIPE) + subprocess.check_call([os.path.join('bin', 'wasm-opt'), '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() @@ -301,23 +250,28 @@ for e in executables: assert e in err, 'Expected help to contain program name, got:\n%s' % err assert len(err.split('\n')) > 8, 'Expected some help, got:\n%s' % err -print '\n[ checking wasm-shell -o notation... ]\n' +print '\n[ checking wasm-opt -o notation... ]\n' wast = os.path.join('test', 'hello_world.wast') delete_from_orbit('a.wast') -cmd = [os.path.join('bin', 'wasm-shell'), wast, '-o', 'a.wast'] +cmd = [os.path.join('bin', 'wasm-opt'), wast, '-o', 'a.wast'] run_command(cmd) fail_if_not_identical(open('a.wast').read(), open(wast).read()) -print '\n[ checking wasm-shell passes... ]\n' +print '\n[ checking wasm-opt passes... ]\n' for t in sorted(os.listdir(os.path.join('test', 'passes'))): if t.endswith('.wast'): print '..', t passname = os.path.basename(t).replace('.wast', '') opts = ['-O'] if passname == 'O' else ['--' + p for p in passname.split('_')] - cmd = [os.path.join('bin', 'wasm-shell')] + opts + [os.path.join('test', 'passes', t), '--print'] - actual = run_command(cmd) + t = os.path.join('test', 'passes', t) + actual = '' + for module, asserts in split_wast(t): + assert len(asserts) == 0 + open('split.wast', 'w').write(module) + cmd = [os.path.join('bin', 'wasm-opt')] + opts + ['split.wast', '--print'] + actual += run_command(cmd) fail_if_not_identical(actual, open(os.path.join('test', 'passes', passname + '.txt')).read()) print '[ checking asm2wasm testcases... ]\n' @@ -350,7 +304,7 @@ for asm in tests: # verify in wasm if interpreter: # remove imports, spec interpreter doesn't know what to do with them - subprocess.check_call([os.path.join('bin', 'wasm-shell'), '--remove-imports', '--print', wasm], stdout=open('ztemp.wast', 'w'), stderr=subprocess.PIPE) + subprocess.check_call([os.path.join('bin', 'wasm-opt'), '--remove-imports', wasm], stdout=open('ztemp.wast', 'w'), stderr=subprocess.PIPE) proc = subprocess.Popen([interpreter, 'ztemp.wast'], stderr=subprocess.PIPE) out, err = proc.communicate() if proc.returncode != 0: @@ -370,28 +324,28 @@ for asm in tests: raise Exception('wasm interpreter error: ' + err) # failed to pretty-print raise Exception('wasm interpreter error') -print '\n[ checking wasm-shell parsing & printing... ]\n' +print '\n[ checking wasm-opt parsing & printing... ]\n' for t in sorted(os.listdir(os.path.join('test', 'print'))): if t.endswith('.wast'): print '..', t wasm = os.path.basename(t).replace('.wast', '') - cmd = [os.path.join('bin', 'wasm-shell'), os.path.join('test', 'print', t), '--print'] + cmd = [os.path.join('bin', 'wasm-opt'), 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', wasm + '.txt')).read()) - cmd = [os.path.join('bin', 'wasm-shell'), os.path.join('test', 'print', t), '--print-minified'] + cmd = [os.path.join('bin', 'wasm-opt'), 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.strip(), open(os.path.join('test', 'print', wasm + '.minified.txt')).read().strip()) -print '\n[ checking wasm-shell testcases... ]\n' +print '\n[ checking wasm-opt testcases... ]\n' for t in tests: if t.endswith('.wast') and not t.startswith('spec'): print '..', t t = os.path.join('test', t) - cmd = [os.path.join('bin', 'wasm-shell'), t, '--print'] + cmd = [os.path.join('bin', 'wasm-opt'), t, '--print'] actual = run_command(cmd) actual = actual.replace('printing before:\n', '') diff --git a/scripts/support.py b/scripts/support.py index a99fb7604..2d4318980 100755 --- a/scripts/support.py +++ b/scripts/support.py @@ -87,3 +87,60 @@ def untar(tarfile, outdir): finally: if os.path.isdir(tmpdir): shutil.rmtree(tmpdir) + + +def split_wast(wast): + # .wast files can contain multiple modules, and assertions for each one. + # this splits out a wast into [(module, assertions), ..] + # we ignore module invalidity tests here. + wast = open(wast).read() + ret = [] + + def to_end(j): + depth = 1 + while depth > 0 and j < len(wast): + if wast[j] == '"': + j = wast.find('"', j + 1) + elif wast[j] == '(': + depth += 1 + elif wast[j] == ')': + depth -= 1 + elif wast[j] == ';' and wast[j + 1] == ';': + j = wast.find('\n', j) + j += 1 + return j + + i = 0 + while i >= 0: + start = wast.find('(', i) + if start >= 0 and wast[start + 1] == ';': + # block comment + i = wast.find(';)', start + 2) + assert i > 0, wast[start:] + i += 2 + continue + skip = wast.find(';', i) + if skip >= 0 and skip < start and skip + 1 < len(wast): + if wast[skip + 1] == ';': + i = wast.find('\n', i) + 1 + continue + if start < 0: + break + i = to_end(start + 1) + chunk = wast[start:i] + if chunk.startswith('(module'): + ret += [(chunk, [])] + elif chunk.startswith('(assert_invalid'): + continue + elif chunk.startswith(('(assert', '(invoke')): + ret[-1][1].append(chunk) + return ret + + +def run_command(cmd, expected_status=0, stderr=None): + print 'executing: ', ' '.join(cmd) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr) + out, err = proc.communicate() + if proc.returncode != expected_status: + raise Exception(('run_command failed', err)) + return out diff --git a/src/tools/wasm-as.cpp b/src/tools/wasm-as.cpp index e2425b24a..376c1288c 100644 --- a/src/tools/wasm-as.cpp +++ b/src/tools/wasm-as.cpp @@ -56,7 +56,7 @@ int main(int argc, const char *argv[]) { Module wasm; - try{ + try { if (options.debug) std::cerr << "s-parsing..." << std::endl; SExpressionParser parser(const_cast(input.c_str())); Element& root = *parser.root; diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp new file mode 100644 index 000000000..a992f77dd --- /dev/null +++ b/src/tools/wasm-opt.cpp @@ -0,0 +1,102 @@ +/* + * Copyright 2016 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// A WebAssembly optimizer, loads code, optionally runs passes on it, +// then writes it. +// + +#include + +#include "pass.h" +#include "support/command-line.h" +#include "support/file.h" +#include "wasm-printing.h" +#include "wasm-s-parser.h" +#include "wasm-validator.h" + +using namespace wasm; + +// +// main +// + +int main(int argc, const char* argv[]) { + Name entry; + std::vector passes; + + Options options("wasm-opt", "Optimize .wast files"); + options + .add("--output", "-o", "Output file (stdout if not specified)", + Options::Arguments::One, + [](Options* o, const std::string& argument) { + o->extra["output"] = argument; + Colors::disable(); + }) + .add("", "-O", "execute default optimization passes", + Options::Arguments::Zero, + [&passes](Options*, const std::string&) { + passes.push_back("O"); + }) + .add_positional("INFILE", Options::Arguments::One, + [](Options* o, const std::string& argument) { + o->extra["infile"] = argument; + }); + for (const auto& p : PassRegistry::get()->getRegisteredNames()) { + options.add( + std::string("--") + p, "", PassRegistry::get()->getPassDescription(p), + Options::Arguments::Zero, + [&passes, p](Options*, const std::string&) { passes.push_back(p); }); + } + options.parse(argc, argv); + + auto input(read_file(options.extra["infile"], Flags::Text, options.debug ? Flags::Debug : Flags::Release)); + + Module wasm; + + try { + if (options.debug) std::cerr << "s-parsing..." << std::endl; + SExpressionParser parser(const_cast(input.c_str())); + Element& root = *parser.root; + if (options.debug) std::cerr << "w-parsing..." << std::endl; + SExpressionWasmBuilder builder(wasm, *root[0]); + assert(WasmValidator().validate(wasm)); + } catch (ParseException& p) { + p.dump(std::cerr); + Fatal() << "error in parsing input"; + } + + if (passes.size() > 0) { + if (options.debug) std::cerr << "running passes...\n"; + PassRunner passRunner(&wasm); + if (options.debug) passRunner.setDebug(true); + for (auto& passName : passes) { + if (passName == "O") { + passRunner.addDefaultOptimizationPasses(); + } else { + passRunner.add(passName); + } + } + passRunner.run(); + assert(WasmValidator().validate(wasm)); + } + + if (options.extra.count("output") > 0) { + if (options.debug) std::cerr << "writing..." << std::endl; + Output output(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release); + WasmPrinter::printModule(&wasm, output.getStream()); + } +} diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp index 27fa6cd50..72e8e13ba 100644 --- a/src/tools/wasm-shell.cpp +++ b/src/tools/wasm-shell.cpp @@ -169,44 +169,21 @@ static void run_asserts(size_t* i, bool* checked, Module* wasm, int main(int argc, const char* argv[]) { Name entry; - std::vector passes; Options options("wasm-shell", "Execute .wast files"); options - .add("--output", "-o", "Output file (stdout if not specified)", - Options::Arguments::One, - [](Options* o, const std::string& argument) { - o->extra["output"] = argument; - Colors::disable(); - }) .add( "--entry", "-e", "call the entry point after parsing the module", Options::Arguments::One, [&entry](Options*, const std::string& argument) { entry = argument; }) - .add("", "-O", "execute default optimization passes", - Options::Arguments::Zero, - [&passes](Options*, const std::string&) { - passes.push_back("O"); - }) .add_positional("INFILE", Options::Arguments::One, [](Options* o, const std::string& argument) { o->extra["infile"] = argument; }); - for (const auto& p : PassRegistry::get()->getRegisteredNames()) { - options.add( - std::string("--") + p, "", PassRegistry::get()->getPassDescription(p), - Options::Arguments::Zero, - [&passes, p](Options*, const std::string&) { passes.push_back(p); }); - } options.parse(argc, argv); auto input(read_file>(options.extra["infile"], Flags::Text, options.debug ? Flags::Debug : Flags::Release)); - std::unique_ptr output; - if (options.extra.count("output") > 0) { - output = wasm::make_unique(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release); - } - bool checked = false; try { @@ -226,29 +203,7 @@ int main(int argc, const char* argv[]) { builder = wasm::make_unique(wasm, *root[i]); i++; assert(WasmValidator().validate(wasm)); - - MixedArena moreModuleAllocations; - - if (passes.size() > 0) { - if (options.debug) std::cerr << "running passes...\n"; - PassRunner passRunner(&wasm); - if (options.debug) passRunner.setDebug(true); - for (auto& passName : passes) { - if (passName == "O") { - passRunner.addDefaultOptimizationPasses(); - } else { - passRunner.add(passName); - } - } - passRunner.run(); - assert(WasmValidator().validate(wasm)); - } - run_asserts(&i, &checked, &wasm, &root, &builder, entry); - - if (output) { - WasmPrinter::printModule(&wasm, output->getStream()); - } } else { run_asserts(&i, &checked, nullptr, &root, nullptr, entry); } diff --git a/test/waterfall b/test/waterfall index cba60ec04..bc52e2063 160000 --- a/test/waterfall +++ b/test/waterfall @@ -1 +1 @@ -Subproject commit cba60ec0417d7d6a741ab42de0f46eee79e4f1e8 +Subproject commit bc52e2063dd1bd06df64b7dfeceeb6e00437b909 -- cgit v1.2.3