Break circular dependency between FIR dialect and utilities
[llvm-project.git] / flang / test / Fir / abstract-results.fir
blob374c0d18753bbcb5a1c7bb46d2c4cd19ab7e18d6
1 // Test rewrite of functions that return fir.array<>, fir.type<>, fir.box<> to
2 // functions that take an additional argument for the result.
4 // RUN: fir-opt %s --abstract-result-on-func-opt | FileCheck %s --check-prefix=FUNC-REF
5 // RUN: fir-opt %s --abstract-result-on-func-opt=abstract-result-as-box | FileCheck %s --check-prefix=FUNC-BOX
6 // RUN: fir-opt %s --abstract-result-on-global-opt | FileCheck %s --check-prefix=GLOBAL-REF
7 // RUN: fir-opt %s --abstract-result-on-global-opt=abstract-result-as-box | FileCheck %s --check-prefix=GLOBAL-BOX
9 // ----------------------- Test declaration rewrite ----------------------------
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)
13 func.func private @arrayfunc(i32) -> !fir.array<?xf32>
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)
17 func.func private @derivedfunc(f32) -> !fir.type<t{x:f32}>
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)
21 func.func private @boxfunc(i64) -> !fir.box<!fir.heap<f64>>
24 // ------------------------ Test callee rewrite --------------------------------
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) {
30 func.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>
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
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
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) {
55 func.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}>
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
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
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>>>) {
77 func.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
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
90 // FUNC-REF-LABEL: func @retcptr() -> i64
91 // FUNC-BOX-LABEL: func @retcptr() -> i64
92 func.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}>
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: return %[[VAL]] : i64
102   // FUNC-BOX: %[[ALLOC:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = "rec", uniq_name = "_QFrecErec"}
103   // FUNC-BOX: %[[FIELD:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
104   // 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>
105   // FUNC-BOX: %[[VAL:.*]] = fir.load %[[ADDR]] : !fir.ref<i64>
106   // FUNC-BOX: return %[[VAL]] : i64
110 // ------------------------ Test caller rewrite --------------------------------
112 // FUNC-REF-LABEL: func @call_arrayfunc() {
113 // FUNC-BOX-LABEL: func @call_arrayfunc() {
114 func.func @call_arrayfunc() {
115   %c100 = arith.constant 100 : index
116   %buffer = fir.alloca !fir.array<?xf32>, %c100
117   %shape = fir.shape %c100 : (index) -> !fir.shape<1>
118   %res = fir.call @arrayfunc_callee(%c100) : (index) -> !fir.array<?xf32>
119   fir.save_result %res to %buffer(%shape) : !fir.array<?xf32>, !fir.ref<!fir.array<?xf32>>, !fir.shape<1>
120   return
122   // FUNC-REF: %[[c100:.*]] = arith.constant 100 : index
123   // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.array<?xf32>, %[[c100]]
124   // FUNC-REF: fir.call @arrayfunc_callee(%[[buffer]], %[[c100]]) : (!fir.ref<!fir.array<?xf32>>, index) -> ()
125   // FUNC-REF-NOT: fir.save_result
127   // FUNC-BOX: %[[c100:.*]] = arith.constant 100 : index
128   // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.array<?xf32>, %[[c100]]
129   // FUNC-BOX: %[[shape:.*]] = fir.shape %[[c100]] : (index) -> !fir.shape<1>
130   // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]](%[[shape]]) : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
131   // FUNC-BOX: fir.call @arrayfunc_callee(%[[box]], %[[c100]]) : (!fir.box<!fir.array<?xf32>>, index) -> ()
132   // FUNC-BOX-NOT: fir.save_result
135 // FUNC-REF-LABEL: func @call_derivedfunc() {
136 // FUNC-BOX-LABEL: func @call_derivedfunc() {
137 func.func @call_derivedfunc() {
138   %buffer = fir.alloca !fir.type<t{x:f32}>
139   %cst = arith.constant 4.200000e+01 : f32
140   %res = fir.call @derivedfunc_callee(%cst) : (f32) -> !fir.type<t{x:f32}>
141   fir.save_result %res to %buffer : !fir.type<t{x:f32}>, !fir.ref<!fir.type<t{x:f32}>>
142   return
143   // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.type<t{x:f32}>
144   // FUNC-REF: %[[cst:.*]] = arith.constant {{.*}} : f32
145   // FUNC-REF: fir.call @derivedfunc_callee(%[[buffer]], %[[cst]]) : (!fir.ref<!fir.type<t{x:f32}>>, f32) -> ()
146   // FUNC-REF-NOT: fir.save_result
148   // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.type<t{x:f32}>
149   // FUNC-BOX: %[[cst:.*]] = arith.constant {{.*}} : f32
150   // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]] : (!fir.ref<!fir.type<t{x:f32}>>) -> !fir.box<!fir.type<t{x:f32}>>
151   // FUNC-BOX: fir.call @derivedfunc_callee(%[[box]], %[[cst]]) : (!fir.box<!fir.type<t{x:f32}>>, f32) -> ()
152   // FUNC-BOX-NOT: fir.save_result
155 func.func private @derived_lparams_func() -> !fir.type<t2(l1:i32,l2:i32){x:f32}>
157 // FUNC-REF-LABEL: func @call_derived_lparams_func(
158 // FUNC-REF-SAME: %[[buffer:.*]]: !fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>
159 // FUNC-BOX-LABEL: func @call_derived_lparams_func(
160 // FUNC-BOX-SAME: %[[buffer:.*]]: !fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>
161 func.func @call_derived_lparams_func(%buffer: !fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>) {
162   %l1 = arith.constant 3 : i32
163   %l2 = arith.constant 5 : i32
164   %res = fir.call @derived_lparams_func() : () -> !fir.type<t2(l1:i32,l2:i32){x:f32}>
165   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
166   return
168   // FUNC-REF: %[[l1:.*]] = arith.constant 3 : i32
169   // FUNC-REF: %[[l2:.*]] = arith.constant 5 : i32
170   // FUNC-REF: fir.call @derived_lparams_func(%[[buffer]]) : (!fir.ref<!fir.type<t2(l1:i32,l2:i32){x:f32}>>) -> ()
171   // FUNC-REF-NOT: fir.save_result
173   // FUNC-BOX: %[[l1:.*]] = arith.constant 3 : i32
174   // FUNC-BOX: %[[l2:.*]] = arith.constant 5 : i32
175   // 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}>>
176   // FUNC-BOX: fir.call @derived_lparams_func(%[[box]]) : (!fir.box<!fir.type<t2(l1:i32,l2:i32){x:f32}>>) -> ()
177   // FUNC-BOX-NOT: fir.save_result
180 // FUNC-REF-LABEL: func @call_boxfunc() {
181 // FUNC-BOX-LABEL: func @call_boxfunc() {
182 func.func @call_boxfunc() {
183   %buffer = fir.alloca !fir.box<!fir.heap<f64>>
184   %res = fir.call @boxfunc_callee() : () -> !fir.box<!fir.heap<f64>>
185   fir.save_result %res to %buffer: !fir.box<!fir.heap<f64>>, !fir.ref<!fir.box<!fir.heap<f64>>>
186   return
188   // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.box<!fir.heap<f64>>
189   // FUNC-REF: fir.call @boxfunc_callee(%[[buffer]]) : (!fir.ref<!fir.box<!fir.heap<f64>>>) -> ()
190   // FUNC-REF-NOT: fir.save_result
192   // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.box<!fir.heap<f64>>
193   // FUNC-BOX: fir.call @boxfunc_callee(%[[buffer]]) : (!fir.ref<!fir.box<!fir.heap<f64>>>) -> ()
194   // FUNC-BOX-NOT: fir.save_result
197 func.func private @chararrayfunc(index, index) -> !fir.array<?x!fir.char<1,?>>
199 // FUNC-REF-LABEL: func @call_chararrayfunc() {
200 // FUNC-BOX-LABEL: func @call_chararrayfunc() {
201 func.func @call_chararrayfunc() {
202   %c100 = arith.constant 100 : index
203   %c50 = arith.constant 50 : index
204   %buffer = fir.alloca !fir.array<?x!fir.char<1,?>>(%c100 : index), %c50
205   %shape = fir.shape %c100 : (index) -> !fir.shape<1>
206   %res = fir.call @chararrayfunc(%c100, %c50) : (index, index) -> !fir.array<?x!fir.char<1,?>>
207   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
208   return
210   // FUNC-REF: %[[c100:.*]] = arith.constant 100 : index
211   // FUNC-REF: %[[c50:.*]] = arith.constant 50 : index
212   // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.array<?x!fir.char<1,?>>(%[[c100]] : index), %[[c50]]
213   // FUNC-REF: fir.call @chararrayfunc(%[[buffer]], %[[c100]], %[[c50]]) : (!fir.ref<!fir.array<?x!fir.char<1,?>>>, index, index) -> ()
214   // FUNC-REF-NOT: fir.save_result
216   // FUNC-BOX: %[[c100:.*]] = arith.constant 100 : index
217   // FUNC-BOX: %[[c50:.*]] = arith.constant 50 : index
218   // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.array<?x!fir.char<1,?>>(%[[c100]] : index), %[[c50]]
219   // FUNC-BOX: %[[shape:.*]] = fir.shape %[[c100]] : (index) -> !fir.shape<1>
220   // 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,?>>>
221   // FUNC-BOX: fir.call @chararrayfunc(%[[box]], %[[c100]], %[[c50]]) : (!fir.box<!fir.array<?x!fir.char<1,?>>>, index, index) -> ()
222   // FUNC-BOX-NOT: fir.save_result
225 // FUNC-REF-LABEL: func @_QPtest_return_cptr
226 // FUNC-BOX-LABEL: func @_QPtest_return_cptr
227 func.func @_QPtest_return_cptr() {
228   %0 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
229   %1 = fir.call @retcptr() : () -> i64
230   %2 = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
231   %3 = fir.coordinate_of %0, %2 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64>
232   fir.store %1 to %3 : !fir.ref<i64>
233   return
235   // FUNC-REF: %[[ALLOC:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
236   // FUNC-REF: %[[VAL:.*]] = fir.call @retcptr() : () -> i64
237   // FUNC-REF: %[[FIELD:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
238   // 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>
239   // FUNC-REF: fir.store %[[VAL]] to %[[ADDR]] : !fir.ref<i64>
240   // FUNC-BOX: %[[ALLOC:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
241   // FUNC-BOX: %[[VAL:.*]] = fir.call @retcptr() : () -> i64
242   // FUNC-BOX: %[[FIELD:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
243   // 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>
244   // FUNC-BOX: fir.store %[[VAL]] to %[[ADDR]] : !fir.ref<i64>
247 // FUNC-REF-LABEL: func @dispatch(
248 // FUNC-REF-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}
249 // FUNC-BOX-LABEL: func @dispatch(
250 // FUNC-BOX-SAME:    %[[ARG0:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}
251 func.func @dispatch(%arg0: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) {
252   %buffer = fir.alloca !fir.type<t{x:f32}>
253   %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}
254   fir.save_result %res to %buffer : !fir.type<t{x:f32}>, !fir.ref<!fir.type<t{x:f32}>>
255   return
256   // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.type<t{x:f32}>
257   // 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}
258   // FUNC-REF-NOT: fir.save_result
260   // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.type<t{x:f32}>
261   // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]] : (!fir.ref<!fir.type<t{x:f32}>>) -> !fir.box<!fir.type<t{x:f32}>>
262   // 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}
263   // FUNC-BOX-NOT: fir.save_result
266 // ------------------------ Test fir.address_of rewrite ------------------------
268 func.func private @takesfuncarray((i32) -> !fir.array<?xf32>)
270 // FUNC-REF-LABEL: func @test_address_of() {
271 // FUNC-BOX-LABEL: func @test_address_of() {
272 func.func @test_address_of() {
273   %0 = fir.address_of(@arrayfunc) : (i32) -> !fir.array<?xf32>
274   fir.call @takesfuncarray(%0) : ((i32) -> !fir.array<?xf32>) -> ()
275   return
277   // FUNC-REF: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.ref<!fir.array<?xf32>>, i32) -> ()
278   // FUNC-REF: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.ref<!fir.array<?xf32>>, i32) -> ()) -> ((i32) -> !fir.array<?xf32>)
279   // FUNC-REF: fir.call @takesfuncarray(%[[conv]]) : ((i32) -> !fir.array<?xf32>) -> ()
281   // FUNC-BOX: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.box<!fir.array<?xf32>>, i32) -> ()
282   // FUNC-BOX: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.box<!fir.array<?xf32>>, i32) -> ()) -> ((i32) -> !fir.array<?xf32>)
283   // FUNC-BOX: fir.call @takesfuncarray(%[[conv]]) : ((i32) -> !fir.array<?xf32>) -> ()
287 // FUNC-REF-LABEL: func.func private @returns_null() -> i64
288 // FUNC-BOX-LABEL: func.func private @returns_null() -> i64
289 func.func private @returns_null() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
291 // FUNC-REF-LABEL: func @test_address_of_cptr
292 // FUNC-BOX-LABEL: func @test_address_of_cptr
293 func.func @test_address_of_cptr() {
294   %0 = fir.address_of(@returns_null) : () -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
295   %1 = fir.convert %0 : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> ())
296   fir.call @_QMtest_c_func_modPsubr(%1) : (() -> ()) -> ()
297   return
299   // FUNC-REF: %[[VAL_0:.*]] = fir.address_of(@returns_null) : () -> i64
300   // FUNC-REF: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (() -> i64) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
301   // FUNC-REF: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> ())
302   // FUNC-REF: fir.call @_QMtest_c_func_modPsubr(%[[VAL_2]]) : (() -> ()) -> ()
303   // FUNC-BOX: %[[VAL_0:.*]] = fir.address_of(@returns_null) : () -> i64
304   // FUNC-BOX: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (() -> i64) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
305   // FUNC-BOX: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> ())
306   // FUNC-BOX: fir.call @_QMtest_c_func_modPsubr(%[[VAL_2]]) : (() -> ()) -> ()
310 // ----------------------- Test indirect calls rewrite ------------------------
312 // FUNC-REF-LABEL: func @test_indirect_calls(
313 // FUNC-REF-SAME: %[[arg0:.*]]: () -> ()) {
314 // FUNC-BOX-LABEL: func @test_indirect_calls(
315 // FUNC-BOX-SAME: %[[arg0:.*]]: () -> ()) {
316 func.func @test_indirect_calls(%arg0: () -> ()) {
317   %c100 = arith.constant 100 : index
318   %buffer = fir.alloca !fir.array<?xf32>, %c100
319   %shape = fir.shape %c100 : (index) -> !fir.shape<1>
320   %0 = fir.convert %arg0 : (() -> ()) -> ((index) -> !fir.array<?xf32>)
321   %res = fir.call %0(%c100) : (index) -> !fir.array<?xf32>
322   fir.save_result %res to %buffer(%shape) : !fir.array<?xf32>, !fir.ref<!fir.array<?xf32>>, !fir.shape<1>
323   return
325   // FUNC-REF: %[[c100:.*]] = arith.constant 100 : index
326   // FUNC-REF: %[[buffer:.*]] = fir.alloca !fir.array<?xf32>, %[[c100]]
327   // FUNC-REF: %[[shape:.*]] = fir.shape %[[c100]] : (index) -> !fir.shape<1>
328   // FUNC-REF: %[[original_conv:.*]] = fir.convert %[[arg0]] : (() -> ()) -> ((index) -> !fir.array<?xf32>)
329   // FUNC-REF: %[[conv:.*]] = fir.convert %[[original_conv]] : ((index) -> !fir.array<?xf32>) -> ((!fir.ref<!fir.array<?xf32>>, index) -> ())
330   // FUNC-REF: fir.call %[[conv]](%[[buffer]], %c100) : (!fir.ref<!fir.array<?xf32>>, index) -> ()
331   // FUNC-REF-NOT: fir.save_result
333   // FUNC-BOX: %[[c100:.*]] = arith.constant 100 : index
334   // FUNC-BOX: %[[buffer:.*]] = fir.alloca !fir.array<?xf32>, %[[c100]]
335   // FUNC-BOX: %[[shape:.*]] = fir.shape %[[c100]] : (index) -> !fir.shape<1>
336   // FUNC-BOX: %[[original_conv:.*]] = fir.convert %[[arg0]] : (() -> ()) -> ((index) -> !fir.array<?xf32>)
337   // FUNC-BOX: %[[box:.*]] = fir.embox %[[buffer]](%[[shape]]) : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
338   // FUNC-BOX: %[[conv:.*]] = fir.convert %[[original_conv]] : ((index) -> !fir.array<?xf32>) -> ((!fir.box<!fir.array<?xf32>>, index) -> ())
339   // FUNC-BOX: fir.call %[[conv]](%[[box]], %c100) : (!fir.box<!fir.array<?xf32>>, index) -> ()
340   // FUNC-BOX-NOT: fir.save_result
343 // FUNC-REF-LABEL: func @test_indirect_calls_return_cptr(
344 // FUNC-REF-SAME: %[[ARG0:.*]]: () -> ())
345 // FUNC-BOX-LABEL: func @test_indirect_calls_return_cptr(
346 // FUNC-BOX-SAME: %[[ARG0:.*]]: () -> ())
347 func.func @test_indirect_calls_return_cptr(%arg0: () -> ()) {
348   %0 = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
349   %1 = fir.convert %arg0 : (() -> ()) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
350   %2 = fir.call %1() : () -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
351   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}>>
352   return
354   // FUNC-REF: %[[VAL_0:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
355   // FUNC-REF: %[[VAL_1:.*]] = fir.convert %[[ARG0]] : (() -> ()) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
356   // FUNC-REF: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> i64)
357   // FUNC-REF: %[[VAL_3:.*]] = fir.call %[[VAL_2]]() : () -> i64
358   // FUNC-REF: %[[VAL_4:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
359   // 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>
360   // FUNC-REF: fir.store %[[VAL_3]] to %[[VAL_5]] : !fir.ref<i64>
361   // FUNC-BOX: %[[VAL_0:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> {bindc_name = ".result"}
362   // FUNC-BOX: %[[VAL_1:.*]] = fir.convert %[[ARG0]] : (() -> ()) -> (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>)
363   // FUNC-BOX: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (() -> !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>) -> (() -> i64)
364   // FUNC-BOX: %[[VAL_3:.*]] = fir.call %[[VAL_2]]() : () -> i64
365   // FUNC-BOX: %[[VAL_4:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>
366   // 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>
367   // FUNC-BOX: fir.store %[[VAL_3]] to %[[VAL_5]] : !fir.ref<i64>
370 // ----------------------- Test GlobalOp rewrite ------------------------
372 // This is needed to separate GlobalOp tests from FuncOp tests for FileCheck
373 // FUNC-REF-LABEL: fir.global {{.*}} : {{.*}} {
374 // FUNC-BOX-LABEL: fir.global {{.*}} : {{.*}} {
376 // GLOBAL-REF-LABEL: fir.global @global_test_address_of : i32 {
377 // GLOBAL-BOX-LABEL: fir.global @global_test_address_of : i32 {
378 fir.global @global_test_address_of : i32 {
379   %0 = fir.address_of(@arrayfunc) : (i32) -> !fir.array<?xf32>
381   // GLOBAL-REF: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.ref<!fir.array<?xf32>>, i32) -> ()
382   // GLOBAL-REF: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.ref<!fir.array<?xf32>>, i32) -> ()) -> ((i32) -> !fir.array<?xf32>)
384   // GLOBAL-BOX: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.box<!fir.array<?xf32>>, i32) -> ()
385   // GLOBAL-BOX: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.box<!fir.array<?xf32>>, i32) -> ()) -> ((i32) -> !fir.array<?xf32>)
387   %c42 = arith.constant 42 : i32
388   fir.has_value %c42 : i32