From e8b470d40c4d44b77c2efab3cb977beb23344ff6 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Sat, 23 Aug 2008 04:28:29 +0000 Subject: [PATCH] NeXT: Implement super message sends. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55225 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjCMac.cpp | 71 +++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 1ad55491d9..d3eb85b848 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -40,7 +40,7 @@ private: const llvm::StructType *CFStringType; llvm::Constant *CFConstantStringClassReference; - llvm::Function *MessageSendFn; + llvm::Function *MessageSendFn, *MessageSendSuperFn; public: const llvm::Type *ShortTy, *IntTy, *LongTy; @@ -54,6 +54,9 @@ public: /// (typeof(Protocol)) const llvm::Type *ExternalProtocolPtrTy; + /// SuperTy - LLVM type for struct objc_super. + const llvm::StructType *SuperTy; + /// SymtabTy - LLVM type for struct objc_symtab. const llvm::StructType *SymtabTy; /// SymtabPtrTy - LLVM type for struct objc_symtab *. @@ -126,6 +129,7 @@ public: llvm::Constant *getCFConstantStringClassReference(); const llvm::StructType *getCFStringType(); llvm::Function *getMessageSendFn(); + llvm::Function *getMessageSendSuperFn(); }; class CGObjCMac : public CodeGen::CGObjCRuntime { @@ -421,8 +425,39 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, const ObjCMessageExpr *E, const ObjCInterfaceDecl *SuperClass, llvm::Value *Receiver) { - assert(0 && "Cannot generate message send to super for Mac runtime."); - return CodeGen::RValue::get(0); + // FIXME: This should be cached, not looked up every time. Meh. We + // should just make sure the optimizer hits it. + llvm::Value *ReceiverClass = EmitClassRef(CGF.Builder, SuperClass); + + // 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)); + CGF.Builder.CreateStore(ReceiverClass, + CGF.Builder.CreateStructGEP(ObjCSuper, 1)); + + const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType()); + llvm::Function *F = ObjCTypes.getMessageSendSuperFn(); + llvm::Value *Args[2]; + Args[0] = ObjCSuper; + Args[1] = EmitSelector(CGF.Builder, E->getSelector()); + + std::vector Params(2); + Params[0] = llvm::PointerType::getUnqual(ObjCTypes.SuperTy); + Params[1] = ObjCTypes.SelectorPtrTy; + llvm::FunctionType *CallFTy = llvm::FunctionType::get(ReturnTy, + Params, + true); + llvm::Type *PCallFTy = llvm::PointerType::getUnqual(CallFTy); + llvm::Constant *C = llvm::ConstantExpr::getBitCast(F, PCallFTy); + return CGF.EmitCallExprExt(C, E->getType(), + E->arg_begin(), + E->arg_end(), + Args, 2); } /// Generate code for a message send expression. @@ -435,9 +470,9 @@ CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, Args[0] = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp"); Args[1] = EmitSelector(CGF.Builder, E->getSelector()); - std::vector Params; - Params.push_back(ObjCTypes.ObjectPtrTy); - Params.push_back(ObjCTypes.SelectorPtrTy); + std::vector Params(2); + Params[0] = ObjCTypes.ObjectPtrTy; + Params[1] = ObjCTypes.SelectorPtrTy; llvm::FunctionType *CallFTy = llvm::FunctionType::get(ReturnTy, Params, true); @@ -1661,6 +1696,13 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) NULL); CGM.getModule().addTypeName("struct._objc_category", CategoryTy); + SuperTy = + llvm::StructType::get(ObjectPtrTy, + ClassPtrTy, + NULL); + CGM.getModule().addTypeName("struct._objc_super", + SuperTy); + // Global metadata structures SymtabTy = llvm::StructType::get(LongTy, @@ -1731,6 +1773,23 @@ llvm::Function *ObjCTypesHelper::getMessageSendFn() { return MessageSendFn; } +llvm::Function *ObjCTypesHelper::getMessageSendSuperFn() { + if (!MessageSendSuperFn) { + std::vector Params; + Params.push_back(llvm::PointerType::getUnqual(SuperTy)); + Params.push_back(SelectorPtrTy); + MessageSendSuperFn = + llvm::Function::Create(llvm::FunctionType::get(ObjectPtrTy, + Params, + true), + llvm::Function::ExternalLinkage, + "objc_msgSendSuper", + &CGM.getModule()); + } + + return MessageSendSuperFn; +} + /* *** */ CodeGen::CGObjCRuntime * -- 2.40.0