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