diff options
-rw-r--r-- | scripts/fuzz_shell.js | 89 | ||||
-rw-r--r-- | src/tools/execution-results.h | 55 | ||||
-rw-r--r-- | src/tools/fuzzing.h | 6 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 122 | ||||
-rw-r--r-- | test/lit/exec/fuzzing-api.wast | 199 | ||||
-rw-r--r-- | test/lit/passes/gufa-closed-open.wast | 6 | ||||
-rw-r--r-- | test/passes/fuzz_metrics_noprint.bin.txt | 52 | ||||
-rw-r--r-- | test/passes/fuzz_metrics_passes_noprint.bin.txt | 53 | ||||
-rw-r--r-- | test/passes/translate-to-fuzz_all-features_metrics_noprint.txt | 87 |
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 |