diff options
author | Alon Zakai <azakai@google.com> | 2022-10-28 12:15:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-28 19:15:16 +0000 |
commit | 7e7dd338b9ae6026f54f3384bebe095fefb9fab5 (patch) | |
tree | f388c8d088e1c52ab6e629a88a7109959a26e4ed | |
parent | 1762c33df1d1fcd704cf4d7497ba5788ee93a07d (diff) | |
download | binaryen-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.h | 14 | ||||
-rw-r--r-- | test/gtest/possible-contents.cpp | 41 | ||||
-rw-r--r-- | test/gtest/type-builder.cpp | 22 |
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; |