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.)
This commit is contained in:
bptato
2025-12-30 23:09:01 +01:00
committed by GitHub
parent 234c73c58a
commit e97b0bb541

View File

@@ -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.