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/binaryen-shell.cpp | 267 ------------------------------------------- src/tools/wasm-shell.cpp | 267 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+), 267 deletions(-) delete mode 100644 src/tools/binaryen-shell.cpp create mode 100644 src/tools/wasm-shell.cpp (limited to 'src') diff --git a/src/tools/binaryen-shell.cpp b/src/tools/binaryen-shell.cpp deleted file mode 100644 index 79c01c5bf..000000000 --- a/src/tools/binaryen-shell.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - * 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("binaryen-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); - } -} 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