xref: /llvm-project/flang/test/Fir/abstract-results.fir (revision 1ead51a86c6c746a1b9948ca1ee142df223ffebd)
1// Test rewrite of functions that return fir.array<>, fir.type<>, fir.box<> to
2// functions that take an additional argument for the result.
3
4// RUN: fir-opt %s --abstract-result | FileCheck %s --check-prefix=FUNC-REF
5// RUN: fir-opt %s --abstract-result=abstract-result-as-box | FileCheck %s --check-prefix=FUNC-BOX
6// RUN: fir-opt %s --abstract-result | FileCheck %s --check-prefix=GLOBAL-REF
7// RUN: fir-opt %s --abstract-result=abstract-result-as-box | FileCheck %s --check-prefix=GLOBAL-BOX
8
9// ----------------------- Test declaration rewrite ----------------------------
10
11// FUNC-REF-LABEL:  func private @arrayfunc(!fir.ref<!fir.array<?xf32>>, i32)
12// FUNC-BOX-LABEL:  func private @arrayfunc(!fir.box<!fir.array<?xf32>>, i32)
13func.func private @arrayfunc(i32) -> !fir.array<?xf32>
14
15// FUNC-REF-LABEL:  func private @derivedfunc(!fir.ref<!fir.type<t{x:f32}>>, f32)
16// FUNC-BOX-LABEL:  func private @derivedfunc(!fir.box<!fir.type<t{x:f32}>>, f32)
17func.func private @derivedfunc(f32) -> !fir.type<t{x:f32}>
18
19// FUNC-REF-LABEL:  func private @boxfunc(!fir.ref<!fir.box<!fir.heap<f64>>>, i64)
20// FUNC-BOX-LABEL:  func private @boxfunc(!fir.ref<!fir.box<!fir.heap<f64>>>, i64)
21func.func private @boxfunc(i64) -> !fir.box<!fir.heap<f64>>
22
23
24// ------------------------ Test callee rewrite --------------------------------
25
26// FUNC-REF-LABEL:  func private @arrayfunc_callee(
27// FUNC-REF-SAME: %[[buffer:.*]]: !fir.ref<!fir.array<?xf32>>, %[[n:.*]]: index) {
28// FUNC-BOX-LABEL:  func private @arrayfunc_callee(
29// FUNC-BOX-SAME: %[[box:.*]]: !fir.box<!fir.array<?xf32>>, %[[n:.*]]: index) {
30func.func private @arrayfunc_callee(%n : index) -> !fir.array<?xf32> {
31  %buffer = fir.alloca !fir.array<?xf32>, %n
32  // Do something with result (res(4) = 42.)
33  %c4 = arith.constant 4 : i64
34  %coor = fir.coordinate_of %buffer, %c4 : (!fir.ref<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
35  %cst = arith.constant 4.200000e+01 : f32
36  fir.store %cst to %coor : !fir.ref<f32>
37  %res = fir.load %buffer : !fir.ref<!fir.array<?xf32>>
38  return %res : !fir.array<?xf32>
39
40  // FUNC-REF-DAG: %[[coor:.*]] = fir.coordinate_of %[[buffer]], %{{.*}} : (!fir.ref<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
41  // FUNC-REF-DAG: fir.store %{{.*}} to %[[coor]] : !fir.ref<f32>
42  // FUNC-REF: return
43
44  // FUNC-BOX: %[[buffer:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
45  // FUNC-BOX-DAG: %[[coor:.*]] = fir.coordinate_of %[[buffer]], %{{.*}} : (!fir.ref<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
46  // FUNC-BOX-DAG: fir.store %{{.*}} to %[[coor]] : !fir.ref<f32>
47  // FUNC-BOX: return
48}
49
50
51// FUNC-REF-LABEL: func @derivedfunc_callee(
52// FUNC-REF-SAME: %[[buffer:.*]]: !fir.ref<!fir.type<t{x:f32}>>, %[[v:.*]]: f32) {
53// FUNC-BOX-LABEL: func @derivedfunc_callee(
54// FUNC-BOX-SAME: %[[box:.*]]: !fir.box<!fir.type<t{x:f32}>>, %[[v:.*]]: f32) {
55func.func @derivedfunc_callee(%v: f32) -> !fir.type<t{x:f32}> {
56  %buffer = fir.alloca !fir.type<t{x:f32}>
57  %0 = fir.field_index x, !fir.type<t{x:f32}>
58  %1 = fir.coordinate_of %buffer, %0 : (!fir.ref<!fir.type<t{x:f32}>>, !fir.field) -> !fir.ref<f32>
59  fir.store %v to %1 : !fir.ref<f32>
60  %res = fir.load %buffer : !fir.ref<!fir.type<t{x:f32}>>
61  return %res : !fir.type<t{x:f32}>
62
63  // FUNC-REF: %[[coor:.*]] = fir.coordinate_of %[[buffer]], %{{.*}} : (!fir.ref<!fir.type<t{x:f32}>>, !fir.field) -> !fir.ref<f32>
64  // FUNC-REF: fir.store %[[v]] to %[[coor]] : !fir.ref<f32>
65  // FUNC-REF: return
66
67  // FUNC-BOX: %[[buffer:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.type<t{x:f32}>>) -> !fir.ref<!fir.type<t{x:f32}>>
68  // FUNC-BOX: %[[coor:.*]] = fir.coordinate_of %[[buffer]], %{{.*}} : (!fir.ref<!fir.type<t{x:f32}>>, !fir.field) -> !fir.ref<f32>
69  // FUNC-BOX: fir.store %[[v]] to %[[coor]] : !fir.ref<f32>
70  // FUNC-BOX: return
71}
72
73// FUNC-REF-LABEL: func @boxfunc_callee(
74// FUNC-REF-SAME: %[[buffer:.*]]: !fir.ref<!fir.box<!fir.heap<f64>>>) {
75// FUNC-BOX-LABEL: func @boxfunc_callee(
76// FUNC-BOX-SAME: %[[buffer:.*]]: !fir.ref<!fir.box<!fir.heap<f64>>>) {
77func.func @boxfunc_callee() -> !fir.box<!fir.heap<f64>> {
78  %alloc = fir.allocmem f64
79  %res = fir.embox %alloc : (!fir.heap<f64>) -> !fir.box<!fir.heap<f64>>
80  return %res : !fir.box<!fir.heap<f64>>
81  // FUNC-REF: %[[box:.*]] = fir.embox %{{.*}} : (!fir.heap<f64>) -> !fir.box<!fir.heap<f64>>
82  // FUNC-REF: fir.store %[[box]] to %[[buffer]] : !fir.ref<!fir.box<!fir.heap<f64>>>
83  // FUNC-REF: return
84
85  // FUNC-BOX: %[[box:.*]] = fir.embox %{{.*}} : (!fir.heap<f64>) -> !fir.box<!fir.heap<f64>>
86  // FUNC-BOX: fir.store %[[box]] to %[[buffer]] : !fir.ref<!fir.box<!fir.heap<f64>>>
87  // FUNC-BOX: return
88}
89
90// FUNC-REF-LABEL: func @retcptr() -> !fir.ref<none>
91// FUNC-BOX-LABEL: func @retcptr() -> !fir.ref<none>
92func.func @retcptr() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {
93  %0 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = "rec", uniq_name = "_QFrecErec"}
94  %1 = fir.load %0 : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>
95  return %1 : !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
96
97  // FUNC-REF: %[[ALLOC:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = "rec", uniq_name = "_QFrecErec"}
98  // FUNC-REF: %[[FIELD:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
99  // FUNC-REF: %[[ADDR:.*]] = fir.coordinate_of %[[ALLOC]], %[[FIELD]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64>
100  // FUNC-REF: %[[VAL:.*]] = fir.load %[[ADDR]] : !fir.ref<i64>
101  // FUNC-REF: %[[CAST:.*]] = fir.convert %[[VAL]] : (i64) -> !fir.ref<none>
102  // FUNC-REF: return %[[CAST]] : !fir.ref<none>
103  // FUNC-BOX: %[[ALLOC:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = "rec", uniq_name = "_QFrecErec"}
104  // FUNC-BOX: %[[FIELD:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
105  // FUNC-BOX: %[[ADDR:.*]] = fir.coordinate_of %[[ALLOC]], %[[FIELD]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64>
106  // FUNC-BOX: %[[VAL:.*]] = fir.load %[[ADDR]] : !fir.ref<i64>
107  // FUNC-BOX: %[[CAST:.*]] = fir.convert %[[VAL]] : (i64) -> !fir.ref<none>
108  // FUNC-BOX: return %[[CAST]] : !fir.ref<none>
109}
110
111// FUNC-REF-LABEL:  func private @arrayfunc_callee_declare(
112// FUNC-REF-SAME: %[[buffer:.*]]: !fir.ref<!fir.array<?xf32>>, %[[n:.*]]: index) {
113// FUNC-BOX-LABEL:  func private @arrayfunc_callee_declare(
114// FUNC-BOX-SAME: %[[box:.*]]: !fir.box<!fir.array<?xf32>>, %[[n:.*]]: index) {
115func.func private @arrayfunc_callee_declare(%n : index) -> !fir.array<?xf32> {
116  %buffer_alloc = fir.alloca !fir.array<?xf32>, %n
117  %shape = fir.shape %n : (index) -> !fir.shape<1>
118  %buffer = fir.declare %buffer_alloc(%shape) {uniq_name = "x"}: (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<?xf32>>
119  // Do something with result (res(4) = 42.)
120  %c4 = arith.constant 4 : i64
121  %coor = fir.coordinate_of %buffer, %c4 : (!fir.ref<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
122  %cst = arith.constant 4.200000e+01 : f32
123  fir.store %cst to %coor : !fir.ref<f32>
124  %res = fir.load %buffer : !fir.ref<!fir.array<?xf32>>
125  return %res : !fir.array<?xf32>
126
127  // FUNC-REF-DAG: %[[buffer_declare:.*]] = fir.declare %[[buffer]](%{{.*}}) {uniq_name = "x"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<?xf32>>
128  // FUNC-REF-DAG: %[[coor:.*]] = fir.coordinate_of %[[buffer_declare]], %{{.*}} : (!fir.ref<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
129  // FUNC-REF-DAG: fir.store %{{.*}} to %[[coor]] : !fir.ref<f32>
130  // FUNC-REF: return
131
132  // FUNC-BOX: %[[buffer:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
133  // FUNC-BOX-DAG: %[[buffer_declare:.*]] = fir.declare %[[buffer]](%{{.*}}) {uniq_name = "x"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<?xf32>>
134  // FUNC-BOX-DAG: %[[coor:.*]] = fir.coordinate_of %[[buffer_declare]], %{{.*}} : (!fir.ref<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
135  // FUNC-BOX-DAG: fir.store %{{.*}} to %[[coor]] : !fir.ref<f32>
136  // FUNC-BOX: return
137}
138
139// ------------------------ Test caller rewrite --------------------------------
140
141// FUNC-REF-LABEL: func @call_arrayfunc() {
142// FUNC-BOX-LABEL: func @call_arrayfunc() {
143func.func @call_arrayfunc() {
144  %c100 = arith.constant 100 : index
145  %buffer = fir.alloca !fir.array<?xf32>, %c100
146  %shape = fir.shape %c100 : (index) -> !fir.shape<1>
147  %res = fir.call @arrayfunc_callee(%c100) : (index) -> !fir.array<?xf32>
148  fir.save_result %res to %buffer(%shape) : !fir.array<?xf32>, !fir.ref<!fir.array<?xf32>>, !fir.shape<1>
149  return
150
151  // FUNC-REF: %[[c100:.*]] = arith.constant 100 : index
152  // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.array<?xf32>, %[[c100]]
153  // FUNC-REF: fir.call @arrayfunc_callee(%[[buffer]], %[[c100]]) : (!fir.ref<!fir.array<?xf32>>, index) -> ()
154  // FUNC-REF-NOT: fir.save_result
155
156  // FUNC-BOX: %[[c100:.*]] = arith.constant 100 : index
157  // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.array<?xf32>, %[[c100]]
158  // FUNC-BOX: %[[shape:.*]] = fir.shape %[[c100]] : (index) -> !fir.shape<1>
159  // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]](%[[shape]]) : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
160  // FUNC-BOX: fir.call @arrayfunc_callee(%[[box]], %[[c100]]) : (!fir.box<!fir.array<?xf32>>, index) -> ()
161  // FUNC-BOX-NOT: fir.save_result
162}
163
164// FUNC-REF-LABEL: func @call_derivedfunc() {
165// FUNC-BOX-LABEL: func @call_derivedfunc() {
166func.func @call_derivedfunc() {
167  %buffer = fir.alloca !fir.type<t{x:f32}>
168  %cst = arith.constant 4.200000e+01 : f32
169  %res = fir.call @derivedfunc_callee(%cst) : (f32) -> !fir.type<t{x:f32}>
170  fir.save_result %res to %buffer : !fir.type<t{x:f32}>, !fir.ref<!fir.type<t{x:f32}>>
171  return
172  // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.type<t{x:f32}>
173  // FUNC-REF: %[[cst:.*]] = arith.constant {{.*}} : f32
174  // FUNC-REF: fir.call @derivedfunc_callee(%[[buffer]], %[[cst]]) : (!fir.ref<!fir.type<t{x:f32}>>, f32) -> ()
175  // FUNC-REF-NOT: fir.save_result
176
177  // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.type<t{x:f32}>
178  // FUNC-BOX: %[[cst:.*]] = arith.constant {{.*}} : f32
179  // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]] : (!fir.ref<!fir.type<t{x:f32}>>) -> !fir.box<!fir.type<t{x:f32}>>
180  // FUNC-BOX: fir.call @derivedfunc_callee(%[[box]], %[[cst]]) : (!fir.box<!fir.type<t{x:f32}>>, f32) -> ()
181  // FUNC-BOX-NOT: fir.save_result
182}
183
184func.func private @derived_lparams_func() -> !fir.type<t2(l1:i32,l2:i32){x:f32}>
185
186// FUNC-REF-LABEL: func @call_derived_lparams_func(
187// FUNC-REF-SAME: %[[buffer:.*]]: !fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>
188// FUNC-BOX-LABEL: func @call_derived_lparams_func(
189// FUNC-BOX-SAME: %[[buffer:.*]]: !fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>
190func.func @call_derived_lparams_func(%buffer: !fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>) {
191  %l1 = arith.constant 3 : i32
192  %l2 = arith.constant 5 : i32
193  %res = fir.call @derived_lparams_func() : () -> !fir.type<t2(l1:i32,l2:i32){x:f32}>
194  fir.save_result %res to %buffer typeparams %l1, %l2 : !fir.type<t2(l1:i32,l2:i32){x:f32}>, !fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>, i32, i32
195  return
196
197  // FUNC-REF: %[[l1:.*]] = arith.constant 3 : i32
198  // FUNC-REF: %[[l2:.*]] = arith.constant 5 : i32
199  // FUNC-REF: fir.call @derived_lparams_func(%[[buffer]]) : (!fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>) -> ()
200  // FUNC-REF-NOT: fir.save_result
201
202  // FUNC-BOX: %[[l1:.*]] = arith.constant 3 : i32
203  // FUNC-BOX: %[[l2:.*]] = arith.constant 5 : i32
204  // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]] typeparams %[[l1]], %[[l2]] : (!fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>, i32, i32) -> !fir.box<!fir.type<t2(l1:i32,l2:i32){x:f32}>>
205  // FUNC-BOX: fir.call @derived_lparams_func(%[[box]]) : (!fir.box<!fir.type<t2(l1:i32,l2:i32){x:f32}>>) -> ()
206  // FUNC-BOX-NOT: fir.save_result
207}
208
209// FUNC-REF-LABEL: func @call_boxfunc() {
210// FUNC-BOX-LABEL: func @call_boxfunc() {
211func.func @call_boxfunc() {
212  %buffer = fir.alloca !fir.box<!fir.heap<f64>>
213  %res = fir.call @boxfunc_callee() : () -> !fir.box<!fir.heap<f64>>
214  fir.save_result %res to %buffer: !fir.box<!fir.heap<f64>>, !fir.ref<!fir.box<!fir.heap<f64>>>
215  return
216
217  // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.box<!fir.heap<f64>>
218  // FUNC-REF: fir.call @boxfunc_callee(%[[buffer]]) : (!fir.ref<!fir.box<!fir.heap<f64>>>) -> ()
219  // FUNC-REF-NOT: fir.save_result
220
221  // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.box<!fir.heap<f64>>
222  // FUNC-BOX: fir.call @boxfunc_callee(%[[buffer]]) : (!fir.ref<!fir.box<!fir.heap<f64>>>) -> ()
223  // FUNC-BOX-NOT: fir.save_result
224}
225
226func.func private @chararrayfunc(index, index) -> !fir.array<?x!fir.char<1,?>>
227
228// FUNC-REF-LABEL: func @call_chararrayfunc() {
229// FUNC-BOX-LABEL: func @call_chararrayfunc() {
230func.func @call_chararrayfunc() {
231  %c100 = arith.constant 100 : index
232  %c50 = arith.constant 50 : index
233  %buffer = fir.alloca !fir.array<?x!fir.char<1,?>>(%c100 : index), %c50
234  %shape = fir.shape %c100 : (index) -> !fir.shape<1>
235  %res = fir.call @chararrayfunc(%c100, %c50) : (index, index) -> !fir.array<?x!fir.char<1,?>>
236  fir.save_result %res to %buffer(%shape) typeparams %c50 : !fir.array<?x!fir.char<1,?>>, !fir.ref<!fir.array<?x!fir.char<1,?>>>, !fir.shape<1>, index
237  return
238
239  // FUNC-REF: %[[c100:.*]] = arith.constant 100 : index
240  // FUNC-REF: %[[c50:.*]] = arith.constant 50 : index
241  // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.array<?x!fir.char<1,?>>(%[[c100]] : index), %[[c50]]
242  // FUNC-REF: fir.call @chararrayfunc(%[[buffer]], %[[c100]], %[[c50]]) : (!fir.ref<!fir.array<?x!fir.char<1,?>>>, index, index) -> ()
243  // FUNC-REF-NOT: fir.save_result
244
245  // FUNC-BOX: %[[c100:.*]] = arith.constant 100 : index
246  // FUNC-BOX: %[[c50:.*]] = arith.constant 50 : index
247  // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.array<?x!fir.char<1,?>>(%[[c100]] : index), %[[c50]]
248  // FUNC-BOX: %[[shape:.*]] = fir.shape %[[c100]] : (index) -> !fir.shape<1>
249  // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]](%[[shape]]) typeparams %[[c50]] : (!fir.ref<!fir.array<?x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.box<!fir.array<?x!fir.char<1,?>>>
250  // FUNC-BOX: fir.call @chararrayfunc(%[[box]], %[[c100]], %[[c50]]) : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index, index) -> ()
251  // FUNC-BOX-NOT: fir.save_result
252}
253
254// FUNC-REF-LABEL: func @_QPtest_return_cptr
255// FUNC-BOX-LABEL: func @_QPtest_return_cptr
256func.func @_QPtest_return_cptr() {
257  %0 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
258  %1 = fir.call @retcptr() : () -> i64
259  %2 = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
260  %3 = fir.coordinate_of %0, %2 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64>
261  fir.store %1 to %3 : !fir.ref<i64>
262  return
263
264  // FUNC-REF: %[[ALLOC:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
265  // FUNC-REF: %[[VAL:.*]] = fir.call @retcptr() : () -> i64
266  // FUNC-REF: %[[FIELD:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
267  // FUNC-REF: %[[ADDR:.*]] = fir.coordinate_of %[[ALLOC]], %[[FIELD]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64>
268  // FUNC-REF: fir.store %[[VAL]] to %[[ADDR]] : !fir.ref<i64>
269  // FUNC-BOX: %[[ALLOC:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
270  // FUNC-BOX: %[[VAL:.*]] = fir.call @retcptr() : () -> i64
271  // FUNC-BOX: %[[FIELD:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
272  // FUNC-BOX: %[[ADDR:.*]] = fir.coordinate_of %[[ALLOC]], %[[FIELD]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64>
273  // FUNC-BOX: fir.store %[[VAL]] to %[[ADDR]] : !fir.ref<i64>
274}
275
276// FUNC-REF-LABEL: func @dispatch(
277// FUNC-REF-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}
278// FUNC-BOX-LABEL: func @dispatch(
279// FUNC-BOX-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}
280func.func @dispatch(%arg0: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) {
281  %buffer = fir.alloca !fir.type<t{x:f32}>
282  %res = fir.dispatch "ret_array"(%arg0 : !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) (%arg0 : !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.type<t{x:f32}> {pass_arg_pos = 0 : i32}
283  fir.save_result %res to %buffer : !fir.type<t{x:f32}>, !fir.ref<!fir.type<t{x:f32}>>
284  return
285  // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.type<t{x:f32}>
286  // FUNC-REF: fir.dispatch "ret_array"(%[[ARG0]] : !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) (%[[buffer]], %[[ARG0]] : !fir.ref<!fir.type<t{x:f32}>>, !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) {pass_arg_pos = 1 : i32}
287  // FUNC-REF-NOT: fir.save_result
288
289  // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.type<t{x:f32}>
290  // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]] : (!fir.ref<!fir.type<t{x:f32}>>) -> !fir.box<!fir.type<t{x:f32}>>
291  // FUNC-BOX: fir.dispatch "ret_array"(%[[ARG0]] : !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) (%[[box]], %[[ARG0]] : !fir.box<!fir.type<t{x:f32}>>, !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) {pass_arg_pos = 1 : i32}
292  // FUNC-BOX-NOT: fir.save_result
293}
294
295// ------------------------ Test fir.address_of rewrite ------------------------
296
297func.func private @takesfuncarray((i32) -> !fir.array<?xf32>)
298
299// FUNC-REF-LABEL: func @test_address_of() {
300// FUNC-BOX-LABEL: func @test_address_of() {
301func.func @test_address_of() {
302  %0 = fir.address_of(@arrayfunc) : (i32) -> !fir.array<?xf32>
303  fir.call @takesfuncarray(%0) : ((i32) -> !fir.array<?xf32>) -> ()
304  return
305
306  // FUNC-REF: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.ref<!fir.array<?xf32>>, i32) -> ()
307  // FUNC-REF: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.ref<!fir.array<?xf32>>, i32) -> ()) -> ((i32) -> !fir.array<?xf32>)
308  // FUNC-REF: fir.call @takesfuncarray(%[[conv]]) : ((i32) -> !fir.array<?xf32>) -> ()
309
310  // FUNC-BOX: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.box<!fir.array<?xf32>>, i32) -> ()
311  // FUNC-BOX: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.box<!fir.array<?xf32>>, i32) -> ()) -> ((i32) -> !fir.array<?xf32>)
312  // FUNC-BOX: fir.call @takesfuncarray(%[[conv]]) : ((i32) -> !fir.array<?xf32>) -> ()
313
314}
315
316// FUNC-REF-LABEL: func.func private @returns_null() -> !fir.ref<none>
317// FUNC-BOX-LABEL: func.func private @returns_null() -> !fir.ref<none>
318func.func private @returns_null() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
319
320// FUNC-REF-LABEL: func @test_address_of_cptr
321// FUNC-BOX-LABEL: func @test_address_of_cptr
322func.func @test_address_of_cptr() {
323  %0 = fir.address_of(@returns_null) : () -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
324  %1 = fir.convert %0 : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> ())
325  fir.call @_QMtest_c_func_modPsubr(%1) : (() -> ()) -> ()
326  return
327
328  // FUNC-REF: %[[VAL_0:.*]] = fir.address_of(@returns_null) : () -> !fir.ref<none>
329  // FUNC-REF: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (() -> !fir.ref<none>) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
330  // FUNC-REF: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> ())
331  // FUNC-REF: fir.call @_QMtest_c_func_modPsubr(%[[VAL_2]]) : (() -> ()) -> ()
332  // FUNC-BOX: %[[VAL_0:.*]] = fir.address_of(@returns_null) : () -> !fir.ref<none>
333  // FUNC-BOX: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (() -> !fir.ref<none>) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
334  // FUNC-BOX: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> ())
335  // FUNC-BOX: fir.call @_QMtest_c_func_modPsubr(%[[VAL_2]]) : (() -> ()) -> ()
336}
337
338
339// ----------------------- Test indirect calls rewrite ------------------------
340
341// FUNC-REF-LABEL: func @test_indirect_calls(
342// FUNC-REF-SAME: %[[arg0:.*]]: () -> ()) {
343// FUNC-BOX-LABEL: func @test_indirect_calls(
344// FUNC-BOX-SAME: %[[arg0:.*]]: () -> ()) {
345func.func @test_indirect_calls(%arg0: () -> ()) {
346  %c100 = arith.constant 100 : index
347  %buffer = fir.alloca !fir.array<?xf32>, %c100
348  %shape = fir.shape %c100 : (index) -> !fir.shape<1>
349  %0 = fir.convert %arg0 : (() -> ()) -> ((index) -> !fir.array<?xf32>)
350  %res = fir.call %0(%c100) : (index) -> !fir.array<?xf32>
351  fir.save_result %res to %buffer(%shape) : !fir.array<?xf32>, !fir.ref<!fir.array<?xf32>>, !fir.shape<1>
352  return
353
354  // FUNC-REF: %[[c100:.*]] = arith.constant 100 : index
355  // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.array<?xf32>, %[[c100]]
356  // FUNC-REF: %[[shape:.*]] = fir.shape %[[c100]] : (index) -> !fir.shape<1>
357  // FUNC-REF: %[[original_conv:.*]] = fir.convert %[[arg0]] : (() -> ()) -> ((index) -> !fir.array<?xf32>)
358  // FUNC-REF: %[[conv:.*]] = fir.convert %[[original_conv]] : ((index) -> !fir.array<?xf32>) -> ((!fir.ref<!fir.array<?xf32>>, index) -> ())
359  // FUNC-REF: fir.call %[[conv]](%[[buffer]], %c100) : (!fir.ref<!fir.array<?xf32>>, index) -> ()
360  // FUNC-REF-NOT: fir.save_result
361
362  // FUNC-BOX: %[[c100:.*]] = arith.constant 100 : index
363  // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.array<?xf32>, %[[c100]]
364  // FUNC-BOX: %[[shape:.*]] = fir.shape %[[c100]] : (index) -> !fir.shape<1>
365  // FUNC-BOX: %[[original_conv:.*]] = fir.convert %[[arg0]] : (() -> ()) -> ((index) -> !fir.array<?xf32>)
366  // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]](%[[shape]]) : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
367  // FUNC-BOX: %[[conv:.*]] = fir.convert %[[original_conv]] : ((index) -> !fir.array<?xf32>) -> ((!fir.box<!fir.array<?xf32>>, index) -> ())
368  // FUNC-BOX: fir.call %[[conv]](%[[box]], %c100) : (!fir.box<!fir.array<?xf32>>, index) -> ()
369  // FUNC-BOX-NOT: fir.save_result
370}
371
372// FUNC-REF-LABEL: func @test_indirect_calls_return_cptr(
373// FUNC-REF-SAME: %[[ARG0:.*]]: () -> ())
374// FUNC-BOX-LABEL: func @test_indirect_calls_return_cptr(
375// FUNC-BOX-SAME: %[[ARG0:.*]]: () -> ())
376func.func @test_indirect_calls_return_cptr(%arg0: () -> ()) {
377  %0 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
378  %1 = fir.convert %arg0 : (() -> ()) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
379  %2 = fir.call %1() : () -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
380  fir.save_result %2 to %0 : !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>
381  return
382
383  // FUNC-REF: %[[VAL_0:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
384  // FUNC-REF: %[[VAL_1:.*]] = fir.convert %[[ARG0]] : (() -> ()) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
385  // FUNC-REF: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> !fir.ref<none>)
386  // FUNC-REF: %[[VAL_3:.*]] = fir.call %[[VAL_2]]() : () -> !fir.ref<none>
387  // FUNC-REF: %[[VAL_4:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
388  // FUNC-REF: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_4]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64>
389  // FUNC-REF: %[[CAST:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<none>) -> i64
390  // FUNC-REF: fir.store %[[CAST]] to %[[VAL_5]] : !fir.ref<i64>
391  // FUNC-BOX: %[[VAL_0:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
392  // FUNC-BOX: %[[VAL_1:.*]] = fir.convert %[[ARG0]] : (() -> ()) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
393  // FUNC-BOX: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> !fir.ref<none>)
394  // FUNC-BOX: %[[VAL_3:.*]] = fir.call %[[VAL_2]]() : () -> !fir.ref<none>
395  // FUNC-BOX: %[[VAL_4:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
396  // FUNC-BOX: %[[VAL_5:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_4]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64>
397  // FUNC-BOX: %[[CAST:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<none>) -> i64
398  // FUNC-BOX: fir.store %[[CAST]] to %[[VAL_5]] : !fir.ref<i64>
399}
400
401// ----------------------- Test GlobalOp rewrite ------------------------
402
403// This is needed to separate GlobalOp tests from FuncOp tests for FileCheck
404// FUNC-REF-LABEL: fir.global {{.*}} : {{.*}} {
405// FUNC-BOX-LABEL: fir.global {{.*}} : {{.*}} {
406
407// GLOBAL-REF-LABEL: fir.global @global_test_address_of : i32 {
408// GLOBAL-BOX-LABEL: fir.global @global_test_address_of : i32 {
409fir.global @global_test_address_of : i32 {
410  %0 = fir.address_of(@arrayfunc) : (i32) -> !fir.array<?xf32>
411
412  // GLOBAL-REF: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.ref<!fir.array<?xf32>>, i32) -> ()
413  // GLOBAL-REF: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.ref<!fir.array<?xf32>>, i32) -> ()) -> ((i32) -> !fir.array<?xf32>)
414
415  // GLOBAL-BOX: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.box<!fir.array<?xf32>>, i32) -> ()
416  // GLOBAL-BOX: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.box<!fir.array<?xf32>>, i32) -> ()) -> ((i32) -> !fir.array<?xf32>)
417
418  %c42 = arith.constant 42 : i32
419  fir.has_value %c42 : i32
420}
421