diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-05-15 22:33:15 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-05-15 22:33:15 +0000 |
commit | 74d4b127d9f924ad354f47012e0d0e42ab1ee32b (patch) | |
tree | bc033960026474a90edf6408664f962e8f0275fb /lib/CodeGen/CGObjCMac.cpp | |
parent | 861ce3178c70cfb0fa50baf685e1ad363538eaa9 (diff) |
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
Diffstat (limited to 'lib/CodeGen/CGObjCMac.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 50 |
1 files changed, 40 insertions, 10 deletions
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<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 @@ 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<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 @@ 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 |