about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPetr Sumbera <petr.sumbera@oracle.com>2021-12-01 10:03:45 +0100
committerPetr Sumbera <petr.sumbera@oracle.com>2021-12-01 10:03:45 +0100
commit128ceec92d04a9b4feaf55804f5e7d1f3f1dbfd2 (patch)
treeafa1955bbcb51551f1f90ee250ed5f70cab58659 /src
parent6414e0b5b308d3ae27da83c6a25098cc8aadc1a9 (diff)
downloadrust-128ceec92d04a9b4feaf55804f5e7d1f3f1dbfd2.tar.gz
rust-128ceec92d04a9b4feaf55804f5e7d1f3f1dbfd2.zip
fix sparc64 ABI for aggregates with floating point members
Diffstat (limited to 'src')
-rw-r--r--src/test/assembly/sparc-struct-abi.rs64
-rw-r--r--src/test/codegen/sparc-struct-abi.rs58
2 files changed, 121 insertions, 1 deletions
diff --git a/src/test/assembly/sparc-struct-abi.rs b/src/test/assembly/sparc-struct-abi.rs
new file mode 100644
index 00000000000..dd8e6f614df
--- /dev/null
+++ b/src/test/assembly/sparc-struct-abi.rs
@@ -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);
+}
diff --git a/src/test/codegen/sparc-struct-abi.rs b/src/test/codegen/sparc-struct-abi.rs
index f228d7c5500..b531dba4607 100644
--- a/src/test/codegen/sparc-struct-abi.rs
+++ b/src/test/codegen/sparc-struct-abi.rs
@@ -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 }
+}