diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-09-16 21:08:58 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-09-17 14:56:48 -0700 |
commit | 0201f77b30f875de0d0fc8e407ffc985d47f8535 (patch) | |
tree | a1a3f9618b7619dba9ac4f7bc13d37539d599459 | |
parent | d46a737d421d53f68fc13d55fe405cf8c3c5d4c0 (diff) | |
download | binaryen-0201f77b30f875de0d0fc8e407ffc985d47f8535.tar.gz binaryen-0201f77b30f875de0d0fc8e407ffc985d47f8535.tar.bz2 binaryen-0201f77b30f875de0d0fc8e407ffc985d47f8535.zip |
support module operations in shell tests
-rw-r--r-- | src/shared-constants.h | 1 | ||||
-rw-r--r-- | src/tools/wasm-shell.cpp | 83 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 11 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 4 | ||||
-rw-r--r-- | src/wasm.cpp | 1 |
5 files changed, 68 insertions, 32 deletions
diff --git a/src/shared-constants.h b/src/shared-constants.h index e37879088..2d656f0eb 100644 --- a/src/shared-constants.h +++ b/src/shared-constants.h @@ -49,7 +49,6 @@ extern Name GROW_WASM_MEMORY, FAKE_RETURN, SPECTEST, PRINT, - INVOKE, EXIT; } // namespace wasm diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp index ddb2f8a85..e0bc5d7e9 100644 --- a/src/tools/wasm-shell.cpp +++ b/src/tools/wasm-shell.cpp @@ -37,28 +37,51 @@ using namespace wasm; Name ASSERT_RETURN("assert_return"), ASSERT_TRAP("assert_trap"), ASSERT_INVALID("assert_invalid"), - ASSERT_MALFORMED("assert_malformed"); + ASSERT_MALFORMED("assert_malformed"), + INVOKE("invoke"), + GET("get"); + +// Modules named in the file + +std::map<Name, std::unique_ptr<Module>> modules; +std::map<Name, std::unique_ptr<SExpressionWasmBuilder>> builders; +std::map<Name, std::unique_ptr<ShellExternalInterface>> interfaces; +std::map<Name, std::unique_ptr<ModuleInstance>> instances; // -// An invocation into a module +// An operation on a module // -struct Invocation { +struct Operation { ModuleInstance* instance; - IString name; + Name operation; + Name 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]); + Operation(Element& element, ModuleInstance* instanceInit, SExpressionWasmBuilder& builder) : instance(instanceInit) { + operation = element[0]->str(); + Index i = 1; + if (element.size() >= 3 && element[2]->isStr()) { + // module also specified + Name moduleName = element[i++]->str(); + instance = instances[moduleName].get(); + } + name = element[i++]->str(); + for (size_t j = i; j < element.size(); j++) { + Expression* argument = builder.parseExpression(*element[j]); arguments.push_back(argument->dynCast<Const>()->value); } } - Literal invoke() { - return instance->callExport(name, arguments); + Literal operate() { + if (operation == INVOKE) { + return instance->callExport(name, arguments); + } else if (operation == GET) { + return instance->getExport(name); + } else { + Fatal() << "unknown operation: " << operation << '\n'; + WASM_UNREACHABLE(); + } } }; @@ -75,15 +98,17 @@ static void verify_result(Literal a, Literal b) { } } -static void run_asserts(size_t* i, bool* checked, Module* wasm, +static void run_asserts(Name moduleName, size_t* i, bool* checked, Module* wasm, Element* root, - std::unique_ptr<SExpressionWasmBuilder>* builder, + SExpressionWasmBuilder* builder, Name entry) { - std::unique_ptr<ShellExternalInterface> interface; - std::unique_ptr<ModuleInstance> instance; + ModuleInstance* instance = nullptr; if (wasm) { - interface = wasm::make_unique<ShellExternalInterface>(); // prefix make_unique to work around visual studio bugs - instance = wasm::make_unique<ModuleInstance>(*wasm, interface.get()); + auto tempInterface = wasm::make_unique<ShellExternalInterface>(); // prefix make_unique to work around visual studio bugs + auto tempInstance = wasm::make_unique<ModuleInstance>(*wasm, tempInterface.get()); + interfaces[moduleName].swap(tempInterface); + instances[moduleName].swap(tempInstance); + instance = instances[moduleName].get(); if (entry.is()) { Function* function = wasm->getFunction(entry); if (!function) { @@ -139,23 +164,23 @@ static void run_asserts(size_t* i, bool* checked, Module* wasm, } } else if (id == INVOKE) { assert(wasm); - Invocation invocation(curr, instance.get(), *builder->get()); - invocation.invoke(); + Operation operation(curr, instance, *builder); + operation.operate(); } else if (wasm) { // if no wasm, we skipped the module // an invoke test bool trapped = false; WASM_UNUSED(trapped); Literal result; try { - Invocation invocation(*curr[1], instance.get(), *builder->get()); - result = invocation.invoke(); + Operation operation(*curr[1], instance, *builder); + result = operation.operate(); } catch (const TrapException&) { trapped = true; } if (id == ASSERT_RETURN) { assert(!trapped); if (curr.size() >= 3) { - Literal expected = builder->get() + Literal expected = builder ->parseExpression(*curr[2]) ->dynCast<Const>() ->value; @@ -234,14 +259,16 @@ int main(int argc, const char* argv[]) { Colors::green(std::cerr); std::cerr << "BUILDING MODULE [line: " << curr.line << "]\n"; Colors::normal(std::cerr); - Module wasm; - std::unique_ptr<SExpressionWasmBuilder> builder; - builder = wasm::make_unique<SExpressionWasmBuilder>(wasm, *root[i]); + auto module = wasm::make_unique<Module>(); + Name moduleName; + auto builder = wasm::make_unique<SExpressionWasmBuilder>(*module, *root[i], &moduleName); + builders[moduleName].swap(builder); + modules[moduleName].swap(module); i++; - assert(WasmValidator().validate(wasm)); - run_asserts(&i, &checked, &wasm, &root, &builder, entry); + assert(WasmValidator().validate(*modules[moduleName])); + run_asserts(moduleName, &i, &checked, modules[moduleName].get(), &root, builders[moduleName].get(), entry); } else { - run_asserts(&i, &checked, nullptr, &root, nullptr, entry); + run_asserts(Name(), &i, &checked, nullptr, &root, nullptr, entry); } } } catch (ParseException& p) { diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 5d4e7d7b4..f699ba6f8 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -554,12 +554,23 @@ public: } } + // call an exported function Literal callExport(Name name, LiteralList& arguments) { Export *export_ = wasm.checkExport(name); if (!export_) externalInterface->trap("callExport not found"); return callFunction(export_->value, arguments); } + // get an exported global + Literal getExport(Name name) { + Export *export_ = wasm.checkExport(name); + if (!export_) externalInterface->trap("getExport external not found"); + Name internalName = export_->value; + auto iter = globals.find(internalName); + if (iter == globals.end()) externalInterface->trap("getExport internal not found"); + return iter->second; + } + std::string printFunctionStack() { std::string ret = "/== (binaryen interpreter stack trace)\n"; for (int i = int(functionStack.size()) - 1; i >= 0; i--) { diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index f244a08f9..0f11bd521 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -1473,7 +1473,7 @@ private: ex->kind = Export::Table; } else if (inner[0]->str() == GLOBAL) { ex->value = inner[1]->str(); - ex->kind = Export::Table; + ex->kind = Export::Global; } else { WASM_UNREACHABLE(); } @@ -1487,7 +1487,7 @@ private: ex->kind = Export::Table; } else if (s[2]->str() == GLOBAL) { ex->value = s[3]->str(); - ex->kind = Export::Table; + ex->kind = Export::Global; } else { WASM_UNREACHABLE(); } diff --git a/src/wasm.cpp b/src/wasm.cpp index 144cabd16..8badaa6be 100644 --- a/src/wasm.cpp +++ b/src/wasm.cpp @@ -74,7 +74,6 @@ Name GROW_WASM_MEMORY("__growWasmMemory"), FAKE_RETURN("fake_return_waka123"), SPECTEST("spectest"), PRINT("print"), - INVOKE("invoke"), EXIT("exit"); // core AST type checking |