summaryrefslogtreecommitdiff
path: root/src/literal.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/literal.h')
-rw-r--r--src/literal.h11
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);