xref: /minix3/external/bsd/llvm/dist/clang/lib/CodeGen/CGDeclCXX.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This contains code dealing with code generation of C++ declarations
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "CodeGenFunction.h"
15f4a2713aSLionel Sambuc #include "CGCXXABI.h"
16f4a2713aSLionel Sambuc #include "CGObjCRuntime.h"
17*0a6a1f1dSLionel Sambuc #include "CGOpenMPRuntime.h"
18f4a2713aSLionel Sambuc #include "clang/Frontend/CodeGenOptions.h"
19f4a2713aSLionel Sambuc #include "llvm/ADT/StringExtras.h"
20f4a2713aSLionel Sambuc #include "llvm/IR/Intrinsics.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/Support/Path.h"
22f4a2713aSLionel Sambuc 
23f4a2713aSLionel Sambuc using namespace clang;
24f4a2713aSLionel Sambuc using namespace CodeGen;
25f4a2713aSLionel Sambuc 
EmitDeclInit(CodeGenFunction & CGF,const VarDecl & D,llvm::Constant * DeclPtr)26f4a2713aSLionel Sambuc static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
27f4a2713aSLionel Sambuc                          llvm::Constant *DeclPtr) {
28f4a2713aSLionel Sambuc   assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
29f4a2713aSLionel Sambuc   assert(!D.getType()->isReferenceType() &&
30f4a2713aSLionel Sambuc          "Should not call EmitDeclInit on a reference!");
31f4a2713aSLionel Sambuc 
32f4a2713aSLionel Sambuc   ASTContext &Context = CGF.getContext();
33f4a2713aSLionel Sambuc 
34f4a2713aSLionel Sambuc   CharUnits alignment = Context.getDeclAlign(&D);
35f4a2713aSLionel Sambuc   QualType type = D.getType();
36f4a2713aSLionel Sambuc   LValue lv = CGF.MakeAddrLValue(DeclPtr, type, alignment);
37f4a2713aSLionel Sambuc 
38f4a2713aSLionel Sambuc   const Expr *Init = D.getInit();
39f4a2713aSLionel Sambuc   switch (CGF.getEvaluationKind(type)) {
40f4a2713aSLionel Sambuc   case TEK_Scalar: {
41f4a2713aSLionel Sambuc     CodeGenModule &CGM = CGF.CGM;
42f4a2713aSLionel Sambuc     if (lv.isObjCStrong())
43f4a2713aSLionel Sambuc       CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init),
44f4a2713aSLionel Sambuc                                                 DeclPtr, D.getTLSKind());
45f4a2713aSLionel Sambuc     else if (lv.isObjCWeak())
46f4a2713aSLionel Sambuc       CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init),
47f4a2713aSLionel Sambuc                                               DeclPtr);
48f4a2713aSLionel Sambuc     else
49f4a2713aSLionel Sambuc       CGF.EmitScalarInit(Init, &D, lv, false);
50f4a2713aSLionel Sambuc     return;
51f4a2713aSLionel Sambuc   }
52f4a2713aSLionel Sambuc   case TEK_Complex:
53f4a2713aSLionel Sambuc     CGF.EmitComplexExprIntoLValue(Init, lv, /*isInit*/ true);
54f4a2713aSLionel Sambuc     return;
55f4a2713aSLionel Sambuc   case TEK_Aggregate:
56f4a2713aSLionel Sambuc     CGF.EmitAggExpr(Init, AggValueSlot::forLValue(lv,AggValueSlot::IsDestructed,
57f4a2713aSLionel Sambuc                                           AggValueSlot::DoesNotNeedGCBarriers,
58f4a2713aSLionel Sambuc                                                   AggValueSlot::IsNotAliased));
59f4a2713aSLionel Sambuc     return;
60f4a2713aSLionel Sambuc   }
61f4a2713aSLionel Sambuc   llvm_unreachable("bad evaluation kind");
62f4a2713aSLionel Sambuc }
63f4a2713aSLionel Sambuc 
64f4a2713aSLionel Sambuc /// Emit code to cause the destruction of the given variable with
65f4a2713aSLionel Sambuc /// static storage duration.
EmitDeclDestroy(CodeGenFunction & CGF,const VarDecl & D,llvm::Constant * addr)66f4a2713aSLionel Sambuc static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
67f4a2713aSLionel Sambuc                             llvm::Constant *addr) {
68f4a2713aSLionel Sambuc   CodeGenModule &CGM = CGF.CGM;
69f4a2713aSLionel Sambuc 
70f4a2713aSLionel Sambuc   // FIXME:  __attribute__((cleanup)) ?
71f4a2713aSLionel Sambuc 
72f4a2713aSLionel Sambuc   QualType type = D.getType();
73f4a2713aSLionel Sambuc   QualType::DestructionKind dtorKind = type.isDestructedType();
74f4a2713aSLionel Sambuc 
75f4a2713aSLionel Sambuc   switch (dtorKind) {
76f4a2713aSLionel Sambuc   case QualType::DK_none:
77f4a2713aSLionel Sambuc     return;
78f4a2713aSLionel Sambuc 
79f4a2713aSLionel Sambuc   case QualType::DK_cxx_destructor:
80f4a2713aSLionel Sambuc     break;
81f4a2713aSLionel Sambuc 
82f4a2713aSLionel Sambuc   case QualType::DK_objc_strong_lifetime:
83f4a2713aSLionel Sambuc   case QualType::DK_objc_weak_lifetime:
84f4a2713aSLionel Sambuc     // We don't care about releasing objects during process teardown.
85f4a2713aSLionel Sambuc     assert(!D.getTLSKind() && "should have rejected this");
86f4a2713aSLionel Sambuc     return;
87f4a2713aSLionel Sambuc   }
88f4a2713aSLionel Sambuc 
89f4a2713aSLionel Sambuc   llvm::Constant *function;
90f4a2713aSLionel Sambuc   llvm::Constant *argument;
91f4a2713aSLionel Sambuc 
92f4a2713aSLionel Sambuc   // Special-case non-array C++ destructors, where there's a function
93f4a2713aSLionel Sambuc   // with the right signature that we can just call.
94*0a6a1f1dSLionel Sambuc   const CXXRecordDecl *record = nullptr;
95f4a2713aSLionel Sambuc   if (dtorKind == QualType::DK_cxx_destructor &&
96f4a2713aSLionel Sambuc       (record = type->getAsCXXRecordDecl())) {
97f4a2713aSLionel Sambuc     assert(!record->hasTrivialDestructor());
98f4a2713aSLionel Sambuc     CXXDestructorDecl *dtor = record->getDestructor();
99f4a2713aSLionel Sambuc 
100*0a6a1f1dSLionel Sambuc     function = CGM.getAddrOfCXXStructor(dtor, StructorType::Complete);
101f4a2713aSLionel Sambuc     argument = llvm::ConstantExpr::getBitCast(
102f4a2713aSLionel Sambuc         addr, CGF.getTypes().ConvertType(type)->getPointerTo());
103f4a2713aSLionel Sambuc 
104f4a2713aSLionel Sambuc   // Otherwise, the standard logic requires a helper function.
105f4a2713aSLionel Sambuc   } else {
106f4a2713aSLionel Sambuc     function = CodeGenFunction(CGM)
107f4a2713aSLionel Sambuc         .generateDestroyHelper(addr, type, CGF.getDestroyer(dtorKind),
108f4a2713aSLionel Sambuc                                CGF.needsEHCleanup(dtorKind), &D);
109f4a2713aSLionel Sambuc     argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
110f4a2713aSLionel Sambuc   }
111f4a2713aSLionel Sambuc 
112f4a2713aSLionel Sambuc   CGM.getCXXABI().registerGlobalDtor(CGF, D, function, argument);
113f4a2713aSLionel Sambuc }
114f4a2713aSLionel Sambuc 
115f4a2713aSLionel Sambuc /// Emit code to cause the variable at the given address to be considered as
116f4a2713aSLionel Sambuc /// constant from this point onwards.
EmitDeclInvariant(CodeGenFunction & CGF,const VarDecl & D,llvm::Constant * Addr)117f4a2713aSLionel Sambuc static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D,
118f4a2713aSLionel Sambuc                               llvm::Constant *Addr) {
119f4a2713aSLionel Sambuc   // Don't emit the intrinsic if we're not optimizing.
120f4a2713aSLionel Sambuc   if (!CGF.CGM.getCodeGenOpts().OptimizationLevel)
121f4a2713aSLionel Sambuc     return;
122f4a2713aSLionel Sambuc 
123f4a2713aSLionel Sambuc   // Grab the llvm.invariant.start intrinsic.
124f4a2713aSLionel Sambuc   llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
125f4a2713aSLionel Sambuc   llvm::Constant *InvariantStart = CGF.CGM.getIntrinsic(InvStartID);
126f4a2713aSLionel Sambuc 
127f4a2713aSLionel Sambuc   // Emit a call with the size in bytes of the object.
128f4a2713aSLionel Sambuc   CharUnits WidthChars = CGF.getContext().getTypeSizeInChars(D.getType());
129f4a2713aSLionel Sambuc   uint64_t Width = WidthChars.getQuantity();
130f4a2713aSLionel Sambuc   llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(CGF.Int64Ty, Width),
131f4a2713aSLionel Sambuc                            llvm::ConstantExpr::getBitCast(Addr, CGF.Int8PtrTy)};
132f4a2713aSLionel Sambuc   CGF.Builder.CreateCall(InvariantStart, Args);
133f4a2713aSLionel Sambuc }
134f4a2713aSLionel Sambuc 
EmitCXXGlobalVarDeclInit(const VarDecl & D,llvm::Constant * DeclPtr,bool PerformInit)135f4a2713aSLionel Sambuc void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
136f4a2713aSLionel Sambuc                                                llvm::Constant *DeclPtr,
137f4a2713aSLionel Sambuc                                                bool PerformInit) {
138f4a2713aSLionel Sambuc 
139f4a2713aSLionel Sambuc   const Expr *Init = D.getInit();
140f4a2713aSLionel Sambuc   QualType T = D.getType();
141f4a2713aSLionel Sambuc 
142f4a2713aSLionel Sambuc   if (!T->isReferenceType()) {
143*0a6a1f1dSLionel Sambuc     if (getLangOpts().OpenMP && D.hasAttr<OMPThreadPrivateDeclAttr>())
144*0a6a1f1dSLionel Sambuc       (void)CGM.getOpenMPRuntime().EmitOMPThreadPrivateVarDefinition(
145*0a6a1f1dSLionel Sambuc           &D, DeclPtr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(),
146*0a6a1f1dSLionel Sambuc           PerformInit, this);
147f4a2713aSLionel Sambuc     if (PerformInit)
148f4a2713aSLionel Sambuc       EmitDeclInit(*this, D, DeclPtr);
149f4a2713aSLionel Sambuc     if (CGM.isTypeConstant(D.getType(), true))
150f4a2713aSLionel Sambuc       EmitDeclInvariant(*this, D, DeclPtr);
151f4a2713aSLionel Sambuc     else
152f4a2713aSLionel Sambuc       EmitDeclDestroy(*this, D, DeclPtr);
153f4a2713aSLionel Sambuc     return;
154f4a2713aSLionel Sambuc   }
155f4a2713aSLionel Sambuc 
156f4a2713aSLionel Sambuc   assert(PerformInit && "cannot have constant initializer which needs "
157f4a2713aSLionel Sambuc          "destruction for reference");
158f4a2713aSLionel Sambuc   unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
159f4a2713aSLionel Sambuc   RValue RV = EmitReferenceBindingToExpr(Init);
160f4a2713aSLionel Sambuc   EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
161f4a2713aSLionel Sambuc }
162f4a2713aSLionel Sambuc 
163f4a2713aSLionel Sambuc /// Create a stub function, suitable for being passed to atexit,
164f4a2713aSLionel Sambuc /// which passes the given address to the given destructor function.
createAtExitStub(const VarDecl & VD,llvm::Constant * dtor,llvm::Constant * addr)165*0a6a1f1dSLionel Sambuc llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD,
166f4a2713aSLionel Sambuc                                                   llvm::Constant *dtor,
167f4a2713aSLionel Sambuc                                                   llvm::Constant *addr) {
168f4a2713aSLionel Sambuc   // Get the destructor function type, void(*)(void).
169f4a2713aSLionel Sambuc   llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false);
170f4a2713aSLionel Sambuc   SmallString<256> FnName;
171f4a2713aSLionel Sambuc   {
172f4a2713aSLionel Sambuc     llvm::raw_svector_ostream Out(FnName);
173f4a2713aSLionel Sambuc     CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out);
174f4a2713aSLionel Sambuc   }
175*0a6a1f1dSLionel Sambuc   llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(ty, FnName.str(),
176*0a6a1f1dSLionel Sambuc                                                               VD.getLocation());
177f4a2713aSLionel Sambuc 
178f4a2713aSLionel Sambuc   CodeGenFunction CGF(CGM);
179f4a2713aSLionel Sambuc 
180f4a2713aSLionel Sambuc   CGF.StartFunction(&VD, CGM.getContext().VoidTy, fn,
181*0a6a1f1dSLionel Sambuc                     CGM.getTypes().arrangeNullaryFunction(), FunctionArgList());
182f4a2713aSLionel Sambuc 
183f4a2713aSLionel Sambuc   llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
184f4a2713aSLionel Sambuc 
185f4a2713aSLionel Sambuc  // Make sure the call and the callee agree on calling convention.
186f4a2713aSLionel Sambuc   if (llvm::Function *dtorFn =
187f4a2713aSLionel Sambuc         dyn_cast<llvm::Function>(dtor->stripPointerCasts()))
188f4a2713aSLionel Sambuc     call->setCallingConv(dtorFn->getCallingConv());
189f4a2713aSLionel Sambuc 
190f4a2713aSLionel Sambuc   CGF.FinishFunction();
191f4a2713aSLionel Sambuc 
192f4a2713aSLionel Sambuc   return fn;
193f4a2713aSLionel Sambuc }
194f4a2713aSLionel Sambuc 
195f4a2713aSLionel Sambuc /// Register a global destructor using the C atexit runtime function.
registerGlobalDtorWithAtExit(const VarDecl & VD,llvm::Constant * dtor,llvm::Constant * addr)196f4a2713aSLionel Sambuc void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,
197f4a2713aSLionel Sambuc                                                    llvm::Constant *dtor,
198f4a2713aSLionel Sambuc                                                    llvm::Constant *addr) {
199f4a2713aSLionel Sambuc   // Create a function which calls the destructor.
200*0a6a1f1dSLionel Sambuc   llvm::Constant *dtorStub = createAtExitStub(VD, dtor, addr);
201f4a2713aSLionel Sambuc 
202f4a2713aSLionel Sambuc   // extern "C" int atexit(void (*f)(void));
203f4a2713aSLionel Sambuc   llvm::FunctionType *atexitTy =
204f4a2713aSLionel Sambuc     llvm::FunctionType::get(IntTy, dtorStub->getType(), false);
205f4a2713aSLionel Sambuc 
206f4a2713aSLionel Sambuc   llvm::Constant *atexit =
207f4a2713aSLionel Sambuc     CGM.CreateRuntimeFunction(atexitTy, "atexit");
208f4a2713aSLionel Sambuc   if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit))
209f4a2713aSLionel Sambuc     atexitFn->setDoesNotThrow();
210f4a2713aSLionel Sambuc 
211f4a2713aSLionel Sambuc   EmitNounwindRuntimeCall(atexit, dtorStub);
212f4a2713aSLionel Sambuc }
213f4a2713aSLionel Sambuc 
EmitCXXGuardedInit(const VarDecl & D,llvm::GlobalVariable * DeclPtr,bool PerformInit)214f4a2713aSLionel Sambuc void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
215f4a2713aSLionel Sambuc                                          llvm::GlobalVariable *DeclPtr,
216f4a2713aSLionel Sambuc                                          bool PerformInit) {
217f4a2713aSLionel Sambuc   // If we've been asked to forbid guard variables, emit an error now.
218f4a2713aSLionel Sambuc   // This diagnostic is hard-coded for Darwin's use case;  we can find
219f4a2713aSLionel Sambuc   // better phrasing if someone else needs it.
220f4a2713aSLionel Sambuc   if (CGM.getCodeGenOpts().ForbidGuardVariables)
221f4a2713aSLionel Sambuc     CGM.Error(D.getLocation(),
222f4a2713aSLionel Sambuc               "this initialization requires a guard variable, which "
223f4a2713aSLionel Sambuc               "the kernel does not support");
224f4a2713aSLionel Sambuc 
225f4a2713aSLionel Sambuc   CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit);
226f4a2713aSLionel Sambuc }
227f4a2713aSLionel Sambuc 
CreateGlobalInitOrDestructFunction(llvm::FunctionType * FTy,const Twine & Name,SourceLocation Loc,bool TLS)228*0a6a1f1dSLionel Sambuc llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
229*0a6a1f1dSLionel Sambuc     llvm::FunctionType *FTy, const Twine &Name, SourceLocation Loc, bool TLS) {
230f4a2713aSLionel Sambuc   llvm::Function *Fn =
231f4a2713aSLionel Sambuc     llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
232*0a6a1f1dSLionel Sambuc                            Name, &getModule());
233*0a6a1f1dSLionel Sambuc   if (!getLangOpts().AppleKext && !TLS) {
234f4a2713aSLionel Sambuc     // Set the section if needed.
235*0a6a1f1dSLionel Sambuc     if (const char *Section = getTarget().getStaticInitSectionSpecifier())
236f4a2713aSLionel Sambuc       Fn->setSection(Section);
237f4a2713aSLionel Sambuc   }
238f4a2713aSLionel Sambuc 
239*0a6a1f1dSLionel Sambuc   Fn->setCallingConv(getRuntimeCC());
240f4a2713aSLionel Sambuc 
241*0a6a1f1dSLionel Sambuc   if (!getLangOpts().Exceptions)
242f4a2713aSLionel Sambuc     Fn->setDoesNotThrow();
243f4a2713aSLionel Sambuc 
244*0a6a1f1dSLionel Sambuc   if (!isInSanitizerBlacklist(Fn, Loc)) {
245*0a6a1f1dSLionel Sambuc     if (getLangOpts().Sanitize.has(SanitizerKind::Address))
246f4a2713aSLionel Sambuc       Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
247*0a6a1f1dSLionel Sambuc     if (getLangOpts().Sanitize.has(SanitizerKind::Thread))
248f4a2713aSLionel Sambuc       Fn->addFnAttr(llvm::Attribute::SanitizeThread);
249*0a6a1f1dSLionel Sambuc     if (getLangOpts().Sanitize.has(SanitizerKind::Memory))
250f4a2713aSLionel Sambuc       Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
251*0a6a1f1dSLionel Sambuc   }
252f4a2713aSLionel Sambuc 
253f4a2713aSLionel Sambuc   return Fn;
254f4a2713aSLionel Sambuc }
255f4a2713aSLionel Sambuc 
256*0a6a1f1dSLionel Sambuc /// Create a global pointer to a function that will initialize a global
257*0a6a1f1dSLionel Sambuc /// variable.  The user has requested that this pointer be emitted in a specific
258*0a6a1f1dSLionel Sambuc /// section.
EmitPointerToInitFunc(const VarDecl * D,llvm::GlobalVariable * GV,llvm::Function * InitFunc,InitSegAttr * ISA)259*0a6a1f1dSLionel Sambuc void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D,
260*0a6a1f1dSLionel Sambuc                                           llvm::GlobalVariable *GV,
261*0a6a1f1dSLionel Sambuc                                           llvm::Function *InitFunc,
262*0a6a1f1dSLionel Sambuc                                           InitSegAttr *ISA) {
263*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *PtrArray = new llvm::GlobalVariable(
264*0a6a1f1dSLionel Sambuc       TheModule, InitFunc->getType(), /*isConstant=*/true,
265*0a6a1f1dSLionel Sambuc       llvm::GlobalValue::PrivateLinkage, InitFunc, "__cxx_init_fn_ptr");
266*0a6a1f1dSLionel Sambuc   PtrArray->setSection(ISA->getSection());
267*0a6a1f1dSLionel Sambuc   addUsedGlobal(PtrArray);
268*0a6a1f1dSLionel Sambuc 
269*0a6a1f1dSLionel Sambuc   // If the GV is already in a comdat group, then we have to join it.
270*0a6a1f1dSLionel Sambuc   llvm::Comdat *C = GV->getComdat();
271*0a6a1f1dSLionel Sambuc 
272*0a6a1f1dSLionel Sambuc   // LinkOnce and Weak linkage are lowered down to a single-member comdat group.
273*0a6a1f1dSLionel Sambuc   // Make an explicit group so we can join it.
274*0a6a1f1dSLionel Sambuc   if (!C && (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())) {
275*0a6a1f1dSLionel Sambuc     C = TheModule.getOrInsertComdat(GV->getName());
276*0a6a1f1dSLionel Sambuc     GV->setComdat(C);
277*0a6a1f1dSLionel Sambuc   }
278*0a6a1f1dSLionel Sambuc   if (C)
279*0a6a1f1dSLionel Sambuc     PtrArray->setComdat(C);
280*0a6a1f1dSLionel Sambuc }
281*0a6a1f1dSLionel Sambuc 
282f4a2713aSLionel Sambuc void
EmitCXXGlobalVarDeclInitFunc(const VarDecl * D,llvm::GlobalVariable * Addr,bool PerformInit)283f4a2713aSLionel Sambuc CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
284f4a2713aSLionel Sambuc                                             llvm::GlobalVariable *Addr,
285f4a2713aSLionel Sambuc                                             bool PerformInit) {
286f4a2713aSLionel Sambuc   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
287f4a2713aSLionel Sambuc   SmallString<256> FnName;
288f4a2713aSLionel Sambuc   {
289f4a2713aSLionel Sambuc     llvm::raw_svector_ostream Out(FnName);
290f4a2713aSLionel Sambuc     getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out);
291f4a2713aSLionel Sambuc   }
292f4a2713aSLionel Sambuc 
293f4a2713aSLionel Sambuc   // Create a variable initialization function.
294f4a2713aSLionel Sambuc   llvm::Function *Fn =
295*0a6a1f1dSLionel Sambuc       CreateGlobalInitOrDestructFunction(FTy, FnName.str(), D->getLocation());
296f4a2713aSLionel Sambuc 
297*0a6a1f1dSLionel Sambuc   auto *ISA = D->getAttr<InitSegAttr>();
298f4a2713aSLionel Sambuc   CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr,
299f4a2713aSLionel Sambuc                                                           PerformInit);
300f4a2713aSLionel Sambuc 
301*0a6a1f1dSLionel Sambuc   llvm::GlobalVariable *COMDATKey =
302*0a6a1f1dSLionel Sambuc       supportsCOMDAT() && D->isExternallyVisible() ? Addr : nullptr;
303*0a6a1f1dSLionel Sambuc 
304f4a2713aSLionel Sambuc   if (D->getTLSKind()) {
305f4a2713aSLionel Sambuc     // FIXME: Should we support init_priority for thread_local?
306f4a2713aSLionel Sambuc     // FIXME: Ideally, initialization of instantiated thread_local static data
307f4a2713aSLionel Sambuc     // members of class templates should not trigger initialization of other
308f4a2713aSLionel Sambuc     // entities in the TU.
309f4a2713aSLionel Sambuc     // FIXME: We only need to register one __cxa_thread_atexit function for the
310f4a2713aSLionel Sambuc     // entire TU.
311f4a2713aSLionel Sambuc     CXXThreadLocalInits.push_back(Fn);
312*0a6a1f1dSLionel Sambuc     CXXThreadLocalInitVars.push_back(Addr);
313*0a6a1f1dSLionel Sambuc   } else if (PerformInit && ISA) {
314*0a6a1f1dSLionel Sambuc     EmitPointerToInitFunc(D, Addr, Fn, ISA);
315*0a6a1f1dSLionel Sambuc     DelayedCXXInitPosition.erase(D);
316*0a6a1f1dSLionel Sambuc   } else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
317*0a6a1f1dSLionel Sambuc     OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size());
318f4a2713aSLionel Sambuc     PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
319f4a2713aSLionel Sambuc     DelayedCXXInitPosition.erase(D);
320*0a6a1f1dSLionel Sambuc   } else if (isTemplateInstantiation(D->getTemplateSpecializationKind())) {
321f4a2713aSLionel Sambuc     // C++ [basic.start.init]p2:
322f4a2713aSLionel Sambuc     //   Definitions of explicitly specialized class template static data
323f4a2713aSLionel Sambuc     //   members have ordered initialization. Other class template static data
324f4a2713aSLionel Sambuc     //   members (i.e., implicitly or explicitly instantiated specializations)
325f4a2713aSLionel Sambuc     //   have unordered initialization.
326f4a2713aSLionel Sambuc     //
327f4a2713aSLionel Sambuc     // As a consequence, we can put them into their own llvm.global_ctors entry.
328*0a6a1f1dSLionel Sambuc     //
329*0a6a1f1dSLionel Sambuc     // If the global is externally visible, put the initializer into a COMDAT
330*0a6a1f1dSLionel Sambuc     // group with the global being initialized.  On most platforms, this is a
331*0a6a1f1dSLionel Sambuc     // minor startup time optimization.  In the MS C++ ABI, there are no guard
332*0a6a1f1dSLionel Sambuc     // variables, so this COMDAT key is required for correctness.
333*0a6a1f1dSLionel Sambuc     AddGlobalCtor(Fn, 65535, COMDATKey);
334*0a6a1f1dSLionel Sambuc     DelayedCXXInitPosition.erase(D);
335*0a6a1f1dSLionel Sambuc   } else if (D->hasAttr<SelectAnyAttr>()) {
336*0a6a1f1dSLionel Sambuc     // SelectAny globals will be comdat-folded. Put the initializer into a
337*0a6a1f1dSLionel Sambuc     // COMDAT group associated with the global, so the initializers get folded
338*0a6a1f1dSLionel Sambuc     // too.
339*0a6a1f1dSLionel Sambuc     AddGlobalCtor(Fn, 65535, COMDATKey);
340f4a2713aSLionel Sambuc     DelayedCXXInitPosition.erase(D);
341f4a2713aSLionel Sambuc   } else {
342f4a2713aSLionel Sambuc     llvm::DenseMap<const Decl *, unsigned>::iterator I =
343f4a2713aSLionel Sambuc       DelayedCXXInitPosition.find(D);
344f4a2713aSLionel Sambuc     if (I == DelayedCXXInitPosition.end()) {
345f4a2713aSLionel Sambuc       CXXGlobalInits.push_back(Fn);
346f4a2713aSLionel Sambuc     } else {
347*0a6a1f1dSLionel Sambuc       assert(CXXGlobalInits[I->second] == nullptr);
348f4a2713aSLionel Sambuc       CXXGlobalInits[I->second] = Fn;
349f4a2713aSLionel Sambuc       DelayedCXXInitPosition.erase(I);
350f4a2713aSLionel Sambuc     }
351f4a2713aSLionel Sambuc   }
352f4a2713aSLionel Sambuc }
353f4a2713aSLionel Sambuc 
EmitCXXThreadLocalInitFunc()354f4a2713aSLionel Sambuc void CodeGenModule::EmitCXXThreadLocalInitFunc() {
355*0a6a1f1dSLionel Sambuc   getCXXABI().EmitThreadLocalInitFuncs(
356*0a6a1f1dSLionel Sambuc       *this, CXXThreadLocals, CXXThreadLocalInits, CXXThreadLocalInitVars);
357f4a2713aSLionel Sambuc 
358f4a2713aSLionel Sambuc   CXXThreadLocalInits.clear();
359*0a6a1f1dSLionel Sambuc   CXXThreadLocalInitVars.clear();
360f4a2713aSLionel Sambuc   CXXThreadLocals.clear();
361f4a2713aSLionel Sambuc }
362f4a2713aSLionel Sambuc 
363f4a2713aSLionel Sambuc void
EmitCXXGlobalInitFunc()364f4a2713aSLionel Sambuc CodeGenModule::EmitCXXGlobalInitFunc() {
365f4a2713aSLionel Sambuc   while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
366f4a2713aSLionel Sambuc     CXXGlobalInits.pop_back();
367f4a2713aSLionel Sambuc 
368f4a2713aSLionel Sambuc   if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
369f4a2713aSLionel Sambuc     return;
370f4a2713aSLionel Sambuc 
371f4a2713aSLionel Sambuc   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
372f4a2713aSLionel Sambuc 
373f4a2713aSLionel Sambuc 
374f4a2713aSLionel Sambuc   // Create our global initialization function.
375f4a2713aSLionel Sambuc   if (!PrioritizedCXXGlobalInits.empty()) {
376*0a6a1f1dSLionel Sambuc     SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
377f4a2713aSLionel Sambuc     llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
378f4a2713aSLionel Sambuc                          PrioritizedCXXGlobalInits.end());
379f4a2713aSLionel Sambuc     // Iterate over "chunks" of ctors with same priority and emit each chunk
380f4a2713aSLionel Sambuc     // into separate function. Note - everything is sorted first by priority,
381f4a2713aSLionel Sambuc     // second - by lex order, so we emit ctor functions in proper order.
382f4a2713aSLionel Sambuc     for (SmallVectorImpl<GlobalInitData >::iterator
383f4a2713aSLionel Sambuc            I = PrioritizedCXXGlobalInits.begin(),
384f4a2713aSLionel Sambuc            E = PrioritizedCXXGlobalInits.end(); I != E; ) {
385f4a2713aSLionel Sambuc       SmallVectorImpl<GlobalInitData >::iterator
386f4a2713aSLionel Sambuc         PrioE = std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
387f4a2713aSLionel Sambuc 
388f4a2713aSLionel Sambuc       LocalCXXGlobalInits.clear();
389f4a2713aSLionel Sambuc       unsigned Priority = I->first.priority;
390f4a2713aSLionel Sambuc       // Compute the function suffix from priority. Prepend with zeroes to make
391f4a2713aSLionel Sambuc       // sure the function names are also ordered as priorities.
392f4a2713aSLionel Sambuc       std::string PrioritySuffix = llvm::utostr(Priority);
393*0a6a1f1dSLionel Sambuc       // Priority is always <= 65535 (enforced by sema).
394f4a2713aSLionel Sambuc       PrioritySuffix = std::string(6-PrioritySuffix.size(), '0')+PrioritySuffix;
395*0a6a1f1dSLionel Sambuc       llvm::Function *Fn = CreateGlobalInitOrDestructFunction(
396*0a6a1f1dSLionel Sambuc           FTy, "_GLOBAL__I_" + PrioritySuffix);
397f4a2713aSLionel Sambuc 
398f4a2713aSLionel Sambuc       for (; I < PrioE; ++I)
399f4a2713aSLionel Sambuc         LocalCXXGlobalInits.push_back(I->second);
400f4a2713aSLionel Sambuc 
401f4a2713aSLionel Sambuc       CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, LocalCXXGlobalInits);
402f4a2713aSLionel Sambuc       AddGlobalCtor(Fn, Priority);
403f4a2713aSLionel Sambuc     }
404f4a2713aSLionel Sambuc   }
405f4a2713aSLionel Sambuc 
406*0a6a1f1dSLionel Sambuc   SmallString<128> FileName;
407*0a6a1f1dSLionel Sambuc   SourceManager &SM = Context.getSourceManager();
408*0a6a1f1dSLionel Sambuc   if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
409*0a6a1f1dSLionel Sambuc     // Include the filename in the symbol name. Including "sub_" matches gcc and
410*0a6a1f1dSLionel Sambuc     // makes sure these symbols appear lexicographically behind the symbols with
411*0a6a1f1dSLionel Sambuc     // priority emitted above.
412*0a6a1f1dSLionel Sambuc     FileName = llvm::sys::path::filename(MainFile->getName());
413*0a6a1f1dSLionel Sambuc   } else {
414*0a6a1f1dSLionel Sambuc     FileName = SmallString<128>("<null>");
415*0a6a1f1dSLionel Sambuc   }
416*0a6a1f1dSLionel Sambuc 
417*0a6a1f1dSLionel Sambuc   for (size_t i = 0; i < FileName.size(); ++i) {
418*0a6a1f1dSLionel Sambuc     // Replace everything that's not [a-zA-Z0-9._] with a _. This set happens
419*0a6a1f1dSLionel Sambuc     // to be the set of C preprocessing numbers.
420*0a6a1f1dSLionel Sambuc     if (!isPreprocessingNumberBody(FileName[i]))
421*0a6a1f1dSLionel Sambuc       FileName[i] = '_';
422*0a6a1f1dSLionel Sambuc   }
423*0a6a1f1dSLionel Sambuc 
424*0a6a1f1dSLionel Sambuc   llvm::Function *Fn = CreateGlobalInitOrDestructFunction(
425*0a6a1f1dSLionel Sambuc       FTy, llvm::Twine("_GLOBAL__sub_I_", FileName));
426f4a2713aSLionel Sambuc 
427f4a2713aSLionel Sambuc   CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits);
428f4a2713aSLionel Sambuc   AddGlobalCtor(Fn);
429f4a2713aSLionel Sambuc 
430f4a2713aSLionel Sambuc   CXXGlobalInits.clear();
431f4a2713aSLionel Sambuc   PrioritizedCXXGlobalInits.clear();
432f4a2713aSLionel Sambuc }
433f4a2713aSLionel Sambuc 
EmitCXXGlobalDtorFunc()434f4a2713aSLionel Sambuc void CodeGenModule::EmitCXXGlobalDtorFunc() {
435f4a2713aSLionel Sambuc   if (CXXGlobalDtors.empty())
436f4a2713aSLionel Sambuc     return;
437f4a2713aSLionel Sambuc 
438f4a2713aSLionel Sambuc   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
439f4a2713aSLionel Sambuc 
440f4a2713aSLionel Sambuc   // Create our global destructor function.
441*0a6a1f1dSLionel Sambuc   llvm::Function *Fn = CreateGlobalInitOrDestructFunction(FTy, "_GLOBAL__D_a");
442f4a2713aSLionel Sambuc 
443f4a2713aSLionel Sambuc   CodeGenFunction(*this).GenerateCXXGlobalDtorsFunc(Fn, CXXGlobalDtors);
444f4a2713aSLionel Sambuc   AddGlobalDtor(Fn);
445f4a2713aSLionel Sambuc }
446f4a2713aSLionel Sambuc 
447f4a2713aSLionel Sambuc /// Emit the code necessary to initialize the given global variable.
GenerateCXXGlobalVarDeclInitFunc(llvm::Function * Fn,const VarDecl * D,llvm::GlobalVariable * Addr,bool PerformInit)448f4a2713aSLionel Sambuc void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
449f4a2713aSLionel Sambuc                                                        const VarDecl *D,
450f4a2713aSLionel Sambuc                                                  llvm::GlobalVariable *Addr,
451f4a2713aSLionel Sambuc                                                        bool PerformInit) {
452f4a2713aSLionel Sambuc   // Check if we need to emit debug info for variable initializer.
453f4a2713aSLionel Sambuc   if (D->hasAttr<NoDebugAttr>())
454*0a6a1f1dSLionel Sambuc     DebugInfo = nullptr; // disable debug info indefinitely for this function
455*0a6a1f1dSLionel Sambuc 
456*0a6a1f1dSLionel Sambuc   CurEHLocation = D->getLocStart();
457f4a2713aSLionel Sambuc 
458f4a2713aSLionel Sambuc   StartFunction(GlobalDecl(D), getContext().VoidTy, Fn,
459f4a2713aSLionel Sambuc                 getTypes().arrangeNullaryFunction(),
460*0a6a1f1dSLionel Sambuc                 FunctionArgList(), D->getLocation(),
461*0a6a1f1dSLionel Sambuc                 D->getInit()->getExprLoc());
462f4a2713aSLionel Sambuc 
463f4a2713aSLionel Sambuc   // Use guarded initialization if the global variable is weak. This
464f4a2713aSLionel Sambuc   // occurs for, e.g., instantiated static data members and
465f4a2713aSLionel Sambuc   // definitions explicitly marked weak.
466*0a6a1f1dSLionel Sambuc   if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage()) {
467f4a2713aSLionel Sambuc     EmitCXXGuardedInit(*D, Addr, PerformInit);
468f4a2713aSLionel Sambuc   } else {
469f4a2713aSLionel Sambuc     EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);
470f4a2713aSLionel Sambuc   }
471f4a2713aSLionel Sambuc 
472f4a2713aSLionel Sambuc   FinishFunction();
473f4a2713aSLionel Sambuc }
474f4a2713aSLionel Sambuc 
475f4a2713aSLionel Sambuc void
GenerateCXXGlobalInitFunc(llvm::Function * Fn,ArrayRef<llvm::Function * > Decls,llvm::GlobalVariable * Guard)476f4a2713aSLionel Sambuc CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
477*0a6a1f1dSLionel Sambuc                                            ArrayRef<llvm::Function *> Decls,
478f4a2713aSLionel Sambuc                                            llvm::GlobalVariable *Guard) {
479*0a6a1f1dSLionel Sambuc   {
480*0a6a1f1dSLionel Sambuc     ApplyDebugLocation NL(*this);
481f4a2713aSLionel Sambuc     StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
482*0a6a1f1dSLionel Sambuc                   getTypes().arrangeNullaryFunction(), FunctionArgList());
483*0a6a1f1dSLionel Sambuc     // Emit an artificial location for this function.
484*0a6a1f1dSLionel Sambuc     ArtificialLocation AL(*this);
485f4a2713aSLionel Sambuc 
486*0a6a1f1dSLionel Sambuc     llvm::BasicBlock *ExitBlock = nullptr;
487f4a2713aSLionel Sambuc     if (Guard) {
488*0a6a1f1dSLionel Sambuc       // If we have a guard variable, check whether we've already performed
489*0a6a1f1dSLionel Sambuc       // these initializations. This happens for TLS initialization functions.
490f4a2713aSLionel Sambuc       llvm::Value *GuardVal = Builder.CreateLoad(Guard);
491*0a6a1f1dSLionel Sambuc       llvm::Value *Uninit = Builder.CreateIsNull(GuardVal,
492*0a6a1f1dSLionel Sambuc                                                  "guard.uninitialized");
493f4a2713aSLionel Sambuc       // Mark as initialized before initializing anything else. If the
494f4a2713aSLionel Sambuc       // initializers use previously-initialized thread_local vars, that's
495f4a2713aSLionel Sambuc       // probably supposed to be OK, but the standard doesn't say.
496f4a2713aSLionel Sambuc       Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard);
497f4a2713aSLionel Sambuc       llvm::BasicBlock *InitBlock = createBasicBlock("init");
498f4a2713aSLionel Sambuc       ExitBlock = createBasicBlock("exit");
499f4a2713aSLionel Sambuc       Builder.CreateCondBr(Uninit, InitBlock, ExitBlock);
500f4a2713aSLionel Sambuc       EmitBlock(InitBlock);
501f4a2713aSLionel Sambuc     }
502f4a2713aSLionel Sambuc 
503f4a2713aSLionel Sambuc     RunCleanupsScope Scope(*this);
504f4a2713aSLionel Sambuc 
505f4a2713aSLionel Sambuc     // When building in Objective-C++ ARC mode, create an autorelease pool
506f4a2713aSLionel Sambuc     // around the global initializers.
507f4a2713aSLionel Sambuc     if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) {
508f4a2713aSLionel Sambuc       llvm::Value *token = EmitObjCAutoreleasePoolPush();
509f4a2713aSLionel Sambuc       EmitObjCAutoreleasePoolCleanup(token);
510f4a2713aSLionel Sambuc     }
511f4a2713aSLionel Sambuc 
512f4a2713aSLionel Sambuc     for (unsigned i = 0, e = Decls.size(); i != e; ++i)
513f4a2713aSLionel Sambuc       if (Decls[i])
514f4a2713aSLionel Sambuc         EmitRuntimeCall(Decls[i]);
515f4a2713aSLionel Sambuc 
516f4a2713aSLionel Sambuc     Scope.ForceCleanup();
517f4a2713aSLionel Sambuc 
518f4a2713aSLionel Sambuc     if (ExitBlock) {
519f4a2713aSLionel Sambuc       Builder.CreateBr(ExitBlock);
520f4a2713aSLionel Sambuc       EmitBlock(ExitBlock);
521f4a2713aSLionel Sambuc     }
522*0a6a1f1dSLionel Sambuc   }
523f4a2713aSLionel Sambuc 
524f4a2713aSLionel Sambuc   FinishFunction();
525f4a2713aSLionel Sambuc }
526f4a2713aSLionel Sambuc 
GenerateCXXGlobalDtorsFunc(llvm::Function * Fn,const std::vector<std::pair<llvm::WeakVH,llvm::Constant * >> & DtorsAndObjects)527f4a2713aSLionel Sambuc void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn,
528f4a2713aSLionel Sambuc                   const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
529f4a2713aSLionel Sambuc                                                 &DtorsAndObjects) {
530*0a6a1f1dSLionel Sambuc   {
531*0a6a1f1dSLionel Sambuc     ApplyDebugLocation NL(*this);
532f4a2713aSLionel Sambuc     StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
533*0a6a1f1dSLionel Sambuc                   getTypes().arrangeNullaryFunction(), FunctionArgList());
534*0a6a1f1dSLionel Sambuc     // Emit an artificial location for this function.
535*0a6a1f1dSLionel Sambuc     ArtificialLocation AL(*this);
536f4a2713aSLionel Sambuc 
537f4a2713aSLionel Sambuc     // Emit the dtors, in reverse order from construction.
538f4a2713aSLionel Sambuc     for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
539f4a2713aSLionel Sambuc       llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
540f4a2713aSLionel Sambuc       llvm::CallInst *CI = Builder.CreateCall(Callee,
541f4a2713aSLionel Sambuc                                           DtorsAndObjects[e - i - 1].second);
542f4a2713aSLionel Sambuc       // Make sure the call and the callee agree on calling convention.
543f4a2713aSLionel Sambuc       if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
544f4a2713aSLionel Sambuc         CI->setCallingConv(F->getCallingConv());
545f4a2713aSLionel Sambuc     }
546*0a6a1f1dSLionel Sambuc   }
547f4a2713aSLionel Sambuc 
548f4a2713aSLionel Sambuc   FinishFunction();
549f4a2713aSLionel Sambuc }
550f4a2713aSLionel Sambuc 
551f4a2713aSLionel Sambuc /// generateDestroyHelper - Generates a helper function which, when
552f4a2713aSLionel Sambuc /// invoked, destroys the given object.
generateDestroyHelper(llvm::Constant * addr,QualType type,Destroyer * destroyer,bool useEHCleanupForArray,const VarDecl * VD)553f4a2713aSLionel Sambuc llvm::Function *CodeGenFunction::generateDestroyHelper(
554f4a2713aSLionel Sambuc     llvm::Constant *addr, QualType type, Destroyer *destroyer,
555f4a2713aSLionel Sambuc     bool useEHCleanupForArray, const VarDecl *VD) {
556f4a2713aSLionel Sambuc   FunctionArgList args;
557*0a6a1f1dSLionel Sambuc   ImplicitParamDecl dst(getContext(), nullptr, SourceLocation(), nullptr,
558*0a6a1f1dSLionel Sambuc                         getContext().VoidPtrTy);
559f4a2713aSLionel Sambuc   args.push_back(&dst);
560f4a2713aSLionel Sambuc 
561*0a6a1f1dSLionel Sambuc   const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
562*0a6a1f1dSLionel Sambuc       getContext().VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false);
563f4a2713aSLionel Sambuc   llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
564*0a6a1f1dSLionel Sambuc   llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction(
565*0a6a1f1dSLionel Sambuc       FTy, "__cxx_global_array_dtor", VD->getLocation());
566f4a2713aSLionel Sambuc 
567*0a6a1f1dSLionel Sambuc   CurEHLocation = VD->getLocStart();
568*0a6a1f1dSLionel Sambuc 
569*0a6a1f1dSLionel Sambuc   StartFunction(VD, getContext().VoidTy, fn, FI, args);
570f4a2713aSLionel Sambuc 
571f4a2713aSLionel Sambuc   emitDestroy(addr, type, destroyer, useEHCleanupForArray);
572f4a2713aSLionel Sambuc 
573f4a2713aSLionel Sambuc   FinishFunction();
574f4a2713aSLionel Sambuc 
575f4a2713aSLionel Sambuc   return fn;
576f4a2713aSLionel Sambuc }
577