summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/fuzzing.h1
-rw-r--r--src/tools/fuzzing/fuzzing.cpp68
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt82
3 files changed, 110 insertions, 41 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index 75e3a2a9a..f4400e39e 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -293,6 +293,7 @@ private:
Expression* buildIf(const struct ThreeArgs& args, Type type);
Expression* makeIf(Type type);
Expression* makeTry(Type type);
+ Expression* makeTryTable(Type type);
Expression* makeBreak(Type type);
Expression* makeCall(Type type);
Expression* makeCallIndirect(Type type);
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index a8b8f7855..abc6a63d5 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -1366,6 +1366,7 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
&Self::makeCall,
&Self::makeCallIndirect)
.add(FeatureSet::ExceptionHandling, &Self::makeTry)
+ .add(FeatureSet::ExceptionHandling, &Self::makeTryTable)
.add(FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeCallRef);
}
if (type.isSingle()) {
@@ -1451,6 +1452,8 @@ Expression* TranslateToFuzzReader::_makenone() {
&Self::makeGlobalSet)
.add(FeatureSet::BulkMemory, &Self::makeBulkMemory)
.add(FeatureSet::Atomics, &Self::makeAtomic)
+ .add(FeatureSet::ExceptionHandling, &Self::makeTry)
+ .add(FeatureSet::ExceptionHandling, &Self::makeTryTable)
.add(FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeCallRef)
.add(FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeStructSet)
.add(FeatureSet::GC | FeatureSet::ReferenceTypes, &Self::makeArraySet)
@@ -1688,6 +1691,71 @@ Expression* TranslateToFuzzReader::makeTry(Type type) {
return builder.makeTry(body, catchTags, catchBodies);
}
+Expression* TranslateToFuzzReader::makeTryTable(Type type) {
+ auto* body = make(type);
+
+ if (funcContext->breakableStack.empty()) {
+ // Nothing to break to, emit a trivial TryTable.
+ // TODO: Perhaps generate a block wrapping us?
+ return builder.makeTryTable(body, {}, {}, {});
+ }
+
+ if (wasm.tags.empty()) {
+ addTag();
+ }
+
+ // Add catches of specific tags, and possibly a catch_all at the end. We use
+ // the last iteration of the loop for that.
+ std::vector<Name> catchTags;
+ std::vector<Name> catchDests;
+ std::vector<bool> catchRefs;
+ auto numCatches = upTo(MAX_TRY_CATCHES);
+ for (Index i = 0; i <= numCatches; i++) {
+ Name tagName;
+ Type tagType;
+ if (i < numCatches) {
+ // Look for a specific tag.
+ auto& tag = pick(wasm.tags);
+ tagName = tag->name;
+ tagType = tag->sig.params;
+ } else {
+ // Add a catch_all at the end, some of the time (but all of the time if we
+ // have nothing else).
+ if (!catchTags.empty() && oneIn(2)) {
+ break;
+ }
+ tagType = Type::none;
+ }
+
+ // We need to find a proper target to break to, which means a target that
+ // has the type of the tag, or the tag + an exnref at the end.
+ std::vector<Type> vec(tagType.begin(), tagType.end());
+ // Use a non-nullable exnref here, and then the subtyping check below will
+ // also accept a target that is nullable.
+ vec.push_back(Type(HeapType::exn, NonNullable));
+ auto tagTypeWithExn = Type(vec);
+ int tries = TRIES;
+ while (tries-- > 0) {
+ auto* target = pick(funcContext->breakableStack);
+ auto dest = getTargetName(target);
+ auto valueType = getTargetType(target);
+ auto subOfTagType = Type::isSubType(tagType, valueType);
+ auto subOfTagTypeWithExn = Type::isSubType(tagTypeWithExn, valueType);
+ if (subOfTagType || subOfTagTypeWithExn) {
+ catchTags.push_back(tagName);
+ catchDests.push_back(dest);
+ catchRefs.push_back(subOfTagTypeWithExn);
+ break;
+ }
+ }
+ // TODO: Perhaps generate a block wrapping us, if we fail to find a target?
+ // TODO: It takes a bit of luck to find a target with an exnref - perhaps
+ // generate those?
+ }
+
+ return builder.makeTryTable(body, catchTags, catchDests, catchRefs);
+}
+
Expression* TranslateToFuzzReader::makeBreak(Type type) {
if (funcContext->breakableStack.empty()) {
return makeTrivial(type);
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 07afaa7eb..e58a50830 100644
--- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
+++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
@@ -1,53 +1,53 @@
Metrics
total
- [exports] : 5
- [funcs] : 9
+ [exports] : 3
+ [funcs] : 5
[globals] : 26
[imports] : 5
[memories] : 1
[memory-data] : 20
- [table-data] : 3
+ [table-data] : 0
[tables] : 1
[tags] : 2
- [total] : 669
- [vars] : 27
- ArrayNew : 16
- ArrayNewFixed : 3
+ [total] : 499
+ [vars] : 20
+ ArrayNew : 14
+ ArrayNewFixed : 2
AtomicCmpxchg : 1
- AtomicFence : 1
- Binary : 75
- Block : 70
- Break : 7
- Call : 26
- CallRef : 1
- Const : 143
- Drop : 3
- GlobalGet : 37
- GlobalSet : 27
+ AtomicNotify : 1
+ AtomicRMW : 1
+ Binary : 69
+ Block : 42
+ Break : 8
+ Call : 6
+ Const : 126
+ Drop : 2
+ GlobalGet : 27
+ GlobalSet : 16
I31Get : 1
- If : 20
- Load : 21
- LocalGet : 55
- LocalSet : 40
- Loop : 6
- Nop : 5
- Pop : 5
+ If : 10
+ Load : 18
+ LocalGet : 43
+ LocalSet : 22
+ Loop : 5
+ Nop : 3
+ Pop : 3
RefAs : 2
- RefEq : 2
- RefFunc : 5
- RefI31 : 2
- RefNull : 11
- RefTest : 2
- Return : 6
- Select : 2
- StringConst : 6
- StringEq : 1
- StringMeasure : 1
- StringWTF16Get : 1
- StructNew : 17
+ RefFunc : 2
+ RefI31 : 1
+ RefNull : 8
+ RefTest : 1
+ Return : 1
+ Select : 1
+ Store : 3
+ StringConst : 9
+ StringEncode : 1
+ StringEq : 3
+ StructNew : 12
StructSet : 1
- Try : 4
- TupleExtract : 3
- TupleMake : 5
- Unary : 20
- Unreachable : 15
+ Try : 3
+ TryTable : 2
+ TupleExtract : 1
+ TupleMake : 4
+ Unary : 13
+ Unreachable : 11