diff options
author | Alon Zakai <azakai@google.com> | 2023-04-07 10:13:25 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-07 10:13:25 -0700 |
commit | a3fe7713bde3d652ec14267915585f6fca85e0d5 (patch) | |
tree | 2665009220571606019d9172ff0f91f78d7111e9 /src/ir/possible-contents.cpp | |
parent | 757d6a21a3c5626cfaa9dac28c28555748b93a6b (diff) | |
download | binaryen-a3fe7713bde3d652ec14267915585f6fca85e0d5.tar.gz binaryen-a3fe7713bde3d652ec14267915585f6fca85e0d5.tar.bz2 binaryen-a3fe7713bde3d652ec14267915585f6fca85e0d5.zip |
[Wasm GC] Handle packed fields in GUFA and CFP (#5640)
The same bug was present in both: We ignored packing, so writing a larger
value than fits in the field would lead to us propagating that original value.
Diffstat (limited to 'src/ir/possible-contents.cpp')
-rw-r--r-- | src/ir/possible-contents.cpp | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index 83762a458..d63830c40 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -17,8 +17,10 @@ #include <optional> #include <variant> +#include "ir/bits.h" #include "ir/branch-utils.h" #include "ir/eh-utils.h" +#include "ir/gc-type-utils.h" #include "ir/local-graph.h" #include "ir/module-utils.h" #include "ir/possible-contents.h" @@ -1430,6 +1432,8 @@ private: bool& worthSendingMore); void filterGlobalContents(PossibleContents& contents, const GlobalLocation& globalLoc); + void filterDataContents(PossibleContents& contents, + const DataLocation& dataLoc); // Reads from GC data: a struct.get or array.get. This is given the type of // the read operation, the field that is read on that type, the known contents @@ -1739,6 +1743,9 @@ bool Flower::updateContents(LocationIndex locationIndex, } else if (auto* globalLoc = std::get_if<GlobalLocation>(&location)) { filterGlobalContents(contents, *globalLoc); filtered = true; + } else if (auto* dataLoc = std::get_if<DataLocation>(&location)) { + filterDataContents(contents, *dataLoc); + filtered = true; } // Check if anything changed after filtering, if we did so. @@ -1971,6 +1978,30 @@ void Flower::filterGlobalContents(PossibleContents& contents, } } +void Flower::filterDataContents(PossibleContents& contents, + const DataLocation& dataLoc) { + auto field = GCTypeUtils::getField(dataLoc.type, dataLoc.index); + assert(field); + if (field->isPacked()) { + // We must handle packed fields carefully. + if (contents.isLiteral()) { + // This is a constant. We can truncate it and use that value. + auto mask = Literal(int32_t(Bits::lowBitMask(field->getByteSize() * 8))); + contents = PossibleContents::literal(contents.getLiteral().and_(mask)); + } else { + // This is not a constant. We can't even handle a global here, as we'd + // need to track that this global's value must be truncated before it is + // used, and we don't do that atm. Leave only the type. + // TODO Consider tracking packing on GlobalInfo alongside the type. + // Another option is to make GUFA.cpp apply packing on the read, + // like CFP does - but that can only be done when replacing a + // StructGet of a packed field, and not anywhere else we saw that + // value reach. + contents = PossibleContents::fromType(contents.getType()); + } + } +} + void Flower::readFromData(Type declaredType, Index fieldIndex, const PossibleContents& refContents, |