https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89604

            Bug ID: 89604
           Summary: Type conversion from signed char to a wider integer
                    generates wrong assembly for ARM,
           Product: gcc
           Version: 8.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: driver
          Assignee: unassigned at gcc dot gnu.org
          Reporter: christalization at gmail dot com
  Target Milestone: ---

Created attachment 45902
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45902&action=edit
Preprocessed file

So I've stumbled upon this bug when compiling a project on the Raspberry pi.
I created a barebone test project to verify that nothing else was causing it,
and indeed, I got the same result.

What happens is that when you're converting a signed char type to a signed
integer, the conversion fails to move the sign bit, instead it just extends the
bits like it would with an unsigned conversion.
I've verified that this does not happen on x86/64 builds so it appears to be
specific for ARM builds. Compiling exactly the same piece of code on Windows
yields the correct result:

int main()
{
char c = -40;
double s = c;
printf("%f", s);
return 0;
}

Windows: -40
Raspbian: 226

226 is what you get when interpreting the bits of the char as unsigned.
I got around the problem for now by explicitly moving the sign bit as such:
((int)c & ~0x80) | ~0x7FFFFFFF

Here is the compiler output along with the commandline arguments:

g++ -v -save-temps test.cpp -o test
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/6/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Raspbian
6.3.0-18+rpi1+deb9u1' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs
--enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-6 --program-prefix=arm-linux-gnueabihf- --enable-shared
--enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/
--enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm
--disable-libquadmath --enable-plugin --with-system-zlib
--disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-6-armhf/jre --enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-armhf
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-armhf
--with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
--with-target-system-zlib --enable-objc-gc=auto --enable-multiarch
--disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard
--enable-checking=release --build=arm-linux-gnueabihf
--host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 6.3.0 20170516 (Raspbian 6.3.0-18+rpi1+deb9u1) 
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'test' '-shared-libgcc'
'-march=armv6' '-mfloat-abi=hard' '-mfpu=vfp' '-mtls-dialect=gnu'
 /usr/lib/gcc/arm-linux-gnueabihf/6/cc1plus -E -quiet -v -imultilib .
-imultiarch arm-linux-gnueabihf -D_GNU_SOURCE test.cpp -march=armv6
-mfloat-abi=hard -mfpu=vfp -mtls-dialect=gnu -fpch-preprocess -o test.ii
ignoring duplicate directory "/usr/include/arm-linux-gnueabihf/c++/6"
ignoring nonexistent directory "/usr/local/include/arm-linux-gnueabihf"
ignoring nonexistent directory
"/usr/lib/gcc/arm-linux-gnueabihf/6/../../../../arm-linux-gnueabihf/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/6
 /usr/include/arm-linux-gnueabihf/c++/6
 /usr/include/c++/6/backward
 /usr/lib/gcc/arm-linux-gnueabihf/6/include
 /usr/local/include
 /usr/lib/gcc/arm-linux-gnueabihf/6/include-fixed
 /usr/include/arm-linux-gnueabihf
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'test' '-shared-libgcc'
'-march=armv6' '-mfloat-abi=hard' '-mfpu=vfp' '-mtls-dialect=gnu'
 /usr/lib/gcc/arm-linux-gnueabihf/6/cc1plus -fpreprocessed test.ii -quiet
-dumpbase test.cpp -march=armv6 -mfloat-abi=hard -mfpu=vfp -mtls-dialect=gnu
-auxbase test -version -o test.s
GNU C++14 (Raspbian 6.3.0-18+rpi1+deb9u1) version 6.3.0 20170516
(arm-linux-gnueabihf)
        compiled by GNU C version 6.3.0 20170516, GMP version 6.1.2, MPFR
version 3.1.5, MPC version 1.0.3, isl version 0.15
GGC heuristics: --param ggc-min-expand=93 --param ggc-min-heapsize=118680
GNU C++14 (Raspbian 6.3.0-18+rpi1+deb9u1) version 6.3.0 20170516
(arm-linux-gnueabihf)
        compiled by GNU C version 6.3.0 20170516, GMP version 6.1.2, MPFR
version 3.1.5, MPC version 1.0.3, isl version 0.15
GGC heuristics: --param ggc-min-expand=93 --param ggc-min-heapsize=118680
Compiler executable checksum: 79dca666fccaa96025c9107a8b3f60f3
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'test' '-shared-libgcc'
'-march=armv6' '-mfloat-abi=hard' '-mfpu=vfp' '-mtls-dialect=gnu'
 as -v -march=armv6 -mfloat-abi=hard -mfpu=vfp -meabi=5 -o test.o test.s
GNU assembler version 2.28 (arm-linux-gnueabihf) using BFD version (GNU
Binutils for Raspbian) 2.28
COMPILER_PATH=/usr/lib/gcc/arm-linux-gnueabihf/6/:/usr/lib/gcc/arm-linux-gnueabihf/6/:/usr/lib/gcc/arm-linux-gnueabihf/:/usr/lib/gcc/arm-linux-gnueabihf/6/:/usr/lib/gcc/arm-linux-gnueabihf/
LIBRARY_PATH=/usr/lib/gcc/arm-linux-gnueabihf/6/:/usr/lib/gcc/arm-linux-gnueabihf/6/../../../arm-linux-gnueabihf/:/usr/lib/gcc/arm-linux-gnueabihf/6/../../../:/lib/arm-linux-gnueabihf/:/lib/:/usr/lib/arm-linux-gnueabihf/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'test' '-shared-libgcc'
'-march=armv6' '-mfloat-abi=hard' '-mfpu=vfp' '-mtls-dialect=gnu'
 /usr/lib/gcc/arm-linux-gnueabihf/6/collect2 -plugin
/usr/lib/gcc/arm-linux-gnueabihf/6/liblto_plugin.so
-plugin-opt=/usr/lib/gcc/arm-linux-gnueabihf/6/lto-wrapper
-plugin-opt=-fresolution=test.res -plugin-opt=-pass-through=-lgcc_s
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc
-plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=/
--build-id --eh-frame-hdr -dynamic-linker /lib/ld-linux-armhf.so.3 -X
--hash-style=gnu -m armelf_linux_eabi -o test
/usr/lib/gcc/arm-linux-gnueabihf/6/../../../arm-linux-gnueabihf/crt1.o
/usr/lib/gcc/arm-linux-gnueabihf/6/../../../arm-linux-gnueabihf/crti.o
/usr/lib/gcc/arm-linux-gnueabihf/6/crtbegin.o
-L/usr/lib/gcc/arm-linux-gnueabihf/6
-L/usr/lib/gcc/arm-linux-gnueabihf/6/../../../arm-linux-gnueabihf
-L/usr/lib/gcc/arm-linux-gnueabihf/6/../../.. -L/lib/arm-linux-gnueabihf
-L/usr/lib/arm-linux-gnueabihf test.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s
-lgcc /usr/lib/gcc/arm-linux-gnueabihf/6/crtend.o
/usr/lib/gcc/arm-linux-gnueabihf/6/../../../arm-linux-gnueabihf/crtn.o
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-o' 'test' '-shared-libgcc'
'-march=armv6' '-mfloat-abi=hard' '-mfpu=vfp' '-mtls-dialect=gnu'

Reply via email to