Fix bug in ivar align computation.

__builtin_clz takes an unsigned int, it isn't overloaded for different
types.  This meant that we were computing log2 by counting the
leading bits in a 32-bit value and using that result as if it were the
number of bits in a 64-bit value.  This meant that our alignment values
were 2^32 times as big as they should be.  This mostly didn't matter,
because we then truncated the result to 32 bits and the wrapping gave
the correct answer.

Unfortunately, this was undefined behaviour and, at sufficiently high
optimisation levels, this resulted in the value being optimised away,
leading to odd results.
main
David Chisnall 7 years ago
parent 5585a44574
commit 8db0450dcc

@ -94,7 +94,15 @@ static inline void ivarSetAlign(Ivar ivar, size_t align)
{ {
if (align != 0) if (align != 0)
{ {
align = sizeof(size_t) * 8 - __builtin_clz(align) - 1; if (sizeof(size_t) == 4)
{
align = 4 * 8 - __builtin_clz(align) - 1;
}
else if (sizeof(size_t) == 8)
{
align = 8 * 8 - __builtin_clzll(align) - 1;
}
_Static_assert((sizeof(size_t) == 4) || (sizeof(size_t) == 8), "Unexpected type for size_t");
} }
align <<= ivar_align_shift; align <<= ivar_align_shift;
ivar->flags = (ivar->flags & ~ivar_align_mask) | align; ivar->flags = (ivar->flags & ~ivar_align_mask) | align;

Loading…
Cancel
Save