diff options
author | Alon Zakai <azakai@google.com> | 2022-07-25 12:47:44 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-25 19:47:44 +0000 |
commit | 68e2ed11e86e72cc4e12a1b4026ef19d5149fda9 (patch) | |
tree | ad4ee672468c5fdf41be4bb612e070de66c27a5b /src/literal.h | |
parent | 2db1e13f731e22fe53fbfebef6e4a15c043a587e (diff) | |
download | binaryen-68e2ed11e86e72cc4e12a1b4026ef19d5149fda9.tar.gz binaryen-68e2ed11e86e72cc4e12a1b4026ef19d5149fda9.tar.bz2 binaryen-68e2ed11e86e72cc4e12a1b4026ef19d5149fda9.zip |
[Wasm GC] Properly represent nulls in i31 (#4819)
The encoding here is simple: we store i31 values in the literal.i32
field. The top bit says if a value exists, which means literal.i32 == 0 is the
same as null.
Diffstat (limited to 'src/literal.h')
-rw-r--r-- | src/literal.h | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/src/literal.h b/src/literal.h index c37f74499..1151abd2c 100644 --- a/src/literal.h +++ b/src/literal.h @@ -38,6 +38,9 @@ class Literal { // store only integers, whose bits are deterministic. floats // can have their signalling bit set, for example. union { + // Note: i31 is stored in the |i32| field, with the lower 31 bits containing + // the value if there is one, and the highest bit containing whether there + // is a value. Thus, a null is |i32 === 0|. int32_t i32; int64_t i64; uint8_t v128[16]; @@ -111,6 +114,9 @@ public: if (isData()) { return !gcData; } + if (type.getHeapType() == HeapType::i31) { + return i32 == 0; + } return true; } return false; @@ -257,7 +263,7 @@ public: } static Literal makeI31(int32_t value) { auto lit = Literal(Type(HeapType::i31, NonNullable)); - lit.i32 = value & 0x7fffffff; + lit.i32 = value | 0x80000000; return lit; } @@ -276,7 +282,8 @@ public: } int32_t geti31(bool signed_ = true) const { assert(type.getHeapType() == HeapType::i31); - return signed_ ? (i32 << 1) >> 1 : i32; + // Cast to unsigned for the left shift to avoid undefined behavior. + return signed_ ? int32_t((uint32_t(i32) << 1)) >> 1 : (i32 & 0x7fffffff); } int64_t geti64() const { assert(type == Type::i64); |