ahatanak created this revision.
ahatanak added reviewers: pete, rjmccall, erik.pilkington.
ahatanak added a project: clang.
Herald added subscribers: dexonsmith, jkorous.
This patch makes IRGen emit ObjC runtime functions
(`objc_autoreleaseReturnValue` and `objc_retainAutoreleasedReturnValue`) that
were previously emitted only in ARC mode. This enables retain message sends in
MRR code to participate in the retainRV/autoreleaseRV handshake, which keeps
returned objects out of the autorelease pool. Also, it enables the ARC
optimizer and ARC contract pass to remove retain/autorelease pairs and mark
autorelease message sends converted to autoreleaseRV calls as tail calls, which
is necessary for the retainRV/autoreleaseRV handshake to succeed.
rdar://problem/50353574
Repository:
rC Clang
https://reviews.llvm.org/D61970
Files:
include/clang/Basic/CodeGenOptions.def
include/clang/Driver/Options.td
lib/CodeGen/CGObjC.cpp
lib/CodeGen/CodeGenFunction.h
lib/Driver/ToolChains/Clang.cpp
lib/Frontend/CompilerInvocation.cpp
test/CodeGenObjC/convert-messages-to-runtime-calls.m
Index: test/CodeGenObjC/convert-messages-to-runtime-calls.m
===================================================================
--- test/CodeGenObjC/convert-messages-to-runtime-calls.m
+++ test/CodeGenObjC/convert-messages-to-runtime-calls.m
@@ -1,12 +1,13 @@
// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fno-objc-convert-messages-to-runtime-calls -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS
-// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS --check-prefix=CALLS-ARC-INTRINSICS
// RUN: %clang_cc1 -fobjc-runtime=macosx-10.9.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS
// RUN: %clang_cc1 -fobjc-runtime=macosx-fragile-10.10.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS
-// RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS --check-prefix=CALLS-ARC-INTRINSICS
// RUN: %clang_cc1 -fobjc-runtime=ios-7.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS
// Note: This line below is for tvos for which the driver passes through to use the ios9.0 runtime.
-// RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS
-// RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS --check-prefix=CALLS-ARC-INTRINSICS
+// RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS --check-prefix=CALLS-ARC-INTRINSICS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions -fobjc-no-builtin-retain-release | FileCheck %s --check-prefix=CALLS --check-prefix=CALLS-NO-ARC-INTRINSICS
#define nil (id)0
@@ -28,9 +29,11 @@
// MSGS: {{call.*@objc_msgSend}}
// CALLS: {{call.*@objc_alloc}}
// CALLS: {{call.*@objc_allocWithZone}}
- // CALLS: {{call.*@objc_retain}}
+ // CALLS-ARC-INTRINSICS: {{call.*@llvm.objc.retainAutoreleasedReturnValue}}
+ // CALLS-NO-ARC-INTRINSICS: {{call.*@objc_retain}}
// CALLS: {{call.*@objc_release}}
- // CALLS: {{call.*@objc_autorelease}}
+ // CALLS-ARC-INTRINSICS: {{call.*@llvm.objc.autoreleaseReturnValue}}
+ // CALLS-NO-ARC-INTRINSICS: {{call.*@objc_autorelease}}
[NSObject alloc];
[NSObject allocWithZone:nil];
[x retain];
@@ -111,7 +114,8 @@
// call will return i8* which we have to cast to A*
// CHECK-LABEL: define {{.*}}void @test_retain_class_ptr
A* test_retain_class_ptr(B *b) {
- // CALLS: {{call.*@objc_retain}}
+ // CALLS-ARC-INTRINSICS: {{call.*@llvm.objc.retainAutoreleasedReturnValue}}
+ // CALLS-NO-ARC-INTRINSICS: {{call.*@objc_retain}}
// CALLS-NEXT: bitcast i8*
// CALLS-NEXT: ret
return [b retain];
@@ -121,7 +125,8 @@
// call will return i8* which we have to cast to A*
// CHECK-LABEL: define {{.*}}void @test_autorelease_class_ptr
A* test_autorelease_class_ptr(B *b) {
- // CALLS: {{call.*@objc_autorelease}}
+ // CALLS-ARC-INTRINSICS: {{call.*@llvm.objc.autoreleaseReturnValue}}
+ // CALLS-NO-ARC-INTRINSICS: {{call.*@objc_autorelease}}
// CALLS-NEXT: bitcast i8*
// CALLS-NEXT: ret
return [b autorelease];
@@ -161,7 +166,8 @@
// CHECK-LABEL: define {{.*}}void @retain_self
+ (void)retain_self {
// MSGS: {{call.*@objc_msgSend}}
- // CALLS: {{call.*@objc_retain}}
+ // CALLS-ARC-INTRINSICS: {{call.*@llvm.objc.retainAutoreleasedReturnValue}}
+ // CALLS-NO-ARC-INTRINSICS: {{call.*@objc_retain}}
[self retain];
}
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1163,6 +1163,8 @@
}
}
+ if (Args.hasArg(OPT_fobjc_no_builtin_retain_release))
+ Opts.ObjCNoBuiltinRetainRelease = 1;
if (Args.hasArg(OPT_fno_objc_convert_messages_to_runtime_calls))
Opts.ObjCConvertMessagesToRuntimeCalls = 0;
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -2986,6 +2986,9 @@
Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions);
}
+ if (Args.hasArg(options::OPT_fobjc_no_builtin_retain_release))
+ CmdArgs.push_back("-fobjc-no-builtin-retain-release");
+
// Allow the user to control whether messages can be converted to runtime
// functions.
if (types::isObjC(Input.getType())) {
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -3799,9 +3799,12 @@
void EmitARCDestroyStrong(Address addr, ARCPreciseLifetime_t precise);
void EmitARCRelease(llvm::Value *value, ARCPreciseLifetime_t precise);
llvm::Value *EmitARCAutorelease(llvm::Value *value);
- llvm::Value *EmitARCAutoreleaseReturnValue(llvm::Value *value);
+ llvm::Value *EmitARCAutoreleaseReturnValue(llvm::Value *value,
+ llvm::Type *returnType = nullptr);
llvm::Value *EmitARCRetainAutoreleaseReturnValue(llvm::Value *value);
- llvm::Value *EmitARCRetainAutoreleasedReturnValue(llvm::Value *value);
+ llvm::Value *
+ EmitARCRetainAutoreleasedReturnValue(llvm::Value *value,
+ llvm::Type *returnType = nullptr);
llvm::Value *EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value);
llvm::Value *EmitObjCAutorelease(llvm::Value *value, llvm::Type *returnType);
Index: lib/CodeGen/CGObjC.cpp
===================================================================
--- lib/CodeGen/CGObjC.cpp
+++ lib/CodeGen/CGObjC.cpp
@@ -2176,7 +2176,8 @@
/// Yes, this function name is one character away from a different
/// call with completely different semantics.
llvm::Value *
-CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
+CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value,
+ llvm::Type *returnType) {
emitAutoreleasedReturnValueMarker(*this);
llvm::CallInst::TailCallKind tailKind =
CGM.getTargetCodeGenInfo()
@@ -2184,7 +2185,7 @@
? llvm::CallInst::TCK_NoTail
: llvm::CallInst::TCK_None;
return emitARCValueOperation(
- *this, value, nullptr,
+ *this, value, returnType,
CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue,
llvm::Intrinsic::objc_retainAutoreleasedReturnValue, tailKind);
}
@@ -2319,8 +2320,9 @@
/// Autorelease the given object.
/// call i8* \@objc_autoreleaseReturnValue(i8* %value)
llvm::Value *
-CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
- return emitARCValueOperation(*this, value, nullptr,
+CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value,
+ llvm::Type *returnType) {
+ return emitARCValueOperation(*this, value, returnType,
CGM.getObjCEntrypoints().objc_autoreleaseReturnValue,
llvm::Intrinsic::objc_autoreleaseReturnValue,
llvm::CallInst::TCK_Tail);
@@ -2586,9 +2588,13 @@
}
/// Autorelease the given object.
-/// call i8* \@objc_autorelease(i8* %value)
+/// If we don't have to handle exceptions and ObjCNoBuiltinRetainRelease isn't
+/// set, call objc_autoreleaseReturnValue. Otherwise, call objc_autorelease.
llvm::Value *CodeGenFunction::EmitObjCAutorelease(llvm::Value *value,
llvm::Type *returnType) {
+ // Do not call the ARC intrinsic if we are handling exceptions.
+ if (!CGM.getCodeGenOpts().ObjCNoBuiltinRetainRelease && !getInvokeDest())
+ return EmitARCAutoreleaseReturnValue(value, returnType);
return emitObjCValueOperation(
*this, value, returnType,
CGM.getObjCEntrypoints().objc_autoreleaseRuntimeFunction,
@@ -2596,9 +2602,13 @@
}
/// Retain the given object, with normal retain semantics.
-/// call i8* \@objc_retain(i8* %value)
+/// If we don't have to handle exceptions and ObjCNoBuiltinRetainRelease isn't
+/// set, call objc_retainAutoreleasedReturnValue. Otherwise, call objc_retain.
llvm::Value *CodeGenFunction::EmitObjCRetainNonBlock(llvm::Value *value,
llvm::Type *returnType) {
+ // Do not call the ARC intrinsic if we are handling exceptions.
+ if (!CGM.getCodeGenOpts().ObjCNoBuiltinRetainRelease && !getInvokeDest())
+ return EmitARCRetainAutoreleasedReturnValue(value, returnType);
return emitObjCValueOperation(
*this, value, returnType,
CGM.getObjCEntrypoints().objc_retainRuntimeFunction, "objc_retain");
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1495,6 +1495,9 @@
def fno_objc_arc : Flag<["-"], "fno-objc-arc">, Group<f_Group>;
def fobjc_convert_messages_to_runtime_calls :
Flag<["-"], "fobjc-convert-messages-to-runtime-calls">, Group<f_Group>;
+def fobjc_no_builtin_retain_release :
+ Flag<["-"], "fobjc-no-builtin-retain-release">, Group<f_Group>,
+ Flags<[CC1Option]>;
def fno_objc_convert_messages_to_runtime_calls :
Flag<["-"], "fno-objc-convert-messages-to-runtime-calls">, Group<f_Group>, Flags<[CC1Option]>;
def fobjc_arc_exceptions : Flag<["-"], "fobjc-arc-exceptions">, Group<f_Group>, Flags<[CC1Option]>,
Index: include/clang/Basic/CodeGenOptions.def
===================================================================
--- include/clang/Basic/CodeGenOptions.def
+++ include/clang/Basic/CodeGenOptions.def
@@ -154,6 +154,7 @@
ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
/// Replace certain message sends with calls to ObjC runtime entrypoints
CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1)
+CODEGENOPT(ObjCNoBuiltinRetainRelease , 1, 0)
CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
///< enabled.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits