Skip to content

extern "C" fn on mips64 targets does not respect repr(transparent) #115404

Open

Description

@RalfJung

This is the MIPS version of #115336: on the target mips64-unknown-linux-gnuabi64, all arrays and some tuple types like (i32, f32, i64, f64) have a different ABI when being wrapped in repr(transparent) wrappers, and hence this fails the test I added in #115372.

For instance for [u8; 2], the PassMode becomes

                   mode: Indirect {
                       attrs: ArgAttributes {
                           regular: NoAlias | NoCapture | NonNull | NoUndef,
                           arg_ext: None,
                           pointee_size: Size(2 bytes),
                           pointee_align: Some(
                               Align(1 bytes),
                           ),
                       },
                       extra_attrs: None,
                       on_stack: false,
                   },

But for Wrapper<[u8; 2]> it becomes

                   mode: Cast(
                       CastTarget {
                           prefix: [
                               None,
                               None,
                               None,
                               None,
                               None,
                               None,
                               None,
                               None,
                           ],
                           rest: Uniform {
                               unit: Reg {
                                   kind: Integer,
                                   size: Size(8 bytes),
                               },
                               total: Size(2 bytes),
                           },
                           attrs: ArgAttributes {
                               regular: (empty),
                               arg_ext: None,
                               pointee_size: Size(0 bytes),
                               pointee_align: None,
                           },
                       },
                       false,
                   ),

This also affects mips64el-unknown-linux-gnuabi64, mips64-openwrt-linux-musl, mips64-unknown-linux-muslabi64, mips64el-unknown-linux-muslabi64
Cc @Itus-Shield (listed as maintainer for the openwrt target)

Activity

  1. added
    O-MIPSTarget: MIPS processors
    I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness
    on Aug 31, 2023
  2. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Aug 31, 2023
  3. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    A-ABIArea: Concerning the application binary interface (ABI)
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Aug 31, 2023
  4. RalfJung commented on Aug 31, 2023

    @RalfJung
    MemberAuthor

    As per #115238, all affected targets are tier 3 targets.

  5. apiraino commented on Sep 4, 2023

    @apiraino
    Contributor

    WG-prioritization assigning priority (Zulip discussion).

    @rustbot label -I-prioritize +P-low

  6. added
    P-lowLow priority
    and removed
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Sep 4, 2023
  7. RalfJung commented on Sep 6, 2023

    @RalfJung
    MemberAuthor

    Here's another example of a repr(transparent) violation on mips64, orthogonal to the first:

    struct T(f64, f64, f64);
    struct Wrap<T>(T);
    
    #[rustc_abi(assert_eq)]
    type Test = (extern "C" fn(T), extern "C" fn(Wrap<T>));

    T gets passed in 3 float registers, but Wrap<T> is passed in 3 integer registers. The problem is that this search here doesn't recurse into fields of nested structs.

    (I don't know what the C ABI says for this target, i.e. whether it is truly only double fields that appear directly in the struct type that should be passed in registers, and any doubles in nested fields-of-fields really should be ignored. So there might also be an ABI incompatibility with C here.)

  8. RalfJung commented on Sep 8, 2023

    @RalfJung
    MemberAuthor

    I'm also seeing this target use PassMode::Cast for unsized types... that makes no sense, right?

  9. bjorn3 commented on Sep 8, 2023

    @bjorn3
    Member

    Yeah, unsized args should always be passed as PassMode::Indirect with on_stack=false.

  10. RalfJung commented on Aug 30, 2026

    @RalfJung
    MemberAuthor

    There are more cases where mips is wrong:

    #[repr(C)]
    struct ReprC<T>(T);

    With that declaration, ReprC<f32> behaves incorrectly when wrapped in a repr(transparent) wrapper. See the test in #161991.

    But apparently nobody cares about MIPS enough to fix critical ABI issues. It's been 3 years. All the other targets got fixed. MIPS is clearly unmaintained and broken. Even tier 3 targets require a target maintainer, so IMO MIPS should be removed.

  11. beetrees commented on Aug 30, 2026

    @beetrees
    Contributor

    While mips64{,el}-unknown-linux-gnuabi64 don't have target maintainers, several other 64-bit MIPS target do. Specifically:

    This issue has been on my TODO pile for a while, so I'll take a look now: @rustbot claim

  12. Gelbpunkt commented on Aug 30, 2026

    @Gelbpunkt
    Contributor

    Thanks for the ping. Generally speaking I'm happy to look into MIPS ABI issues, but I wasn't listed as a maintainer for the target at the time that this issue was opened (and it seems like some people only look at the -gnu targets for finding maintainers). Please feel free to ping me on MIPS ABI issues. I make use of Rust on mips64 quite a bit, but haven't encountered any noticeable issues so far beyond what I've already fixed previously, so I did not have issues like this one on my radar.

  13. folkertdev commented on Aug 30, 2026

    @folkertdev
    Contributor

    We've also had good success with fixing a variety of Clang/LLVM bugs in LLVM 23 and LLVM 24, and the targets are straightforward to cross compile to and run with qemu (which cannot be said for some other targets that we have, that also have glaring ABI issues).

    So, the situation seems fine to me actually, and this bug looks straightforward to fix (especially now that we have decent testing infrastructure). Just a matter of nerdsniping the right person.

  14. RalfJung commented on Aug 30, 2026

    @RalfJung
    MemberAuthor

    In terms of repr(transparent) issues, mips64 is the only target I am aware of that has glaring issues. And we've had the cross-testing infrastructure for that for 3 years, that's how I found these problems in the first place.

    But, if there are people caring about the target and willing to look into it, it's all good. :)
    When I opened the issue indeed there wasn't anyone to ping for most of the mips targets.

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

Metadata

Metadata

Assignees

Labels

A-ABIArea: Concerning the application binary interface (ABI)A-FFIArea: Foreign function interface (FFI)I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-MIPSTarget: MIPS processorsP-lowLow priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions