about summary refs log tree commit diff
path: root/tests/assembly-llvm/riscv-float-struct-abi.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/assembly-llvm/riscv-float-struct-abi.rs')
-rw-r--r--tests/assembly-llvm/riscv-float-struct-abi.rs177
1 files changed, 177 insertions, 0 deletions
diff --git a/tests/assembly-llvm/riscv-float-struct-abi.rs b/tests/assembly-llvm/riscv-float-struct-abi.rs
new file mode 100644
index 00000000000..5d9ac9d70b8
--- /dev/null
+++ b/tests/assembly-llvm/riscv-float-struct-abi.rs
@@ -0,0 +1,177 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu
+//@ needs-llvm-components: riscv
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+#[repr(C, align(64))]
+struct Aligned(f64);
+
+#[repr(C)]
+struct Padded(u8, Aligned);
+
+#[repr(C, packed)]
+struct Packed(u8, f32);
+
+impl Copy for Aligned {}
+impl Copy for Padded {}
+impl Copy for Packed {}
+
+extern "C" {
+    fn take_padded(x: Padded);
+    fn get_padded() -> Padded;
+    fn take_packed(x: Packed);
+    fn get_packed() -> Packed;
+}
+
+// CHECK-LABEL: pass_padded
+#[unsafe(no_mangle)]
+extern "C" fn pass_padded(out: &mut Padded, x: Padded) {
+    // CHECK: sb a1, 0(a0)
+    // CHECK-NEXT: fsd fa0, 64(a0)
+    // CHECK-NEXT: ret
+    *out = x;
+}
+
+// CHECK-LABEL: ret_padded
+#[unsafe(no_mangle)]
+extern "C" fn ret_padded(x: &Padded) -> Padded {
+    // CHECK: fld fa0, 64(a0)
+    // CHECK-NEXT: lbu a0, 0(a0)
+    // CHECK-NEXT: ret
+    *x
+}
+
+#[unsafe(no_mangle)]
+extern "C" fn call_padded(x: &Padded) {
+    // CHECK: fld fa0, 64(a0)
+    // CHECK-NEXT: lbu a0, 0(a0)
+    // CHECK-NEXT: tail take_padded
+    unsafe {
+        take_padded(*x);
+    }
+}
+
+#[unsafe(no_mangle)]
+extern "C" fn receive_padded(out: &mut Padded) {
+    // CHECK: addi sp, sp, -16
+    // CHECK-NEXT: .cfi_def_cfa_offset 16
+    // CHECK-NEXT: sd ra, [[#%d,RA_SPILL:]](sp)
+    // CHECK-NEXT: sd [[TEMP:.*]], [[#%d,TEMP_SPILL:]](sp)
+    // CHECK-NEXT: .cfi_offset ra, [[#%d,RA_SPILL - 16]]
+    // CHECK-NEXT: .cfi_offset [[TEMP]], [[#%d,TEMP_SPILL - 16]]
+    // CHECK-NEXT: mv [[TEMP]], a0
+    // CHECK-NEXT: call get_padded
+    // CHECK-NEXT: sb a0, 0([[TEMP]])
+    // CHECK-NEXT: fsd fa0, 64([[TEMP]])
+    // CHECK-NEXT: ld ra, [[#%d,RA_SPILL]](sp)
+    // CHECK-NEXT: ld [[TEMP]], [[#%d,TEMP_SPILL]](sp)
+    // CHECK: addi sp, sp, 16
+    // CHECK: ret
+    unsafe {
+        *out = get_padded();
+    }
+}
+
+// CHECK-LABEL: pass_packed
+#[unsafe(no_mangle)]
+extern "C" fn pass_packed(out: &mut Packed, x: Packed) {
+    // CHECK: addi sp, sp, -16
+    // CHECK-NEXT: .cfi_def_cfa_offset 16
+    // CHECK-NEXT: sb a1, 0(a0)
+    // CHECK-NEXT: fsw fa0, 8(sp)
+    // CHECK-NEXT: lw [[VALUE:.*]], 8(sp)
+    // CHECK-DAG: srli [[BYTE4:.*]], [[VALUE]], 24
+    // CHECK-DAG: srli [[BYTE3:.*]], [[VALUE]], 16
+    // CHECK-DAG: srli [[BYTE2:.*]], [[VALUE]], 8
+    // CHECK-DAG: sb [[VALUE]], 1(a0)
+    // CHECK-DAG: sb [[BYTE2]], 2(a0)
+    // CHECK-DAG: sb [[BYTE3]], 3(a0)
+    // CHECK-DAG: sb [[BYTE4]], 4(a0)
+    // CHECK-NEXT: addi sp, sp, 16
+    // CHECK: ret
+    *out = x;
+}
+
+// CHECK-LABEL: ret_packed
+#[unsafe(no_mangle)]
+extern "C" fn ret_packed(x: &Packed) -> Packed {
+    // CHECK: addi sp, sp, -16
+    // CHECK-NEXT: .cfi_def_cfa_offset 16
+    // CHECK-NEXT: lbu [[BYTE2:.*]], 2(a0)
+    // CHECK-NEXT: lbu [[BYTE1:.*]], 1(a0)
+    // CHECK-NEXT: lbu [[BYTE3:.*]], 3(a0)
+    // CHECK-NEXT: lbu [[BYTE4:.*]], 4(a0)
+    // CHECK-NEXT: slli [[SHIFTED2:.*]], [[BYTE2]], 8
+    // CHECK-NEXT: or [[BYTE12:.*]], [[SHIFTED2]], [[BYTE1]]
+    // CHECK-NEXT: slli [[SHIFTED3:.*]], [[BYTE3]], 16
+    // CHECK-NEXT: slli [[SHIFTED4:.*]], [[BYTE4]], 24
+    // CHECK-NEXT: or [[BYTE34:.*]], [[SHIFTED3]], [[SHIFTED4]]
+    // CHECK-NEXT: or [[VALUE:.*]], [[BYTE12]], [[BYTE34]]
+    // CHECK-NEXT: sw [[VALUE]], 8(sp)
+    // CHECK-NEXT: flw fa0, 8(sp)
+    // CHECK-NEXT: lbu a0, 0(a0)
+    // CHECK-NEXT: addi sp, sp, 16
+    // CHECK: ret
+    *x
+}
+
+#[unsafe(no_mangle)]
+extern "C" fn call_packed(x: &Packed) {
+    // CHECK: addi sp, sp, -16
+    // CHECK-NEXT: .cfi_def_cfa_offset 16
+    // CHECK-NEXT: lbu [[BYTE2:.*]], 2(a0)
+    // CHECK-NEXT: lbu [[BYTE1:.*]], 1(a0)
+    // CHECK-NEXT: lbu [[BYTE3:.*]], 3(a0)
+    // CHECK-NEXT: lbu [[BYTE4:.*]], 4(a0)
+    // CHECK-NEXT: slli [[SHIFTED2:.*]], [[BYTE2]], 8
+    // CHECK-NEXT: or [[BYTE12:.*]], [[SHIFTED2]], [[BYTE1]]
+    // CHECK-NEXT: slli [[SHIFTED3:.*]], [[BYTE3]], 16
+    // CHECK-NEXT: slli [[SHIFTED4:.*]], [[BYTE4]], 24
+    // CHECK-NEXT: or [[BYTE34:.*]], [[SHIFTED3]], [[SHIFTED4]]
+    // CHECK-NEXT: or [[VALUE:.*]], [[BYTE12]], [[BYTE34]]
+    // CHECK-NEXT: sw [[VALUE]], 8(sp)
+    // CHECK-NEXT: flw fa0, 8(sp)
+    // CHECK-NEXT: lbu a0, 0(a0)
+    // CHECK-NEXT: addi sp, sp, 16
+    // CHECK: tail take_packed
+    unsafe {
+        take_packed(*x);
+    }
+}
+
+#[unsafe(no_mangle)]
+extern "C" fn receive_packed(out: &mut Packed) {
+    // CHECK: addi sp, sp, -32
+    // CHECK-NEXT: .cfi_def_cfa_offset 32
+    // CHECK-NEXT: sd ra, [[#%d,RA_SPILL:]](sp)
+    // CHECK-NEXT: sd [[TEMP:.*]], [[#%d,TEMP_SPILL:]](sp)
+    // CHECK-NEXT: .cfi_offset ra, [[#%d,RA_SPILL - 32]]
+    // CHECK-NEXT: .cfi_offset [[TEMP]], [[#%d,TEMP_SPILL - 32]]
+    // CHECK-NEXT: mv [[TEMP]], a0
+    // CHECK-NEXT: call get_packed
+    // CHECK-NEXT: sb a0, 0([[TEMP]])
+    // CHECK-NEXT: fsw fa0, [[FLOAT_SPILL:.*]](sp)
+    // CHECK-NEXT: lw [[VALUE:.*]], [[FLOAT_SPILL]](sp)
+    // CHECK-DAG: srli [[BYTE4:.*]], [[VALUE]], 24
+    // CHECK-DAG: srli [[BYTE3:.*]], [[VALUE]], 16
+    // CHECK-DAG: srli [[BYTE2:.*]], [[VALUE]], 8
+    // CHECK-DAG: sb [[VALUE]], 1([[TEMP]])
+    // CHECK-DAG: sb [[BYTE2]], 2([[TEMP]])
+    // CHECK-DAG: sb [[BYTE3]], 3([[TEMP]])
+    // CHECK-DAG: sb [[BYTE4]], 4([[TEMP]])
+    // CHECK-NEXT: ld ra, [[#%d,RA_SPILL]](sp)
+    // CHECK-NEXT: ld [[TEMP]], [[#%d,TEMP_SPILL]](sp)
+    // CHECK: addi sp, sp, 32
+    // CHECK: ret
+    unsafe {
+        *out = get_packed();
+    }
+}