1 /// Test LoongArch64 ABI rewrite of struct returned by value (BIND(C), VALUE derived types).
2 /// This test test cases where the struct can be returned in registers.
3 /// Test cases can be roughly divided into two categories:
4 /// - struct with a single intrinsic component;
5 /// - sturct with more than one field;
6 /// Since the argument marshalling logic is largely the same within each category,
7 /// only the first example in each category checks the entire invocation process,
8 /// while the other examples only check the signatures.
10 // REQUIRES: loongarch-registered-target
11 // RUN: fir-opt --split-input-file --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s
14 /// *********************** Struct with a single intrinsic component *********************** ///
16 !ty_i16 = !fir.type<ti16{i:i16}>
17 !ty_i32 = !fir.type<ti32{i:i32}>
18 !ty_i64 = !fir.type<ti64{i:i64}>
19 !ty_i128 = !fir.type<ti128{i:i128}>
20 !ty_f16 = !fir.type<tf16{i:f16}>
21 !ty_f32 = !fir.type<tf32{i:f32}>
22 !ty_f64 = !fir.type<tf64{i:f64}>
23 !ty_f128 = !fir.type<tf128{i:f128}>
24 !ty_bf16 = !fir.type<tbf16{i:bf16}>
25 !ty_char1 = !fir.type<tchar1{i:!fir.char<1>}>
26 !ty_char2 = !fir.type<tchar2{i:!fir.char<1,2>}>
27 !ty_log1 = !fir.type<tlog1{i:!fir.logical<1>}>
28 !ty_log2 = !fir.type<tlog2{i:!fir.logical<2>}>
29 !ty_log4 = !fir.type<tlog4{i:!fir.logical<4>}>
30 !ty_log8 = !fir.type<tlog8{i:!fir.logical<8>}>
31 !ty_log16 = !fir.type<tlog16{i:!fir.logical<16>}>
32 !ty_cmplx_f32 = !fir.type<tcmplx_f32{i:complex<f32>}>
33 !ty_cmplx_f64 = !fir.type<tcmplx_f64{i:complex<f64>}>
35 module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", llvm.target_triple = "loongarch64-unknown-linux-gnu"} {
37 // CHECK-LABEL: func.func private @test_func_i16() -> i64
38 func.func private @test_func_i16() -> !ty_i16
39 // CHECK-LABEL: func.func @test_call_i16(
40 // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<ti16{i:i16}>>) {
41 func.func @test_call_i16(%arg0: !fir.ref<!ty_i16>) {
42 // CHECK: %[[OUT:.*]] = fir.call @test_func_i16() : () -> i64
43 // CHECK: %[[STACK:.*]] = llvm.intr.stacksave : !llvm.ptr
44 // CHECK: %[[ARR:.*]] = fir.alloca i64
45 // CHECK: fir.store %[[OUT]] to %[[ARR]] : !fir.ref<i64>
46 // CHECK: %[[CVT:.*]] = fir.convert %[[ARR]] : (!fir.ref<i64>) -> !fir.ref<!fir.type<ti16{i:i16}>>
47 // CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<ti16{i:i16}>>
48 // CHECK: llvm.intr.stackrestore %[[STACK]] : !llvm.ptr
49 %out = fir.call @test_func_i16() : () -> !ty_i16
50 // CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<ti16{i:i16}>>
51 fir.store %out to %arg0 : !fir.ref<!ty_i16>
56 // CHECK-LABEL: func.func private @test_func_i32() -> i64
57 func.func private @test_func_i32() -> !ty_i32
59 // CHECK-LABEL: func.func private @test_func_i64() -> i64
60 func.func private @test_func_i64() -> !ty_i64
62 // CHECK-LABEL: func.func private @test_func_i128() -> i128
63 func.func private @test_func_i128() -> !ty_i128
65 // CHECK-LABEL: func.func private @test_func_f16() -> i64
66 func.func private @test_func_f16() -> !ty_f16
68 // CHECK-LABEL: func.func private @test_func_f32() -> f32
69 func.func private @test_func_f32() -> !ty_f32
71 // CHECK-LABEL: func.func private @test_func_f64() -> f64
72 func.func private @test_func_f64() -> !ty_f64
74 // CHECK-LABEL: func.func private @test_func_f128() -> i128
75 func.func private @test_func_f128() -> !ty_f128
77 // CHECK-LABEL: func.func private @test_func_bf16() -> i64
78 func.func private @test_func_bf16() -> !ty_bf16
80 // CHECK-LABEL: func.func private @test_func_char1() -> i64
81 func.func private @test_func_char1() -> !ty_char1
83 // CHECK-LABEL: func.func private @test_func_char2() -> i64
84 func.func private @test_func_char2() -> !ty_char2
86 // CHECK-LABEL: func.func private @test_func_log1() -> i64
87 func.func private @test_func_log1() -> !ty_log1
89 // CHECK-LABEL: func.func private @test_func_log2() -> i64
90 func.func private @test_func_log2() -> !ty_log2
92 // CHECK-LABEL: func.func private @test_func_log4() -> i64
93 func.func private @test_func_log4() -> !ty_log4
95 // CHECK-LABEL: func.func private @test_func_log8() -> i64
96 func.func private @test_func_log8() -> !ty_log8
98 // CHECK-LABEL: func.func private @test_func_log16() -> i128
99 func.func private @test_func_log16() -> !ty_log16
101 // CHECK-LABEL: func.func private @test_func_cmplx_f32() -> tuple<f32, f32>
102 func.func private @test_func_cmplx_f32() -> !ty_cmplx_f32
104 // CHECK-LABEL: func.func private @test_func_cmplx_f64() -> tuple<f64, f64>
105 func.func private @test_func_cmplx_f64() -> !ty_cmplx_f64
109 /// *************************** Struct with more than one field **************************** ///
113 !ty_i32_f32 = !fir.type<ti32_f32{i:i32,j:f32}>
114 !ty_i32_f64 = !fir.type<ti32_f64{i:i32,j:f64}>
115 !ty_i64_f32 = !fir.type<ti64_f32{i:i64,j:f32}>
116 !ty_i64_f64 = !fir.type<ti64_f64{i:i64,j:f64}>
117 !ty_f64_i64 = !fir.type<tf64_i64{i:f64,j:i64}>
118 !ty_f16_f16 = !fir.type<tf16_f16{i:f16,j:f16}>
119 !ty_f32_f32 = !fir.type<tf32_f32{i:f32,j:f32}>
120 !ty_f64_f64 = !fir.type<tf64_f64{i:f64,j:f64}>
121 !ty_f32_i32_i32 = !fir.type<tf32_i32_i32{i:f32,j:i32,k:i32}>
122 !ty_f32_f32_i32 = !fir.type<tf32_f32_i32{i:f32,j:f32,k:i32}>
123 !ty_f32_f32_f32 = !fir.type<tf32_f32_f32{i:f32,j:f32,k:f32}>
125 !ty_i8_a8 = !fir.type<ti8_a8{i:!fir.array<8xi8>}>
126 !ty_i8_a16 = !fir.type<ti8_a16{i:!fir.array<16xi8>}>
127 !ty_f32_a2 = !fir.type<tf32_a2{i:!fir.array<2xf32>}>
128 !ty_f64_a2 = !fir.type<tf64_a2{i:!fir.array<2xf64>}>
129 !ty_nested_i32_f32 = !fir.type<t11{i:!ty_i32_f32}>
130 !ty_nested_i8_a8_i32 = !fir.type<t12{i:!ty_i8_a8, j:i32}>
132 module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128", llvm.target_triple = "loongarch64-unknown-linux-gnu"} {
134 // CHECK-LABEL: func.func private @test_func_i32_f32() -> tuple<i32, f32>
135 func.func private @test_func_i32_f32() -> !ty_i32_f32
136 // CHECK-LABEL: func.func @test_call_i32_f32(
137 // CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>) {
138 func.func @test_call_i32_f32(%arg0: !fir.ref<!ty_i32_f32>) {
139 // CHECK: %[[OUT:.*]] = fir.call @test_func_i32_f32() : () -> tuple<i32, f32>
140 // CHECK: %[[STACK:.*]] = llvm.intr.stacksave : !llvm.ptr
141 // CHECK: %[[ARR:.*]] = fir.alloca tuple<i32, f32>
142 // CHECK: fir.store %[[OUT]] to %[[ARR]] : !fir.ref<tuple<i32, f32>>
143 // CHECK: %[[CVT:.*]] = fir.convert %[[ARR]] : (!fir.ref<tuple<i32, f32>>) -> !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>
144 // CHECK: %[[LD:.*]] = fir.load %[[CVT]] : !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>
145 // CHECK: llvm.intr.stackrestore %[[STACK]] : !llvm.ptr
146 %out = fir.call @test_func_i32_f32() : () -> !ty_i32_f32
147 // CHECK: fir.store %[[LD]] to %[[ARG0]] : !fir.ref<!fir.type<ti32_f32{i:i32,j:f32}>>
148 fir.store %out to %arg0 : !fir.ref<!ty_i32_f32>
153 // CHECK-LABEL: func.func private @test_func_i32_f64() -> tuple<i32, f64>
154 func.func private @test_func_i32_f64() -> !ty_i32_f64
156 // CHECK-LABEL: func.func private @test_func_i64_f32() -> tuple<i64, f32>
157 func.func private @test_func_i64_f32() -> !ty_i64_f32
159 // CHECK-LABEL: func.func private @test_func_i64_f64() -> tuple<i64, f64>
160 func.func private @test_func_i64_f64() -> !ty_i64_f64
162 // CHECK-LABEL: func.func private @test_func_f64_i64() -> tuple<f64, i64>
163 func.func private @test_func_f64_i64() -> !ty_f64_i64
165 // CHECK-LABEL: func.func private @test_func_f16_f16() -> i64
166 func.func private @test_func_f16_f16() -> !ty_f16_f16
168 // CHECK-LABEL: func.func private @test_func_f32_f32() -> tuple<f32, f32>
169 func.func private @test_func_f32_f32() -> !ty_f32_f32
171 // CHECK-LABEL: func.func private @test_func_f64_f64() -> tuple<f64, f64>
172 func.func private @test_func_f64_f64() -> !ty_f64_f64
174 // CHECK-LABEL: func.func private @test_func_f32_i32_i32() -> !fir.array<2xi64>
175 func.func private @test_func_f32_i32_i32() -> !ty_f32_i32_i32
177 // CHECK-LABEL: func.func private @test_func_f32_f32_i32() -> !fir.array<2xi64>
178 func.func private @test_func_f32_f32_i32() -> !ty_f32_f32_i32
180 // CHECK-LABEL: func.func private @test_func_f32_f32_f32() -> !fir.array<2xi64>
181 func.func private @test_func_f32_f32_f32() -> !ty_f32_f32_f32
183 // CHECK-LABEL: func.func private @test_func_i8_a8() -> i64
184 func.func private @test_func_i8_a8() -> !ty_i8_a8
186 // CHECK-LABEL: func.func private @test_func_i8_a16() -> !fir.array<2xi64>
187 func.func private @test_func_i8_a16() -> !ty_i8_a16
189 // CHECK-LABEL: func.func private @test_func_f32_a2() -> tuple<f32, f32>
190 func.func private @test_func_f32_a2() -> !ty_f32_a2
192 // CHECK-LABEL: func.func private @test_func_f64_a2() -> tuple<f64, f64>
193 func.func private @test_func_f64_a2() -> !ty_f64_a2
195 // CHECK-LABEL: func.func private @test_func_nested_i32_f32() -> tuple<i32, f32>
196 func.func private @test_func_nested_i32_f32() -> !ty_nested_i32_f32
198 // CHECK-LABEL: func.func private @test_func_nested_i8_a8_i32() -> !fir.array<2xi64>
199 func.func private @test_func_nested_i8_a8_i32() -> !ty_nested_i8_a8_i32