From e97b0bb541ee182c4f38709e2dbbaee03be12138 Mon Sep 17 00:00:00 2001 From: bptato <60043228+bptato@users.noreply.github.com> Date: Tue, 30 Dec 2025 23:09:01 +0100 Subject: [PATCH] Do not directly cast int128 to uint64 in semfold (#25396) int128 is an array of uint32s, so while this works on little-endian CPUs, it's completely broken on big-endian. e.g. following snippet would fail: const x = 0xFFFFFFFF'u32 const y = (x shr 1) echo y # amd64: 2147483647, s390x: 0 That in turn broke float printing, resulting in miscompilation of any code that used floats. To fix this, we now call the aptly named castToUInt64 procedure which performs the same cast portably. (Thanks to barracuda156 for helping debug this.) --- compiler/semfold.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 501e66969a..1a3f40a47a 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -201,8 +201,8 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl valueB), n, idgen, g) else: internalError(g.config, n.info, "constant folding for shl") of mShrI: - var a = cast[uint64](getInt(a)) - let b = cast[uint64](getInt(b)) and cast[uint64](n.typ.size * 8 - 1) + var a = castToUInt64(getInt(a)) + let b = castToUInt64(getInt(b)) and cast[uint64](n.typ.size * 8 - 1) # To support the ``-d:nimOldShiftRight`` flag, we need to mask the # signed integers to cut off the extended sign bit in the internal # representation.