diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index de89f0d961..362865dac6 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -95,7 +95,8 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { Args); } return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(), - Receiver, isClassMessage, Args); + Receiver, isClassMessage, Args, + E->getMethodDecl()); } /// StartObjCMethod - Begin emission of an ObjCMethod. This generates diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 2ddd6e15dc..7bcd9797fb 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -106,7 +106,8 @@ public: Selector Sel, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs); + const CallArgList &CallArgs, + const ObjCMethodDecl *Method); virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, QualType ResultType, @@ -119,6 +120,8 @@ public: virtual llvm::Value *GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *OID); virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel); + virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl + *Method); virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD); @@ -160,7 +163,7 @@ public: static std::string SymbolNameForClass(const std::string &ClassName) { - return ".objc_class_" + ClassName; + return "___objc_class_name_" + ClassName; } static std::string SymbolNameForMethod(const std::string &ClassName, const @@ -218,9 +221,7 @@ llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder, return Builder.CreateCall(ClassLookupFn, ClassName); } -/// GetSelector - Return the pointer to the unique'd string for this selector. llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) { - // FIXME: uniquing on the string is wasteful, unique on Sel instead! llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()]; if (US == 0) US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy), @@ -229,7 +230,32 @@ llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) { NULL, &TheModule); return Builder.CreateLoad(US); - +} + +llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl + *Method) { + + std::string SelName = Method->getSelector().getAsString(); + std::string SelTypes; + CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes); + // Typed selectors + TypedSelector Selector = TypedSelector(SelName, + SelTypes); + + // If it's already cached, return it. + if (TypedSelectors[Selector]) + { + return Builder.CreateLoad(TypedSelectors[Selector]); + } + + // If it isn't, cache it. + llvm::GlobalAlias *Sel = new llvm::GlobalAlias( + llvm::PointerType::getUnqual(SelectorTy), + llvm::GlobalValue::InternalLinkage, SelName, + NULL, &TheModule); + TypedSelectors[Selector] = Sel; + + return Builder.CreateLoad(Sel); } llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str, @@ -360,8 +386,13 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, Selector Sel, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs) { - llvm::Value *cmd = GetSelector(CGF.Builder, Sel); + const CallArgList &CallArgs, + const ObjCMethodDecl *Method) { + llvm::Value *cmd; + if (Method) + cmd = GetSelector(CGF.Builder, Method); + else + cmd = GetSelector(CGF.Builder, Sel); CallArgList ActualArgs; ActualArgs.push_back( diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 5571f0f558..8043f7652b 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1016,7 +1016,8 @@ private: Selector Sel, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs); + const CallArgList &CallArgs, + const ObjCMethodDecl *Method); virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, @@ -1032,7 +1033,12 @@ private: const ObjCInterfaceDecl *ID); virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel); - + + /// The NeXT/Apple runtimes do not support typed selectors; just emit an + /// untyped one. + virtual llvm::Value *GetSelector(CGBuilderTy &Builder, + const ObjCMethodDecl *Method); + virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); @@ -1200,7 +1206,8 @@ public: Selector Sel, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs); + const CallArgList &CallArgs, + const ObjCMethodDecl *Method); virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, @@ -1217,6 +1224,12 @@ public: virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel) { return EmitSelector(Builder, Sel); } + + /// The NeXT/Apple runtimes do not support typed selectors; just emit an + /// untyped one. + virtual llvm::Value *GetSelector(CGBuilderTy &Builder, + const ObjCMethodDecl *Method) + { return EmitSelector(Builder, Method->getSelector()); } virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); @@ -1303,6 +1316,10 @@ llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder, llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) { return EmitSelector(Builder, Sel); } +llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl + *Method) { + return EmitSelector(Builder, Method->getSelector()); +} /// Generate a constant CFString object. /* @@ -1382,7 +1399,8 @@ CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, Selector Sel, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs) { + const CallArgList &CallArgs, + const ObjCMethodDecl *Method) { return EmitMessageSend(CGF, ResultType, Sel, Receiver, CGF.getContext().getObjCIdType(), false, CallArgs); @@ -4983,7 +5001,8 @@ CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend( Selector Sel, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs) { + const CallArgList &CallArgs, + const ObjCMethodDecl *Method) { return EmitMessageSend(CGF, ResultType, Sel, Receiver, CGF.getContext().getObjCIdType(), false, CallArgs); diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index ada449559d..55d94a051e 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -17,6 +17,7 @@ #define CLANG_CODEGEN_OBCJRUNTIME_H #include "clang/Basic/IdentifierTable.h" // Selector #include "llvm/ADT/SmallVector.h" +#include "clang/AST/DeclObjC.h" #include #include "CGBuilder.h" @@ -100,6 +101,10 @@ public: virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel) = 0; + /// Get a typed selector. + virtual llvm::Value *GetSelector(CGBuilderTy &Builder, + const ObjCMethodDecl *Method) = 0; + /// Generate a constant string object. virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *) = 0; @@ -110,14 +115,15 @@ public: /// Generate a class stucture for this class. virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0; - /// Generate an Objective-C message send operation. + /// Generate an Objective-C message send operation. virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs) = 0; + const CallArgList &CallArgs, + const ObjCMethodDecl *Method=0) = 0; /// Generate an Objective-C message send operation to the super /// class initiated in a method for Class and with the given Self