Skip to content

Commit 2d7f32a

Browse files
authored
[ObjC][ARC] Use the addresses of the ARC runtime functions instead of integer 0/1 for the operand of bundle "clang.arc.attachedcall" (#3518)
* Refactor inlineRetainOrClaimRVCalls. NFC This is in preparation for committing https://reviews.llvm.org/D103000. (cherry picked from commit 898dc45) * [ObjC][ARC] Use the addresses of the ARC runtime functions instead of integer 0/1 for the operand of bundle "clang.arc.attachedcall" This should make it easier to understand what the IR is doing and also simplify some of the passes as they no longer have to translate the integer values to the runtime functions. Differential Revision: https://reviews.llvm.org/D102996 (cherry picked from commit 59cc39a) * [ObjC][ARC] Use the addresses of the ARC runtime functions instead of integer 0/1 for the operand of bundle "clang.arc.attachedcall" https://reviews.llvm.org/D102996 changes the operand of bundle "clang.arc.attachedcall". This patch makes changes to llvm that are needed to handle the new IR. This should make it easier to understand what the IR is doing and also simplify some of the passes as they no longer have to translate the integer values to the runtime functions. Differential Revision: https://reviews.llvm.org/D103000 (cherry picked from commit dea6f71)
1 parent c41282e commit 2d7f32a

30 files changed

+349
-245
lines changed

clang/lib/CodeGen/CGObjC.cpp

Lines changed: 34 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,6 +2108,13 @@ static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM,
21082108
setARCRuntimeFunctionLinkage(CGM, RTF.getCallee());
21092109
}
21102110

2111+
static llvm::Function *getARCIntrinsic(llvm::Intrinsic::ID IntID,
2112+
CodeGenModule &CGM) {
2113+
llvm::Function *fn = CGM.getIntrinsic(IntID);
2114+
setARCRuntimeFunctionLinkage(CGM, fn);
2115+
return fn;
2116+
}
2117+
21112118
/// Perform an operation having the signature
21122119
/// i8* (i8*)
21132120
/// where a null input causes a no-op and returns null.
@@ -2118,10 +2125,8 @@ static llvm::Value *emitARCValueOperation(
21182125
if (isa<llvm::ConstantPointerNull>(value))
21192126
return value;
21202127

2121-
if (!fn) {
2122-
fn = CGF.CGM.getIntrinsic(IntID);
2123-
setARCRuntimeFunctionLinkage(CGF.CGM, fn);
2124-
}
2128+
if (!fn)
2129+
fn = getARCIntrinsic(IntID, CGF.CGM);
21252130

21262131
// Cast the argument to 'id'.
21272132
llvm::Type *origType = returnType ? returnType : value->getType();
@@ -2140,10 +2145,8 @@ static llvm::Value *emitARCValueOperation(
21402145
static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, Address addr,
21412146
llvm::Function *&fn,
21422147
llvm::Intrinsic::ID IntID) {
2143-
if (!fn) {
2144-
fn = CGF.CGM.getIntrinsic(IntID);
2145-
setARCRuntimeFunctionLinkage(CGF.CGM, fn);
2146-
}
2148+
if (!fn)
2149+
fn = getARCIntrinsic(IntID, CGF.CGM);
21472150

21482151
// Cast the argument to 'id*'.
21492152
llvm::Type *origType = addr.getElementType();
@@ -2168,10 +2171,8 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, Address addr,
21682171
bool ignored) {
21692172
assert(addr.getElementType() == value->getType());
21702173

2171-
if (!fn) {
2172-
fn = CGF.CGM.getIntrinsic(IntID);
2173-
setARCRuntimeFunctionLinkage(CGF.CGM, fn);
2174-
}
2174+
if (!fn)
2175+
fn = getARCIntrinsic(IntID, CGF.CGM);
21752176

21762177
llvm::Type *origType = value->getType();
21772178

@@ -2193,10 +2194,8 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, Address dst, Address src,
21932194
llvm::Intrinsic::ID IntID) {
21942195
assert(dst.getType() == src.getType());
21952196

2196-
if (!fn) {
2197-
fn = CGF.CGM.getIntrinsic(IntID);
2198-
setARCRuntimeFunctionLinkage(CGF.CGM, fn);
2199-
}
2197+
if (!fn)
2198+
fn = getARCIntrinsic(IntID, CGF.CGM);
22002199

22012200
llvm::Value *args[] = {
22022201
CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy),
@@ -2340,13 +2339,19 @@ static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,
23402339
// retainRV or claimRV calls in the IR. We currently do this only when the
23412340
// optimization level isn't -O0 since global-isel, which is currently run at
23422341
// -O0, doesn't know about the operand bundle.
2342+
ObjCEntrypoints &EPs = CGF.CGM.getObjCEntrypoints();
2343+
llvm::Function *&EP = IsRetainRV
2344+
? EPs.objc_retainAutoreleasedReturnValue
2345+
: EPs.objc_unsafeClaimAutoreleasedReturnValue;
2346+
llvm::Intrinsic::ID IID =
2347+
IsRetainRV ? llvm::Intrinsic::objc_retainAutoreleasedReturnValue
2348+
: llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue;
2349+
EP = getARCIntrinsic(IID, CGF.CGM);
23432350

23442351
// FIXME: Do this when the target isn't aarch64.
23452352
if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 &&
23462353
CGF.CGM.getTarget().getTriple().isAArch64()) {
2347-
llvm::Value *bundleArgs[] = {llvm::ConstantInt::get(
2348-
CGF.Int64Ty,
2349-
llvm::objcarc::getAttachedCallOperandBundleEnum(IsRetainRV))};
2354+
llvm::Value *bundleArgs[] = {EP};
23502355
llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs);
23512356
auto *oldCall = cast<llvm::CallBase>(value);
23522357
llvm::CallBase *newCall = llvm::CallBase::addOperandBundle(
@@ -2362,13 +2367,6 @@ static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,
23622367
CGF.CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail();
23632368
llvm::CallInst::TailCallKind tailKind =
23642369
isNoTail ? llvm::CallInst::TCK_NoTail : llvm::CallInst::TCK_None;
2365-
ObjCEntrypoints &EPs = CGF.CGM.getObjCEntrypoints();
2366-
llvm::Function *&EP = IsRetainRV
2367-
? EPs.objc_retainAutoreleasedReturnValue
2368-
: EPs.objc_unsafeClaimAutoreleasedReturnValue;
2369-
llvm::Intrinsic::ID IID =
2370-
IsRetainRV ? llvm::Intrinsic::objc_retainAutoreleasedReturnValue
2371-
: llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue;
23722370
return emitARCValueOperation(CGF, value, nullptr, EP, IID, tailKind);
23732371
}
23742372

@@ -2401,10 +2399,8 @@ void CodeGenFunction::EmitARCRelease(llvm::Value *value,
24012399
if (isa<llvm::ConstantPointerNull>(value)) return;
24022400

24032401
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_release;
2404-
if (!fn) {
2405-
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_release);
2406-
setARCRuntimeFunctionLinkage(CGM, fn);
2407-
}
2402+
if (!fn)
2403+
fn = getARCIntrinsic(llvm::Intrinsic::objc_release, CGM);
24082404

24092405
// Cast the argument to 'id'.
24102406
value = Builder.CreateBitCast(value, Int8PtrTy);
@@ -2447,10 +2443,8 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr,
24472443
assert(addr.getElementType() == value->getType());
24482444

24492445
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_storeStrong;
2450-
if (!fn) {
2451-
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_storeStrong);
2452-
setARCRuntimeFunctionLinkage(CGM, fn);
2453-
}
2446+
if (!fn)
2447+
fn = getARCIntrinsic(llvm::Intrinsic::objc_storeStrong, CGM);
24542448

24552449
llvm::Value *args[] = {
24562450
Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy),
@@ -2603,10 +2597,8 @@ void CodeGenFunction::EmitARCInitWeak(Address addr, llvm::Value *value) {
26032597
/// Essentially objc_storeWeak(addr, nil).
26042598
void CodeGenFunction::EmitARCDestroyWeak(Address addr) {
26052599
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_destroyWeak;
2606-
if (!fn) {
2607-
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_destroyWeak);
2608-
setARCRuntimeFunctionLinkage(CGM, fn);
2609-
}
2600+
if (!fn)
2601+
fn = getARCIntrinsic(llvm::Intrinsic::objc_destroyWeak, CGM);
26102602

26112603
// Cast the argument to 'id*'.
26122604
addr = Builder.CreateBitCast(addr, Int8PtrPtrTy);
@@ -2651,10 +2643,8 @@ void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr,
26512643
/// call i8* \@objc_autoreleasePoolPush(void)
26522644
llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
26532645
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPush;
2654-
if (!fn) {
2655-
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush);
2656-
setARCRuntimeFunctionLinkage(CGM, fn);
2657-
}
2646+
if (!fn)
2647+
fn = getARCIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush, CGM);
26582648

26592649
return EmitNounwindRuntimeCall(fn);
26602650
}
@@ -2679,10 +2669,8 @@ void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) {
26792669
EmitRuntimeCallOrInvoke(fn, value);
26802670
} else {
26812671
llvm::FunctionCallee &fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop;
2682-
if (!fn) {
2683-
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop);
2684-
setARCRuntimeFunctionLinkage(CGM, fn);
2685-
}
2672+
if (!fn)
2673+
fn = getARCIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop, CGM);
26862674

26872675
EmitRuntimeCall(fn, value);
26882676
}

clang/test/CodeGenObjC/arc-rv-attr.m

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void test_assign() {
1010
}
1111
// CHECK-LABEL: define{{.*}} void @test_assign()
1212
// CHECK: [[X:%.*]] = alloca i8*
13-
// CHECK: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
13+
// CHECK: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
1414
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
1515
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
1616
// CHECK-NEXT: store i8* [[T1]], i8** [[X]]
@@ -25,7 +25,7 @@ void test_assign_assign() {
2525
// CHECK-LABEL: define{{.*}} void @test_assign_assign()
2626
// CHECK: [[X:%.*]] = alloca i8*
2727
// CHECK: [[Y:%.*]] = alloca i8*
28-
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
28+
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
2929
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
3030
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
3131
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
@@ -44,7 +44,7 @@ void test_strong_assign_assign() {
4444
// CHECK-LABEL: define{{.*}} void @test_strong_assign_assign()
4545
// CHECK: [[X:%.*]] = alloca i8*
4646
// CHECK: [[Y:%.*]] = alloca i8*
47-
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]
47+
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
4848
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
4949
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
5050
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
@@ -67,7 +67,7 @@ void test_assign_strong_assign() {
6767
// CHECK-LABEL: define{{.*}} void @test_assign_strong_assign()
6868
// CHECK: [[X:%.*]] = alloca i8*
6969
// CHECK: [[Y:%.*]] = alloca i8*
70-
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]
70+
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
7171
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
7272
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
7373
// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[Y]]
@@ -87,7 +87,7 @@ void test_init() {
8787
}
8888
// CHECK-LABEL: define{{.*}} void @test_init()
8989
// CHECK: [[X:%.*]] = alloca i8*
90-
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
90+
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
9191
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
9292
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
9393
// CHECK-NEXT: store i8* [[T1]], i8** [[X]]
@@ -102,7 +102,7 @@ void test_init_assignment() {
102102
// CHECK-LABEL: define{{.*}} void @test_init_assignment()
103103
// CHECK: [[X:%.*]] = alloca i8*
104104
// CHECK: [[Y:%.*]] = alloca i8*
105-
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
105+
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
106106
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
107107
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
108108
// CHECK-NEXT: store i8* [[T1]], i8** [[X]]
@@ -120,7 +120,7 @@ void test_strong_init_assignment() {
120120
// CHECK-LABEL: define{{.*}} void @test_strong_init_assignment()
121121
// CHECK: [[X:%.*]] = alloca i8*
122122
// CHECK: [[Y:%.*]] = alloca i8*
123-
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]
123+
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
124124
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
125125
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
126126
// CHECK-NEXT: store i8* [[T1]], i8** [[X]]
@@ -140,7 +140,7 @@ void test_init_strong_assignment() {
140140
// CHECK-LABEL: define{{.*}} void @test_init_strong_assignment()
141141
// CHECK: [[X:%.*]] = alloca i8*
142142
// CHECK: [[Y:%.*]] = alloca i8*
143-
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]
143+
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
144144
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
145145
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
146146
// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[X]]
@@ -159,15 +159,15 @@ void test_ignored() {
159159
makeA();
160160
}
161161
// CHECK-LABEL: define{{.*}} void @test_ignored()
162-
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
162+
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
163163
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
164164
// CHECK-NEXT: ret void
165165

166166
void test_cast_to_void() {
167167
(void)makeA();
168168
}
169169
// CHECK-LABEL: define{{.*}} void @test_cast_to_void()
170-
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
170+
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
171171
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
172172
// CHECK-NEXT: ret void
173173

clang/test/CodeGenObjCXX/arc-rv-attr.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
id foo(void);
44

55
// CHECK-LABEL: define{{.*}} void @_Z14test_list_initv(
6-
// CHECK: %[[CALL1:.*]] = call i8* @_Z3foov() [ "clang.arc.attachedcall"(i64 0) ]
6+
// CHECK: %[[CALL1:.*]] = call i8* @_Z3foov() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
77
// CHECK: call i8* @llvm.objc.retain(i8* %[[CALL1]])
88

99
void test_list_init() {

llvm/docs/LangRef.rst

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,14 +2459,26 @@ for further details.
24592459
ObjC ARC Attached Call Operand Bundles
24602460
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24612461

2462-
A ``"clang.arc.attachedcall`` operand bundle on a call indicates the call is
2462+
A ``"clang.arc.attachedcall"`` operand bundle on a call indicates the call is
24632463
implicitly followed by a marker instruction and a call to an ObjC runtime
2464-
function that uses the result of the call. If the argument passed to the operand
2465-
bundle is 0, ``@objc_retainAutoreleasedReturnValue`` is called. If 1 is passed,
2466-
``@objc_unsafeClaimAutoreleasedReturnValue`` is called. The return value of a
2467-
call with this bundle is used by a call to ``@llvm.objc.clang.arc.noop.use``
2468-
unless the called function's return type is void, in which case the operand
2469-
bundle is ignored.
2464+
function that uses the result of the call. The operand bundle takes either the
2465+
pointer to the runtime function (``@objc_retainAutoreleasedReturnValue`` or
2466+
``@objc_unsafeClaimAutoreleasedReturnValue``) or no arguments. If the bundle
2467+
doesn't take any arguments, only the marker instruction has to be emitted after
2468+
the call; the runtime function calls don't have to be emitted since they already
2469+
have been emitted. The return value of a call with this bundle is used by a call
2470+
to ``@llvm.objc.clang.arc.noop.use`` unless the called function's return type is
2471+
void, in which case the operand bundle is ignored.
2472+
2473+
.. code-block:: llvm
2474+
2475+
; The marker instruction and a runtime function call are inserted after the call
2476+
; to @foo.
2477+
call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
2478+
call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_unsafeClaimAutoreleasedReturnValue) ]
2479+
2480+
; Only the marker instruction is inserted after the call to @foo.
2481+
call i8* @foo() [ "clang.arc.attachedcall"() ]
24702482

24712483
The operand bundle is needed to ensure the call is immediately followed by the
24722484
marker instruction or the ObjC runtime call in the final output.

llvm/include/llvm/Analysis/ObjCARCUtil.h

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#ifndef LLVM_IR_OBJCARCUTIL_H
1515
#define LLVM_IR_OBJCARCUTIL_H
1616

17+
#include "llvm/Analysis/ObjCARCInstKind.h"
18+
#include "llvm/IR/Function.h"
1719
#include "llvm/IR/InstrTypes.h"
1820
#include "llvm/IR/LLVMContext.h"
1921

@@ -24,13 +26,6 @@ inline const char *getRVMarkerModuleFlagStr() {
2426
return "clang.arc.retainAutoreleasedReturnValueMarker";
2527
}
2628

27-
enum AttachedCallOperandBundle : unsigned { RVOB_Retain, RVOB_Claim };
28-
29-
inline AttachedCallOperandBundle
30-
getAttachedCallOperandBundleEnum(bool IsRetain) {
31-
return IsRetain ? RVOB_Retain : RVOB_Claim;
32-
}
33-
3429
inline bool hasAttachedCallOpBundle(const CallBase *CB) {
3530
// Ignore the bundle if the return type is void. Global optimization passes
3631
// can turn the called function's return type to void. That should happen only
@@ -43,14 +38,32 @@ inline bool hasAttachedCallOpBundle(const CallBase *CB) {
4338
.hasValue();
4439
}
4540

46-
inline bool hasAttachedCallOpBundle(const CallBase *CB, bool IsRetain) {
47-
assert(hasAttachedCallOpBundle(CB) &&
48-
"call doesn't have operand bundle clang_arc_attachedcall");
41+
/// This function returns operand bundle clang_arc_attachedcall's argument,
42+
/// which is the address of the ARC runtime function.
43+
inline Optional<Function *> getAttachedARCFunction(const CallBase *CB) {
4944
auto B = CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall);
50-
if (!B.hasValue())
51-
return false;
52-
return cast<ConstantInt>(B->Inputs[0])->getZExtValue() ==
53-
getAttachedCallOperandBundleEnum(IsRetain);
45+
if (!B.hasValue() || B->Inputs.size() == 0)
46+
return None;
47+
48+
return cast<Function>(B->Inputs[0]);
49+
}
50+
51+
/// Check whether the function is retainRV/claimRV.
52+
inline bool isRetainOrClaimRV(ARCInstKind Kind) {
53+
return Kind == ARCInstKind::RetainRV || Kind == ARCInstKind::ClaimRV;
54+
}
55+
56+
/// This function returns the ARCInstKind of the function attached to operand
57+
/// bundle clang_arc_attachedcall. It returns None if the call doesn't have the
58+
/// operand bundle or the operand is null. Otherwise it returns either RetainRV
59+
/// or ClaimRV.
60+
inline ARCInstKind getAttachedARCFunctionKind(const CallBase *CB) {
61+
Optional<Function *> Fn = getAttachedARCFunction(CB);
62+
if (!Fn.hasValue())
63+
return ARCInstKind::None;
64+
auto FnClass = GetFunctionClass(*Fn);
65+
assert(isRetainOrClaimRV(FnClass) && "unexpected ARC runtime function");
66+
return FnClass;
5467
}
5568

5669
} // end namespace objcarc

llvm/include/llvm/IR/Function.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -904,13 +904,14 @@ class Function : public GlobalObject, public ilist_node<Function> {
904904
/// hasAddressTaken - returns true if there are any uses of this function
905905
/// other than direct calls or invokes to it, or blockaddress expressions.
906906
/// Optionally passes back an offending user for diagnostic purposes,
907-
/// ignores callback uses, assume like pointer annotation calls, and
908-
/// references in llvm.used and llvm.compiler.used variables.
909-
///
907+
/// ignores callback uses, assume like pointer annotation calls, references in
908+
/// llvm.used and llvm.compiler.used variables, and operand bundle
909+
/// "clang.arc.attachedcall".
910910
bool hasAddressTaken(const User ** = nullptr,
911911
bool IgnoreCallbackUses = false,
912912
bool IgnoreAssumeLikeCalls = true,
913-
bool IngoreLLVMUsed = false) const;
913+
bool IngoreLLVMUsed = false,
914+
bool IgnoreARCAttachedCall = false) const;
914915

915916
/// isDefTriviallyDead - Return true if it is trivially safe to remove
916917
/// this function definition from the module (because it isn't externally

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,6 +1918,13 @@ class CallBase : public Instruction {
19181918
Idx < getBundleOperandsEndIndex();
19191919
}
19201920

1921+
/// Return true if the operand at index \p Idx is a bundle operand that has
1922+
/// tag ID \p ID.
1923+
bool isOperandBundleOfType(uint32_t ID, unsigned Idx) const {
1924+
return isBundleOperand(Idx) &&
1925+
getOperandBundleForOperand(Idx).getTagID() == ID;
1926+
}
1927+
19211928
/// Returns true if the use is a bundle operand.
19221929
bool isBundleOperand(const Use *U) const {
19231930
assert(this == U->getUser() &&

0 commit comments

Comments
 (0)