1bc49cfedSAnders Carlsson //===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
2bc49cfedSAnders Carlsson //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bc49cfedSAnders Carlsson //
7bc49cfedSAnders Carlsson //===----------------------------------------------------------------------===//
8bc49cfedSAnders Carlsson //
9bc49cfedSAnders Carlsson // This contains code dealing with code generation of C++ declarations
10bc49cfedSAnders Carlsson //
11bc49cfedSAnders Carlsson //===----------------------------------------------------------------------===//
12bc49cfedSAnders Carlsson 
135d865c32SJohn McCall #include "CGCXXABI.h"
143a02247dSChandler Carruth #include "CGObjCRuntime.h"
159772000aSAlexey Bataev #include "CGOpenMPRuntime.h"
169803178aSReid Kleckner #include "CodeGenFunction.h"
17960ff081SAnastasia Stulova #include "TargetInfo.h"
189803178aSReid Kleckner #include "clang/AST/Attr.h"
197314aea5SDaniel Kiss #include "clang/Basic/LangOptions.h"
20abed7492SAnton Korobeynikov #include "llvm/ADT/StringExtras.h"
21ffd5551bSChandler Carruth #include "llvm/IR/Intrinsics.h"
22ae8d62c9SRichard Smith #include "llvm/IR/MDBuilder.h"
23bdc96983SNico Weber #include "llvm/Support/Path.h"
2451150ab1SDouglas Gregor 
25bc49cfedSAnders Carlsson using namespace clang;
26bc49cfedSAnders Carlsson using namespace CodeGen;
27bc49cfedSAnders Carlsson 
EmitDeclInit(CodeGenFunction & CGF,const VarDecl & D,ConstantAddress DeclPtr)28364051c6SAnders Carlsson static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
297f416cc4SJohn McCall                          ConstantAddress DeclPtr) {
309d2872dbSMikael Nilsson   assert(
319d2872dbSMikael Nilsson       (D.hasGlobalStorage() ||
329d2872dbSMikael Nilsson        (D.hasLocalStorage() && CGF.getContext().getLangOpts().OpenCLCPlusPlus)) &&
339d2872dbSMikael Nilsson       "VarDecl must have global or local (in the case of OpenCL) storage!");
34364051c6SAnders Carlsson   assert(!D.getType()->isReferenceType() &&
35364051c6SAnders Carlsson          "Should not call EmitDeclInit on a reference!");
36364051c6SAnders Carlsson 
371553b190SJohn McCall   QualType type = D.getType();
387f416cc4SJohn McCall   LValue lv = CGF.MakeAddrLValue(DeclPtr, type);
39bc49cfedSAnders Carlsson 
401553b190SJohn McCall   const Expr *Init = D.getInit();
4147fb9508SJohn McCall   switch (CGF.getEvaluationKind(type)) {
4247fb9508SJohn McCall   case TEK_Scalar: {
43d1339796SFariborz Jahanian     CodeGenModule &CGM = CGF.CGM;
441553b190SJohn McCall     if (lv.isObjCStrong())
4531168b07SJohn McCall       CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init),
46fd3834f7SRichard Smith                                                 DeclPtr, D.getTLSKind());
471553b190SJohn McCall     else if (lv.isObjCWeak())
4831168b07SJohn McCall       CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init),
4931168b07SJohn McCall                                               DeclPtr);
50d1339796SFariborz Jahanian     else
511553b190SJohn McCall       CGF.EmitScalarInit(Init, &D, lv, false);
5247fb9508SJohn McCall     return;
5347fb9508SJohn McCall   }
5447fb9508SJohn McCall   case TEK_Complex:
5547fb9508SJohn McCall     CGF.EmitComplexExprIntoLValue(Init, lv, /*isInit*/ true);
5647fb9508SJohn McCall     return;
5747fb9508SJohn McCall   case TEK_Aggregate:
58f139ae3dSAkira Hatanaka     CGF.EmitAggExpr(Init,
59f139ae3dSAkira Hatanaka                     AggValueSlot::forLValue(lv, CGF, AggValueSlot::IsDestructed,
60a5efa738SJohn McCall                                             AggValueSlot::DoesNotNeedGCBarriers,
61e78fac51SRichard Smith                                             AggValueSlot::IsNotAliased,
62e78fac51SRichard Smith                                             AggValueSlot::DoesNotOverlap));
6347fb9508SJohn McCall     return;
64370eadf3SDouglas Gregor   }
6547fb9508SJohn McCall   llvm_unreachable("bad evaluation kind");
66370eadf3SDouglas Gregor }
67370eadf3SDouglas Gregor 
6868ff0372SJohn McCall /// Emit code to cause the destruction of the given variable with
6968ff0372SJohn McCall /// static storage duration.
EmitDeclDestroy(CodeGenFunction & CGF,const VarDecl & D,ConstantAddress Addr)70370eadf3SDouglas Gregor static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
71825f9d3eSKristina Brooks                             ConstantAddress Addr) {
727349d90bSKristina Brooks   // Honor __attribute__((no_destroy)) and bail instead of attempting
737349d90bSKristina Brooks   // to emit a reference to a possibly nonexistent destructor, which
747349d90bSKristina Brooks   // in turn can cause a crash. This will result in a global constructor
757349d90bSKristina Brooks   // that isn't balanced out by a destructor call as intended by the
767349d90bSKristina Brooks   // attribute. This also checks for -fno-c++-static-destructors and
777349d90bSKristina Brooks   // bails even if the attribute is not present.
782b4fa534SRichard Smith   QualType::DestructionKind DtorKind = D.needsDestruction(CGF.getContext());
79370eadf3SDouglas Gregor 
8098de3d74SJohn McCall   // FIXME:  __attribute__((cleanup)) ?
81364051c6SAnders Carlsson 
821333b57fSKristina Brooks   switch (DtorKind) {
8398de3d74SJohn McCall   case QualType::DK_none:
84364051c6SAnders Carlsson     return;
85364051c6SAnders Carlsson 
8698de3d74SJohn McCall   case QualType::DK_cxx_destructor:
8798de3d74SJohn McCall     break;
8898de3d74SJohn McCall 
8998de3d74SJohn McCall   case QualType::DK_objc_strong_lifetime:
9098de3d74SJohn McCall   case QualType::DK_objc_weak_lifetime:
917275da0fSAkira Hatanaka   case QualType::DK_nontrivial_c_struct:
9298de3d74SJohn McCall     // We don't care about releasing objects during process teardown.
93dbf74baeSRichard Smith     assert(!D.getTLSKind() && "should have rejected this");
94364051c6SAnders Carlsson     return;
9598de3d74SJohn McCall   }
96364051c6SAnders Carlsson 
97f7321540SJames Y Knight   llvm::FunctionCallee Func;
981333b57fSKristina Brooks   llvm::Constant *Argument;
99364051c6SAnders Carlsson 
1002b4fa534SRichard Smith   CodeGenModule &CGM = CGF.CGM;
1012b4fa534SRichard Smith   QualType Type = D.getType();
1022b4fa534SRichard Smith 
10309b24923SDerek Schuff   // Special-case non-array C++ destructors, if they have the right signature.
10409b24923SDerek Schuff   // Under some ABIs, destructors return this instead of void, and cannot be
1051333b57fSKristina Brooks   // passed directly to __cxa_atexit if the target does not allow this
1061333b57fSKristina Brooks   // mismatch.
1071333b57fSKristina Brooks   const CXXRecordDecl *Record = Type->getAsCXXRecordDecl();
1088179be48SDerek Schuff   bool CanRegisterDestructor =
1098179be48SDerek Schuff       Record && (!CGM.getCXXABI().HasThisReturn(
1108179be48SDerek Schuff                      GlobalDecl(Record->getDestructor(), Dtor_Complete)) ||
1118179be48SDerek Schuff                  CGM.getCXXABI().canCallMismatchedFunctionType());
1122136eed8SDerek Schuff   // If __cxa_atexit is disabled via a flag, a different helper function is
1132136eed8SDerek Schuff   // generated elsewhere which uses atexit instead, and it takes the destructor
1142136eed8SDerek Schuff   // directly.
1152136eed8SDerek Schuff   bool UsingExternalHelper = !CGM.getCodeGenOpts().CXAAtExit;
11609b24923SDerek Schuff   if (Record && (CanRegisterDestructor || UsingExternalHelper)) {
117060fd220SDerek Schuff     assert(!Record->hasTrivialDestructor());
1181333b57fSKristina Brooks     CXXDestructorDecl *Dtor = Record->getDestructor();
119364051c6SAnders Carlsson 
120d1c5b28cSPeter Collingbourne     Func = CGM.getAddrAndTypeOfCXXStructor(GlobalDecl(Dtor, Dtor_Complete));
121960ff081SAnastasia Stulova     if (CGF.getContext().getLangOpts().OpenCL) {
122960ff081SAnastasia Stulova       auto DestAS =
123960ff081SAnastasia Stulova           CGM.getTargetCodeGenInfo().getAddrSpaceOfCxaAtexitPtrParam();
124960ff081SAnastasia Stulova       auto DestTy = CGF.getTypes().ConvertType(Type)->getPointerTo(
125960ff081SAnastasia Stulova           CGM.getContext().getTargetAddressSpace(DestAS));
126960ff081SAnastasia Stulova       auto SrcAS = D.getType().getQualifiers().getAddressSpace();
127960ff081SAnastasia Stulova       if (DestAS == SrcAS)
128960ff081SAnastasia Stulova         Argument = llvm::ConstantExpr::getBitCast(Addr.getPointer(), DestTy);
129960ff081SAnastasia Stulova       else
130960ff081SAnastasia Stulova         // FIXME: On addr space mismatch we are passing NULL. The generation
131960ff081SAnastasia Stulova         // of the global destructor function should be adjusted accordingly.
132960ff081SAnastasia Stulova         Argument = llvm::ConstantPointerNull::get(DestTy);
133960ff081SAnastasia Stulova     } else {
1341333b57fSKristina Brooks       Argument = llvm::ConstantExpr::getBitCast(
1351333b57fSKristina Brooks           Addr.getPointer(), CGF.getTypes().ConvertType(Type)->getPointerTo());
136960ff081SAnastasia Stulova     }
13798de3d74SJohn McCall   // Otherwise, the standard logic requires a helper function.
13898de3d74SJohn McCall   } else {
1392d1b55ebSNikita Popov     Addr = Addr.getElementBitCast(CGF.ConvertTypeForMem(Type));
1401333b57fSKristina Brooks     Func = CodeGenFunction(CGM)
1411333b57fSKristina Brooks            .generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind),
1421333b57fSKristina Brooks                                   CGF.needsEHCleanup(DtorKind), &D);
1431333b57fSKristina Brooks     Argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
14498de3d74SJohn McCall   }
14598de3d74SJohn McCall 
1461333b57fSKristina Brooks   CGM.getCXXABI().registerGlobalDtor(CGF, D, Func, Argument);
147bc49cfedSAnders Carlsson }
148bc49cfedSAnders Carlsson 
14908a51446SRichard Smith /// Emit code to cause the variable at the given address to be considered as
15008a51446SRichard Smith /// constant from this point onwards.
EmitDeclInvariant(CodeGenFunction & CGF,const VarDecl & D,llvm::Constant * Addr)15145062046SNick Lewycky static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D,
15245062046SNick Lewycky                               llvm::Constant *Addr) {
1533ad0636eSRichard Smith   return CGF.EmitInvariantStart(
1543ad0636eSRichard Smith       Addr, CGF.getContext().getTypeSizeInChars(D.getType()));
1553ad0636eSRichard Smith }
1563ad0636eSRichard Smith 
EmitInvariantStart(llvm::Constant * Addr,CharUnits Size)1573ad0636eSRichard Smith void CodeGenFunction::EmitInvariantStart(llvm::Constant *Addr, CharUnits Size) {
158b772151aSAnna Thomas   // Do not emit the intrinsic if we're not optimizing.
1593ad0636eSRichard Smith   if (!CGM.getCodeGenOpts().OptimizationLevel)
160132bea96SRichard Smith     return;
161132bea96SRichard Smith 
16208a51446SRichard Smith   // Grab the llvm.invariant.start intrinsic.
16308a51446SRichard Smith   llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
164142ea998SAnna Thomas   // Overloaded address space type.
1653ad0636eSRichard Smith   llvm::Type *ObjectPtr[1] = {Int8PtrTy};
1668799caeeSJames Y Knight   llvm::Function *InvariantStart = CGM.getIntrinsic(InvStartID, ObjectPtr);
16708a51446SRichard Smith 
16845062046SNick Lewycky   // Emit a call with the size in bytes of the object.
1693ad0636eSRichard Smith   uint64_t Width = Size.getQuantity();
1703ad0636eSRichard Smith   llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(Int64Ty, Width),
1713ad0636eSRichard Smith                            llvm::ConstantExpr::getBitCast(Addr, Int8PtrTy)};
1723ad0636eSRichard Smith   Builder.CreateCall(InvariantStart, Args);
17308a51446SRichard Smith }
17408a51446SRichard Smith 
EmitCXXGlobalVarDeclInit(const VarDecl & D,llvm::GlobalVariable * GV,bool PerformInit)175364051c6SAnders Carlsson void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
17655d7a12bSNikita Popov                                                llvm::GlobalVariable *GV,
1776331c408SRichard Smith                                                bool PerformInit) {
178364051c6SAnders Carlsson 
179364051c6SAnders Carlsson   const Expr *Init = D.getInit();
180364051c6SAnders Carlsson   QualType T = D.getType();
181364051c6SAnders Carlsson 
1824f7b9eb2SJingyue Wu   // The address space of a static local variable (DeclPtr) may be different
1834f7b9eb2SJingyue Wu   // from the address space of the "this" argument of the constructor. In that
1844f7b9eb2SJingyue Wu   // case, we need an addrspacecast before calling the constructor.
1854f7b9eb2SJingyue Wu   //
1864f7b9eb2SJingyue Wu   // struct StructWithCtor {
1874f7b9eb2SJingyue Wu   //   __device__ StructWithCtor() {...}
1884f7b9eb2SJingyue Wu   // };
1894f7b9eb2SJingyue Wu   // __device__ void foo() {
1904f7b9eb2SJingyue Wu   //   __shared__ StructWithCtor s;
1914f7b9eb2SJingyue Wu   //   ...
1924f7b9eb2SJingyue Wu   // }
1934f7b9eb2SJingyue Wu   //
1944f7b9eb2SJingyue Wu   // For example, in the above CUDA code, the static local variable s has a
1954f7b9eb2SJingyue Wu   // "shared" address space qualifier, but the constructor of StructWithCtor
1964f7b9eb2SJingyue Wu   // expects "this" in the "generic" address space.
1974f7b9eb2SJingyue Wu   unsigned ExpectedAddrSpace = getContext().getTargetAddressSpace(T);
19855d7a12bSNikita Popov   unsigned ActualAddrSpace = GV->getAddressSpace();
19955d7a12bSNikita Popov   llvm::Constant *DeclPtr = GV;
2004f7b9eb2SJingyue Wu   if (ActualAddrSpace != ExpectedAddrSpace) {
20155d7a12bSNikita Popov     llvm::PointerType *PTy = llvm::PointerType::getWithSamePointeeType(
20255d7a12bSNikita Popov         GV->getType(), ExpectedAddrSpace);
2034f7b9eb2SJingyue Wu     DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy);
2044f7b9eb2SJingyue Wu   }
2054f7b9eb2SJingyue Wu 
20655d7a12bSNikita Popov   ConstantAddress DeclAddr(
20755d7a12bSNikita Popov       DeclPtr, GV->getValueType(), getContext().getDeclAlign(&D));
2087f416cc4SJohn McCall 
209364051c6SAnders Carlsson   if (!T->isReferenceType()) {
210a8a9153aSAlexey Bataev     if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
211a8a9153aSAlexey Bataev         D.hasAttr<OMPThreadPrivateDeclAttr>()) {
2123eff5f46SAlexey Bataev       (void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition(
2137f416cc4SJohn McCall           &D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
2149772000aSAlexey Bataev           PerformInit, this);
215a8a9153aSAlexey Bataev     }
2166331c408SRichard Smith     if (PerformInit)
2177f416cc4SJohn McCall       EmitDeclInit(*this, D, DeclAddr);
21808a51446SRichard Smith     if (CGM.isTypeConstant(D.getType(), true))
21945062046SNick Lewycky       EmitDeclInvariant(*this, D, DeclPtr);
22008a51446SRichard Smith     else
2217f416cc4SJohn McCall       EmitDeclDestroy(*this, D, DeclAddr);
222364051c6SAnders Carlsson     return;
223364051c6SAnders Carlsson   }
2243f48c603SAnders Carlsson 
2256331c408SRichard Smith   assert(PerformInit && "cannot have constant initializer which needs "
2266331c408SRichard Smith          "destruction for reference");
227a1c9d4d9SRichard Smith   RValue RV = EmitReferenceBindingToExpr(Init);
2287f416cc4SJohn McCall   EmitStoreOfScalar(RV.getScalarVal(), DeclAddr, false, T);
229364051c6SAnders Carlsson }
230633c6f6fSAnders Carlsson 
23176cc43a2SJohn McCall /// Create a stub function, suitable for being passed to atexit,
23276cc43a2SJohn McCall /// which passes the given address to the given destructor function.
createAtExitStub(const VarDecl & VD,llvm::FunctionCallee dtor,llvm::Constant * addr)233f7321540SJames Y Knight llvm::Function *CodeGenFunction::createAtExitStub(const VarDecl &VD,
234f7321540SJames Y Knight                                                   llvm::FunctionCallee dtor,
23576cc43a2SJohn McCall                                                   llvm::Constant *addr) {
23676cc43a2SJohn McCall   // Get the destructor function type, void(*)(void).
23776cc43a2SJohn McCall   llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false);
238d8110b65SReid Kleckner   SmallString<256> FnName;
239d8110b65SReid Kleckner   {
240d8110b65SReid Kleckner     llvm::raw_svector_ostream Out(FnName);
241d8110b65SReid Kleckner     CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out);
242d8110b65SReid Kleckner   }
2437791f1a4SAkira Hatanaka 
2447791f1a4SAkira Hatanaka   const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
24522337bfeSXiangling Liao   llvm::Function *fn = CGM.CreateGlobalInitOrCleanUpFunction(
246105c565eSReid Kleckner       ty, FnName.str(), FI, VD.getLocation());
24776cc43a2SJohn McCall 
24876cc43a2SJohn McCall   CodeGenFunction CGF(CGM);
24976cc43a2SJohn McCall 
250105c565eSReid Kleckner   CGF.StartFunction(GlobalDecl(&VD, DynamicInitKind::AtExit),
25169f3378aSXiangling Liao                     CGM.getContext().VoidTy, fn, FI, FunctionArgList(),
25269f3378aSXiangling Liao                     VD.getLocation(), VD.getInit()->getExprLoc());
25366face6aSAlexandre Ganea   // Emit an artificial location for this function.
25466face6aSAlexandre Ganea   auto AL = ApplyDebugLocation::CreateArtificial(CGF);
25576cc43a2SJohn McCall 
25676cc43a2SJohn McCall   llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
25776cc43a2SJohn McCall 
25876cc43a2SJohn McCall   // Make sure the call and the callee agree on calling convention.
2598a410bceSErich Keane   if (auto *dtorFn = dyn_cast<llvm::Function>(
2608a410bceSErich Keane           dtor.getCallee()->stripPointerCastsAndAliases()))
26176cc43a2SJohn McCall     call->setCallingConv(dtorFn->getCallingConv());
26276cc43a2SJohn McCall 
26376cc43a2SJohn McCall   CGF.FinishFunction();
26476cc43a2SJohn McCall 
26576cc43a2SJohn McCall   return fn;
26676cc43a2SJohn McCall }
26776cc43a2SJohn McCall 
26873840f9fSJamie Schmeiser /// Create a stub function, suitable for being passed to __pt_atexit_np,
26973840f9fSJamie Schmeiser /// which passes the given address to the given destructor function.
createTLSAtExitStub(const VarDecl & D,llvm::FunctionCallee Dtor,llvm::Constant * Addr,llvm::FunctionCallee & AtExit)27073840f9fSJamie Schmeiser llvm::Function *CodeGenFunction::createTLSAtExitStub(
27173840f9fSJamie Schmeiser     const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr,
27273840f9fSJamie Schmeiser     llvm::FunctionCallee &AtExit) {
27373840f9fSJamie Schmeiser   SmallString<256> FnName;
27473840f9fSJamie Schmeiser   {
27573840f9fSJamie Schmeiser     llvm::raw_svector_ostream Out(FnName);
27673840f9fSJamie Schmeiser     CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&D, Out);
27773840f9fSJamie Schmeiser   }
27873840f9fSJamie Schmeiser 
27973840f9fSJamie Schmeiser   const CGFunctionInfo &FI = CGM.getTypes().arrangeLLVMFunctionInfo(
28073840f9fSJamie Schmeiser       getContext().IntTy, /*instanceMethod=*/false, /*chainCall=*/false,
28173840f9fSJamie Schmeiser       {getContext().IntTy}, FunctionType::ExtInfo(), {}, RequiredArgs::All);
28273840f9fSJamie Schmeiser 
28373840f9fSJamie Schmeiser   // Get the stub function type, int(*)(int,...).
28473840f9fSJamie Schmeiser   llvm::FunctionType *StubTy =
28573840f9fSJamie Schmeiser       llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy}, true);
28673840f9fSJamie Schmeiser 
28773840f9fSJamie Schmeiser   llvm::Function *DtorStub = CGM.CreateGlobalInitOrCleanUpFunction(
28873840f9fSJamie Schmeiser       StubTy, FnName.str(), FI, D.getLocation());
28973840f9fSJamie Schmeiser 
29073840f9fSJamie Schmeiser   CodeGenFunction CGF(CGM);
29173840f9fSJamie Schmeiser 
29273840f9fSJamie Schmeiser   FunctionArgList Args;
29373840f9fSJamie Schmeiser   ImplicitParamDecl IPD(CGM.getContext(), CGM.getContext().IntTy,
29473840f9fSJamie Schmeiser                         ImplicitParamDecl::Other);
29573840f9fSJamie Schmeiser   Args.push_back(&IPD);
29673840f9fSJamie Schmeiser   QualType ResTy = CGM.getContext().IntTy;
29773840f9fSJamie Schmeiser 
29873840f9fSJamie Schmeiser   CGF.StartFunction(GlobalDecl(&D, DynamicInitKind::AtExit), ResTy, DtorStub,
29973840f9fSJamie Schmeiser                     FI, Args, D.getLocation(), D.getInit()->getExprLoc());
30073840f9fSJamie Schmeiser 
30173840f9fSJamie Schmeiser   // Emit an artificial location for this function.
30273840f9fSJamie Schmeiser   auto AL = ApplyDebugLocation::CreateArtificial(CGF);
30373840f9fSJamie Schmeiser 
30473840f9fSJamie Schmeiser   llvm::CallInst *call = CGF.Builder.CreateCall(Dtor, Addr);
30573840f9fSJamie Schmeiser 
30673840f9fSJamie Schmeiser   // Make sure the call and the callee agree on calling convention.
30773840f9fSJamie Schmeiser   if (auto *DtorFn = dyn_cast<llvm::Function>(
30873840f9fSJamie Schmeiser           Dtor.getCallee()->stripPointerCastsAndAliases()))
30973840f9fSJamie Schmeiser     call->setCallingConv(DtorFn->getCallingConv());
31073840f9fSJamie Schmeiser 
31173840f9fSJamie Schmeiser   // Return 0 from function
31273840f9fSJamie Schmeiser   CGF.Builder.CreateStore(llvm::Constant::getNullValue(CGM.IntTy),
31373840f9fSJamie Schmeiser                           CGF.ReturnValue);
31473840f9fSJamie Schmeiser 
31573840f9fSJamie Schmeiser   CGF.FinishFunction();
31673840f9fSJamie Schmeiser 
31773840f9fSJamie Schmeiser   return DtorStub;
31873840f9fSJamie Schmeiser }
31973840f9fSJamie Schmeiser 
320c84ed6a3SJohn McCall /// Register a global destructor using the C atexit runtime function.
registerGlobalDtorWithAtExit(const VarDecl & VD,llvm::FunctionCallee dtor,llvm::Constant * addr)321ebe87e1cSDavid Blaikie void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,
322f7321540SJames Y Knight                                                    llvm::FunctionCallee dtor,
32376cc43a2SJohn McCall                                                    llvm::Constant *addr) {
32476cc43a2SJohn McCall   // Create a function which calls the destructor.
325b3341ea4SDavid Majnemer   llvm::Constant *dtorStub = createAtExitStub(VD, dtor, addr);
326617e2615SAkira Hatanaka   registerGlobalDtorWithAtExit(dtorStub);
327617e2615SAkira Hatanaka }
32876cc43a2SJohn McCall 
registerGlobalDtorWithAtExit(llvm::Constant * dtorStub)329617e2615SAkira Hatanaka void CodeGenFunction::registerGlobalDtorWithAtExit(llvm::Constant *dtorStub) {
33076cc43a2SJohn McCall   // extern "C" int atexit(void (*f)(void));
33117497ec5SXiangling Liao   assert(dtorStub->getType() ==
33217497ec5SXiangling Liao              llvm::PointerType::get(
33317497ec5SXiangling Liao                  llvm::FunctionType::get(CGM.VoidTy, false),
33417497ec5SXiangling Liao                  dtorStub->getType()->getPointerAddressSpace()) &&
33522337bfeSXiangling Liao          "Argument to atexit has a wrong type.");
33622337bfeSXiangling Liao 
33776cc43a2SJohn McCall   llvm::FunctionType *atexitTy =
338c84ed6a3SJohn McCall       llvm::FunctionType::get(IntTy, dtorStub->getType(), false);
33976cc43a2SJohn McCall 
3409871db06SJames Y Knight   llvm::FunctionCallee atexit =
341de86482cSReid Kleckner       CGM.CreateRuntimeFunction(atexitTy, "atexit", llvm::AttributeList(),
3426cb07449SSaleem Abdulrasool                                 /*Local=*/true);
3439871db06SJames Y Knight   if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit.getCallee()))
34476cc43a2SJohn McCall     atexitFn->setDoesNotThrow();
34576cc43a2SJohn McCall 
346882987f3SJohn McCall   EmitNounwindRuntimeCall(atexit, dtorStub);
347633c6f6fSAnders Carlsson }
348633c6f6fSAnders Carlsson 
34922337bfeSXiangling Liao llvm::Value *
unregisterGlobalDtorWithUnAtExit(llvm::Constant * dtorStub)35017497ec5SXiangling Liao CodeGenFunction::unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub) {
35122337bfeSXiangling Liao   // The unatexit subroutine unregisters __dtor functions that were previously
35222337bfeSXiangling Liao   // registered by the atexit subroutine. If the referenced function is found,
35322337bfeSXiangling Liao   // it is removed from the list of functions that are called at normal program
35422337bfeSXiangling Liao   // termination and the unatexit returns a value of 0, otherwise a non-zero
35522337bfeSXiangling Liao   // value is returned.
35622337bfeSXiangling Liao   //
35722337bfeSXiangling Liao   // extern "C" int unatexit(void (*f)(void));
35817497ec5SXiangling Liao   assert(dtorStub->getType() ==
35917497ec5SXiangling Liao              llvm::PointerType::get(
36017497ec5SXiangling Liao                  llvm::FunctionType::get(CGM.VoidTy, false),
36117497ec5SXiangling Liao                  dtorStub->getType()->getPointerAddressSpace()) &&
36222337bfeSXiangling Liao          "Argument to unatexit has a wrong type.");
36322337bfeSXiangling Liao 
36422337bfeSXiangling Liao   llvm::FunctionType *unatexitTy =
36522337bfeSXiangling Liao       llvm::FunctionType::get(IntTy, {dtorStub->getType()}, /*isVarArg=*/false);
36622337bfeSXiangling Liao 
36722337bfeSXiangling Liao   llvm::FunctionCallee unatexit =
36822337bfeSXiangling Liao       CGM.CreateRuntimeFunction(unatexitTy, "unatexit", llvm::AttributeList());
36922337bfeSXiangling Liao 
37022337bfeSXiangling Liao   cast<llvm::Function>(unatexit.getCallee())->setDoesNotThrow();
37122337bfeSXiangling Liao 
37222337bfeSXiangling Liao   return EmitNounwindRuntimeCall(unatexit, dtorStub);
37322337bfeSXiangling Liao }
37422337bfeSXiangling Liao 
EmitCXXGuardedInit(const VarDecl & D,llvm::GlobalVariable * DeclPtr,bool PerformInit)375cdf7ef54SJohn McCall void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
37684537952SChandler Carruth                                          llvm::GlobalVariable *DeclPtr,
3776331c408SRichard Smith                                          bool PerformInit) {
3787ef5cb30SJohn McCall   // If we've been asked to forbid guard variables, emit an error now.
3797ef5cb30SJohn McCall   // This diagnostic is hard-coded for Darwin's use case;  we can find
3807ef5cb30SJohn McCall   // better phrasing if someone else needs it.
3817ef5cb30SJohn McCall   if (CGM.getCodeGenOpts().ForbidGuardVariables)
3827ef5cb30SJohn McCall     CGM.Error(D.getLocation(),
3837ef5cb30SJohn McCall               "this initialization requires a guard variable, which "
3847ef5cb30SJohn McCall               "the kernel does not support");
3857ef5cb30SJohn McCall 
38684537952SChandler Carruth   CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit);
38768ff0372SJohn McCall }
38868ff0372SJohn McCall 
EmitCXXGuardedInitBranch(llvm::Value * NeedsInit,llvm::BasicBlock * InitBlock,llvm::BasicBlock * NoInitBlock,GuardKind Kind,const VarDecl * D)389ae8d62c9SRichard Smith void CodeGenFunction::EmitCXXGuardedInitBranch(llvm::Value *NeedsInit,
390ae8d62c9SRichard Smith                                                llvm::BasicBlock *InitBlock,
391ae8d62c9SRichard Smith                                                llvm::BasicBlock *NoInitBlock,
392ae8d62c9SRichard Smith                                                GuardKind Kind,
393ae8d62c9SRichard Smith                                                const VarDecl *D) {
394ae8d62c9SRichard Smith   assert((Kind == GuardKind::TlsGuard || D) && "no guarded variable");
395ae8d62c9SRichard Smith 
396ae8d62c9SRichard Smith   // A guess at how many times we will enter the initialization of a
397ae8d62c9SRichard Smith   // variable, depending on the kind of variable.
398ae8d62c9SRichard Smith   static const uint64_t InitsPerTLSVar = 1024;
399ae8d62c9SRichard Smith   static const uint64_t InitsPerLocalVar = 1024 * 1024;
400ae8d62c9SRichard Smith 
401ae8d62c9SRichard Smith   llvm::MDNode *Weights;
402ae8d62c9SRichard Smith   if (Kind == GuardKind::VariableGuard && !D->isLocalVarDecl()) {
403ae8d62c9SRichard Smith     // For non-local variables, don't apply any weighting for now. Due to our
404ae8d62c9SRichard Smith     // use of COMDATs, we expect there to be at most one initialization of the
405ae8d62c9SRichard Smith     // variable per DSO, but we have no way to know how many DSOs will try to
406ae8d62c9SRichard Smith     // initialize the variable.
407ae8d62c9SRichard Smith     Weights = nullptr;
408ae8d62c9SRichard Smith   } else {
409ae8d62c9SRichard Smith     uint64_t NumInits;
410ae8d62c9SRichard Smith     // FIXME: For the TLS case, collect and use profiling information to
411ae8d62c9SRichard Smith     // determine a more accurate brach weight.
412ae8d62c9SRichard Smith     if (Kind == GuardKind::TlsGuard || D->getTLSKind())
413ae8d62c9SRichard Smith       NumInits = InitsPerTLSVar;
414ae8d62c9SRichard Smith     else
415ae8d62c9SRichard Smith       NumInits = InitsPerLocalVar;
416ae8d62c9SRichard Smith 
417ae8d62c9SRichard Smith     // The probability of us entering the initializer is
418ae8d62c9SRichard Smith     //   1 / (total number of times we attempt to initialize the variable).
419ae8d62c9SRichard Smith     llvm::MDBuilder MDHelper(CGM.getLLVMContext());
420ae8d62c9SRichard Smith     Weights = MDHelper.createBranchWeights(1, NumInits - 1);
421ae8d62c9SRichard Smith   }
422ae8d62c9SRichard Smith 
423ae8d62c9SRichard Smith   Builder.CreateCondBr(NeedsInit, InitBlock, NoInitBlock, Weights);
424ae8d62c9SRichard Smith }
425ae8d62c9SRichard Smith 
CreateGlobalInitOrCleanUpFunction(llvm::FunctionType * FTy,const Twine & Name,const CGFunctionInfo & FI,SourceLocation Loc,bool TLS,llvm::GlobalVariable::LinkageTypes Linkage)42622337bfeSXiangling Liao llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
4277791f1a4SAkira Hatanaka     llvm::FunctionType *FTy, const Twine &Name, const CGFunctionInfo &FI,
4283c6d32ecSJoseph Huber     SourceLocation Loc, bool TLS, llvm::GlobalVariable::LinkageTypes Linkage) {
4293c6d32ecSJoseph Huber   llvm::Function *Fn = llvm::Function::Create(FTy, Linkage, Name, &getModule());
43022337bfeSXiangling Liao 
431b3341ea4SDavid Majnemer   if (!getLangOpts().AppleKext && !TLS) {
432851318a9SAnders Carlsson     // Set the section if needed.
433b3341ea4SDavid Majnemer     if (const char *Section = getTarget().getStaticInitSectionSpecifier())
434851318a9SAnders Carlsson       Fn->setSection(Section);
43509948f1aSFariborz Jahanian   }
436851318a9SAnders Carlsson 
4373c6d32ecSJoseph Huber   if (Linkage == llvm::GlobalVariable::InternalLinkage)
43851ec5a9cSRafael Espindola     SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
439787dc438SReid Kleckner 
440b3341ea4SDavid Majnemer   Fn->setCallingConv(getRuntimeCC());
441882987f3SJohn McCall 
442b3341ea4SDavid Majnemer   if (!getLangOpts().Exceptions)
443466e2210SJohn McCall     Fn->setDoesNotThrow();
444466e2210SJohn McCall 
4452eccdab3SVlad Tsyrklevich   if (getLangOpts().Sanitize.has(SanitizerKind::Address) &&
446e64fcdf8SMelanie Blower       !isInNoSanitizeList(SanitizerKind::Address, Fn, Loc))
4474c0fc993SKostya Serebryany     Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
4482eccdab3SVlad Tsyrklevich 
4492eccdab3SVlad Tsyrklevich   if (getLangOpts().Sanitize.has(SanitizerKind::KernelAddress) &&
450e64fcdf8SMelanie Blower       !isInNoSanitizeList(SanitizerKind::KernelAddress, Fn, Loc))
4512eccdab3SVlad Tsyrklevich     Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
4522eccdab3SVlad Tsyrklevich 
45312817e59SEvgeniy Stepanov   if (getLangOpts().Sanitize.has(SanitizerKind::HWAddress) &&
454e64fcdf8SMelanie Blower       !isInNoSanitizeList(SanitizerKind::HWAddress, Fn, Loc))
45512817e59SEvgeniy Stepanov     Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
45612817e59SEvgeniy Stepanov 
4571ba9d9c6SAndrey Konovalov   if (getLangOpts().Sanitize.has(SanitizerKind::KernelHWAddress) &&
458e64fcdf8SMelanie Blower       !isInNoSanitizeList(SanitizerKind::KernelHWAddress, Fn, Loc))
4591ba9d9c6SAndrey Konovalov     Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
4601ba9d9c6SAndrey Konovalov 
461fa34951fSMitch Phillips   if (getLangOpts().Sanitize.has(SanitizerKind::MemtagStack) &&
462fa34951fSMitch Phillips       !isInNoSanitizeList(SanitizerKind::MemtagStack, Fn, Loc))
463c5e7f562SEvgeniy Stepanov     Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
464c5e7f562SEvgeniy Stepanov 
4652eccdab3SVlad Tsyrklevich   if (getLangOpts().Sanitize.has(SanitizerKind::Thread) &&
466e64fcdf8SMelanie Blower       !isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))
4674c0fc993SKostya Serebryany     Fn->addFnAttr(llvm::Attribute::SanitizeThread);
4682eccdab3SVlad Tsyrklevich 
4692eccdab3SVlad Tsyrklevich   if (getLangOpts().Sanitize.has(SanitizerKind::Memory) &&
470e64fcdf8SMelanie Blower       !isInNoSanitizeList(SanitizerKind::Memory, Fn, Loc))
4714c0fc993SKostya Serebryany     Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
4722eccdab3SVlad Tsyrklevich 
473d49c32ceSAlexander Potapenko   if (getLangOpts().Sanitize.has(SanitizerKind::KernelMemory) &&
474e64fcdf8SMelanie Blower       !isInNoSanitizeList(SanitizerKind::KernelMemory, Fn, Loc))
475d49c32ceSAlexander Potapenko     Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
476d49c32ceSAlexander Potapenko 
4772eccdab3SVlad Tsyrklevich   if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack) &&
478e64fcdf8SMelanie Blower       !isInNoSanitizeList(SanitizerKind::SafeStack, Fn, Loc))
479c4122c17SPeter Collingbourne     Fn->addFnAttr(llvm::Attribute::SafeStack);
480bf84b8faSKostya Serebryany 
481e55aa03aSVlad Tsyrklevich   if (getLangOpts().Sanitize.has(SanitizerKind::ShadowCallStack) &&
482e64fcdf8SMelanie Blower       !isInNoSanitizeList(SanitizerKind::ShadowCallStack, Fn, Loc))
483e55aa03aSVlad Tsyrklevich     Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
484e55aa03aSVlad Tsyrklevich 
485b2839e4aSAnders Carlsson   return Fn;
486b2839e4aSAnders Carlsson }
487b2839e4aSAnders Carlsson 
4881a711b16SReid Kleckner /// Create a global pointer to a function that will initialize a global
4891a711b16SReid Kleckner /// variable.  The user has requested that this pointer be emitted in a specific
4901a711b16SReid Kleckner /// section.
EmitPointerToInitFunc(const VarDecl * D,llvm::GlobalVariable * GV,llvm::Function * InitFunc,InitSegAttr * ISA)4911a711b16SReid Kleckner void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D,
4921a711b16SReid Kleckner                                           llvm::GlobalVariable *GV,
4931a711b16SReid Kleckner                                           llvm::Function *InitFunc,
4941a711b16SReid Kleckner                                           InitSegAttr *ISA) {
4951a711b16SReid Kleckner   llvm::GlobalVariable *PtrArray = new llvm::GlobalVariable(
4961a711b16SReid Kleckner       TheModule, InitFunc->getType(), /*isConstant=*/true,
4971a711b16SReid Kleckner       llvm::GlobalValue::PrivateLinkage, InitFunc, "__cxx_init_fn_ptr");
4981a711b16SReid Kleckner   PtrArray->setSection(ISA->getSection());
4991a711b16SReid Kleckner   addUsedGlobal(PtrArray);
5001a711b16SReid Kleckner 
5011a711b16SReid Kleckner   // If the GV is already in a comdat group, then we have to join it.
5020d4fb985SRafael Espindola   if (llvm::Comdat *C = GV->getComdat())
5031a711b16SReid Kleckner     PtrArray->setComdat(C);
5041a711b16SReid Kleckner }
5051a711b16SReid Kleckner 
506fe06df4bSDaniel Dunbar void
EmitCXXGlobalVarDeclInitFunc(const VarDecl * D,llvm::GlobalVariable * Addr,bool PerformInit)507cdf7ef54SJohn McCall CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
5086331c408SRichard Smith                                             llvm::GlobalVariable *Addr,
5096331c408SRichard Smith                                             bool PerformInit) {
51097c01c35SArtem Belevich 
51197c01c35SArtem Belevich   // According to E.2.3.1 in CUDA-7.5 Programming guide: __device__,
51297c01c35SArtem Belevich   // __constant__ and __shared__ variables defined in namespace scope,
51397c01c35SArtem Belevich   // that are of class type, cannot have a non-empty constructor. All
51497c01c35SArtem Belevich   // the checks have been done in Sema by now. Whatever initializers
51597c01c35SArtem Belevich   // are allowed are empty and we just need to ignore them here.
51668f5ca4eSYaxun (Sam) Liu   if (getLangOpts().CUDAIsDevice && !getLangOpts().GPUAllowDeviceInit &&
51797c01c35SArtem Belevich       (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() ||
51897c01c35SArtem Belevich        D->hasAttr<CUDASharedAttr>()))
51997c01c35SArtem Belevich     return;
52097c01c35SArtem Belevich 
52134f8a704SAlexey Bataev   if (getLangOpts().OpenMP &&
52234f8a704SAlexey Bataev       getOpenMPRuntime().emitDeclareTargetVarDefinition(D, Addr, PerformInit))
52334f8a704SAlexey Bataev     return;
52434f8a704SAlexey Bataev 
525e07140ebSReid Kleckner   // Check if we've already initialized this decl.
526e07140ebSReid Kleckner   auto I = DelayedCXXInitPosition.find(D);
527e07140ebSReid Kleckner   if (I != DelayedCXXInitPosition.end() && I->second == ~0U)
528e07140ebSReid Kleckner     return;
529e07140ebSReid Kleckner 
530ece0409aSChris Lattner   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
5311ece9fc8SReid Kleckner   SmallString<256> FnName;
5321ece9fc8SReid Kleckner   {
5331ece9fc8SReid Kleckner     llvm::raw_svector_ostream Out(FnName);
5341ece9fc8SReid Kleckner     getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out);
5351ece9fc8SReid Kleckner   }
5365866fe30SEli Friedman 
5375866fe30SEli Friedman   // Create a variable initialization function.
53822337bfeSXiangling Liao   llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
53922337bfeSXiangling Liao       FTy, FnName.str(), getTypes().arrangeNullaryFunction(), D->getLocation());
5405866fe30SEli Friedman 
5411a711b16SReid Kleckner   auto *ISA = D->getAttr<InitSegAttr>();
5426331c408SRichard Smith   CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,
5436331c408SRichard Smith                                                           PerformInit);
5449f834735SRafael Espindola 
54572d03beeSReid Kleckner   llvm::GlobalVariable *COMDATKey =
54672d03beeSReid Kleckner       supportsCOMDAT() && D->isExternallyVisible() ? Addr : nullptr;
5479f834735SRafael Espindola 
5482fd1d7aeSRichard Smith   if (D->getTLSKind()) {
5492fd1d7aeSRichard Smith     // FIXME: Should we support init_priority for thread_local?
5502fd1d7aeSRichard Smith     // FIXME: We only need to register one __cxa_thread_atexit function for the
5512fd1d7aeSRichard Smith     // entire TU.
5522fd1d7aeSRichard Smith     CXXThreadLocalInits.push_back(Fn);
5535a99c49dSRichard Smith     CXXThreadLocalInitVars.push_back(D);
5541a711b16SReid Kleckner   } else if (PerformInit && ISA) {
5551a711b16SReid Kleckner     EmitPointerToInitFunc(D, Addr, Fn, ISA);
5561a711b16SReid Kleckner   } else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
557d5085617SXiangling Liao     OrderGlobalInitsOrStermFinalizers Key(IPA->getPriority(),
558d5085617SXiangling Liao                                           PrioritizedCXXGlobalInits.size());
55989bdd14fSFariborz Jahanian     PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
560c19f4f80SJennifer Yu   } else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) ||
561828767f3SFangrui Song              getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR ||
562828767f3SFangrui Song              D->hasAttr<SelectAnyAttr>()) {
5633738445cSReid Kleckner     // C++ [basic.start.init]p2:
5642753324eSReid Kleckner     //   Definitions of explicitly specialized class template static data
5652753324eSReid Kleckner     //   members have ordered initialization. Other class template static data
5662753324eSReid Kleckner     //   members (i.e., implicitly or explicitly instantiated specializations)
5672753324eSReid Kleckner     //   have unordered initialization.
5683738445cSReid Kleckner     //
5693738445cSReid Kleckner     // As a consequence, we can put them into their own llvm.global_ctors entry.
570563f0e85SReid Kleckner     //
57172d03beeSReid Kleckner     // If the global is externally visible, put the initializer into a COMDAT
57272d03beeSReid Kleckner     // group with the global being initialized.  On most platforms, this is a
57372d03beeSReid Kleckner     // minor startup time optimization.  In the MS C++ ABI, there are no guard
57472d03beeSReid Kleckner     // variables, so this COMDAT key is required for correctness.
575828767f3SFangrui Song     //
5760a02992dSNico Weber     // SelectAny globals will be comdat-folded. Put the initializer into a
5770a02992dSNico Weber     // COMDAT group associated with the global, so the initializers get folded
5780a02992dSNico Weber     // too.
579828767f3SFangrui Song 
58072d03beeSReid Kleckner     AddGlobalCtor(Fn, 65535, COMDATKey);
581828767f3SFangrui Song     if (COMDATKey && (getTriple().isOSBinFormatELF() ||
582828767f3SFangrui Song                       getTarget().getCXXABI().isMicrosoft())) {
583828767f3SFangrui Song       // When COMDAT is used on ELF or in the MS C++ ABI, the key must be in
584828767f3SFangrui Song       // llvm.used to prevent linker GC.
585828767f3SFangrui Song       addUsedGlobal(COMDATKey);
586828767f3SFangrui Song     }
587cd4d6d71SRichard Smith 
588cd4d6d71SRichard Smith     // If we used a COMDAT key for the global ctor, the init function can be
589cd4d6d71SRichard Smith     // discarded if the global ctor entry is discarded.
590cd4d6d71SRichard Smith     // FIXME: Do we need to restrict this to ELF and Wasm?
591cd4d6d71SRichard Smith     llvm::Comdat *C = Addr->getComdat();
592cd4d6d71SRichard Smith     if (COMDATKey && C &&
593cd4d6d71SRichard Smith         (getTarget().getTriple().isOSBinFormatELF() ||
594cd4d6d71SRichard Smith          getTarget().getTriple().isOSBinFormatWasm())) {
595cd4d6d71SRichard Smith       Fn->setComdat(C);
596cd4d6d71SRichard Smith     }
597abed7492SAnton Korobeynikov   } else {
598e07140ebSReid Kleckner     I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash.
59970013b64SJohn McCall     if (I == DelayedCXXInitPosition.end()) {
6005866fe30SEli Friedman       CXXGlobalInits.push_back(Fn);
601e07140ebSReid Kleckner     } else if (I->second != ~0U) {
602e07140ebSReid Kleckner       assert(I->second < CXXGlobalInits.size() &&
603e07140ebSReid Kleckner              CXXGlobalInits[I->second] == nullptr);
60470013b64SJohn McCall       CXXGlobalInits[I->second] = Fn;
60570013b64SJohn McCall     }
60670013b64SJohn McCall   }
607e07140ebSReid Kleckner 
608e07140ebSReid Kleckner   // Remember that we already emitted the initializer for this global.
609e07140ebSReid Kleckner   DelayedCXXInitPosition[D] = ~0U;
6105866fe30SEli Friedman }
6115866fe30SEli Friedman 
EmitCXXThreadLocalInitFunc()6122fd1d7aeSRichard Smith void CodeGenModule::EmitCXXThreadLocalInitFunc() {
613b3341ea4SDavid Majnemer   getCXXABI().EmitThreadLocalInitFuncs(
614b3341ea4SDavid Majnemer       *this, CXXThreadLocals, CXXThreadLocalInits, CXXThreadLocalInitVars);
6152fd1d7aeSRichard Smith 
6162fd1d7aeSRichard Smith   CXXThreadLocalInits.clear();
617b3341ea4SDavid Majnemer   CXXThreadLocalInitVars.clear();
6182fd1d7aeSRichard Smith   CXXThreadLocals.clear();
6192fd1d7aeSRichard Smith }
6202fd1d7aeSRichard Smith 
621afda39a5SIain Sandoe /* Build the initializer for a C++20 module:
622afda39a5SIain Sandoe    This is arranged to be run only once regardless of how many times the module
623afda39a5SIain Sandoe    might be included transitively.  This arranged by using a control variable.
624afda39a5SIain Sandoe 
625afda39a5SIain Sandoe    First we call any initializers for imported modules.
626afda39a5SIain Sandoe    We then call initializers for the Global Module Fragment (if present)
627afda39a5SIain Sandoe    We then call initializers for the current module.
628afda39a5SIain Sandoe    We then call initializers for the Private Module Fragment (if present)
629afda39a5SIain Sandoe */
630afda39a5SIain Sandoe 
EmitCXXModuleInitFunc(Module * Primary)631afda39a5SIain Sandoe void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
632afda39a5SIain Sandoe   while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
633afda39a5SIain Sandoe     CXXGlobalInits.pop_back();
634afda39a5SIain Sandoe 
635afda39a5SIain Sandoe   // We create the function, even if it is empty, since an importer of this
636afda39a5SIain Sandoe   // module will refer to it unconditionally (for the current implementation
637afda39a5SIain Sandoe   // there is no way for the importer to know that an importee does not need
638afda39a5SIain Sandoe   // an initializer to be run).
639afda39a5SIain Sandoe 
640afda39a5SIain Sandoe   // Module initializers for imported modules are emitted first.
641afda39a5SIain Sandoe   // Collect the modules that we import
642afda39a5SIain Sandoe   SmallVector<Module *> AllImports;
643afda39a5SIain Sandoe   // Ones that we export
644afda39a5SIain Sandoe   for (auto I : Primary->Exports)
645afda39a5SIain Sandoe     AllImports.push_back(I.getPointer());
646afda39a5SIain Sandoe   // Ones that we only import.
647afda39a5SIain Sandoe   for (Module *M : Primary->Imports)
648afda39a5SIain Sandoe     AllImports.push_back(M);
649afda39a5SIain Sandoe 
650afda39a5SIain Sandoe   SmallVector<llvm::Function *, 8> ModuleInits;
651afda39a5SIain Sandoe   for (Module *M : AllImports) {
652*786a4f42SChuanqi Xu     // No Itanium initializer in header like modules.
653*786a4f42SChuanqi Xu     if (M->isHeaderLikeModule())
654afda39a5SIain Sandoe       continue; // TODO: warn of mixed use of module map modules and C++20?
655afda39a5SIain Sandoe     llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
656afda39a5SIain Sandoe     SmallString<256> FnName;
657afda39a5SIain Sandoe     {
658afda39a5SIain Sandoe       llvm::raw_svector_ostream Out(FnName);
659afda39a5SIain Sandoe       cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
660afda39a5SIain Sandoe           .mangleModuleInitializer(M, Out);
661afda39a5SIain Sandoe     }
662afda39a5SIain Sandoe     assert(!GetGlobalValue(FnName.str()) &&
663afda39a5SIain Sandoe            "We should only have one use of the initializer call");
664afda39a5SIain Sandoe     llvm::Function *Fn = llvm::Function::Create(
665afda39a5SIain Sandoe         FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
666afda39a5SIain Sandoe     ModuleInits.push_back(Fn);
667afda39a5SIain Sandoe   }
668afda39a5SIain Sandoe   AllImports.clear();
669afda39a5SIain Sandoe 
670afda39a5SIain Sandoe   // Add any initializers with specified priority; this uses the same  approach
671afda39a5SIain Sandoe   // as EmitCXXGlobalInitFunc().
672afda39a5SIain Sandoe   if (!PrioritizedCXXGlobalInits.empty()) {
673afda39a5SIain Sandoe     SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
674afda39a5SIain Sandoe     llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
675afda39a5SIain Sandoe                          PrioritizedCXXGlobalInits.end());
676afda39a5SIain Sandoe     for (SmallVectorImpl<GlobalInitData>::iterator
677afda39a5SIain Sandoe              I = PrioritizedCXXGlobalInits.begin(),
678afda39a5SIain Sandoe              E = PrioritizedCXXGlobalInits.end();
679afda39a5SIain Sandoe          I != E;) {
680afda39a5SIain Sandoe       SmallVectorImpl<GlobalInitData>::iterator PrioE =
681afda39a5SIain Sandoe           std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
682afda39a5SIain Sandoe 
683afda39a5SIain Sandoe       for (; I < PrioE; ++I)
684afda39a5SIain Sandoe         ModuleInits.push_back(I->second);
685afda39a5SIain Sandoe     }
686afda39a5SIain Sandoe     PrioritizedCXXGlobalInits.clear();
687afda39a5SIain Sandoe   }
688afda39a5SIain Sandoe 
689afda39a5SIain Sandoe   // Now append the ones without specified priority.
690afda39a5SIain Sandoe   for (auto F : CXXGlobalInits)
691afda39a5SIain Sandoe     ModuleInits.push_back(F);
692afda39a5SIain Sandoe   CXXGlobalInits.clear();
693afda39a5SIain Sandoe 
694afda39a5SIain Sandoe   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
695afda39a5SIain Sandoe   const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
696afda39a5SIain Sandoe 
697afda39a5SIain Sandoe   // We now build the initializer for this module, which has a mangled name
698afda39a5SIain Sandoe   // as per the Itanium ABI .  The action of the initializer is guarded so that
699afda39a5SIain Sandoe   // each init is run just once (even though a module might be imported
700afda39a5SIain Sandoe   // multiple times via nested use).
701afda39a5SIain Sandoe   llvm::Function *Fn;
702afda39a5SIain Sandoe   llvm::GlobalVariable *Guard = nullptr;
703afda39a5SIain Sandoe   {
704afda39a5SIain Sandoe     SmallString<256> InitFnName;
705afda39a5SIain Sandoe     llvm::raw_svector_ostream Out(InitFnName);
706afda39a5SIain Sandoe     cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
707afda39a5SIain Sandoe         .mangleModuleInitializer(Primary, Out);
708afda39a5SIain Sandoe     Fn = CreateGlobalInitOrCleanUpFunction(
709afda39a5SIain Sandoe         FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
710afda39a5SIain Sandoe         llvm::GlobalVariable::ExternalLinkage);
711afda39a5SIain Sandoe 
712afda39a5SIain Sandoe     Guard = new llvm::GlobalVariable(getModule(), Int8Ty, /*isConstant=*/false,
713afda39a5SIain Sandoe                                      llvm::GlobalVariable::InternalLinkage,
714afda39a5SIain Sandoe                                      llvm::ConstantInt::get(Int8Ty, 0),
715afda39a5SIain Sandoe                                      InitFnName.str() + "__in_chrg");
716afda39a5SIain Sandoe   }
717afda39a5SIain Sandoe   CharUnits GuardAlign = CharUnits::One();
718afda39a5SIain Sandoe   Guard->setAlignment(GuardAlign.getAsAlign());
719afda39a5SIain Sandoe 
720afda39a5SIain Sandoe   CodeGenFunction(*this).GenerateCXXGlobalInitFunc(
721afda39a5SIain Sandoe       Fn, ModuleInits, ConstantAddress(Guard, Int8Ty, GuardAlign));
722afda39a5SIain Sandoe   // We allow for the case that a module object is added to  a linked binary
723afda39a5SIain Sandoe   // without a specific call to the the initializer.  This also ensure that
724afda39a5SIain Sandoe   // implementation partition initializers are called when the partition
725afda39a5SIain Sandoe   // is not imported as an interface.
726afda39a5SIain Sandoe   AddGlobalCtor(Fn);
727afda39a5SIain Sandoe 
728afda39a5SIain Sandoe   // See the comment in EmitCXXGlobalInitFunc about OpenCL global init
729afda39a5SIain Sandoe   // functions.
730afda39a5SIain Sandoe   if (getLangOpts().OpenCL) {
731afda39a5SIain Sandoe     GenKernelArgMetadata(Fn);
732afda39a5SIain Sandoe     Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
733afda39a5SIain Sandoe   }
734afda39a5SIain Sandoe 
735afda39a5SIain Sandoe   assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
736afda39a5SIain Sandoe          getLangOpts().GPUAllowDeviceInit);
737afda39a5SIain Sandoe   if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
738afda39a5SIain Sandoe     Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
739afda39a5SIain Sandoe     Fn->addFnAttr("device-init");
740afda39a5SIain Sandoe   }
741afda39a5SIain Sandoe 
742afda39a5SIain Sandoe   ModuleInits.clear();
743afda39a5SIain Sandoe }
744afda39a5SIain Sandoe 
getTransformedFileName(llvm::Module & M)745ed1b5569SXiangling Liao static SmallString<128> getTransformedFileName(llvm::Module &M) {
746ed1b5569SXiangling Liao   SmallString<128> FileName = llvm::sys::path::filename(M.getName());
747ed1b5569SXiangling Liao 
748ed1b5569SXiangling Liao   if (FileName.empty())
749ed1b5569SXiangling Liao     FileName = "<null>";
750ed1b5569SXiangling Liao 
751ed1b5569SXiangling Liao   for (size_t i = 0; i < FileName.size(); ++i) {
752ed1b5569SXiangling Liao     // Replace everything that's not [a-zA-Z0-9._] with a _. This set happens
753ed1b5569SXiangling Liao     // to be the set of C preprocessing numbers.
754ed1b5569SXiangling Liao     if (!isPreprocessingNumberBody(FileName[i]))
755ed1b5569SXiangling Liao       FileName[i] = '_';
756ed1b5569SXiangling Liao   }
757ed1b5569SXiangling Liao 
758ed1b5569SXiangling Liao   return FileName;
759ed1b5569SXiangling Liao }
760ed1b5569SXiangling Liao 
getPrioritySuffix(unsigned int Priority)761d5085617SXiangling Liao static std::string getPrioritySuffix(unsigned int Priority) {
762d5085617SXiangling Liao   assert(Priority <= 65535 && "Priority should always be <= 65535.");
763d5085617SXiangling Liao 
764d5085617SXiangling Liao   // Compute the function suffix from priority. Prepend with zeroes to make
765d5085617SXiangling Liao   // sure the function names are also ordered as priorities.
766d5085617SXiangling Liao   std::string PrioritySuffix = llvm::utostr(Priority);
767d5085617SXiangling Liao   PrioritySuffix = std::string(6 - PrioritySuffix.size(), '0') + PrioritySuffix;
768d5085617SXiangling Liao 
769d5085617SXiangling Liao   return PrioritySuffix;
770d5085617SXiangling Liao }
771d5085617SXiangling Liao 
772fe06df4bSDaniel Dunbar void
EmitCXXGlobalInitFunc()773fe06df4bSDaniel Dunbar CodeGenModule::EmitCXXGlobalInitFunc() {
77470013b64SJohn McCall   while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
77570013b64SJohn McCall     CXXGlobalInits.pop_back();
77670013b64SJohn McCall 
777afda39a5SIain Sandoe   // When we import C++20 modules, we must run their initializers first.
778afda39a5SIain Sandoe   SmallVector<llvm::Function *, 8> ModuleInits;
779afda39a5SIain Sandoe   if (CXX20ModuleInits)
780afda39a5SIain Sandoe     for (Module *M : ImportedModules) {
781*786a4f42SChuanqi Xu       // No Itanium initializer in header like modules.
782*786a4f42SChuanqi Xu       if (M->isHeaderLikeModule())
783afda39a5SIain Sandoe         continue;
784afda39a5SIain Sandoe       llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
785afda39a5SIain Sandoe       SmallString<256> FnName;
786afda39a5SIain Sandoe       {
787afda39a5SIain Sandoe         llvm::raw_svector_ostream Out(FnName);
788afda39a5SIain Sandoe         cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
789afda39a5SIain Sandoe             .mangleModuleInitializer(M, Out);
790afda39a5SIain Sandoe       }
791afda39a5SIain Sandoe       assert(!GetGlobalValue(FnName.str()) &&
792afda39a5SIain Sandoe              "We should only have one use of the initializer call");
793afda39a5SIain Sandoe       llvm::Function *Fn = llvm::Function::Create(
794afda39a5SIain Sandoe           FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
795afda39a5SIain Sandoe       ModuleInits.push_back(Fn);
796afda39a5SIain Sandoe     }
797afda39a5SIain Sandoe 
798afda39a5SIain Sandoe   if (ModuleInits.empty() && CXXGlobalInits.empty() &&
799afda39a5SIain Sandoe       PrioritizedCXXGlobalInits.empty())
800633c6f6fSAnders Carlsson     return;
801633c6f6fSAnders Carlsson 
802ece0409aSChris Lattner   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
8037791f1a4SAkira Hatanaka   const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
804633c6f6fSAnders Carlsson 
80522337bfeSXiangling Liao   // Create our global prioritized initialization function.
8069f2a4eedSFariborz Jahanian   if (!PrioritizedCXXGlobalInits.empty()) {
807b3341ea4SDavid Majnemer     SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
808090e4e57SFariborz Jahanian     llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
809469b2003SFariborz Jahanian                          PrioritizedCXXGlobalInits.end());
810abed7492SAnton Korobeynikov     // Iterate over "chunks" of ctors with same priority and emit each chunk
811abed7492SAnton Korobeynikov     // into separate function. Note - everything is sorted first by priority,
812abed7492SAnton Korobeynikov     // second - by lex order, so we emit ctor functions in proper order.
813abed7492SAnton Korobeynikov     for (SmallVectorImpl<GlobalInitData >::iterator
814abed7492SAnton Korobeynikov            I = PrioritizedCXXGlobalInits.begin(),
815abed7492SAnton Korobeynikov            E = PrioritizedCXXGlobalInits.end(); I != E; ) {
816abed7492SAnton Korobeynikov       SmallVectorImpl<GlobalInitData >::iterator
817abed7492SAnton Korobeynikov         PrioE = std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
818abed7492SAnton Korobeynikov 
819abed7492SAnton Korobeynikov       LocalCXXGlobalInits.clear();
820d5085617SXiangling Liao 
821d5085617SXiangling Liao       unsigned int Priority = I->first.priority;
82222337bfeSXiangling Liao       llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
823d5085617SXiangling Liao           FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI);
824abed7492SAnton Korobeynikov 
825afda39a5SIain Sandoe       // Prepend the module inits to the highest priority set.
826afda39a5SIain Sandoe       if (!ModuleInits.empty()) {
827afda39a5SIain Sandoe         for (auto F : ModuleInits)
828afda39a5SIain Sandoe           LocalCXXGlobalInits.push_back(F);
829afda39a5SIain Sandoe         ModuleInits.clear();
830afda39a5SIain Sandoe       }
831afda39a5SIain Sandoe 
832abed7492SAnton Korobeynikov       for (; I < PrioE; ++I)
833abed7492SAnton Korobeynikov         LocalCXXGlobalInits.push_back(I->second);
834abed7492SAnton Korobeynikov 
835139cfc2eSBenjamin Kramer       CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, LocalCXXGlobalInits);
836abed7492SAnton Korobeynikov       AddGlobalCtor(Fn, Priority);
8379f2a4eedSFariborz Jahanian     }
83835071ac8SYaron Keren     PrioritizedCXXGlobalInits.clear();
839abed7492SAnton Korobeynikov   }
840abed7492SAnton Korobeynikov 
841afda39a5SIain Sandoe   if (getCXXABI().useSinitAndSterm() && ModuleInits.empty() &&
842afda39a5SIain Sandoe       CXXGlobalInits.empty())
84322337bfeSXiangling Liao     return;
84422337bfeSXiangling Liao 
845afda39a5SIain Sandoe   for (auto F : CXXGlobalInits)
846afda39a5SIain Sandoe     ModuleInits.push_back(F);
847afda39a5SIain Sandoe   CXXGlobalInits.clear();
848afda39a5SIain Sandoe 
849ed1b5569SXiangling Liao   // Include the filename in the symbol name. Including "sub_" matches gcc
850ed1b5569SXiangling Liao   // and makes sure these symbols appear lexicographically behind the symbols
851ed1b5569SXiangling Liao   // with priority emitted above.
852afda39a5SIain Sandoe   llvm::Function *Fn;
853afda39a5SIain Sandoe   if (CXX20ModuleInits && getContext().getModuleForCodeGen()) {
854afda39a5SIain Sandoe     SmallString<256> InitFnName;
855afda39a5SIain Sandoe     llvm::raw_svector_ostream Out(InitFnName);
856afda39a5SIain Sandoe     cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
857afda39a5SIain Sandoe         .mangleModuleInitializer(getContext().getModuleForCodeGen(), Out);
858afda39a5SIain Sandoe     Fn = CreateGlobalInitOrCleanUpFunction(
859afda39a5SIain Sandoe         FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
860afda39a5SIain Sandoe         llvm::GlobalVariable::ExternalLinkage);
861afda39a5SIain Sandoe   } else
862afda39a5SIain Sandoe     Fn = CreateGlobalInitOrCleanUpFunction(
863afda39a5SIain Sandoe         FTy,
864afda39a5SIain Sandoe         llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
8656ef801aaSXiangling Liao         FI);
866abed7492SAnton Korobeynikov 
867afda39a5SIain Sandoe   CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits);
868fe06df4bSDaniel Dunbar   AddGlobalCtor(Fn);
869abed7492SAnton Korobeynikov 
870e6cf6c78SAnastasia Stulova   // In OpenCL global init functions must be converted to kernels in order to
871e6cf6c78SAnastasia Stulova   // be able to launch them from the host.
872e6cf6c78SAnastasia Stulova   // FIXME: Some more work might be needed to handle destructors correctly.
873e6cf6c78SAnastasia Stulova   // Current initialization function makes use of function pointers callbacks.
874e6cf6c78SAnastasia Stulova   // We can't support function pointers especially between host and device.
875e6cf6c78SAnastasia Stulova   // However it seems global destruction has little meaning without any
876e6cf6c78SAnastasia Stulova   // dynamic resource allocation on the device and program scope variables are
877e6cf6c78SAnastasia Stulova   // destroyed by the runtime when program is released.
878e6cf6c78SAnastasia Stulova   if (getLangOpts().OpenCL) {
8798ad4c6e4SYaxun (Sam) Liu     GenKernelArgMetadata(Fn);
880e6cf6c78SAnastasia Stulova     Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
881e6cf6c78SAnastasia Stulova   }
882e6cf6c78SAnastasia Stulova 
8834cb42564SYaxun (Sam) Liu   assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
8844cb42564SYaxun (Sam) Liu          getLangOpts().GPUAllowDeviceInit);
8854cb42564SYaxun (Sam) Liu   if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
88668f5ca4eSYaxun (Sam) Liu     Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
88768f5ca4eSYaxun (Sam) Liu     Fn->addFnAttr("device-init");
88868f5ca4eSYaxun (Sam) Liu   }
88968f5ca4eSYaxun (Sam) Liu 
890afda39a5SIain Sandoe   ModuleInits.clear();
891fe06df4bSDaniel Dunbar }
892fe06df4bSDaniel Dunbar 
EmitCXXGlobalCleanUpFunc()89322337bfeSXiangling Liao void CodeGenModule::EmitCXXGlobalCleanUpFunc() {
894d5085617SXiangling Liao   if (CXXGlobalDtorsOrStermFinalizers.empty() &&
895d5085617SXiangling Liao       PrioritizedCXXStermFinalizers.empty())
896fe06df4bSDaniel Dunbar     return;
897fe06df4bSDaniel Dunbar 
898ece0409aSChris Lattner   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
8997791f1a4SAkira Hatanaka   const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
900fe06df4bSDaniel Dunbar 
901d5085617SXiangling Liao   // Create our global prioritized cleanup function.
902d5085617SXiangling Liao   if (!PrioritizedCXXStermFinalizers.empty()) {
903d5085617SXiangling Liao     SmallVector<CXXGlobalDtorsOrStermFinalizer_t, 8> LocalCXXStermFinalizers;
904d5085617SXiangling Liao     llvm::array_pod_sort(PrioritizedCXXStermFinalizers.begin(),
905d5085617SXiangling Liao                          PrioritizedCXXStermFinalizers.end());
906d5085617SXiangling Liao     // Iterate over "chunks" of dtors with same priority and emit each chunk
907d5085617SXiangling Liao     // into separate function. Note - everything is sorted first by priority,
908d5085617SXiangling Liao     // second - by lex order, so we emit dtor functions in proper order.
909d5085617SXiangling Liao     for (SmallVectorImpl<StermFinalizerData>::iterator
910d5085617SXiangling Liao              I = PrioritizedCXXStermFinalizers.begin(),
911d5085617SXiangling Liao              E = PrioritizedCXXStermFinalizers.end();
912d5085617SXiangling Liao          I != E;) {
913d5085617SXiangling Liao       SmallVectorImpl<StermFinalizerData>::iterator PrioE =
914d5085617SXiangling Liao           std::upper_bound(I + 1, E, *I, StermFinalizerPriorityCmp());
915d5085617SXiangling Liao 
916d5085617SXiangling Liao       LocalCXXStermFinalizers.clear();
917d5085617SXiangling Liao 
918d5085617SXiangling Liao       unsigned int Priority = I->first.priority;
919d5085617SXiangling Liao       llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
920d5085617SXiangling Liao           FTy, "_GLOBAL__a_" + getPrioritySuffix(Priority), FI);
921d5085617SXiangling Liao 
922d5085617SXiangling Liao       for (; I < PrioE; ++I) {
923d5085617SXiangling Liao         llvm::FunctionCallee DtorFn = I->second;
924d5085617SXiangling Liao         LocalCXXStermFinalizers.emplace_back(DtorFn.getFunctionType(),
925d5085617SXiangling Liao                                              DtorFn.getCallee(), nullptr);
926d5085617SXiangling Liao       }
927d5085617SXiangling Liao 
928d5085617SXiangling Liao       CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc(
929d5085617SXiangling Liao           Fn, LocalCXXStermFinalizers);
930d5085617SXiangling Liao       AddGlobalDtor(Fn, Priority);
931d5085617SXiangling Liao     }
932d5085617SXiangling Liao     PrioritizedCXXStermFinalizers.clear();
933d5085617SXiangling Liao   }
934d5085617SXiangling Liao 
935d5085617SXiangling Liao   if (CXXGlobalDtorsOrStermFinalizers.empty())
936d5085617SXiangling Liao     return;
937d5085617SXiangling Liao 
93822337bfeSXiangling Liao   // Create our global cleanup function.
9396ef801aaSXiangling Liao   llvm::Function *Fn =
9406ef801aaSXiangling Liao       CreateGlobalInitOrCleanUpFunction(FTy, "_GLOBAL__D_a", FI);
94122337bfeSXiangling Liao 
94222337bfeSXiangling Liao   CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc(
94322337bfeSXiangling Liao       Fn, CXXGlobalDtorsOrStermFinalizers);
944fe06df4bSDaniel Dunbar   AddGlobalDtor(Fn);
94522337bfeSXiangling Liao   CXXGlobalDtorsOrStermFinalizers.clear();
946fe06df4bSDaniel Dunbar }
947fe06df4bSDaniel Dunbar 
948cdf7ef54SJohn McCall /// Emit the code necessary to initialize the given global variable.
GenerateCXXGlobalVarDeclInitFunc(llvm::Function * Fn,const VarDecl * D,llvm::GlobalVariable * Addr,bool PerformInit)949fe06df4bSDaniel Dunbar void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
950cdf7ef54SJohn McCall                                                        const VarDecl *D,
9516331c408SRichard Smith                                                  llvm::GlobalVariable *Addr,
9526331c408SRichard Smith                                                        bool PerformInit) {
95338e24964SAlexey Samsonov   // Check if we need to emit debug info for variable initializer.
95492848deeSDavid Blaikie   if (D->hasAttr<NoDebugAttr>())
9558a13c418SCraig Topper     DebugInfo = nullptr; // disable debug info indefinitely for this function
95608597073SNick Lewycky 
957f2ceec48SStephen Kelly   CurEHLocation = D->getBeginLoc();
95847d28e07SDavid Blaikie 
959105c565eSReid Kleckner   StartFunction(GlobalDecl(D, DynamicInitKind::Initializer),
960105c565eSReid Kleckner                 getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(),
96166face6aSAlexandre Ganea                 FunctionArgList());
96266face6aSAlexandre Ganea   // Emit an artificial location for this function.
96366face6aSAlexandre Ganea   auto AL = ApplyDebugLocation::CreateArtificial(*this);
9647572284fSDaniel Dunbar 
965fa918f69SDouglas Gregor   // Use guarded initialization if the global variable is weak. This
966fa918f69SDouglas Gregor   // occurs for, e.g., instantiated static data members and
967fa918f69SDouglas Gregor   // definitions explicitly marked weak.
968453b7caaSRichard Smith   //
969453b7caaSRichard Smith   // Also use guarded initialization for a variable with dynamic TLS and
970453b7caaSRichard Smith   // unordered initialization. (If the initialization is ordered, the ABI
971453b7caaSRichard Smith   // layer will guard the whole-TU initialization for us.)
972453b7caaSRichard Smith   if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage() ||
973453b7caaSRichard Smith       (D->getTLSKind() == VarDecl::TLS_Dynamic &&
974453b7caaSRichard Smith        isTemplateInstantiation(D->getTemplateSpecializationKind()))) {
9756331c408SRichard Smith     EmitCXXGuardedInit(*D, Addr, PerformInit);
976cdf7ef54SJohn McCall   } else {
9776331c408SRichard Smith     EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);
97867ca8c4cSFariborz Jahanian   }
9797572284fSDaniel Dunbar 
9807572284fSDaniel Dunbar   FinishFunction();
981fe06df4bSDaniel Dunbar }
9827572284fSDaniel Dunbar 
983139cfc2eSBenjamin Kramer void
GenerateCXXGlobalInitFunc(llvm::Function * Fn,ArrayRef<llvm::Function * > Decls,ConstantAddress Guard)984139cfc2eSBenjamin Kramer CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
985b3341ea4SDavid Majnemer                                            ArrayRef<llvm::Function *> Decls,
9863ad0636eSRichard Smith                                            ConstantAddress Guard) {
9870ce2b875SAdrian Prantl   {
98895b24e9bSAdrian Prantl     auto NL = ApplyDebugLocation::CreateEmpty(*this);
989a738c25fSJohn McCall     StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
99022e66b43SAdrian Prantl                   getTypes().arrangeNullaryFunction(), FunctionArgList());
9910ce2b875SAdrian Prantl     // Emit an artificial location for this function.
99295b24e9bSAdrian Prantl     auto AL = ApplyDebugLocation::CreateArtificial(*this);
993fe06df4bSDaniel Dunbar 
9948a13c418SCraig Topper     llvm::BasicBlock *ExitBlock = nullptr;
9957f416cc4SJohn McCall     if (Guard.isValid()) {
9960ce2b875SAdrian Prantl       // If we have a guard variable, check whether we've already performed
9970ce2b875SAdrian Prantl       // these initializations. This happens for TLS initialization functions.
9982fd1d7aeSRichard Smith       llvm::Value *GuardVal = Builder.CreateLoad(Guard);
9990ce2b875SAdrian Prantl       llvm::Value *Uninit = Builder.CreateIsNull(GuardVal,
10000ce2b875SAdrian Prantl                                                  "guard.uninitialized");
10012fd1d7aeSRichard Smith       llvm::BasicBlock *InitBlock = createBasicBlock("init");
10022fd1d7aeSRichard Smith       ExitBlock = createBasicBlock("exit");
1003ae8d62c9SRichard Smith       EmitCXXGuardedInitBranch(Uninit, InitBlock, ExitBlock,
1004ae8d62c9SRichard Smith                                GuardKind::TlsGuard, nullptr);
10052fd1d7aeSRichard Smith       EmitBlock(InitBlock);
100614f88158SManman Ren       // Mark as initialized before initializing anything else. If the
100714f88158SManman Ren       // initializers use previously-initialized thread_local vars, that's
100814f88158SManman Ren       // probably supposed to be OK, but the standard doesn't say.
100914f88158SManman Ren       Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);
10103ad0636eSRichard Smith 
10113ad0636eSRichard Smith       // The guard variable can't ever change again.
10123ad0636eSRichard Smith       EmitInvariantStart(
10133ad0636eSRichard Smith           Guard.getPointer(),
10143ad0636eSRichard Smith           CharUnits::fromQuantity(
10153ad0636eSRichard Smith               CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())));
10162fd1d7aeSRichard Smith     }
10172fd1d7aeSRichard Smith 
101831168b07SJohn McCall     RunCleanupsScope Scope(*this);
101931168b07SJohn McCall 
102031168b07SJohn McCall     // When building in Objective-C++ ARC mode, create an autorelease pool
102131168b07SJohn McCall     // around the global initializers.
1022bbafb8a7SDavid Blaikie     if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) {
102331168b07SJohn McCall       llvm::Value *token = EmitObjCAutoreleasePoolPush();
102431168b07SJohn McCall       EmitObjCAutoreleasePoolCleanup(token);
102531168b07SJohn McCall     }
102631168b07SJohn McCall 
1027139cfc2eSBenjamin Kramer     for (unsigned i = 0, e = Decls.size(); i != e; ++i)
102870013b64SJohn McCall       if (Decls[i])
1029882987f3SJohn McCall         EmitRuntimeCall(Decls[i]);
1030fe06df4bSDaniel Dunbar 
103131168b07SJohn McCall     Scope.ForceCleanup();
103231168b07SJohn McCall 
10332fd1d7aeSRichard Smith     if (ExitBlock) {
10342fd1d7aeSRichard Smith       Builder.CreateBr(ExitBlock);
10352fd1d7aeSRichard Smith       EmitBlock(ExitBlock);
10362fd1d7aeSRichard Smith     }
10370ce2b875SAdrian Prantl   }
10382fd1d7aeSRichard Smith 
1039fe06df4bSDaniel Dunbar   FinishFunction();
1040fe06df4bSDaniel Dunbar }
1041fe06df4bSDaniel Dunbar 
GenerateCXXGlobalCleanUpFunc(llvm::Function * Fn,ArrayRef<std::tuple<llvm::FunctionType *,llvm::WeakTrackingVH,llvm::Constant * >> DtorsOrStermFinalizers)104222337bfeSXiangling Liao void CodeGenFunction::GenerateCXXGlobalCleanUpFunc(
1043e369bd92SSanjoy Das     llvm::Function *Fn,
1044d5085617SXiangling Liao     ArrayRef<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,
1045d5085617SXiangling Liao                         llvm::Constant *>>
1046d5085617SXiangling Liao         DtorsOrStermFinalizers) {
10470ce2b875SAdrian Prantl   {
104895b24e9bSAdrian Prantl     auto NL = ApplyDebugLocation::CreateEmpty(*this);
1049a738c25fSJohn McCall     StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
105022e66b43SAdrian Prantl                   getTypes().arrangeNullaryFunction(), FunctionArgList());
10510ce2b875SAdrian Prantl     // Emit an artificial location for this function.
105295b24e9bSAdrian Prantl     auto AL = ApplyDebugLocation::CreateArtificial(*this);
1053fe06df4bSDaniel Dunbar 
105422337bfeSXiangling Liao     // Emit the cleanups, in reverse order from construction.
105522337bfeSXiangling Liao     for (unsigned i = 0, e = DtorsOrStermFinalizers.size(); i != e; ++i) {
1056f7321540SJames Y Knight       llvm::FunctionType *CalleeTy;
1057f7321540SJames Y Knight       llvm::Value *Callee;
1058f7321540SJames Y Knight       llvm::Constant *Arg;
105922337bfeSXiangling Liao       std::tie(CalleeTy, Callee, Arg) = DtorsOrStermFinalizers[e - i - 1];
106022337bfeSXiangling Liao 
106122337bfeSXiangling Liao       llvm::CallInst *CI = nullptr;
106222337bfeSXiangling Liao       if (Arg == nullptr) {
106322337bfeSXiangling Liao         assert(
106422337bfeSXiangling Liao             CGM.getCXXABI().useSinitAndSterm() &&
106522337bfeSXiangling Liao             "Arg could not be nullptr unless using sinit and sterm functions.");
106622337bfeSXiangling Liao         CI = Builder.CreateCall(CalleeTy, Callee);
106722337bfeSXiangling Liao       } else
106822337bfeSXiangling Liao         CI = Builder.CreateCall(CalleeTy, Callee, Arg);
106922337bfeSXiangling Liao 
10705e8416a7SChris Lattner       // Make sure the call and the callee agree on calling convention.
10715e8416a7SChris Lattner       if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
10725e8416a7SChris Lattner         CI->setCallingConv(F->getCallingConv());
10735e8416a7SChris Lattner     }
10740ce2b875SAdrian Prantl   }
1075fe06df4bSDaniel Dunbar 
1076fe06df4bSDaniel Dunbar   FinishFunction();
1077633c6f6fSAnders Carlsson }
1078633c6f6fSAnders Carlsson 
107998de3d74SJohn McCall /// generateDestroyHelper - Generates a helper function which, when
10807f416cc4SJohn McCall /// invoked, destroys the given object.  The address of the object
10817f416cc4SJohn McCall /// should be in global memory.
generateDestroyHelper(Address addr,QualType type,Destroyer * destroyer,bool useEHCleanupForArray,const VarDecl * VD)1082ebe87e1cSDavid Blaikie llvm::Function *CodeGenFunction::generateDestroyHelper(
10837f416cc4SJohn McCall     Address addr, QualType type, Destroyer *destroyer,
1084ebe87e1cSDavid Blaikie     bool useEHCleanupForArray, const VarDecl *VD) {
1085a738c25fSJohn McCall   FunctionArgList args;
108656223237SAlexey Bataev   ImplicitParamDecl Dst(getContext(), getContext().VoidPtrTy,
108756223237SAlexey Bataev                         ImplicitParamDecl::Other);
108856223237SAlexey Bataev   args.push_back(&Dst);
1089282bc10eSAnders Carlsson 
1090c56a8b32SJohn McCall   const CGFunctionInfo &FI =
1091c56a8b32SJohn McCall     CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, args);
1092a729c62bSJohn McCall   llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
109322337bfeSXiangling Liao   llvm::Function *fn = CGM.CreateGlobalInitOrCleanUpFunction(
10947791f1a4SAkira Hatanaka       FTy, "__cxx_global_array_dtor", FI, VD->getLocation());
1095282bc10eSAnders Carlsson 
1096f2ceec48SStephen Kelly   CurEHLocation = VD->getBeginLoc();
109747d28e07SDavid Blaikie 
109866face6aSAlexandre Ganea   StartFunction(GlobalDecl(VD, DynamicInitKind::GlobalArrayDestructor),
109966face6aSAlexandre Ganea                 getContext().VoidTy, fn, FI, args);
110066face6aSAlexandre Ganea   // Emit an artificial location for this function.
110166face6aSAlexandre Ganea   auto AL = ApplyDebugLocation::CreateArtificial(*this);
1102282bc10eSAnders Carlsson 
110398de3d74SJohn McCall   emitDestroy(addr, type, destroyer, useEHCleanupForArray);
1104282bc10eSAnders Carlsson 
1105282bc10eSAnders Carlsson   FinishFunction();
1106282bc10eSAnders Carlsson 
110798de3d74SJohn McCall   return fn;
1108282bc10eSAnders Carlsson }
1109