fix sparc64 ABI for aggregates with floating point members
This commit is contained in:
parent
6414e0b5b3
commit
128ceec92d
8 changed files with 272 additions and 58 deletions
64
src/test/assembly/sparc-struct-abi.rs
Normal file
64
src/test/assembly/sparc-struct-abi.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// Test SPARC64 ABI
|
||||
// - float structure members are passes in floating point registers
|
||||
// (#86163)
|
||||
|
||||
// assembly-output: emit-asm
|
||||
// needs-llvm-components: sparc
|
||||
// compile-flags: --target=sparcv9-sun-solaris -Copt-level=3
|
||||
#![crate_type = "lib"]
|
||||
#![feature(no_core, lang_items)]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Franta {
|
||||
a: f32,
|
||||
b: f32,
|
||||
c: f32,
|
||||
d: f32,
|
||||
}
|
||||
|
||||
// NB: due to delay slots the `ld` following the call is actually executed before the call.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn callee(arg: Franta) {
|
||||
// CHECK-LABEL: callee:
|
||||
// CHECK: st %f3, [[PLACE_D:.*]]
|
||||
// CHECK: st %f2, [[PLACE_C:.*]]
|
||||
// CHECK: st %f1, [[PLACE_B:.*]]
|
||||
// CHECK: st %f0, [[PLACE_A:.*]]
|
||||
// CHECK: call tst_use
|
||||
// CHECK-NEXT: ld [[PLACE_A]], %f1
|
||||
// CHECK: call tst_use
|
||||
// CHECK-NEXT: ld [[PLACE_B]], %f1
|
||||
// CHECK: call tst_use
|
||||
// CHECK-NEXT: ld [[PLACE_C]], %f1
|
||||
// CHECK: call tst_use
|
||||
// CHECK-NEXT: ld [[PLACE_D]], %f1
|
||||
clobber();
|
||||
tst_use(arg.a);
|
||||
tst_use(arg.b);
|
||||
tst_use(arg.c);
|
||||
tst_use(arg.d);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn opaque_callee(arg: Franta, intarg: i32);
|
||||
fn tst_use(arg: f32);
|
||||
fn clobber();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn caller() {
|
||||
// CHECK-LABEL: caller:
|
||||
// CHECK: ld [{{.*}}], %f0
|
||||
// CHECK: ld [{{.*}}], %f1
|
||||
// CHECK: ld [{{.*}}], %f2
|
||||
// CHECK: ld [{{.*}}], %f3
|
||||
// CHECK: call opaque_callee
|
||||
// CHECK: mov 3, %o2
|
||||
opaque_callee(Franta { a: 1.0, b: 2.0, c: 3.0, d: 4.0 }, 3);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Checks that we correctly codegen extern "C" functions returning structs.
|
||||
// See issue #52638.
|
||||
// See issues #52638 and #86163.
|
||||
|
||||
// compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib
|
||||
// needs-llvm-components: sparc
|
||||
|
|
@ -25,3 +25,59 @@ pub struct Bool {
|
|||
pub extern "C" fn structbool() -> Bool {
|
||||
Bool { b: true }
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
pub struct BoolFloat {
|
||||
b: bool,
|
||||
f: f32,
|
||||
}
|
||||
|
||||
// CHECK: define inreg { i32, float } @structboolfloat()
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: ret { i32, float } { i32 16777216, float 0x40091EB860000000 }
|
||||
#[no_mangle]
|
||||
pub extern "C" fn structboolfloat() -> BoolFloat {
|
||||
BoolFloat { b: true, f: 3.14 }
|
||||
}
|
||||
|
||||
// CHECK: define void @structboolfloat_input({ i32, float } inreg %0)
|
||||
// CHECK-NEXT: start:
|
||||
#[no_mangle]
|
||||
pub extern "C" fn structboolfloat_input(a: BoolFloat) { }
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ShortDouble {
|
||||
s: i16,
|
||||
d: f64,
|
||||
}
|
||||
|
||||
// CHECK: define { i64, double } @structshortdouble()
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: ret { i64, double } { i64 34621422135410688, double 3.140000e+00 }
|
||||
#[no_mangle]
|
||||
pub extern "C" fn structshortdouble() -> ShortDouble {
|
||||
ShortDouble { s: 123, d: 3.14 }
|
||||
}
|
||||
|
||||
// CHECK: define void @structshortdouble_input({ i64, double } %0)
|
||||
// CHECK-NEXT: start:
|
||||
#[no_mangle]
|
||||
pub extern "C" fn structshortdouble_input(a: ShortDouble) { }
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FloatLongFloat {
|
||||
f: f32,
|
||||
i: i64,
|
||||
g: f32,
|
||||
}
|
||||
|
||||
// CHECK: define inreg { float, i32, i64, float, i32 } @structfloatlongfloat()
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: ret { float, i32, i64, float, i32 } { float 0x3FB99999A0000000, i32 undef, i64 123, float 0x40091EB860000000, i32 undef }
|
||||
#[no_mangle]
|
||||
pub extern "C" fn structfloatlongfloat() -> FloatLongFloat {
|
||||
FloatLongFloat { f: 0.1, i: 123, g: 3.14 }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue