summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-10-28 12:15:16 -0700
committerGitHub <noreply@github.com>2022-10-28 19:15:16 +0000
commit7e7dd338b9ae6026f54f3384bebe095fefb9fab5 (patch)
treef388c8d088e1c52ab6e629a88a7109959a26e4ed
parent1762c33df1d1fcd704cf4d7497ba5788ee93a07d (diff)
downloadbinaryen-7e7dd338b9ae6026f54f3384bebe095fefb9fab5.tar.gz
binaryen-7e7dd338b9ae6026f54f3384bebe095fefb9fab5.tar.bz2
binaryen-7e7dd338b9ae6026f54f3384bebe095fefb9fab5.zip
[Wasm GC] Fix the depth of the new array heap type (#5186)
-rw-r--r--src/ir/subtypes.h14
-rw-r--r--test/gtest/possible-contents.cpp41
-rw-r--r--test/gtest/type-builder.cpp22
3 files changed, 74 insertions, 3 deletions
diff --git a/src/ir/subtypes.h b/src/ir/subtypes.h
index 0d8fccdbc..198a69b7a 100644
--- a/src/ir/subtypes.h
+++ b/src/ir/subtypes.h
@@ -113,12 +113,22 @@ struct SubTypes {
}
// Add the max depths of basic types.
- // TODO: update when we get structtype and arraytype
+ // TODO: update when we get structtype
for (auto type : types) {
- HeapType basic = type.isData() ? HeapType::data : HeapType::func;
+ HeapType basic;
+ if (type.isStruct()) {
+ basic = HeapType::data;
+ } else if (type.isArray()) {
+ basic = HeapType::array;
+ } else {
+ assert(type.isSignature());
+ basic = HeapType::func;
+ }
depths[basic] = std::max(depths[basic], depths[type] + 1);
}
+ depths[HeapType::data] =
+ std::max(depths[HeapType::data], depths[HeapType::array] + 1);
depths[HeapType::eq] = std::max(Index(1), depths[HeapType::data] + 1);
depths[HeapType::any] = depths[HeapType::eq] + 1;
diff --git a/test/gtest/possible-contents.cpp b/test/gtest/possible-contents.cpp
index 802d08c18..63486e7a9 100644
--- a/test/gtest/possible-contents.cpp
+++ b/test/gtest/possible-contents.cpp
@@ -1,4 +1,5 @@
#include "ir/possible-contents.h"
+#include "ir/subtypes.h"
#include "wasm-s-parser.h"
#include "wasm.h"
#include "gtest/gtest.h"
@@ -347,6 +348,21 @@ TEST_F(PossibleContentsTest, TestIntersectWithCombinations) {
auto doTest = [](std::unordered_set<PossibleContents> set) {
std::vector<PossibleContents> vec(set.begin(), set.end());
+ // Find the maximum depths for the normalized cone tests later down.
+ std::unordered_set<HeapType> heapTypes;
+ for (auto& contents : set) {
+ auto type = contents.getType();
+ if (type.isRef()) {
+ auto heapType = type.getHeapType();
+ if (!heapType.isBasic()) {
+ heapTypes.insert(heapType);
+ }
+ }
+ }
+ std::vector<HeapType> heapTypesVec(heapTypes.begin(), heapTypes.end());
+ SubTypes subTypes(heapTypesVec);
+ auto maxDepths = subTypes.getMaxDepths();
+
// Go over all permutations up to a certain size (this quickly becomes
// extremely slow, obviously, so keep this low).
size_t max = 3;
@@ -397,6 +413,17 @@ TEST_F(PossibleContentsTest, TestIntersectWithCombinations) {
#endif
assertHaveIntersection(combination, item);
+ auto type = combination.getType();
+ if (type.isRef()) {
+ // If we normalize the combination's depth, the item must still have
+ // an intersection. That is, normalization must not have a bug that
+ // results in cones that are too shallow.
+ auto normalizedDepth = maxDepths[type.getHeapType()];
+ auto normalizedCone =
+ PossibleContents::coneType(type, normalizedDepth);
+ assertHaveIntersection(normalizedCone, item);
+ }
+
// Test intersectWithFullCone() method, which is supported with a full
// cone type. In that case we can test that the intersection of A with
// A + B is simply A.
@@ -413,6 +440,12 @@ TEST_F(PossibleContentsTest, TestIntersectWithCombinations) {
abort();
}
#endif
+
+ // The intersection is contained in each of the things we intersected
+ // (but we can only compare to the full cone, as the API is restricted
+ // to that).
+ EXPECT_TRUE(
+ PossibleContents::isSubContents(intersection, combination));
}
}
@@ -466,6 +499,14 @@ TEST_F(PossibleContentsTest, TestIntersectWithCombinations) {
coneFuncref,
coneFuncref1};
+ // Add some additional interesting types.
+ auto structType =
+ Type(HeapType(Struct({Field(Type::i32, Immutable)})), NonNullable);
+ initial.insert(PossibleContents::coneType(structType, 0));
+ auto arrayType =
+ Type(HeapType(Array(Field(Type::i32, Immutable))), NonNullable);
+ initial.insert(PossibleContents::coneType(arrayType, 0));
+
// After testing on the initial contents, also test using anything new that
// showed up while combining them.
auto subsequent = doTest(initial);
diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp
index 5760838da..fe1f19871 100644
--- a/test/gtest/type-builder.cpp
+++ b/test/gtest/type-builder.cpp
@@ -839,7 +839,7 @@ TEST_F(IsorecursiveTest, TestExistingSuperType) {
}
// Test .getMaxDepths() helper.
-TEST_F(NominalTest, TestMaxDepths) {
+TEST_F(NominalTest, TestMaxStructDepths) {
/*
A
|
@@ -867,6 +867,26 @@ TEST_F(NominalTest, TestMaxDepths) {
EXPECT_EQ(maxDepths[HeapType::eq], Index(3));
}
+TEST_F(NominalTest, TestMaxArrayDepths) {
+ HeapType A;
+ {
+ TypeBuilder builder(1);
+ builder[0] = Array(Field(Type::i32, Immutable));
+ auto result = builder.build();
+ ASSERT_TRUE(result);
+ auto built = *result;
+ A = built[0];
+ }
+
+ SubTypes subTypes({A});
+ auto maxDepths = subTypes.getMaxDepths();
+
+ EXPECT_EQ(maxDepths[A], Index(0));
+ EXPECT_EQ(maxDepths[HeapType::array], Index(1));
+ EXPECT_EQ(maxDepths[HeapType::data], Index(2));
+ EXPECT_EQ(maxDepths[HeapType::eq], Index(3));
+}
+
// Test .depth() helper.
TEST_F(NominalTest, TestDepth) {
HeapType A, B, C;