From: Rafael Espindola Date: Wed, 26 Feb 2014 22:25:45 +0000 (+0000) Subject: Refactor linkage computation in CGObjCMac.cpp. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=98cafc64641be338090ca73ad69ba59702dcbc50;p=clang Refactor linkage computation in CGObjCMac.cpp. Before this patch the globals were created with the wrong linkage and patched afterwards. From the comments it looks like something would complain about having an internal GV with no initializer. At least in clang the verifier will only run way after we set the initializer, so that is not a problem. This patch should be a nop. It just figures out the linkage earlier and converts the old calls to setLinkage to asserts. The only case where that is not possible is when we first see a weak import that is then implemented. In that case we have to change the linkage, but that is the only setLinkage left. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202305 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 9504d7dd11..ec4a2f1409 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -573,8 +573,9 @@ public: QualType T) { return NULLPtr; } - - virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) { + + llvm::GlobalVariable *GetClassGlobal(const std::string &Name, + bool Weak = false) LLVM_OVERRIDE { return 0; } }; diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 99bd35f0fb..c91060d9c6 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1272,7 +1272,8 @@ public: /// GetClassGlobal - Return the global variable for the Objective-C /// class of the given name. - virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) { + llvm::GlobalVariable *GetClassGlobal(const std::string &Name, + bool Weak = false) LLVM_OVERRIDE { llvm_unreachable("CGObjCMac::GetClassGlobal"); } }; @@ -1321,7 +1322,8 @@ private: llvm::Constant *IsAGV, llvm::Constant *SuperClassGV, llvm::Constant *ClassRoGV, - bool HiddenVisibility); + bool HiddenVisibility, + bool Weak = false); llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); @@ -1372,15 +1374,16 @@ private: /// GetClassGlobal - Return the global variable for the Objective-C /// class of the given name. - llvm::GlobalVariable *GetClassGlobal(const std::string &Name); - + llvm::GlobalVariable *GetClassGlobal(const std::string &Name, + bool Weak = false) LLVM_OVERRIDE; + /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, /// for the given class reference. llvm::Value *EmitClassRef(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID); llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II); + IdentifierInfo *II, bool Weak); llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF); @@ -2649,7 +2652,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { if (Entry) { // Already created, fix the linkage and update the initializer. - Entry->setLinkage(llvm::GlobalValue::InternalLinkage); + assert(Entry->getLinkage() == llvm::GlobalValue::InternalLinkage); Entry->setInitializer(Init); } else { Entry = @@ -2677,7 +2680,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { // contents for protocols which were referenced but never defined. Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, - llvm::GlobalValue::ExternalLinkage, + llvm::GlobalValue::InternalLinkage, 0, "\01L_OBJC_PROTOCOL_" + PD->getName()); Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); @@ -3135,11 +3138,11 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { Name += ClassName; const char *Section = "__OBJC,__class,regular,no_dead_strip"; // Check for a forward reference. - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); + llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); if (GV) { assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && "Forward metaclass reference has incorrect type."); - GV->setLinkage(llvm::GlobalValue::InternalLinkage); + assert(GV->getLinkage() == llvm::GlobalValue::InternalLinkage); GV->setInitializer(Init); GV->setSection(Section); GV->setAlignment(4); @@ -3203,11 +3206,11 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, Name += ID->getName(); // Check for a forward reference. - llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); + llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); if (GV) { assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && "Forward metaclass reference has incorrect type."); - GV->setLinkage(llvm::GlobalValue::InternalLinkage); + assert(GV->getLinkage() == llvm::GlobalValue::InternalLinkage); GV->setInitializer(Init); } else { GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, @@ -3241,7 +3244,7 @@ llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { // Generate as an external reference to keep a consistent // module. This will be patched up when we emit the metaclass. return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, - llvm::GlobalValue::ExternalLinkage, + llvm::GlobalValue::InternalLinkage, 0, Name); } @@ -3257,7 +3260,7 @@ llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) { return GV; } else { return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, - llvm::GlobalValue::ExternalLinkage, + llvm::GlobalValue::InternalLinkage, 0, Name); } @@ -4995,7 +4998,7 @@ void CGObjCMac::FinishModule() { Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); Values[3] = Values[4] = llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); - I->second->setLinkage(llvm::GlobalValue::InternalLinkage); + assert(I->second->getLinkage() == llvm::GlobalValue::InternalLinkage); I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, Values)); CGM.AddUsedGlobal(I->second); @@ -5536,21 +5539,7 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() { AddModuleClassList(DefinedClasses, "\01L_OBJC_LABEL_CLASS_$", "__DATA, __objc_classlist, regular, no_dead_strip"); - - for (unsigned i = 0, e = DefinedClasses.size(); i < e; i++) { - llvm::GlobalValue *IMPLGV = DefinedClasses[i]; - if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) - continue; - IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); - } - - for (unsigned i = 0, e = DefinedMetaClasses.size(); i < e; i++) { - llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i]; - if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) - continue; - IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); - } - + AddModuleClassList(DefinedNonLazyClasses, "\01L_OBJC_LABEL_NONLAZY_CLASS_$", "__DATA, __objc_nlclslist, regular, no_dead_strip"); @@ -5742,12 +5731,9 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( /// struct class_ro_t *ro; /// } /// -llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( - std::string &ClassName, - llvm::Constant *IsAGV, - llvm::Constant *SuperClassGV, - llvm::Constant *ClassRoGV, - bool HiddenVisibility) { +llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassMetaData( + std::string &ClassName, llvm::Constant *IsAGV, llvm::Constant *SuperClassGV, + llvm::Constant *ClassRoGV, bool HiddenVisibility, bool Weak) { llvm::Constant *Values[] = { IsAGV, SuperClassGV, @@ -5762,7 +5748,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( llvm::PointerType::getUnqual(ObjCTypes.ImpnfABITy)); llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy, Values); - llvm::GlobalVariable *GV = GetClassGlobal(ClassName); + llvm::GlobalVariable *GV = GetClassGlobal(ClassName, Weak); GV->setInitializer(Init); GV->setSection("__DATA, __objc_data"); GV->setAlignment( @@ -5849,30 +5835,35 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { // class is root flags |= NonFragileABI_Class_Root; SuperClassGV = GetClassGlobal(ObjCClassName + ClassName); - IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName); + IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName, + ID->getClassInterface()->isWeakImported()); + + // We are implementing a weak imported interface. Give it external + // linkage. + if (!ID->isWeakImported() && ID->getClassInterface()->isWeakImported()) + IsAGV->setLinkage(llvm::GlobalVariable::ExternalLinkage); } else { // Has a root. Current class is not a root. const ObjCInterfaceDecl *Root = ID->getClassInterface(); while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) Root = Super; - IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString()); - if (Root->isWeakImported()) - IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); + IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString(), + Root->isWeakImported()); // work on super class metadata symbol. std::string SuperClassName = ObjCMetaClassName + ID->getClassInterface()->getSuperClass()->getNameAsString(); - SuperClassGV = GetClassGlobal(SuperClassName); - if (ID->getClassInterface()->getSuperClass()->isWeakImported()) - SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); + SuperClassGV = GetClassGlobal( + SuperClassName, + ID->getClassInterface()->getSuperClass()->isWeakImported()); } llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags, InstanceStart, InstanceSize,ID); std::string TClassName = ObjCMetaClassName + ClassName; - llvm::GlobalVariable *MetaTClass = - BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV, - classIsHidden); + llvm::GlobalVariable *MetaTClass = BuildClassMetaData( + TClassName, IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden, + ID->isWeakImported()); DefinedMetaClasses.push_back(MetaTClass); // Metadata for the class @@ -5903,9 +5894,9 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { // Has a root. Current class is not a root. std::string RootClassName = ID->getClassInterface()->getSuperClass()->getNameAsString(); - SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName); - if (ID->getClassInterface()->getSuperClass()->isWeakImported()) - SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); + SuperClassGV = GetClassGlobal( + ObjCClassName + RootClassName, + ID->getClassInterface()->getSuperClass()->isWeakImported()); } GetClassSizeInfo(ID, InstanceStart, InstanceSize); CLASS_RO_GV = BuildClassRoTInitializer(flags, @@ -5987,10 +5978,9 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { llvm::Constant *Values[6]; Values[0] = GetClassName(OCD->getIdentifier()); // meta-class entry symbol - llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName); - if (Interface->isWeakImported()) - ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); - + llvm::GlobalVariable *ClassGV = + GetClassGlobal(ExtClassName, Interface->isWeakImported()); + Values[1] = ClassGV; std::vector Methods; std::string MethodListName(Prefix); @@ -6359,7 +6349,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( if (Entry) { // Already created, fix the linkage and update the initializer. - Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage); + assert(Entry->getLinkage() == llvm::GlobalValue::WeakAnyLinkage); Entry->setInitializer(Init); } else { Entry = @@ -6651,25 +6641,29 @@ CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, } llvm::GlobalVariable * -CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) { +CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name, bool Weak) { + llvm::GlobalValue::LinkageTypes L = + Weak ? llvm::GlobalValue::ExternalWeakLinkage + : llvm::GlobalValue::ExternalLinkage; + llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); - if (!GV) { + if (!GV) GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy, - false, llvm::GlobalValue::ExternalLinkage, - 0, Name); - } + false, L, 0, Name); + assert(GV->getLinkage() == L); return GV; } llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II) { + IdentifierInfo *II, + bool Weak) { llvm::GlobalVariable *&Entry = ClassReferences[II]; if (!Entry) { std::string ClassName(getClassSymbolPrefix() + II->getName().str()); - llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); + llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, Weak); Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, llvm::GlobalValue::InternalLinkage, @@ -6687,13 +6681,13 @@ llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID) { - return EmitClassRefFromId(CGF, ID->getIdentifier()); + return EmitClassRefFromId(CGF, ID->getIdentifier(), ID->isWeakImported()); } llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef( CodeGenFunction &CGF) { IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool"); - return EmitClassRefFromId(CGF, II); + return EmitClassRefFromId(CGF, II, false); } llvm::Value * @@ -6751,8 +6745,8 @@ llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID) { if (ID->isWeakImported()) { std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); - llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); - ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); + llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, true); + assert(ClassGV->getLinkage() == llvm::GlobalValue::ExternalWeakLinkage); } return EmitClassRef(CGF, ID); @@ -7053,27 +7047,29 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values); + llvm::GlobalValue::LinkageTypes L = ForDefinition + ? llvm::GlobalValue::ExternalLinkage + : llvm::GlobalValue::WeakAnyLinkage; if (Entry) { Entry->setInitializer(Init); } else { Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, - llvm::GlobalValue::WeakAnyLinkage, + L, Init, ("OBJC_EHTYPE_$_" + ID->getIdentifier()->getName())); } + assert(Entry->getLinkage() == L); if (ID->getVisibility() == HiddenVisibility) Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment( ObjCTypes.EHTypeTy)); - if (ForDefinition) { + if (ForDefinition) Entry->setSection("__DATA,__objc_const"); - Entry->setLinkage(llvm::GlobalValue::ExternalLinkage); - } else { + else Entry->setSection("__DATA,__datacoal_nt,coalesced"); - } return Entry; } diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 7f030f2341..2a8ae90265 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -268,7 +268,8 @@ public: const CodeGen::CGBlockInfo &blockInfo) = 0; virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM, QualType T) = 0; - virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) = 0; + virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name, + bool Weak = false) = 0; struct MessageSendInfo { const CGFunctionInfo &CallInfo;