[cfe-commits] r71904 - in /cfe/trunk: lib/CodeGen/CGObjCMac.cpp test/CodeGenObjC/non-lazy-classes.m

Daniel Dunbar daniel at zuster.org
Fri May 15 15:33:15 PDT 2009


Author: ddunbar
Date: Fri May 15 17:33:15 2009
New Revision: 71904

URL: http://llvm.org/viewvc/llvm-project?rev=71904&view=rev
Log:
Classes with "+load" methods need to go in the non-lazy class list (or
else the method will not be found by the runtime at class load time).

Added:
    cfe/trunk/test/CodeGenObjC/non-lazy-classes.m
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=71904&r1=71903&r2=71904&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Fri May 15 17:33:15 2009
@@ -810,10 +810,16 @@
   
   /// DefinedClasses - List of defined classes.
   std::vector<llvm::GlobalValue*> DefinedClasses;
+
+  /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
+  std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
   
   /// DefinedCategories - List of defined categories.
   std::vector<llvm::GlobalValue*> DefinedCategories;
   
+  /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
+  std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
+  
   /// UsedGlobals - List of globals to pack into the llvm.used metadata
   /// to prevent them from being clobbered.
   std::vector<llvm::GlobalVariable*> UsedGlobals;
@@ -1259,16 +1265,20 @@
                         uint32_t &InstanceSize);
   
   // Shamelessly stolen from Analysis/CFRefCount.cpp
-  Selector GetNullarySelector(const char* name) {
+  Selector GetNullarySelector(const char* name) const {
     IdentifierInfo* II = &CGM.getContext().Idents.get(name);
     return CGM.getContext().Selectors.getSelector(0, &II);
   }
   
-  Selector GetUnarySelector(const char* name) {
+  Selector GetUnarySelector(const char* name) const {
     IdentifierInfo* II = &CGM.getContext().Idents.get(name);
     return CGM.getContext().Selectors.getSelector(1, &II);
   }
 
+  /// ImplementationIsNonLazy - Check whether the given category or
+  /// class implementation is "non-lazy".
+  bool ImplementationIsNonLazy(const DeclContext *DC) const;
+
 public:
   CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
   // FIXME. All stubs for now!
@@ -4075,21 +4085,21 @@
   
   // Build list of all implemented class addresses in array
   // L_OBJC_LABEL_CLASS_$.
-  // FIXME. Also generate in L_OBJC_LABEL_NONLAZY_CLASS_$
-  // list of 'nonlazy' implementations (defined as those with a +load{}
-  // method!!).
   AddModuleClassList(DefinedClasses, 
                      "\01L_OBJC_LABEL_CLASS_$",
                      "__DATA, __objc_classlist, regular, no_dead_strip");
+  AddModuleClassList(DefinedNonLazyClasses, 
+                     "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
+                     "__DATA, __objc_nlclslist, regular, no_dead_strip");
   
   // Build list of all implemented category addresses in array
   // L_OBJC_LABEL_CATEGORY_$.
-  // FIXME. Also generate in L_OBJC_LABEL_NONLAZY_CATEGORY_$
-  // list of 'nonlazy' category implementations (defined as those with a +load{}
-  // method!!).
   AddModuleClassList(DefinedCategories, 
                      "\01L_OBJC_LABEL_CATEGORY_$",
                      "__DATA, __objc_catlist, regular, no_dead_strip");
+  AddModuleClassList(DefinedNonLazyCategories, 
+                     "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
+                     "__DATA, __objc_nlcatlist, regular, no_dead_strip");
   
   //  static int L_OBJC_IMAGE_INFO[2] = { 0, flags };
   // FIXME. flags can be 0 | 1 | 2 | 6. For now just use 0
@@ -4321,6 +4331,19 @@
   return GV;
 }
 
+bool 
+CGObjCNonFragileABIMac::ImplementationIsNonLazy(const DeclContext *DC) const {
+  DeclContext::lookup_const_result res = 
+    DC->lookup(CGM.getContext(), GetNullarySelector("load"));
+
+  for (; res.first != res.second; ++res.first)
+    if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(*res.first))
+      if (OMD->isClassMethod())
+        return true;
+  
+  return false;
+}
+
 void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
                                               uint32_t &InstanceStart,
                                               uint32_t &InstanceSize) {
@@ -4425,6 +4448,10 @@
                        classIsHidden);
   DefinedClasses.push_back(ClassMD);
 
+  // Determine if this class is also "non-lazy".
+  if (ImplementationIsNonLazy(ID))
+    DefinedNonLazyClasses.push_back(ClassMD);
+
   // Force the definition of the EHType if necessary.
   if (flags & CLS_EXCEPTION)
     GetInterfaceEHType(ID->getClassInterface(), true);
@@ -4475,8 +4502,7 @@
 ///   const struct _prop_list_t * const properties;
 /// }
 ///
-void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) 
-{
+void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
   const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
   const char *Prefix = "\01l_OBJC_$_CATEGORY_";
   std::string ExtCatName(Prefix + Interface->getNameAsString()+ 
@@ -4553,6 +4579,10 @@
   GCATV->setSection("__DATA, __objc_const");
   UsedGlobals.push_back(GCATV);
   DefinedCategories.push_back(GCATV);
+
+  // Determine if this category is also "non-lazy".
+  if (ImplementationIsNonLazy(OCD))
+    DefinedNonLazyCategories.push_back(GCATV);
 }
 
 /// GetMethodConstant - Return a struct objc_method constant for the

Added: cfe/trunk/test/CodeGenObjC/non-lazy-classes.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/non-lazy-classes.m?rev=71904&view=auto

==============================================================================
--- cfe/trunk/test/CodeGenObjC/non-lazy-classes.m (added)
+++ cfe/trunk/test/CodeGenObjC/non-lazy-classes.m Fri May 15 17:33:15 2009
@@ -0,0 +1,30 @@
+// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s &&
+// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s &&
+// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CLASS_$" = internal global \[1 x .*\] .*@"OBJC_CLASS_$_A".*, section "__DATA, __objc_nlclslist, regular, no_dead_strip", align 8' %t &&
+// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CATEGORY_$" = internal global \[1 x .*\] .*@".01l_OBJC_$_CATEGORY_A_$_Cat".*, section "__DATA, __objc_nlcatlist, regular, no_dead_strip", align 8' %t &&
+// RUN: true
+
+ at interface A @end
+ at implementation A
++(void) load {
+}
+ at end
+
+ at interface A (Cat) @end
+ at implementation A (Cat)
++(void) load {
+}
+ at end
+
+ at interface B @end
+ at implementation B
+-(void) load {
+}
+ at end
+
+ at interface B (Cat) @end
+ at implementation B (Cat)
+-(void) load {
+}
+ at end
+





More information about the cfe-commits mailing list