summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/fuzz_opt.py11
-rw-r--r--scripts/fuzz_shell.js49
-rw-r--r--src/tools/execution-results.h14
-rw-r--r--src/tools/js-wrapper.h134
-rw-r--r--src/tools/wasm-opt.cpp24
-rw-r--r--test/lit/exec/no-compare-refs.wast4
-rw-r--r--test/lit/help/wasm-opt.test4
-rw-r--r--test/lit/unicode-filenames.wast2
-rw-r--r--test/passes/emit-js-wrapper=a.js.txt84
-rw-r--r--test/passes/emit-js-wrapper=a.js.wast37
-rw-r--r--test/passes/emit-js-wrapper=a.js.wast.js79
-rw-r--r--test/passes/fuzz-exec_all-features.txt4
-rw-r--r--test/passes/simplify-globals_all-features_fuzz-exec.txt4
13 files changed, 62 insertions, 388 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py
index 8e80c2bb9..8dc87cb7a 100755
--- a/scripts/fuzz_opt.py
+++ b/scripts/fuzz_opt.py
@@ -665,8 +665,11 @@ def run_d8_js(js, args=[], liftoff=True):
return run_vm(cmd)
+FUZZ_SHELL_JS = in_binaryen('scripts', 'fuzz_shell.js')
+
+
def run_d8_wasm(wasm, liftoff=True):
- return run_d8_js(in_binaryen('scripts', 'fuzz_shell.js'), [wasm], liftoff=liftoff)
+ return run_d8_js(FUZZ_SHELL_JS, [wasm], liftoff=liftoff)
def all_disallowed(features):
@@ -746,8 +749,7 @@ class CompareVMs(TestCaseHandler):
name = 'd8'
def run(self, wasm, extra_d8_flags=[]):
- run([in_bin('wasm-opt'), wasm, '--emit-js-wrapper=' + wasm + '.js'] + FEATURE_OPTS)
- return run_vm([shared.V8, wasm + '.js'] + shared.V8_OPTS + extra_d8_flags + ['--', wasm])
+ return run_vm([shared.V8, FUZZ_SHELL_JS] + shared.V8_OPTS + extra_d8_flags + ['--', wasm])
def can_run(self, wasm):
# INITIAL_CONTENT is disallowed because some initial spec testcases
@@ -1036,7 +1038,8 @@ class Wasm2JS(TestCaseHandler):
compare_between_vms(before, interpreter, 'Wasm2JS (vs interpreter)')
def run(self, wasm):
- wrapper = run([in_bin('wasm-opt'), wasm, '--emit-js-wrapper=/dev/stdout'] + FEATURE_OPTS)
+ with open(FUZZ_SHELL_JS) as f:
+ wrapper = f.read()
cmd = [in_bin('wasm2js'), wasm, '--emscripten']
# avoid optimizations if we have nans, as we don't handle them with
# full precision and optimizations can change things
diff --git a/scripts/fuzz_shell.js b/scripts/fuzz_shell.js
index 4a3b42d9f..743e838b5 100644
--- a/scripts/fuzz_shell.js
+++ b/scripts/fuzz_shell.js
@@ -38,15 +38,34 @@ var detrand = (function() {
};
})();
-// Fuzz integration.
-function logValue(x, y) {
+// Print out a value in a way that works well for fuzzing.
+function printed(x, y) {
if (typeof y !== 'undefined') {
- console.log('[LoggingExternalInterface logging ' + x + ' ' + y + ']');
+ // A pair of i32s which are a legalized i64.
+ return x + ' ' + y;
+ } else if (x === null) {
+ // JS has just one null. Print that out rather than typeof null which is
+ // 'object', below.
+ return 'null';
+ } else if (typeof x !== 'number' && typeof x !== 'string') {
+ // Something that is not a number or string, like a reference. We can't
+ // print a reference because it could look different after opts - imagine
+ // that a function gets renamed internally (that is, the problem is that
+ // JS printing will emit some info about the reference and not a stable
+ // external representation of it). In those cases just print the type,
+ // which will be 'object' or 'function'.
+ return typeof x;
} else {
- console.log('[LoggingExternalInterface logging ' + x + ']');
+ // A number. Print the whole thing.
+ return '' + x;
}
}
+// Fuzzer integration.
+function logValue(x, y) {
+ console.log('[LoggingExternalInterface logging ' + printed(x, y) + ']');
+}
+
// Set up the imports.
var imports = {
'fuzzing-support': {
@@ -94,21 +113,25 @@ function refreshView() {
}
// Run the wasm.
-var sortedExports = [];
for (var e in exports) {
- sortedExports.push(e);
-}
-sortedExports.sort();
-sortedExports.forEach(function(e) {
- if (typeof exports[e] !== 'function') return;
+ if (typeof exports[e] !== 'function') {
+ continue;
+ }
+ // Send the function a null for each parameter. Null can be converted without
+ // error to both a number and a reference.
+ var func = exports[e];
+ var args = [];
+ for (var i = 0; i < func.length; i++) {
+ args.push(null);
+ }
try {
console.log('[fuzz-exec] calling ' + e);
- var result = exports[e]();
+ var result = func.apply(null, args);
if (typeof result !== 'undefined') {
- console.log('[fuzz-exec] note result: $' + e + ' => ' + result);
+ console.log('[fuzz-exec] note result: ' + e + ' => ' + printed(result));
}
} catch (e) {
console.log('exception!');// + [e, e.stack]);
}
-});
+}
diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h
index 0cd40959e..add7cd3a5 100644
--- a/src/tools/execution-results.h
+++ b/src/tools/execution-results.h
@@ -119,8 +119,18 @@ struct ExecutionResults {
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.
- std::cout << resultType << '\n';
+ // 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
diff --git a/src/tools/js-wrapper.h b/src/tools/js-wrapper.h
deleted file mode 100644
index edee301ca..000000000
--- a/src/tools/js-wrapper.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2017 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.
- */
-
-//
-// Emit a JavaScript wrapper to run a wasm module with some test
-// values, useful for fuzzing.
-//
-
-#include "wasm-type.h"
-#include "wasm.h"
-#include <string>
-
-namespace wasm {
-
-inline std::string generateJSWrapper(Module& wasm) {
- std::string ret;
- ret += "if (typeof console === 'undefined') {\n"
- " console = { log: print };\n"
- "}\n"
- "var tempRet0;\n"
- "var binary;\n"
- "if (typeof process === 'object' && typeof require === 'function' /* "
- "node.js detection */) {\n"
- " var args = process.argv.slice(2);\n"
- " binary = require('fs').readFileSync(args[0]);\n"
- " if (!binary.buffer) binary = new Uint8Array(binary);\n"
- "} else {\n"
- " var args;\n"
- " if (typeof scriptArgs != 'undefined') {\n"
- " args = scriptArgs;\n"
- " } else if (typeof arguments != 'undefined') {\n"
- " args = arguments;\n"
- " }\n"
- " if (typeof readbuffer === 'function') {\n"
- " binary = new Uint8Array(readbuffer(args[0]));\n"
- " } else {\n"
- " binary = read(args[0], 'binary');\n"
- " }\n"
- "}\n"
- "function literal(x, type) {\n"
- " var ret = '';\n"
- " switch (type) {\n"
- " case 'i32': ret += (x | 0); break;\n"
- " case 'f32':\n"
- " case 'f64': {\n"
- " if (x == 0 && (1 / x) < 0) ret += '-';\n"
- " ret += Number(x).toString();\n"
- " break;\n"
- " }\n"
- " // For anything else, just print the type.\n"
- " default: ret += type; break;\n"
- " }\n"
- " return ret;\n"
- "}\n"
- "var instance = new WebAssembly.Instance(new "
- "WebAssembly.Module(binary), {\n"
- " 'fuzzing-support': {\n"
- " 'log-i32': function(x) { "
- "console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') "
- "+ ']') },\n"
- " 'log-i64': function(x, y) { "
- "console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') "
- "+ ' ' + literal(y, 'i32') + ']') },\n" // legalization: two i32s
- " 'log-f32': function(x) { "
- "console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') "
- "+ ']') },\n" // legalization: an f64
- " 'log-f64': function(x) { "
- "console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') "
- "+ ']') },\n"
- " },\n"
- " 'env': {\n"
- " 'setTempRet0': function(x) { tempRet0 = x },\n"
- " 'getTempRet0': function() { return tempRet0 },\n"
- " },\n"
- "});\n";
- for (auto& exp : wasm.exports) {
- if (exp->kind != ExternalKind::Function) {
- continue; // something exported other than a function
- }
- auto* func = wasm.getFunction(exp->value);
- ret += "try {\n";
- ret += std::string(" console.log('[fuzz-exec] calling ") +
- exp->name.toString() + "');\n";
- if (func->getResults() != Type::none) {
- ret += std::string(" console.log('[fuzz-exec] note result: ") +
- exp->name.toString() + " => ' + literal(";
- } else {
- ret += " ";
- }
- ret += std::string("instance.exports.") + exp->name.toString() + "(";
- bool first = true;
- for (auto param : func->getParams()) {
- // zeros in arguments TODO more?
- if (first) {
- first = false;
- } else {
- ret += ", ";
- }
- if (param.isRef()) {
- ret += "null";
- } else {
- ret += "0";
- if (param == Type::i64) {
- ret += ", 0";
- }
- }
- }
- ret += ")";
- if (func->getResults() != Type::none) {
- ret += ", '" + func->getResults().toString() + "'))";
- // TODO: getTempRet
- }
- ret += ";\n";
- ret += "} catch (e) {\n";
- ret += " console.log('exception!' /* + e */);\n";
- ret += "}\n";
- }
- return ret;
-}
-
-} // namespace wasm
diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp
index 0b0ea2cd4..54a83d15a 100644
--- a/src/tools/wasm-opt.cpp
+++ b/src/tools/wasm-opt.cpp
@@ -23,7 +23,6 @@
#include "execution-results.h"
#include "fuzzing.h"
-#include "js-wrapper.h"
#include "optimization-options.h"
#include "pass.h"
#include "shell-interface.h"
@@ -86,7 +85,6 @@ int main(int argc, const char* argv[]) {
bool fuzzPasses = false;
bool fuzzMemory = true;
bool fuzzOOB = true;
- std::string emitJSWrapper;
std::string emitSpecWrapper;
std::string emitWasm2CWrapper;
std::string inputSourceMapFilename;
@@ -180,15 +178,6 @@ int main(int argc, const char* argv[]) {
WasmOptOption,
Options::Arguments::Zero,
[&](Options* o, const std::string& arguments) { fuzzOOB = false; })
- .add("--emit-js-wrapper",
- "-ejw",
- "Emit a JavaScript wrapper file that can run the wasm with some test "
- "values, useful for fuzzing",
- WasmOptOption,
- Options::Arguments::One,
- [&](Options* o, const std::string& arguments) {
- emitJSWrapper = arguments;
- })
.add("--emit-spec-wrapper",
"-esw",
"Emit a wasm spec interpreter wrapper file that can run the wasm with "
@@ -329,24 +318,11 @@ int main(int argc, const char* argv[]) {
}
}
- if (emitJSWrapper.size() > 0) {
- // As the code will run in JS, we must legalize it.
- PassRunner runner(&wasm);
- runner.add("legalize-js-interface");
- runner.run();
- }
-
ExecutionResults results;
if (fuzzExecBefore) {
results.get(wasm);
}
- if (emitJSWrapper.size() > 0) {
- std::ofstream outfile;
- outfile.open(wasm::Path::to_path(emitJSWrapper), std::ofstream::out);
- outfile << generateJSWrapper(wasm);
- outfile.close();
- }
if (emitSpecWrapper.size() > 0) {
std::ofstream outfile;
outfile.open(wasm::Path::to_path(emitSpecWrapper), std::ofstream::out);
diff --git a/test/lit/exec/no-compare-refs.wast b/test/lit/exec/no-compare-refs.wast
index bfa317a53..646ec1550 100644
--- a/test/lit/exec/no-compare-refs.wast
+++ b/test/lit/exec/no-compare-refs.wast
@@ -12,11 +12,11 @@
;; The type of the reference this function returns will change as a result of
;; signature pruning. The fuzzer should not complain about this.
;; CHECK: [fuzz-exec] calling return-ref
- ;; CHECK-NEXT: [fuzz-exec] note result: return-ref => funcref
+ ;; CHECK-NEXT: [fuzz-exec] note result: return-ref => function
(func $return-ref (export "return-ref") (result funcref)
(ref.func $no-use-param)
)
)
;; CHECK: [fuzz-exec] calling return-ref
-;; CHECK-NEXT: [fuzz-exec] note result: return-ref => funcref
+;; CHECK-NEXT: [fuzz-exec] note result: return-ref => function
;; CHECK-NEXT: [fuzz-exec] comparing return-ref
diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test
index be5924cf7..5e3a322ed 100644
--- a/test/lit/help/wasm-opt.test
+++ b/test/lit/help/wasm-opt.test
@@ -53,10 +53,6 @@
;; CHECK-NEXT: loads/stores/indirect calls when
;; CHECK-NEXT: fuzzing
;; CHECK-NEXT:
-;; CHECK-NEXT: --emit-js-wrapper,-ejw Emit a JavaScript wrapper file
-;; CHECK-NEXT: that can run the wasm with some
-;; CHECK-NEXT: test values, useful for fuzzing
-;; CHECK-NEXT:
;; CHECK-NEXT: --emit-spec-wrapper,-esw Emit a wasm spec interpreter
;; CHECK-NEXT: wrapper file that can run the
;; CHECK-NEXT: wasm with some test values,
diff --git a/test/lit/unicode-filenames.wast b/test/lit/unicode-filenames.wast
index f30ad9c09..a3fbabed0 100644
--- a/test/lit/unicode-filenames.wast
+++ b/test/lit/unicode-filenames.wast
@@ -1,6 +1,6 @@
;; RUN: wasm-as %s -o %t-❤.wasm --source-map %t-🗺️.map
;; RUN: cat %t-🗺️.map | filecheck %s --check-prefix SOURCEMAP
-;; RUN: wasm-opt %t-❤.wasm -o %t-🤬.wasm --emit-js-wrapper %t-❤.js --input-source-map %t-🗺️.map --output-source-map %t-🗺️.out.map
+;; RUN: wasm-opt %t-❤.wasm -o %t-🤬.wasm --emit-spec-wrapper %t-❤.js --input-source-map %t-🗺️.map --output-source-map %t-🗺️.out.map
;; RUN: cat %t-🗺️.out.map | filecheck %s --check-prefix SOURCEMAP
;; RUN: wasm-dis %t-🤬.wasm | filecheck %s --check-prefix MODULE
diff --git a/test/passes/emit-js-wrapper=a.js.txt b/test/passes/emit-js-wrapper=a.js.txt
deleted file mode 100644
index 4a72da8eb..000000000
--- a/test/passes/emit-js-wrapper=a.js.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-(module
- (type $0 (func (param i32 i32) (result i32)))
- (type $1 (func (param i32)))
- (type $2 (func (param i32 i64 f32 f64)))
- (type $3 (func (param i32 f32 f64)))
- (type $4 (func (param i32 f32 f64) (result i64)))
- (type $5 (func (param i32 i32 i32 f32 f64)))
- (type $6 (func (param i32 f32 f64) (result i32)))
- (import "env" "setTempRet0" (func $setTempRet0 (param i32)))
- (memory $0 256 256)
- (export "add" (func $add))
- (export "no_return" (func $no-return))
- (export "types" (func $legalstub$types))
- (export "types2" (func $types2))
- (export "types3" (func $legalstub$types3))
- (func $add (param $x i32) (param $y i32) (result i32)
- (i32.add
- (local.get $x)
- (local.get $y)
- )
- )
- (func $unexported (param $x i32) (param $y i32) (result i32)
- (i32.add
- (local.get $x)
- (local.get $y)
- )
- )
- (func $no-return (param $x i32)
- (drop
- (i32.add
- (local.get $x)
- (local.get $x)
- )
- )
- )
- (func $types (param $x i32) (param $y i64) (param $z f32) (param $w f64)
- (nop)
- )
- (func $types2 (param $x i32) (param $z f32) (param $w f64)
- (nop)
- )
- (func $types3 (param $x i32) (param $z f32) (param $w f64) (result i64)
- (i64.const 1)
- )
- (func $legalstub$types (param $0 i32) (param $1 i32) (param $2 i32) (param $3 f32) (param $4 f64)
- (call $types
- (local.get $0)
- (i64.or
- (i64.extend_i32_u
- (local.get $1)
- )
- (i64.shl
- (i64.extend_i32_u
- (local.get $2)
- )
- (i64.const 32)
- )
- )
- (local.get $3)
- (local.get $4)
- )
- )
- (func $legalstub$types3 (param $0 i32) (param $1 f32) (param $2 f64) (result i32)
- (local $3 i64)
- (local.set $3
- (call $types3
- (local.get $0)
- (local.get $1)
- (local.get $2)
- )
- )
- (call $setTempRet0
- (i32.wrap_i64
- (i64.shr_u
- (local.get $3)
- (i64.const 32)
- )
- )
- )
- (i32.wrap_i64
- (local.get $3)
- )
- )
-)
diff --git a/test/passes/emit-js-wrapper=a.js.wast b/test/passes/emit-js-wrapper=a.js.wast
deleted file mode 100644
index 8ebd83b0b..000000000
--- a/test/passes/emit-js-wrapper=a.js.wast
+++ /dev/null
@@ -1,37 +0,0 @@
-(module
- (memory $0 256 256)
- (export "add" (func $add))
- (export "no_return" (func $no-return)) ;; note exported name is slightly different
- (export "types" (func $types))
- (export "types2" (func $types2))
- (export "types3" (func $types3))
- (func $add (param $x i32) (param $y i32) (result i32)
- (i32.add
- (local.get $x)
- (local.get $y)
- )
- )
- (func $unexported (param $x i32) (param $y i32) (result i32)
- (i32.add
- (local.get $x)
- (local.get $y)
- )
- )
- (func $no-return (param $x i32)
- (drop
- (i32.add
- (local.get $x)
- (local.get $x)
- )
- )
- )
- (func $types (param $x i32) (param $y i64) (param $z f32) (param $w f64)
- (nop)
- )
- (func $types2 (param $x i32) (param $z f32) (param $w f64)
- (nop)
- )
- (func $types3 (param $x i32) (param $z f32) (param $w f64) (result i64)
- (i64.const 1)
- )
-)
diff --git a/test/passes/emit-js-wrapper=a.js.wast.js b/test/passes/emit-js-wrapper=a.js.wast.js
deleted file mode 100644
index 916f029f5..000000000
--- a/test/passes/emit-js-wrapper=a.js.wast.js
+++ /dev/null
@@ -1,79 +0,0 @@
-if (typeof console === 'undefined') {
- console = { log: print };
-}
-var tempRet0;
-var binary;
-if (typeof process === 'object' && typeof require === 'function' /* node.js detection */) {
- var args = process.argv.slice(2);
- binary = require('fs').readFileSync(args[0]);
- if (!binary.buffer) binary = new Uint8Array(binary);
-} else {
- var args;
- if (typeof scriptArgs != 'undefined') {
- args = scriptArgs;
- } else if (typeof arguments != 'undefined') {
- args = arguments;
- }
- if (typeof readbuffer === 'function') {
- binary = new Uint8Array(readbuffer(args[0]));
- } else {
- binary = read(args[0], 'binary');
- }
-}
-function literal(x, type) {
- var ret = '';
- switch (type) {
- case 'i32': ret += (x | 0); break;
- case 'f32':
- case 'f64': {
- if (x == 0 && (1 / x) < 0) ret += '-';
- ret += Number(x).toString();
- break;
- }
- // For anything else, just print the type.
- default: ret += type; break;
- }
- return ret;
-}
-var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), {
- 'fuzzing-support': {
- 'log-i32': function(x) { console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') + ']') },
- 'log-i64': function(x, y) { console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') + ' ' + literal(y, 'i32') + ']') },
- 'log-f32': function(x) { console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') + ']') },
- 'log-f64': function(x) { console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') + ']') },
- },
- 'env': {
- 'setTempRet0': function(x) { tempRet0 = x },
- 'getTempRet0': function() { return tempRet0 },
- },
-});
-try {
- console.log('[fuzz-exec] calling add');
- console.log('[fuzz-exec] note result: add => ' + literal(instance.exports.add(0, 0), 'i32'));
-} catch (e) {
- console.log('exception!' /* + e */);
-}
-try {
- console.log('[fuzz-exec] calling no_return');
- instance.exports.no_return(0);
-} catch (e) {
- console.log('exception!' /* + e */);
-}
-try {
- console.log('[fuzz-exec] calling types');
- instance.exports.types(0, 0, 0, 0, 0);
-} catch (e) {
- console.log('exception!' /* + e */);
-}
-try {
- console.log('[fuzz-exec] calling types2');
- instance.exports.types2(0, 0, 0);
-} catch (e) {
- console.log('exception!' /* + e */);
-}
-try {
- console.log('[fuzz-exec] calling types3');
- console.log('[fuzz-exec] note result: types3 => ' + literal(instance.exports.types3(0, 0, 0), 'i32'));
-} catch (e) {
- console.log('exception!' /* + e */);
-}
diff --git a/test/passes/fuzz-exec_all-features.txt b/test/passes/fuzz-exec_all-features.txt
index 22ea5f06a..fcb8e8a3c 100644
--- a/test/passes/fuzz-exec_all-features.txt
+++ b/test/passes/fuzz-exec_all-features.txt
@@ -212,7 +212,7 @@
[LoggingExternalInterface logging 214]
[fuzz-exec] comparing rmw-reads-modifies-and-writes-asymmetrical
[fuzz-exec] calling func
-[fuzz-exec] note result: func => funcref
+[fuzz-exec] note result: func => function
(module
(type $0 (func (result funcref)))
(elem declare func $func)
@@ -222,5 +222,5 @@
)
)
[fuzz-exec] calling func
-[fuzz-exec] note result: func => funcref
+[fuzz-exec] note result: func => function
[fuzz-exec] comparing func
diff --git a/test/passes/simplify-globals_all-features_fuzz-exec.txt b/test/passes/simplify-globals_all-features_fuzz-exec.txt
index fbbcc30c4..cb097d587 100644
--- a/test/passes/simplify-globals_all-features_fuzz-exec.txt
+++ b/test/passes/simplify-globals_all-features_fuzz-exec.txt
@@ -1,5 +1,5 @@
[fuzz-exec] calling export
-[fuzz-exec] note result: export => funcref
+[fuzz-exec] note result: export => function
(module
(type $0 (func (param f32 i31ref i64 f64 funcref)))
(type $1 (func (result funcref)))
@@ -17,5 +17,5 @@
)
)
[fuzz-exec] calling export
-[fuzz-exec] note result: export => funcref
+[fuzz-exec] note result: export => function
[fuzz-exec] comparing export