Skip to content

Conversation

@laurenthuberdeau
Copy link
Collaborator

Context

When SUPPORT_64_BIT_LITERALS is not enabled, INTEGER nodes store the negation of the integer value. This is done to support the full range of 32-bit signed integers, since the positive value 2147483648 cannot be represented as a positive signed 32-bit integer.

To get the actual value, it must be negated. If the negated value is -2147483648, negating it produces 2147483648, which overflows the 32-bit signed integer range (assuming the host platform uses 32-bit integers) and loops back to -2147483648. Additionally, for 64-bit targets, the value must be sign-extended to 64-bits, which is done by left shifting by 31.

On platforms with 32-bit integers, the two's complement representation of 2147483648 is the same as -2147483648's two's complement, 0x80000000 in hex, and so everything works out.

On platforms with larger integers, such as some shells, the value 2147483648 is representable as a positive integer, and so negating -2147483648 produces 2147483648, which produces an invalid sign-extended value when shifted. Sign-extension is only performed when targeting 64-bit platforms, where 2147483648 >> 31 evaluates to 1.

This PR changes the sign-extension to no longer assume exactly 32-bit integers.

When SUPPORT_64_BIT_LITERALS is not enabled, INTEGER nodes store the
negation of the integer value. This is done to support the full range of
32-bit signed integers, since the positive value 2147483648 cannot be
represented as a positive signed 32-bit integer.

To get the actual value, it must be negated. If the negated value is
-2147483648, negating it produces 2147483648, which overflows the 32-bit
signed integer range (assuming the host platform uses 32-bit integers)
and loops back to -2147483648. Additionally, for 64-bit targets, the
value must be sign-extended to 64-bits, which is done by left shifting
by 31.

On platforms with 32-bit integers, the two's complement representation
of 2147483648 is the same as -2147483648's two's complement, 0x80000000
in hex, and so everything works out.

On platforms with larger integers, such as some shells, the value
2147483648 is representable as a positive integer, and so negating
-2147483648 produces 2147483648, which produces an invalid sign-extended
value when shifted. Sign-extension is only performed when targeting
64-bit platforms, where 2147483648 >> 31 evaluates to 1.
laurenthuberdeau added a commit that referenced this pull request Nov 11, 2025
Without this, the 0x80000000 literal in
sign-extended which causes differences in the
bootstrapped compiler binaries.

See #213
for more information.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants