Open Quuxplusone opened 8 years ago
Attached test_complex.c
(332 bytes, text/x-csrc): A simple program which demonstrates the affects
Brian,
It might happen that gcc changed its behavior silently (thus breaking the ABI). I believe that back in 2014 when this issue was first seen libgcc certainly used AAPCS calling convention.
clang change was added to effectively fix the opposite problem - we used to emit calls using AAPCS-FP calling while both libgcc and compiler-rt had only AAPCS versions (I believe I double checked this behavior at that time).
So, I'm not sure how to proceed. We cannot simply revert the change, because this will surely break ABI and backward compatibility.
This is certainly interesting. Ive looked into this previously, but it is
possible that I missed something or analyzed something incorrectly.
My understanding is that the hard float/soft float choice does not impact
libgcc at all. GCC will *generate* calls to the library using ARM_AAPCSCC.
However, it may be possible to get libgcc to be compiled ARM_AAPCS_VFPCC. In
this case you end up with the calling convention mismatch, and that will
certainly fail.
In the case of "soft" and "soft fp", the calling convention matches and
everything is happy. In the case of "hard", most of the calls can be lowered
directly to instructions rather than a library call. In such a scenario, again
we are safe. What remains is the last few cases where we generate library
calls.
Retaining the current behavior of compiling compiler-rt as ARM_AAPCSCC means
that we remain compatible with gcc's code generation irrespective of the
floating point ABI used.
This area is certainly under documented, but AIUI, the ABI for the libgcc calls
for AAPCSCC rather than AAPCS_VFPCC. If there is documentation indicating
otherwise (or worst case scenario, code) or perhaps things have changed in the
past year or so, we can certainly adjust the behavior of clang/llvm.
If GCC does use both calling conventions when making library calls, we can
always do two builds with differing calling conventions and link them
appropriately. If necessary, we could add thunks to adjust for the calling
convention as well.
(In reply to comment #2)
> If GCC does use both calling conventions when making library calls, we can
> always do two builds with differing calling conventions and link them
> appropriately. If necessary, we could add thunks to adjust for the calling
> convention as well.
One of the problems is that there is no mangling which would allow us to
distinguish between different calling conventions....
Clang is currently not compatible with GCC's code generation. I do have code indicating that GCC uses AAPCS_VFPCC for functions (calls and definitions) in libgcc. The Debian Jessie armhf libgcc.a is an example of code, and the compiler from the same place generates matching calls. The gcc-linaro-4.9-2015.05-x86_64_arm-linux-gnueabihf (amd64 to armhf cross) toolchain has both of those too, and the libgcc_s shared objects from both places also have hard-float code.
I'm not sure changing this would break much. From what I'm seeing, these functions get statically linked into all binaries which use them. This means that (unless somebody's doing something pretty unusual, like somehow using the code from libgcc_s.so or the compiler-rt equivalent) changing compiler-rt and clang together won't break anybody, as long as they're using matched versions.
It sounds like Clang needs two versions of the lib and some kind of option for how to generate calls to be fully compatible with GCC.
I'm currently working on compiling a libclang from compiler-rt to try using at compile time. I think by linking that into the binary first I'll get the soft-fp versions of the functions, and it'll work. That's definitely a somewhat fragile workaround though.
test_complex.c
(332 bytes, text/x-csrc)