]> granicus.if.org Git - clang/commitdiff
Patch to support Gnu runtime's typed selectors.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 5 May 2009 21:36:57 +0000 (21:36 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 5 May 2009 21:36:57 +0000 (21:36 +0000)
Patch by David Chisnall.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71023 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGObjC.cpp
lib/CodeGen/CGObjCGNU.cpp
lib/CodeGen/CGObjCMac.cpp
lib/CodeGen/CGObjCRuntime.h

index de89f0d961aec32c7e45c9c95a80d1c0b1e6f143..362865dac64db46c09301635f777aebdc94790f7 100644 (file)
@@ -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
index 2ddd6e15dc6873330fd39b4e0d7a08cf8d5a6c55..7bcd9797fb1d58599a87b750be62f5a98102b9e1 100644 (file)
@@ -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(
index 5571f0f55822d01d9fc804a16d68daac04c8bf89..8043f7652b73b3bd7d941936210651ced33fe632 100644 (file)
@@ -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);
index ada449559d90445864c0a33ece7b84e31a8a2424..55d94a051e6f4981b7934a560dff1abc799be815 100644 (file)
@@ -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 <string>
 
 #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