Skip to content

sparc: make ABI consistent with clang - #160401

Open
folkertdev wants to merge 3 commits into
rust-lang:mainfrom
folkertdev:sparc-abi-fixes
Open

sparc: make ABI consistent with clang#160401
folkertdev wants to merge 3 commits into
rust-lang:mainfrom
folkertdev:sparc-abi-fixes

Conversation

@folkertdev

@folkertdev folkertdev commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

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

Pass ZST arguments

https://godbolt.org/z/P7KoqTWvr

The sparc ABI does not skip zero-sized arguments.

Pass and return f128 (i.e. long double) indirectly

The long double type, which corresponds to rust f128, is special-cased, it uses getNaturalAlignIndirect for both arguments and returns.

pass aggregate arguments by reference

https://godbolt.org/z/hM8Gh1bfY

The implementation defers to DefaultABIInfo::{classifyReturnType, classifyArgumentType}, which use byval and sret for aggregate types.

long double (i.e. f128) is special-case in the sparc abi
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 2, 2026
@folkertdev

Copy link
Copy Markdown
Contributor Author

r? workingjubilee (who else lol)
cc @jonathanpallant as target maintainer

This is totally tier 3, but if we have it, it should be correct.

@rustbot

rustbot commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

workingjubilee is currently at their maximum review capacity.
They may take a while to respond.

@folkertdev
folkertdev marked this pull request as ready for review August 2, 2026 22:55
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 2, 2026
@jonathanpallant

Copy link
Copy Markdown
Contributor

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, sparc64-unknown-linux-gnu is Tier 2 with no platform docs, and hence no recorded maintainer ... so that's not ideal)

@folkertdev

Copy link
Copy Markdown
Contributor Author

Neat, to be clear I validated the changes with qemu, clang and gcc 16.

I'm pinging glaubitz who knows more about the 64-bit SPARC Linux side than I do.

The changes here only touch 32-bit SPARC, and the ABI is, from what I can tell, quite different to SPARC64.

@beetrees beetrees left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this PR is to fix the SPARC struct ABI could you add "Fixes: #43894"?

View changes since this review

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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@folkertdev folkertdev left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this PR is to fix the SPARC struct ABI could you add "Fixes: #43894"?

added, but also wow from 2017 huh

View changes since this review

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);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@folkertdev folkertdev added the O-SPARC Target: SPARC processors label Aug 3, 2026
@jonathanpallant

Copy link
Copy Markdown
Contributor

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?

@folkertdev

folkertdev commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

LLVM does not take the OS into account at all

https://github.com/llvm/llvm-project/blob/6849789a8fa1fc4a09f4f81dc655235e648eb15a/clang/lib/CodeGen/Targets/Sparc.cpp#L34-L59

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 +v8plus feature for the linux target

options: TargetOptions {
features: "+v8plus".into(),
cpu: "v9".into(),
endian: Endian::Big,
late_link_args: TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&["-mcpu=v9", "-m32"],
),

To clarify: I believe this uses V9 instructions (or something like it), but still uses the V8 abi.

@taiki-e

taiki-e commented Aug 4, 2026

Copy link
Copy Markdown
Member

To clarify: I believe this uses V9 instructions (or something like it), but still uses the V8 abi.

+v8plus enables the use of the v8+ ABI. See #132552 for details. (I think it would actually be more appropriate to use the rustc_abi field here in addition to features, but I don't think that field was implemented at the time.)

@RalfJung

RalfJung commented Aug 5, 2026

Copy link
Copy Markdown
Member

Do our SPARC Linux and SPARC bare-metal targets have the same 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.

@RalfJung

RalfJung commented Aug 5, 2026

Copy link
Copy Markdown
Member

#160562 adds a rustc_abi toggle for v8plus.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

O-SPARC Target: SPARC processors S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

struct pass-by-value failing on SPARC

7 participants