summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/subtypes.h21
-rw-r--r--test/gtest/type-builder.cpp51
-rw-r--r--test/lit/passes/gufa-tnh.wast29
3 files changed, 80 insertions, 21 deletions
diff --git a/src/ir/subtypes.h b/src/ir/subtypes.h
index 8645afb98..767c79fd7 100644
--- a/src/ir/subtypes.h
+++ b/src/ir/subtypes.h
@@ -124,20 +124,27 @@ struct SubTypes {
// Add the max depths of basic types.
for (auto type : types) {
HeapType basic;
+ auto share = type.getShared();
if (type.isStruct()) {
- basic = HeapType::struct_;
+ basic = HeapTypes::struct_.getBasic(share);
} else if (type.isArray()) {
- basic = HeapType::array;
+ basic = HeapTypes::array.getBasic(share);
} else {
assert(type.isSignature());
- basic = HeapType::func;
+ basic = HeapTypes::func.getBasic(share);
}
- depths[basic] = std::max(depths[basic], depths[type] + 1);
+ auto& basicDepth = depths[basic];
+ basicDepth = std::max(basicDepth, depths[type] + 1);
}
- depths[HeapType::eq] =
- std::max(depths[HeapType::struct_], depths[HeapType::array]) + 1;
- depths[HeapType::any] = depths[HeapType::eq] + 1;
+ for (auto share : {Unshared, Shared}) {
+ depths[HeapTypes::eq.getBasic(share)] =
+ std::max(depths[HeapTypes::struct_.getBasic(share)],
+ depths[HeapTypes::array.getBasic(share)]) +
+ 1;
+ depths[HeapTypes::any.getBasic(share)] =
+ depths[HeapTypes::eq.getBasic(share)] + 1;
+ }
return depths;
}
diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp
index 2ad43d189..97943551f 100644
--- a/test/gtest/type-builder.cpp
+++ b/test/gtest/type-builder.cpp
@@ -1110,12 +1110,18 @@ TEST_F(TypeTest, TestSubtypeErrors) {
TEST_F(TypeTest, TestSubTypes) {
Type anyref = Type(HeapType::any, Nullable);
Type eqref = Type(HeapType::eq, Nullable);
+ Type sharedAnyref = Type(HeapTypes::any.getBasic(Shared), Nullable);
+ Type sharedEqref = Type(HeapTypes::eq.getBasic(Shared), Nullable);
// Build type types, the second of which is a subtype.
- TypeBuilder builder(2);
+ TypeBuilder builder(4);
builder[0].setOpen() = Struct({Field(anyref, Immutable)});
builder[1].setOpen() = Struct({Field(eqref, Immutable)});
+ // Make shared versions, too.
+ builder[2].setOpen().setShared() = Array(Field(sharedAnyref, Immutable));
+ builder[3].setOpen().setShared() = Array(Field(sharedEqref, Immutable));
builder[1].subTypeOf(builder[0]);
+ builder[3].subTypeOf(builder[2]);
auto result = builder.build();
ASSERT_TRUE(result);
@@ -1125,20 +1131,37 @@ TEST_F(TypeTest, TestSubTypes) {
// SubTypes utility code.
Module wasm;
Builder wasmBuilder(wasm);
- wasm.addFunction(wasmBuilder.makeFunction(
- "func",
- Signature(Type::none, Type::none),
- {Type(built[0], Nullable), Type(built[1], Nullable)},
- wasmBuilder.makeNop()));
+ wasm.addFunction(wasmBuilder.makeFunction("func",
+ Signature(Type::none, Type::none),
+ {Type(built[0], Nullable),
+ Type(built[1], Nullable),
+ Type(built[2], Nullable),
+ Type(built[3], Nullable)},
+ wasmBuilder.makeNop()));
SubTypes subTypes(wasm);
- auto subTypes0 = subTypes.getImmediateSubTypes(built[0]);
- EXPECT_TRUE(subTypes0.size() == 1 && subTypes0[0] == built[1]);
- auto subTypes0Inclusive = subTypes.getSubTypes(built[0]);
- EXPECT_TRUE(subTypes0Inclusive.size() == 2 &&
- subTypes0Inclusive[0] == built[1] &&
- subTypes0Inclusive[1] == built[0]);
- auto subTypes1 = subTypes.getImmediateSubTypes(built[1]);
- EXPECT_EQ(subTypes1.size(), 0u);
+ auto immSubTypes0 = subTypes.getImmediateSubTypes(built[0]);
+ ASSERT_EQ(immSubTypes0.size(), 1u);
+ EXPECT_EQ(immSubTypes0[0], built[1]);
+ auto subTypes0 = subTypes.getSubTypes(built[0]);
+ ASSERT_EQ(subTypes0.size(), 2u);
+ EXPECT_EQ(subTypes0[0], built[1]);
+ EXPECT_EQ(subTypes0[1], built[0]);
+ auto immSubTypes1 = subTypes.getImmediateSubTypes(built[1]);
+ EXPECT_EQ(immSubTypes1.size(), 0u);
+
+ auto depths = subTypes.getMaxDepths();
+ EXPECT_EQ(depths[HeapTypes::any.getBasic(Unshared)], 4u);
+ EXPECT_EQ(depths[HeapTypes::any.getBasic(Shared)], 4u);
+ EXPECT_EQ(depths[HeapTypes::eq.getBasic(Unshared)], 3u);
+ EXPECT_EQ(depths[HeapTypes::eq.getBasic(Shared)], 3u);
+ EXPECT_EQ(depths[HeapTypes::struct_.getBasic(Unshared)], 2u);
+ EXPECT_EQ(depths[HeapTypes::struct_.getBasic(Shared)], 0u);
+ EXPECT_EQ(depths[HeapTypes::array.getBasic(Unshared)], 0u);
+ EXPECT_EQ(depths[HeapTypes::array.getBasic(Shared)], 2u);
+ EXPECT_EQ(depths[built[0]], 1u);
+ EXPECT_EQ(depths[built[1]], 0u);
+ EXPECT_EQ(depths[built[2]], 1u);
+ EXPECT_EQ(depths[built[3]], 0u);
}
// Test reuse of a previously built type as supertype.
diff --git a/test/lit/passes/gufa-tnh.wast b/test/lit/passes/gufa-tnh.wast
index d276421f8..ecf031bbf 100644
--- a/test/lit/passes/gufa-tnh.wast
+++ b/test/lit/passes/gufa-tnh.wast
@@ -2034,3 +2034,32 @@
)
)
)
+
+(module
+ ;; CHECK: (type $0 (func (param i32) (result (ref null (shared any)))))
+
+ ;; CHECK: (table $0 3 3 (ref null (shared any)))
+ (table $0 3 3 (ref null (shared any)))
+ ;; CHECK: (elem $0 (table $0) (i32.const 0) (ref null (shared i31)) (item (ref.i31_shared
+ ;; CHECK-NEXT: (i32.const 999)
+ ;; CHECK-NEXT: )))
+ (elem $0 (table $0) (i32.const 0) (ref null (shared i31)) (item (ref.i31_shared (i32.const 999))))
+ ;; CHECK: (export "get" (func $0))
+
+ ;; CHECK: (func $0 (type $0) (param $0 i32) (result (ref null (shared any)))
+ ;; CHECK-NEXT: (ref.cast (ref null (shared i31))
+ ;; CHECK-NEXT: (table.get $0
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $0 (export "get") (param $0 i32) (result (ref null (shared any)))
+ ;; Regression test for a bug where subtypes.h did not handle shared types
+ ;; correctly, causing this example to be misoptimized to return null.
+ (ref.cast (ref null (shared i31))
+ (table.get $0
+ (i32.const 0)
+ )
+ )
+ )
+)