[cfe-dev] ABI of libgcc functions on hard-float ARM

Brian Silverman via cfe-dev cfe-dev at lists.llvm.org
Thu Apr 21 12:37:29 PDT 2016


Hi,

I've run into a compatibility issue with the calling convention of the
runtime library (libgcc/compiler-rt) functions on ARM with hard floating
point. Clang passes the floating point arguments in integer registers (like
with -mfloat-abi=soft), but GCC calls them like other functions with the
hard-float ABI. The only reference to this I can find online is this LLVM
development mailing list post
<http://lists.llvm.org/pipermail/llvm-dev/2014-October/077898.html>
discussing why Clang switched to always using soft-float. At least one of
the Clang developers thought GCC did this too, but it doesn't seem to
currently. Complex arithmetic is implemented with these functions even when
hardware floating point is supported, which means complex arithmetic is
pretty completely broken on platforms like this when using libgcc.

I found the code in clang's lib/CodeGen/TargetInfo.cpp which sets BuiltinCC
to CallingConv::ARM_AAPCS and the __attribute__((pcs("aapcs"))) in
compiler-rt's lib/builtins/int_lib.h which compiles the relevant functions
that way. I can't find any evidence of GCC doing either of those.

In all three copies of libgcc.a I've disassembled (Debian Jessie armhf and
both of the ones
from gcc-linaro-4.9-2015.05-x86_64_arm-linux-gnueabihf) __divdc3 (for
example) definitely uses the hard-float ABI.
In clang+llvm-3.8.0-armv7a-linux-gnueabihf/lib/clang/3.8.0/lib/linux/libclang_rt.builtins-armhf.a
(downloaded from llvm.org), __divdc3 is definitely using the soft-float ABI.

I wrote up a simple test program to demonstrate the effects:
$ cat test_complex.c
#include <complex.h>
#include <stdio.h>

int main(int argc, char **argv) {
double complex two = 2.0 + 0.0 * I;

// Prevent GCC from just optimizing all the math out.
if (argv[0] == '\0') {
two += 1.0;
}

double complex result = two / two;
if (creal(result) > 1.5) {
printf("broken\n");
} else {
printf("works\n");
}
}
$ gcc -lm test_complex.c -O3 && ./a.out
works
$ clang -lm test_complex.c -O3 && ./a.out
broken

I've tried with Clang 3.7.1 I cross-compiled for armhf myself and 3.8.0
binaries downloaded from llvm.org.

I'm pretty sure using clang with libgcc is supposed to work, so this seems
like a bug. Is there some solution I'm not seeing?

Thanks in advance,
Brian Silverman
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160421/b18a4107/attachment.html>


More information about the cfe-dev mailing list