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