@@ -2029,112 +2029,6 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
20292029 llvm::StructType::get (CGM.getLLVMContext (),
20302030 { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
20312031 }
2032-
2033- void GenerateDirectMethodPrologue (CodeGenFunction &CGF, llvm::Function *Fn,
2034- const ObjCMethodDecl *OMD,
2035- const ObjCContainerDecl *CD) override {
2036- auto &Builder = CGF.Builder ;
2037- bool ReceiverCanBeNull = true ;
2038- auto selfAddr = CGF.GetAddrOfLocalVar (OMD->getSelfDecl ());
2039- auto selfValue = Builder.CreateLoad (selfAddr);
2040-
2041- // Generate:
2042- //
2043- // /* unless the receiver is never NULL */
2044- // if (self == nil) {
2045- // return (ReturnType){ };
2046- // }
2047- //
2048- // /* for class methods only to force class lazy initialization */
2049- // if (!__objc_{class}_initialized)
2050- // {
2051- // objc_send_initialize(class);
2052- // __objc_{class}_initialized = 1;
2053- // }
2054- //
2055- // _cmd = @selector(...)
2056- // ...
2057-
2058- if (OMD->isClassMethod ()) {
2059- const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
2060-
2061- // Nullable `Class` expressions cannot be messaged with a direct method
2062- // so the only reason why the receive can be null would be because
2063- // of weak linking.
2064- ReceiverCanBeNull = isWeakLinkedClass (OID);
2065- }
2066-
2067- llvm::MDBuilder MDHelper (CGM.getLLVMContext ());
2068- if (ReceiverCanBeNull) {
2069- llvm::BasicBlock *SelfIsNilBlock =
2070- CGF.createBasicBlock (" objc_direct_method.self_is_nil" );
2071- llvm::BasicBlock *ContBlock =
2072- CGF.createBasicBlock (" objc_direct_method.cont" );
2073-
2074- // if (self == nil) {
2075- auto selfTy = cast<llvm::PointerType>(selfValue->getType ());
2076- auto Zero = llvm::ConstantPointerNull::get (selfTy);
2077-
2078- Builder.CreateCondBr (Builder.CreateICmpEQ (selfValue, Zero),
2079- SelfIsNilBlock, ContBlock,
2080- MDHelper.createUnlikelyBranchWeights ());
2081-
2082- CGF.EmitBlock (SelfIsNilBlock);
2083-
2084- // return (ReturnType){ };
2085- auto retTy = OMD->getReturnType ();
2086- Builder.SetInsertPoint (SelfIsNilBlock);
2087- if (!retTy->isVoidType ()) {
2088- CGF.EmitNullInitialization (CGF.ReturnValue , retTy);
2089- }
2090- CGF.EmitBranchThroughCleanup (CGF.ReturnBlock );
2091- // }
2092-
2093- // rest of the body
2094- CGF.EmitBlock (ContBlock);
2095- Builder.SetInsertPoint (ContBlock);
2096- }
2097-
2098- if (OMD->isClassMethod ()) {
2099- // Prefix of the class type.
2100- auto *classStart =
2101- llvm::StructType::get (PtrTy, PtrTy, PtrTy, LongTy, LongTy);
2102- auto &astContext = CGM.getContext ();
2103- // FIXME: The following few lines up to and including the call to
2104- // `CreateLoad` were known to miscompile when MSVC 19.40.33813 is used
2105- // to build Clang. When the bug is fixed in future MSVC releases, we
2106- // should revert these lines to their previous state. See discussion in
2107- // https://github.com/llvm/llvm-project/pull/102681
2108- llvm::Value *Val = Builder.CreateStructGEP (classStart, selfValue, 4 );
2109- auto Align = CharUnits::fromQuantity (
2110- astContext.getTypeAlign (astContext.UnsignedLongTy ));
2111- auto flags = Builder.CreateLoad (Address{Val, LongTy, Align});
2112- auto isInitialized =
2113- Builder.CreateAnd (flags, ClassFlags::ClassFlagInitialized);
2114- llvm::BasicBlock *notInitializedBlock =
2115- CGF.createBasicBlock (" objc_direct_method.class_uninitialized" );
2116- llvm::BasicBlock *initializedBlock =
2117- CGF.createBasicBlock (" objc_direct_method.class_initialized" );
2118- Builder.CreateCondBr (Builder.CreateICmpEQ (isInitialized, Zeros[0 ]),
2119- notInitializedBlock, initializedBlock,
2120- MDHelper.createUnlikelyBranchWeights ());
2121- CGF.EmitBlock (notInitializedBlock);
2122- Builder.SetInsertPoint (notInitializedBlock);
2123- CGF.EmitRuntimeCall (SentInitializeFn, selfValue);
2124- Builder.CreateBr (initializedBlock);
2125- CGF.EmitBlock (initializedBlock);
2126- Builder.SetInsertPoint (initializedBlock);
2127- }
2128-
2129- // only synthesize _cmd if it's referenced
2130- if (OMD->getCmdDecl ()->isUsed ()) {
2131- // `_cmd` is not a parameter to direct methods, so storage must be
2132- // explicitly declared for it.
2133- CGF.EmitVarDecl (*OMD->getCmdDecl ());
2134- Builder.CreateStore (GetSelector (CGF, OMD),
2135- CGF.GetAddrOfLocalVar (OMD->getCmdDecl ()));
2136- }
2137- }
21382032};
21392033
21402034const char *const CGObjCGNUstep2::SectionsBaseNames[8 ] =
@@ -4121,7 +4015,110 @@ void CGObjCGNU::GenerateDirectMethodPrologue(CodeGenFunction &CGF,
41214015 llvm::Function *Fn,
41224016 const ObjCMethodDecl *OMD,
41234017 const ObjCContainerDecl *CD) {
4124- // GNU runtime doesn't support direct calls at this time
4018+ if (!CGM.getLangOpts ().ObjCRuntime .allowsDirectDispatch ())
4019+ return ;
4020+
4021+ auto &Builder = CGF.Builder ;
4022+ bool ReceiverCanBeNull = true ;
4023+ auto selfAddr = CGF.GetAddrOfLocalVar (OMD->getSelfDecl ());
4024+ auto selfValue = Builder.CreateLoad (selfAddr);
4025+
4026+ // Generate:
4027+ //
4028+ // /* unless the receiver is never NULL */
4029+ // if (self == nil) {
4030+ // return (ReturnType){ };
4031+ // }
4032+ //
4033+ // /* for class methods only to force class lazy initialization */
4034+ // if (!__objc_{class}_initialized)
4035+ // {
4036+ // objc_send_initialize(class);
4037+ // __objc_{class}_initialized = 1;
4038+ // }
4039+ //
4040+ // _cmd = @selector(...)
4041+ // ...
4042+
4043+ if (OMD->isClassMethod ()) {
4044+ const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
4045+
4046+ // Nullable `Class` expressions cannot be messaged with a direct method
4047+ // so the only reason why the receive can be null would be because
4048+ // of weak linking.
4049+ ReceiverCanBeNull = isWeakLinkedClass (OID);
4050+ }
4051+
4052+ llvm::MDBuilder MDHelper (CGM.getLLVMContext ());
4053+ if (ReceiverCanBeNull) {
4054+ llvm::BasicBlock *SelfIsNilBlock =
4055+ CGF.createBasicBlock (" objc_direct_method.self_is_nil" );
4056+ llvm::BasicBlock *ContBlock =
4057+ CGF.createBasicBlock (" objc_direct_method.cont" );
4058+
4059+ // if (self == nil) {
4060+ auto selfTy = cast<llvm::PointerType>(selfValue->getType ());
4061+ auto Zero = llvm::ConstantPointerNull::get (selfTy);
4062+
4063+ Builder.CreateCondBr (Builder.CreateICmpEQ (selfValue, Zero),
4064+ SelfIsNilBlock, ContBlock,
4065+ MDHelper.createUnlikelyBranchWeights ());
4066+
4067+ CGF.EmitBlock (SelfIsNilBlock);
4068+
4069+ // return (ReturnType){ };
4070+ auto retTy = OMD->getReturnType ();
4071+ Builder.SetInsertPoint (SelfIsNilBlock);
4072+ if (!retTy->isVoidType ()) {
4073+ CGF.EmitNullInitialization (CGF.ReturnValue , retTy);
4074+ }
4075+ CGF.EmitBranchThroughCleanup (CGF.ReturnBlock );
4076+ // }
4077+
4078+ // rest of the body
4079+ CGF.EmitBlock (ContBlock);
4080+ Builder.SetInsertPoint (ContBlock);
4081+ }
4082+
4083+ if (OMD->isClassMethod ()) {
4084+ // Prefix of the class type.
4085+ auto *classStart =
4086+ llvm::StructType::get (PtrTy, PtrTy, PtrTy, LongTy, LongTy);
4087+ auto &astContext = CGM.getContext ();
4088+ // FIXME: The following few lines up to and including the call to
4089+ // `CreateLoad` were known to miscompile when MSVC 19.40.33813 is used
4090+ // to build Clang. When the bug is fixed in future MSVC releases, we
4091+ // should revert these lines to their previous state. See discussion in
4092+ // https://github.com/llvm/llvm-project/pull/102681
4093+ llvm::Value *Val = Builder.CreateStructGEP (classStart, selfValue, 4 );
4094+ auto Align = CharUnits::fromQuantity (
4095+ astContext.getTypeAlign (astContext.UnsignedLongTy ));
4096+ auto flags = Builder.CreateLoad (Address{Val, LongTy, Align});
4097+ auto isInitialized =
4098+ Builder.CreateAnd (flags, ClassFlags::ClassFlagInitialized);
4099+ llvm::BasicBlock *notInitializedBlock =
4100+ CGF.createBasicBlock (" objc_direct_method.class_uninitialized" );
4101+ llvm::BasicBlock *initializedBlock =
4102+ CGF.createBasicBlock (" objc_direct_method.class_initialized" );
4103+ Builder.CreateCondBr (Builder.CreateICmpEQ (isInitialized, Zeros[0 ]),
4104+ notInitializedBlock, initializedBlock,
4105+ MDHelper.createUnlikelyBranchWeights ());
4106+ CGF.EmitBlock (notInitializedBlock);
4107+ Builder.SetInsertPoint (notInitializedBlock);
4108+ CGF.EmitRuntimeCall (SentInitializeFn, selfValue);
4109+ Builder.CreateBr (initializedBlock);
4110+ CGF.EmitBlock (initializedBlock);
4111+ Builder.SetInsertPoint (initializedBlock);
4112+ }
4113+
4114+ // only synthesize _cmd if it's referenced
4115+ if (OMD->getCmdDecl ()->isUsed ()) {
4116+ // `_cmd` is not a parameter to direct methods, so storage must be
4117+ // explicitly declared for it.
4118+ CGF.EmitVarDecl (*OMD->getCmdDecl ());
4119+ Builder.CreateStore (GetSelector (CGF, OMD),
4120+ CGF.GetAddrOfLocalVar (OMD->getCmdDecl ()));
4121+ }
41254122}
41264123
41274124llvm::FunctionCallee CGObjCGNU::GetPropertyGetFunction () {
0 commit comments