]> granicus.if.org Git - clang/commitdiff
CodeGen: annotate ObjC ARC functions with ABI constraints
authorSaleem Abdulrasool <compnerd@compnerd.org>
Sat, 11 Feb 2017 21:34:18 +0000 (21:34 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Sat, 11 Feb 2017 21:34:18 +0000 (21:34 +0000)
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
test/CodeGenObjC/arc.m

index 1ca56df37ff56e9aebdb7a57bf8897c8f3f59227..304288de6da0afff0451ce831ebaa0ea6ae8794e 100644 (file)
@@ -1802,6 +1802,22 @@ void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values) {
 }
 
 
+static bool IsForwarding(StringRef Name) {
+  return llvm::StringSwitch<bool>(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;
index bed91c99535da9e35891b4ba1b1a1b1b5b9ec9b2..fc135af6d31ddb13fa01fef4410e3dae6cc8dafa 100644 (file)
@@ -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) {