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. 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; def fobjc_convert_messages_to_runtime_calls : Flag<["-"], "fobjc-convert-messages-to-runtime-calls">, Group; +def fobjc_no_builtin_retain_release : + Flag<["-"], "fobjc-no-builtin-retain-release">, Group, + Flags<[CC1Option]>; def fno_objc_convert_messages_to_runtime_calls : Flag<["-"], "fno-objc-convert-messages-to-runtime-calls">, Group, Flags<[CC1Option]>; def fobjc_arc_exceptions : Flag<["-"], "fobjc-arc-exceptions">, Group, Flags<[CC1Option]>, Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -580,8 +580,9 @@ PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible, addAddDiscriminatorsPass); - // In ObjC ARC mode, add the main ARC optimization passes. - if (LangOpts.ObjCAutoRefCount) { + // Add the main ARC optimization passes if ObjC ARC is enabled or + // ObjCNoBuiltinRetainRelease isn't set. + if (LangOpts.ObjCAutoRefCount || !CodeGenOpts.ObjCNoBuiltinRetainRelease) { PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible, addObjCARCExpandPass); PMBuilder.addExtension(PassManagerBuilder::EP_ModuleOptimizerEarly, 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: 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/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/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: 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]; }