diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGDeclCXX.cpp | 33 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 3 |
2 files changed, 34 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 6a03e9afe4d..94cfe211601 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -257,6 +257,32 @@ CreateGlobalInitOrDestructFunction(CodeGenModule &CGM, return Fn; } +/// Create a global pointer to a function that will initialize a global +/// variable. The user has requested that this pointer be emitted in a specific +/// section. +void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D, + llvm::GlobalVariable *GV, + llvm::Function *InitFunc, + InitSegAttr *ISA) { + llvm::GlobalVariable *PtrArray = new llvm::GlobalVariable( + TheModule, InitFunc->getType(), /*isConstant=*/true, + llvm::GlobalValue::PrivateLinkage, InitFunc, "__cxx_init_fn_ptr"); + PtrArray->setSection(ISA->getSection()); + addUsedGlobal(PtrArray); + + // If the GV is already in a comdat group, then we have to join it. + llvm::Comdat *C = GV->getComdat(); + + // LinkOnce and Weak linkage are lowered down to a single-member comdat group. + // Make an explicit group so we can join it. + if (!C && (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())) { + C = TheModule.getOrInsertComdat(GV->getName()); + GV->setComdat(C); + } + if (C) + PtrArray->setComdat(C); +} + void CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, llvm::GlobalVariable *Addr, @@ -272,9 +298,9 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, llvm::Function *Fn = CreateGlobalInitOrDestructFunction(*this, FTy, FnName.str()); + auto *ISA = D->getAttr<InitSegAttr>(); CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr, PerformInit); - if (D->getTLSKind()) { // FIXME: Should we support init_priority for thread_local? // FIXME: Ideally, initialization of instantiated thread_local static data @@ -283,7 +309,10 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, // FIXME: We only need to register one __cxa_thread_atexit function for the // entire TU. CXXThreadLocalInits.push_back(Fn); - } else if (const InitPriorityAttr *IPA = D->getAttr<InitPriorityAttr>()) { + } else if (PerformInit && ISA) { + EmitPointerToInitFunc(D, Addr, Fn, ISA); + DelayedCXXInitPosition.erase(D); + } else if (auto *IPA = D->getAttr<InitPriorityAttr>()) { OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size()); PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); DelayedCXXInitPosition.erase(D); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index c65598e96df..44597bfaa91 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1103,6 +1103,9 @@ private: llvm::GlobalVariable *Addr, bool PerformInit); + void EmitPointerToInitFunc(const VarDecl *VD, llvm::GlobalVariable *Addr, + llvm::Function *InitFunc, InitSegAttr *ISA); + // FIXME: Hardcoding priority here is gross. void AddGlobalCtor(llvm::Function *Ctor, int Priority = 65535, llvm::Constant *AssociatedData = 0); |