Skip to content

Commit 92bae8f

Browse files
committed
[ObjCARC] Tolerate missing attachedcall op by ignoring the bundle.
In some situations (swiftc bitcode) we end up running the objc-arc-contract pass twice, which is not supposed to occur. This was fine until relatively recently, where the clang.arc.attachedcall operand bundle support caused the second run to crash: when emitting the calls, the pass was assuming that the bundle always had an operand, which is not true in 5.6. That will be true in the future, but that's a massive change. For now, try to workaround the issue by ignoring the nullary bundles, and not emitting the call. The pass will get a little confused, but the semantics are preserved by the presence of the intrinsic call later on (emitted by the first run of the pass). However, one difference is that we're now going to emit a redundant inline-asm marker, since we're not able to eliminate the (standalone) intrinsic anymore, as we don't remember emitting it in the pass. That costs us an extra nop, which is okay. rdar://90366906
1 parent 167beca commit 92bae8f

File tree

3 files changed

+42
-6
lines changed

3 files changed

+42
-6
lines changed

llvm/lib/Transforms/ObjCARC/ObjCARC.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,16 @@ CallInst *BundledRetainClaimRVs::insertRVCallWithColors(
103103
Instruction *InsertPt, CallBase *AnnotatedCall,
104104
const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
105105
IRBuilder<> Builder(InsertPt);
106-
Function *Func = *objcarc::getAttachedARCFunction(AnnotatedCall);
107-
assert(Func && "operand isn't a Function");
108-
Type *ParamTy = Func->getArg(0)->getType();
106+
Optional<Function *> Func = objcarc::getAttachedARCFunction(AnnotatedCall);
107+
// This might be a call with an empty bundle, because contract already ran.
108+
// In that case, we don't have to insert another call.
109+
if (!Func)
110+
return nullptr;
111+
112+
Type *ParamTy = (*Func)->getArg(0)->getType();
109113
Value *CallArg = Builder.CreateBitCast(AnnotatedCall, ParamTy);
110114
auto *Call =
111-
createCallInstWithColors(Func, CallArg, "", InsertPt, BlockColors);
115+
createCallInstWithColors(*Func, CallArg, "", InsertPt, BlockColors);
112116
RVCalls[Call] = AnnotatedCall;
113117
return Call;
114118
}

llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,8 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) {
580580

581581
if (auto *CI = dyn_cast<CallInst>(Inst))
582582
if (objcarc::hasAttachedCallOpBundle(CI)) {
583-
BundledInsts->insertRVCallWithColors(&*I, CI, BlockColors);
584-
--I;
583+
if (BundledInsts->insertRVCallWithColors(&*I, CI, BlockColors))
584+
--I;
585585
Changed = true;
586586
}
587587

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
2+
; RUN: opt -passes=objc-arc-contract -S < %s | FileCheck %s
3+
4+
; CHECK-LABEL: define void @test0() {
5+
; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"() ]
6+
; CHECK-NEXT: call void asm sideeffect "mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue", ""()
7+
; CHECK-NEXT: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL]])
8+
9+
define void @test0() {
10+
%call1 = notail call i8* @foo() [ "clang.arc.attachedcall"() ]
11+
call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call1)
12+
ret void
13+
}
14+
15+
; CHECK-LABEL: define void @test1() {
16+
; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"() ]
17+
; CHECK-NEXT: call void asm sideeffect "mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue", ""()
18+
; CHECK-NEXT: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL]])
19+
20+
define void @test1() {
21+
%call1 = notail call i8* @foo() [ "clang.arc.attachedcall"() ]
22+
call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %call1)
23+
ret void
24+
}
25+
26+
declare i8* @foo()
27+
declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
28+
declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)
29+
30+
!llvm.module.flags = !{!0}
31+
32+
!0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue"}

0 commit comments

Comments
 (0)