diff options
-rw-r--r-- | src/tools/execution-results.h | 52 | ||||
-rw-r--r-- | test/lit/exec/eh.wast | 64 | ||||
-rw-r--r-- | test/passes/fuzz-exec_all-features.txt | 4 | ||||
-rw-r--r-- | test/passes/optimize-instructions_fuzz-exec.txt | 6 |
4 files changed, 102 insertions, 24 deletions
diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h index b689ffc66..18f4a399c 100644 --- a/src/tools/execution-results.h +++ b/src/tools/execution-results.h @@ -87,7 +87,11 @@ struct LoggingExternalInterface : public ShellExternalInterface { // we can only get results when there are no imports. we then call each method // that has a result, with some values struct ExecutionResults { - std::map<Name, Literals> results; + struct FunctionResult { + Literals values; + bool exception; // Whether an exception is uncaught and the function crashes + }; + std::map<Name, FunctionResult> results; Loggings loggings; // If set, we should ignore this and not compare it to anything. @@ -106,26 +110,20 @@ struct ExecutionResults { } std::cout << "[fuzz-exec] calling " << exp->name << "\n"; auto* func = wasm.getFunction(exp->value); - if (func->getResults() != Type::none) { - // this has a result - Literals ret = run(func, wasm, instance); - results[exp->name] = ret; - // ignore the result if we hit an unreachable and returned no value - if (ret.size() > 0) { - std::cout << "[fuzz-exec] note result: " << exp->name << " => "; - auto resultType = func->getResults(); - if (resultType.isRef()) { - // Don't print reference values, as funcref(N) contains an index - // for example, which is not guaranteed to remain identical after - // optimizations. - std::cout << resultType << '\n'; - } else { - std::cout << ret << '\n'; - } + FunctionResult ret = run(func, wasm, instance); + results[exp->name] = ret; + // ignore the result if we hit an unreachable and returned no value + if (ret.values.size() > 0) { + std::cout << "[fuzz-exec] note result: " << exp->name << " => "; + auto resultType = func->getResults(); + if (resultType.isRef()) { + // Don't print reference values, as funcref(N) contains an index + // for example, which is not guaranteed to remain identical after + // optimizations. + std::cout << resultType << '\n'; + } else { + std::cout << ret.values << '\n'; } - } else { - // no result, run it anyhow (it might modify memory etc.) - run(func, wasm, instance); } } } catch (const TrapException&) { @@ -191,7 +189,10 @@ struct ExecutionResults { return false; } std::cout << "[fuzz-exec] comparing " << name << '\n'; - if (!areEqual(results[name], other.results[name])) { + if (!areEqual(results[name].values, other.results[name].values)) { + return false; + } + if (results[name].exception != other.results[name].exception) { return false; } } @@ -209,7 +210,7 @@ struct ExecutionResults { bool operator!=(ExecutionResults& other) { return !((*this) == other); } - Literals run(Function* func, Module& wasm) { + FunctionResult run(Function* func, Module& wasm) { LoggingExternalInterface interface(loggings); try { ModuleInstance instance(wasm, &interface); @@ -220,7 +221,7 @@ struct ExecutionResults { } } - Literals run(Function* func, Module& wasm, ModuleInstance& instance) { + FunctionResult run(Function* func, Module& wasm, ModuleInstance& instance) { try { LiteralList arguments; // init hang support, if present @@ -236,9 +237,12 @@ struct ExecutionResults { } arguments.push_back(Literal::makeZero(param)); } - return instance.callFunction(func->name, arguments); + return {instance.callFunction(func->name, arguments), false}; } catch (const TrapException&) { return {}; + } catch (const WasmException& e) { + std::cout << "[exception thrown: " << e << "]" << std::endl; + return {{}, true}; } catch (const HostLimitException&) { // This should be ignored and not compared with, as optimizations can // change whether a host limit is reached. diff --git a/test/lit/exec/eh.wast b/test/lit/exec/eh.wast new file mode 100644 index 000000000..779309eb6 --- /dev/null +++ b/test/lit/exec/eh.wast @@ -0,0 +1,64 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. + +;; RUN: wasm-opt %s -all --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s + +(module + (tag $e-i32 (param i32)) + + ;; CHECK: [fuzz-exec] calling throw + ;; CHECK-NEXT: [exception thrown: e-i32 1] + (func "throw" + (throw $e-i32 (i32.const 1)) + ) + + ;; CHECK: [fuzz-exec] calling try-catch + (func "try-catch" + (try + (do + (throw $e-i32 (i32.const 2)) + ) + (catch $e-i32 + (drop (pop i32)) + ) + ) + ) + + ;; CHECK: [fuzz-exec] calling catchless-try + ;; CHECK-NEXT: [exception thrown: e-i32 3] + (func "catchless-try" + (try + (do + (throw $e-i32 (i32.const 3)) + ) + ) + ) + + ;; CHECK: [fuzz-exec] calling try-delegate + ;; CHECK-NEXT: [exception thrown: e-i32 4] + (func "try-delegate" + (try $l0 + (do + (try + (do + (throw $e-i32 (i32.const 4)) + ) + (delegate $l0) + ) + ) + ) + ) +) +;; CHECK: [fuzz-exec] calling throw +;; CHECK-NEXT: [exception thrown: e-i32 1] + +;; CHECK: [fuzz-exec] calling try-catch + +;; CHECK: [fuzz-exec] calling catchless-try +;; CHECK-NEXT: [exception thrown: e-i32 3] + +;; CHECK: [fuzz-exec] calling try-delegate +;; CHECK-NEXT: [exception thrown: e-i32 4] +;; CHECK-NEXT: [fuzz-exec] comparing catchless-try +;; CHECK-NEXT: [fuzz-exec] comparing throw +;; CHECK-NEXT: [fuzz-exec] comparing try-catch +;; CHECK-NEXT: [fuzz-exec] comparing try-delegate diff --git a/test/passes/fuzz-exec_all-features.txt b/test/passes/fuzz-exec_all-features.txt index 0225876a1..4b3e64e7c 100644 --- a/test/passes/fuzz-exec_all-features.txt +++ b/test/passes/fuzz-exec_all-features.txt @@ -139,9 +139,11 @@ [fuzz-exec] calling oob_notify [trap final > memory: 18446744073709551512 > 65514] [fuzz-exec] comparing aligned_for_size +[fuzz-exec] comparing oob_notify [fuzz-exec] comparing unaligned_load [fuzz-exec] comparing unaligned_load_offset [fuzz-exec] comparing unaligned_notify +[fuzz-exec] comparing wrap_cmpxchg [fuzz-exec] calling unsigned_2_bytes [fuzz-exec] note result: unsigned_2_bytes => 65535 (module @@ -183,6 +185,7 @@ ) [fuzz-exec] calling rmw-reads-modifies-and-writes [LoggingExternalInterface logging 0] +[fuzz-exec] comparing rmw-reads-modifies-and-writes [fuzz-exec] calling rmw-reads-modifies-and-writes-asymmetrical [LoggingExternalInterface logging 214] (module @@ -207,6 +210,7 @@ ) [fuzz-exec] calling rmw-reads-modifies-and-writes-asymmetrical [LoggingExternalInterface logging 214] +[fuzz-exec] comparing rmw-reads-modifies-and-writes-asymmetrical [fuzz-exec] calling func [fuzz-exec] note result: func => funcref (module diff --git a/test/passes/optimize-instructions_fuzz-exec.txt b/test/passes/optimize-instructions_fuzz-exec.txt index 2ebd01f1c..ea32b8916 100644 --- a/test/passes/optimize-instructions_fuzz-exec.txt +++ b/test/passes/optimize-instructions_fuzz-exec.txt @@ -253,6 +253,10 @@ [LoggingExternalInterface logging nan:0x400000] [LoggingExternalInterface logging nan:0x400000] [LoggingExternalInterface logging nan:0x400000] +[fuzz-exec] comparing ignore +[fuzz-exec] comparing just-one-nan +[fuzz-exec] comparing test32 +[fuzz-exec] comparing test64 [fuzz-exec] calling foo [LoggingExternalInterface logging 1] [LoggingExternalInterface logging 1] @@ -381,3 +385,5 @@ [fuzz-exec] note result: call-compare-maybe-signed-ne => 1 [fuzz-exec] comparing call-compare-maybe-signed-eq [fuzz-exec] comparing call-compare-maybe-signed-ne +[fuzz-exec] comparing do-shift +[fuzz-exec] comparing foo |