Skip to content

Commit 5280e98

Browse files
authored
fix(stdlib): Correctly promote numbers to bigints when left-shifting (#1354)
1 parent 2cbaae8 commit 5280e98

File tree

2 files changed

+14
-1
lines changed

2 files changed

+14
-1
lines changed

compiler/test/suites/numbers.re

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ describe("numbers", ({test, testSkip}) => {
4141
assertRun("number_syntax8", "print(1.2e2)", "120.0\n");
4242
assertRun("number_syntax9", "print(1l)", "1\n");
4343
assertRun("number_syntax10", "print(1L)", "1\n");
44+
assertRun(
45+
"number_shift_promote",
46+
"print(5 << 64)",
47+
"92233720368547758080\n",
48+
);
4449
assertRun(
4550
"number_syntax11",
4651
"print(987654321987654321987654321)",

stdlib/runtime/numbers.gr

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1833,7 +1833,15 @@ export let (<<) = (x: Number, y: Number) => {
18331833
} else {
18341834
let xval = coerceNumberToWasmI64(x)
18351835
let yval = coerceNumberToWasmI64(y)
1836-
WasmI32.toGrain(reducedInteger(WasmI64.shl(xval, yval))): Number
1836+
// if the number will be shifted beyond the end of the i64 range, promote to BigInt
1837+
// (note that we subtract one leading zero, since the leading bit is the sign bit)
1838+
if (WasmI64.leU(WasmI64.sub(WasmI64.clz(i64abs(xval)), 1N), yval)) {
1839+
let xbi = coerceNumberToBigInt(x)
1840+
let yval = coerceNumberToWasmI32(y)
1841+
WasmI32.toGrain(reducedBigInteger(BI.shl(xbi, yval))): Number
1842+
} else {
1843+
WasmI32.toGrain(reducedInteger(WasmI64.shl(xval, yval))): Number
1844+
}
18371845
}
18381846
}
18391847

0 commit comments

Comments
 (0)