summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/fuzzing/fuzzing.cpp57
-rw-r--r--src/tools/fuzzing/heap-types.cpp37
-rw-r--r--src/tools/wasm-ctor-eval.cpp5
-rw-r--r--src/tools/wasm-reduce.cpp2
4 files changed, 77 insertions, 24 deletions
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index 2b368a4e8..09df9ac31 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -1976,7 +1976,7 @@ Expression* TranslateToFuzzReader::makeRefFuncConst(Type type) {
// to add a ref.as_non_null to validate, and the code will trap when we get
// here).
if ((type.isNullable() && oneIn(2)) || (type.isNonNullable() && oneIn(16))) {
- Expression* ret = builder.makeRefNull(Type(heapType, Nullable));
+ Expression* ret = builder.makeRefNull(HeapType::nofunc);
if (!type.isNullable()) {
ret = builder.makeRefAs(RefAsNonNull, ret);
}
@@ -2000,7 +2000,7 @@ Expression* TranslateToFuzzReader::makeConst(Type type) {
assert(wasm.features.hasReferenceTypes());
// With a low chance, just emit a null if that is valid.
if (type.isNullable() && oneIn(8)) {
- return builder.makeRefNull(type);
+ return builder.makeRefNull(type.getHeapType());
}
if (type.getHeapType().isBasic()) {
return makeConstBasicRef(type);
@@ -2050,7 +2050,7 @@ Expression* TranslateToFuzzReader::makeConstBasicRef(Type type) {
// a subtype of anyref, but we cannot create constants of it, except
// for null.
assert(type.isNullable());
- return builder.makeRefNull(type);
+ return builder.makeRefNull(HeapType::none);
}
auto nullability = getSubType(type.getNullability());
// i31.new is not allowed in initializer expressions.
@@ -2065,7 +2065,7 @@ Expression* TranslateToFuzzReader::makeConstBasicRef(Type type) {
case HeapType::i31: {
assert(wasm.features.hasGC());
if (type.isNullable() && oneIn(4)) {
- return builder.makeRefNull(type);
+ return builder.makeRefNull(HeapType::none);
}
return builder.makeI31New(makeConst(Type::i32));
}
@@ -2086,10 +2086,22 @@ Expression* TranslateToFuzzReader::makeConstBasicRef(Type type) {
return builder.makeArrayInit(trivialArray, {});
}
}
- default: {
- WASM_UNREACHABLE("invalid basic ref type");
+ case HeapType::string:
+ case HeapType::stringview_wtf8:
+ case HeapType::stringview_wtf16:
+ case HeapType::stringview_iter:
+ WASM_UNREACHABLE("TODO: strings");
+ case HeapType::none:
+ case HeapType::noext:
+ case HeapType::nofunc: {
+ auto null = builder.makeRefNull(heapType);
+ if (!type.isNullable()) {
+ return builder.makeRefAs(RefAsNonNull, null);
+ }
+ return null;
}
}
+ WASM_UNREACHABLE("invalid basic ref type");
}
Expression* TranslateToFuzzReader::makeConstCompoundRef(Type type) {
@@ -2104,15 +2116,14 @@ Expression* TranslateToFuzzReader::makeConstCompoundRef(Type type) {
// We weren't able to directly materialize a non-null constant. Try again to
// create a null.
if (type.isNullable()) {
- return builder.makeRefNull(type);
+ 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(Type(heapType, Nullable)));
+ return builder.makeRefAs(RefAsNonNull, builder.makeRefNull(heapType));
}
// Otherwise, we are not in a function context. This can happen if we need
@@ -3138,33 +3149,49 @@ Nullability TranslateToFuzzReader::getSubType(Nullability nullability) {
}
HeapType TranslateToFuzzReader::getSubType(HeapType type) {
+ if (oneIn(2)) {
+ return type;
+ }
if (type.isBasic()) {
switch (type.getBasic()) {
case HeapType::func:
// TODO: Typed function references.
- return HeapType::func;
+ return pick(FeatureOptions<HeapType>()
+ .add(FeatureSet::ReferenceTypes, HeapType::func)
+ .add(FeatureSet::GC, HeapType::nofunc));
case HeapType::ext:
- return HeapType::ext;
+ return pick(FeatureOptions<HeapType>()
+ .add(FeatureSet::ReferenceTypes, HeapType::ext)
+ .add(FeatureSet::GC, HeapType::noext));
case HeapType::any:
// TODO: nontrivial types as well.
assert(wasm.features.hasReferenceTypes());
assert(wasm.features.hasGC());
- return pick(HeapType::any, HeapType::eq, HeapType::i31, HeapType::data);
+ return pick(HeapType::any,
+ HeapType::eq,
+ HeapType::i31,
+ HeapType::data,
+ HeapType::none);
case HeapType::eq:
// TODO: nontrivial types as well.
assert(wasm.features.hasReferenceTypes());
assert(wasm.features.hasGC());
- return pick(HeapType::eq, HeapType::i31, HeapType::data);
+ return pick(
+ HeapType::eq, HeapType::i31, HeapType::data, HeapType::none);
case HeapType::i31:
- return HeapType::i31;
+ return pick(HeapType::i31, HeapType::none);
case HeapType::data:
// TODO: nontrivial types as well.
- return HeapType::data;
+ return pick(HeapType::data, HeapType::none);
case HeapType::string:
case HeapType::stringview_wtf8:
case HeapType::stringview_wtf16:
case HeapType::stringview_iter:
WASM_UNREACHABLE("TODO: fuzz strings");
+ case HeapType::none:
+ case HeapType::noext:
+ case HeapType::nofunc:
+ break;
}
}
// TODO: nontrivial types as well.
diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp
index ad87c6fab..351035f93 100644
--- a/src/tools/fuzzing/heap-types.cpp
+++ b/src/tools/fuzzing/heap-types.cpp
@@ -69,7 +69,7 @@ struct HeapTypeGeneratorImpl {
typeIndices.insert({builder[i], i});
// Everything is a subtype of itself.
subtypeIndices[i].push_back(i);
- if (i < numRoots) {
+ if (i < numRoots || rand.oneIn(2)) {
// This is a root type with no supertype. Choose a kind for this type.
typeKinds.emplace_back(generateHeapTypeKind());
} else {
@@ -148,6 +148,11 @@ struct HeapTypeGeneratorImpl {
}
HeapType::BasicHeapType generateBasicHeapType() {
+ // Choose bottom types more rarely.
+ if (rand.oneIn(16)) {
+ return rand.pick(HeapType::noext, HeapType::nofunc, HeapType::none);
+ }
+ // TODO: strings
return rand.pick(HeapType::func,
HeapType::ext,
HeapType::any,
@@ -254,6 +259,8 @@ struct HeapTypeGeneratorImpl {
HeapType pickSubFunc() {
if (auto type = pickKind<SignatureKind>()) {
return *type;
+ } else if (rand.oneIn(2)) {
+ return HeapType::nofunc;
} else {
return HeapType::func;
}
@@ -262,6 +269,8 @@ struct HeapTypeGeneratorImpl {
HeapType pickSubData() {
if (auto type = pickKind<DataKind>()) {
return *type;
+ } else if (rand.oneIn(2)) {
+ return HeapType::none;
} else {
return HeapType::data;
}
@@ -292,7 +301,7 @@ struct HeapTypeGeneratorImpl {
// can only choose those defined before the end of the current recursion
// group.
std::vector<Index> candidateIndices;
- for (auto i : subtypeIndices[typeIndices[type]]) {
+ for (auto i : subtypeIndices[it->second]) {
if (i < recGroupEnds[index]) {
candidateIndices.push_back(i);
}
@@ -301,6 +310,9 @@ struct HeapTypeGeneratorImpl {
} else {
// This is not a constructed type, so it must be a basic type.
assert(type.isBasic());
+ if (rand.oneIn(8)) {
+ return type.getBottom();
+ }
switch (type.getBasic()) {
case HeapType::ext:
return HeapType::ext;
@@ -318,7 +330,10 @@ struct HeapTypeGeneratorImpl {
case HeapType::stringview_wtf8:
case HeapType::stringview_wtf16:
case HeapType::stringview_iter:
- WASM_UNREACHABLE("TODO: fuzz strings");
+ case HeapType::none:
+ case HeapType::noext:
+ case HeapType::nofunc:
+ return type;
}
WASM_UNREACHABLE("unexpected kind");
}
@@ -403,6 +418,17 @@ struct HeapTypeGeneratorImpl {
}
HeapTypeKind getSubKind(HeapTypeKind super) {
+ if (rand.oneIn(16)) {
+ // Occasionally go directly to the bottom type.
+ if (auto* basic = std::get_if<BasicKind>(&super)) {
+ return HeapType(*basic).getBottom();
+ } else if (std::get_if<SignatureKind>(&super)) {
+ return HeapType::nofunc;
+ } else if (std::get_if<DataKind>(&super)) {
+ return HeapType::none;
+ }
+ WASM_UNREACHABLE("unexpected kind");
+ }
if (auto* basic = std::get_if<BasicKind>(&super)) {
if (rand.oneIn(8)) {
return super;
@@ -441,7 +467,10 @@ struct HeapTypeGeneratorImpl {
case HeapType::stringview_wtf8:
case HeapType::stringview_wtf16:
case HeapType::stringview_iter:
- WASM_UNREACHABLE("TODO: fuzz strings");
+ case HeapType::none:
+ case HeapType::noext:
+ case HeapType::nofunc:
+ return super;
}
WASM_UNREACHABLE("unexpected kind");
} else {
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp
index 5e9874ccc..45cc63c37 100644
--- a/src/tools/wasm-ctor-eval.cpp
+++ b/src/tools/wasm-ctor-eval.cpp
@@ -553,10 +553,7 @@ public:
// This is GC data, which we must handle in a more careful way.
auto* data = value.getGCData().get();
- if (!data) {
- // This is a null, so simply emit one.
- return builder.makeRefNull(value.type);
- }
+ assert(data);
// There was actual GC data allocated here.
auto type = value.type;
diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp
index 6febcf6b9..557e8a770 100644
--- a/src/tools/wasm-reduce.cpp
+++ b/src/tools/wasm-reduce.cpp
@@ -1142,7 +1142,7 @@ struct Reducer
}
// try to replace with a trivial value
if (curr->type.isNullable()) {
- RefNull* n = builder->makeRefNull(curr->type);
+ RefNull* n = builder->makeRefNull(curr->type.getHeapType());
return tryToReplaceCurrent(n);
}
if (curr->type.isTuple() && curr->type.isDefaultable()) {