[cfe-commits] r54664 - /cfe/trunk/lib/CodeGen/CGObjCMac.cpp

Daniel Dunbar daniel at zuster.org
Mon Aug 11 20:39:26 PDT 2008


Author: ddunbar
Date: Mon Aug 11 22:39:23 2008
New Revision: 54664

URL: http://llvm.org/viewvc/llvm-project?rev=54664&view=rev
Log:
Add NeXT support for (simple) message sends.

Modified:
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=54664&r1=54663&r2=54664&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Mon Aug 11 22:39:23 2008
@@ -33,16 +33,23 @@
   
   const llvm::StructType *CFStringType;
   llvm::Constant *CFConstantStringClassReference;
-  
+  llvm::Function *MessageSendFn;
+
 public:
   const llvm::Type *LongTy;
-  
+
+  /// ObjectTy - Opaque type for Objective-C objects
+  const llvm::Type *ObjectTy, *ObjectPtrTy;
+  /// SelectorTy - Opaque type for Objective-C selectors
+  const llvm::Type *SelectorTy, *SelectorPtrTy;
+
 public:
   ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
   ~ObjCTypesHelper();
   
   llvm::Constant *getCFConstantStringClassReference();
   const llvm::StructType *getCFStringType();
+  llvm::Function *getMessageSendFn();
 };
 
 class CGObjCMac : public CodeGen::CGObjCRuntime {
@@ -52,6 +59,12 @@
   /// ObjCABI - FIXME: Not sure yet.
   unsigned ObjCABI;
 
+  /// MethodVarNames - uniqued method variable names.
+  llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
+
+  /// SelectorReferences - uniqued selector references.
+  llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
+
   /// UsedGlobals - list of globals to pack into the llvm.used metadata
   /// to prevent them from being clobbered.
   std::vector<llvm::GlobalValue*> UsedGlobals;
@@ -63,6 +76,14 @@
   /// FinishModule - Write out global data structures at the end of
   /// processing a translation unit.
   void FinishModule();
+  
+  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
+  /// for the given selector.
+  llvm::Value *EmitSelector(llvm::IRBuilder<> &Builder, Selector Sel);
+
+  /// GetMethodVarName - Return a unique constant for the given
+  /// selector's name.
+  llvm::Constant *GetMethodVarName(Selector Sel);
 
 public:
   CGObjCMac(CodeGen::CodeGenModule &cgm);
@@ -171,8 +192,7 @@
 
 /// GetSelector - Return the pointer to the unique'd string for this selector.
 llvm::Value *CGObjCMac::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
-  assert(0 && "Cannot get selector on Mac runtime.");
-  return 0;
+  return EmitSelector(Builder, Sel);
 }
 
 /// Generate a constant CFString object.
@@ -244,9 +264,20 @@
                                             llvm::Value *Receiver,
                                             Selector Sel,
                                             llvm::Value** ArgV,
-                                            unsigned ArgC) {
-  assert(0 && "Cannot generate message send for Mac runtime.");
-  return 0;
+                                            unsigned ArgC) {  
+  if (!Sender) {
+    llvm::Function *F = ObjCTypes.getMessageSendFn();
+    llvm::Value **Args = new llvm::Value*[ArgC+2];
+    Args[0] = Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
+    Args[1] = EmitSelector(Builder, Sel);
+    std::copy(ArgV, ArgV+ArgC, Args+2);
+    llvm::CallInst *CI = Builder.CreateCall(F, Args, Args+ArgC+2, "tmp");
+    delete[] Args;
+    return Builder.CreateBitCast(CI, ReturnTy, "tmp");
+  } else {
+    assert(0 && "cannot generate message sends with sender");
+    return 0;
+  }
 }
 
 llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder, 
@@ -297,16 +328,15 @@
   return NULL;
 }
 
-llvm::Function *CGObjCMac::MethodPreamble(
-                                         const std::string &ClassName,
-                                         const std::string &CategoryName,
-                                         const std::string &MethodName,
-                                         const llvm::Type *ReturnTy,
-                                         const llvm::Type *SelfTy,
-                                         const llvm::Type **ArgTy,
-                                         unsigned ArgC,
-                                         bool isClassMethod,
-                                         bool isVarArg) {
+llvm::Function *CGObjCMac::MethodPreamble(const std::string &ClassName,
+                                          const std::string &CategoryName,
+                                          const std::string &MethodName,
+                                          const llvm::Type *ReturnTy,
+                                          const llvm::Type *SelfTy,
+                                          const llvm::Type **ArgTy,
+                                          unsigned ArgC,
+                                          bool isClassMethod,
+                                          bool isVarArg) {
   assert(0 && "Cannot generate method preamble for Mac runtime.");
   return 0;
 }
@@ -359,6 +389,42 @@
   UsedGlobals.push_back(GV);
 }
 
+llvm::Value *CGObjCMac::EmitSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
+  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
+  
+  if (!Entry) {
+    llvm::Constant *Casted = 
+      llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
+                                     ObjCTypes.SelectorPtrTy);
+    Entry = 
+      new llvm::GlobalVariable(ObjCTypes.SelectorPtrTy, false,
+                               llvm::GlobalValue::InternalLinkage,
+                               Casted, "\01L_OBJC_SELECTOR_REFERENCES_",
+                               &CGM.getModule());
+    Entry->setSection("__OBJC,__message_refs,literal_pointers,no_dead_strip");
+    UsedGlobals.push_back(Entry);
+  }
+
+  return Builder.CreateLoad(Entry, false, "tmp");
+}
+
+llvm::Constant *CGObjCMac::GetMethodVarName(Selector Sel) {
+  llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
+
+  if (!Entry) {
+    llvm::Constant *C = llvm::ConstantArray::get(Sel.getName());
+    Entry = 
+      new llvm::GlobalVariable(C->getType(), true, 
+                               llvm::GlobalValue::InternalLinkage,
+                               C, "\01L_OBJC_METH_VAR_NAME_", 
+                               &CGM.getModule());
+    Entry->setSection("__TEXT,__cstring,cstring_literals");
+    UsedGlobals.push_back(Entry);
+  }
+
+  return Entry;
+}
+
 void CGObjCMac::FinishModule() {
   std::vector<llvm::Constant*> Used;
   
@@ -385,8 +451,16 @@
   : CGM(cgm),
     CFStringType(0),
     CFConstantStringClassReference(0),
-    LongTy(CGM.getTypes().ConvertType(CGM.getContext().LongTy))
+    MessageSendFn(0),
+    LongTy(CGM.getTypes().ConvertType(CGM.getContext().LongTy)),
+    // FIXME: We want the types from the front-end.
+    ObjectTy(llvm::OpaqueType::get()),
+    ObjectPtrTy(llvm::PointerType::getUnqual(ObjectTy)),
+    SelectorTy(llvm::OpaqueType::get()),
+    SelectorPtrTy(llvm::PointerType::getUnqual(SelectorTy))
 {
+  CGM.getModule().addTypeName("struct.__objc_object", ObjectTy);
+  CGM.getModule().addTypeName("struct.__objc_selector", SelectorTy);
 }
 
 ObjCTypesHelper::~ObjCTypesHelper() {
@@ -423,6 +497,22 @@
   return CFConstantStringClassReference;
 }
 
+llvm::Function *ObjCTypesHelper::getMessageSendFn() {
+  if (!MessageSendFn) {
+    std::vector<const llvm::Type*> Params;
+    Params.push_back(ObjectPtrTy);
+    Params.push_back(SelectorPtrTy);
+    MessageSendFn = llvm::Function::Create(llvm::FunctionType::get(ObjectPtrTy,
+                                                                   Params,
+                                                                   true),
+                                           llvm::Function::ExternalLinkage,
+                                           "objc_msgSend",
+                                           &CGM.getModule());
+  }
+
+  return MessageSendFn;
+}
+
 /* *** */
 
 CodeGen::CGObjCRuntime *CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM){





More information about the cfe-commits mailing list