summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/fuzz_opt.py4
-rw-r--r--src/tools/execution-results.h56
-rw-r--r--test/lit/exec/i31.wast29
3 files changed, 68 insertions, 21 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py
index c5498822e..d0705693f 100755
--- a/scripts/fuzz_opt.py
+++ b/scripts/fuzz_opt.py
@@ -561,6 +561,10 @@ def fix_output(out):
# change that index, so ignore it
out = re.sub(r'funcref\([\d\w$+-_:]+\)', 'funcref()', out)
+ # JS prints i31 as just a number, so change "i31ref(N)" (which C++ emits)
+ # to "N".
+ out = re.sub(r'i31ref\((\d+)\)', r'\1', out)
+
lines = out.splitlines()
for i in range(len(lines)):
line = lines[i]
diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h
index add7cd3a5..40d844f19 100644
--- a/src/tools/execution-results.h
+++ b/src/tools/execution-results.h
@@ -115,27 +115,8 @@ struct ExecutionResults {
// ignore the result if we hit an unreachable and returned no value
if (values->size() > 0) {
std::cout << "[fuzz-exec] note result: " << exp->name << " => ";
- auto resultType = func->getResults();
- if (resultType.isRef() && !resultType.isString()) {
- // Don't print reference values, as funcref(N) contains an index
- // for example, which is not guaranteed to remain identical after
- // optimizations. Do not print the type in detail (as even that
- // may change due to closed-world optimizations); just print a
- // simple type like JS does, 'object' or 'function', but also
- // print null for a null (so a null function does not get
- // printed as object, as in JS we have typeof null == 'object').
- if (values->size() == 1 && (*values)[0].isNull()) {
- std::cout << "null\n";
- } else if (resultType.isFunction()) {
- std::cout << "function\n";
- } else {
- std::cout << "object\n";
- }
- } else {
- // Non-references can be printed in full. So can strings, since we
- // always know how to print them and there is just one string
- // type.
- std::cout << *values << '\n';
+ for (auto value : *values) {
+ printValue(value);
}
}
}
@@ -150,6 +131,39 @@ struct ExecutionResults {
}
}
+ void printValue(Literal value) {
+ // Unwrap an externalized value to get the actual value.
+ if (Type::isSubType(value.type, Type(HeapType::ext, Nullable))) {
+ value = value.internalize();
+ }
+
+ // Don't print most reference values, as e.g. funcref(N) contains an index,
+ // which is not guaranteed to remain identical after optimizations. Do not
+ // print the type in detail (as even that may change due to closed-world
+ // optimizations); just print a simple type like JS does, 'object' or
+ // 'function', but also print null for a null (so a null function does not
+ // get printed as object, as in JS we have typeof null == 'object').
+ //
+ // The only references we print in full are strings and i31s, which have
+ // simple and stable internal structures that optimizations will not alter.
+ auto type = value.type;
+ if (type.isRef()) {
+ if (type.isString() || type.getHeapType() == HeapType::i31) {
+ std::cout << value << '\n';
+ } else if (value.isNull()) {
+ std::cout << "null\n";
+ } else if (type.isFunction()) {
+ std::cout << "function\n";
+ } else {
+ std::cout << "object\n";
+ }
+ return;
+ }
+
+ // Non-references can be printed in full.
+ std::cout << value << '\n';
+ }
+
// get current results and check them against previous ones
void check(Module& wasm) {
ExecutionResults optimizedResults;
diff --git a/test/lit/exec/i31.wast b/test/lit/exec/i31.wast
index 70d220d8c..0833d490d 100644
--- a/test/lit/exec/i31.wast
+++ b/test/lit/exec/i31.wast
@@ -76,6 +76,27 @@
(ref.null i31)
)
)
+
+ ;; CHECK: [fuzz-exec] calling return-i31
+ ;; CHECK-NEXT: [fuzz-exec] note result: return-i31 => i31ref(42)
+ (func $return-i31 (export "return-i31") (result i31ref)
+ ;; An i31 should be logged out using its integer value, unlike a struct or
+ ;; array which ends up as only "object".
+ (ref.i31
+ (i32.const 42)
+ )
+ )
+
+ ;; CHECK: [fuzz-exec] calling return-exted-i31
+ ;; CHECK-NEXT: [fuzz-exec] note result: return-exted-i31 => i31ref(42)
+ (func $return-exted-i31 (export "return-exted-i31") (result externref)
+ ;; Even an externalized i31 is logged out using its integer value.
+ (extern.externalize
+ (ref.i31
+ (i32.const 42)
+ )
+ )
+ )
)
;; CHECK: [fuzz-exec] calling null-local
;; CHECK-NEXT: [fuzz-exec] note result: null-local => 1
@@ -97,10 +118,18 @@
;; CHECK: [fuzz-exec] calling trap
;; CHECK-NEXT: [trap null ref]
+
+;; CHECK: [fuzz-exec] calling return-i31
+;; CHECK-NEXT: [fuzz-exec] note result: return-i31 => i31ref(42)
+
+;; CHECK: [fuzz-exec] calling return-exted-i31
+;; CHECK-NEXT: [fuzz-exec] note result: return-exted-i31 => i31ref(42)
;; CHECK-NEXT: [fuzz-exec] comparing nn-s
;; CHECK-NEXT: [fuzz-exec] comparing nn-u
;; CHECK-NEXT: [fuzz-exec] comparing non-null
;; CHECK-NEXT: [fuzz-exec] comparing null-immediate
;; CHECK-NEXT: [fuzz-exec] comparing null-local
+;; CHECK-NEXT: [fuzz-exec] comparing return-exted-i31
+;; CHECK-NEXT: [fuzz-exec] comparing return-i31
;; CHECK-NEXT: [fuzz-exec] comparing trap
;; CHECK-NEXT: [fuzz-exec] comparing zero-is-not-null