llvm-project
1176 строк · 46.6 Кб
1//===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code dealing with code generation of C++ declarations
10//
11//===----------------------------------------------------------------------===//
12
13#include "CGCXXABI.h"14#include "CGHLSLRuntime.h"15#include "CGObjCRuntime.h"16#include "CGOpenMPRuntime.h"17#include "CodeGenFunction.h"18#include "TargetInfo.h"19#include "clang/AST/Attr.h"20#include "clang/Basic/LangOptions.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/IR/Intrinsics.h"23#include "llvm/IR/MDBuilder.h"24#include "llvm/Support/Path.h"25
26using namespace clang;27using namespace CodeGen;28
29static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,30ConstantAddress DeclPtr) {31assert(32(D.hasGlobalStorage() ||33(D.hasLocalStorage() && CGF.getContext().getLangOpts().OpenCLCPlusPlus)) &&34"VarDecl must have global or local (in the case of OpenCL) storage!");35assert(!D.getType()->isReferenceType() &&36"Should not call EmitDeclInit on a reference!");37
38QualType type = D.getType();39LValue lv = CGF.MakeAddrLValue(DeclPtr, type);40
41const Expr *Init = D.getInit();42switch (CGF.getEvaluationKind(type)) {43case TEK_Scalar: {44CodeGenModule &CGM = CGF.CGM;45if (lv.isObjCStrong())46CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init),47DeclPtr, D.getTLSKind());48else if (lv.isObjCWeak())49CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init),50DeclPtr);51else52CGF.EmitScalarInit(Init, &D, lv, false);53return;54}55case TEK_Complex:56CGF.EmitComplexExprIntoLValue(Init, lv, /*isInit*/ true);57return;58case TEK_Aggregate:59CGF.EmitAggExpr(Init,60AggValueSlot::forLValue(lv, AggValueSlot::IsDestructed,61AggValueSlot::DoesNotNeedGCBarriers,62AggValueSlot::IsNotAliased,63AggValueSlot::DoesNotOverlap));64return;65}66llvm_unreachable("bad evaluation kind");67}
68
69/// Emit code to cause the destruction of the given variable with
70/// static storage duration.
71static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,72ConstantAddress Addr) {73// Honor __attribute__((no_destroy)) and bail instead of attempting74// to emit a reference to a possibly nonexistent destructor, which75// in turn can cause a crash. This will result in a global constructor76// that isn't balanced out by a destructor call as intended by the77// attribute. This also checks for -fno-c++-static-destructors and78// bails even if the attribute is not present.79QualType::DestructionKind DtorKind = D.needsDestruction(CGF.getContext());80
81// FIXME: __attribute__((cleanup)) ?82
83switch (DtorKind) {84case QualType::DK_none:85return;86
87case QualType::DK_cxx_destructor:88break;89
90case QualType::DK_objc_strong_lifetime:91case QualType::DK_objc_weak_lifetime:92case QualType::DK_nontrivial_c_struct:93// We don't care about releasing objects during process teardown.94assert(!D.getTLSKind() && "should have rejected this");95return;96}97
98llvm::FunctionCallee Func;99llvm::Constant *Argument;100
101CodeGenModule &CGM = CGF.CGM;102QualType Type = D.getType();103
104// Special-case non-array C++ destructors, if they have the right signature.105// Under some ABIs, destructors return this instead of void, and cannot be106// passed directly to __cxa_atexit if the target does not allow this107// mismatch.108const CXXRecordDecl *Record = Type->getAsCXXRecordDecl();109bool CanRegisterDestructor =110Record && (!CGM.getCXXABI().HasThisReturn(111GlobalDecl(Record->getDestructor(), Dtor_Complete)) ||112CGM.getCXXABI().canCallMismatchedFunctionType());113// If __cxa_atexit is disabled via a flag, a different helper function is114// generated elsewhere which uses atexit instead, and it takes the destructor115// directly.116bool UsingExternalHelper = !CGM.getCodeGenOpts().CXAAtExit;117if (Record && (CanRegisterDestructor || UsingExternalHelper)) {118assert(!Record->hasTrivialDestructor());119CXXDestructorDecl *Dtor = Record->getDestructor();120
121Func = CGM.getAddrAndTypeOfCXXStructor(GlobalDecl(Dtor, Dtor_Complete));122if (CGF.getContext().getLangOpts().OpenCL) {123auto DestAS =124CGM.getTargetCodeGenInfo().getAddrSpaceOfCxaAtexitPtrParam();125auto DestTy = llvm::PointerType::get(126CGM.getLLVMContext(), CGM.getContext().getTargetAddressSpace(DestAS));127auto SrcAS = D.getType().getQualifiers().getAddressSpace();128if (DestAS == SrcAS)129Argument = Addr.getPointer();130else131// FIXME: On addr space mismatch we are passing NULL. The generation132// of the global destructor function should be adjusted accordingly.133Argument = llvm::ConstantPointerNull::get(DestTy);134} else {135Argument = Addr.getPointer();136}137// Otherwise, the standard logic requires a helper function.138} else {139Addr = Addr.withElementType(CGF.ConvertTypeForMem(Type));140Func = CodeGenFunction(CGM)141.generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind),142CGF.needsEHCleanup(DtorKind), &D);143Argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);144}145
146CGM.getCXXABI().registerGlobalDtor(CGF, D, Func, Argument);147}
148
149/// Emit code to cause the variable at the given address to be considered as
150/// constant from this point onwards.
151static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D,152llvm::Constant *Addr) {153return CGF.EmitInvariantStart(154Addr, CGF.getContext().getTypeSizeInChars(D.getType()));155}
156
157void CodeGenFunction::EmitInvariantStart(llvm::Constant *Addr, CharUnits Size) {158// Do not emit the intrinsic if we're not optimizing.159if (!CGM.getCodeGenOpts().OptimizationLevel)160return;161
162// Grab the llvm.invariant.start intrinsic.163llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;164// Overloaded address space type.165assert(Addr->getType()->isPointerTy() && "Address must be a pointer");166llvm::Type *ObjectPtr[1] = {Addr->getType()};167llvm::Function *InvariantStart = CGM.getIntrinsic(InvStartID, ObjectPtr);168
169// Emit a call with the size in bytes of the object.170uint64_t Width = Size.getQuantity();171llvm::Value *Args[2] = {llvm::ConstantInt::getSigned(Int64Ty, Width), Addr};172Builder.CreateCall(InvariantStart, Args);173}
174
175void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,176llvm::GlobalVariable *GV,177bool PerformInit) {178
179const Expr *Init = D.getInit();180QualType T = D.getType();181
182// The address space of a static local variable (DeclPtr) may be different183// from the address space of the "this" argument of the constructor. In that184// case, we need an addrspacecast before calling the constructor.185//186// struct StructWithCtor {187// __device__ StructWithCtor() {...}188// };189// __device__ void foo() {190// __shared__ StructWithCtor s;191// ...192// }193//194// For example, in the above CUDA code, the static local variable s has a195// "shared" address space qualifier, but the constructor of StructWithCtor196// expects "this" in the "generic" address space.197unsigned ExpectedAddrSpace = getTypes().getTargetAddressSpace(T);198unsigned ActualAddrSpace = GV->getAddressSpace();199llvm::Constant *DeclPtr = GV;200if (ActualAddrSpace != ExpectedAddrSpace) {201llvm::PointerType *PTy =202llvm::PointerType::get(getLLVMContext(), ExpectedAddrSpace);203DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy);204}205
206ConstantAddress DeclAddr(207DeclPtr, GV->getValueType(), getContext().getDeclAlign(&D));208
209if (!T->isReferenceType()) {210if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&211D.hasAttr<OMPThreadPrivateDeclAttr>()) {212(void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition(213&D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),214PerformInit, this);215}216bool NeedsDtor =217D.needsDestruction(getContext()) == QualType::DK_cxx_destructor;218if (PerformInit)219EmitDeclInit(*this, D, DeclAddr);220if (D.getType().isConstantStorage(getContext(), true, !NeedsDtor))221EmitDeclInvariant(*this, D, DeclPtr);222else223EmitDeclDestroy(*this, D, DeclAddr);224return;225}226
227assert(PerformInit && "cannot have constant initializer which needs "228"destruction for reference");229RValue RV = EmitReferenceBindingToExpr(Init);230EmitStoreOfScalar(RV.getScalarVal(), DeclAddr, false, T);231}
232
233/// Create a stub function, suitable for being passed to atexit,
234/// which passes the given address to the given destructor function.
235llvm::Function *CodeGenFunction::createAtExitStub(const VarDecl &VD,236llvm::FunctionCallee dtor,237llvm::Constant *addr) {238// Get the destructor function type, void(*)(void).239llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false);240SmallString<256> FnName;241{242llvm::raw_svector_ostream Out(FnName);243CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out);244}245
246const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();247llvm::Function *fn = CGM.CreateGlobalInitOrCleanUpFunction(248ty, FnName.str(), FI, VD.getLocation());249
250CodeGenFunction CGF(CGM);251
252CGF.StartFunction(GlobalDecl(&VD, DynamicInitKind::AtExit),253CGM.getContext().VoidTy, fn, FI, FunctionArgList(),254VD.getLocation(), VD.getInit()->getExprLoc());255// Emit an artificial location for this function.256auto AL = ApplyDebugLocation::CreateArtificial(CGF);257
258llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);259
260// Make sure the call and the callee agree on calling convention.261if (auto *dtorFn = dyn_cast<llvm::Function>(262dtor.getCallee()->stripPointerCastsAndAliases()))263call->setCallingConv(dtorFn->getCallingConv());264
265CGF.FinishFunction();266
267return fn;268}
269
270/// Create a stub function, suitable for being passed to __pt_atexit_np,
271/// which passes the given address to the given destructor function.
272llvm::Function *CodeGenFunction::createTLSAtExitStub(273const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr,274llvm::FunctionCallee &AtExit) {275SmallString<256> FnName;276{277llvm::raw_svector_ostream Out(FnName);278CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&D, Out);279}280
281const CGFunctionInfo &FI = CGM.getTypes().arrangeLLVMFunctionInfo(282getContext().IntTy, FnInfoOpts::None, {getContext().IntTy},283FunctionType::ExtInfo(), {}, RequiredArgs::All);284
285// Get the stub function type, int(*)(int,...).286llvm::FunctionType *StubTy =287llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy}, true);288
289llvm::Function *DtorStub = CGM.CreateGlobalInitOrCleanUpFunction(290StubTy, FnName.str(), FI, D.getLocation());291
292CodeGenFunction CGF(CGM);293
294FunctionArgList Args;295ImplicitParamDecl IPD(CGM.getContext(), CGM.getContext().IntTy,296ImplicitParamKind::Other);297Args.push_back(&IPD);298QualType ResTy = CGM.getContext().IntTy;299
300CGF.StartFunction(GlobalDecl(&D, DynamicInitKind::AtExit), ResTy, DtorStub,301FI, Args, D.getLocation(), D.getInit()->getExprLoc());302
303// Emit an artificial location for this function.304auto AL = ApplyDebugLocation::CreateArtificial(CGF);305
306llvm::CallInst *call = CGF.Builder.CreateCall(Dtor, Addr);307
308// Make sure the call and the callee agree on calling convention.309if (auto *DtorFn = dyn_cast<llvm::Function>(310Dtor.getCallee()->stripPointerCastsAndAliases()))311call->setCallingConv(DtorFn->getCallingConv());312
313// Return 0 from function314CGF.Builder.CreateStore(llvm::Constant::getNullValue(CGM.IntTy),315CGF.ReturnValue);316
317CGF.FinishFunction();318
319return DtorStub;320}
321
322/// Register a global destructor using the C atexit runtime function.
323void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,324llvm::FunctionCallee dtor,325llvm::Constant *addr) {326// Create a function which calls the destructor.327llvm::Constant *dtorStub = createAtExitStub(VD, dtor, addr);328registerGlobalDtorWithAtExit(dtorStub);329}
330
331/// Register a global destructor using the LLVM 'llvm.global_dtors' global.
332void CodeGenFunction::registerGlobalDtorWithLLVM(const VarDecl &VD,333llvm::FunctionCallee Dtor,334llvm::Constant *Addr) {335// Create a function which calls the destructor.336llvm::Function *dtorStub = createAtExitStub(VD, Dtor, Addr);337CGM.AddGlobalDtor(dtorStub);338}
339
340void CodeGenFunction::registerGlobalDtorWithAtExit(llvm::Constant *dtorStub) {341// extern "C" int atexit(void (*f)(void));342assert(dtorStub->getType() ==343llvm::PointerType::get(344llvm::FunctionType::get(CGM.VoidTy, false),345dtorStub->getType()->getPointerAddressSpace()) &&346"Argument to atexit has a wrong type.");347
348llvm::FunctionType *atexitTy =349llvm::FunctionType::get(IntTy, dtorStub->getType(), false);350
351llvm::FunctionCallee atexit =352CGM.CreateRuntimeFunction(atexitTy, "atexit", llvm::AttributeList(),353/*Local=*/true);354if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit.getCallee()))355atexitFn->setDoesNotThrow();356
357EmitNounwindRuntimeCall(atexit, dtorStub);358}
359
360llvm::Value *361CodeGenFunction::unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub) {362// The unatexit subroutine unregisters __dtor functions that were previously363// registered by the atexit subroutine. If the referenced function is found,364// it is removed from the list of functions that are called at normal program365// termination and the unatexit returns a value of 0, otherwise a non-zero366// value is returned.367//368// extern "C" int unatexit(void (*f)(void));369assert(dtorStub->getType() ==370llvm::PointerType::get(371llvm::FunctionType::get(CGM.VoidTy, false),372dtorStub->getType()->getPointerAddressSpace()) &&373"Argument to unatexit has a wrong type.");374
375llvm::FunctionType *unatexitTy =376llvm::FunctionType::get(IntTy, {dtorStub->getType()}, /*isVarArg=*/false);377
378llvm::FunctionCallee unatexit =379CGM.CreateRuntimeFunction(unatexitTy, "unatexit", llvm::AttributeList());380
381cast<llvm::Function>(unatexit.getCallee())->setDoesNotThrow();382
383return EmitNounwindRuntimeCall(unatexit, dtorStub);384}
385
386void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,387llvm::GlobalVariable *DeclPtr,388bool PerformInit) {389// If we've been asked to forbid guard variables, emit an error now.390// This diagnostic is hard-coded for Darwin's use case; we can find391// better phrasing if someone else needs it.392if (CGM.getCodeGenOpts().ForbidGuardVariables)393CGM.Error(D.getLocation(),394"this initialization requires a guard variable, which "395"the kernel does not support");396
397CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit);398}
399
400void CodeGenFunction::EmitCXXGuardedInitBranch(llvm::Value *NeedsInit,401llvm::BasicBlock *InitBlock,402llvm::BasicBlock *NoInitBlock,403GuardKind Kind,404const VarDecl *D) {405assert((Kind == GuardKind::TlsGuard || D) && "no guarded variable");406
407// A guess at how many times we will enter the initialization of a408// variable, depending on the kind of variable.409static const uint64_t InitsPerTLSVar = 1024;410static const uint64_t InitsPerLocalVar = 1024 * 1024;411
412llvm::MDNode *Weights;413if (Kind == GuardKind::VariableGuard && !D->isLocalVarDecl()) {414// For non-local variables, don't apply any weighting for now. Due to our415// use of COMDATs, we expect there to be at most one initialization of the416// variable per DSO, but we have no way to know how many DSOs will try to417// initialize the variable.418Weights = nullptr;419} else {420uint64_t NumInits;421// FIXME: For the TLS case, collect and use profiling information to422// determine a more accurate brach weight.423if (Kind == GuardKind::TlsGuard || D->getTLSKind())424NumInits = InitsPerTLSVar;425else426NumInits = InitsPerLocalVar;427
428// The probability of us entering the initializer is429// 1 / (total number of times we attempt to initialize the variable).430llvm::MDBuilder MDHelper(CGM.getLLVMContext());431Weights = MDHelper.createBranchWeights(1, NumInits - 1);432}433
434Builder.CreateCondBr(NeedsInit, InitBlock, NoInitBlock, Weights);435}
436
437llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(438llvm::FunctionType *FTy, const Twine &Name, const CGFunctionInfo &FI,439SourceLocation Loc, bool TLS, llvm::GlobalVariable::LinkageTypes Linkage) {440llvm::Function *Fn = llvm::Function::Create(FTy, Linkage, Name, &getModule());441
442if (!getLangOpts().AppleKext && !TLS) {443// Set the section if needed.444if (const char *Section = getTarget().getStaticInitSectionSpecifier())445Fn->setSection(Section);446}447
448if (Linkage == llvm::GlobalVariable::InternalLinkage)449SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);450
451Fn->setCallingConv(getRuntimeCC());452
453if (!getLangOpts().Exceptions)454Fn->setDoesNotThrow();455
456if (getLangOpts().Sanitize.has(SanitizerKind::Address) &&457!isInNoSanitizeList(SanitizerKind::Address, Fn, Loc))458Fn->addFnAttr(llvm::Attribute::SanitizeAddress);459
460if (getLangOpts().Sanitize.has(SanitizerKind::KernelAddress) &&461!isInNoSanitizeList(SanitizerKind::KernelAddress, Fn, Loc))462Fn->addFnAttr(llvm::Attribute::SanitizeAddress);463
464if (getLangOpts().Sanitize.has(SanitizerKind::HWAddress) &&465!isInNoSanitizeList(SanitizerKind::HWAddress, Fn, Loc))466Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);467
468if (getLangOpts().Sanitize.has(SanitizerKind::KernelHWAddress) &&469!isInNoSanitizeList(SanitizerKind::KernelHWAddress, Fn, Loc))470Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);471
472if (getLangOpts().Sanitize.has(SanitizerKind::MemtagStack) &&473!isInNoSanitizeList(SanitizerKind::MemtagStack, Fn, Loc))474Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);475
476if (getLangOpts().Sanitize.has(SanitizerKind::Thread) &&477!isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))478Fn->addFnAttr(llvm::Attribute::SanitizeThread);479
480if (getLangOpts().Sanitize.has(SanitizerKind::NumericalStability) &&481!isInNoSanitizeList(SanitizerKind::NumericalStability, Fn, Loc))482Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);483
484if (getLangOpts().Sanitize.has(SanitizerKind::Memory) &&485!isInNoSanitizeList(SanitizerKind::Memory, Fn, Loc))486Fn->addFnAttr(llvm::Attribute::SanitizeMemory);487
488if (getLangOpts().Sanitize.has(SanitizerKind::KernelMemory) &&489!isInNoSanitizeList(SanitizerKind::KernelMemory, Fn, Loc))490Fn->addFnAttr(llvm::Attribute::SanitizeMemory);491
492if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack) &&493!isInNoSanitizeList(SanitizerKind::SafeStack, Fn, Loc))494Fn->addFnAttr(llvm::Attribute::SafeStack);495
496if (getLangOpts().Sanitize.has(SanitizerKind::ShadowCallStack) &&497!isInNoSanitizeList(SanitizerKind::ShadowCallStack, Fn, Loc))498Fn->addFnAttr(llvm::Attribute::ShadowCallStack);499
500return Fn;501}
502
503/// Create a global pointer to a function that will initialize a global
504/// variable. The user has requested that this pointer be emitted in a specific
505/// section.
506void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D,507llvm::GlobalVariable *GV,508llvm::Function *InitFunc,509InitSegAttr *ISA) {510llvm::GlobalVariable *PtrArray = new llvm::GlobalVariable(511TheModule, InitFunc->getType(), /*isConstant=*/true,512llvm::GlobalValue::PrivateLinkage, InitFunc, "__cxx_init_fn_ptr");513PtrArray->setSection(ISA->getSection());514addUsedGlobal(PtrArray);515
516// If the GV is already in a comdat group, then we have to join it.517if (llvm::Comdat *C = GV->getComdat())518PtrArray->setComdat(C);519}
520
521void
522CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,523llvm::GlobalVariable *Addr,524bool PerformInit) {525
526// According to E.2.3.1 in CUDA-7.5 Programming guide: __device__,527// __constant__ and __shared__ variables defined in namespace scope,528// that are of class type, cannot have a non-empty constructor. All529// the checks have been done in Sema by now. Whatever initializers530// are allowed are empty and we just need to ignore them here.531if (getLangOpts().CUDAIsDevice && !getLangOpts().GPUAllowDeviceInit &&532(D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() ||533D->hasAttr<CUDASharedAttr>()))534return;535
536// Check if we've already initialized this decl.537auto I = DelayedCXXInitPosition.find(D);538if (I != DelayedCXXInitPosition.end() && I->second == ~0U)539return;540
541llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);542SmallString<256> FnName;543{544llvm::raw_svector_ostream Out(FnName);545getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out);546}547
548// Create a variable initialization function.549llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(550FTy, FnName.str(), getTypes().arrangeNullaryFunction(), D->getLocation());551
552auto *ISA = D->getAttr<InitSegAttr>();553CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,554PerformInit);555
556llvm::GlobalVariable *COMDATKey =557supportsCOMDAT() && D->isExternallyVisible() ? Addr : nullptr;558
559if (D->getTLSKind()) {560// FIXME: Should we support init_priority for thread_local?561// FIXME: We only need to register one __cxa_thread_atexit function for the562// entire TU.563CXXThreadLocalInits.push_back(Fn);564CXXThreadLocalInitVars.push_back(D);565} else if (PerformInit && ISA) {566// Contract with backend that "init_seg(compiler)" corresponds to priority567// 200 and "init_seg(lib)" corresponds to priority 400.568int Priority = -1;569if (ISA->getSection() == ".CRT$XCC")570Priority = 200;571else if (ISA->getSection() == ".CRT$XCL")572Priority = 400;573
574if (Priority != -1)575AddGlobalCtor(Fn, Priority, ~0U, COMDATKey);576else577EmitPointerToInitFunc(D, Addr, Fn, ISA);578} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {579OrderGlobalInitsOrStermFinalizers Key(IPA->getPriority(),580PrioritizedCXXGlobalInits.size());581PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));582} else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) ||583getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR ||584D->hasAttr<SelectAnyAttr>()) {585// C++ [basic.start.init]p2:586// Definitions of explicitly specialized class template static data587// members have ordered initialization. Other class template static data588// members (i.e., implicitly or explicitly instantiated specializations)589// have unordered initialization.590//591// As a consequence, we can put them into their own llvm.global_ctors entry.592//593// If the global is externally visible, put the initializer into a COMDAT594// group with the global being initialized. On most platforms, this is a595// minor startup time optimization. In the MS C++ ABI, there are no guard596// variables, so this COMDAT key is required for correctness.597//598// SelectAny globals will be comdat-folded. Put the initializer into a599// COMDAT group associated with the global, so the initializers get folded600// too.601I = DelayedCXXInitPosition.find(D);602// CXXGlobalInits.size() is the lex order number for the next deferred603// VarDecl. Use it when the current VarDecl is non-deferred. Although this604// lex order number is shared between current VarDecl and some following605// VarDecls, their order of insertion into `llvm.global_ctors` is the same606// as the lexing order and the following stable sort would preserve such607// order.608unsigned LexOrder =609I == DelayedCXXInitPosition.end() ? CXXGlobalInits.size() : I->second;610AddGlobalCtor(Fn, 65535, LexOrder, COMDATKey);611if (COMDATKey && (getTriple().isOSBinFormatELF() ||612getTarget().getCXXABI().isMicrosoft())) {613// When COMDAT is used on ELF or in the MS C++ ABI, the key must be in614// llvm.used to prevent linker GC.615addUsedGlobal(COMDATKey);616}617
618// If we used a COMDAT key for the global ctor, the init function can be619// discarded if the global ctor entry is discarded.620// FIXME: Do we need to restrict this to ELF and Wasm?621llvm::Comdat *C = Addr->getComdat();622if (COMDATKey && C &&623(getTarget().getTriple().isOSBinFormatELF() ||624getTarget().getTriple().isOSBinFormatWasm())) {625Fn->setComdat(C);626}627} else {628I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash.629if (I == DelayedCXXInitPosition.end()) {630CXXGlobalInits.push_back(Fn);631} else if (I->second != ~0U) {632assert(I->second < CXXGlobalInits.size() &&633CXXGlobalInits[I->second] == nullptr);634CXXGlobalInits[I->second] = Fn;635}636}637
638// Remember that we already emitted the initializer for this global.639DelayedCXXInitPosition[D] = ~0U;640}
641
642void CodeGenModule::EmitCXXThreadLocalInitFunc() {643getCXXABI().EmitThreadLocalInitFuncs(644*this, CXXThreadLocals, CXXThreadLocalInits, CXXThreadLocalInitVars);645
646CXXThreadLocalInits.clear();647CXXThreadLocalInitVars.clear();648CXXThreadLocals.clear();649}
650
651/* Build the initializer for a C++20 module:
652This is arranged to be run only once regardless of how many times the module
653might be included transitively. This arranged by using a guard variable.
654
655If there are no initializers at all (and also no imported modules) we reduce
656this to an empty function (since the Itanium ABI requires that this function
657be available to a caller, which might be produced by a different
658implementation).
659
660First we call any initializers for imported modules.
661We then call initializers for the Global Module Fragment (if present)
662We then call initializers for the current module.
663We then call initializers for the Private Module Fragment (if present)
664*/
665
666void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {667assert(Primary->isInterfaceOrPartition() &&668"The function should only be called for C++20 named module interface"669" or partition.");670
671while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())672CXXGlobalInits.pop_back();673
674// As noted above, we create the function, even if it is empty.675// Module initializers for imported modules are emitted first.676
677// Collect all the modules that we import678llvm::SmallSetVector<Module *, 8> AllImports;679// Ones that we export680for (auto I : Primary->Exports)681AllImports.insert(I.getPointer());682// Ones that we only import.683for (Module *M : Primary->Imports)684AllImports.insert(M);685// Ones that we import in the global module fragment or the private module686// fragment.687for (Module *SubM : Primary->submodules()) {688assert((SubM->isGlobalModule() || SubM->isPrivateModule()) &&689"The sub modules of C++20 module unit should only be global module "690"fragments or private module framents.");691assert(SubM->Exports.empty() &&692"The global mdoule fragments and the private module fragments are "693"not allowed to export import modules.");694for (Module *M : SubM->Imports)695AllImports.insert(M);696}697
698SmallVector<llvm::Function *, 8> ModuleInits;699for (Module *M : AllImports) {700// No Itanium initializer in header like modules.701if (M->isHeaderLikeModule())702continue; // TODO: warn of mixed use of module map modules and C++20?703// We're allowed to skip the initialization if we are sure it doesn't704// do any thing.705if (!M->isNamedModuleInterfaceHasInit())706continue;707llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);708SmallString<256> FnName;709{710llvm::raw_svector_ostream Out(FnName);711cast<ItaniumMangleContext>(getCXXABI().getMangleContext())712.mangleModuleInitializer(M, Out);713}714assert(!GetGlobalValue(FnName.str()) &&715"We should only have one use of the initializer call");716llvm::Function *Fn = llvm::Function::Create(717FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());718ModuleInits.push_back(Fn);719}720
721// Add any initializers with specified priority; this uses the same approach722// as EmitCXXGlobalInitFunc().723if (!PrioritizedCXXGlobalInits.empty()) {724SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;725llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),726PrioritizedCXXGlobalInits.end());727for (SmallVectorImpl<GlobalInitData>::iterator728I = PrioritizedCXXGlobalInits.begin(),729E = PrioritizedCXXGlobalInits.end();730I != E;) {731SmallVectorImpl<GlobalInitData>::iterator PrioE =732std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());733
734for (; I < PrioE; ++I)735ModuleInits.push_back(I->second);736}737}738
739// Now append the ones without specified priority.740for (auto *F : CXXGlobalInits)741ModuleInits.push_back(F);742
743llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);744const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();745
746// We now build the initializer for this module, which has a mangled name747// as per the Itanium ABI . The action of the initializer is guarded so that748// each init is run just once (even though a module might be imported749// multiple times via nested use).750llvm::Function *Fn;751{752SmallString<256> InitFnName;753llvm::raw_svector_ostream Out(InitFnName);754cast<ItaniumMangleContext>(getCXXABI().getMangleContext())755.mangleModuleInitializer(Primary, Out);756Fn = CreateGlobalInitOrCleanUpFunction(757FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,758llvm::GlobalVariable::ExternalLinkage);759
760// If we have a completely empty initializer then we do not want to create761// the guard variable.762ConstantAddress GuardAddr = ConstantAddress::invalid();763if (!ModuleInits.empty()) {764// Create the guard var.765llvm::GlobalVariable *Guard = new llvm::GlobalVariable(766getModule(), Int8Ty, /*isConstant=*/false,767llvm::GlobalVariable::InternalLinkage,768llvm::ConstantInt::get(Int8Ty, 0), InitFnName.str() + "__in_chrg");769CharUnits GuardAlign = CharUnits::One();770Guard->setAlignment(GuardAlign.getAsAlign());771GuardAddr = ConstantAddress(Guard, Int8Ty, GuardAlign);772}773CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits,774GuardAddr);775}776
777// We allow for the case that a module object is added to a linked binary778// without a specific call to the the initializer. This also ensures that779// implementation partition initializers are called when the partition780// is not imported as an interface.781AddGlobalCtor(Fn);782
783// See the comment in EmitCXXGlobalInitFunc about OpenCL global init784// functions.785if (getLangOpts().OpenCL) {786GenKernelArgMetadata(Fn);787Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);788}789
790assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||791getLangOpts().GPUAllowDeviceInit);792if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {793Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);794Fn->addFnAttr("device-init");795}796
797// We are done with the inits.798AllImports.clear();799PrioritizedCXXGlobalInits.clear();800CXXGlobalInits.clear();801ModuleInits.clear();802}
803
804static SmallString<128> getTransformedFileName(llvm::Module &M) {805SmallString<128> FileName = llvm::sys::path::filename(M.getName());806
807if (FileName.empty())808FileName = "<null>";809
810for (size_t i = 0; i < FileName.size(); ++i) {811// Replace everything that's not [a-zA-Z0-9._] with a _. This set happens812// to be the set of C preprocessing numbers.813if (!isPreprocessingNumberBody(FileName[i]))814FileName[i] = '_';815}816
817return FileName;818}
819
820static std::string getPrioritySuffix(unsigned int Priority) {821assert(Priority <= 65535 && "Priority should always be <= 65535.");822
823// Compute the function suffix from priority. Prepend with zeroes to make824// sure the function names are also ordered as priorities.825std::string PrioritySuffix = llvm::utostr(Priority);826PrioritySuffix = std::string(6 - PrioritySuffix.size(), '0') + PrioritySuffix;827
828return PrioritySuffix;829}
830
831void
832CodeGenModule::EmitCXXGlobalInitFunc() {833while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())834CXXGlobalInits.pop_back();835
836// When we import C++20 modules, we must run their initializers first.837SmallVector<llvm::Function *, 8> ModuleInits;838if (CXX20ModuleInits)839for (Module *M : ImportedModules) {840// No Itanium initializer in header like modules.841if (M->isHeaderLikeModule())842continue;843// We're allowed to skip the initialization if we are sure it doesn't844// do any thing.845if (!M->isNamedModuleInterfaceHasInit())846continue;847llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);848SmallString<256> FnName;849{850llvm::raw_svector_ostream Out(FnName);851cast<ItaniumMangleContext>(getCXXABI().getMangleContext())852.mangleModuleInitializer(M, Out);853}854assert(!GetGlobalValue(FnName.str()) &&855"We should only have one use of the initializer call");856llvm::Function *Fn = llvm::Function::Create(857FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());858ModuleInits.push_back(Fn);859}860
861if (ModuleInits.empty() && CXXGlobalInits.empty() &&862PrioritizedCXXGlobalInits.empty())863return;864
865llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);866const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();867
868// Create our global prioritized initialization function.869if (!PrioritizedCXXGlobalInits.empty()) {870SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;871llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),872PrioritizedCXXGlobalInits.end());873// Iterate over "chunks" of ctors with same priority and emit each chunk874// into separate function. Note - everything is sorted first by priority,875// second - by lex order, so we emit ctor functions in proper order.876for (SmallVectorImpl<GlobalInitData >::iterator877I = PrioritizedCXXGlobalInits.begin(),878E = PrioritizedCXXGlobalInits.end(); I != E; ) {879SmallVectorImpl<GlobalInitData >::iterator880PrioE = std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());881
882LocalCXXGlobalInits.clear();883
884unsigned int Priority = I->first.priority;885llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(886FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI);887
888// Prepend the module inits to the highest priority set.889if (!ModuleInits.empty()) {890for (auto *F : ModuleInits)891LocalCXXGlobalInits.push_back(F);892ModuleInits.clear();893}894
895for (; I < PrioE; ++I)896LocalCXXGlobalInits.push_back(I->second);897
898CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, LocalCXXGlobalInits);899AddGlobalCtor(Fn, Priority);900}901PrioritizedCXXGlobalInits.clear();902}903
904if (getCXXABI().useSinitAndSterm() && ModuleInits.empty() &&905CXXGlobalInits.empty())906return;907
908for (auto *F : CXXGlobalInits)909ModuleInits.push_back(F);910CXXGlobalInits.clear();911
912// Include the filename in the symbol name. Including "sub_" matches gcc913// and makes sure these symbols appear lexicographically behind the symbols914// with priority emitted above. Module implementation units behave the same915// way as a non-modular TU with imports.916llvm::Function *Fn;917if (CXX20ModuleInits && getContext().getCurrentNamedModule() &&918!getContext().getCurrentNamedModule()->isModuleImplementation()) {919SmallString<256> InitFnName;920llvm::raw_svector_ostream Out(InitFnName);921cast<ItaniumMangleContext>(getCXXABI().getMangleContext())922.mangleModuleInitializer(getContext().getCurrentNamedModule(), Out);923Fn = CreateGlobalInitOrCleanUpFunction(924FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,925llvm::GlobalVariable::ExternalLinkage);926} else927Fn = CreateGlobalInitOrCleanUpFunction(928FTy,929llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),930FI);931
932CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits);933AddGlobalCtor(Fn);934
935// In OpenCL global init functions must be converted to kernels in order to936// be able to launch them from the host.937// FIXME: Some more work might be needed to handle destructors correctly.938// Current initialization function makes use of function pointers callbacks.939// We can't support function pointers especially between host and device.940// However it seems global destruction has little meaning without any941// dynamic resource allocation on the device and program scope variables are942// destroyed by the runtime when program is released.943if (getLangOpts().OpenCL) {944GenKernelArgMetadata(Fn);945Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);946}947
948assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||949getLangOpts().GPUAllowDeviceInit);950if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {951Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);952Fn->addFnAttr("device-init");953}954
955ModuleInits.clear();956}
957
958void CodeGenModule::EmitCXXGlobalCleanUpFunc() {959if (CXXGlobalDtorsOrStermFinalizers.empty() &&960PrioritizedCXXStermFinalizers.empty())961return;962
963llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);964const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();965
966// Create our global prioritized cleanup function.967if (!PrioritizedCXXStermFinalizers.empty()) {968SmallVector<CXXGlobalDtorsOrStermFinalizer_t, 8> LocalCXXStermFinalizers;969llvm::array_pod_sort(PrioritizedCXXStermFinalizers.begin(),970PrioritizedCXXStermFinalizers.end());971// Iterate over "chunks" of dtors with same priority and emit each chunk972// into separate function. Note - everything is sorted first by priority,973// second - by lex order, so we emit dtor functions in proper order.974for (SmallVectorImpl<StermFinalizerData>::iterator975I = PrioritizedCXXStermFinalizers.begin(),976E = PrioritizedCXXStermFinalizers.end();977I != E;) {978SmallVectorImpl<StermFinalizerData>::iterator PrioE =979std::upper_bound(I + 1, E, *I, StermFinalizerPriorityCmp());980
981LocalCXXStermFinalizers.clear();982
983unsigned int Priority = I->first.priority;984llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(985FTy, "_GLOBAL__a_" + getPrioritySuffix(Priority), FI);986
987for (; I < PrioE; ++I) {988llvm::FunctionCallee DtorFn = I->second;989LocalCXXStermFinalizers.emplace_back(DtorFn.getFunctionType(),990DtorFn.getCallee(), nullptr);991}992
993CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc(994Fn, LocalCXXStermFinalizers);995AddGlobalDtor(Fn, Priority);996}997PrioritizedCXXStermFinalizers.clear();998}999
1000if (CXXGlobalDtorsOrStermFinalizers.empty())1001return;1002
1003// Create our global cleanup function.1004llvm::Function *Fn =1005CreateGlobalInitOrCleanUpFunction(FTy, "_GLOBAL__D_a", FI);1006
1007CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc(1008Fn, CXXGlobalDtorsOrStermFinalizers);1009AddGlobalDtor(Fn);1010CXXGlobalDtorsOrStermFinalizers.clear();1011}
1012
1013/// Emit the code necessary to initialize the given global variable.
1014void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,1015const VarDecl *D,1016llvm::GlobalVariable *Addr,1017bool PerformInit) {1018// Check if we need to emit debug info for variable initializer.1019if (D->hasAttr<NoDebugAttr>())1020DebugInfo = nullptr; // disable debug info indefinitely for this function1021
1022CurEHLocation = D->getBeginLoc();1023
1024StartFunction(GlobalDecl(D, DynamicInitKind::Initializer),1025getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(),1026FunctionArgList());1027// Emit an artificial location for this function.1028auto AL = ApplyDebugLocation::CreateArtificial(*this);1029
1030// Use guarded initialization if the global variable is weak. This1031// occurs for, e.g., instantiated static data members and1032// definitions explicitly marked weak.1033//1034// Also use guarded initialization for a variable with dynamic TLS and1035// unordered initialization. (If the initialization is ordered, the ABI1036// layer will guard the whole-TU initialization for us.)1037if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage() ||1038(D->getTLSKind() == VarDecl::TLS_Dynamic &&1039isTemplateInstantiation(D->getTemplateSpecializationKind()))) {1040EmitCXXGuardedInit(*D, Addr, PerformInit);1041} else {1042EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);1043}1044
1045if (getLangOpts().HLSL)1046CGM.getHLSLRuntime().annotateHLSLResource(D, Addr);1047
1048FinishFunction();1049}
1050
1051void
1052CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,1053ArrayRef<llvm::Function *> Decls,1054ConstantAddress Guard) {1055{1056auto NL = ApplyDebugLocation::CreateEmpty(*this);1057StartFunction(GlobalDecl(), getContext().VoidTy, Fn,1058getTypes().arrangeNullaryFunction(), FunctionArgList());1059// Emit an artificial location for this function.1060auto AL = ApplyDebugLocation::CreateArtificial(*this);1061
1062llvm::BasicBlock *ExitBlock = nullptr;1063if (Guard.isValid()) {1064// If we have a guard variable, check whether we've already performed1065// these initializations. This happens for TLS initialization functions.1066llvm::Value *GuardVal = Builder.CreateLoad(Guard);1067llvm::Value *Uninit = Builder.CreateIsNull(GuardVal,1068"guard.uninitialized");1069llvm::BasicBlock *InitBlock = createBasicBlock("init");1070ExitBlock = createBasicBlock("exit");1071EmitCXXGuardedInitBranch(Uninit, InitBlock, ExitBlock,1072GuardKind::TlsGuard, nullptr);1073EmitBlock(InitBlock);1074// Mark as initialized before initializing anything else. If the1075// initializers use previously-initialized thread_local vars, that's1076// probably supposed to be OK, but the standard doesn't say.1077Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);1078
1079// The guard variable can't ever change again.1080EmitInvariantStart(1081Guard.getPointer(),1082CharUnits::fromQuantity(1083CGM.getDataLayout().getTypeAllocSize(GuardVal->getType())));1084}1085
1086RunCleanupsScope Scope(*this);1087
1088// When building in Objective-C++ ARC mode, create an autorelease pool1089// around the global initializers.1090if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) {1091llvm::Value *token = EmitObjCAutoreleasePoolPush();1092EmitObjCAutoreleasePoolCleanup(token);1093}1094
1095for (unsigned i = 0, e = Decls.size(); i != e; ++i)1096if (Decls[i])1097EmitRuntimeCall(Decls[i]);1098
1099Scope.ForceCleanup();1100
1101if (ExitBlock) {1102Builder.CreateBr(ExitBlock);1103EmitBlock(ExitBlock);1104}1105}1106
1107FinishFunction();1108}
1109
1110void CodeGenFunction::GenerateCXXGlobalCleanUpFunc(1111llvm::Function *Fn,1112ArrayRef<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,1113llvm::Constant *>>1114DtorsOrStermFinalizers) {1115{1116auto NL = ApplyDebugLocation::CreateEmpty(*this);1117StartFunction(GlobalDecl(), getContext().VoidTy, Fn,1118getTypes().arrangeNullaryFunction(), FunctionArgList());1119// Emit an artificial location for this function.1120auto AL = ApplyDebugLocation::CreateArtificial(*this);1121
1122// Emit the cleanups, in reverse order from construction.1123for (unsigned i = 0, e = DtorsOrStermFinalizers.size(); i != e; ++i) {1124llvm::FunctionType *CalleeTy;1125llvm::Value *Callee;1126llvm::Constant *Arg;1127std::tie(CalleeTy, Callee, Arg) = DtorsOrStermFinalizers[e - i - 1];1128
1129llvm::CallInst *CI = nullptr;1130if (Arg == nullptr) {1131assert(1132CGM.getCXXABI().useSinitAndSterm() &&1133"Arg could not be nullptr unless using sinit and sterm functions.");1134CI = Builder.CreateCall(CalleeTy, Callee);1135} else1136CI = Builder.CreateCall(CalleeTy, Callee, Arg);1137
1138// Make sure the call and the callee agree on calling convention.1139if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))1140CI->setCallingConv(F->getCallingConv());1141}1142}1143
1144FinishFunction();1145}
1146
1147/// generateDestroyHelper - Generates a helper function which, when
1148/// invoked, destroys the given object. The address of the object
1149/// should be in global memory.
1150llvm::Function *CodeGenFunction::generateDestroyHelper(1151Address addr, QualType type, Destroyer *destroyer,1152bool useEHCleanupForArray, const VarDecl *VD) {1153FunctionArgList args;1154ImplicitParamDecl Dst(getContext(), getContext().VoidPtrTy,1155ImplicitParamKind::Other);1156args.push_back(&Dst);1157
1158const CGFunctionInfo &FI =1159CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, args);1160llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);1161llvm::Function *fn = CGM.CreateGlobalInitOrCleanUpFunction(1162FTy, "__cxx_global_array_dtor", FI, VD->getLocation());1163
1164CurEHLocation = VD->getBeginLoc();1165
1166StartFunction(GlobalDecl(VD, DynamicInitKind::GlobalArrayDestructor),1167getContext().VoidTy, fn, FI, args);1168// Emit an artificial location for this function.1169auto AL = ApplyDebugLocation::CreateArtificial(*this);1170
1171emitDestroy(addr, type, destroyer, useEHCleanupForArray);1172
1173FinishFunction();1174
1175return fn;1176}
1177