[clang] Enable direct methods and fast alloc calls for libobjc2. (PR #78030)
Saleem Abdulrasool via cfe-commits
cfe-commits at lists.llvm.org
Sun Jan 14 11:08:52 PST 2024
================
@@ -1994,6 +2004,106 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
{ PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
}
+ void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
+ const ObjCMethodDecl *OMD,
+ const ObjCContainerDecl *CD) override {
+ auto &Builder = CGF.Builder;
+ bool ReceiverCanBeNull = true;
+ auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
+ auto selfValue = Builder.CreateLoad(selfAddr);
+
+ // Generate:
+ //
+ // /* unless the receiver is never NULL */
+ // if (self == nil) {
+ // return (ReturnType){ };
+ // }
+ //
+ // /* for class methods only to force class lazy initialization */
+ // if (!__objc_{class}_initialized)
+ // {
+ // objc_send_initialize(class);
+ // __objc_{class}_initialized = 1;
+ // }
+ //
+ // _cmd = @selector(...)
+ // ...
+
+ if (OMD->isClassMethod()) {
+ const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
+
+ // Nullable `Class` expressions cannot be messaged with a direct method
+ // so the only reason why the receive can be null would be because
+ // of weak linking.
+ ReceiverCanBeNull = isWeakLinkedClass(OID);
+ }
+
+ if (ReceiverCanBeNull) {
+ llvm::BasicBlock *SelfIsNilBlock =
+ CGF.createBasicBlock("objc_direct_method.self_is_nil");
+ llvm::BasicBlock *ContBlock =
+ CGF.createBasicBlock("objc_direct_method.cont");
+
+ // if (self == nil) {
+ auto selfTy = cast<llvm::PointerType>(selfValue->getType());
+ auto Zero = llvm::ConstantPointerNull::get(selfTy);
+
+ llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+ Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero),
+ SelfIsNilBlock, ContBlock,
+ MDHelper.createBranchWeights(1, 1 << 20));
+
+ CGF.EmitBlock(SelfIsNilBlock);
+
+ // return (ReturnType){ };
+ auto retTy = OMD->getReturnType();
+ Builder.SetInsertPoint(SelfIsNilBlock);
+ if (!retTy->isVoidType()) {
+ CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
+ }
+ CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+ // }
+
+ // rest of the body
+ CGF.EmitBlock(ContBlock);
+ Builder.SetInsertPoint(ContBlock);
+ }
+
+ if (OMD->isClassMethod()) {
+ // Prefix of the class type.
+ auto *classStart =
+ llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
+ auto &astContext = CGM.getContext();
+ auto flags = Builder.CreateLoad(
+ Address{Builder.CreateStructGEP(classStart, selfValue, 4), LongTy,
+ CharUnits::fromQuantity(
+ astContext.getTypeAlign(astContext.UnsignedLongTy))});
+ auto isInitialized = Builder.CreateAnd(flags, (1 << 8));
----------------
compnerd wrote:
It might be nice to extract the flags enumeration into named constants for re-use.
https://github.com/llvm/llvm-project/pull/78030
More information about the cfe-commits
mailing list