summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2023-10-17 10:12:02 -0700
committerGitHub <noreply@github.com>2023-10-17 17:12:02 +0000
commit2bf3caae764689c606ae38353b1bad5fe28bf5bb (patch)
tree7112801575e46132fdccad7bf120f5cafb9471da
parentb816ac563de6b1c53087796335fce593a96f569a (diff)
downloadbinaryen-2bf3caae764689c606ae38353b1bad5fe28bf5bb.tar.gz
binaryen-2bf3caae764689c606ae38353b1bad5fe28bf5bb.tar.bz2
binaryen-2bf3caae764689c606ae38353b1bad5fe28bf5bb.zip
Add getGeneralSuperType() that includes basic supers, and use in fuzzer (#6005)
With this, the fuzzer can replace e.g. an eq expression with a specific struct type, because now it is away that struct types have eq as their ancestor.
-rw-r--r--src/ir/subtypes.h1
-rw-r--r--src/tools/fuzzing.h7
-rw-r--r--src/tools/fuzzing/fuzzing.cpp3
-rw-r--r--src/wasm-type.h5
-rw-r--r--src/wasm/wasm-type.cpp41
-rw-r--r--test/gtest/possible-contents.cpp7
-rw-r--r--test/gtest/type-builder.cpp73
-rw-r--r--test/passes/translate-to-fuzz_all-features_metrics_noprint.txt81
8 files changed, 166 insertions, 52 deletions
diff --git a/src/ir/subtypes.h b/src/ir/subtypes.h
index 7cc633a75..488bb8310 100644
--- a/src/ir/subtypes.h
+++ b/src/ir/subtypes.h
@@ -122,7 +122,6 @@ struct SubTypes {
}
// Add the max depths of basic types.
- // TODO: update when we get structtype
for (auto type : types) {
HeapType basic;
if (type.isStruct()) {
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index e29a6ddaf..a40a76106 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -25,8 +25,6 @@ high chance for set at start of loop
high chance of a tee in that case => loop var
*/
-// TODO Generate exception handling instructions
-
#include "ir/branch-utils.h"
#include "ir/memory-utils.h"
#include "ir/struct-utils.h"
@@ -399,8 +397,3 @@ private:
};
} // namespace wasm
-
-// XXX Switch class has a condition?! is it real? should the node type be the
-// value type if it exists?!
-
-// TODO copy an existing function and replace just one node in it
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index 2e4d460f7..bdaf71e83 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -765,8 +765,7 @@ void TranslateToFuzzReader::recombine(Function* func) {
while (1) {
ret.push_back(Type(heapType, nullability));
- // TODO: handle basic supertypes too
- auto super = heapType.getDeclaredSuperType();
+ auto super = heapType.getSuperType();
if (!super) {
break;
}
diff --git a/src/wasm-type.h b/src/wasm-type.h
index bc6b25b34..23ceb9143 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -372,6 +372,11 @@ public:
// module) nominal supertype, return it, else an empty optional.
std::optional<HeapType> getDeclaredSuperType() const;
+ // As |getDeclaredSuperType|, but also handles basic types, that is, if the
+ // super is a basic type, then we return it here. Declared types are returned
+ // as well, just like |getDeclaredSuperType|.
+ std::optional<HeapType> getSuperType() const;
+
// Return the depth of this heap type in the nominal type hierarchy, i.e. the
// number of supertypes in its supertype chain.
size_t getDepth() const;
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 1b8d7d0f1..68d7f732b 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -1219,6 +1219,47 @@ std::optional<HeapType> HeapType::getDeclaredSuperType() const {
return {};
}
+std::optional<HeapType> HeapType::getSuperType() const {
+ auto ret = getDeclaredSuperType();
+ if (ret) {
+ return ret;
+ }
+
+ // There may be a basic supertype.
+ if (isBasic()) {
+ switch (getBasic()) {
+ case ext:
+ case noext:
+ case func:
+ case nofunc:
+ case any:
+ case none:
+ case string:
+ case stringview_wtf8:
+ case stringview_wtf16:
+ case stringview_iter:
+ return {};
+ case eq:
+ return any;
+ case i31:
+ case struct_:
+ case array:
+ return eq;
+ }
+ }
+
+ auto* info = getHeapTypeInfo(*this);
+ switch (info->kind) {
+ case HeapTypeInfo::SignatureKind:
+ return func;
+ case HeapTypeInfo::StructKind:
+ return struct_;
+ case HeapTypeInfo::ArrayKind:
+ return array;
+ }
+ WASM_UNREACHABLE("unexpected kind");
+}
+
size_t HeapType::getDepth() const {
size_t depth = 0;
std::optional<HeapType> super;
diff --git a/test/gtest/possible-contents.cpp b/test/gtest/possible-contents.cpp
index 8e07ef8c3..ce5a1ae18 100644
--- a/test/gtest/possible-contents.cpp
+++ b/test/gtest/possible-contents.cpp
@@ -552,9 +552,10 @@ TEST_F(PossibleContentsTest, TestStructCones) {
auto C = types[2];
auto D = types[3];
auto E = types[4];
- ASSERT_TRUE(B.getDeclaredSuperType() == A);
- ASSERT_TRUE(C.getDeclaredSuperType() == A);
- ASSERT_TRUE(D.getDeclaredSuperType() == C);
+ ASSERT_FALSE(A.getDeclaredSuperType());
+ ASSERT_EQ(B.getDeclaredSuperType(), A);
+ ASSERT_EQ(C.getDeclaredSuperType(), A);
+ ASSERT_EQ(D.getDeclaredSuperType(), C);
auto nullA = Type(A, Nullable);
auto nullB = Type(B, Nullable);
diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp
index 0184eb074..43e470a02 100644
--- a/test/gtest/type-builder.cpp
+++ b/test/gtest/type-builder.cpp
@@ -1080,3 +1080,76 @@ TEST_F(TypeTest, TestIterSubTypes) {
EXPECT_EQ(getSubTypes(C, 1), TypeDepths({{C, 0}, {D, 1}}));
EXPECT_EQ(getSubTypes(C, 2), TypeDepths({{C, 0}, {D, 1}}));
}
+
+// Test supertypes
+TEST_F(TypeTest, TestSupertypes) {
+ // Basic types: getDeclaredSuperType always returns nothing.
+ ASSERT_FALSE(HeapType(HeapType::ext).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::func).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::any).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::eq).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::i31).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::struct_).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::array).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::string).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::stringview_wtf8).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::stringview_wtf16).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::stringview_iter).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::none).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::noext).getDeclaredSuperType());
+ ASSERT_FALSE(HeapType(HeapType::nofunc).getDeclaredSuperType());
+
+ // Basic types: getSuperType does return a super, when there is one.
+ ASSERT_FALSE(HeapType(HeapType::ext).getSuperType());
+ ASSERT_FALSE(HeapType(HeapType::func).getSuperType());
+ ASSERT_FALSE(HeapType(HeapType::any).getSuperType());
+ ASSERT_EQ(HeapType(HeapType::eq).getSuperType(), HeapType::any);
+ ASSERT_EQ(HeapType(HeapType::i31).getSuperType(), HeapType::eq);
+ ASSERT_EQ(HeapType(HeapType::struct_).getSuperType(), HeapType::eq);
+ ASSERT_EQ(HeapType(HeapType::array).getSuperType(), HeapType::eq);
+ ASSERT_FALSE(HeapType(HeapType::string).getSuperType());
+ ASSERT_FALSE(HeapType(HeapType::stringview_wtf8).getSuperType());
+ ASSERT_FALSE(HeapType(HeapType::stringview_wtf16).getSuperType());
+ ASSERT_FALSE(HeapType(HeapType::stringview_iter).getSuperType());
+ ASSERT_FALSE(HeapType(HeapType::none).getSuperType());
+ ASSERT_FALSE(HeapType(HeapType::noext).getSuperType());
+ ASSERT_FALSE(HeapType(HeapType::nofunc).getSuperType());
+
+ // Non-basic types.
+ HeapType struct1, struct2, array1, array2, sig1, sig2;
+ {
+ TypeBuilder builder(6);
+ builder[0].setOpen() = Struct();
+ builder[1].setOpen().subTypeOf(builder[0]) = Struct();
+ auto array = Array(Field(Type::i32, Immutable));
+ builder[2].setOpen() = array;
+ builder[3].setOpen().subTypeOf(builder[2]) = array;
+ auto sig = Signature(Type::none, Type::none);
+ builder[4].setOpen() = sig;
+ builder[5].setOpen().subTypeOf(builder[4]) = sig;
+ auto result = builder.build();
+ ASSERT_TRUE(result);
+ auto built = *result;
+ struct1 = built[0];
+ struct2 = built[1];
+ array1 = built[2];
+ array2 = built[3];
+ sig1 = built[4];
+ sig2 = built[5];
+ }
+
+ ASSERT_EQ(struct1.getSuperType(), HeapType::struct_);
+ ASSERT_EQ(struct2.getSuperType(), struct1);
+ ASSERT_EQ(array1.getSuperType(), HeapType::array);
+ ASSERT_EQ(array2.getSuperType(), array1);
+ ASSERT_EQ(sig1.getSuperType(), HeapType::func);
+ ASSERT_EQ(sig2.getSuperType(), sig1);
+
+ // With getDeclaredSuperType we don't get basic supers, only declared ones.
+ ASSERT_FALSE(struct1.getDeclaredSuperType());
+ ASSERT_EQ(struct2.getDeclaredSuperType(), struct1);
+ ASSERT_FALSE(array1.getDeclaredSuperType());
+ ASSERT_EQ(array2.getDeclaredSuperType(), array1);
+ ASSERT_FALSE(sig1.getDeclaredSuperType());
+ ASSERT_EQ(sig2.getDeclaredSuperType(), sig1);
+}
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 8d88600ed..3cd4228e9 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,56 @@
total
- [exports] : 4
- [funcs] : 6
+ [exports] : 5
+ [funcs] : 8
[globals] : 1
[imports] : 5
[memories] : 1
[memory-data] : 20
- [table-data] : 0
+ [table-data] : 6
[tables] : 1
[tags] : 2
- [total] : 630
- [vars] : 23
- ArrayGet : 1
- ArrayLen : 2
- ArrayNew : 8
+ [total] : 807
+ [vars] : 27
+ ArrayLen : 1
+ ArrayNew : 7
ArrayNewFixed : 3
ArraySet : 1
- AtomicNotify : 1
- Binary : 81
- Block : 66
- Break : 12
- Call : 22
+ AtomicCmpxchg : 1
+ AtomicFence : 1
+ Binary : 89
+ Block : 102
+ Break : 18
+ Call : 21
CallRef : 1
- Const : 132
- Drop : 6
- GlobalGet : 20
- GlobalSet : 20
- I31Get : 1
- If : 23
- Load : 23
- LocalGet : 70
- LocalSet : 41
- Loop : 5
- Nop : 12
- RefAs : 4
- RefCast : 1
+ Const : 154
+ Drop : 5
+ GlobalGet : 38
+ GlobalSet : 38
+ I31Get : 2
+ If : 27
+ Load : 19
+ LocalGet : 62
+ LocalSet : 48
+ Loop : 12
+ MemoryFill : 1
+ Nop : 10
+ Pop : 5
+ RefAs : 19
+ RefCast : 3
RefEq : 2
- RefFunc : 1
- RefI31 : 3
- RefNull : 6
- Return : 7
+ RefFunc : 7
+ RefI31 : 4
+ RefIsNull : 2
+ RefNull : 14
+ RefTest : 2
+ Return : 2
SIMDExtract : 1
- SIMDTernary : 1
- Select : 4
- Store : 3
- StructGet : 1
+ Select : 5
+ Store : 4
+ StructGet : 6
StructNew : 9
- StructSet : 2
- Try : 2
- TupleExtract : 1
+ StructSet : 1
+ Try : 5
+ TupleExtract : 2
TupleMake : 2
- Unary : 19
- Unreachable : 10
+ Unary : 32
+ Unreachable : 19