Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a conforming compiler break uint32_t -> int16_t -> int32_t conversions?

Recently, we discovered odd behavior in some old code. This code has worked for ages, but broke on some platform (XBox 360, PowerPC) with compiler optimizations turned on max. Usually, I'd suspect undefined behavior.

Code looks roughly like this:

#include <stdint.h>
uint32_t sign_extend16(uint32_t val)
{
   return (int32_t)(int16_t)val;
}

It's part of an emulator so the operation in question shouldn't be too strange. Normally, I'd expect this to only consider the lower 16-bits and sign-extend that to 32-bits. Apparently, this was the behavior it had for ages. On x86_64, GCC gives me this result:

0000000000000000 <sign_extend16>:
   0:   0f bf c7                movswl %di,%eax
   3:   c3                      retq

However, from what I could understand of the standard, converting an unsigned to a signed is not defined should it not be possible to represent the value of the unsigned one with the signed type.

Could it then be possible for the compiler to assume that the unsigned value would have to be in the range of [0, 32767], as any other value would be undefined? In that case, a cast to int16_t and yet another cast to int32_t would do nothing. In this case, would it be legal for the compiler to translate the code to a simple move?

like image 213
Maister Avatar asked Feb 09 '12 23:02

Maister


1 Answers

A conversion between two integer types is never undefined behavior.

But some integer conversions are implementation defined.

On integer conversions C says:

(C99, 6.3.1.3p3) "Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised."

what does gcc on this case is documented here:

http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html

"For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; no signal is raised"

like image 80
ouah Avatar answered Oct 09 '22 20:10

ouah