You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Bitwise AND on signed i8/i16 skips sign extension when one operand is wrapped or negative #3061
Bitwise & on i8 or i16 omits sign extension (i32.extend8_s / i32.extend16_s) when one operand is already wrapped or is a negative constant, leaving upper bits from an unmasked arithmetic expression intact.
For example, in the reproduction below:
In f(), a + a wraps to -2 in i16, and -2 & -1 should evaluate to -2, so f() should return -2n, but it returns 65534n.
In g(100), a + a wraps to -56 in i8, and -56 & -128 should evaluate to -128, so g(100) should return true (1), but it returns false (0).
Flow.canOverflow for BinaryOp.AndI32 treats x & y as non-overflowing if either operand cannot overflow or is a constant <= computeSmallIntegerMask(type), which only holds for non-negative values since negative small integers have 1s in their upper 16/24 bits.
Steps to reproduce
exportfunctionf(): i64{leta: i16=32767;letm: i16=-1;letb: i16=(a+a)&m;// a + a wraps to -2 in i16; -2 & -1 is -2return<i64>b;}exportfunctiong(a: i8): bool{letb: i8=(a+a)&<i8>-128;// for a = 100: a + a wraps to -56; -56 & -128 is -128returnb==-128;}
Compile with asc repro.ts -O0 (or -O3) and call f() and g(100).
Activity