From 74d4b127d9f924ad354f47012e0d0e42ab1ee32b Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 15 May 2009 22:33:15 +0000 Subject: [PATCH] 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). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71904 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjCMac.cpp | 50 +++++++++++++++++++++++------ test/CodeGenObjC/non-lazy-classes.m | 30 +++++++++++++++++ 2 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 test/CodeGenObjC/non-lazy-classes.m diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 38a9f2f8eb..25aad64ea7 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -810,10 +810,16 @@ protected: /// DefinedClasses - List of defined classes. std::vector DefinedClasses; + + /// DefinedNonLazyClasses - List of defined "non-lazy" classes. + std::vector DefinedNonLazyClasses; /// DefinedCategories - List of defined categories. std::vector DefinedCategories; + /// DefinedNonLazyCategories - List of defined "non-lazy" categories. + std::vector DefinedNonLazyCategories; + /// UsedGlobals - List of globals to pack into the llvm.used metadata /// to prevent them from being clobbered. std::vector UsedGlobals; @@ -1259,16 +1265,20 @@ private: 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 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() { // 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 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( 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(*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 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { 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 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder, /// 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 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) 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 diff --git a/test/CodeGenObjC/non-lazy-classes.m b/test/CodeGenObjC/non-lazy-classes.m new file mode 100644 index 0000000000..1734f5ae3f --- /dev/null +++ b/test/CodeGenObjC/non-lazy-classes.m @@ -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 + +@interface A @end +@implementation A ++(void) load { +} +@end + +@interface A (Cat) @end +@implementation A (Cat) ++(void) load { +} +@end + +@interface B @end +@implementation B +-(void) load { +} +@end + +@interface B (Cat) @end +@implementation B (Cat) +-(void) load { +} +@end + -- 2.40.0