From 6b7cd6e5f445ea1708780e2f9aae264a621236ba Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 6 Feb 2009 20:09:23 +0000 Subject: [PATCH] objc2's nonfragile abi API for messages sent to 'super'. llvm-svn: 63959 --- clang/lib/CodeGen/CGObjCMac.cpp | 117 ++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 7 deletions(-) diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 8b0c9bb0f225..c5ce163b3bb1 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -597,6 +597,8 @@ private: ObjCNonFragileABITypesHelper ObjCTypes; llvm::GlobalVariable* ObjCEmptyCacheVar; llvm::GlobalVariable* ObjCEmptyVtableVar; + /// MetaClassReferences - uniqued meta class references. + llvm::DenseMap MetaClassReferences; /// FinishNonFragileABIModule - Write out global data structures at the end of /// processing a translation unit. @@ -660,7 +662,14 @@ private: /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, /// for the given class. llvm::Value *EmitClassRef(CGBuilderTy &Builder, - const ObjCInterfaceDecl *ID); + const ObjCInterfaceDecl *ID, + bool IsSuper = false); + + /// EmitMetaClassRef - Return a Value * of the address of _class_t + /// meta-data + llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder, + const ObjCInterfaceDecl *ID); + public: CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); @@ -681,7 +690,7 @@ public: const ObjCInterfaceDecl *Class, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs){ return RValue::get(0);} + const CallArgList &CallArgs); virtual llvm::Value *GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID); @@ -4298,8 +4307,9 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( // FIXME. Even though IsSuper is passes. This function doese not // handle calls to 'super' receivers. CodeGenTypes &Types = CGM.getTypes(); - llvm::Value *Arg0 = - CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp"); + llvm::Value *Arg0 = Receiver; + if (!IsSuper) + Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); // Find the message function name. // FIXME. This is too much work to get the ABI-specific result type @@ -4319,6 +4329,11 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( } else #endif + if (IsSuper) { + Fn = ObjCTypes.MessageSendSuper2StretFixupFn; + Name += "objc_msgSendSuper2_stret_fixup"; + } + else { Fn = ObjCTypes.MessageSendStretFixupFn; Name += "objc_msgSend_stret_fixup"; @@ -4339,6 +4354,11 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( } else #endif + if (IsSuper) { + Fn = ObjCTypes.MessageSendSuper2FixupFn; + Name += "objc_msgSendSuper2_fixup"; + } + else { Fn = ObjCTypes.MessageSendFixupFn; Name += "objc_msgSend_fixup"; @@ -4403,7 +4423,8 @@ CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend( } llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder, - const ObjCInterfaceDecl *ID) { + const ObjCInterfaceDecl *ID, + bool IsSuper) { llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()]; @@ -4423,19 +4444,62 @@ llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder, Entry = new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false, llvm::GlobalValue::InternalLinkage, - ClassGV, "\01L_OBJC_CLASSLIST_REFERENCES_$_", + ClassGV, + IsSuper ? "\01L_OBJC_CLASSLIST_SUP_REFS_$_" + : "\01L_OBJC_CLASSLIST_REFERENCES_$_", &CGM.getModule()); Entry->setAlignment( CGM.getTargetData().getPrefTypeAlignment( ObjCTypes.ClassnfABIPtrTy)); - Entry->setSection("__OBJC,__objc_classrefs,regular,no_dead_strip"); + if (IsSuper) + Entry->setSection("__OBJC,__objc_superrefs,regular,no_dead_strip"); + else + Entry->setSection("__OBJC,__objc_classrefs,regular,no_dead_strip"); UsedGlobals.push_back(Entry); } return Builder.CreateLoad(Entry, false, "tmp"); } +/// EmitMetaClassRef - Return a Value * of the address of _class_t +/// meta-data +/// +llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder, + const ObjCInterfaceDecl *ID) { + llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; + if (Entry) + return Builder.CreateLoad(Entry, false, "tmp"); + + std::string MetaClassName("\01_OBJC_METACLASS_$_" + ID->getNameAsString()); + llvm::GlobalVariable *MetaClassGV = + CGM.getModule().getGlobalVariable(MetaClassName); + if (!MetaClassGV) { + MetaClassGV = + new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, + llvm::GlobalValue::ExternalLinkage, + 0, + MetaClassName, + &CGM.getModule()); + UsedGlobals.push_back(MetaClassGV); + } + + Entry = + new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false, + llvm::GlobalValue::InternalLinkage, + MetaClassGV, + "\01L_OBJC_CLASSLIST_SUP_REFS_$_", + &CGM.getModule()); + Entry->setAlignment( + CGM.getTargetData().getPrefTypeAlignment( + ObjCTypes.ClassnfABIPtrTy)); + + Entry->setSection("__OBJC,__objc_superrefs,regular,no_dead_strip"); + UsedGlobals.push_back(Entry); + + return Builder.CreateLoad(Entry, false, "tmp"); +} + /// GetClass - Return a reference to the class for the given interface /// decl. llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder, @@ -4443,6 +4507,45 @@ llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder, return EmitClassRef(Builder, ID); } +/// Generates a message send where the super is the receiver. This is +/// a message send to self with special delivery semantics indicating +/// which class's method should be called. +CodeGen::RValue +CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, + QualType ResultType, + Selector Sel, + const ObjCInterfaceDecl *Class, + llvm::Value *Receiver, + bool IsClassMessage, + const CodeGen::CallArgList &CallArgs) { + // ... + // Create and init a super structure; this is a (receiver, class) + // pair we will pass to objc_msgSendSuper. + llvm::Value *ObjCSuper = + CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); + + llvm::Value *ReceiverAsObject = + CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); + CGF.Builder.CreateStore(ReceiverAsObject, + CGF.Builder.CreateStructGEP(ObjCSuper, 0)); + + // If this is a class message the metaclass is passed as the target. + llvm::Value *Target = + IsClassMessage ? EmitMetaClassRef(CGF.Builder, Class) + : EmitClassRef(CGF.Builder, Class, true); + + // FIXME: We shouldn't need to do this cast, rectify the ASTContext + // and ObjCTypes types. + const llvm::Type *ClassTy = + CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); + Target = CGF.Builder.CreateBitCast(Target, ClassTy); + CGF.Builder.CreateStore(Target, + CGF.Builder.CreateStructGEP(ObjCSuper, 1)); + + return EmitMessageSend(CGF, ResultType, Sel, + ObjCSuper, ObjCTypes.SuperPtrCTy, + true, CallArgs); +} /* *** */ CodeGen::CGObjCRuntime *