You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ABI mismatch on powerpc64 (elfv1) for union containing floats #162011
The ELFv1 specification says "Floating point registers f1 through f13 are used consecutively to pass [...] one member aggregates passed by value containing a floating point value" and the specification defines aggregates at the first use of the term as "Aggregates (structures and arrays)", so GCC and Clang are correct.
Yes, we're still using it. Losing host tools would be unfortunate as it it has quite some enthusiasts still.
Not much we can do, unfortunately. Rust upstream is extremely strict and insist on two maintainers per target which smaller downstream projects can't really provide.
Luckily, gccrs is in the works and if Rust upstream ever decides to completely kill off older PowerPC ports, we will still have GCC.
Please note that the barrier for being a target maintainer is actually rather low, it certainly doesn't come with any time commitment. Our docs say:
A tier 2 target must have a designated team of developers (the "target maintainers") available to consult on target-specific build-breaking issues, or if necessary to develop target-specific language or library implementation details. This team must have at least 2 developers.
All that's really needed is somebody who knows about some target specifics, and knows who to get in touch with for issues that they themselves can't address. If they can work on the issues that's of course better, but it could also be e.g. a GCC/LLVM contributor who dabbles in Rust and doesn't mind some ./x build work to help figure out the occasional issue.
I have to imagine it's possible to dig up two people like that for the target - please do reach out and point them at #113739 (comment) if so! If there really aren't two people like that around then it is not a good sign of this target's health.
I'll also note that this issue is not at all cause for demotion on its own. However, the target has accumulated a number of broken edge cases like this. Three years have gone by since #113739 was opened and in that time, nobody has expressed enough interest in keeping the target alive to sign up. Demotion would only be a reflection of that, and is completely reversible if that situation changes.
Fwiw I don't think we should demote now. But if at some point this target starts blocking something (breaks CI or blocks a new feature - IIRC this is problematic with tail calls) and we still don't have a target maintainer, I expect it would be demoted very rapidly.
I'll also note that this issue is not at all cause for demotion on its own. However, the target has accumulated a number of broken edge cases like this. Three years have gone by since #113739 was opened and in that time, nobody has expressed enough interest in keeping the target alive to sign up. Demotion would only be a reflection of that, and is completely reversible if that situation changes.
It's a communications problem. Not every downstream developer can be aware of every upstream issue of every upstream project.
Upstream developers often make announcements about changes that affect downstream within their upstream channels only and then they're surprised that they're not getting any feedback. But we can't just be everywhere. Downstream developers from distributions like Debian and Gentoo try to contribute as much as they can, but we don't have the manpower to be everywhere.
What frustrates me is that IBM engineers could perfectly take care of the other PowerPC ports besides ppc64el like they already do in GCC and the kernel. But apparently the management side has decided that older PowerPC targets deserve no attention, so these ports and the people maintaining them downstream end up getting under pressure.
Fwiw I don't think we should demote now. But if at some point this target starts blocking something (breaks CI or blocks a new feature - IIRC this is problematic with tail calls) and we still don't have a target maintainer, I expect it would be demoted very rapidly.
Well, the first message that reached downstream regarding this issue was the threat of demotion and not the question to ask for help resolving these issues. So, maybe you can understand the frustration a bit.
Fwiw I don't think we should demote now. But if at some point this target starts blocking something (breaks CI or blocks a new feature - IIRC this is problematic with tail calls) and we still don't have a target maintainer, I expect it would be demoted very rapidly.
Well, the first message that reached downstream regarding this issue was the threat of demotion and not the question to ask for help resolving these issues. So, maybe you can understand the frustration a bit.
I was the one that took the initiative to talk about demoting this target (in rust-lang/compiler-team#1035) so I am in part responsible for the confusion, for which I apologize.
As discussed on Zulip we (Rust project) try to balance maintenance reality and downstream expectations. I think we have enough evidence that demoting the target would create concrete inconveniences downstream, so I will retract the proposal.
Last but not least, thank you @glaubitz for your hard work in the Debian project and for taking the time to interface with us as well!
Clang seems to have this bug only with unions containing a single element (e.g. union { float a; }). This original bug report example is a union with two elements (e.g. union { float a; float b; }), which Rust doesn't handle correctly but Clang does.
It looks like you filed a Clang fix (thank you!), but per #162011 (comment) isn't Clang already doing the right thing?
For the reported case, yes. Clang gets single-member unions wrong, though.
The spec lists unions separately from aggregates everywhere ("Aggregates and Unions" in 3.1.6, "aggregates and unions passed by value" in 3.2.3), and the FPR rule only mentions "one member aggregates". So a union should never be passed in an FPR, even if it has one field. GCC does this. Clang unwraps single-member unions:
ELFv1
GCC
Clang 22
rustc
union { float a; float b; }
GPR
GPR
FPR
struct { union { float a; float b; } u; }
GPR
GPR
FPR
union { float a; }
GPR
FPR
FPR
struct { union { float a; } u; }
GPR
FPR
FPR
union { struct { float a; } s; }
GPR
FPR
FPR
It's the same with double, long double and 128-bit vector members. In Clang this comes from isSingleElementStruct accepting unions; llvm/llvm-project#223481 fixes that for ELFv1.
My rustc change never unwraps a union on ELFv1, so it matches GCC in all of these cases (and Clang once that PR lands). It does change rustc's ABI for single-member unions.
I look forward to seeing this. Does that mean you don't use homogenous_aggregate at all on elfv1? That function is causing issues on some other targets (where an empty array should disqualify an aggregate) so it needs some work.
Activity
rustbot commentedon Aug 31, 2026
Assigning P-high (discussion on Zulip).
folkertdev commentedon Sep 3, 2026
Ping target maintainers: @daltenty @gilamn5tr @amy-kwan @Gelbpunkt @famfo @neuschaefer
beetrees commentedon Sep 3, 2026
The ELFv1 specification says "Floating point registers f1 through f13 are used consecutively to pass [...] one member aggregates passed by value containing a floating point value" and the specification defines aggregates at the first use of the term as "Aggregates (structures and arrays)", so GCC and Clang are correct.
3 remaining items
glaubitz commentedon Sep 9, 2026
Not much we can do, unfortunately. Rust upstream is extremely strict and insist on two maintainers per target which smaller downstream projects can't really provide.
Luckily, gccrs is in the works and if Rust upstream ever decides to completely kill off older PowerPC ports, we will still have GCC.
tgross35 commentedon Sep 9, 2026
Please note that the barrier for being a target maintainer is actually rather low, it certainly doesn't come with any time commitment. Our docs say:
All that's really needed is somebody who knows about some target specifics, and knows who to get in touch with for issues that they themselves can't address. If they can work on the issues that's of course better, but it could also be e.g. a GCC/LLVM contributor who dabbles in Rust and doesn't mind some
./x buildwork to help figure out the occasional issue.I have to imagine it's possible to dig up two people like that for the target - please do reach out and point them at #113739 (comment) if so! If there really aren't two people like that around then it is not a good sign of this target's health.
tgross35 commentedon Sep 9, 2026
I'll also note that this issue is not at all cause for demotion on its own. However, the target has accumulated a number of broken edge cases like this. Three years have gone by since #113739 was opened and in that time, nobody has expressed enough interest in keeping the target alive to sign up. Demotion would only be a reflection of that, and is completely reversible if that situation changes.
Fwiw I don't think we should demote now. But if at some point this target starts blocking something (breaks CI or blocks a new feature - IIRC this is problematic with tail calls) and we still don't have a target maintainer, I expect it would be demoted very rapidly.
mattst88 commentedon Sep 9, 2026
From the
TwoFloatsexample in the initial report, clang pass the float in a GPR and rust passes it in an FPR.This bit of code seems likely to be involved: https://github.com/rust-lang/rust/blob/main/compiler/rustc_target/src/callconv/powerpc64.rs#L27-L44
glaubitz commentedon Sep 10, 2026
It's a communications problem. Not every downstream developer can be aware of every upstream issue of every upstream project.
Upstream developers often make announcements about changes that affect downstream within their upstream channels only and then they're surprised that they're not getting any feedback. But we can't just be everywhere. Downstream developers from distributions like Debian and Gentoo try to contribute as much as they can, but we don't have the manpower to be everywhere.
What frustrates me is that IBM engineers could perfectly take care of the other PowerPC ports besides ppc64el like they already do in GCC and the kernel. But apparently the management side has decided that older PowerPC targets deserve no attention, so these ports and the people maintaining them downstream end up getting under pressure.
Well, the first message that reached downstream regarding this issue was the threat of demotion and not the question to ask for help resolving these issues. So, maybe you can understand the frustration a bit.
apiraino commentedon Sep 10, 2026
I was the one that took the initiative to talk about demoting this target (in rust-lang/compiler-team#1035) so I am in part responsible for the confusion, for which I apologize.
As discussed on Zulip we (Rust project) try to balance maintenance reality and downstream expectations. I think we have enough evidence that demoting the target would create concrete inconveniences downstream, so I will retract the proposal.
Last but not least, thank you @glaubitz for your hard work in the Debian project and for taking the time to interface with us as well!
mattst88 commentedon Sep 14, 2026
I think I have a fix. I'll try to clean it up and add some tests.
tgross35 commentedon Sep 15, 2026
It looks like you filed a Clang fix (thank you!), but per #162011 (comment) isn't Clang already doing the right thing?
beetrees commentedon Sep 15, 2026
Clang seems to have this bug only with unions containing a single element (e.g.
union { float a; }). This original bug report example is a union with two elements (e.g.union { float a; float b; }), which Rust doesn't handle correctly but Clang does.mattst88 commentedon Sep 15, 2026
For the reported case, yes. Clang gets single-member unions wrong, though.
The spec lists unions separately from aggregates everywhere ("Aggregates and Unions" in 3.1.6, "aggregates and unions passed by value" in 3.2.3), and the FPR rule only mentions "one member aggregates". So a union should never be passed in an FPR, even if it has one field. GCC does this. Clang unwraps single-member unions:
union { float a; float b; }struct { union { float a; float b; } u; }union { float a; }struct { union { float a; } u; }union { struct { float a; } s; }It's the same with
double,long doubleand 128-bit vector members. In Clang this comes fromisSingleElementStructaccepting unions; llvm/llvm-project#223481 fixes that for ELFv1.My rustc change never unwraps a union on ELFv1, so it matches GCC in all of these cases (and Clang once that PR lands). It does change rustc's ABI for single-member unions.
folkertdev commentedon Sep 15, 2026
I look forward to seeing this. Does that mean you don't use
homogenous_aggregateat all on elfv1? That function is causing issues on some other targets (where an empty array should disqualify an aggregate) so it needs some work.mattst88 commentedon Sep 20, 2026
Sorry, took a while to get the tests done.
Rollup merge of rust-lang#163076 - mattst88:powerpc64-elfv1-union-abi…
Unrolled build for #163076 in rollup 163296