From: Daniel Dunbar Date: Sat, 16 Aug 2008 00:25:02 +0000 (+0000) Subject: Change ObjCRuntime::LookupClass -> GetClass, and now takes the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ddb2a3d55a24a1dbdf9152621642d9a4b4fc2f61;p=clang Change ObjCRuntime::LookupClass -> GetClass, and now takes the ObjCInterfaceDecl. Change ObjCRuntime::GenerateMessageSendSuper to take the ObjCInterfaceDecl for the super class, instead of just its name. Change EmitObjCMessageExpr to make the right runtime calls for super sends in class methods (i.e. a super send with the class object as the receiver). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54833 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index df3226d128..54b4e19c57 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -48,13 +48,18 @@ llvm::Value *CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { // Find the receiver llvm::Value *Receiver; if (!ReceiverExpr) { - const char * classname = E->getClassName()->getName(); - if (!strcmp(classname, "super")) { - classname = E->getMethodDecl()->getClassInterface()->getName(); + const ObjCInterfaceDecl *OID = E->getClassInfo().first; + + // Very special case, super send in class method. The receiver is + // self (the class object) and the send uses super semantics. + if (!OID) { + assert(!strcmp(E->getClassName()->getName(), "super") && + "Unexpected missing class interface in message send."); + OID = E->getMethodDecl()->getClassInterface(); + isSuperMessage = true; } - llvm::Value *ClassName = CGM.GetAddrOfConstantCString(classname); - ClassName = Builder.CreateStructGEP(ClassName, 0); - Receiver = Runtime.LookupClass(Builder, ClassName); + + Receiver = Runtime.GetClass(Builder, OID); } else if (const PredefinedExpr *PDE = dyn_cast(E->getReceiver())) { assert(PDE->getIdentType() == PredefinedExpr::ObjCSuper); @@ -88,10 +93,8 @@ llvm::Value *CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { if (isSuperMessage) { // super is only valid in an Objective-C method const ObjCMethodDecl *OMD = cast(CurFuncDecl); - const char *SuperClass = - OMD->getClassInterface()->getSuperClass()->getName(); return Runtime.GenerateMessageSendSuper(Builder, ConvertType(E->getType()), - SuperClass, + OMD->getClassInterface()->getSuperClass(), Receiver, E->getSelector(), &Args[0], Args.size()); } diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 4c678c9f8f..7257f8d569 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -101,13 +101,13 @@ public: unsigned ArgC); virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<> &Builder, const llvm::Type *ReturnTy, - const char *SuperClassName, + const ObjCInterfaceDecl *SuperClass, llvm::Value *Receiver, Selector Sel, llvm::Value** ArgV, unsigned ArgC); - virtual llvm::Value *LookupClass(llvm::IRBuilder<> &Builder, - llvm::Value *ClassName); + virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder, + const ObjCInterfaceDecl *OID); virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel); virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD); @@ -170,8 +170,11 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm) } // This has to perform the lookup every time, since posing and related // techniques can modify the name -> class mapping. -llvm::Value *CGObjCGNU::LookupClass(llvm::IRBuilder<> &Builder, - llvm::Value *ClassName) { +llvm::Value *CGObjCGNU::GetClass(llvm::IRBuilder<> &Builder, + const ObjCInterfaceDecl *OID) { + llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getName()); + ClassName = Builder.CreateStructGEP(ClassName, 0); + llvm::Constant *ClassLookupFn = TheModule.getOrInsertFunction("objc_lookup_class", IdTy, PtrToInt8Ty, NULL); @@ -235,14 +238,13 @@ llvm::Constant *CGObjCGNU::GenerateConstantString(const std::string &Str) { ///should be called. llvm::Value *CGObjCGNU::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder, const llvm::Type *ReturnTy, - const char *SuperClassName, + const ObjCInterfaceDecl *SuperClass, llvm::Value *Receiver, Selector Sel, llvm::Value** ArgV, unsigned ArgC) { // TODO: This should be cached, not looked up every time. - llvm::Value *ReceiverClass = LookupClass(Builder, - MakeConstantString(SuperClassName)); + llvm::Value *ReceiverClass = GetClass(Builder, SuperClass); llvm::Value *cmd = GetSelector(Builder, Sel); std::vector impArgTypes; impArgTypes.push_back(Receiver->getType()); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index b307148955..61b9534759 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -205,16 +205,17 @@ public: llvm::Value** ArgV, unsigned ArgC); - virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<> &Builder, - const llvm::Type *ReturnTy, - const char *SuperClassName, - llvm::Value *Receiver, - Selector Sel, - llvm::Value** ArgV, - unsigned ArgC); - - virtual llvm::Value *LookupClass(llvm::IRBuilder<> &Builder, - llvm::Value *ClassName); + virtual llvm::Value * + GenerateMessageSendSuper(llvm::IRBuilder<> &Builder, + const llvm::Type *ReturnTy, + const ObjCInterfaceDecl *SuperClass, + llvm::Value *Receiver, + Selector Sel, + llvm::Value** ArgV, + unsigned ArgC); + + virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder, + const ObjCInterfaceDecl *SuperClass); virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel); @@ -260,10 +261,10 @@ CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) EmitImageInfo(); } -// This has to perform the lookup every time, since posing and related -// techniques can modify the name -> class mapping. -llvm::Value *CGObjCMac::LookupClass(llvm::IRBuilder<> &Builder, - llvm::Value *ClassName) { +/// GetClass - Return a reference to the class for the given interface +/// decl. +llvm::Value *CGObjCMac::GetClass(llvm::IRBuilder<> &Builder, + const ObjCInterfaceDecl *OID) { assert(0 && "Cannot lookup classes on Mac runtime."); return 0; } @@ -323,13 +324,14 @@ llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) { /// 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. -llvm::Value *CGObjCMac::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder, - const llvm::Type *ReturnTy, - const char *SuperClassName, - llvm::Value *Receiver, - Selector Sel, - llvm::Value** ArgV, - unsigned ArgC) { +llvm::Value * +CGObjCMac::GenerateMessageSendSuper(llvm::IRBuilder<> &Builder, + const llvm::Type *ReturnTy, + const ObjCInterfaceDecl *SuperClass, + llvm::Value *Receiver, + Selector Sel, + llvm::Value** ArgV, + unsigned ArgC) { assert(0 && "Cannot generate message send to super for Mac runtime."); return 0; } diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 83ca0e638c..368e5ae105 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -31,6 +31,7 @@ namespace llvm { namespace clang { class ObjCCategoryImplDecl; class ObjCImplementationDecl; + class ObjCInterfaceDecl; class ObjCMethodDecl; class ObjCProtocolDecl; class Selector; @@ -78,13 +79,14 @@ public: /// Generate an Objective-C message send operation to the super /// class. - virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder &Builder, - const llvm::Type *ReturnTy, - const char *SuperClassName, - llvm::Value *Receiver, - Selector Sel, - llvm::Value** ArgV, - unsigned ArgC) = 0; + virtual llvm::Value * + GenerateMessageSendSuper(llvm::IRBuilder &Builder, + const llvm::Type *ReturnTy, + const ObjCInterfaceDecl *SuperClassName, + llvm::Value *Receiver, + Selector Sel, + llvm::Value** ArgV, + unsigned ArgC) = 0; /// Emit the code to return the named protocol as an object, as in a /// @protocol expression. @@ -104,9 +106,10 @@ public: // parameters are passed. virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD) = 0; - /// Look up the class for the specified name - virtual llvm::Value *LookupClass(BuilderType &Builder, - llvm::Value *ClassName) = 0; + /// GetClass - Return a reference to the class for the given + /// interface decl. + virtual llvm::Value *GetClass(BuilderType &Builder, + const ObjCInterfaceDecl *OID) = 0; /// If instance variable addresses are determined at runtime then this should /// return true, otherwise instance variables will be accessed directly from