diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 21 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCGNU.cpp | 18 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 44 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCRuntime.h | 23 |
4 files changed, 58 insertions, 48 deletions
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index df3226d128a..54b4e19c572 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/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<PredefinedExpr>(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<ObjCMethodDecl>(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/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 4c678c9f8fb..7257f8d5691 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/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<const llvm::Type*> impArgTypes; impArgTypes.push_back(Receiver->getType()); diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index b307148955d..61b9534759a 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/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/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index 83ca0e638c9..368e5ae1059 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/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<true> &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<true> &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 |