rust-lang / rust-lang/rust

ABI mismatch on powerpc64 (elfv1) for union containing floats

Open
#162,011 17 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-ABI C-bug I-miscompile O-PowerPC P-high T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

with

https://godbolt.org/z/EYxKxTs4f

// --target=powerpc64-unknown-linux-gnu -Copt-level=3
#[repr(C)] pub union TwoFloats { a: f32, b: f32 }

#[unsafe(no_mangle)]
extern "C" fn foo(x: TwoFloats) -> f32 {
    unsafe { x.a }
}

rustc emits

foo:
        .quad   .Lfunc_begin0
        .quad   .TOC.@tocbase
        .quad   0
.Lfunc_begin0:
        blr

I.e. the argument is already in a float register, and it stays there for the return. But with GCC and Clang the equivalent

https://godbolt.org/z/Mx8GEzdvn

typedef union { float a; float b; } TwoFloats;

float foo(TwoFloats x) {
    return x.a;
}

Has an explicit move from GPR to memory to FPR

foo:
        .quad   .Lfunc_begin0
        .quad   .TOC.@tocbase
        .quad   0
.Lfunc_begin0:
        stw 3, -4(1)
        lfs 1, -4(1)
        blr

You can see this difference in the LLVM IR emitted by rustc and clang too:

; rust 
define noundef float @foo(float returned %0) unnamed_addr {
start:
  ret float %0
}

; clang
define dso_local float @foo(i32 %x.coerce) local_unnamed_addr {
entry:
  %0 = bitcast i32 %x.coerce to float
  ret float %0
}

This came up in relation to https://github.com/rust-lang/rust/pull/161987.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the rustc invocation for the powerpc64-unknown-linux-gnu target and inspect the emitted LLVM IR, then compare it with the linked Clang output. Trace how the union argument and return value are lowered for the elfv1 ABI; done means the generated ABI matches the C compiler's register and coercion behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.