@@ -1079,15 +1079,6 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
10791079 void GenerateDirectMethodPrologue (CodeGenFunction &CGF, llvm::Function *Fn,
10801080 const ObjCMethodDecl *OMD,
10811081 const ObjCContainerDecl *CD) override ;
1082- // / We split `GenerateDirectMethodPrologue` into the following two functions.
1083- // / The motivation is that nil check thunk function does the nil check, it
1084- // / definitely doesn't need _cmd.
1085- void GenerateObjCDirectNilCheck (CodeGenFunction &CGF,
1086- const ObjCMethodDecl *OMD,
1087- const ObjCContainerDecl *CD) override ;
1088- // / The inner function can decide if it needs `_cmd` for itself.
1089- void GenerateCmdIfNecessary (CodeGenFunction &CGF,
1090- const ObjCMethodDecl *OMD) override ;
10911082
10921083 void GenerateProtocol (const ObjCProtocolDecl *PD) override ;
10931084
@@ -3948,99 +3939,16 @@ llvm::Function *CGObjCCommonMac::GenerateDirectMethod(
39483939 return Fn;
39493940}
39503941
3951- void CGObjCCommonMac::GenerateObjCDirectNilCheck (CodeGenFunction &CGF,
3952- const ObjCMethodDecl *OMD,
3953- const ObjCContainerDecl *CD) {
3954- auto &Builder = CGF.Builder ;
3955- bool ReceiverCanBeNull = true ;
3956- auto selfAddr = CGF.GetAddrOfLocalVar (OMD->getSelfDecl ());
3957- auto selfValue = Builder.CreateLoad (selfAddr);
3958-
3959- // Generate:
3960- //
3961- // /* for class methods only to force class lazy initialization */
3962- // self = [self self];
3963- //
3964- // /* unless the receiver is never NULL */
3965- // if (self == nil) {
3966- // return (ReturnType){ };
3967- // }
3968-
3969- if (OMD->isClassMethod ()) {
3970- const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
3971- assert (OID &&
3972- " GenerateDirectMethod() should be called with the Class Interface" );
3973- Selector SelfSel = GetNullarySelector (" self" , CGM.getContext ());
3974- auto ResultType = CGF.getContext ().getObjCIdType ();
3975- RValue result;
3976- CallArgList Args;
3977-
3978- // TODO: If this method is inlined, the caller might know that `self` is
3979- // already initialized; for example, it might be an ordinary Objective-C
3980- // method which always receives an initialized `self`, or it might have just
3981- // forced initialization on its own.
3982- //
3983- // We should find a way to eliminate this unnecessary initialization in such
3984- // cases in LLVM.
3985- result = GeneratePossiblySpecializedMessageSend (
3986- CGF, ReturnValueSlot (), ResultType, SelfSel, selfValue, Args, OID,
3987- nullptr , true );
3988- Builder.CreateStore (result.getScalarVal (), selfAddr);
3989-
3990- // Nullable `Class` expressions cannot be messaged with a direct method
3991- // so the only reason why the receive can be null would be because
3992- // of weak linking.
3993- ReceiverCanBeNull = isWeakLinkedClass (OID);
3994- }
3995-
3996- if (ReceiverCanBeNull) {
3997- llvm::BasicBlock *SelfIsNilBlock =
3998- CGF.createBasicBlock (" objc_direct_method.self_is_nil" );
3999- llvm::BasicBlock *ContBlock =
4000- CGF.createBasicBlock (" objc_direct_method.cont" );
4001-
4002- // if (self == nil) {
4003- auto selfTy = cast<llvm::PointerType>(selfValue->getType ());
4004- auto Zero = llvm::ConstantPointerNull::get (selfTy);
4005-
4006- llvm::MDBuilder MDHelper (CGM.getLLVMContext ());
4007- Builder.CreateCondBr (Builder.CreateICmpEQ (selfValue, Zero), SelfIsNilBlock,
4008- ContBlock, MDHelper.createBranchWeights (1 , 1 << 20 ));
4009-
4010- CGF.EmitBlock (SelfIsNilBlock);
4011-
4012- // return (ReturnType){ };
4013- auto retTy = OMD->getReturnType ();
4014- Builder.SetInsertPoint (SelfIsNilBlock);
4015- if (!retTy->isVoidType ()) {
4016- CGF.EmitNullInitialization (CGF.ReturnValue , retTy);
4017- }
4018- CGF.EmitBranchThroughCleanup (CGF.ReturnBlock );
4019- // }
4020-
4021- CGF.EmitBlock (ContBlock);
4022- Builder.SetInsertPoint (ContBlock);
4023- }
4024- }
4025- void CGObjCCommonMac::GenerateCmdIfNecessary (CodeGenFunction &CGF,
4026- const ObjCMethodDecl *OMD) {
4027- // only synthesize _cmd if it's referenced
4028- if (OMD->getCmdDecl ()->isUsed ()) {
4029- // `_cmd` is not a parameter to direct methods, so storage must be
4030- // explicitly declared for it.
4031- CGF.EmitVarDecl (*OMD->getCmdDecl ());
4032- CGF.Builder .CreateStore (GetSelector (CGF, OMD),
4033- CGF.GetAddrOfLocalVar (OMD->getCmdDecl ()));
4034- }
4035- }
4036-
40373942void CGObjCCommonMac::GenerateDirectMethodPrologue (
40383943 CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
40393944 const ObjCContainerDecl *CD) {
40403945 auto &Builder = CGF.Builder ;
40413946 bool ReceiverCanBeNull = true ;
40423947 auto selfAddr = CGF.GetAddrOfLocalVar (OMD->getSelfDecl ());
40433948 auto selfValue = Builder.CreateLoad (selfAddr);
3949+ bool shouldHaveNilCheckThunk =
3950+ CGF.CGM .shouldHaveNilCheckThunk (OMD) bool isNilCheckThunk =
3951+ shouldHaveNilCheckThunk && CGF.InnerFn ;
40443952
40453953 // Generate:
40463954 //
@@ -4082,7 +3990,10 @@ void CGObjCCommonMac::GenerateDirectMethodPrologue(
40823990 ReceiverCanBeNull = isWeakLinkedClass (OID);
40833991 }
40843992
4085- if (ReceiverCanBeNull) {
3993+ // Only emit nil check if this is a nil check thunk or the method
3994+ // decides that its receiver can be null
3995+ if (isNilCheckThunk ||
3996+ (!CGF.CGM .shouldHaveNilCheckThunk (OMD) && ReceiverCanBeNull)) {
40863997 llvm::BasicBlock *SelfIsNilBlock =
40873998 CGF.createBasicBlock (" objc_direct_method.self_is_nil" );
40883999 llvm::BasicBlock *ContBlock =
@@ -4112,14 +4023,19 @@ void CGObjCCommonMac::GenerateDirectMethodPrologue(
41124023 Builder.SetInsertPoint (ContBlock);
41134024 }
41144025
4115- // only synthesize _cmd if it's referenced
4116- if (OMD->getCmdDecl ()->isUsed ()) {
4026+ // Only synthesize _cmd if it's referenced
4027+ // However, a nil check thunk doesn't need _cmd even if it's referenced
4028+ if (!isNilCheckThunk && OMD->getCmdDecl ()->isUsed ()) {
41174029 // `_cmd` is not a parameter to direct methods, so storage must be
41184030 // explicitly declared for it.
41194031 CGF.EmitVarDecl (*OMD->getCmdDecl ());
41204032 Builder.CreateStore (GetSelector (CGF, OMD),
41214033 CGF.GetAddrOfLocalVar (OMD->getCmdDecl ()));
41224034 }
4035+
4036+ // It's possible that selfValue is never used.
4037+ if (selfValue->use_empty ())
4038+ selfValue->eraseFromParent ();
41234039}
41244040
41254041llvm::GlobalVariable *
0 commit comments