diff options
author | Thomas Lively <tlively@google.com> | 2022-11-17 13:30:47 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-17 13:30:47 -0800 |
commit | 5f5c70255cfa917efee9855ce1f8340b017e0adb (patch) | |
tree | fd52430526a6dcf3ef9aa57960cde0b646cb8af4 | |
parent | ec53f4b2d5b0d52ae703c5b696ecf052ad5fffbb (diff) | |
download | binaryen-5f5c70255cfa917efee9855ce1f8340b017e0adb.tar.gz binaryen-5f5c70255cfa917efee9855ce1f8340b017e0adb.tar.bz2 binaryen-5f5c70255cfa917efee9855ce1f8340b017e0adb.zip |
Fix isorecursive canonicalization (#5269)
Fixes a longstanding problem with isorecursive canonicalization that only showed
up in MacOS and occasionally Windows builds. The problem was that
`RecGroupEquator` was not quite correct in the presence of self-references in
rec groups. Specifically, `RecGroupEquator` did not differentiate between
instances of the same type appearing across two rec groups where the type was a
self-reference in one group but not in the other.
The reason this only showed up occasionally on some platforms was that this bug
could only cause incorrect behavior if two groups that would incorrectly be
compared as equal were hashed into the same bucket of a hash map. Apparently the
hash map used on Linux never hashes the two problematic groups into the same
bucket.
-rw-r--r-- | src/wasm/wasm-type.cpp | 9 | ||||
-rw-r--r-- | test/gtest/type-builder.cpp | 2 |
2 files changed, 5 insertions, 6 deletions
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 4fa7ff9d5..6b11ff95e 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -2676,11 +2676,8 @@ bool RecGroupEquator::topLevelEq(HeapType a, HeapType b) const { } bool RecGroupEquator::eq(Type a, Type b) const { - if (a == b) { - return true; - } if (a.isBasic() || b.isBasic()) { - return false; + return a == b; } return eq(*getTypeInfo(a), *getTypeInfo(b)); } @@ -2699,7 +2696,9 @@ bool RecGroupEquator::eq(HeapType a, HeapType b) const { } auto groupA = a.getRecGroup(); auto groupB = b.getRecGroup(); - return groupA == groupB || (groupA == newGroup && groupB == otherGroup); + bool selfRefA = groupA == newGroup; + bool selfRefB = groupB == otherGroup; + return (selfRefA && selfRefB) || (!selfRefA && !selfRefB && groupA == groupB); } bool RecGroupEquator::eq(const TypeInfo& a, const TypeInfo& b) const { diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp index fe1f19871..8ba2a39d1 100644 --- a/test/gtest/type-builder.cpp +++ b/test/gtest/type-builder.cpp @@ -362,7 +362,7 @@ TEST_F(IsorecursiveTest, CanonicalizeUses) { EXPECT_NE(built[4], built[6]); } -TEST_F(IsorecursiveTest, DISABLED_CanonicalizeSelfReferences) { +TEST_F(IsorecursiveTest, CanonicalizeSelfReferences) { TypeBuilder builder(5); // Single self-reference builder[0] = makeStruct(builder, {0}); |