sparc: make ABI consistent with clang - #160401
Conversation
long double (i.e. f128) is special-case in the sparc abi
|
r? workingjubilee (who else lol) This is totally tier 3, but if we have it, it should be correct. |
|
|
|
I will dig out my TSIM3 licence and double check this on the LEON3 simulator. I'm pinging @glaubitz who knows more about the 64-bit SPARC Linux side than I do. (Also, |
|
Neat, to be clear I validated the changes with qemu, clang and gcc 16.
The changes here only touch 32-bit SPARC, and the ABI is, from what I can tell, quite different to SPARC64. |
There was a problem hiding this comment.
Since this PR is to fix the SPARC struct ABI could you add "Fixes: #43894"?
| let pad_i32 = !offset.is_aligned(align); | ||
| arg.cast_to_and_pad_i32(Uniform::new(Reg::i32(), size), pad_i32); | ||
| if is_long_double(arg.layout.backend_repr) || arg.layout.is_aggregate() { | ||
| arg.pass_by_stack_offset(None); |
There was a problem hiding this comment.
| arg.pass_by_stack_offset(None); | |
| arg.make_indirect(); |
According to the 32-bit SPARC ABI, this should be passed indirectly, not by stack offset ("[...] structure and union objects are not passed directly in the argument list."). pass_by_stack_offset appears to work with LLVM as the LLVM SPARC backend appears to ignore the byval attribute (compiler explorer), but we should use make_indirect as other codegen backends might not ignore it.
There was a problem hiding this comment.
Since this PR is to fix the SPARC struct ABI could you add "Fixes: #43894"?
added, but also wow from 2017 huh
| let pad_i32 = !offset.is_aligned(align); | ||
| arg.cast_to_and_pad_i32(Uniform::new(Reg::i32(), size), pad_i32); | ||
| if is_long_double(arg.layout.backend_repr) || arg.layout.is_aggregate() { | ||
| arg.pass_by_stack_offset(None); |
this matches GCC and Clang.
ccdb6c7 to
4873fa1
Compare
|
Do our SPARC Linux and SPARC bare-metal targets have the same ABI? Bare metal SPARC is aimed at the LEON3 but I think SPARC Linux is for 32 bit applications for 64 bit SPARC machines? Which QEMU machine did you test with? |
|
LLVM does not take the OS into account at all My config is [target.sparc-unknown-linux-gnu]
runner = "qemu-sparc32plus -L /usr/sparc-linux-gnu"So that runs the v9-flavored v8, at least based on https://stackoverflow.com/questions/23506538/what-is-em-sparc32plus-for. That is needed because we configure the To clarify: I believe this uses V9 instructions (or something like it), but still uses the V8 abi. |
|
I don't think so, no. At least, sparc-unknown-none-elf does not set v8plus which I think means it uses a different ABI. |
|
#160562 adds a rustc_abi toggle for v8plus. |
fixes #43894
I've hacked together a version of abi-cafe that can cross-compile. It finds many GCC vs. Clang inconsistencies, but for this target it found 3 ABI bugs that are specific to the rust implementation.
For reference
SparcV8ABIInfo::{classifyArgumentType, classifyReturnType}DefaultABIInfo::{classifyArgumentType, classifyReturnType}Pass ZST arguments
https://godbolt.org/z/P7KoqTWvr
The
sparcABI does not skip zero-sized arguments.Pass and return
f128(i.e.long double) indirectlyThe
long doubletype, which corresponds to rustf128, is special-cased, it usesgetNaturalAlignIndirectfor both arguments and returns.pass aggregate arguments by reference
https://godbolt.org/z/hM8Gh1bfY
The implementation defers to
DefaultABIInfo::{classifyReturnType, classifyArgumentType}, which usebyvalandsretfor aggregate types.