summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/fuzzing.h11
-rw-r--r--src/tools/fuzzing/fuzzing.cpp35
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt68
3 files changed, 64 insertions, 50 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index 9789a3a5b..4eb0c3960 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -138,8 +138,19 @@ private:
FunctionCreationContext* funcContext = nullptr;
+public:
int nesting = 0;
+ struct AutoNester {
+ TranslateToFuzzReader& parent;
+
+ AutoNester(TranslateToFuzzReader& parent) : parent(parent) {
+ parent.nesting++;
+ }
+ ~AutoNester() { parent.nesting--; }
+ };
+
+private:
// Generating random data is common enough that it's worth having helpers that
// forward to `random`.
int8_t get() { return random.get(); }
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index db4d0196e..7d663641e 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -2172,28 +2172,27 @@ Expression* TranslateToFuzzReader::makeConstCompoundRef(Type type) {
auto heapType = type.getHeapType();
assert(!heapType.isBasic());
assert(wasm.features.hasReferenceTypes());
- if (heapType.isSignature()) {
- return makeRefFuncConst(type);
- }
- // We weren't able to directly materialize a non-null constant. Try again to
- // create a null.
- if (type.isNullable()) {
+ // Prefer not to emit a null, in general, as we can trap from them. If it is
+ // nullable, give a small chance to do so; if we hit the nesting limit then we
+ // really have no choice and must emit a null (or else we could infinitely
+ // recurse). For the nesting limit, use a bound that is higher than the normal
+ // one, so that the normal mechanisms should prevent us from getting here;
+ // this limit is really a last resort we want to never reach.
+ //
+ // Note that we might have cycles of types where some are non-nullable. We
+ // will only stop here when we exceed the nesting and reach a nullable one.
+ // (This assumes there is a nullable one, that is, that the types are
+ // inhabitable.)
+ const auto LIMIT = 2 * NESTING_LIMIT;
+ AutoNester nester(*this);
+ if (type.isNullable() && (oneIn(10) || nesting >= LIMIT)) {
return builder.makeRefNull(heapType);
}
- // We have to produce a non-null value. Possibly create a null and cast it
- // to non-null even though that will trap at runtime. We must have a
- // function context for this because the cast is not allowed in globals.
- if (funcContext) {
- return builder.makeRefAs(RefAsNonNull, builder.makeRefNull(heapType));
- }
-
- // Otherwise, we are not in a function context. This can happen if we need
- // to make a constant for the initializer of a global, for example. We've
- // already handled simple cases of this above, for basic heap types, so what
- // we have left here are user-defined heap types like structs.
- if (type.isStruct()) {
+ if (heapType.isSignature()) {
+ return makeRefFuncConst(type);
+ } else if (type.isStruct()) {
auto& fields = heapType.getStruct().fields;
std::vector<Expression*> values;
// TODO: use non-default values randomly even when not necessary, sometimes
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 cdbd4dd27..24943eddd 100644
--- a/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
+++ b/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
@@ -1,39 +1,43 @@
total
- [exports] : 4
- [funcs] : 8
+ [exports] : 6
+ [funcs] : 13
[globals] : 5
[imports] : 5
[memories] : 1
[memory-data] : 20
- [table-data] : 2
+ [table-data] : 3
[tables] : 1
[tags] : 1
- [total] : 526
- [vars] : 8
- Binary : 69
- Block : 74
- Break : 11
- Call : 10
- Const : 100
- Drop : 1
- GlobalGet : 32
- GlobalSet : 33
- I31Get : 1
- I31New : 3
- If : 23
- Load : 19
- LocalGet : 40
- LocalSet : 23
- Loop : 10
- Nop : 17
- RefAs : 2
- RefFunc : 5
- RefIsNull : 1
- RefNull : 3
- Return : 2
- Select : 1
- Store : 1
- StructNew : 2
- TupleMake : 3
- Unary : 23
- Unreachable : 17
+ [total] : 558
+ [vars] : 36
+ ArrayNew : 7
+ ArrayNewFixed : 3
+ AtomicCmpxchg : 1
+ AtomicNotify : 1
+ Binary : 70
+ Block : 73
+ Break : 2
+ Call : 21
+ CallRef : 1
+ Const : 120
+ Drop : 9
+ GlobalGet : 34
+ GlobalSet : 34
+ I31New : 1
+ If : 22
+ Load : 18
+ LocalGet : 38
+ LocalSet : 19
+ Loop : 5
+ Nop : 5
+ RefAs : 1
+ RefFunc : 8
+ RefNull : 4
+ Return : 5
+ SIMDExtract : 1
+ Select : 2
+ StructNew : 6
+ TupleExtract : 3
+ TupleMake : 6
+ Unary : 20
+ Unreachable : 18