diff options
author | Alon Zakai <azakai@google.com> | 2024-04-10 14:14:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-10 14:14:37 -0700 |
commit | 6236dc31d397aa53c03c90fb27bf5cf4933d0c24 (patch) | |
tree | 052291a94eb74b97dd35c707cdf92248f2052280 /src | |
parent | f7ea0c4cff5e3d80e3feb2bce15037bd2c6b9383 (diff) | |
download | binaryen-6236dc31d397aa53c03c90fb27bf5cf4933d0c24.tar.gz binaryen-6236dc31d397aa53c03c90fb27bf5cf4933d0c24.tar.bz2 binaryen-6236dc31d397aa53c03c90fb27bf5cf4933d0c24.zip |
Heap2Local: Fix signed struct/array reads (#6484)
In #6480 I forgot that StructGet can be signed, which means we need to emit
a sign-extend.
Arrays already copied the field as part of Array2Struct.
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/Heap2Local.cpp | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/src/passes/Heap2Local.cpp b/src/passes/Heap2Local.cpp index 3b0410a77..b77775462 100644 --- a/src/passes/Heap2Local.cpp +++ b/src/passes/Heap2Local.cpp @@ -652,7 +652,7 @@ struct Struct2Local : PostWalker<Struct2Local> { // Add a mask for packed fields. We add masks on sets rather than on gets // because gets tend to be more numerous both in code appearances and in // runtime execution. As a result of masking on sets, the value in the local - // is always the masked value (which is also nice for debugging, + // is always the masked unsigned value (which is also nice for debugging, // incidentally). Expression* addMask(Expression* value, const Field& field) { if (!field.isPacked()) { @@ -795,7 +795,8 @@ struct Struct2Local : PostWalker<Struct2Local> { return; } - auto type = fields[curr->index].type; + auto& field = fields[curr->index]; + auto type = field.type; if (type != curr->type) { // Normally we are just replacing a struct.get with a local.get of a // local that was created to have the same type as the struct's field, @@ -811,9 +812,13 @@ struct Struct2Local : PostWalker<Struct2Local> { // which may be more refined. refinalize = true; } - replaceCurrent(builder.makeSequence( - builder.makeDrop(curr->ref), - builder.makeLocalGet(localIndexes[curr->index], type))); + Expression* value = builder.makeLocalGet(localIndexes[curr->index], type); + if (field.isPacked() && curr->signed_) { + // The value in the local is the masked unsigned value, which we must + // sign-extend. + value = Bits::makeSignExt(value, field.getByteSize(), wasm); + } + replaceCurrent(builder.makeSequence(builder.makeDrop(curr->ref), value)); } }; |