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

Daniel Dunbar daniel at zuster.org
Fri Aug 22 21:28:30 PDT 2008


Author: ddunbar
Date: Fri Aug 22 23:28:29 2008
New Revision: 55225

URL: http://llvm.org/viewvc/llvm-project?rev=55225&view=rev
Log:
NeXT: Implement super 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=55225&r1=55224&r2=55225&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Fri Aug 22 23:28:29 2008
@@ -40,7 +40,7 @@
   
   const llvm::StructType *CFStringType;
   llvm::Constant *CFConstantStringClassReference;
-  llvm::Function *MessageSendFn;
+  llvm::Function *MessageSendFn, *MessageSendSuperFn;
 
 public:
   const llvm::Type *ShortTy, *IntTy, *LongTy;
@@ -54,6 +54,9 @@
   /// (typeof(Protocol))
   const llvm::Type *ExternalProtocolPtrTy;
 
+  /// SuperTy - LLVM type for struct objc_super.
+  const llvm::StructType *SuperTy;
+
   /// SymtabTy - LLVM type for struct objc_symtab.
   const llvm::StructType *SymtabTy;
   /// SymtabPtrTy - LLVM type for struct objc_symtab *.
@@ -126,6 +129,7 @@
   llvm::Constant *getCFConstantStringClassReference();
   const llvm::StructType *getCFStringType();
   llvm::Function *getMessageSendFn();
+  llvm::Function *getMessageSendSuperFn();
 };
 
 class CGObjCMac : public CodeGen::CGObjCRuntime {
@@ -421,8 +425,39 @@
                                     const ObjCMessageExpr *E,
                                     const ObjCInterfaceDecl *SuperClass,
                                     llvm::Value *Receiver) {
-  assert(0 && "Cannot generate message send to super for Mac runtime.");
-  return CodeGen::RValue::get(0);
+  // FIXME: This should be cached, not looked up every time. Meh. We
+  // should just make sure the optimizer hits it.
+  llvm::Value *ReceiverClass = EmitClassRef(CGF.Builder, SuperClass);
+  
+  // Create and init a super structure; this is a (receiver, class)
+  // pair we will pass to objc_msgSendSuper.
+  llvm::Value *ObjCSuper = 
+    CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
+  llvm::Value *ReceiverAsObject = 
+    CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
+  CGF.Builder.CreateStore(ReceiverAsObject, 
+                          CGF.Builder.CreateStructGEP(ObjCSuper, 0));
+  CGF.Builder.CreateStore(ReceiverClass, 
+                          CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+
+  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
+  llvm::Function *F = ObjCTypes.getMessageSendSuperFn();
+  llvm::Value *Args[2];
+  Args[0] = ObjCSuper;
+  Args[1] = EmitSelector(CGF.Builder, E->getSelector());
+
+  std::vector<const llvm::Type*> Params(2);
+  Params[0] = llvm::PointerType::getUnqual(ObjCTypes.SuperTy);
+  Params[1] = ObjCTypes.SelectorPtrTy;
+  llvm::FunctionType *CallFTy = llvm::FunctionType::get(ReturnTy,
+                                                        Params,
+                                                        true);
+  llvm::Type *PCallFTy = llvm::PointerType::getUnqual(CallFTy);
+  llvm::Constant *C = llvm::ConstantExpr::getBitCast(F, PCallFTy);
+  return CGF.EmitCallExprExt(C, E->getType(),
+                             E->arg_begin(),
+                             E->arg_end(),
+                             Args, 2);
 }
 
 /// Generate code for a message send expression.  
@@ -435,9 +470,9 @@
   Args[0] = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
   Args[1] = EmitSelector(CGF.Builder, E->getSelector());
 
-  std::vector<const llvm::Type*> Params;
-  Params.push_back(ObjCTypes.ObjectPtrTy);
-  Params.push_back(ObjCTypes.SelectorPtrTy);
+  std::vector<const llvm::Type*> Params(2);
+  Params[0] = ObjCTypes.ObjectPtrTy;
+  Params[1] = ObjCTypes.SelectorPtrTy;
   llvm::FunctionType *CallFTy = llvm::FunctionType::get(ReturnTy,
                                                         Params,
                                                         true);
@@ -1661,6 +1696,13 @@
                                      NULL);
   CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
 
+  SuperTy = 
+    llvm::StructType::get(ObjectPtrTy,
+                          ClassPtrTy,
+                          NULL);
+  CGM.getModule().addTypeName("struct._objc_super", 
+                              SuperTy);
+
   // Global metadata structures
 
   SymtabTy = llvm::StructType::get(LongTy,
@@ -1731,6 +1773,23 @@
   return MessageSendFn;
 }
 
+llvm::Function *ObjCTypesHelper::getMessageSendSuperFn() {
+  if (!MessageSendSuperFn) {
+    std::vector<const llvm::Type*> Params;
+    Params.push_back(llvm::PointerType::getUnqual(SuperTy));
+    Params.push_back(SelectorPtrTy);
+    MessageSendSuperFn = 
+      llvm::Function::Create(llvm::FunctionType::get(ObjectPtrTy,
+                                                     Params,
+                                                     true),
+                             llvm::Function::ExternalLinkage,
+                             "objc_msgSendSuper",
+                             &CGM.getModule());
+  }
+
+  return MessageSendSuperFn;
+}
+
 /* *** */
 
 CodeGen::CGObjCRuntime *





More information about the cfe-commits mailing list