From a92ce662c187e295059100cd71bf41ed9ea3b88c Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sat, 11 Feb 2017 21:34:18 +0000 Subject: [PATCH] CodeGen: annotate ObjC ARC functions with ABI constraints Certain ARC runtime functions have an ABI contract of being forwarding. Annotate the functions with the appropriate `returned` attribute on the arguments. This hoists some of the runtime ABI contract information into the frontend rather than the backend transformations. The test adjustments are to mark the returned function parameter as such. The minor change to the IR output is due to the fact that the returned reference of the object causes it to extend the lifetime of the object by returning an autoreleased return value. The result is that the explicit objc_autorelease call is no longer formed, as autorelease elision is now possible on the return. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@294872 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjC.cpp | 23 +++++++++++++++++++++++ test/CodeGenObjC/arc.m | 24 +++++++++++++----------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 1ca56df37f..304288de6d 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -1802,6 +1802,22 @@ void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef values) { } +static bool IsForwarding(StringRef Name) { + return llvm::StringSwitch(Name) + .Cases("objc_autoreleaseReturnValue", // ARCInstKind::AutoreleaseRV + "objc_autorelease", // ARCInstKind::Autorelease + "objc_retainAutoreleaseReturnValue", // ARCInstKind::FusedRetainAutoreleaseRV + "objc_retainAutoreleasedReturnValue", // ARCInstKind::RetainRV + "objc_retainAutorelease", // ARCInstKind::FusedRetainAutorelease + "objc_retainedObject", // ARCInstKind::NoopCast + "objc_retain", // ARCInstKind::Retain + "objc_unretainedObject", // ARCInstKind::NoopCast + "objc_unretainedPointer", // ARCInstKind::NoopCast + "objc_unsafeClaimAutoreleasedReturnValue", // ARCInstKind::ClaimRV + true) + .Default(false); +} + static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM, llvm::FunctionType *FTy, StringRef Name) { @@ -1819,6 +1835,13 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM, // performance. F->addFnAttr(llvm::Attribute::NonLazyBind); } + + if (IsForwarding(Name)) { + llvm::AttrBuilder B; + B.addAttribute(llvm::Attribute::Returned); + + F->arg_begin()->addAttr(llvm::AttributeSet::get(F->getContext(), 1, B)); + } } return RTF; diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m index bed91c9953..fc135af6d3 100644 --- a/test/CodeGenObjC/arc.m +++ b/test/CodeGenObjC/arc.m @@ -7,30 +7,30 @@ // RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s // ARC-ALIEN: declare extern_weak void @objc_storeStrong(i8**, i8*) -// ARC-ALIEN: declare extern_weak i8* @objc_retain(i8*) -// ARC-ALIEN: declare extern_weak i8* @objc_autoreleaseReturnValue(i8*) +// ARC-ALIEN: declare extern_weak i8* @objc_retain(i8* returned) +// ARC-ALIEN: declare extern_weak i8* @objc_autoreleaseReturnValue(i8* returned) // ARC-ALIEN: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]] // ARC-ALIEN: declare extern_weak void @objc_release(i8*) -// ARC-ALIEN: declare extern_weak i8* @objc_retainAutoreleasedReturnValue(i8*) +// ARC-ALIEN: declare extern_weak i8* @objc_retainAutoreleasedReturnValue(i8* returned) // ARC-ALIEN: declare extern_weak i8* @objc_initWeak(i8**, i8*) // ARC-ALIEN: declare extern_weak i8* @objc_storeWeak(i8**, i8*) // ARC-ALIEN: declare extern_weak i8* @objc_loadWeakRetained(i8**) // ARC-ALIEN: declare extern_weak void @objc_destroyWeak(i8**) -// ARC-ALIEN: declare extern_weak i8* @objc_autorelease(i8*) -// ARC-ALIEN: declare extern_weak i8* @objc_retainAutorelease(i8*) +// declare extern_weak i8* @objc_autorelease(i8*) +// ARC-ALIEN: declare extern_weak i8* @objc_retainAutorelease(i8* returned) // ARC-NATIVE: declare void @objc_storeStrong(i8**, i8*) -// ARC-NATIVE: declare i8* @objc_retain(i8*) [[NLB:#[0-9]+]] -// ARC-NATIVE: declare i8* @objc_autoreleaseReturnValue(i8*) +// ARC-NATIVE: declare i8* @objc_retain(i8* returned) [[NLB:#[0-9]+]] +// ARC-NATIVE: declare i8* @objc_autoreleaseReturnValue(i8* returned) // ARC-NATIVE: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB]] // ARC-NATIVE: declare void @objc_release(i8*) [[NLB]] -// ARC-NATIVE: declare i8* @objc_retainAutoreleasedReturnValue(i8*) +// ARC-NATIVE: declare i8* @objc_retainAutoreleasedReturnValue(i8* returned) // ARC-NATIVE: declare i8* @objc_initWeak(i8**, i8*) // ARC-NATIVE: declare i8* @objc_storeWeak(i8**, i8*) // ARC-NATIVE: declare i8* @objc_loadWeakRetained(i8**) // ARC-NATIVE: declare void @objc_destroyWeak(i8**) -// ARC-NATIVE: declare i8* @objc_autorelease(i8*) -// ARC-NATIVE: declare i8* @objc_retainAutorelease(i8*) +// declare i8* @objc_autorelease(i8*) +// ARC-NATIVE: declare i8* @objc_retainAutorelease(i8* returned) // CHECK-LABEL: define void @test0 void test0(id x) { @@ -1504,7 +1504,9 @@ void test68(void) { // CHECK: [[SELF:%.*]] = alloca [[TEST69:%.*]]*, align 8 // CHECK: [[T0:%.*]] = load [[TEST69]]*, [[TEST69]]** [[SELF]], align 8 // CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST69]]* [[T0]] to i8* -// CHECK-NEXT: ret i8* [[T1]] +// CHECK-NEXT: [[RETAIN:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: [[AUTORELEASE:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[RETAIN]]) +// CHECK-NEXT: ret i8* [[AUTORELEASE]] // rdar://problem/10907547 void test70(id i) { -- 2.40.0