diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/shell-interface.h | 2 | ||||
-rw-r--r-- | src/tools/wasm-ctor-eval.cpp | 2 | ||||
-rw-r--r-- | src/tools/wasm-shell.cpp | 2 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 88 | ||||
-rw-r--r-- | src/wasm/wasm-interpreter.cpp | 4 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 6 |
6 files changed, 63 insertions, 41 deletions
diff --git a/src/shell-interface.h b/src/shell-interface.h index d82885ced..c429c3a29 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -232,7 +232,7 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { throw TrapException(); } - void throwException(Literal exn) override { throw WasmException(exn); } + void throwException(const WasmException& exn) override { throw exn; } }; } // namespace wasm diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 9e78cfb7a..4ad9979cd 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -292,7 +292,7 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { throw FailToEvalException(std::string("trap: ") + why); } - void throwException(Literal exn) override { + void throwException(const WasmException& exn) override { std::stringstream ss; ss << "exception thrown: " << exn; throw FailToEvalException(ss.str()); diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp index 08c76ac9c..20d4b9344 100644 --- a/src/tools/wasm-shell.cpp +++ b/src/tools/wasm-shell.cpp @@ -208,7 +208,7 @@ static void run_asserts(Name moduleName, } catch (const TrapException&) { trapped = true; } catch (const WasmException& e) { - std::cout << "[exception thrown: " << e.exn << "]" << std::endl; + std::cout << "[exception thrown: " << e << "]" << std::endl; trapped = true; } if (id == ASSERT_RETURN) { diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 9fc9734eb..ac9fd80c8 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -41,9 +41,10 @@ namespace wasm { struct WasmException { - WasmException(Literal exn) : exn(exn) {} - Literal exn; + Name event; + Literals values; }; +std::ostream& operator<<(std::ostream& o, const WasmException& exn); using namespace cashew; @@ -1344,31 +1345,15 @@ public: return flow; } NOTE_EVAL1(curr->event); - auto exn = std::make_unique<ExceptionPackage>(); - exn->event = curr->event; + WasmException exn; + exn.event = curr->event; for (auto item : arguments) { - exn->values.push_back(item); + exn.values.push_back(item); } - throwException(Literal::makeExn(std::move(exn))); + throwException(exn); WASM_UNREACHABLE("throw"); } - Flow visitRethrow(Rethrow* curr) { - // FIXME Update the implementation to match the new spec - NOTE_ENTER("Rethrow"); - WASM_UNREACHABLE("unimp"); - /* - Flow flow = visit(curr->exnref); - if (flow.breaking()) { - return flow; - } - const auto& value = flow.getSingleValue(); - if (value.isNull()) { - trap("rethrow: argument is null"); - } - throwException(value); - WASM_UNREACHABLE("rethrow"); - */ - } + Flow visitRethrow(Rethrow* curr) { WASM_UNREACHABLE("unimp"); } Flow visitBrOnExn(BrOnExn* curr) { NOTE_ENTER("BrOnExn"); Flow flow = this->visit(curr->exnref); @@ -1660,7 +1645,9 @@ public: virtual void trap(const char* why) { WASM_UNREACHABLE("unimp"); } - virtual void throwException(Literal exn) { WASM_UNREACHABLE("unimp"); } + virtual void throwException(const WasmException& exn) { + WASM_UNREACHABLE("unimp"); + } private: // Truncate the value if we need to. The storage is just a list of Literals, @@ -1943,10 +1930,14 @@ public: NOTE_ENTER("Try"); return Flow(NONCONSTANT_FLOW); } + Flow visitRethrow(Rethrow* curr) { + NOTE_ENTER("Rethrow"); + return Flow(NONCONSTANT_FLOW); + } void trap(const char* why) override { throw NonconstantException(); } - virtual void throwException(Literal exn) override { + virtual void throwException(const WasmException& exn) override { throw NonconstantException(); } }; @@ -1995,7 +1986,7 @@ public: SubType& instance) = 0; virtual bool growMemory(Address oldSize, Address newSize) = 0; virtual void trap(const char* why) = 0; - virtual void throwException(Literal exnref) = 0; + virtual void throwException(const WasmException& exn) = 0; // the default impls for load and store switch on the sizes. you can either // customize load/store, or the sub-functions which they call @@ -2152,7 +2143,7 @@ public: GlobalManager globals; // Multivalue ABI support (see push/pop). - std::vector<Literal> multiValues; + std::vector<Literals> multiValues; ModuleInstanceBase(Module& wasm, ExternalInterface* externalInterface) : wasm(wasm), externalInterface(externalInterface) { @@ -2315,6 +2306,7 @@ private: : public ExpressionRunner<RuntimeExpressionRunner> { ModuleInstanceBase& instance; FunctionScope& scope; + SmallVector<WasmException, 4> exceptionStack; public: RuntimeExpressionRunner(ModuleInstanceBase& instance, @@ -2953,22 +2945,50 @@ private: return {}; } Flow visitTry(Try* curr) { - // FIXME Update the implementation to match the new spec - WASM_UNREACHABLE("unimp"); - /* NOTE_ENTER("Try"); try { return this->visit(curr->body); } catch (const WasmException& e) { - instance.multiValues.push_back(e.exn); - return this->visit(curr->catchBody); + auto processCatchBody = [&](Expression* catchBody) { + // Push the current exception onto the exceptionStack in case + // 'rethrow's use it + exceptionStack.push_back(e); + // We need to pop exceptionStack in either case: when the catch body + // exits normally or when a new exception is thrown + Flow ret; + try { + ret = this->visit(catchBody); + } catch (const WasmException& e) { + exceptionStack.pop_back(); + throw; + } + exceptionStack.pop_back(); + return ret; + }; + + for (size_t i = 0; i < curr->catchEvents.size(); i++) { + if (curr->catchEvents[i] == e.event) { + instance.multiValues.push_back(e.values); + return processCatchBody(curr->catchBodies[i]); + } + } + if (curr->hasCatchAll()) { + return processCatchBody(curr->catchBodies.back()); + } + // This exception is not caught by this try-catch. Rethrow it. + throw; } - */ + } + Flow visitRethrow(Rethrow* curr) { + assert(exceptionStack.size() > curr->depth); + throwException(exceptionStack[exceptionStack.size() - 1 - curr->depth]); + WASM_UNREACHABLE("rethrow"); } Flow visitPop(Pop* curr) { NOTE_ENTER("Pop"); assert(!instance.multiValues.empty()); auto ret = instance.multiValues.back(); + assert(curr->type == ret.getType()); instance.multiValues.pop_back(); return ret; } @@ -2977,7 +2997,7 @@ private: instance.externalInterface->trap(why); } - void throwException(Literal exn) override { + void throwException(const WasmException& exn) override { instance.externalInterface->throwException(exn); } diff --git a/src/wasm/wasm-interpreter.cpp b/src/wasm/wasm-interpreter.cpp index ad4b565fe..f37758808 100644 --- a/src/wasm/wasm-interpreter.cpp +++ b/src/wasm/wasm-interpreter.cpp @@ -19,4 +19,8 @@ void Indenter::print() { } #endif // WASM_INTERPRETER_DEBUG +std::ostream& operator<<(std::ostream& o, const WasmException& exn) { + return o << exn.event << " " << exn.values; +} + } // namespace wasm diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index e7055a8b0..1557240bb 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2097,10 +2097,8 @@ void FunctionValidator::visitRethrow(Rethrow* curr) { Type(Type::unreachable), curr, "rethrow's type must be unreachable"); - // TODO Allow non-zero depths and Validate the depth field. The current LLVM - // toolchain only generates depth 0 for C++ support. - shouldBeEqual( - curr->depth, (Index)0, curr, "rethrow only support depth 0 at the moment"); + // TODO Validate the depth field. The current LLVM toolchain only generates + // depth 0 for C++ support. } void FunctionValidator::visitBrOnExn(BrOnExn* curr) { |