1! RUN: bbc -emit-fir %s -o - | FileCheck %s
2
3! Test procedure declarations. Change appearance order of definition and usages
4! (passing a procedure and calling it), with and without definitions.
5! Check that the definition type prevail if available and that casts are inserted to
6! accommodate for the signature mismatch in the different location due to implicit
7! typing rules and Fortran loose interface compatibility rule history.
8
9
10! Note: all the cases where their is a definition are exactly the same,
11! since definition should be processed first regardless.
12
13! pass, call, define
14! CHECK-LABEL: func @_QPpass_foo() {
15subroutine pass_foo()
16  external :: foo
17  ! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo)
18  ! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
19  call bar(foo)
20end subroutine
21! CHECK-LABEL: func @_QPcall_foo(
22! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
23subroutine call_foo(i)
24  integer :: i(10)
25  ! %[[argconvert:*]] = fir.convert %arg0 :
26  ! fir.call @_QPfoo(%[[argconvert]]) : (!fir.ref<!fir.array<2x5xi32>>) -> ()
27  call foo(i)
28end subroutine
29! CHECK-LABEL: func @_QPfoo(
30! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
31subroutine foo(i)
32  integer :: i(2, 5)
33  call do_something(i)
34end subroutine
35
36! call, pass, define
37! CHECK-LABEL: func @_QPcall_foo2(
38! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
39subroutine call_foo2(i)
40  integer :: i(10)
41  ! %[[argconvert:*]] = fir.convert %arg0 :
42  ! fir.call @_QPfoo2(%[[argconvert]]) : (!fir.ref<!fir.array<2x5xi32>>) -> ()
43  call foo2(i)
44end subroutine
45! CHECK-LABEL: func @_QPpass_foo2() {
46subroutine pass_foo2()
47  external :: foo2
48  ! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo2)
49  ! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
50  call bar(foo2)
51end subroutine
52! CHECK-LABEL: func @_QPfoo2(
53! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
54subroutine foo2(i)
55  integer :: i(2, 5)
56  call do_something(i)
57end subroutine
58
59! call, define, pass
60! CHECK-LABEL: func @_QPcall_foo3(
61! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
62subroutine call_foo3(i)
63  integer :: i(10)
64  ! %[[argconvert:*]] = fir.convert %arg0 :
65  ! fir.call @_QPfoo3(%[[argconvert]]) : (!fir.ref<!fir.array<2x5xi32>>) -> ()
66  call foo3(i)
67end subroutine
68! CHECK-LABEL: func @_QPfoo3(
69! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
70subroutine foo3(i)
71  integer :: i(2, 5)
72  call do_something(i)
73end subroutine
74! CHECK-LABEL: func @_QPpass_foo3() {
75subroutine pass_foo3()
76  external :: foo3
77  ! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo3)
78  ! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
79  call bar(foo3)
80end subroutine
81
82! define, call, pass
83! CHECK-LABEL: func @_QPfoo4(
84! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
85subroutine foo4(i)
86  integer :: i(2, 5)
87  call do_something(i)
88end subroutine
89! CHECK-LABEL: func @_QPcall_foo4(
90! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
91subroutine call_foo4(i)
92  integer :: i(10)
93  ! %[[argconvert:*]] = fir.convert %arg0 :
94  ! fir.call @_QPfoo4(%[[argconvert]]) : (!fir.ref<!fir.array<2x5xi32>>) -> ()
95  call foo4(i)
96end subroutine
97! CHECK-LABEL: func @_QPpass_foo4() {
98subroutine pass_foo4()
99  external :: foo4
100  ! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo4)
101  ! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
102  call bar(foo4)
103end subroutine
104
105! define, pass, call
106! CHECK-LABEL: func @_QPfoo5(
107! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
108subroutine foo5(i)
109  integer :: i(2, 5)
110  call do_something(i)
111end subroutine
112! CHECK-LABEL: func @_QPpass_foo5() {
113subroutine pass_foo5()
114  external :: foo5
115  ! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo5)
116  ! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<2x5xi32>>) -> ()) -> !fir.boxproc<() -> ()>
117  call bar(foo5)
118end subroutine
119! CHECK-LABEL: func @_QPcall_foo5(
120! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
121subroutine call_foo5(i)
122  integer :: i(10)
123  ! %[[argconvert:*]] = fir.convert %arg0 :
124  ! fir.call @_QPfoo5(%[[argconvert]]) : (!fir.ref<!fir.array<2x5xi32>>) -> ()
125  call foo5(i)
126end subroutine
127
128
129! Test when there is no definition (declaration at the end of the mlir module)
130! First use gives the function type
131
132! call, pass
133! CHECK-LABEL: func @_QPcall_foo6(
134! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
135subroutine call_foo6(i)
136  integer :: i(10)
137  ! CHECK-NOT: convert
138  call foo6(i)
139end subroutine
140! CHECK-LABEL: func @_QPpass_foo6() {
141subroutine pass_foo6()
142  external :: foo6
143  ! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo6) : (!fir.ref<!fir.array<10xi32>>) -> ()
144  ! CHECK: fir.emboxproc %[[f]] : ((!fir.ref<!fir.array<10xi32>>) -> ()) -> !fir.boxproc<() -> ()>
145  call bar(foo6)
146end subroutine
147
148! pass, call
149! CHECK-LABEL: func @_QPpass_foo7() {
150subroutine pass_foo7()
151  external :: foo7
152  ! CHECK-NOT: convert
153  call bar(foo7)
154end subroutine
155! CHECK-LABEL: func @_QPcall_foo7(
156! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) -> f32 {
157function call_foo7(i)
158  integer :: i(10)
159  ! CHECK: %[[f:.*]] = fir.address_of(@_QPfoo7) : () -> ()
160  ! CHECK: %[[funccast:.*]] = fir.convert %[[f]] : (() -> ()) -> ((!fir.ref<!fir.array<10xi32>>) -> f32)
161  ! CHECK: fir.call %[[funccast]](%arg0) : (!fir.ref<!fir.array<10xi32>>) -> f32
162  call_foo7 =  foo7(i)
163end function
164
165
166! call, call with different type
167! CHECK-LABEL: func @_QPcall_foo8(
168! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<10xi32>>{{.*}}) {
169subroutine call_foo8(i)
170  integer :: i(10)
171  ! CHECK-NOT: convert
172  call foo8(i)
173end subroutine
174! CHECK-LABEL: func @_QPcall_foo8_2(
175! CHECK-SAME: %{{.*}}: !fir.ref<!fir.array<2x5xi32>>{{.*}}) {
176subroutine call_foo8_2(i)
177  integer :: i(2, 5)
178  ! %[[argconvert:*]] = fir.convert %arg0 :
179  call foo8(i)
180end subroutine
181
182! Test that target attribute is lowered in declaration of functions that are
183! not defined in this file.
184! CHECK-LABEL:func @_QPtest_target_in_iface
185subroutine test_target_in_iface()
186  interface
187  subroutine test_target(i, x)
188    integer, target :: i
189    real, target :: x(:)
190  end subroutine
191  end interface
192  integer :: i
193  real :: x(10)
194  ! CHECK: fir.call @_QPtest_target
195  call test_target(i, x)
196end subroutine
197
198! CHECK: func private @_QPfoo6(!fir.ref<!fir.array<10xi32>>)
199! CHECK: func private @_QPfoo7()
200
201! Test declaration from test_target_in_iface
202! CHECK-LABEL: func private @_QPtest_target(!fir.ref<i32> {fir.target}, !fir.box<!fir.array<?xf32>> {fir.target})
203