10b57cec5SDimitry Andric //===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This contains code dealing with code generation of C++ declarations
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "CGCXXABI.h"
14bdd1243dSDimitry Andric #include "CGHLSLRuntime.h"
150b57cec5SDimitry Andric #include "CGObjCRuntime.h"
160b57cec5SDimitry Andric #include "CGOpenMPRuntime.h"
17480093f4SDimitry Andric #include "CodeGenFunction.h"
180b57cec5SDimitry Andric #include "TargetInfo.h"
19480093f4SDimitry Andric #include "clang/AST/Attr.h"
205ffd83dbSDimitry Andric #include "clang/Basic/LangOptions.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
220b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
230b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h"
240b57cec5SDimitry Andric #include "llvm/Support/Path.h"
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric using namespace clang;
270b57cec5SDimitry Andric using namespace CodeGen;
280b57cec5SDimitry Andric
EmitDeclInit(CodeGenFunction & CGF,const VarDecl & D,ConstantAddress DeclPtr)290b57cec5SDimitry Andric static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
300b57cec5SDimitry Andric ConstantAddress DeclPtr) {
310b57cec5SDimitry Andric assert(
320b57cec5SDimitry Andric (D.hasGlobalStorage() ||
330b57cec5SDimitry Andric (D.hasLocalStorage() && CGF.getContext().getLangOpts().OpenCLCPlusPlus)) &&
340b57cec5SDimitry Andric "VarDecl must have global or local (in the case of OpenCL) storage!");
350b57cec5SDimitry Andric assert(!D.getType()->isReferenceType() &&
360b57cec5SDimitry Andric "Should not call EmitDeclInit on a reference!");
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric QualType type = D.getType();
390b57cec5SDimitry Andric LValue lv = CGF.MakeAddrLValue(DeclPtr, type);
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric const Expr *Init = D.getInit();
420b57cec5SDimitry Andric switch (CGF.getEvaluationKind(type)) {
430b57cec5SDimitry Andric case TEK_Scalar: {
440b57cec5SDimitry Andric CodeGenModule &CGM = CGF.CGM;
450b57cec5SDimitry Andric if (lv.isObjCStrong())
460b57cec5SDimitry Andric CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init),
470b57cec5SDimitry Andric DeclPtr, D.getTLSKind());
480b57cec5SDimitry Andric else if (lv.isObjCWeak())
490b57cec5SDimitry Andric CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init),
500b57cec5SDimitry Andric DeclPtr);
510b57cec5SDimitry Andric else
520b57cec5SDimitry Andric CGF.EmitScalarInit(Init, &D, lv, false);
530b57cec5SDimitry Andric return;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric case TEK_Complex:
560b57cec5SDimitry Andric CGF.EmitComplexExprIntoLValue(Init, lv, /*isInit*/ true);
570b57cec5SDimitry Andric return;
580b57cec5SDimitry Andric case TEK_Aggregate:
59480093f4SDimitry Andric CGF.EmitAggExpr(Init,
60*0fca6ea1SDimitry Andric AggValueSlot::forLValue(lv, AggValueSlot::IsDestructed,
610b57cec5SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers,
620b57cec5SDimitry Andric AggValueSlot::IsNotAliased,
630b57cec5SDimitry Andric AggValueSlot::DoesNotOverlap));
640b57cec5SDimitry Andric return;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric llvm_unreachable("bad evaluation kind");
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric /// Emit code to cause the destruction of the given variable with
700b57cec5SDimitry Andric /// static storage duration.
EmitDeclDestroy(CodeGenFunction & CGF,const VarDecl & D,ConstantAddress Addr)710b57cec5SDimitry Andric static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
720b57cec5SDimitry Andric ConstantAddress Addr) {
730b57cec5SDimitry Andric // Honor __attribute__((no_destroy)) and bail instead of attempting
740b57cec5SDimitry Andric // to emit a reference to a possibly nonexistent destructor, which
750b57cec5SDimitry Andric // in turn can cause a crash. This will result in a global constructor
760b57cec5SDimitry Andric // that isn't balanced out by a destructor call as intended by the
770b57cec5SDimitry Andric // attribute. This also checks for -fno-c++-static-destructors and
780b57cec5SDimitry Andric // bails even if the attribute is not present.
79a7dea167SDimitry Andric QualType::DestructionKind DtorKind = D.needsDestruction(CGF.getContext());
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric // FIXME: __attribute__((cleanup)) ?
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric switch (DtorKind) {
840b57cec5SDimitry Andric case QualType::DK_none:
850b57cec5SDimitry Andric return;
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric case QualType::DK_cxx_destructor:
880b57cec5SDimitry Andric break;
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric case QualType::DK_objc_strong_lifetime:
910b57cec5SDimitry Andric case QualType::DK_objc_weak_lifetime:
920b57cec5SDimitry Andric case QualType::DK_nontrivial_c_struct:
930b57cec5SDimitry Andric // We don't care about releasing objects during process teardown.
940b57cec5SDimitry Andric assert(!D.getTLSKind() && "should have rejected this");
950b57cec5SDimitry Andric return;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric llvm::FunctionCallee Func;
990b57cec5SDimitry Andric llvm::Constant *Argument;
1000b57cec5SDimitry Andric
101a7dea167SDimitry Andric CodeGenModule &CGM = CGF.CGM;
102a7dea167SDimitry Andric QualType Type = D.getType();
103a7dea167SDimitry Andric
1040b57cec5SDimitry Andric // Special-case non-array C++ destructors, if they have the right signature.
1050b57cec5SDimitry Andric // Under some ABIs, destructors return this instead of void, and cannot be
1060b57cec5SDimitry Andric // passed directly to __cxa_atexit if the target does not allow this
1070b57cec5SDimitry Andric // mismatch.
1080b57cec5SDimitry Andric const CXXRecordDecl *Record = Type->getAsCXXRecordDecl();
1090b57cec5SDimitry Andric bool CanRegisterDestructor =
1100b57cec5SDimitry Andric Record && (!CGM.getCXXABI().HasThisReturn(
1110b57cec5SDimitry Andric GlobalDecl(Record->getDestructor(), Dtor_Complete)) ||
1120b57cec5SDimitry Andric CGM.getCXXABI().canCallMismatchedFunctionType());
1130b57cec5SDimitry Andric // If __cxa_atexit is disabled via a flag, a different helper function is
1140b57cec5SDimitry Andric // generated elsewhere which uses atexit instead, and it takes the destructor
1150b57cec5SDimitry Andric // directly.
1160b57cec5SDimitry Andric bool UsingExternalHelper = !CGM.getCodeGenOpts().CXAAtExit;
1170b57cec5SDimitry Andric if (Record && (CanRegisterDestructor || UsingExternalHelper)) {
1180b57cec5SDimitry Andric assert(!Record->hasTrivialDestructor());
1190b57cec5SDimitry Andric CXXDestructorDecl *Dtor = Record->getDestructor();
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric Func = CGM.getAddrAndTypeOfCXXStructor(GlobalDecl(Dtor, Dtor_Complete));
1220b57cec5SDimitry Andric if (CGF.getContext().getLangOpts().OpenCL) {
1230b57cec5SDimitry Andric auto DestAS =
1240b57cec5SDimitry Andric CGM.getTargetCodeGenInfo().getAddrSpaceOfCxaAtexitPtrParam();
12506c3fb27SDimitry Andric auto DestTy = llvm::PointerType::get(
12606c3fb27SDimitry Andric CGM.getLLVMContext(), CGM.getContext().getTargetAddressSpace(DestAS));
1270b57cec5SDimitry Andric auto SrcAS = D.getType().getQualifiers().getAddressSpace();
1280b57cec5SDimitry Andric if (DestAS == SrcAS)
1295f757f3fSDimitry Andric Argument = Addr.getPointer();
1300b57cec5SDimitry Andric else
1310b57cec5SDimitry Andric // FIXME: On addr space mismatch we are passing NULL. The generation
1320b57cec5SDimitry Andric // of the global destructor function should be adjusted accordingly.
1330b57cec5SDimitry Andric Argument = llvm::ConstantPointerNull::get(DestTy);
1340b57cec5SDimitry Andric } else {
13506c3fb27SDimitry Andric Argument = Addr.getPointer();
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric // Otherwise, the standard logic requires a helper function.
1380b57cec5SDimitry Andric } else {
13906c3fb27SDimitry Andric Addr = Addr.withElementType(CGF.ConvertTypeForMem(Type));
1400b57cec5SDimitry Andric Func = CodeGenFunction(CGM)
1410b57cec5SDimitry Andric .generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind),
1420b57cec5SDimitry Andric CGF.needsEHCleanup(DtorKind), &D);
1430b57cec5SDimitry Andric Argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric CGM.getCXXABI().registerGlobalDtor(CGF, D, Func, Argument);
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andric /// Emit code to cause the variable at the given address to be considered as
1500b57cec5SDimitry Andric /// constant from this point onwards.
EmitDeclInvariant(CodeGenFunction & CGF,const VarDecl & D,llvm::Constant * Addr)1510b57cec5SDimitry Andric static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D,
1520b57cec5SDimitry Andric llvm::Constant *Addr) {
1530b57cec5SDimitry Andric return CGF.EmitInvariantStart(
1540b57cec5SDimitry Andric Addr, CGF.getContext().getTypeSizeInChars(D.getType()));
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric
EmitInvariantStart(llvm::Constant * Addr,CharUnits Size)1570b57cec5SDimitry Andric void CodeGenFunction::EmitInvariantStart(llvm::Constant *Addr, CharUnits Size) {
1580b57cec5SDimitry Andric // Do not emit the intrinsic if we're not optimizing.
1590b57cec5SDimitry Andric if (!CGM.getCodeGenOpts().OptimizationLevel)
1600b57cec5SDimitry Andric return;
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric // Grab the llvm.invariant.start intrinsic.
1630b57cec5SDimitry Andric llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
1640b57cec5SDimitry Andric // Overloaded address space type.
165*0fca6ea1SDimitry Andric assert(Addr->getType()->isPointerTy() && "Address must be a pointer");
166*0fca6ea1SDimitry Andric llvm::Type *ObjectPtr[1] = {Addr->getType()};
1670b57cec5SDimitry Andric llvm::Function *InvariantStart = CGM.getIntrinsic(InvStartID, ObjectPtr);
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric // Emit a call with the size in bytes of the object.
1700b57cec5SDimitry Andric uint64_t Width = Size.getQuantity();
1715f757f3fSDimitry Andric llvm::Value *Args[2] = {llvm::ConstantInt::getSigned(Int64Ty, Width), Addr};
1720b57cec5SDimitry Andric Builder.CreateCall(InvariantStart, Args);
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
EmitCXXGlobalVarDeclInit(const VarDecl & D,llvm::GlobalVariable * GV,bool PerformInit)1750b57cec5SDimitry Andric void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
1760eae32dcSDimitry Andric llvm::GlobalVariable *GV,
1770b57cec5SDimitry Andric bool PerformInit) {
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric const Expr *Init = D.getInit();
1800b57cec5SDimitry Andric QualType T = D.getType();
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric // The address space of a static local variable (DeclPtr) may be different
1830b57cec5SDimitry Andric // from the address space of the "this" argument of the constructor. In that
1840b57cec5SDimitry Andric // case, we need an addrspacecast before calling the constructor.
1850b57cec5SDimitry Andric //
1860b57cec5SDimitry Andric // struct StructWithCtor {
1870b57cec5SDimitry Andric // __device__ StructWithCtor() {...}
1880b57cec5SDimitry Andric // };
1890b57cec5SDimitry Andric // __device__ void foo() {
1900b57cec5SDimitry Andric // __shared__ StructWithCtor s;
1910b57cec5SDimitry Andric // ...
1920b57cec5SDimitry Andric // }
1930b57cec5SDimitry Andric //
1940b57cec5SDimitry Andric // For example, in the above CUDA code, the static local variable s has a
1950b57cec5SDimitry Andric // "shared" address space qualifier, but the constructor of StructWithCtor
1960b57cec5SDimitry Andric // expects "this" in the "generic" address space.
197bdd1243dSDimitry Andric unsigned ExpectedAddrSpace = getTypes().getTargetAddressSpace(T);
1980eae32dcSDimitry Andric unsigned ActualAddrSpace = GV->getAddressSpace();
1990eae32dcSDimitry Andric llvm::Constant *DeclPtr = GV;
2000b57cec5SDimitry Andric if (ActualAddrSpace != ExpectedAddrSpace) {
20106c3fb27SDimitry Andric llvm::PointerType *PTy =
20206c3fb27SDimitry Andric llvm::PointerType::get(getLLVMContext(), ExpectedAddrSpace);
2030b57cec5SDimitry Andric DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy);
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric
2060eae32dcSDimitry Andric ConstantAddress DeclAddr(
2070eae32dcSDimitry Andric DeclPtr, GV->getValueType(), getContext().getDeclAlign(&D));
2080b57cec5SDimitry Andric
2090b57cec5SDimitry Andric if (!T->isReferenceType()) {
2100b57cec5SDimitry Andric if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
2110b57cec5SDimitry Andric D.hasAttr<OMPThreadPrivateDeclAttr>()) {
2120b57cec5SDimitry Andric (void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition(
2130b57cec5SDimitry Andric &D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
2140b57cec5SDimitry Andric PerformInit, this);
2150b57cec5SDimitry Andric }
21606c3fb27SDimitry Andric bool NeedsDtor =
21706c3fb27SDimitry Andric D.needsDestruction(getContext()) == QualType::DK_cxx_destructor;
2180b57cec5SDimitry Andric if (PerformInit)
2190b57cec5SDimitry Andric EmitDeclInit(*this, D, DeclAddr);
2205f757f3fSDimitry Andric if (D.getType().isConstantStorage(getContext(), true, !NeedsDtor))
2210b57cec5SDimitry Andric EmitDeclInvariant(*this, D, DeclPtr);
2220b57cec5SDimitry Andric else
2230b57cec5SDimitry Andric EmitDeclDestroy(*this, D, DeclAddr);
2240b57cec5SDimitry Andric return;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andric assert(PerformInit && "cannot have constant initializer which needs "
2280b57cec5SDimitry Andric "destruction for reference");
2290b57cec5SDimitry Andric RValue RV = EmitReferenceBindingToExpr(Init);
2300b57cec5SDimitry Andric EmitStoreOfScalar(RV.getScalarVal(), DeclAddr, false, T);
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric
2330b57cec5SDimitry Andric /// Create a stub function, suitable for being passed to atexit,
2340b57cec5SDimitry Andric /// which passes the given address to the given destructor function.
createAtExitStub(const VarDecl & VD,llvm::FunctionCallee dtor,llvm::Constant * addr)235*0fca6ea1SDimitry Andric llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD,
2360b57cec5SDimitry Andric llvm::FunctionCallee dtor,
2370b57cec5SDimitry Andric llvm::Constant *addr) {
2380b57cec5SDimitry Andric // Get the destructor function type, void(*)(void).
2390b57cec5SDimitry Andric llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false);
2400b57cec5SDimitry Andric SmallString<256> FnName;
2410b57cec5SDimitry Andric {
2420b57cec5SDimitry Andric llvm::raw_svector_ostream Out(FnName);
2430b57cec5SDimitry Andric CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out);
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2475ffd83dbSDimitry Andric llvm::Function *fn = CGM.CreateGlobalInitOrCleanUpFunction(
2480b57cec5SDimitry Andric ty, FnName.str(), FI, VD.getLocation());
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric CodeGenFunction CGF(CGM);
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric CGF.StartFunction(GlobalDecl(&VD, DynamicInitKind::AtExit),
253e8d8bef9SDimitry Andric CGM.getContext().VoidTy, fn, FI, FunctionArgList(),
254e8d8bef9SDimitry Andric VD.getLocation(), VD.getInit()->getExprLoc());
255e8d8bef9SDimitry Andric // Emit an artificial location for this function.
256e8d8bef9SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(CGF);
2570b57cec5SDimitry Andric
2580b57cec5SDimitry Andric llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andric // Make sure the call and the callee agree on calling convention.
261a7dea167SDimitry Andric if (auto *dtorFn = dyn_cast<llvm::Function>(
262a7dea167SDimitry Andric dtor.getCallee()->stripPointerCastsAndAliases()))
2630b57cec5SDimitry Andric call->setCallingConv(dtorFn->getCallingConv());
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric CGF.FinishFunction();
2660b57cec5SDimitry Andric
267*0fca6ea1SDimitry Andric // Get a proper function pointer.
268*0fca6ea1SDimitry Andric FunctionProtoType::ExtProtoInfo EPI(getContext().getDefaultCallingConvention(
269*0fca6ea1SDimitry Andric /*IsVariadic=*/false, /*IsCXXMethod=*/false));
270*0fca6ea1SDimitry Andric QualType fnType = getContext().getFunctionType(getContext().VoidTy,
271*0fca6ea1SDimitry Andric {getContext().VoidPtrTy}, EPI);
272*0fca6ea1SDimitry Andric return CGM.getFunctionPointer(fn, fnType);
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
275fe6060f1SDimitry Andric /// Create a stub function, suitable for being passed to __pt_atexit_np,
276fe6060f1SDimitry Andric /// which passes the given address to the given destructor function.
createTLSAtExitStub(const VarDecl & D,llvm::FunctionCallee Dtor,llvm::Constant * Addr,llvm::FunctionCallee & AtExit)277fe6060f1SDimitry Andric llvm::Function *CodeGenFunction::createTLSAtExitStub(
278fe6060f1SDimitry Andric const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr,
279fe6060f1SDimitry Andric llvm::FunctionCallee &AtExit) {
280fe6060f1SDimitry Andric SmallString<256> FnName;
281fe6060f1SDimitry Andric {
282fe6060f1SDimitry Andric llvm::raw_svector_ostream Out(FnName);
283fe6060f1SDimitry Andric CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&D, Out);
284fe6060f1SDimitry Andric }
285fe6060f1SDimitry Andric
286fe6060f1SDimitry Andric const CGFunctionInfo &FI = CGM.getTypes().arrangeLLVMFunctionInfo(
2878a4dda33SDimitry Andric getContext().IntTy, FnInfoOpts::None, {getContext().IntTy},
2888a4dda33SDimitry Andric FunctionType::ExtInfo(), {}, RequiredArgs::All);
289fe6060f1SDimitry Andric
290fe6060f1SDimitry Andric // Get the stub function type, int(*)(int,...).
291fe6060f1SDimitry Andric llvm::FunctionType *StubTy =
292fe6060f1SDimitry Andric llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy}, true);
293fe6060f1SDimitry Andric
294fe6060f1SDimitry Andric llvm::Function *DtorStub = CGM.CreateGlobalInitOrCleanUpFunction(
295fe6060f1SDimitry Andric StubTy, FnName.str(), FI, D.getLocation());
296fe6060f1SDimitry Andric
297fe6060f1SDimitry Andric CodeGenFunction CGF(CGM);
298fe6060f1SDimitry Andric
299fe6060f1SDimitry Andric FunctionArgList Args;
300fe6060f1SDimitry Andric ImplicitParamDecl IPD(CGM.getContext(), CGM.getContext().IntTy,
3015f757f3fSDimitry Andric ImplicitParamKind::Other);
302fe6060f1SDimitry Andric Args.push_back(&IPD);
303fe6060f1SDimitry Andric QualType ResTy = CGM.getContext().IntTy;
304fe6060f1SDimitry Andric
305fe6060f1SDimitry Andric CGF.StartFunction(GlobalDecl(&D, DynamicInitKind::AtExit), ResTy, DtorStub,
306fe6060f1SDimitry Andric FI, Args, D.getLocation(), D.getInit()->getExprLoc());
307fe6060f1SDimitry Andric
308fe6060f1SDimitry Andric // Emit an artificial location for this function.
309fe6060f1SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(CGF);
310fe6060f1SDimitry Andric
311fe6060f1SDimitry Andric llvm::CallInst *call = CGF.Builder.CreateCall(Dtor, Addr);
312fe6060f1SDimitry Andric
313fe6060f1SDimitry Andric // Make sure the call and the callee agree on calling convention.
314fe6060f1SDimitry Andric if (auto *DtorFn = dyn_cast<llvm::Function>(
315fe6060f1SDimitry Andric Dtor.getCallee()->stripPointerCastsAndAliases()))
316fe6060f1SDimitry Andric call->setCallingConv(DtorFn->getCallingConv());
317fe6060f1SDimitry Andric
318fe6060f1SDimitry Andric // Return 0 from function
319fe6060f1SDimitry Andric CGF.Builder.CreateStore(llvm::Constant::getNullValue(CGM.IntTy),
320fe6060f1SDimitry Andric CGF.ReturnValue);
321fe6060f1SDimitry Andric
322fe6060f1SDimitry Andric CGF.FinishFunction();
323fe6060f1SDimitry Andric
324fe6060f1SDimitry Andric return DtorStub;
325fe6060f1SDimitry Andric }
326fe6060f1SDimitry Andric
3270b57cec5SDimitry Andric /// Register a global destructor using the C atexit runtime function.
registerGlobalDtorWithAtExit(const VarDecl & VD,llvm::FunctionCallee dtor,llvm::Constant * addr)3280b57cec5SDimitry Andric void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,
3290b57cec5SDimitry Andric llvm::FunctionCallee dtor,
3300b57cec5SDimitry Andric llvm::Constant *addr) {
3310b57cec5SDimitry Andric // Create a function which calls the destructor.
3320b57cec5SDimitry Andric llvm::Constant *dtorStub = createAtExitStub(VD, dtor, addr);
3330b57cec5SDimitry Andric registerGlobalDtorWithAtExit(dtorStub);
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric
3365f757f3fSDimitry Andric /// Register a global destructor using the LLVM 'llvm.global_dtors' global.
registerGlobalDtorWithLLVM(const VarDecl & VD,llvm::FunctionCallee Dtor,llvm::Constant * Addr)3375f757f3fSDimitry Andric void CodeGenFunction::registerGlobalDtorWithLLVM(const VarDecl &VD,
3385f757f3fSDimitry Andric llvm::FunctionCallee Dtor,
3395f757f3fSDimitry Andric llvm::Constant *Addr) {
3405f757f3fSDimitry Andric // Create a function which calls the destructor.
341*0fca6ea1SDimitry Andric llvm::Function *dtorStub =
342*0fca6ea1SDimitry Andric cast<llvm::Function>(createAtExitStub(VD, Dtor, Addr));
3435f757f3fSDimitry Andric CGM.AddGlobalDtor(dtorStub);
3445f757f3fSDimitry Andric }
3455f757f3fSDimitry Andric
registerGlobalDtorWithAtExit(llvm::Constant * dtorStub)3460b57cec5SDimitry Andric void CodeGenFunction::registerGlobalDtorWithAtExit(llvm::Constant *dtorStub) {
3470b57cec5SDimitry Andric // extern "C" int atexit(void (*f)(void));
348e8d8bef9SDimitry Andric assert(dtorStub->getType() ==
349e8d8bef9SDimitry Andric llvm::PointerType::get(
350e8d8bef9SDimitry Andric llvm::FunctionType::get(CGM.VoidTy, false),
351e8d8bef9SDimitry Andric dtorStub->getType()->getPointerAddressSpace()) &&
3525ffd83dbSDimitry Andric "Argument to atexit has a wrong type.");
3535ffd83dbSDimitry Andric
3540b57cec5SDimitry Andric llvm::FunctionType *atexitTy =
3550b57cec5SDimitry Andric llvm::FunctionType::get(IntTy, dtorStub->getType(), false);
3560b57cec5SDimitry Andric
3570b57cec5SDimitry Andric llvm::FunctionCallee atexit =
3580b57cec5SDimitry Andric CGM.CreateRuntimeFunction(atexitTy, "atexit", llvm::AttributeList(),
3590b57cec5SDimitry Andric /*Local=*/true);
3600b57cec5SDimitry Andric if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit.getCallee()))
3610b57cec5SDimitry Andric atexitFn->setDoesNotThrow();
3620b57cec5SDimitry Andric
3630b57cec5SDimitry Andric EmitNounwindRuntimeCall(atexit, dtorStub);
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric
3665ffd83dbSDimitry Andric llvm::Value *
unregisterGlobalDtorWithUnAtExit(llvm::Constant * dtorStub)367e8d8bef9SDimitry Andric CodeGenFunction::unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub) {
3685ffd83dbSDimitry Andric // The unatexit subroutine unregisters __dtor functions that were previously
3695ffd83dbSDimitry Andric // registered by the atexit subroutine. If the referenced function is found,
3705ffd83dbSDimitry Andric // it is removed from the list of functions that are called at normal program
3715ffd83dbSDimitry Andric // termination and the unatexit returns a value of 0, otherwise a non-zero
3725ffd83dbSDimitry Andric // value is returned.
3735ffd83dbSDimitry Andric //
3745ffd83dbSDimitry Andric // extern "C" int unatexit(void (*f)(void));
375e8d8bef9SDimitry Andric assert(dtorStub->getType() ==
376e8d8bef9SDimitry Andric llvm::PointerType::get(
377e8d8bef9SDimitry Andric llvm::FunctionType::get(CGM.VoidTy, false),
378e8d8bef9SDimitry Andric dtorStub->getType()->getPointerAddressSpace()) &&
3795ffd83dbSDimitry Andric "Argument to unatexit has a wrong type.");
3805ffd83dbSDimitry Andric
3815ffd83dbSDimitry Andric llvm::FunctionType *unatexitTy =
3825ffd83dbSDimitry Andric llvm::FunctionType::get(IntTy, {dtorStub->getType()}, /*isVarArg=*/false);
3835ffd83dbSDimitry Andric
3845ffd83dbSDimitry Andric llvm::FunctionCallee unatexit =
3855ffd83dbSDimitry Andric CGM.CreateRuntimeFunction(unatexitTy, "unatexit", llvm::AttributeList());
3865ffd83dbSDimitry Andric
3875ffd83dbSDimitry Andric cast<llvm::Function>(unatexit.getCallee())->setDoesNotThrow();
3885ffd83dbSDimitry Andric
3895ffd83dbSDimitry Andric return EmitNounwindRuntimeCall(unatexit, dtorStub);
3905ffd83dbSDimitry Andric }
3915ffd83dbSDimitry Andric
EmitCXXGuardedInit(const VarDecl & D,llvm::GlobalVariable * DeclPtr,bool PerformInit)3920b57cec5SDimitry Andric void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
3930b57cec5SDimitry Andric llvm::GlobalVariable *DeclPtr,
3940b57cec5SDimitry Andric bool PerformInit) {
3950b57cec5SDimitry Andric // If we've been asked to forbid guard variables, emit an error now.
3960b57cec5SDimitry Andric // This diagnostic is hard-coded for Darwin's use case; we can find
3970b57cec5SDimitry Andric // better phrasing if someone else needs it.
3980b57cec5SDimitry Andric if (CGM.getCodeGenOpts().ForbidGuardVariables)
3990b57cec5SDimitry Andric CGM.Error(D.getLocation(),
4000b57cec5SDimitry Andric "this initialization requires a guard variable, which "
4010b57cec5SDimitry Andric "the kernel does not support");
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit);
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric
EmitCXXGuardedInitBranch(llvm::Value * NeedsInit,llvm::BasicBlock * InitBlock,llvm::BasicBlock * NoInitBlock,GuardKind Kind,const VarDecl * D)4060b57cec5SDimitry Andric void CodeGenFunction::EmitCXXGuardedInitBranch(llvm::Value *NeedsInit,
4070b57cec5SDimitry Andric llvm::BasicBlock *InitBlock,
4080b57cec5SDimitry Andric llvm::BasicBlock *NoInitBlock,
4090b57cec5SDimitry Andric GuardKind Kind,
4100b57cec5SDimitry Andric const VarDecl *D) {
4110b57cec5SDimitry Andric assert((Kind == GuardKind::TlsGuard || D) && "no guarded variable");
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andric // A guess at how many times we will enter the initialization of a
4140b57cec5SDimitry Andric // variable, depending on the kind of variable.
4150b57cec5SDimitry Andric static const uint64_t InitsPerTLSVar = 1024;
4160b57cec5SDimitry Andric static const uint64_t InitsPerLocalVar = 1024 * 1024;
4170b57cec5SDimitry Andric
4180b57cec5SDimitry Andric llvm::MDNode *Weights;
4190b57cec5SDimitry Andric if (Kind == GuardKind::VariableGuard && !D->isLocalVarDecl()) {
4200b57cec5SDimitry Andric // For non-local variables, don't apply any weighting for now. Due to our
4210b57cec5SDimitry Andric // use of COMDATs, we expect there to be at most one initialization of the
4220b57cec5SDimitry Andric // variable per DSO, but we have no way to know how many DSOs will try to
4230b57cec5SDimitry Andric // initialize the variable.
4240b57cec5SDimitry Andric Weights = nullptr;
4250b57cec5SDimitry Andric } else {
4260b57cec5SDimitry Andric uint64_t NumInits;
4270b57cec5SDimitry Andric // FIXME: For the TLS case, collect and use profiling information to
4280b57cec5SDimitry Andric // determine a more accurate brach weight.
4290b57cec5SDimitry Andric if (Kind == GuardKind::TlsGuard || D->getTLSKind())
4300b57cec5SDimitry Andric NumInits = InitsPerTLSVar;
4310b57cec5SDimitry Andric else
4320b57cec5SDimitry Andric NumInits = InitsPerLocalVar;
4330b57cec5SDimitry Andric
4340b57cec5SDimitry Andric // The probability of us entering the initializer is
4350b57cec5SDimitry Andric // 1 / (total number of times we attempt to initialize the variable).
4360b57cec5SDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext());
4370b57cec5SDimitry Andric Weights = MDHelper.createBranchWeights(1, NumInits - 1);
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric
4400b57cec5SDimitry Andric Builder.CreateCondBr(NeedsInit, InitBlock, NoInitBlock, Weights);
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric
CreateGlobalInitOrCleanUpFunction(llvm::FunctionType * FTy,const Twine & Name,const CGFunctionInfo & FI,SourceLocation Loc,bool TLS,llvm::GlobalVariable::LinkageTypes Linkage)4435ffd83dbSDimitry Andric llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
4440b57cec5SDimitry Andric llvm::FunctionType *FTy, const Twine &Name, const CGFunctionInfo &FI,
44581ad6265SDimitry Andric SourceLocation Loc, bool TLS, llvm::GlobalVariable::LinkageTypes Linkage) {
44681ad6265SDimitry Andric llvm::Function *Fn = llvm::Function::Create(FTy, Linkage, Name, &getModule());
4475ffd83dbSDimitry Andric
4480b57cec5SDimitry Andric if (!getLangOpts().AppleKext && !TLS) {
4490b57cec5SDimitry Andric // Set the section if needed.
4500b57cec5SDimitry Andric if (const char *Section = getTarget().getStaticInitSectionSpecifier())
4510b57cec5SDimitry Andric Fn->setSection(Section);
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric
45481ad6265SDimitry Andric if (Linkage == llvm::GlobalVariable::InternalLinkage)
4550b57cec5SDimitry Andric SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric Fn->setCallingConv(getRuntimeCC());
4580b57cec5SDimitry Andric
4590b57cec5SDimitry Andric if (!getLangOpts().Exceptions)
4600b57cec5SDimitry Andric Fn->setDoesNotThrow();
4610b57cec5SDimitry Andric
4620b57cec5SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::Address) &&
463fe6060f1SDimitry Andric !isInNoSanitizeList(SanitizerKind::Address, Fn, Loc))
4640b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
4650b57cec5SDimitry Andric
4660b57cec5SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::KernelAddress) &&
467fe6060f1SDimitry Andric !isInNoSanitizeList(SanitizerKind::KernelAddress, Fn, Loc))
4680b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
4690b57cec5SDimitry Andric
4700b57cec5SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::HWAddress) &&
471fe6060f1SDimitry Andric !isInNoSanitizeList(SanitizerKind::HWAddress, Fn, Loc))
4720b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
4730b57cec5SDimitry Andric
4740b57cec5SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::KernelHWAddress) &&
475fe6060f1SDimitry Andric !isInNoSanitizeList(SanitizerKind::KernelHWAddress, Fn, Loc))
4760b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
4770b57cec5SDimitry Andric
47881ad6265SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::MemtagStack) &&
47981ad6265SDimitry Andric !isInNoSanitizeList(SanitizerKind::MemtagStack, Fn, Loc))
4800b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
4810b57cec5SDimitry Andric
4820b57cec5SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::Thread) &&
483fe6060f1SDimitry Andric !isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))
4840b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::SanitizeThread);
4850b57cec5SDimitry Andric
486*0fca6ea1SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::NumericalStability) &&
487*0fca6ea1SDimitry Andric !isInNoSanitizeList(SanitizerKind::NumericalStability, Fn, Loc))
488*0fca6ea1SDimitry Andric Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);
489*0fca6ea1SDimitry Andric
4900b57cec5SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::Memory) &&
491fe6060f1SDimitry Andric !isInNoSanitizeList(SanitizerKind::Memory, Fn, Loc))
4920b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
4930b57cec5SDimitry Andric
4940b57cec5SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::KernelMemory) &&
495fe6060f1SDimitry Andric !isInNoSanitizeList(SanitizerKind::KernelMemory, Fn, Loc))
4960b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
4970b57cec5SDimitry Andric
4980b57cec5SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack) &&
499fe6060f1SDimitry Andric !isInNoSanitizeList(SanitizerKind::SafeStack, Fn, Loc))
5000b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::SafeStack);
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric if (getLangOpts().Sanitize.has(SanitizerKind::ShadowCallStack) &&
503fe6060f1SDimitry Andric !isInNoSanitizeList(SanitizerKind::ShadowCallStack, Fn, Loc))
5040b57cec5SDimitry Andric Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
5050b57cec5SDimitry Andric
5060b57cec5SDimitry Andric return Fn;
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
5090b57cec5SDimitry Andric /// Create a global pointer to a function that will initialize a global
5100b57cec5SDimitry Andric /// variable. The user has requested that this pointer be emitted in a specific
5110b57cec5SDimitry Andric /// section.
EmitPointerToInitFunc(const VarDecl * D,llvm::GlobalVariable * GV,llvm::Function * InitFunc,InitSegAttr * ISA)5120b57cec5SDimitry Andric void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D,
5130b57cec5SDimitry Andric llvm::GlobalVariable *GV,
5140b57cec5SDimitry Andric llvm::Function *InitFunc,
5150b57cec5SDimitry Andric InitSegAttr *ISA) {
5160b57cec5SDimitry Andric llvm::GlobalVariable *PtrArray = new llvm::GlobalVariable(
5170b57cec5SDimitry Andric TheModule, InitFunc->getType(), /*isConstant=*/true,
5180b57cec5SDimitry Andric llvm::GlobalValue::PrivateLinkage, InitFunc, "__cxx_init_fn_ptr");
5190b57cec5SDimitry Andric PtrArray->setSection(ISA->getSection());
5200b57cec5SDimitry Andric addUsedGlobal(PtrArray);
5210b57cec5SDimitry Andric
5220b57cec5SDimitry Andric // If the GV is already in a comdat group, then we have to join it.
5230b57cec5SDimitry Andric if (llvm::Comdat *C = GV->getComdat())
5240b57cec5SDimitry Andric PtrArray->setComdat(C);
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric
5270b57cec5SDimitry Andric void
EmitCXXGlobalVarDeclInitFunc(const VarDecl * D,llvm::GlobalVariable * Addr,bool PerformInit)5280b57cec5SDimitry Andric CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
5290b57cec5SDimitry Andric llvm::GlobalVariable *Addr,
5300b57cec5SDimitry Andric bool PerformInit) {
5310b57cec5SDimitry Andric
5320b57cec5SDimitry Andric // According to E.2.3.1 in CUDA-7.5 Programming guide: __device__,
5330b57cec5SDimitry Andric // __constant__ and __shared__ variables defined in namespace scope,
5340b57cec5SDimitry Andric // that are of class type, cannot have a non-empty constructor. All
5350b57cec5SDimitry Andric // the checks have been done in Sema by now. Whatever initializers
5360b57cec5SDimitry Andric // are allowed are empty and we just need to ignore them here.
537480093f4SDimitry Andric if (getLangOpts().CUDAIsDevice && !getLangOpts().GPUAllowDeviceInit &&
5380b57cec5SDimitry Andric (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() ||
5390b57cec5SDimitry Andric D->hasAttr<CUDASharedAttr>()))
5400b57cec5SDimitry Andric return;
5410b57cec5SDimitry Andric
5420b57cec5SDimitry Andric // Check if we've already initialized this decl.
5430b57cec5SDimitry Andric auto I = DelayedCXXInitPosition.find(D);
5440b57cec5SDimitry Andric if (I != DelayedCXXInitPosition.end() && I->second == ~0U)
5450b57cec5SDimitry Andric return;
5460b57cec5SDimitry Andric
5470b57cec5SDimitry Andric llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
5480b57cec5SDimitry Andric SmallString<256> FnName;
5490b57cec5SDimitry Andric {
5500b57cec5SDimitry Andric llvm::raw_svector_ostream Out(FnName);
5510b57cec5SDimitry Andric getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out);
5520b57cec5SDimitry Andric }
5530b57cec5SDimitry Andric
5540b57cec5SDimitry Andric // Create a variable initialization function.
5555ffd83dbSDimitry Andric llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
5565ffd83dbSDimitry Andric FTy, FnName.str(), getTypes().arrangeNullaryFunction(), D->getLocation());
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric auto *ISA = D->getAttr<InitSegAttr>();
5590b57cec5SDimitry Andric CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,
5600b57cec5SDimitry Andric PerformInit);
5610b57cec5SDimitry Andric
5620b57cec5SDimitry Andric llvm::GlobalVariable *COMDATKey =
5630b57cec5SDimitry Andric supportsCOMDAT() && D->isExternallyVisible() ? Addr : nullptr;
5640b57cec5SDimitry Andric
5650b57cec5SDimitry Andric if (D->getTLSKind()) {
5660b57cec5SDimitry Andric // FIXME: Should we support init_priority for thread_local?
5670b57cec5SDimitry Andric // FIXME: We only need to register one __cxa_thread_atexit function for the
5680b57cec5SDimitry Andric // entire TU.
5690b57cec5SDimitry Andric CXXThreadLocalInits.push_back(Fn);
5700b57cec5SDimitry Andric CXXThreadLocalInitVars.push_back(D);
5710b57cec5SDimitry Andric } else if (PerformInit && ISA) {
572bdd1243dSDimitry Andric // Contract with backend that "init_seg(compiler)" corresponds to priority
573bdd1243dSDimitry Andric // 200 and "init_seg(lib)" corresponds to priority 400.
574bdd1243dSDimitry Andric int Priority = -1;
575bdd1243dSDimitry Andric if (ISA->getSection() == ".CRT$XCC")
576bdd1243dSDimitry Andric Priority = 200;
577bdd1243dSDimitry Andric else if (ISA->getSection() == ".CRT$XCL")
578bdd1243dSDimitry Andric Priority = 400;
579bdd1243dSDimitry Andric
580bdd1243dSDimitry Andric if (Priority != -1)
581bdd1243dSDimitry Andric AddGlobalCtor(Fn, Priority, ~0U, COMDATKey);
582bdd1243dSDimitry Andric else
5830b57cec5SDimitry Andric EmitPointerToInitFunc(D, Addr, Fn, ISA);
5840b57cec5SDimitry Andric } else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
585fe6060f1SDimitry Andric OrderGlobalInitsOrStermFinalizers Key(IPA->getPriority(),
586fe6060f1SDimitry Andric PrioritizedCXXGlobalInits.size());
5870b57cec5SDimitry Andric PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
5880b57cec5SDimitry Andric } else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) ||
5896e75b2fbSDimitry Andric getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR ||
5906e75b2fbSDimitry Andric D->hasAttr<SelectAnyAttr>()) {
5910b57cec5SDimitry Andric // C++ [basic.start.init]p2:
5920b57cec5SDimitry Andric // Definitions of explicitly specialized class template static data
5930b57cec5SDimitry Andric // members have ordered initialization. Other class template static data
5940b57cec5SDimitry Andric // members (i.e., implicitly or explicitly instantiated specializations)
5950b57cec5SDimitry Andric // have unordered initialization.
5960b57cec5SDimitry Andric //
5970b57cec5SDimitry Andric // As a consequence, we can put them into their own llvm.global_ctors entry.
5980b57cec5SDimitry Andric //
5990b57cec5SDimitry Andric // If the global is externally visible, put the initializer into a COMDAT
6000b57cec5SDimitry Andric // group with the global being initialized. On most platforms, this is a
6010b57cec5SDimitry Andric // minor startup time optimization. In the MS C++ ABI, there are no guard
6020b57cec5SDimitry Andric // variables, so this COMDAT key is required for correctness.
6036e75b2fbSDimitry Andric //
6040b57cec5SDimitry Andric // SelectAny globals will be comdat-folded. Put the initializer into a
6050b57cec5SDimitry Andric // COMDAT group associated with the global, so the initializers get folded
6060b57cec5SDimitry Andric // too.
607bdd1243dSDimitry Andric I = DelayedCXXInitPosition.find(D);
608bdd1243dSDimitry Andric // CXXGlobalInits.size() is the lex order number for the next deferred
609bdd1243dSDimitry Andric // VarDecl. Use it when the current VarDecl is non-deferred. Although this
610bdd1243dSDimitry Andric // lex order number is shared between current VarDecl and some following
611bdd1243dSDimitry Andric // VarDecls, their order of insertion into `llvm.global_ctors` is the same
612bdd1243dSDimitry Andric // as the lexing order and the following stable sort would preserve such
613bdd1243dSDimitry Andric // order.
614bdd1243dSDimitry Andric unsigned LexOrder =
615bdd1243dSDimitry Andric I == DelayedCXXInitPosition.end() ? CXXGlobalInits.size() : I->second;
616bdd1243dSDimitry Andric AddGlobalCtor(Fn, 65535, LexOrder, COMDATKey);
6176e75b2fbSDimitry Andric if (COMDATKey && (getTriple().isOSBinFormatELF() ||
6186e75b2fbSDimitry Andric getTarget().getCXXABI().isMicrosoft())) {
6196e75b2fbSDimitry Andric // When COMDAT is used on ELF or in the MS C++ ABI, the key must be in
6206e75b2fbSDimitry Andric // llvm.used to prevent linker GC.
6216e75b2fbSDimitry Andric addUsedGlobal(COMDATKey);
6226e75b2fbSDimitry Andric }
623349cc55cSDimitry Andric
624349cc55cSDimitry Andric // If we used a COMDAT key for the global ctor, the init function can be
625349cc55cSDimitry Andric // discarded if the global ctor entry is discarded.
626349cc55cSDimitry Andric // FIXME: Do we need to restrict this to ELF and Wasm?
627349cc55cSDimitry Andric llvm::Comdat *C = Addr->getComdat();
628349cc55cSDimitry Andric if (COMDATKey && C &&
629349cc55cSDimitry Andric (getTarget().getTriple().isOSBinFormatELF() ||
630349cc55cSDimitry Andric getTarget().getTriple().isOSBinFormatWasm())) {
631349cc55cSDimitry Andric Fn->setComdat(C);
632349cc55cSDimitry Andric }
6330b57cec5SDimitry Andric } else {
6340b57cec5SDimitry Andric I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash.
6350b57cec5SDimitry Andric if (I == DelayedCXXInitPosition.end()) {
6360b57cec5SDimitry Andric CXXGlobalInits.push_back(Fn);
6370b57cec5SDimitry Andric } else if (I->second != ~0U) {
6380b57cec5SDimitry Andric assert(I->second < CXXGlobalInits.size() &&
6390b57cec5SDimitry Andric CXXGlobalInits[I->second] == nullptr);
6400b57cec5SDimitry Andric CXXGlobalInits[I->second] = Fn;
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric
6440b57cec5SDimitry Andric // Remember that we already emitted the initializer for this global.
6450b57cec5SDimitry Andric DelayedCXXInitPosition[D] = ~0U;
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric
EmitCXXThreadLocalInitFunc()6480b57cec5SDimitry Andric void CodeGenModule::EmitCXXThreadLocalInitFunc() {
6490b57cec5SDimitry Andric getCXXABI().EmitThreadLocalInitFuncs(
6500b57cec5SDimitry Andric *this, CXXThreadLocals, CXXThreadLocalInits, CXXThreadLocalInitVars);
6510b57cec5SDimitry Andric
6520b57cec5SDimitry Andric CXXThreadLocalInits.clear();
6530b57cec5SDimitry Andric CXXThreadLocalInitVars.clear();
6540b57cec5SDimitry Andric CXXThreadLocals.clear();
6550b57cec5SDimitry Andric }
6560b57cec5SDimitry Andric
657fcaf7f86SDimitry Andric /* Build the initializer for a C++20 module:
658fcaf7f86SDimitry Andric This is arranged to be run only once regardless of how many times the module
659bdd1243dSDimitry Andric might be included transitively. This arranged by using a guard variable.
660bdd1243dSDimitry Andric
66106c3fb27SDimitry Andric If there are no initializers at all (and also no imported modules) we reduce
662bdd1243dSDimitry Andric this to an empty function (since the Itanium ABI requires that this function
663bdd1243dSDimitry Andric be available to a caller, which might be produced by a different
664bdd1243dSDimitry Andric implementation).
665fcaf7f86SDimitry Andric
666fcaf7f86SDimitry Andric First we call any initializers for imported modules.
667fcaf7f86SDimitry Andric We then call initializers for the Global Module Fragment (if present)
668fcaf7f86SDimitry Andric We then call initializers for the current module.
669fcaf7f86SDimitry Andric We then call initializers for the Private Module Fragment (if present)
670fcaf7f86SDimitry Andric */
671fcaf7f86SDimitry Andric
EmitCXXModuleInitFunc(Module * Primary)672fcaf7f86SDimitry Andric void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
6735f757f3fSDimitry Andric assert(Primary->isInterfaceOrPartition() &&
6745f757f3fSDimitry Andric "The function should only be called for C++20 named module interface"
6755f757f3fSDimitry Andric " or partition.");
6765f757f3fSDimitry Andric
677fcaf7f86SDimitry Andric while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
678fcaf7f86SDimitry Andric CXXGlobalInits.pop_back();
679fcaf7f86SDimitry Andric
680bdd1243dSDimitry Andric // As noted above, we create the function, even if it is empty.
681fcaf7f86SDimitry Andric // Module initializers for imported modules are emitted first.
682bdd1243dSDimitry Andric
683bdd1243dSDimitry Andric // Collect all the modules that we import
6845f757f3fSDimitry Andric llvm::SmallSetVector<Module *, 8> AllImports;
685fcaf7f86SDimitry Andric // Ones that we export
686fcaf7f86SDimitry Andric for (auto I : Primary->Exports)
6875f757f3fSDimitry Andric AllImports.insert(I.getPointer());
688fcaf7f86SDimitry Andric // Ones that we only import.
689fcaf7f86SDimitry Andric for (Module *M : Primary->Imports)
6905f757f3fSDimitry Andric AllImports.insert(M);
6915f757f3fSDimitry Andric // Ones that we import in the global module fragment or the private module
6925f757f3fSDimitry Andric // fragment.
6935f757f3fSDimitry Andric for (Module *SubM : Primary->submodules()) {
6945f757f3fSDimitry Andric assert((SubM->isGlobalModule() || SubM->isPrivateModule()) &&
6955f757f3fSDimitry Andric "The sub modules of C++20 module unit should only be global module "
6965f757f3fSDimitry Andric "fragments or private module framents.");
6975f757f3fSDimitry Andric assert(SubM->Exports.empty() &&
6985f757f3fSDimitry Andric "The global mdoule fragments and the private module fragments are "
6995f757f3fSDimitry Andric "not allowed to export import modules.");
7005f757f3fSDimitry Andric for (Module *M : SubM->Imports)
7015f757f3fSDimitry Andric AllImports.insert(M);
7025f757f3fSDimitry Andric }
703fcaf7f86SDimitry Andric
704fcaf7f86SDimitry Andric SmallVector<llvm::Function *, 8> ModuleInits;
705fcaf7f86SDimitry Andric for (Module *M : AllImports) {
70661cfbce3SDimitry Andric // No Itanium initializer in header like modules.
70761cfbce3SDimitry Andric if (M->isHeaderLikeModule())
708fcaf7f86SDimitry Andric continue; // TODO: warn of mixed use of module map modules and C++20?
7095f757f3fSDimitry Andric // We're allowed to skip the initialization if we are sure it doesn't
7105f757f3fSDimitry Andric // do any thing.
7115f757f3fSDimitry Andric if (!M->isNamedModuleInterfaceHasInit())
7125f757f3fSDimitry Andric continue;
713fcaf7f86SDimitry Andric llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
714fcaf7f86SDimitry Andric SmallString<256> FnName;
715fcaf7f86SDimitry Andric {
716fcaf7f86SDimitry Andric llvm::raw_svector_ostream Out(FnName);
717fcaf7f86SDimitry Andric cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
718fcaf7f86SDimitry Andric .mangleModuleInitializer(M, Out);
719fcaf7f86SDimitry Andric }
720fcaf7f86SDimitry Andric assert(!GetGlobalValue(FnName.str()) &&
721fcaf7f86SDimitry Andric "We should only have one use of the initializer call");
722fcaf7f86SDimitry Andric llvm::Function *Fn = llvm::Function::Create(
723fcaf7f86SDimitry Andric FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
724fcaf7f86SDimitry Andric ModuleInits.push_back(Fn);
725fcaf7f86SDimitry Andric }
726fcaf7f86SDimitry Andric
727fcaf7f86SDimitry Andric // Add any initializers with specified priority; this uses the same approach
728fcaf7f86SDimitry Andric // as EmitCXXGlobalInitFunc().
729fcaf7f86SDimitry Andric if (!PrioritizedCXXGlobalInits.empty()) {
730fcaf7f86SDimitry Andric SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
731fcaf7f86SDimitry Andric llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
732fcaf7f86SDimitry Andric PrioritizedCXXGlobalInits.end());
733fcaf7f86SDimitry Andric for (SmallVectorImpl<GlobalInitData>::iterator
734fcaf7f86SDimitry Andric I = PrioritizedCXXGlobalInits.begin(),
735fcaf7f86SDimitry Andric E = PrioritizedCXXGlobalInits.end();
736fcaf7f86SDimitry Andric I != E;) {
737fcaf7f86SDimitry Andric SmallVectorImpl<GlobalInitData>::iterator PrioE =
738fcaf7f86SDimitry Andric std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
739fcaf7f86SDimitry Andric
740fcaf7f86SDimitry Andric for (; I < PrioE; ++I)
741fcaf7f86SDimitry Andric ModuleInits.push_back(I->second);
742fcaf7f86SDimitry Andric }
743fcaf7f86SDimitry Andric }
744fcaf7f86SDimitry Andric
745fcaf7f86SDimitry Andric // Now append the ones without specified priority.
746bdd1243dSDimitry Andric for (auto *F : CXXGlobalInits)
747fcaf7f86SDimitry Andric ModuleInits.push_back(F);
748fcaf7f86SDimitry Andric
749fcaf7f86SDimitry Andric llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
750fcaf7f86SDimitry Andric const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
751fcaf7f86SDimitry Andric
752fcaf7f86SDimitry Andric // We now build the initializer for this module, which has a mangled name
753fcaf7f86SDimitry Andric // as per the Itanium ABI . The action of the initializer is guarded so that
754fcaf7f86SDimitry Andric // each init is run just once (even though a module might be imported
755fcaf7f86SDimitry Andric // multiple times via nested use).
756fcaf7f86SDimitry Andric llvm::Function *Fn;
757fcaf7f86SDimitry Andric {
758fcaf7f86SDimitry Andric SmallString<256> InitFnName;
759fcaf7f86SDimitry Andric llvm::raw_svector_ostream Out(InitFnName);
760fcaf7f86SDimitry Andric cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
761fcaf7f86SDimitry Andric .mangleModuleInitializer(Primary, Out);
762fcaf7f86SDimitry Andric Fn = CreateGlobalInitOrCleanUpFunction(
763fcaf7f86SDimitry Andric FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
764fcaf7f86SDimitry Andric llvm::GlobalVariable::ExternalLinkage);
765fcaf7f86SDimitry Andric
766bdd1243dSDimitry Andric // If we have a completely empty initializer then we do not want to create
767bdd1243dSDimitry Andric // the guard variable.
768bdd1243dSDimitry Andric ConstantAddress GuardAddr = ConstantAddress::invalid();
7695f757f3fSDimitry Andric if (!ModuleInits.empty()) {
770bdd1243dSDimitry Andric // Create the guard var.
771bdd1243dSDimitry Andric llvm::GlobalVariable *Guard = new llvm::GlobalVariable(
772bdd1243dSDimitry Andric getModule(), Int8Ty, /*isConstant=*/false,
773fcaf7f86SDimitry Andric llvm::GlobalVariable::InternalLinkage,
774bdd1243dSDimitry Andric llvm::ConstantInt::get(Int8Ty, 0), InitFnName.str() + "__in_chrg");
775fcaf7f86SDimitry Andric CharUnits GuardAlign = CharUnits::One();
776fcaf7f86SDimitry Andric Guard->setAlignment(GuardAlign.getAsAlign());
777bdd1243dSDimitry Andric GuardAddr = ConstantAddress(Guard, Int8Ty, GuardAlign);
778bdd1243dSDimitry Andric }
779bdd1243dSDimitry Andric CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits,
780bdd1243dSDimitry Andric GuardAddr);
781bdd1243dSDimitry Andric }
782fcaf7f86SDimitry Andric
783fcaf7f86SDimitry Andric // We allow for the case that a module object is added to a linked binary
784bdd1243dSDimitry Andric // without a specific call to the the initializer. This also ensures that
785fcaf7f86SDimitry Andric // implementation partition initializers are called when the partition
786fcaf7f86SDimitry Andric // is not imported as an interface.
787fcaf7f86SDimitry Andric AddGlobalCtor(Fn);
788fcaf7f86SDimitry Andric
789fcaf7f86SDimitry Andric // See the comment in EmitCXXGlobalInitFunc about OpenCL global init
790fcaf7f86SDimitry Andric // functions.
791fcaf7f86SDimitry Andric if (getLangOpts().OpenCL) {
792fcaf7f86SDimitry Andric GenKernelArgMetadata(Fn);
793fcaf7f86SDimitry Andric Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
794fcaf7f86SDimitry Andric }
795fcaf7f86SDimitry Andric
796fcaf7f86SDimitry Andric assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
797fcaf7f86SDimitry Andric getLangOpts().GPUAllowDeviceInit);
798fcaf7f86SDimitry Andric if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
799fcaf7f86SDimitry Andric Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
800fcaf7f86SDimitry Andric Fn->addFnAttr("device-init");
801fcaf7f86SDimitry Andric }
802fcaf7f86SDimitry Andric
803bdd1243dSDimitry Andric // We are done with the inits.
804bdd1243dSDimitry Andric AllImports.clear();
805bdd1243dSDimitry Andric PrioritizedCXXGlobalInits.clear();
806bdd1243dSDimitry Andric CXXGlobalInits.clear();
807fcaf7f86SDimitry Andric ModuleInits.clear();
808fcaf7f86SDimitry Andric }
809fcaf7f86SDimitry Andric
getTransformedFileName(llvm::Module & M)8105ffd83dbSDimitry Andric static SmallString<128> getTransformedFileName(llvm::Module &M) {
8115ffd83dbSDimitry Andric SmallString<128> FileName = llvm::sys::path::filename(M.getName());
8125ffd83dbSDimitry Andric
8135ffd83dbSDimitry Andric if (FileName.empty())
8145ffd83dbSDimitry Andric FileName = "<null>";
8155ffd83dbSDimitry Andric
8165ffd83dbSDimitry Andric for (size_t i = 0; i < FileName.size(); ++i) {
8175ffd83dbSDimitry Andric // Replace everything that's not [a-zA-Z0-9._] with a _. This set happens
8185ffd83dbSDimitry Andric // to be the set of C preprocessing numbers.
8195ffd83dbSDimitry Andric if (!isPreprocessingNumberBody(FileName[i]))
8205ffd83dbSDimitry Andric FileName[i] = '_';
8215ffd83dbSDimitry Andric }
8225ffd83dbSDimitry Andric
8235ffd83dbSDimitry Andric return FileName;
8245ffd83dbSDimitry Andric }
8255ffd83dbSDimitry Andric
getPrioritySuffix(unsigned int Priority)826fe6060f1SDimitry Andric static std::string getPrioritySuffix(unsigned int Priority) {
827fe6060f1SDimitry Andric assert(Priority <= 65535 && "Priority should always be <= 65535.");
828fe6060f1SDimitry Andric
829fe6060f1SDimitry Andric // Compute the function suffix from priority. Prepend with zeroes to make
830fe6060f1SDimitry Andric // sure the function names are also ordered as priorities.
831fe6060f1SDimitry Andric std::string PrioritySuffix = llvm::utostr(Priority);
832fe6060f1SDimitry Andric PrioritySuffix = std::string(6 - PrioritySuffix.size(), '0') + PrioritySuffix;
833fe6060f1SDimitry Andric
834fe6060f1SDimitry Andric return PrioritySuffix;
835fe6060f1SDimitry Andric }
836fe6060f1SDimitry Andric
8370b57cec5SDimitry Andric void
EmitCXXGlobalInitFunc()8380b57cec5SDimitry Andric CodeGenModule::EmitCXXGlobalInitFunc() {
8390b57cec5SDimitry Andric while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
8400b57cec5SDimitry Andric CXXGlobalInits.pop_back();
8410b57cec5SDimitry Andric
842fcaf7f86SDimitry Andric // When we import C++20 modules, we must run their initializers first.
843fcaf7f86SDimitry Andric SmallVector<llvm::Function *, 8> ModuleInits;
844fcaf7f86SDimitry Andric if (CXX20ModuleInits)
845fcaf7f86SDimitry Andric for (Module *M : ImportedModules) {
84661cfbce3SDimitry Andric // No Itanium initializer in header like modules.
84761cfbce3SDimitry Andric if (M->isHeaderLikeModule())
848fcaf7f86SDimitry Andric continue;
849*0fca6ea1SDimitry Andric // We're allowed to skip the initialization if we are sure it doesn't
850*0fca6ea1SDimitry Andric // do any thing.
851*0fca6ea1SDimitry Andric if (!M->isNamedModuleInterfaceHasInit())
852*0fca6ea1SDimitry Andric continue;
853fcaf7f86SDimitry Andric llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
854fcaf7f86SDimitry Andric SmallString<256> FnName;
855fcaf7f86SDimitry Andric {
856fcaf7f86SDimitry Andric llvm::raw_svector_ostream Out(FnName);
857fcaf7f86SDimitry Andric cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
858fcaf7f86SDimitry Andric .mangleModuleInitializer(M, Out);
859fcaf7f86SDimitry Andric }
860fcaf7f86SDimitry Andric assert(!GetGlobalValue(FnName.str()) &&
861fcaf7f86SDimitry Andric "We should only have one use of the initializer call");
862fcaf7f86SDimitry Andric llvm::Function *Fn = llvm::Function::Create(
863fcaf7f86SDimitry Andric FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
864fcaf7f86SDimitry Andric ModuleInits.push_back(Fn);
865fcaf7f86SDimitry Andric }
866fcaf7f86SDimitry Andric
867fcaf7f86SDimitry Andric if (ModuleInits.empty() && CXXGlobalInits.empty() &&
868fcaf7f86SDimitry Andric PrioritizedCXXGlobalInits.empty())
8690b57cec5SDimitry Andric return;
8700b57cec5SDimitry Andric
8710b57cec5SDimitry Andric llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
8720b57cec5SDimitry Andric const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
8730b57cec5SDimitry Andric
8745ffd83dbSDimitry Andric // Create our global prioritized initialization function.
8750b57cec5SDimitry Andric if (!PrioritizedCXXGlobalInits.empty()) {
8760b57cec5SDimitry Andric SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
8770b57cec5SDimitry Andric llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
8780b57cec5SDimitry Andric PrioritizedCXXGlobalInits.end());
8790b57cec5SDimitry Andric // Iterate over "chunks" of ctors with same priority and emit each chunk
8800b57cec5SDimitry Andric // into separate function. Note - everything is sorted first by priority,
8810b57cec5SDimitry Andric // second - by lex order, so we emit ctor functions in proper order.
8820b57cec5SDimitry Andric for (SmallVectorImpl<GlobalInitData >::iterator
8830b57cec5SDimitry Andric I = PrioritizedCXXGlobalInits.begin(),
8840b57cec5SDimitry Andric E = PrioritizedCXXGlobalInits.end(); I != E; ) {
8850b57cec5SDimitry Andric SmallVectorImpl<GlobalInitData >::iterator
8860b57cec5SDimitry Andric PrioE = std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
8870b57cec5SDimitry Andric
8880b57cec5SDimitry Andric LocalCXXGlobalInits.clear();
889fe6060f1SDimitry Andric
890fe6060f1SDimitry Andric unsigned int Priority = I->first.priority;
8915ffd83dbSDimitry Andric llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
892fe6060f1SDimitry Andric FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI);
8930b57cec5SDimitry Andric
894fcaf7f86SDimitry Andric // Prepend the module inits to the highest priority set.
895fcaf7f86SDimitry Andric if (!ModuleInits.empty()) {
896bdd1243dSDimitry Andric for (auto *F : ModuleInits)
897fcaf7f86SDimitry Andric LocalCXXGlobalInits.push_back(F);
898fcaf7f86SDimitry Andric ModuleInits.clear();
899fcaf7f86SDimitry Andric }
900fcaf7f86SDimitry Andric
9010b57cec5SDimitry Andric for (; I < PrioE; ++I)
9020b57cec5SDimitry Andric LocalCXXGlobalInits.push_back(I->second);
9030b57cec5SDimitry Andric
9040b57cec5SDimitry Andric CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, LocalCXXGlobalInits);
9050b57cec5SDimitry Andric AddGlobalCtor(Fn, Priority);
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric PrioritizedCXXGlobalInits.clear();
9080b57cec5SDimitry Andric }
9090b57cec5SDimitry Andric
910fcaf7f86SDimitry Andric if (getCXXABI().useSinitAndSterm() && ModuleInits.empty() &&
911fcaf7f86SDimitry Andric CXXGlobalInits.empty())
9125ffd83dbSDimitry Andric return;
9130b57cec5SDimitry Andric
914bdd1243dSDimitry Andric for (auto *F : CXXGlobalInits)
915fcaf7f86SDimitry Andric ModuleInits.push_back(F);
916fcaf7f86SDimitry Andric CXXGlobalInits.clear();
917fcaf7f86SDimitry Andric
9185ffd83dbSDimitry Andric // Include the filename in the symbol name. Including "sub_" matches gcc
9195ffd83dbSDimitry Andric // and makes sure these symbols appear lexicographically behind the symbols
92006c3fb27SDimitry Andric // with priority emitted above. Module implementation units behave the same
92106c3fb27SDimitry Andric // way as a non-modular TU with imports.
922fcaf7f86SDimitry Andric llvm::Function *Fn;
92306c3fb27SDimitry Andric if (CXX20ModuleInits && getContext().getCurrentNamedModule() &&
92406c3fb27SDimitry Andric !getContext().getCurrentNamedModule()->isModuleImplementation()) {
925fcaf7f86SDimitry Andric SmallString<256> InitFnName;
926fcaf7f86SDimitry Andric llvm::raw_svector_ostream Out(InitFnName);
927fcaf7f86SDimitry Andric cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
92806c3fb27SDimitry Andric .mangleModuleInitializer(getContext().getCurrentNamedModule(), Out);
929fcaf7f86SDimitry Andric Fn = CreateGlobalInitOrCleanUpFunction(
930fcaf7f86SDimitry Andric FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
931fcaf7f86SDimitry Andric llvm::GlobalVariable::ExternalLinkage);
932fcaf7f86SDimitry Andric } else
933fcaf7f86SDimitry Andric Fn = CreateGlobalInitOrCleanUpFunction(
934fcaf7f86SDimitry Andric FTy,
935fcaf7f86SDimitry Andric llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
936e8d8bef9SDimitry Andric FI);
9370b57cec5SDimitry Andric
938fcaf7f86SDimitry Andric CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits);
9390b57cec5SDimitry Andric AddGlobalCtor(Fn);
9400b57cec5SDimitry Andric
9410b57cec5SDimitry Andric // In OpenCL global init functions must be converted to kernels in order to
9420b57cec5SDimitry Andric // be able to launch them from the host.
9430b57cec5SDimitry Andric // FIXME: Some more work might be needed to handle destructors correctly.
9440b57cec5SDimitry Andric // Current initialization function makes use of function pointers callbacks.
9450b57cec5SDimitry Andric // We can't support function pointers especially between host and device.
9460b57cec5SDimitry Andric // However it seems global destruction has little meaning without any
9470b57cec5SDimitry Andric // dynamic resource allocation on the device and program scope variables are
9480b57cec5SDimitry Andric // destroyed by the runtime when program is released.
9490b57cec5SDimitry Andric if (getLangOpts().OpenCL) {
95081ad6265SDimitry Andric GenKernelArgMetadata(Fn);
9510b57cec5SDimitry Andric Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
9520b57cec5SDimitry Andric }
9530b57cec5SDimitry Andric
954fe6060f1SDimitry Andric assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
955fe6060f1SDimitry Andric getLangOpts().GPUAllowDeviceInit);
956fe6060f1SDimitry Andric if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
957480093f4SDimitry Andric Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
958480093f4SDimitry Andric Fn->addFnAttr("device-init");
959480093f4SDimitry Andric }
960480093f4SDimitry Andric
961fcaf7f86SDimitry Andric ModuleInits.clear();
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric
EmitCXXGlobalCleanUpFunc()9645ffd83dbSDimitry Andric void CodeGenModule::EmitCXXGlobalCleanUpFunc() {
965fe6060f1SDimitry Andric if (CXXGlobalDtorsOrStermFinalizers.empty() &&
966fe6060f1SDimitry Andric PrioritizedCXXStermFinalizers.empty())
9670b57cec5SDimitry Andric return;
9680b57cec5SDimitry Andric
9690b57cec5SDimitry Andric llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
9700b57cec5SDimitry Andric const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
9710b57cec5SDimitry Andric
972fe6060f1SDimitry Andric // Create our global prioritized cleanup function.
973fe6060f1SDimitry Andric if (!PrioritizedCXXStermFinalizers.empty()) {
974fe6060f1SDimitry Andric SmallVector<CXXGlobalDtorsOrStermFinalizer_t, 8> LocalCXXStermFinalizers;
975fe6060f1SDimitry Andric llvm::array_pod_sort(PrioritizedCXXStermFinalizers.begin(),
976fe6060f1SDimitry Andric PrioritizedCXXStermFinalizers.end());
977fe6060f1SDimitry Andric // Iterate over "chunks" of dtors with same priority and emit each chunk
978fe6060f1SDimitry Andric // into separate function. Note - everything is sorted first by priority,
979fe6060f1SDimitry Andric // second - by lex order, so we emit dtor functions in proper order.
980fe6060f1SDimitry Andric for (SmallVectorImpl<StermFinalizerData>::iterator
981fe6060f1SDimitry Andric I = PrioritizedCXXStermFinalizers.begin(),
982fe6060f1SDimitry Andric E = PrioritizedCXXStermFinalizers.end();
983fe6060f1SDimitry Andric I != E;) {
984fe6060f1SDimitry Andric SmallVectorImpl<StermFinalizerData>::iterator PrioE =
985fe6060f1SDimitry Andric std::upper_bound(I + 1, E, *I, StermFinalizerPriorityCmp());
986fe6060f1SDimitry Andric
987fe6060f1SDimitry Andric LocalCXXStermFinalizers.clear();
988fe6060f1SDimitry Andric
989fe6060f1SDimitry Andric unsigned int Priority = I->first.priority;
990fe6060f1SDimitry Andric llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
991fe6060f1SDimitry Andric FTy, "_GLOBAL__a_" + getPrioritySuffix(Priority), FI);
992fe6060f1SDimitry Andric
993fe6060f1SDimitry Andric for (; I < PrioE; ++I) {
994fe6060f1SDimitry Andric llvm::FunctionCallee DtorFn = I->second;
995fe6060f1SDimitry Andric LocalCXXStermFinalizers.emplace_back(DtorFn.getFunctionType(),
996fe6060f1SDimitry Andric DtorFn.getCallee(), nullptr);
997fe6060f1SDimitry Andric }
998fe6060f1SDimitry Andric
999fe6060f1SDimitry Andric CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc(
1000fe6060f1SDimitry Andric Fn, LocalCXXStermFinalizers);
1001fe6060f1SDimitry Andric AddGlobalDtor(Fn, Priority);
1002fe6060f1SDimitry Andric }
1003fe6060f1SDimitry Andric PrioritizedCXXStermFinalizers.clear();
1004fe6060f1SDimitry Andric }
1005fe6060f1SDimitry Andric
1006fe6060f1SDimitry Andric if (CXXGlobalDtorsOrStermFinalizers.empty())
1007fe6060f1SDimitry Andric return;
1008fe6060f1SDimitry Andric
10095ffd83dbSDimitry Andric // Create our global cleanup function.
1010e8d8bef9SDimitry Andric llvm::Function *Fn =
1011e8d8bef9SDimitry Andric CreateGlobalInitOrCleanUpFunction(FTy, "_GLOBAL__D_a", FI);
10125ffd83dbSDimitry Andric
10135ffd83dbSDimitry Andric CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc(
10145ffd83dbSDimitry Andric Fn, CXXGlobalDtorsOrStermFinalizers);
10150b57cec5SDimitry Andric AddGlobalDtor(Fn);
10165ffd83dbSDimitry Andric CXXGlobalDtorsOrStermFinalizers.clear();
10170b57cec5SDimitry Andric }
10180b57cec5SDimitry Andric
10190b57cec5SDimitry Andric /// Emit the code necessary to initialize the given global variable.
GenerateCXXGlobalVarDeclInitFunc(llvm::Function * Fn,const VarDecl * D,llvm::GlobalVariable * Addr,bool PerformInit)10200b57cec5SDimitry Andric void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
10210b57cec5SDimitry Andric const VarDecl *D,
10220b57cec5SDimitry Andric llvm::GlobalVariable *Addr,
10230b57cec5SDimitry Andric bool PerformInit) {
10240b57cec5SDimitry Andric // Check if we need to emit debug info for variable initializer.
10250b57cec5SDimitry Andric if (D->hasAttr<NoDebugAttr>())
10260b57cec5SDimitry Andric DebugInfo = nullptr; // disable debug info indefinitely for this function
10270b57cec5SDimitry Andric
10280b57cec5SDimitry Andric CurEHLocation = D->getBeginLoc();
10290b57cec5SDimitry Andric
10300b57cec5SDimitry Andric StartFunction(GlobalDecl(D, DynamicInitKind::Initializer),
10310b57cec5SDimitry Andric getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(),
1032e8d8bef9SDimitry Andric FunctionArgList());
1033e8d8bef9SDimitry Andric // Emit an artificial location for this function.
1034e8d8bef9SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(*this);
10350b57cec5SDimitry Andric
10360b57cec5SDimitry Andric // Use guarded initialization if the global variable is weak. This
10370b57cec5SDimitry Andric // occurs for, e.g., instantiated static data members and
10380b57cec5SDimitry Andric // definitions explicitly marked weak.
10390b57cec5SDimitry Andric //
10400b57cec5SDimitry Andric // Also use guarded initialization for a variable with dynamic TLS and
10410b57cec5SDimitry Andric // unordered initialization. (If the initialization is ordered, the ABI
10420b57cec5SDimitry Andric // layer will guard the whole-TU initialization for us.)
10430b57cec5SDimitry Andric if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage() ||
10440b57cec5SDimitry Andric (D->getTLSKind() == VarDecl::TLS_Dynamic &&
10450b57cec5SDimitry Andric isTemplateInstantiation(D->getTemplateSpecializationKind()))) {
10460b57cec5SDimitry Andric EmitCXXGuardedInit(*D, Addr, PerformInit);
10470b57cec5SDimitry Andric } else {
10480b57cec5SDimitry Andric EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);
10490b57cec5SDimitry Andric }
10500b57cec5SDimitry Andric
1051bdd1243dSDimitry Andric if (getLangOpts().HLSL)
1052bdd1243dSDimitry Andric CGM.getHLSLRuntime().annotateHLSLResource(D, Addr);
1053bdd1243dSDimitry Andric
10540b57cec5SDimitry Andric FinishFunction();
10550b57cec5SDimitry Andric }
10560b57cec5SDimitry Andric
10570b57cec5SDimitry Andric void
GenerateCXXGlobalInitFunc(llvm::Function * Fn,ArrayRef<llvm::Function * > Decls,ConstantAddress Guard)10580b57cec5SDimitry Andric CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
10590b57cec5SDimitry Andric ArrayRef<llvm::Function *> Decls,
10600b57cec5SDimitry Andric ConstantAddress Guard) {
10610b57cec5SDimitry Andric {
10620b57cec5SDimitry Andric auto NL = ApplyDebugLocation::CreateEmpty(*this);
10630b57cec5SDimitry Andric StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
10640b57cec5SDimitry Andric getTypes().arrangeNullaryFunction(), FunctionArgList());
10650b57cec5SDimitry Andric // Emit an artificial location for this function.
10660b57cec5SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(*this);
10670b57cec5SDimitry Andric
10680b57cec5SDimitry Andric llvm::BasicBlock *ExitBlock = nullptr;
10690b57cec5SDimitry Andric if (Guard.isValid()) {
10700b57cec5SDimitry Andric // If we have a guard variable, check whether we've already performed
10710b57cec5SDimitry Andric // these initializations. This happens for TLS initialization functions.
10720b57cec5SDimitry Andric llvm::Value *GuardVal = Builder.CreateLoad(Guard);
10730b57cec5SDimitry Andric llvm::Value *Uninit = Builder.CreateIsNull(GuardVal,
10740b57cec5SDimitry Andric "guard.uninitialized");
10750b57cec5SDimitry Andric llvm::BasicBlock *InitBlock = createBasicBlock("init");
10760b57cec5SDimitry Andric ExitBlock = createBasicBlock("exit");
10770b57cec5SDimitry Andric EmitCXXGuardedInitBranch(Uninit, InitBlock, ExitBlock,
10780b57cec5SDimitry Andric GuardKind::TlsGuard, nullptr);
10790b57cec5SDimitry Andric EmitBlock(InitBlock);
10800b57cec5SDimitry Andric // Mark as initialized before initializing anything else. If the
10810b57cec5SDimitry Andric // initializers use previously-initialized thread_local vars, that's
10820b57cec5SDimitry Andric // probably supposed to be OK, but the standard doesn't say.
10830b57cec5SDimitry Andric Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);
10840b57cec5SDimitry Andric
10850b57cec5SDimitry Andric // The guard variable can't ever change again.
10860b57cec5SDimitry Andric EmitInvariantStart(
10870b57cec5SDimitry Andric Guard.getPointer(),
10880b57cec5SDimitry Andric CharUnits::fromQuantity(
10890b57cec5SDimitry Andric CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())));
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric
10920b57cec5SDimitry Andric RunCleanupsScope Scope(*this);
10930b57cec5SDimitry Andric
10940b57cec5SDimitry Andric // When building in Objective-C++ ARC mode, create an autorelease pool
10950b57cec5SDimitry Andric // around the global initializers.
10960b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) {
10970b57cec5SDimitry Andric llvm::Value *token = EmitObjCAutoreleasePoolPush();
10980b57cec5SDimitry Andric EmitObjCAutoreleasePoolCleanup(token);
10990b57cec5SDimitry Andric }
11000b57cec5SDimitry Andric
11010b57cec5SDimitry Andric for (unsigned i = 0, e = Decls.size(); i != e; ++i)
11020b57cec5SDimitry Andric if (Decls[i])
11030b57cec5SDimitry Andric EmitRuntimeCall(Decls[i]);
11040b57cec5SDimitry Andric
11050b57cec5SDimitry Andric Scope.ForceCleanup();
11060b57cec5SDimitry Andric
11070b57cec5SDimitry Andric if (ExitBlock) {
11080b57cec5SDimitry Andric Builder.CreateBr(ExitBlock);
11090b57cec5SDimitry Andric EmitBlock(ExitBlock);
11100b57cec5SDimitry Andric }
11110b57cec5SDimitry Andric }
11120b57cec5SDimitry Andric
11130b57cec5SDimitry Andric FinishFunction();
11140b57cec5SDimitry Andric }
11150b57cec5SDimitry Andric
GenerateCXXGlobalCleanUpFunc(llvm::Function * Fn,ArrayRef<std::tuple<llvm::FunctionType *,llvm::WeakTrackingVH,llvm::Constant * >> DtorsOrStermFinalizers)11165ffd83dbSDimitry Andric void CodeGenFunction::GenerateCXXGlobalCleanUpFunc(
11170b57cec5SDimitry Andric llvm::Function *Fn,
1118fe6060f1SDimitry Andric ArrayRef<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,
1119fe6060f1SDimitry Andric llvm::Constant *>>
1120fe6060f1SDimitry Andric DtorsOrStermFinalizers) {
11210b57cec5SDimitry Andric {
11220b57cec5SDimitry Andric auto NL = ApplyDebugLocation::CreateEmpty(*this);
11230b57cec5SDimitry Andric StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
11240b57cec5SDimitry Andric getTypes().arrangeNullaryFunction(), FunctionArgList());
11250b57cec5SDimitry Andric // Emit an artificial location for this function.
11260b57cec5SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(*this);
11270b57cec5SDimitry Andric
11285ffd83dbSDimitry Andric // Emit the cleanups, in reverse order from construction.
11295ffd83dbSDimitry Andric for (unsigned i = 0, e = DtorsOrStermFinalizers.size(); i != e; ++i) {
11300b57cec5SDimitry Andric llvm::FunctionType *CalleeTy;
11310b57cec5SDimitry Andric llvm::Value *Callee;
11320b57cec5SDimitry Andric llvm::Constant *Arg;
11335ffd83dbSDimitry Andric std::tie(CalleeTy, Callee, Arg) = DtorsOrStermFinalizers[e - i - 1];
11345ffd83dbSDimitry Andric
11355ffd83dbSDimitry Andric llvm::CallInst *CI = nullptr;
11365ffd83dbSDimitry Andric if (Arg == nullptr) {
11375ffd83dbSDimitry Andric assert(
11385ffd83dbSDimitry Andric CGM.getCXXABI().useSinitAndSterm() &&
11395ffd83dbSDimitry Andric "Arg could not be nullptr unless using sinit and sterm functions.");
11405ffd83dbSDimitry Andric CI = Builder.CreateCall(CalleeTy, Callee);
11415ffd83dbSDimitry Andric } else
11425ffd83dbSDimitry Andric CI = Builder.CreateCall(CalleeTy, Callee, Arg);
11435ffd83dbSDimitry Andric
11440b57cec5SDimitry Andric // Make sure the call and the callee agree on calling convention.
11450b57cec5SDimitry Andric if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
11460b57cec5SDimitry Andric CI->setCallingConv(F->getCallingConv());
11470b57cec5SDimitry Andric }
11480b57cec5SDimitry Andric }
11490b57cec5SDimitry Andric
11500b57cec5SDimitry Andric FinishFunction();
11510b57cec5SDimitry Andric }
11520b57cec5SDimitry Andric
11530b57cec5SDimitry Andric /// generateDestroyHelper - Generates a helper function which, when
11540b57cec5SDimitry Andric /// invoked, destroys the given object. The address of the object
11550b57cec5SDimitry Andric /// should be in global memory.
generateDestroyHelper(Address addr,QualType type,Destroyer * destroyer,bool useEHCleanupForArray,const VarDecl * VD)11560b57cec5SDimitry Andric llvm::Function *CodeGenFunction::generateDestroyHelper(
11570b57cec5SDimitry Andric Address addr, QualType type, Destroyer *destroyer,
11580b57cec5SDimitry Andric bool useEHCleanupForArray, const VarDecl *VD) {
11590b57cec5SDimitry Andric FunctionArgList args;
11600b57cec5SDimitry Andric ImplicitParamDecl Dst(getContext(), getContext().VoidPtrTy,
11615f757f3fSDimitry Andric ImplicitParamKind::Other);
11620b57cec5SDimitry Andric args.push_back(&Dst);
11630b57cec5SDimitry Andric
11640b57cec5SDimitry Andric const CGFunctionInfo &FI =
11650b57cec5SDimitry Andric CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, args);
11660b57cec5SDimitry Andric llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
11675ffd83dbSDimitry Andric llvm::Function *fn = CGM.CreateGlobalInitOrCleanUpFunction(
11680b57cec5SDimitry Andric FTy, "__cxx_global_array_dtor", FI, VD->getLocation());
11690b57cec5SDimitry Andric
11700b57cec5SDimitry Andric CurEHLocation = VD->getBeginLoc();
11710b57cec5SDimitry Andric
1172e8d8bef9SDimitry Andric StartFunction(GlobalDecl(VD, DynamicInitKind::GlobalArrayDestructor),
1173e8d8bef9SDimitry Andric getContext().VoidTy, fn, FI, args);
1174e8d8bef9SDimitry Andric // Emit an artificial location for this function.
1175e8d8bef9SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(*this);
11760b57cec5SDimitry Andric
11770b57cec5SDimitry Andric emitDestroy(addr, type, destroyer, useEHCleanupForArray);
11780b57cec5SDimitry Andric
11790b57cec5SDimitry Andric FinishFunction();
11800b57cec5SDimitry Andric
11810b57cec5SDimitry Andric return fn;
11820b57cec5SDimitry Andric }
1183