diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-02-06 20:09:23 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-02-06 20:09:23 +0000 |
commit | 7a06aae468c94a21c267106ec16bd2c79dab2857 (patch) | |
tree | aaa9505f9de13e09276cc21ccab09d093b40eca8 /lib/CodeGen/CGObjCMac.cpp | |
parent | 6e94ef5696cfb005d3fc7bbac8dcf7690b64f0a5 (diff) |
objc2's nonfragile abi API for messages sent to 'super'.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63959 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGObjCMac.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 117 |
1 files changed, 110 insertions, 7 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 8b0c9bb0f2..c5ce163b3b 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -597,6 +597,8 @@ private: ObjCNonFragileABITypesHelper ObjCTypes; llvm::GlobalVariable* ObjCEmptyCacheVar; llvm::GlobalVariable* ObjCEmptyVtableVar; + /// MetaClassReferences - uniqued meta class references. + llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> 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 * |