From 218caa410aa38c29984be31a5229b9fa717560ee Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:13 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- tests/codegen/riscv-abi/call-llvm-intrinsics.rs | 30 +++ .../riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs | 189 +++++++++++++ tests/codegen/riscv-abi/riscv64-lp64d-abi.rs | 293 +++++++++++++++++++++ tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs | 277 +++++++++++++++++++ 4 files changed, 789 insertions(+) create mode 100644 tests/codegen/riscv-abi/call-llvm-intrinsics.rs create mode 100644 tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs create mode 100644 tests/codegen/riscv-abi/riscv64-lp64d-abi.rs create mode 100644 tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs (limited to 'tests/codegen/riscv-abi') diff --git a/tests/codegen/riscv-abi/call-llvm-intrinsics.rs b/tests/codegen/riscv-abi/call-llvm-intrinsics.rs new file mode 100644 index 000000000..31a88f2c0 --- /dev/null +++ b/tests/codegen/riscv-abi/call-llvm-intrinsics.rs @@ -0,0 +1,30 @@ +// compile-flags: -C no-prepopulate-passes + +// only-riscv64 + +#![feature(link_llvm_intrinsics)] +#![crate_type = "lib"] + +struct A; + +impl Drop for A { + fn drop(&mut self) { + println!("A"); + } +} + +extern "C" { + #[link_name = "llvm.sqrt.f32"] + fn sqrt(x: f32) -> f32; +} + +pub fn do_call() { + let _a = A; + + unsafe { + // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them + // CHECK: store float 4.000000e+00, float* %{{.}}, align 4 + // CHECK: call float @llvm.sqrt.f32(float %{{.}} + sqrt(4.0); + } +} diff --git a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs new file mode 100644 index 000000000..045f01985 --- /dev/null +++ b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs @@ -0,0 +1,189 @@ +// compile-flags: --target riscv64gc-unknown-linux-gnu -O -C no-prepopulate-passes +// needs-llvm-components: riscv + +#![crate_type = "lib"] +#![no_core] +#![feature(no_core, lang_items)] +#![allow(improper_ctypes)] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for bool {} +impl Copy for i8 {} +impl Copy for u8 {} +impl Copy for i32 {} +impl Copy for i64 {} +impl Copy for u64 {} +impl Copy for f32 {} +impl Copy for f64 {} + +// CHECK: define void @f_void() +#[no_mangle] +pub extern "C" fn f_void() {} + +// CHECK: define noundef zeroext i1 @f_scalar_0(i1 noundef zeroext %a) +#[no_mangle] +pub extern "C" fn f_scalar_0(a: bool) -> bool { + a +} + +// CHECK: define noundef signext i8 @f_scalar_1(i8 noundef signext %x) +#[no_mangle] +pub extern "C" fn f_scalar_1(x: i8) -> i8 { + x +} + +// CHECK: define noundef zeroext i8 @f_scalar_2(i8 noundef zeroext %x) +#[no_mangle] +pub extern "C" fn f_scalar_2(x: u8) -> u8 { + x +} + +// CHECK: define noundef signext i32 @f_scalar_3(i32 noundef signext %x) +#[no_mangle] +pub extern "C" fn f_scalar_3(x: i32) -> u32 { + x as u32 +} + +// CHECK: define noundef i64 @f_scalar_4(i64 noundef %x) +#[no_mangle] +pub extern "C" fn f_scalar_4(x: i64) -> i64 { + x +} + +// CHECK: define float @f_fp_scalar_1(float %0) +#[no_mangle] +pub extern "C" fn f_fp_scalar_1(x: f32) -> f32 { + x +} +// CHECK: define double @f_fp_scalar_2(double %0) +#[no_mangle] +pub extern "C" fn f_fp_scalar_2(x: f64) -> f64 { + x +} + +#[repr(C)] +pub struct Empty {} + +// CHECK: define void @f_agg_empty_struct() +#[no_mangle] +pub extern "C" fn f_agg_empty_struct(e: Empty) -> Empty { + e +} + +#[repr(C)] +pub struct Tiny { + a: u16, + b: u16, + c: u16, + d: u16, +} + +// CHECK: define void @f_agg_tiny(i64 %0) +#[no_mangle] +pub extern "C" fn f_agg_tiny(mut e: Tiny) { +} + +// CHECK: define i64 @f_agg_tiny_ret() +#[no_mangle] +pub extern "C" fn f_agg_tiny_ret() -> Tiny { + Tiny { a: 1, b: 2, c: 3, d: 4 } +} + +#[repr(C)] +pub struct Small { + a: i64, + b: *mut i64, +} + +// CHECK: define void @f_agg_small([2 x i64] %0) +#[no_mangle] +pub extern "C" fn f_agg_small(mut x: Small) { +} + +// CHECK: define [2 x i64] @f_agg_small_ret() +#[no_mangle] +pub extern "C" fn f_agg_small_ret() -> Small { + Small { a: 1, b: 0 as *mut _ } +} + +#[repr(C)] +pub struct SmallAligned { + a: i128, +} + +// CHECK: define void @f_agg_small_aligned(i128 %0) +#[no_mangle] +pub extern "C" fn f_agg_small_aligned(mut x: SmallAligned) { +} + +#[repr(C)] +pub struct Large { + a: i64, + b: i64, + c: i64, + d: i64, +} + +// CHECK: define void @f_agg_large({{%Large\*|ptr}} {{.*}}%x) +#[no_mangle] +pub extern "C" fn f_agg_large(mut x: Large) { +} + +// CHECK: define void @f_agg_large_ret({{%Large\*|ptr}} {{.*}}sret{{.*}}, i32 noundef signext %i, i8 noundef signext %j) +#[no_mangle] +pub extern "C" fn f_agg_large_ret(i: i32, j: i8) -> Large { + Large { a: 1, b: 2, c: 3, d: 4 } +} + +// CHECK: define void @f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, {{%Large\*|ptr}} {{.*}}%d, i8 noundef zeroext %e, i8 noundef signext %f, i8 noundef %g, i8 noundef %h) +#[no_mangle] +pub extern "C" fn f_scalar_stack_1( + a: Tiny, + b: Small, + c: SmallAligned, + d: Large, + e: u8, + f: i8, + g: u8, + h: i8, +) { +} + +// CHECK: define void @f_scalar_stack_2({{%Large\*|ptr}} {{.*}}sret{{.*}} %0, i64 noundef %a, i128 %1, i128 %2, i64 noundef %d, i8 noundef zeroext %e, i8 noundef %f, i8 noundef %g) +#[no_mangle] +pub extern "C" fn f_scalar_stack_2( + a: u64, + b: SmallAligned, + c: SmallAligned, + d: u64, + e: u8, + f: i8, + g: u8, +) -> Large { + Large { a: a as i64, b: e as i64, c: f as i64, d: g as i64 } +} + +extern "C" { + fn f_va_callee(_: i32, ...) -> i32; +} + +#[no_mangle] +pub unsafe extern "C" fn f_va_caller() { + // CHECK: call noundef signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i64 noundef 3, double {{.*}}, double {{.*}}, i64 {{.*}}, [2 x i64] {{.*}}, i128 {{.*}}, {{%Large\*|ptr}} {{.*}}) + f_va_callee( + 1, + 2i32, + 3i64, + 4.0f64, + 5.0f64, + Tiny { a: 1, b: 2, c: 3, d: 4 }, + Small { a: 10, b: 0 as *mut _ }, + SmallAligned { a: 11 }, + Large { a: 12, b: 13, c: 14, d: 15 }, + ); + // CHECK: call noundef signext i32 (i32, ...) @f_va_callee(i32 noundef signext 1, i32 noundef signext 2, i32 noundef signext 3, i32 noundef signext 4, i128 {{.*}}, i32 noundef signext 6, i32 noundef signext 7, i32 noundef 8, i32 noundef 9) + f_va_callee(1, 2i32, 3i32, 4i32, SmallAligned { a: 5 }, 6i32, 7i32, 8i32, 9i32); +} diff --git a/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs new file mode 100644 index 000000000..1555acadf --- /dev/null +++ b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs @@ -0,0 +1,293 @@ +// +// compile-flags: -C no-prepopulate-passes +// only-riscv64 +// only-linux +#![crate_type = "lib"] + +// CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 zeroext %i) +#[no_mangle] +pub extern "C" fn f_fpr_tracking( + a: f64, + b: f64, + c: f64, + d: f64, + e: f64, + f: f64, + g: f64, + h: f64, + i: u8, +) { +} + +#[repr(C)] +pub struct Double { + f: f64, +} + +#[repr(C)] +pub struct DoubleDouble { + f: f64, + g: f64, +} + +#[repr(C)] +pub struct DoubleFloat { + f: f64, + g: f32, +} + +// CHECK: define void @f_double_s_arg(double %0) +#[no_mangle] +pub extern "C" fn f_double_s_arg(a: Double) {} + +// CHECK: define double @f_ret_double_s() +#[no_mangle] +pub extern "C" fn f_ret_double_s() -> Double { + Double { f: 1. } +} + +// CHECK: define void @f_double_double_s_arg({ double, double } %0) +#[no_mangle] +pub extern "C" fn f_double_double_s_arg(a: DoubleDouble) {} + +// CHECK: define { double, double } @f_ret_double_double_s() +#[no_mangle] +pub extern "C" fn f_ret_double_double_s() -> DoubleDouble { + DoubleDouble { f: 1., g: 2. } +} + +// CHECK: define void @f_double_float_s_arg({ double, float } %0) +#[no_mangle] +pub extern "C" fn f_double_float_s_arg(a: DoubleFloat) {} + +// CHECK: define { double, float } @f_ret_double_float_s() +#[no_mangle] +pub extern "C" fn f_ret_double_float_s() -> DoubleFloat { + DoubleFloat { f: 1., g: 2. } +} + +// CHECK: define void @f_double_double_s_arg_insufficient_fprs(double %0, double %1, double %2, double %3, double %4, double %5, double %6, [2 x i64] %7) +#[no_mangle] +pub extern "C" fn f_double_double_s_arg_insufficient_fprs( + a: f64, + b: f64, + c: f64, + d: f64, + e: f64, + f: f64, + g: f64, + h: DoubleDouble, +) { +} + +#[repr(C)] +pub struct DoubleInt8 { + f: f64, + i: i8, +} + +#[repr(C)] +pub struct DoubleUInt8 { + f: f64, + i: u8, +} + +#[repr(C)] +pub struct DoubleInt32 { + f: f64, + i: i32, +} + +#[repr(C)] +pub struct DoubleInt64 { + f: f64, + i: i64, +} + +// CHECK: define void @f_double_int8_s_arg({ double, i8 } %0) +#[no_mangle] +pub extern "C" fn f_double_int8_s_arg(a: DoubleInt8) {} + +// CHECK: define { double, i8 } @f_ret_double_int8_s() +#[no_mangle] +pub extern "C" fn f_ret_double_int8_s() -> DoubleInt8 { + DoubleInt8 { f: 1., i: 2 } +} + +// CHECK: define void @f_double_int32_s_arg({ double, i32 } %0) +#[no_mangle] +pub extern "C" fn f_double_int32_s_arg(a: DoubleInt32) {} + +// CHECK: define { double, i32 } @f_ret_double_int32_s() +#[no_mangle] +pub extern "C" fn f_ret_double_int32_s() -> DoubleInt32 { + DoubleInt32 { f: 1., i: 2 } +} + +// CHECK: define void @f_double_uint8_s_arg({ double, i8 } %0) +#[no_mangle] +pub extern "C" fn f_double_uint8_s_arg(a: DoubleUInt8) {} + +// CHECK: define { double, i8 } @f_ret_double_uint8_s() +#[no_mangle] +pub extern "C" fn f_ret_double_uint8_s() -> DoubleUInt8 { + DoubleUInt8 { f: 1., i: 2 } +} + +// CHECK: define void @f_double_int64_s_arg({ double, i64 } %0) +#[no_mangle] +pub extern "C" fn f_double_int64_s_arg(a: DoubleInt64) {} + +// CHECK: define { double, i64 } @f_ret_double_int64_s() +#[no_mangle] +pub extern "C" fn f_ret_double_int64_s() -> DoubleInt64 { + DoubleInt64 { f: 1., i: 2 } +} + +// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, [2 x i64] %0) +#[no_mangle] +pub extern "C" fn f_double_int8_s_arg_insufficient_gprs( + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: DoubleInt8, +) { +} + +// CHECK: define void @f_struct_double_int8_insufficient_fprs(float %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, [2 x i64] %8) +#[no_mangle] +pub extern "C" fn f_struct_double_int8_insufficient_fprs( + a: f32, + b: f64, + c: f64, + d: f64, + e: f64, + f: f64, + g: f64, + h: f64, + i: DoubleInt8, +) { +} + +#[repr(C)] +pub struct DoubleArr1 { + a: [f64; 1], +} + +// CHECK: define void @f_doublearr1_s_arg(double %0) +#[no_mangle] +pub extern "C" fn f_doublearr1_s_arg(a: DoubleArr1) {} + +// CHECK: define double @f_ret_doublearr1_s() +#[no_mangle] +pub extern "C" fn f_ret_doublearr1_s() -> DoubleArr1 { + DoubleArr1 { a: [1.] } +} + +#[repr(C)] +pub struct DoubleArr2 { + a: [f64; 2], +} + +// CHECK: define void @f_doublearr2_s_arg({ double, double } %0) +#[no_mangle] +pub extern "C" fn f_doublearr2_s_arg(a: DoubleArr2) {} + +// CHECK: define { double, double } @f_ret_doublearr2_s() +#[no_mangle] +pub extern "C" fn f_ret_doublearr2_s() -> DoubleArr2 { + DoubleArr2 { a: [1., 2.] } +} + +#[repr(C)] +pub struct Tricky1 { + f: [f64; 1], +} + +#[repr(C)] +pub struct DoubleArr2Tricky1 { + g: [Tricky1; 2], +} + +// CHECK: define void @f_doublearr2_tricky1_s_arg({ double, double } %0) +#[no_mangle] +pub extern "C" fn f_doublearr2_tricky1_s_arg(a: DoubleArr2Tricky1) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky1_s() +#[no_mangle] +pub extern "C" fn f_ret_doublearr2_tricky1_s() -> DoubleArr2Tricky1 { + DoubleArr2Tricky1 { g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] } +} + +#[repr(C)] +pub struct EmptyStruct {} + +#[repr(C)] +pub struct DoubleArr2Tricky2 { + s: EmptyStruct, + g: [Tricky1; 2], +} + +// CHECK: define void @f_doublearr2_tricky2_s_arg({ double, double } %0) +#[no_mangle] +pub extern "C" fn f_doublearr2_tricky2_s_arg(a: DoubleArr2Tricky2) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky2_s() +#[no_mangle] +pub extern "C" fn f_ret_doublearr2_tricky2_s() -> DoubleArr2Tricky2 { + DoubleArr2Tricky2 { s: EmptyStruct {}, g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] } +} + +#[repr(C)] +pub struct IntDoubleInt { + a: i32, + b: f64, + c: i32, +} + +// CHECK: define void @f_int_double_int_s_arg(%IntDoubleInt* {{.*}}%a) +#[no_mangle] +pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {} + +// CHECK: define void @f_ret_int_double_int_s(%IntDoubleInt* {{.*}}sret +#[no_mangle] +pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt { + IntDoubleInt { a: 1, b: 2., c: 3 } +} + +#[repr(C)] +pub struct CharCharDouble { + a: u8, + b: u8, + c: f64, +} + +// CHECK: define void @f_char_char_double_s_arg([2 x i64] %0) +#[no_mangle] +pub extern "C" fn f_char_char_double_s_arg(a: CharCharDouble) {} + +// CHECK: define [2 x i64] @f_ret_char_char_double_s() +#[no_mangle] +pub extern "C" fn f_ret_char_char_double_s() -> CharCharDouble { + CharCharDouble { a: 1, b: 2, c: 3. } +} + +#[repr(C)] +pub union DoubleU { + a: f64, +} + +// CHECK: define void @f_double_u_arg(i64 %0) +#[no_mangle] +pub extern "C" fn f_double_u_arg(a: DoubleU) {} + +// CHECK: define i64 @f_ret_double_u() +#[no_mangle] +pub extern "C" fn f_ret_double_u() -> DoubleU { + unsafe { DoubleU { a: 1. } } +} diff --git a/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs new file mode 100644 index 000000000..f08fabed4 --- /dev/null +++ b/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs @@ -0,0 +1,277 @@ +// +// compile-flags: -C no-prepopulate-passes +// only-riscv64 +// only-linux +#![crate_type = "lib"] + +// CHECK: define void @f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 zeroext %i) +#[no_mangle] +pub extern "C" fn f_fpr_tracking( + a: f32, + b: f32, + c: f32, + d: f32, + e: f32, + f: f32, + g: f32, + h: f32, + i: u8, +) { +} + +#[repr(C)] +pub struct Float { + f: f32, +} + +#[repr(C)] +pub struct FloatFloat { + f: f32, + g: f32, +} + +// CHECK: define void @f_float_s_arg(float %0) +#[no_mangle] +pub extern "C" fn f_float_s_arg(a: Float) {} + +// CHECK: define float @f_ret_float_s() +#[no_mangle] +pub extern "C" fn f_ret_float_s() -> Float { + Float { f: 1. } +} + +// CHECK: define void @f_float_float_s_arg({ float, float } %0) +#[no_mangle] +pub extern "C" fn f_float_float_s_arg(a: FloatFloat) {} + +// CHECK: define { float, float } @f_ret_float_float_s() +#[no_mangle] +pub extern "C" fn f_ret_float_float_s() -> FloatFloat { + FloatFloat { f: 1., g: 2. } +} + +// CHECK: define void @f_float_float_s_arg_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, i64 %7) +#[no_mangle] +pub extern "C" fn f_float_float_s_arg_insufficient_fprs( + a: f32, + b: f32, + c: f32, + d: f32, + e: f32, + f: f32, + g: f32, + h: FloatFloat, +) { +} + +#[repr(C)] +pub struct FloatInt8 { + f: f32, + i: i8, +} + +#[repr(C)] +pub struct FloatUInt8 { + f: f32, + i: u8, +} + +#[repr(C)] +pub struct FloatInt32 { + f: f32, + i: i32, +} + +#[repr(C)] +pub struct FloatInt64 { + f: f32, + i: i64, +} + +// CHECK: define void @f_float_int8_s_arg({ float, i8 } %0) +#[no_mangle] +pub extern "C" fn f_float_int8_s_arg(a: FloatInt8) {} + +// CHECK: define { float, i8 } @f_ret_float_int8_s() +#[no_mangle] +pub extern "C" fn f_ret_float_int8_s() -> FloatInt8 { + FloatInt8 { f: 1., i: 2 } +} + +// CHECK: define void @f_float_int32_s_arg({ float, i32 } %0) +#[no_mangle] +pub extern "C" fn f_float_int32_s_arg(a: FloatInt32) {} + +// CHECK: define { float, i32 } @f_ret_float_int32_s() +#[no_mangle] +pub extern "C" fn f_ret_float_int32_s() -> FloatInt32 { + FloatInt32 { f: 1., i: 2 } +} + +// CHECK: define void @f_float_uint8_s_arg({ float, i8 } %0) +#[no_mangle] +pub extern "C" fn f_float_uint8_s_arg(a: FloatUInt8) {} + +// CHECK: define { float, i8 } @f_ret_float_uint8_s() +#[no_mangle] +pub extern "C" fn f_ret_float_uint8_s() -> FloatUInt8 { + FloatUInt8 { f: 1., i: 2 } +} + +// CHECK: define void @f_float_int64_s_arg({ float, i64 } %0) +#[no_mangle] +pub extern "C" fn f_float_int64_s_arg(a: FloatInt64) {} + +// CHECK: define { float, i64 } @f_ret_float_int64_s() +#[no_mangle] +pub extern "C" fn f_ret_float_int64_s() -> FloatInt64 { + FloatInt64 { f: 1., i: 2 } +} + +// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, i64 %0) +#[no_mangle] +pub extern "C" fn f_float_int8_s_arg_insufficient_gprs( + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: FloatInt8, +) { +} + +// CHECK: define void @f_struct_float_int8_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i64 %8) +#[no_mangle] +pub extern "C" fn f_struct_float_int8_insufficient_fprs( + a: f32, + b: f32, + c: f32, + d: f32, + e: f32, + f: f32, + g: f32, + h: f32, + i: FloatInt8, +) { +} + +#[repr(C)] +pub struct FloatArr1 { + a: [f32; 1], +} + +// CHECK: define void @f_floatarr1_s_arg(float %0) +#[no_mangle] +pub extern "C" fn f_floatarr1_s_arg(a: FloatArr1) {} + +// CHECK: define float @f_ret_floatarr1_s() +#[no_mangle] +pub extern "C" fn f_ret_floatarr1_s() -> FloatArr1 { + FloatArr1 { a: [1.] } +} + +#[repr(C)] +pub struct FloatArr2 { + a: [f32; 2], +} + +// CHECK: define void @f_floatarr2_s_arg({ float, float } %0) +#[no_mangle] +pub extern "C" fn f_floatarr2_s_arg(a: FloatArr2) {} + +// CHECK: define { float, float } @f_ret_floatarr2_s() +#[no_mangle] +pub extern "C" fn f_ret_floatarr2_s() -> FloatArr2 { + FloatArr2 { a: [1., 2.] } +} + +#[repr(C)] +pub struct Tricky1 { + f: [f32; 1], +} + +#[repr(C)] +pub struct FloatArr2Tricky1 { + g: [Tricky1; 2], +} + +// CHECK: define void @f_floatarr2_tricky1_s_arg({ float, float } %0) +#[no_mangle] +pub extern "C" fn f_floatarr2_tricky1_s_arg(a: FloatArr2Tricky1) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky1_s() +#[no_mangle] +pub extern "C" fn f_ret_floatarr2_tricky1_s() -> FloatArr2Tricky1 { + FloatArr2Tricky1 { g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] } +} + +#[repr(C)] +pub struct EmptyStruct {} + +#[repr(C)] +pub struct FloatArr2Tricky2 { + s: EmptyStruct, + g: [Tricky1; 2], +} + +// CHECK: define void @f_floatarr2_tricky2_s_arg({ float, float } %0) +#[no_mangle] +pub extern "C" fn f_floatarr2_tricky2_s_arg(a: FloatArr2Tricky2) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky2_s() +#[no_mangle] +pub extern "C" fn f_ret_floatarr2_tricky2_s() -> FloatArr2Tricky2 { + FloatArr2Tricky2 { s: EmptyStruct {}, g: [Tricky1 { f: [1.] }, Tricky1 { f: [2.] }] } +} + +#[repr(C)] +pub struct IntFloatInt { + a: i32, + b: f32, + c: i32, +} + +// CHECK: define void @f_int_float_int_s_arg([2 x i64] %0) +#[no_mangle] +pub extern "C" fn f_int_float_int_s_arg(a: IntFloatInt) {} + +// CHECK: define [2 x i64] @f_ret_int_float_int_s() +#[no_mangle] +pub extern "C" fn f_ret_int_float_int_s() -> IntFloatInt { + IntFloatInt { a: 1, b: 2., c: 3 } +} + +#[repr(C)] +pub struct CharCharFloat { + a: u8, + b: u8, + c: f32, +} + +// CHECK: define void @f_char_char_float_s_arg(i64 %0) +#[no_mangle] +pub extern "C" fn f_char_char_float_s_arg(a: CharCharFloat) {} + +// CHECK: define i64 @f_ret_char_char_float_s() +#[no_mangle] +pub extern "C" fn f_ret_char_char_float_s() -> CharCharFloat { + CharCharFloat { a: 1, b: 2, c: 3. } +} + +#[repr(C)] +pub union FloatU { + a: f32, +} + +// CHECK: define void @f_float_u_arg(i64 %0) +#[no_mangle] +pub extern "C" fn f_float_u_arg(a: FloatU) {} + +// CHECK: define i64 @f_ret_float_u() +#[no_mangle] +pub extern "C" fn f_ret_float_u() -> FloatU { + unsafe { FloatU { a: 1. } } +} -- cgit v1.2.3