diff options
Diffstat (limited to 'clang/lib/CodeGen/CGObjCMac.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 75 |
1 files changed, 17 insertions, 58 deletions
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index ecf6181b1ce..8bd96382c9e 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -1392,63 +1392,6 @@ public: const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); }; - -/// A helper class for performing the null-initialization of a return -/// value. -struct NullReturnState { - llvm::BasicBlock *NullBB; - llvm::BasicBlock *callBB; - NullReturnState() : NullBB(0), callBB(0) {} - - void init(CodeGenFunction &CGF, llvm::Value *receiver) { - // Make blocks for the null-init and call edges. - NullBB = CGF.createBasicBlock("msgSend.nullinit"); - callBB = CGF.createBasicBlock("msgSend.call"); - - // Check for a null receiver and, if there is one, jump to the - // null-init test. - llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver); - CGF.Builder.CreateCondBr(isNull, NullBB, callBB); - - // Otherwise, start performing the call. - CGF.EmitBlock(callBB); - } - - RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType) { - if (!NullBB) return result; - - // Finish the call path. - llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont"); - if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB); - - // Emit the null-init block and perform the null-initialization there. - CGF.EmitBlock(NullBB); - if (!resultType->isAnyComplexType()) { - assert(result.isAggregate() && "null init of non-aggregate result?"); - CGF.EmitNullInitialization(result.getAggregateAddr(), resultType); - // Jump to the continuation block. - CGF.EmitBlock(contBB); - return result; - } - - // _Complex type - // FIXME. Now easy to handle any other scalar type whose result is returned - // in memory due to ABI limitations. - CGF.EmitBlock(contBB); - CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal(); - llvm::Type *MemberType = CallCV.first->getType(); - llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType); - // Create phi instruction for scalar complex value. - llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2); - PHIReal->addIncoming(ZeroCV, NullBB); - PHIReal->addIncoming(CallCV.first, callBB); - llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2); - PHIImag->addIncoming(ZeroCV, NullBB); - PHIImag->addIncoming(CallCV.second, callBB); - return RValue::getComplex(PHIReal, PHIImag); - } -}; - } // end anonymous namespace /* *** Helper Functions *** */ @@ -1655,7 +1598,23 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, llvm::Constant *Fn = NULL; if (CGM.ReturnTypeUsesSRet(FnInfo)) { - if (!IsSuper) nullReturn.init(CGF, Arg0); + if (!IsSuper) { + bool nullCheckAlreadyDone = false; + // We have already done this computation once and flag could have been + // passed down. But such cases are extremely rare and we do this lazily, + // instead of absorbing cost of passing down a flag for all cases. + if (CGM.getLangOptions().ObjCAutoRefCount && Method) + for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(), + e = Method->param_end(); i != e; ++i) { + if ((*i)->hasAttr<NSConsumedAttr>()) { + nullCheckAlreadyDone = true; + break; + } + } + if (!nullCheckAlreadyDone) + nullReturn.init(CGF, Arg0); + } + Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) : ObjCTypes.getSendStretFn(IsSuper); } else if (CGM.ReturnTypeUsesFPRet(ResultType)) { |