[cfe-commits] r55307 - in /cfe/trunk/lib/CodeGen: CGObjC.cpp CGObjCGNU.cpp CGObjCMac.cpp CGObjCRuntime.h

Daniel Dunbar daniel at zuster.org
Mon Aug 25 01:19:25 PDT 2008


Author: ddunbar
Date: Mon Aug 25 03:19:24 2008
New Revision: 55307

URL: http://llvm.org/viewvc/llvm-project?rev=55307&view=rev
Log:
Fix Obj-C super sends inside class methods.
 - NeXT loads the super class at runtime; this required changing the
   runtime interface to pass more information down.

Modified:
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CGObjCRuntime.h

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Mon Aug 25 03:19:24 2008
@@ -50,6 +50,7 @@
   CGObjCRuntime &Runtime = CGM.getObjCRuntime();
   const Expr *ReceiverExpr = E->getReceiver();
   bool isSuperMessage = false;
+  bool isClassMessage = false;
   // Find the receiver
   llvm::Value *Receiver;
   if (!ReceiverExpr) {
@@ -60,11 +61,13 @@
     if (!OID) {
       assert(!strcmp(E->getClassName()->getName(), "super") &&
              "Unexpected missing class interface in message send.");
-      OID = E->getMethodDecl()->getClassInterface();
       isSuperMessage = true;
+      Receiver = LoadObjCSelf();
+    } else {
+      Receiver = Runtime.GetClass(Builder, OID);
     }
-
-    Receiver = Runtime.GetClass(Builder, OID);   
+    
+    isClassMessage = true;
   } else if (const PredefinedExpr *PDE =
                dyn_cast<PredefinedExpr>(E->getReceiver())) {
     assert(PDE->getIdentType() == PredefinedExpr::ObjCSuper);
@@ -78,10 +81,11 @@
     // super is only valid in an Objective-C method
     const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
     return Runtime.GenerateMessageSendSuper(*this, E,
-                                            OMD->getClassInterface()->getSuperClass(),
-                                            Receiver);
+                                            OMD->getClassInterface(),
+                                            Receiver,
+                                            isClassMessage);
   }
-  return Runtime.GenerateMessageSend(*this, E, Receiver);
+  return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage);
 }
 
 /// Generate an Objective-C method.  An Objective-C method is a C function with

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Mon Aug 25 03:19:24 2008
@@ -97,12 +97,14 @@
   virtual CodeGen::RValue 
   GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
                       const ObjCMessageExpr *E,
-                      llvm::Value *Receiver);
+                      llvm::Value *Receiver,
+                      bool IsClassMessage);
   virtual CodeGen::RValue 
   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
                            const ObjCMessageExpr *E,
-                           const ObjCInterfaceDecl *Super,
-                           llvm::Value *Receiver);
+                           const ObjCInterfaceDecl *Class,
+                           llvm::Value *Receiver,
+                           bool IsClassMessage);
   virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
                                 const ObjCInterfaceDecl *OID);
   virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
@@ -236,8 +238,10 @@
 CodeGen::RValue
 CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
                                     const ObjCMessageExpr *E,
-                                    const ObjCInterfaceDecl *SuperClass,
-                                    llvm::Value *Receiver) {
+                                    const ObjCInterfaceDecl *Class,
+                                    llvm::Value *Receiver,
+                                    bool IsClassMessage) {
+  const ObjCInterfaceDecl *SuperClass = Class->getSuperClass();
   const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
   // TODO: This should be cached, not looked up every time.
   llvm::Value *ReceiverClass = GetClass(CGF.Builder, SuperClass);
@@ -280,7 +284,8 @@
 CodeGen::RValue
 CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
                                const ObjCMessageExpr *E,
-                               llvm::Value *Receiver) {
+                               llvm::Value *Receiver,
+                               bool IsClassMessage) {
   const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
   llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
 

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Mon Aug 25 03:19:24 2008
@@ -220,9 +220,14 @@
   llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
                                bool ForClass,
                                const llvm::Type *InterfaceTy);
-  
+
+  /// EmitMetaClass - Emit a forward reference to the class structure
+  /// for the metaclass of the given interface. The return value has
+  /// type ClassPtrTy.
+  llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
+
   /// EmitMetaClass - Emit a class structure for the metaclass of the
-  /// given implementation. return value has type ClassPtrTy.
+  /// given implementation. The return value has type ClassPtrTy.
   llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
                                 llvm::Constant *Protocols,
                                 const llvm::Type *InterfaceTy);
@@ -316,13 +321,15 @@
 
   virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
                                               const ObjCMessageExpr *E,
-                                              llvm::Value *Receiver);
+                                              llvm::Value *Receiver,
+                                              bool IsClassMessage);
 
   virtual CodeGen::RValue 
   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
                            const ObjCMessageExpr *E,
-                           const ObjCInterfaceDecl *SuperClass,
-                           llvm::Value *Receiver);
+                           const ObjCInterfaceDecl *Class,
+                           llvm::Value *Receiver,
+                           bool IsClassMessage);
   
   virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
                                 const ObjCInterfaceDecl *ID);
@@ -403,12 +410,9 @@
 CodeGen::RValue
 CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
                                     const ObjCMessageExpr *E,
-                                    const ObjCInterfaceDecl *SuperClass,
-                                    llvm::Value *Receiver) {
-  // 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);
-  
+                                    const ObjCInterfaceDecl *Class,
+                                    llvm::Value *Receiver,
+                                    bool IsClassMessage) {
   // Create and init a super structure; this is a (receiver, class)
   // pair we will pass to objc_msgSendSuper.
   llvm::Value *ObjCSuper = 
@@ -417,16 +421,28 @@
     CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
   CGF.Builder.CreateStore(ReceiverAsObject, 
                           CGF.Builder.CreateStructGEP(ObjCSuper, 0));
-  CGF.Builder.CreateStore(ReceiverClass, 
-                          CGF.Builder.CreateStructGEP(ObjCSuper, 1));
 
+  // If this is a class message the metaclass is passed as the target.
+  llvm::Value *Target;
+  if (IsClassMessage) {
+    llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
+    llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
+    llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
+    Target = Super;
+  } else {
+    Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
+  }
+  CGF.Builder.CreateStore(Target, 
+                          CGF.Builder.CreateStructGEP(ObjCSuper, 1));
+    
   return EmitMessageSend(CGF, E, ObjCSuper, true);
 }
                                            
 /// Generate code for a message send expression.  
 CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
                                                const ObjCMessageExpr *E,
-                                               llvm::Value *Receiver) {
+                                               llvm::Value *Receiver,
+                                               bool IsClassMessage) {
   llvm::Value *Arg0 = 
     CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
   return EmitMessageSend(CGF, E, Arg0, false);
@@ -972,12 +988,22 @@
   llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
                                                    Values);
 
-  llvm::GlobalVariable *GV = 
-    new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
-                             llvm::GlobalValue::InternalLinkage,
-                             Init,
-                             std::string("\01L_OBJC_METACLASS_")+ClassName,
-                             &CGM.getModule());
+  std::string Name("\01L_OBJC_METACLASS_");
+  Name += ClassName;
+
+  // Check for a forward reference.
+  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+  if (GV) {
+    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+           "Forward metaclass reference has incorrect type.");
+    GV->setLinkage(llvm::GlobalValue::InternalLinkage);
+    GV->setInitializer(Init);
+  } else {
+    GV = new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
+                                  llvm::GlobalValue::InternalLinkage,
+                                  Init, Name,
+                                  &CGM.getModule());
+  }
   GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
   UsedGlobals.push_back(GV);
   // FIXME: Why?
@@ -986,6 +1012,31 @@
   return GV;
 }
 
+llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {  
+  std::string Name("\01L_OBJC_METACLASS_");
+  Name += ID->getName();
+
+  // FIXME: Should we look these up somewhere other than the
+  // module. Its a bit silly since we only generate these while
+  // processing an implementation, so exactly one pointer would work
+  // if know when we entered/exitted an implementation block.
+
+  // Check for an existing forward reference.
+  if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name)) {
+    assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
+           "Forward metaclass reference has incorrect type.");
+    return GV;
+  } else {
+    // Generate as an external reference to keep a consistent
+    // module. This will be patched up when we emit the metaclass.
+    return new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
+                                    llvm::GlobalValue::ExternalLinkage,
+                                    0,
+                                    Name,
+                                    &CGM.getModule());
+  }
+}
+
 /*
   struct objc_class_ext {
     uint32_t size;

Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=55307&r1=55306&r2=55307&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Mon Aug 25 03:19:24 2008
@@ -80,15 +80,18 @@
   virtual CodeGen::RValue 
   GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
                       const ObjCMessageExpr *E,
-                      llvm::Value *Receiver) = 0;
+                      llvm::Value *Receiver,
+                      bool IsClassMessage) = 0;
 
   /// Generate an Objective-C message send operation to the super
-  /// class.
+  /// class initiated in a method for Class and with the given Self
+  /// object.
   virtual CodeGen::RValue
   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
                            const ObjCMessageExpr *E,
-                           const ObjCInterfaceDecl *SuperClass,
-                           llvm::Value *Receiver) = 0;
+                           const ObjCInterfaceDecl *Class,
+                           llvm::Value *Self,
+                           bool IsClassMessage) = 0;
 
   /// Emit the code to return the named protocol as an object, as in a
   /// @protocol expression.





More information about the cfe-commits mailing list