xref: /llvm-project/llvm/test/Transforms/PreISelIntrinsicLowering/X86/objc-arc.ll (revision 3fe282a83d2bcc23f1a3f9bc47682f7c4bfc9b88)
1; RUN: opt -mtriple=x86_64-pc-linux-gnu -pre-isel-intrinsic-lowering -S -o - %s | FileCheck %s
2; RUN: opt -mtriple=x86_64-pc-linux-gnu -passes=pre-isel-intrinsic-lowering -S -o - %s | FileCheck %s
3
4; Make sure calls to the objc intrinsics are translated to calls in to the
5; runtime
6
7declare ptr @foo()
8declare i32 @__gxx_personality_v0(...)
9
10define ptr @test_objc_autorelease(ptr %arg0) {
11; CHECK-LABEL: test_objc_autorelease
12; CHECK-NEXT: entry
13; CHECK-NEXT: %0 = notail call ptr @objc_autorelease(ptr returned %arg0)
14; CHECK-NEXT: ret ptr %0
15entry:
16  %0 = call ptr @llvm.objc.autorelease(ptr %arg0)
17	ret ptr %0
18}
19
20define void @test_objc_autoreleasePoolPop(ptr %arg0) {
21; CHECK-LABEL: test_objc_autoreleasePoolPop
22; CHECK-NEXT: entry
23; CHECK-NEXT: call void @objc_autoreleasePoolPop(ptr %arg0)
24; CHECK-NEXT: ret void
25entry:
26  call void @llvm.objc.autoreleasePoolPop(ptr %arg0)
27  ret void
28}
29
30define ptr @test_objc_autoreleasePoolPush() {
31; CHECK-LABEL: test_objc_autoreleasePoolPush
32; CHECK-NEXT: entry
33; CHECK-NEXT: %0 = call ptr @objc_autoreleasePoolPush()
34; CHECK-NEXT: ret ptr %0
35entry:
36  %0 = call ptr @llvm.objc.autoreleasePoolPush()
37	ret ptr %0
38}
39
40define ptr @test_objc_autoreleaseReturnValue(ptr %arg0) {
41; CHECK-LABEL: test_objc_autoreleaseReturnValue
42; CHECK-NEXT: entry
43; CHECK-NEXT: %0 = tail call ptr @objc_autoreleaseReturnValue(ptr returned %arg0)
44; CHECK-NEXT: ret ptr %0
45entry:
46  %0 = call ptr @llvm.objc.autoreleaseReturnValue(ptr %arg0)
47	ret ptr %0
48}
49
50define void @test_objc_copyWeak(ptr %arg0, ptr %arg1) {
51; CHECK-LABEL: test_objc_copyWeak
52; CHECK-NEXT: entry
53; CHECK-NEXT: call void @objc_copyWeak(ptr %arg0, ptr %arg1)
54; CHECK-NEXT: ret void
55entry:
56  call void @llvm.objc.copyWeak(ptr %arg0, ptr %arg1)
57  ret void
58}
59
60define void @test_objc_destroyWeak(ptr %arg0) {
61; CHECK-LABEL: test_objc_destroyWeak
62; CHECK-NEXT: entry
63; CHECK-NEXT: call void @objc_destroyWeak(ptr %arg0)
64; CHECK-NEXT: ret void
65entry:
66  call void @llvm.objc.destroyWeak(ptr %arg0)
67  ret void
68}
69
70define ptr @test_objc_initWeak(ptr %arg0, ptr %arg1) {
71; CHECK-LABEL: test_objc_initWeak
72; CHECK-NEXT: entry
73; CHECK-NEXT: %0 = call ptr @objc_initWeak(ptr %arg0, ptr %arg1)
74; CHECK-NEXT: ret ptr %0
75entry:
76  %0 = call ptr @llvm.objc.initWeak(ptr %arg0, ptr %arg1)
77	ret ptr %0
78}
79
80define ptr @test_objc_loadWeak(ptr %arg0) {
81; CHECK-LABEL: test_objc_loadWeak
82; CHECK-NEXT: entry
83; CHECK-NEXT: %0 = call ptr @objc_loadWeak(ptr %arg0)
84; CHECK-NEXT: ret ptr %0
85entry:
86  %0 = call ptr @llvm.objc.loadWeak(ptr %arg0)
87	ret ptr %0
88}
89
90define ptr @test_objc_loadWeakRetained(ptr %arg0) {
91; CHECK-LABEL: test_objc_loadWeakRetained
92; CHECK-NEXT: entry
93; CHECK-NEXT: %0 = call ptr @objc_loadWeakRetained(ptr %arg0)
94; CHECK-NEXT: ret ptr %0
95entry:
96  %0 = call ptr @llvm.objc.loadWeakRetained(ptr %arg0)
97	ret ptr %0
98}
99
100define void @test_objc_moveWeak(ptr %arg0, ptr %arg1) {
101; CHECK-LABEL: test_objc_moveWeak
102; CHECK-NEXT: entry
103; CHECK-NEXT: call void @objc_moveWeak(ptr %arg0, ptr %arg1)
104; CHECK-NEXT: ret void
105entry:
106  call void @llvm.objc.moveWeak(ptr %arg0, ptr %arg1)
107  ret void
108}
109
110define void @test_objc_release(ptr %arg0) {
111; CHECK-LABEL: test_objc_release
112; CHECK-NEXT: entry
113; CHECK-NEXT: call void @objc_release(ptr %arg0)
114; CHECK-NEXT: ret void
115entry:
116  call void @llvm.objc.release(ptr %arg0)
117  ret void
118}
119
120define ptr @test_objc_retain(ptr %arg0) {
121; CHECK-LABEL: test_objc_retain
122; CHECK-NEXT: entry
123; CHECK-NEXT: %0 = tail call ptr @objc_retain(ptr returned %arg0)
124; CHECK-NEXT: ret ptr %0
125entry:
126  %0 = call ptr @llvm.objc.retain(ptr %arg0)
127	ret ptr %0
128}
129
130define ptr @test_objc_retainAutorelease(ptr %arg0) {
131; CHECK-LABEL: test_objc_retainAutorelease
132; CHECK-NEXT: entry
133; CHECK-NEXT: %0 = call ptr @objc_retainAutorelease(ptr returned %arg0)
134; CHECK-NEXT: ret ptr %0
135entry:
136  %0 = call ptr @llvm.objc.retainAutorelease(ptr %arg0)
137	ret ptr %0
138}
139
140define ptr @test_objc_retainAutoreleaseReturnValue(ptr %arg0) {
141; CHECK-LABEL: test_objc_retainAutoreleaseReturnValue
142; CHECK-NEXT: entry
143; CHECK-NEXT: %0 = tail call ptr @objc_retainAutoreleaseReturnValue(ptr returned %arg0)
144; CHECK-NEXT: ret ptr %0
145entry:
146  %0 = tail call ptr @llvm.objc.retainAutoreleaseReturnValue(ptr %arg0)
147	ret ptr %0
148}
149
150; Note: we don't want this intrinsic to have its argument marked 'returned',
151; since that breaks the autorelease elision marker optimization when
152; save/restores of the reciever are introduced between the msg send and the
153; retain. See issue#69658.
154define ptr @test_objc_retainAutoreleasedReturnValue(ptr %arg0) {
155; CHECK-LABEL: test_objc_retainAutoreleasedReturnValue
156; CHECK-NEXT: entry
157; CHECK-NEXT: %0 = tail call ptr @objc_retainAutoreleasedReturnValue(ptr %arg0)
158; CHECK-NEXT: ret ptr %0
159entry:
160  %0 = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %arg0)
161	ret ptr %0
162}
163
164define void @test_objc_retainAutoreleasedReturnValue_bundle() {
165; CHECK-LABEL: test_objc_retainAutoreleasedReturnValue_bundle(
166; CHECK-NEXT: call ptr @foo() [ "clang.arc.attachedcall"(ptr @objc_retainAutoreleasedReturnValue) ]
167  call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
168  ret void
169}
170
171define void @test_objc_retainAutoreleasedReturnValue_bundle_invoke() personality ptr @__gxx_personality_v0 {
172; CHECK-LABEL: test_objc_retainAutoreleasedReturnValue_bundle_invoke(
173; CHECK-NEXT: entry
174; CHECK-NEXT: invoke ptr @foo() [ "clang.arc.attachedcall"(ptr @objc_retainAutoreleasedReturnValue) ]
175entry:
176  invoke ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
177      to label %invoke.cont unwind label %lpad
178
179invoke.cont:
180  ret void
181
182lpad:
183  %1 = landingpad { ptr, i32 }
184          cleanup
185  resume { ptr, i32 } %1
186}
187
188define ptr @test_objc_retainBlock(ptr %arg0) {
189; CHECK-LABEL: test_objc_retainBlock
190; CHECK-NEXT: entry
191; CHECK-NEXT: %0 = call ptr @objc_retainBlock(ptr %arg0)
192; CHECK-NEXT: ret ptr %0
193entry:
194  %0 = call ptr @llvm.objc.retainBlock(ptr %arg0)
195	ret ptr %0
196}
197
198define void @test_objc_storeStrong(ptr %arg0, ptr %arg1) {
199; CHECK-LABEL: test_objc_storeStrong
200; CHECK-NEXT: entry
201; CHECK-NEXT: call void @objc_storeStrong(ptr %arg0, ptr %arg1)
202; CHECK-NEXT: ret void
203entry:
204  call void @llvm.objc.storeStrong(ptr %arg0, ptr %arg1)
205	ret void
206}
207
208define ptr @test_objc_storeWeak(ptr %arg0, ptr %arg1) {
209; CHECK-LABEL: test_objc_storeWeak
210; CHECK-NEXT: entry
211; CHECK-NEXT: %0 = call ptr @objc_storeWeak(ptr %arg0, ptr %arg1)
212; CHECK-NEXT: ret ptr %0
213entry:
214  %0 = call ptr @llvm.objc.storeWeak(ptr %arg0, ptr %arg1)
215	ret ptr %0
216}
217
218; Note: we don't want this intrinsic to have its argument marked 'returned',
219; since that breaks the autorelease elision marker optimization when
220; save/restores of the reciever are introduced between the msg send and the
221; claim. See issue#69658.
222define ptr @test_objc_unsafeClaimAutoreleasedReturnValue(ptr %arg0) {
223; CHECK-LABEL: test_objc_unsafeClaimAutoreleasedReturnValue
224; CHECK-NEXT: entry
225; CHECK-NEXT: %0 = tail call ptr @objc_unsafeClaimAutoreleasedReturnValue(ptr %arg0)
226; CHECK-NEXT: ret ptr %0
227entry:
228  %0 = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr %arg0)
229  ret ptr %0
230}
231
232define void @test_objc_unsafeClaimAutoreleasedReturnValue_bundle() {
233; CHECK-LABEL: test_objc_unsafeClaimAutoreleasedReturnValue_bundle(
234; CHECK-NEXT: call ptr @foo() [ "clang.arc.attachedcall"(ptr @objc_unsafeClaimAutoreleasedReturnValue) ]
235  call ptr @foo() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
236  ret void
237}
238
239define ptr @test_objc_retainedObject(ptr %arg0) {
240; CHECK-LABEL: test_objc_retainedObject
241; CHECK-NEXT: entry
242; CHECK-NEXT: %0 = call ptr @objc_retainedObject(ptr %arg0)
243; CHECK-NEXT: ret ptr %0
244entry:
245  %0 = call ptr @llvm.objc.retainedObject(ptr %arg0)
246  ret ptr %0
247}
248
249define ptr @test_objc_unretainedObject(ptr %arg0) {
250; CHECK-LABEL: test_objc_unretainedObject
251; CHECK-NEXT: entry
252; CHECK-NEXT: %0 = call ptr @objc_unretainedObject(ptr %arg0)
253; CHECK-NEXT: ret ptr %0
254entry:
255  %0 = call ptr @llvm.objc.unretainedObject(ptr %arg0)
256  ret ptr %0
257}
258
259define ptr @test_objc_unretainedPointer(ptr %arg0) {
260; CHECK-LABEL: test_objc_unretainedPointer
261; CHECK-NEXT: entry
262; CHECK-NEXT: %0 = call ptr @objc_unretainedPointer(ptr %arg0)
263; CHECK-NEXT: ret ptr %0
264entry:
265  %0 = call ptr @llvm.objc.unretainedPointer(ptr %arg0)
266  ret ptr %0
267}
268
269define ptr @test_objc_retain_autorelease(ptr %arg0) {
270; CHECK-LABEL: test_objc_retain_autorelease
271; CHECK-NEXT: entry
272; CHECK-NEXT: %0 = call ptr @objc_retain_autorelease(ptr returned %arg0)
273; CHECK-NEXT: ret ptr %0
274entry:
275  %0 = call ptr @llvm.objc.retain.autorelease(ptr %arg0)
276  ret ptr %0
277}
278
279define i32 @test_objc_sync_enter(ptr %arg0) {
280; CHECK-LABEL: test_objc_sync_enter
281; CHECK-NEXT: entry
282; CHECK-NEXT: %0 = call i32 @objc_sync_enter(ptr %arg0)
283; CHECK-NEXT: ret i32 %0
284entry:
285  %0 = call i32 @llvm.objc.sync.enter(ptr %arg0)
286  ret i32 %0
287}
288
289define i32 @test_objc_sync_exit(ptr %arg0) {
290; CHECK-LABEL: test_objc_sync_exit
291; CHECK-NEXT: entry
292; CHECK-NEXT: %0 = call i32 @objc_sync_exit(ptr %arg0)
293; CHECK-NEXT: ret i32 %0
294entry:
295  %0 = call i32 @llvm.objc.sync.exit(ptr %arg0)
296  ret i32 %0
297}
298
299declare ptr @llvm.objc.autorelease(ptr)
300declare void @llvm.objc.autoreleasePoolPop(ptr)
301declare ptr @llvm.objc.autoreleasePoolPush()
302declare ptr @llvm.objc.autoreleaseReturnValue(ptr)
303declare void @llvm.objc.copyWeak(ptr, ptr)
304declare void @llvm.objc.destroyWeak(ptr)
305declare extern_weak ptr @llvm.objc.initWeak(ptr, ptr)
306declare ptr @llvm.objc.loadWeak(ptr)
307declare ptr @llvm.objc.loadWeakRetained(ptr)
308declare void @llvm.objc.moveWeak(ptr, ptr)
309declare void @llvm.objc.release(ptr)
310declare ptr @llvm.objc.retain(ptr)
311declare ptr @llvm.objc.retainAutorelease(ptr)
312declare ptr @llvm.objc.retainAutoreleaseReturnValue(ptr)
313declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)
314declare ptr @llvm.objc.retainBlock(ptr)
315declare void @llvm.objc.storeStrong(ptr, ptr)
316declare ptr @llvm.objc.storeWeak(ptr, ptr)
317declare ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr)
318declare ptr @llvm.objc.retainedObject(ptr)
319declare ptr @llvm.objc.unretainedObject(ptr)
320declare ptr @llvm.objc.unretainedPointer(ptr)
321declare ptr @llvm.objc.retain.autorelease(ptr)
322declare i32 @llvm.objc.sync.enter(ptr)
323declare i32 @llvm.objc.sync.exit(ptr)
324
325attributes #0 = { nounwind }
326
327; CHECK: declare ptr @objc_autorelease(ptr)
328; CHECK: declare void @objc_autoreleasePoolPop(ptr)
329; CHECK: declare ptr @objc_autoreleasePoolPush()
330; CHECK: declare ptr @objc_autoreleaseReturnValue(ptr)
331; CHECK: declare void @objc_copyWeak(ptr, ptr)
332; CHECK: declare void @objc_destroyWeak(ptr)
333; CHECK: declare extern_weak ptr @objc_initWeak(ptr, ptr)
334; CHECK: declare ptr @objc_loadWeak(ptr)
335; CHECK: declare ptr @objc_loadWeakRetained(ptr)
336; CHECK: declare void @objc_moveWeak(ptr, ptr)
337; CHECK: declare void @objc_release(ptr) [[NLB:#[0-9]+]]
338; CHECK: declare ptr @objc_retain(ptr) [[NLB]]
339; CHECK: declare ptr @objc_retainAutorelease(ptr)
340; CHECK: declare ptr @objc_retainAutoreleaseReturnValue(ptr)
341; CHECK: declare ptr @objc_retainAutoreleasedReturnValue(ptr)
342; CHECK: declare ptr @objc_retainBlock(ptr)
343; CHECK: declare void @objc_storeStrong(ptr, ptr)
344; CHECK: declare ptr @objc_storeWeak(ptr, ptr)
345; CHECK: declare ptr @objc_unsafeClaimAutoreleasedReturnValue(ptr)
346; CHECK: declare ptr @objc_retainedObject(ptr)
347; CHECK: declare ptr @objc_unretainedObject(ptr)
348; CHECK: declare ptr @objc_unretainedPointer(ptr)
349; CHECK: declare ptr @objc_retain_autorelease(ptr)
350; CHECK: declare i32 @objc_sync_enter(ptr)
351; CHECK: declare i32 @objc_sync_exit(ptr)
352
353; CHECK: attributes #0 = { nounwind }
354; CHECK: attributes [[NLB]] = { nonlazybind }
355