summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/fuzz_shell.js89
-rw-r--r--src/tools/execution-results.h55
-rw-r--r--src/tools/fuzzing.h6
-rw-r--r--src/tools/fuzzing/fuzzing.cpp122
-rw-r--r--test/lit/exec/fuzzing-api.wast199
-rw-r--r--test/lit/passes/gufa-closed-open.wast6
-rw-r--r--test/passes/fuzz_metrics_noprint.bin.txt52
-rw-r--r--test/passes/fuzz_metrics_passes_noprint.bin.txt53
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt87
9 files changed, 493 insertions, 176 deletions
diff --git a/scripts/fuzz_shell.js b/scripts/fuzz_shell.js
index 782040dac..95176bbe6 100644
--- a/scripts/fuzz_shell.js
+++ b/scripts/fuzz_shell.js
@@ -160,6 +160,49 @@ function callFunc(func) {
return func.apply(null, args);
}
+// Calls a given function in a try-catch, swallowing JS exceptions, and return 1
+// if we did in fact swallow an exception. Wasm traps are not swallowed (see
+// details below).
+function tryCall(func) {
+ try {
+ func();
+ return 0;
+ } catch (e) {
+ // We only want to catch exceptions, not wasm traps: traps should still
+ // halt execution. Handling this requires different code in wasm2js, so
+ // check for that first (wasm2js does not define RuntimeError, so use
+ // that for the check - when wasm2js is run, we override the entire
+ // WebAssembly object with a polyfill, so we know exactly what it
+ // contains).
+ var wasm2js = !WebAssembly.RuntimeError;
+ if (!wasm2js) {
+ // When running native wasm, we can detect wasm traps.
+ if (e instanceof WebAssembly.RuntimeError) {
+ throw e;
+ }
+ }
+ var text = e + '';
+ // We must not swallow host limitations here: a host limitation is a
+ // problem that means we must not compare the outcome here to any other
+ // VM.
+ var hostIssues = ['requested new array is too large',
+ 'out of memory',
+ 'Maximum call stack size exceeded'];
+ if (wasm2js) {
+ // When wasm2js does trap, it just throws an "abort" error.
+ hostIssues.push('abort');
+ }
+ for (var hostIssue of hostIssues) {
+ if (text.includes(hostIssue)) {
+ throw e;
+ }
+ }
+ // Otherwise, this is a normal exception we want to catch (a wasm
+ // exception, or a conversion error on the wasm/JS boundary, etc.).
+ return 1;
+ }
+}
+
// Table get/set operations need a BigInt if the table has 64-bit indexes. This
// adds a proper cast as needed.
function toAddressType(table, index) {
@@ -204,43 +247,15 @@ var imports = {
callFunc(exportList[index].value);
},
'call-export-catch': (index) => {
- try {
- callFunc(exportList[index].value);
- return 0;
- } catch (e) {
- // We only want to catch exceptions, not wasm traps: traps should still
- // halt execution. Handling this requires different code in wasm2js, so
- // check for that first (wasm2js does not define RuntimeError, so use
- // that for the check - when wasm2js is run, we override the entire
- // WebAssembly object with a polyfill, so we know exactly what it
- // contains).
- var wasm2js = !WebAssembly.RuntimeError;
- if (!wasm2js) {
- // When running native wasm, we can detect wasm traps.
- if (e instanceof WebAssembly.RuntimeError) {
- throw e;
- }
- }
- var text = e + '';
- // We must not swallow host limitations here: a host limitation is a
- // problem that means we must not compare the outcome here to any other
- // VM.
- var hostIssues = ['requested new array is too large',
- 'out of memory',
- 'Maximum call stack size exceeded'];
- if (wasm2js) {
- // When wasm2js does trap, it just throws an "abort" error.
- hostIssues.push('abort');
- }
- for (var hostIssue of hostIssues) {
- if (text.includes(hostIssue)) {
- throw e;
- }
- }
- // Otherwise, this is a normal exception we want to catch (a wasm
- // exception, or a conversion error on the wasm/JS boundary, etc.).
- return 1;
- }
+ return tryCall(() => callFunc(exportList[index].value));
+ },
+
+ // Funcref operations.
+ 'call-ref': (ref) => {
+ callFunc(ref);
+ },
+ 'call-ref-catch': (ref) => {
+ return tryCall(() => callFunc(ref));
},
},
// Emscripten support.
diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h
index 25d0c0772..bffc4e8f2 100644
--- a/src/tools/execution-results.h
+++ b/src/tools/execution-results.h
@@ -105,13 +105,25 @@ public:
tableStore(exportedTable, index, arguments[1]);
return {};
} else if (import->base == "call-export") {
- callExport(arguments[0].geti32());
+ callExportAsJS(arguments[0].geti32());
// Return nothing. If we wanted to return a value we'd need to have
// multiple such functions, one for each signature.
return {};
} else if (import->base == "call-export-catch") {
try {
- callExport(arguments[0].geti32());
+ callExportAsJS(arguments[0].geti32());
+ return {Literal(int32_t(0))};
+ } catch (const WasmException& e) {
+ return {Literal(int32_t(1))};
+ }
+ } else if (import->base == "call-ref") {
+ callRefAsJS(arguments[0]);
+ // Return nothing. If we wanted to return a value we'd need to have
+ // multiple such functions, one for each signature.
+ return {};
+ } else if (import->base == "call-ref-catch") {
+ try {
+ callRefAsJS(arguments[0]);
return {Literal(int32_t(0))};
} catch (const WasmException& e) {
return {Literal(int32_t(1))};
@@ -145,7 +157,7 @@ public:
throwException(WasmException{Literal(payload)});
}
- Literals callExport(Index index) {
+ Literals callExportAsJS(Index index) {
if (index >= wasm.exports.size()) {
// No export.
throwEmptyException();
@@ -155,20 +167,47 @@ public:
// No callable export.
throwEmptyException();
}
- auto* func = wasm.getFunction(exp->value);
+ return callFunctionAsJS(exp->value);
+ }
+
+ Literals callRefAsJS(Literal ref) {
+ if (!ref.isFunction()) {
+ // Not a callable ref.
+ throwEmptyException();
+ }
+ return callFunctionAsJS(ref.getFunc());
+ }
- // TODO JS traps on some types on the boundary, which we should behave the
- // same on. For now, this is not needed because the fuzzer will prune all
- // non-JS-compatible exports anyhow.
+ // Call a function in a "JS-ey" manner, adding arguments as needed, and
+ // throwing if necessary, the same way JS does.
+ Literals callFunctionAsJS(Name name) {
+ auto* func = wasm.getFunction(name);
- // Send default values as arguments, or trap if we need anything else.
+ // Send default values as arguments, or error if we need anything else.
Literals arguments;
for (const auto& param : func->getParams()) {
+ // An i64 param can work from JS, but fuzz_shell provides 0, which errors
+ // on attempts to convert it to BigInt. v128 cannot work at all.
+ if (param == Type::i64 || param == Type::v128) {
+ throwEmptyException();
+ }
if (!param.isDefaultable()) {
throwEmptyException();
}
arguments.push_back(Literal::makeZero(param));
}
+
+ // Error on illegal results. Note that this happens, as per JS semantics,
+ // *before* the call.
+ for (const auto& result : func->getResults()) {
+ // An i64 result is fine: a BigInt will be provided. But v128 still
+ // errors.
+ if (result == Type::v128) {
+ throwEmptyException();
+ }
+ }
+
+ // Call the function.
return instance->callFunction(func->name, arguments);
}
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index a3261ccbe..78219045c 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -115,6 +115,8 @@ private:
Name tableSetImportName;
Name callExportImportName;
Name callExportCatchImportName;
+ Name callRefImportName;
+ Name callRefCatchImportName;
std::unordered_map<Type, std::vector<Name>> globalsByType;
std::unordered_map<Type, std::vector<Name>> mutableGlobalsByType;
@@ -244,7 +246,9 @@ private:
Expression* makeImportThrowing(Type type);
Expression* makeImportTableGet();
Expression* makeImportTableSet(Type type);
- Expression* makeImportCallExport(Type type);
+ // Call either an export or a ref. We do this from a single function to better
+ // control the frequency of each.
+ Expression* makeImportCallCode(Type type);
Expression* makeMemoryHashLogging();
// Function creation
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index ab200a126..a7f5e0d01 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -771,22 +771,33 @@ void TranslateToFuzzReader::addImportLoggingSupport() {
}
void TranslateToFuzzReader::addImportCallingSupport() {
+ if (wasm.features.hasReferenceTypes() && closedWorld) {
+ // In closed world mode we must *remove* the call-ref* imports, if they
+ // exist in the initial content. These are not valid to call in closed-world
+ // mode as they call function references. (Another solution here would be to
+ // make closed-world issue validation errors on these imports, but that
+ // would require changes to the general-purpose validator.)
+ for (auto& func : wasm.functions) {
+ if (func->imported() && func->module == "fuzzing-support" &&
+ func->base.startsWith("call-ref")) {
+ // Make it non-imported, and with a simple body.
+ func->module = func->base = Name();
+ auto results = func->getResults();
+ func->body =
+ results.isConcrete() ? makeConst(results) : makeNop(Type::none);
+ }
+ }
+ }
+
// Only add these some of the time, as they inhibit some fuzzing (things like
// wasm-ctor-eval and wasm-merge are sensitive to the wasm being able to call
- // its own exports, and to care about the indexes of the exports):
- //
- // 0 - none
- // 1 - call-export
- // 2 - call-export-catch
- // 3 - call-export & call-export-catch
- // 4 - none
- // 5 - none
- //
- auto choice = upTo(6);
- if (choice >= 4) {
+ // its own exports, and to care about the indexes of the exports).
+ if (oneIn(2)) {
return;
}
+ auto choice = upTo(16);
+
if (choice & 1) {
// Given an export index, call it from JS.
callExportImportName = Names::getValidFunctionName(wasm, "call-export");
@@ -811,6 +822,34 @@ void TranslateToFuzzReader::addImportCallingSupport() {
func->type = Signature(Type::i32, Type::i32);
wasm.addFunction(std::move(func));
}
+
+ // If the wasm will be used for closed-world testing, we cannot use the
+ // call-ref variants, as mentioned before.
+ if (wasm.features.hasReferenceTypes() && !closedWorld) {
+ if (choice & 4) {
+ // Given an funcref, call it from JS.
+ callRefImportName = Names::getValidFunctionName(wasm, "call-ref");
+ auto func = std::make_unique<Function>();
+ func->name = callRefImportName;
+ func->module = "fuzzing-support";
+ func->base = "call-ref";
+ func->type = Signature({Type(HeapType::func, Nullable)}, Type::none);
+ wasm.addFunction(std::move(func));
+ }
+
+ if (choice & 8) {
+ // Given an funcref, call it from JS and catch all exceptions (similar
+ // to callExportCatch), return 1 if we caught).
+ callRefCatchImportName =
+ Names::getValidFunctionName(wasm, "call-ref-catch");
+ auto func = std::make_unique<Function>();
+ func->name = callRefCatchImportName;
+ func->module = "fuzzing-support";
+ func->base = "call-ref-catch";
+ func->type = Signature(Type(HeapType::func, Nullable), Type::i32);
+ wasm.addFunction(std::move(func));
+ }
+ }
}
void TranslateToFuzzReader::addImportThrowingSupport() {
@@ -998,27 +1037,48 @@ Expression* TranslateToFuzzReader::makeImportTableSet(Type type) {
Type::none);
}
-Expression* TranslateToFuzzReader::makeImportCallExport(Type type) {
- // The none-returning variant just does the call. The i32-returning one
- // catches any errors and returns 1 when it saw an error. Based on the
- // variant, pick which to call, and the maximum index to call.
- Name target;
+Expression* TranslateToFuzzReader::makeImportCallCode(Type type) {
+ // Call code: either an export or a ref. Each has a catching and non-catching
+ // variant. The catching variants return i32, the others none.
+ assert(type == Type::none || type == Type::i32);
+ auto catching = type == Type::i32;
+ auto exportTarget =
+ catching ? callExportCatchImportName : callExportImportName;
+ auto refTarget = catching ? callRefCatchImportName : callRefImportName;
+
+ // We want to call a ref less often, as refs are more likely to error (a
+ // function reference can have arbitrary params and results, including things
+ // that error on the JS boundary; an export is already filtered for such
+ // things in some cases - when we legalize the boundary - and even if not, we
+ // emit lots of void(void) functions - all the invoke_foo functions - that are
+ // safe to call).
+ if (refTarget) {
+ // This matters a lot more in the variants that do *not* catch (in the
+ // catching ones, we just get a result of 1, but when not caught it halts
+ // execution).
+ if ((catching && (!exportTarget || oneIn(2))) || (!catching && oneIn(4))) {
+ // Most of the time make a non-nullable funcref, to avoid errors.
+ auto refType = Type(HeapType::func, oneIn(10) ? Nullable : NonNullable);
+ return builder.makeCall(refTarget, {make(refType)}, type);
+ }
+ }
+
+ if (!exportTarget) {
+ // We decided not to emit a call-ref here, due to fear of erroring, and
+ // there is no call-export, so just emit something trivial.
+ return makeTrivial(type);
+ }
+
+ // Pick the maximum export index to call.
Index maxIndex = wasm.exports.size();
- if (type == Type::none) {
- target = callExportImportName;
- } else if (type == Type::i32) {
- target = callExportCatchImportName;
- // This never traps, so we can be less careful, but we do still want to
- // avoid trapping a lot as executing code is more interesting. (Note that
+ if (type == Type::i32) {
+ // This swallows errors, so we can be less careful, but we do still want to
+ // avoid swallowing a lot as executing code is more interesting. (Note that
// even though we double here, the risk is not that great: we are still
// adding functions as we go, so the first half of functions/exports can
// double here and still end up in bounds by the time we've added them all.)
maxIndex = (maxIndex + 1) * 2;
- } else {
- WASM_UNREACHABLE("bad import.call");
}
- // We must have set up the target function.
- assert(target);
// Most of the time, call a valid export index in the range we picked, but
// sometimes allow anything at all.
@@ -1027,7 +1087,7 @@ Expression* TranslateToFuzzReader::makeImportCallExport(Type type) {
index = builder.makeBinary(
RemUInt32, index, builder.makeConst(int32_t(maxIndex)));
}
- return builder.makeCall(target, {index}, type);
+ return builder.makeCall(exportTarget, {index}, type);
}
Expression* TranslateToFuzzReader::makeMemoryHashLogging() {
@@ -1705,8 +1765,8 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
options.add(FeatureSet::Atomics, &Self::makeAtomic);
}
if (type == Type::i32) {
- if (callExportCatchImportName) {
- options.add(FeatureSet::MVP, &Self::makeImportCallExport);
+ if (callExportCatchImportName || callRefCatchImportName) {
+ options.add(FeatureSet::MVP, &Self::makeImportCallCode);
}
options.add(FeatureSet::ReferenceTypes, &Self::makeRefIsNull);
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC,
@@ -1787,8 +1847,8 @@ Expression* TranslateToFuzzReader::_makenone() {
if (tableSetImportName) {
options.add(FeatureSet::ReferenceTypes, &Self::makeImportTableSet);
}
- if (callExportImportName) {
- options.add(FeatureSet::MVP, &Self::makeImportCallExport);
+ if (callExportImportName || callRefImportName) {
+ options.add(FeatureSet::MVP, &Self::makeImportCallCode);
}
return (this->*pick(options))(Type::none);
}
diff --git a/test/lit/exec/fuzzing-api.wast b/test/lit/exec/fuzzing-api.wast
index 38a8ce41b..eae95fc0a 100644
--- a/test/lit/exec/fuzzing-api.wast
+++ b/test/lit/exec/fuzzing-api.wast
@@ -16,6 +16,9 @@
(import "fuzzing-support" "call-export" (func $call.export (param i32)))
(import "fuzzing-support" "call-export-catch" (func $call.export.catch (param i32) (result i32)))
+ (import "fuzzing-support" "call-ref" (func $call.ref (param funcref)))
+ (import "fuzzing-support" "call-ref-catch" (func $call.ref.catch (param funcref) (result i32)))
+
(table $table 10 20 funcref)
;; Note that the exported table appears first here, but in the binary and in
@@ -102,7 +105,6 @@
;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 1]
- ;; CHECK-NEXT: warning: no passes specified, not doing any work
(func $export.calling.catching (export "export.calling.catching")
;; At index 0 in the exports we have $logging, so we will do those loggings,
;; then log a 0 as no exception happens.
@@ -118,6 +120,162 @@
)
)
)
+
+ ;; CHECK: [fuzz-exec] calling ref.calling
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 42]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
+ ;; CHECK-NEXT: [exception thrown: __private ()]
+ (func $ref.calling (export "ref.calling")
+ ;; This will emit some logging.
+ (call $call.ref
+ (ref.func $logging)
+ )
+ ;; This will throw.
+ (call $call.ref
+ (ref.null func)
+ )
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.catching
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 42]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+ (func $ref.calling.catching (export "ref.calling.catching")
+ ;; This will emit some logging, then log 0 as we do not error.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $logging)
+ )
+ )
+ ;; The exception here is caught, and we'll log 1.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.null func)
+ )
+ )
+ )
+
+ (func $legal (param $x i32) (result i32)
+ ;; Helper for the function below. All types here are legal for JS.
+ (call $log-i32
+ (i32.const 12)
+ )
+ ;; Also log the param to show it is 0, which is what $call.ref does for all
+ ;; params.
+ (call $log-i32
+ (local.get $x)
+ )
+ (i32.const 34)
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.legal
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 12]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+ (func $ref.calling.legal (export "ref.calling.legal")
+ ;; It is fine to call-ref a function with params and results. The params get
+ ;; default values, and the results are ignored. All we will see here is the
+ ;; logging from the function, "12".
+ (call $call.ref
+ (ref.func $legal)
+ )
+ )
+
+ (func $illegal (param $x i64)
+ ;; Helper for the function below. The param, an i64, causes a problem: when we
+ ;; call from JS we provide 0, but 0 throws when it tries to convert to BigInt.
+ (call $log-i32
+ (i32.const 56)
+ )
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.illegal
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+ (func $ref.calling.illegal (export "ref.calling.illegal")
+ ;; The i64 param causes an error here, so we will only log 1 because we catch an exception.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $illegal)
+ )
+ )
+ )
+
+ (func $illegal-v128 (param $x v128)
+ ;; Helper for the function below.
+ (call $log-i32
+ (i32.const 56)
+ )
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.illegal-v128
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+ (func $ref.calling.illegal-v128 (export "ref.calling.illegal-v128")
+ ;; As above, we throw on the v128 param, and log 1.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $illegal-v128)
+ )
+ )
+ )
+
+ (func $illegal-result (result v128)
+ ;; Helper for the function below. The result is illegal for JS.
+ (call $log-i32
+ (i32.const 910)
+ )
+ (v128.const i32x4 1 2 3 4)
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.illegal-result
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+ (func $ref.calling.illegal-result (export "ref.calling.illegal-result")
+ ;; The v128 result causes an error here, so we will log 1 as an exception. The JS
+ ;; semantics determine that we do that check *before* the call, so the logging
+ ;; of 910 does not go through.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $illegal-result)
+ )
+ )
+ )
+
+ (func $legal-result (result i64)
+ ;; Helper for the function below.
+ (call $log-i32
+ (i32.const 910)
+ )
+ (i64.const 90)
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.legal-result
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 910]
+ ;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+ (func $ref.calling.legal-result (export "ref.calling.legal-result")
+ ;; Unlike v128, i64 is legal in a result. The JS VM just returns a BigInt.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $legal-result)
+ )
+ )
+ )
+
+ (func $trap
+ ;; Helper for the function below.
+ (unreachable)
+ )
+
+ ;; CHECK: [fuzz-exec] calling ref.calling.trap
+ ;; CHECK-NEXT: [trap unreachable]
+ ;; CHECK-NEXT: warning: no passes specified, not doing any work
+ (func $ref.calling.trap (export "ref.calling.trap")
+ ;; We try to catch an exception here, but the target function traps, which is
+ ;; not something we can catch. We will trap here, and not log at all.
+ (call $log-i32
+ (call $call.ref.catch
+ (ref.func $trap)
+ )
+ )
+ )
)
;; CHECK: [fuzz-exec] calling logging
;; CHECK-NEXT: [LoggingExternalInterface logging 42]
@@ -144,9 +302,48 @@
;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
;; CHECK-NEXT: [LoggingExternalInterface logging 0]
;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling
+;; CHECK-NEXT: [LoggingExternalInterface logging 42]
+;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
+;; CHECK-NEXT: [exception thrown: __private ()]
+
+;; CHECK: [fuzz-exec] calling ref.calling.catching
+;; CHECK-NEXT: [LoggingExternalInterface logging 42]
+;; CHECK-NEXT: [LoggingExternalInterface logging 3.14159]
+;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling.legal
+;; CHECK-NEXT: [LoggingExternalInterface logging 12]
+;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+
+;; CHECK: [fuzz-exec] calling ref.calling.illegal
+;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling.illegal-v128
+;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling.illegal-result
+;; CHECK-NEXT: [LoggingExternalInterface logging 1]
+
+;; CHECK: [fuzz-exec] calling ref.calling.legal-result
+;; CHECK-NEXT: [LoggingExternalInterface logging 910]
+;; CHECK-NEXT: [LoggingExternalInterface logging 0]
+
+;; CHECK: [fuzz-exec] calling ref.calling.trap
+;; CHECK-NEXT: [trap unreachable]
;; CHECK-NEXT: [fuzz-exec] comparing export.calling
;; CHECK-NEXT: [fuzz-exec] comparing export.calling.catching
;; CHECK-NEXT: [fuzz-exec] comparing logging
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.catching
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.illegal
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.illegal-result
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.illegal-v128
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.legal
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.legal-result
+;; CHECK-NEXT: [fuzz-exec] comparing ref.calling.trap
;; CHECK-NEXT: [fuzz-exec] comparing table.getting
;; CHECK-NEXT: [fuzz-exec] comparing table.setting
;; CHECK-NEXT: [fuzz-exec] comparing throwing
diff --git a/test/lit/passes/gufa-closed-open.wast b/test/lit/passes/gufa-closed-open.wast
index 47add9df5..689ee194f 100644
--- a/test/lit/passes/gufa-closed-open.wast
+++ b/test/lit/passes/gufa-closed-open.wast
@@ -12,15 +12,15 @@
;; OPEND: (type $2 (func (param i32)))
- ;; OPEND: (import "fuzzing-support" "call-ref-catch" (func $external-caller (type $0) (param funcref)))
+ ;; OPEND: (import "outside" "call-ref-catch" (func $external-caller (type $0) (param funcref)))
;; CLOSE: (type $0 (func (param funcref)))
;; CLOSE: (type $1 (func))
;; CLOSE: (type $2 (func (param i32)))
- ;; CLOSE: (import "fuzzing-support" "call-ref-catch" (func $external-caller (type $0) (param funcref)))
- (import "fuzzing-support" "call-ref-catch" (func $external-caller (param funcref)))
+ ;; CLOSE: (import "outside" "call-ref-catch" (func $external-caller (type $0) (param funcref)))
+ (import "outside" "call-ref-catch" (func $external-caller (param funcref)))
;; OPEND: (elem declare func $func)
diff --git a/test/passes/fuzz_metrics_noprint.bin.txt b/test/passes/fuzz_metrics_noprint.bin.txt
index 0fa206e0a..a2f996bcb 100644
--- a/test/passes/fuzz_metrics_noprint.bin.txt
+++ b/test/passes/fuzz_metrics_noprint.bin.txt
@@ -1,35 +1,35 @@
Metrics
total
- [exports] : 45
- [funcs] : 60
+ [exports] : 49
+ [funcs] : 74
[globals] : 18
- [imports] : 5
+ [imports] : 4
[memories] : 1
[memory-data] : 24
- [table-data] : 15
+ [table-data] : 19
[tables] : 1
[tags] : 0
- [total] : 5475
- [vars] : 222
- Binary : 410
- Block : 870
- Break : 148
- Call : 271
- CallIndirect : 30
- Const : 915
- Drop : 51
- GlobalGet : 458
- GlobalSet : 323
- If : 293
- Load : 96
- LocalGet : 442
- LocalSet : 284
- Loop : 99
- Nop : 76
- RefFunc : 15
- Return : 78
- Select : 47
- Store : 44
+ [total] : 5695
+ [vars] : 227
+ Binary : 430
+ Block : 976
+ Break : 188
+ Call : 272
+ CallIndirect : 20
+ Const : 876
+ Drop : 99
+ GlobalGet : 504
+ GlobalSet : 373
+ If : 299
+ Load : 111
+ LocalGet : 365
+ LocalSet : 299
+ Loop : 108
+ Nop : 58
+ RefFunc : 19
+ Return : 74
+ Select : 40
+ Store : 34
Switch : 2
Unary : 365
- Unreachable : 158
+ Unreachable : 183
diff --git a/test/passes/fuzz_metrics_passes_noprint.bin.txt b/test/passes/fuzz_metrics_passes_noprint.bin.txt
index 9c8c25c12..c3881104d 100644
--- a/test/passes/fuzz_metrics_passes_noprint.bin.txt
+++ b/test/passes/fuzz_metrics_passes_noprint.bin.txt
@@ -1,35 +1,34 @@
Metrics
total
- [exports] : 54
- [funcs] : 84
+ [exports] : 30
+ [funcs] : 47
[globals] : 17
[imports] : 4
[memories] : 1
[memory-data] : 11
- [table-data] : 22
+ [table-data] : 18
[tables] : 1
[tags] : 0
- [total] : 8343
- [vars] : 264
- Binary : 597
- Block : 1335
- Break : 226
- Call : 346
- CallIndirect : 65
- Const : 1375
- Drop : 107
- GlobalGet : 719
- GlobalSet : 522
- If : 458
- Load : 139
- LocalGet : 650
- LocalSet : 441
- Loop : 165
- Nop : 97
- RefFunc : 22
- Return : 120
- Select : 71
- Store : 56
- Switch : 2
- Unary : 574
- Unreachable : 256
+ [total] : 4738
+ [vars] : 133
+ Binary : 338
+ Block : 781
+ Break : 122
+ Call : 249
+ CallIndirect : 27
+ Const : 780
+ Drop : 105
+ GlobalGet : 378
+ GlobalSet : 288
+ If : 216
+ Load : 79
+ LocalGet : 396
+ LocalSet : 252
+ Loop : 89
+ Nop : 43
+ RefFunc : 18
+ Return : 70
+ Select : 37
+ Store : 36
+ Unary : 294
+ Unreachable : 140
diff --git a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
index 8df9d033c..e2e9b8053 100644
--- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
+++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
@@ -1,54 +1,57 @@
Metrics
total
- [exports] : 9
- [funcs] : 10
+ [exports] : 6
+ [funcs] : 6
[globals] : 4
[imports] : 8
[memories] : 1
[memory-data] : 112
- [table-data] : 2
+ [table-data] : 1
[tables] : 1
[tags] : 1
- [total] : 682
- [vars] : 37
- ArrayLen : 1
- ArrayNew : 7
- ArrayNewFixed : 5
+ [total] : 592
+ [vars] : 38
+ ArrayGet : 2
+ ArrayLen : 2
+ ArrayNew : 6
+ ArrayNewFixed : 4
ArraySet : 1
- AtomicNotify : 1
- Binary : 79
- Block : 72
- BrOn : 4
- Break : 7
- Call : 19
- Const : 149
- Drop : 15
- GlobalGet : 35
- GlobalSet : 32
- If : 20
- Load : 20
- LocalGet : 55
- LocalSet : 26
- Loop : 7
- MemoryFill : 1
- Nop : 9
- Pop : 1
+ AtomicCmpxchg : 1
+ AtomicFence : 1
+ AtomicRMW : 2
+ Binary : 81
+ Block : 62
+ BrOn : 1
+ Break : 11
+ Call : 13
+ CallIndirect : 2
+ Const : 123
+ Drop : 2
+ GlobalGet : 22
+ GlobalSet : 22
+ If : 17
+ Load : 25
+ LocalGet : 63
+ LocalSet : 35
+ Loop : 6
+ Nop : 8
+ Pop : 3
RefAs : 1
- RefCast : 1
RefEq : 1
- RefFunc : 17
- RefI31 : 2
- RefIsNull : 2
- RefNull : 8
- Return : 5
- SIMDExtract : 3
- Store : 1
- StringConst : 3
+ RefFunc : 6
+ RefNull : 3
+ Return : 4
+ SIMDExtract : 2
+ Select : 2
+ StringConst : 5
+ StringEncode : 1
+ StringEq : 2
StringMeasure : 1
- StringWTF16Get : 1
- StructNew : 23
- Try : 1
- TupleExtract : 3
- TupleMake : 4
- Unary : 23
- Unreachable : 16
+ StringWTF16Get : 2
+ StructNew : 9
+ Try : 3
+ TryTable : 3
+ TupleExtract : 1
+ TupleMake : 2
+ Unary : 18
+ Unreachable : 11