xref: /llvm-project/llvm/test/Transforms/ExpandVariadics/expand-va-intrinsic-split-linkage.ll (revision 8516f54e6a984a79d1a988ec66a414b5cfbd7ec7)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: -p --function-signature
2; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=optimize < %s | FileCheck %s --check-prefixes=OPT
3; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=lowering < %s | FileCheck %s --check-prefixes=ABI
4; REQUIRES: webassembly-registered-target
5
6; Split variadic functions into two functions:
7; - one equivalent to the original, same symbol etc
8; - one implementing the contents of the original but taking a valist
9; IR here is applicable to any target that uses a ptr for valist
10;
11; Defines a function with each linkage (in the order of the llvm documentation).
12; If split applies it does the same transform to each.
13; Whether split applies depends on whether the ABI is being changed or not - e.g. a weak
14; function is not normally useful to split as the contents cannot be called from elsewhere.
15; If the ABI is being rewritten then the function is still converted. Call sites tested elsewhere.
16
17; Update test checks doesn't emit checks for declares
18
19declare void @sink_valist(ptr)
20declare void @llvm.va_start(ptr)
21declare void @llvm.va_end(ptr)
22
23declare void @decl_simple(...)
24define void @defn_simple(...) {
25; OPT-LABEL: define {{[^@]+}}@defn_simple(...) {
26; OPT-NEXT:  entry:
27; OPT-NEXT:    %va_start = alloca ptr, align 4
28; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %va_start)
29; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va_start)
30; OPT-NEXT:    %0 = load ptr, ptr %va_start, align 4
31; OPT-NEXT:    call void @defn_simple.valist(ptr %0)
32; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %va_start)
33; OPT-NEXT:    ret void
34;
35; ABI-LABEL: define {{[^@]+}}@defn_simple(ptr %varargs) {
36; ABI-NEXT:    %va = alloca ptr, align 4
37; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
38; ABI-NEXT:    call void @sink_valist(ptr %va)
39; ABI-NEXT:    ret void
40;
41  %va = alloca ptr, align 4
42  call void @llvm.va_start(ptr %va)
43  call void @sink_valist(ptr %va)
44  call void @llvm.va_end(ptr %va)
45  ret void
46}
47
48; no declare for private
49define private void @defn_private_simple(...) {
50; OPT-LABEL: define {{[^@]+}}@defn_private_simple(...) {
51; OPT-NEXT:  entry:
52; OPT-NEXT:    %va_start = alloca ptr, align 4
53; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %va_start)
54; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va_start)
55; OPT-NEXT:    %0 = load ptr, ptr %va_start, align 4
56; OPT-NEXT:    call void @defn_private_simple.valist(ptr %0)
57; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %va_start)
58; OPT-NEXT:    ret void
59;
60; ABI-LABEL: define {{[^@]+}}@defn_private_simple(ptr %varargs) {
61; ABI-NEXT:    %va = alloca ptr, align 4
62; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
63; ABI-NEXT:    call void @sink_valist(ptr %va)
64; ABI-NEXT:    ret void
65;
66  %va = alloca ptr, align 4
67  call void @llvm.va_start(ptr %va)
68  call void @sink_valist(ptr %va)
69  call void @llvm.va_end(ptr %va)
70  ret void
71}
72
73; no declare for internal
74define internal void @defn_internal_simple(...) {
75; OPT-LABEL: define {{[^@]+}}@defn_internal_simple(...) {
76; OPT-NEXT:  entry:
77; OPT-NEXT:    %va_start = alloca ptr, align 4
78; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %va_start)
79; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va_start)
80; OPT-NEXT:    %0 = load ptr, ptr %va_start, align 4
81; OPT-NEXT:    call void @defn_internal_simple.valist(ptr %0)
82; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %va_start)
83; OPT-NEXT:    ret void
84;
85; ABI-LABEL: define {{[^@]+}}@defn_internal_simple(ptr %varargs) {
86; ABI-NEXT:    %va = alloca ptr, align 4
87; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
88; ABI-NEXT:    call void @sink_valist(ptr %va)
89; ABI-NEXT:    ret void
90;
91  %va = alloca ptr, align 4
92  call void @llvm.va_start(ptr %va)
93  call void @sink_valist(ptr %va)
94  call void @llvm.va_end(ptr %va)
95  ret void
96}
97
98; no declare for available_externally
99define available_externally void @available_externally_simple(...) {
100; OPT-LABEL: define {{[^@]+}}@available_externally_simple(...) {
101; OPT-NEXT:    %va = alloca ptr, align 4
102; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va)
103; OPT-NEXT:    call void @sink_valist(ptr %va)
104; OPT-NEXT:    ret void
105;
106; ABI-LABEL: define {{[^@]+}}@available_externally_simple(ptr %varargs) {
107; ABI-NEXT:    %va = alloca ptr, align 4
108; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
109; ABI-NEXT:    call void @sink_valist(ptr %va)
110; ABI-NEXT:    ret void
111;
112  %va = alloca ptr, align 4
113  call void @llvm.va_start(ptr %va)
114  call void @sink_valist(ptr %va)
115  call void @llvm.va_end(ptr %va)
116  ret void
117}
118
119; no declare for linkonce
120define linkonce void @defn_linkonce_simple(...) {
121; OPT-LABEL: define {{[^@]+}}@defn_linkonce_simple(...) {
122; OPT-NEXT:    %va = alloca ptr, align 4
123; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va)
124; OPT-NEXT:    call void @sink_valist(ptr %va)
125; OPT-NEXT:    ret void
126;
127; ABI-LABEL: define {{[^@]+}}@defn_linkonce_simple(ptr %varargs) {
128; ABI-NEXT:    %va = alloca ptr, align 4
129; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
130; ABI-NEXT:    call void @sink_valist(ptr %va)
131; ABI-NEXT:    ret void
132;
133  %va = alloca ptr, align 4
134  call void @llvm.va_start(ptr %va)
135  call void @sink_valist(ptr %va)
136  call void @llvm.va_end(ptr %va)
137  ret void
138}
139
140; no declare for weak
141define weak void @defn_weak_simple(...) {
142; OPT-LABEL: define {{[^@]+}}@defn_weak_simple(...) {
143; OPT-NEXT:    %va = alloca ptr, align 4
144; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va)
145; OPT-NEXT:    call void @sink_valist(ptr %va)
146; OPT-NEXT:    ret void
147;
148; ABI-LABEL: define {{[^@]+}}@defn_weak_simple(ptr %varargs) {
149; ABI-NEXT:    %va = alloca ptr, align 4
150; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
151; ABI-NEXT:    call void @sink_valist(ptr %va)
152; ABI-NEXT:    ret void
153;
154  %va = alloca ptr, align 4
155  call void @llvm.va_start(ptr %va)
156  call void @sink_valist(ptr %va)
157  call void @llvm.va_end(ptr %va)
158  ret void
159}
160
161; common is not applicable to functions
162; appending is not applicable to functions
163
164declare extern_weak void @decl_extern_weak_simple(...)
165; no define for extern_weak
166
167; no declare for linkonce_odr
168define linkonce_odr void @defn_linkonce_odr_simple(...) {
169; OPT-LABEL: define {{[^@]+}}@defn_linkonce_odr_simple(...) {
170; OPT-NEXT:    %va = alloca ptr, align 4
171; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va)
172; OPT-NEXT:    call void @sink_valist(ptr %va)
173; OPT-NEXT:    ret void
174;
175; ABI-LABEL: define {{[^@]+}}@defn_linkonce_odr_simple(ptr %varargs) {
176; ABI-NEXT:    %va = alloca ptr, align 4
177; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
178; ABI-NEXT:    call void @sink_valist(ptr %va)
179; ABI-NEXT:    ret void
180;
181  %va = alloca ptr, align 4
182  call void @llvm.va_start(ptr %va)
183  call void @sink_valist(ptr %va)
184  call void @llvm.va_end(ptr %va)
185  ret void
186}
187
188; no declare for weak_odr
189define weak_odr void @defn_weak_odr_simple(...) {
190; OPT-LABEL: define {{[^@]+}}@defn_weak_odr_simple(...) {
191; OPT-NEXT:    %va = alloca ptr, align 4
192; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va)
193; OPT-NEXT:    call void @sink_valist(ptr %va)
194; OPT-NEXT:    ret void
195;
196; ABI-LABEL: define {{[^@]+}}@defn_weak_odr_simple(ptr %varargs) {
197; ABI-NEXT:    %va = alloca ptr, align 4
198; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
199; ABI-NEXT:    call void @sink_valist(ptr %va)
200; ABI-NEXT:    ret void
201;
202  %va = alloca ptr, align 4
203  call void @llvm.va_start(ptr %va)
204  call void @sink_valist(ptr %va)
205  call void @llvm.va_end(ptr %va)
206  ret void
207}
208
209declare external void @decl_external_simple(...)
210define external void @defn_external_simple(...) {
211; OPT-LABEL: define {{[^@]+}}@defn_external_simple(...) {
212; OPT-NEXT:  entry:
213; OPT-NEXT:    %va_start = alloca ptr, align 4
214; OPT-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %va_start)
215; OPT-NEXT:    call void @llvm.va_start.p0(ptr %va_start)
216; OPT-NEXT:    %0 = load ptr, ptr %va_start, align 4
217; OPT-NEXT:    call void @defn_external_simple.valist(ptr %0)
218; OPT-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %va_start)
219; OPT-NEXT:    ret void
220;
221; ABI-LABEL: define {{[^@]+}}@defn_external_simple(ptr %varargs) {
222; ABI-NEXT:    %va = alloca ptr, align 4
223; ABI-NEXT:    store ptr %varargs, ptr %va, align 4
224; ABI-NEXT:    call void @sink_valist(ptr %va)
225; ABI-NEXT:    ret void
226;
227  %va = alloca ptr, align 4
228  call void @llvm.va_start(ptr %va)
229  call void @sink_valist(ptr %va)
230  call void @llvm.va_end(ptr %va)
231  ret void
232}
233