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