Mercurial > hg > CbC > CbC_llvm
annotate clang/lib/CodeGen/CGDeclCXX.cpp @ 232:70dce7da266c llvm-original
llvm original Jul 20 16:41:34 2021
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 21 Jul 2021 10:27:27 +0900 |
parents | 79ff65ed7e25 |
children | c4bab56944e8 |
rev | line source |
---|---|
150 | 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 "CGObjCRuntime.h" | |
15 #include "CGOpenMPRuntime.h" | |
16 #include "CodeGenFunction.h" | |
17 #include "TargetInfo.h" | |
18 #include "clang/AST/Attr.h" | |
173 | 19 #include "clang/Basic/LangOptions.h" |
150 | 20 #include "llvm/ADT/StringExtras.h" |
21 #include "llvm/IR/Intrinsics.h" | |
22 #include "llvm/IR/MDBuilder.h" | |
23 #include "llvm/Support/Path.h" | |
24 | |
25 using namespace clang; | |
26 using namespace CodeGen; | |
27 | |
28 static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, | |
29 ConstantAddress DeclPtr) { | |
30 assert( | |
31 (D.hasGlobalStorage() || | |
32 (D.hasLocalStorage() && CGF.getContext().getLangOpts().OpenCLCPlusPlus)) && | |
33 "VarDecl must have global or local (in the case of OpenCL) storage!"); | |
34 assert(!D.getType()->isReferenceType() && | |
35 "Should not call EmitDeclInit on a reference!"); | |
36 | |
37 QualType type = D.getType(); | |
38 LValue lv = CGF.MakeAddrLValue(DeclPtr, type); | |
39 | |
40 const Expr *Init = D.getInit(); | |
41 switch (CGF.getEvaluationKind(type)) { | |
42 case TEK_Scalar: { | |
43 CodeGenModule &CGM = CGF.CGM; | |
44 if (lv.isObjCStrong()) | |
45 CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init), | |
46 DeclPtr, D.getTLSKind()); | |
47 else if (lv.isObjCWeak()) | |
48 CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init), | |
49 DeclPtr); | |
50 else | |
51 CGF.EmitScalarInit(Init, &D, lv, false); | |
52 return; | |
53 } | |
54 case TEK_Complex: | |
55 CGF.EmitComplexExprIntoLValue(Init, lv, /*isInit*/ true); | |
56 return; | |
57 case TEK_Aggregate: | |
58 CGF.EmitAggExpr(Init, | |
59 AggValueSlot::forLValue(lv, CGF, AggValueSlot::IsDestructed, | |
60 AggValueSlot::DoesNotNeedGCBarriers, | |
61 AggValueSlot::IsNotAliased, | |
62 AggValueSlot::DoesNotOverlap)); | |
63 return; | |
64 } | |
65 llvm_unreachable("bad evaluation kind"); | |
66 } | |
67 | |
68 /// Emit code to cause the destruction of the given variable with | |
69 /// static storage duration. | |
70 static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, | |
71 ConstantAddress Addr) { | |
72 // Honor __attribute__((no_destroy)) and bail instead of attempting | |
73 // to emit a reference to a possibly nonexistent destructor, which | |
74 // in turn can cause a crash. This will result in a global constructor | |
75 // that isn't balanced out by a destructor call as intended by the | |
76 // attribute. This also checks for -fno-c++-static-destructors and | |
77 // bails even if the attribute is not present. | |
78 QualType::DestructionKind DtorKind = D.needsDestruction(CGF.getContext()); | |
79 | |
80 // FIXME: __attribute__((cleanup)) ? | |
81 | |
82 switch (DtorKind) { | |
83 case QualType::DK_none: | |
84 return; | |
85 | |
86 case QualType::DK_cxx_destructor: | |
87 break; | |
88 | |
89 case QualType::DK_objc_strong_lifetime: | |
90 case QualType::DK_objc_weak_lifetime: | |
91 case QualType::DK_nontrivial_c_struct: | |
92 // We don't care about releasing objects during process teardown. | |
93 assert(!D.getTLSKind() && "should have rejected this"); | |
94 return; | |
95 } | |
96 | |
97 llvm::FunctionCallee Func; | |
98 llvm::Constant *Argument; | |
99 | |
100 CodeGenModule &CGM = CGF.CGM; | |
101 QualType Type = D.getType(); | |
102 | |
103 // Special-case non-array C++ destructors, if they have the right signature. | |
104 // Under some ABIs, destructors return this instead of void, and cannot be | |
105 // passed directly to __cxa_atexit if the target does not allow this | |
106 // mismatch. | |
107 const CXXRecordDecl *Record = Type->getAsCXXRecordDecl(); | |
108 bool CanRegisterDestructor = | |
109 Record && (!CGM.getCXXABI().HasThisReturn( | |
110 GlobalDecl(Record->getDestructor(), Dtor_Complete)) || | |
111 CGM.getCXXABI().canCallMismatchedFunctionType()); | |
112 // If __cxa_atexit is disabled via a flag, a different helper function is | |
113 // generated elsewhere which uses atexit instead, and it takes the destructor | |
114 // directly. | |
115 bool UsingExternalHelper = !CGM.getCodeGenOpts().CXAAtExit; | |
116 if (Record && (CanRegisterDestructor || UsingExternalHelper)) { | |
117 assert(!Record->hasTrivialDestructor()); | |
118 CXXDestructorDecl *Dtor = Record->getDestructor(); | |
119 | |
120 Func = CGM.getAddrAndTypeOfCXXStructor(GlobalDecl(Dtor, Dtor_Complete)); | |
121 if (CGF.getContext().getLangOpts().OpenCL) { | |
122 auto DestAS = | |
123 CGM.getTargetCodeGenInfo().getAddrSpaceOfCxaAtexitPtrParam(); | |
124 auto DestTy = CGF.getTypes().ConvertType(Type)->getPointerTo( | |
125 CGM.getContext().getTargetAddressSpace(DestAS)); | |
126 auto SrcAS = D.getType().getQualifiers().getAddressSpace(); | |
127 if (DestAS == SrcAS) | |
128 Argument = llvm::ConstantExpr::getBitCast(Addr.getPointer(), DestTy); | |
129 else | |
130 // FIXME: On addr space mismatch we are passing NULL. The generation | |
131 // of the global destructor function should be adjusted accordingly. | |
132 Argument = llvm::ConstantPointerNull::get(DestTy); | |
133 } else { | |
134 Argument = llvm::ConstantExpr::getBitCast( | |
135 Addr.getPointer(), CGF.getTypes().ConvertType(Type)->getPointerTo()); | |
136 } | |
137 // Otherwise, the standard logic requires a helper function. | |
138 } else { | |
139 Func = CodeGenFunction(CGM) | |
140 .generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind), | |
141 CGF.needsEHCleanup(DtorKind), &D); | |
142 Argument = llvm::Constant::getNullValue(CGF.Int8PtrTy); | |
143 } | |
144 | |
145 CGM.getCXXABI().registerGlobalDtor(CGF, D, Func, Argument); | |
146 } | |
147 | |
148 /// Emit code to cause the variable at the given address to be considered as | |
149 /// constant from this point onwards. | |
150 static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D, | |
151 llvm::Constant *Addr) { | |
152 return CGF.EmitInvariantStart( | |
153 Addr, CGF.getContext().getTypeSizeInChars(D.getType())); | |
154 } | |
155 | |
156 void CodeGenFunction::EmitInvariantStart(llvm::Constant *Addr, CharUnits Size) { | |
157 // Do not emit the intrinsic if we're not optimizing. | |
158 if (!CGM.getCodeGenOpts().OptimizationLevel) | |
159 return; | |
160 | |
161 // Grab the llvm.invariant.start intrinsic. | |
162 llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start; | |
163 // Overloaded address space type. | |
164 llvm::Type *ObjectPtr[1] = {Int8PtrTy}; | |
165 llvm::Function *InvariantStart = CGM.getIntrinsic(InvStartID, ObjectPtr); | |
166 | |
167 // Emit a call with the size in bytes of the object. | |
168 uint64_t Width = Size.getQuantity(); | |
169 llvm::Value *Args[2] = { llvm::ConstantInt::getSigned(Int64Ty, Width), | |
170 llvm::ConstantExpr::getBitCast(Addr, Int8PtrTy)}; | |
171 Builder.CreateCall(InvariantStart, Args); | |
172 } | |
173 | |
174 void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, | |
175 llvm::Constant *DeclPtr, | |
176 bool PerformInit) { | |
177 | |
178 const Expr *Init = D.getInit(); | |
179 QualType T = D.getType(); | |
180 | |
181 // The address space of a static local variable (DeclPtr) may be different | |
182 // from the address space of the "this" argument of the constructor. In that | |
183 // case, we need an addrspacecast before calling the constructor. | |
184 // | |
185 // struct StructWithCtor { | |
186 // __device__ StructWithCtor() {...} | |
187 // }; | |
188 // __device__ void foo() { | |
189 // __shared__ StructWithCtor s; | |
190 // ... | |
191 // } | |
192 // | |
193 // For example, in the above CUDA code, the static local variable s has a | |
194 // "shared" address space qualifier, but the constructor of StructWithCtor | |
195 // expects "this" in the "generic" address space. | |
196 unsigned ExpectedAddrSpace = getContext().getTargetAddressSpace(T); | |
197 unsigned ActualAddrSpace = DeclPtr->getType()->getPointerAddressSpace(); | |
198 if (ActualAddrSpace != ExpectedAddrSpace) { | |
199 llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(T); | |
200 llvm::PointerType *PTy = llvm::PointerType::get(LTy, ExpectedAddrSpace); | |
201 DeclPtr = llvm::ConstantExpr::getAddrSpaceCast(DeclPtr, PTy); | |
202 } | |
203 | |
204 ConstantAddress DeclAddr(DeclPtr, getContext().getDeclAlign(&D)); | |
205 | |
206 if (!T->isReferenceType()) { | |
207 if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && | |
208 D.hasAttr<OMPThreadPrivateDeclAttr>()) { | |
209 (void)CGM.getOpenMPRuntime().emitThreadPrivateVarDefinition( | |
210 &D, DeclAddr, D.getAttr<OMPThreadPrivateDeclAttr>()->getLocation(), | |
211 PerformInit, this); | |
212 } | |
213 if (PerformInit) | |
214 EmitDeclInit(*this, D, DeclAddr); | |
215 if (CGM.isTypeConstant(D.getType(), true)) | |
216 EmitDeclInvariant(*this, D, DeclPtr); | |
217 else | |
218 EmitDeclDestroy(*this, D, DeclAddr); | |
219 return; | |
220 } | |
221 | |
222 assert(PerformInit && "cannot have constant initializer which needs " | |
223 "destruction for reference"); | |
224 RValue RV = EmitReferenceBindingToExpr(Init); | |
225 EmitStoreOfScalar(RV.getScalarVal(), DeclAddr, false, T); | |
226 } | |
227 | |
228 /// Create a stub function, suitable for being passed to atexit, | |
229 /// which passes the given address to the given destructor function. | |
230 llvm::Function *CodeGenFunction::createAtExitStub(const VarDecl &VD, | |
231 llvm::FunctionCallee dtor, | |
232 llvm::Constant *addr) { | |
233 // Get the destructor function type, void(*)(void). | |
234 llvm::FunctionType *ty = llvm::FunctionType::get(CGM.VoidTy, false); | |
235 SmallString<256> FnName; | |
236 { | |
237 llvm::raw_svector_ostream Out(FnName); | |
238 CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&VD, Out); | |
239 } | |
240 | |
241 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); | |
221 | 242 llvm::Function *fn = CGM.CreateGlobalInitOrCleanUpFunction( |
150 | 243 ty, FnName.str(), FI, VD.getLocation()); |
244 | |
245 CodeGenFunction CGF(CGM); | |
246 | |
247 CGF.StartFunction(GlobalDecl(&VD, DynamicInitKind::AtExit), | |
221 | 248 CGM.getContext().VoidTy, fn, FI, FunctionArgList(), |
249 VD.getLocation(), VD.getInit()->getExprLoc()); | |
250 // Emit an artificial location for this function. | |
251 auto AL = ApplyDebugLocation::CreateArtificial(CGF); | |
150 | 252 |
253 llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr); | |
254 | |
221 | 255 // Make sure the call and the callee agree on calling convention. |
150 | 256 if (auto *dtorFn = dyn_cast<llvm::Function>( |
257 dtor.getCallee()->stripPointerCastsAndAliases())) | |
258 call->setCallingConv(dtorFn->getCallingConv()); | |
259 | |
260 CGF.FinishFunction(); | |
261 | |
262 return fn; | |
263 } | |
264 | |
232
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
265 /// Create a stub function, suitable for being passed to __pt_atexit_np, |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
266 /// which passes the given address to the given destructor function. |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
267 llvm::Function *CodeGenFunction::createTLSAtExitStub( |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
268 const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr, |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
269 llvm::FunctionCallee &AtExit) { |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
270 SmallString<256> FnName; |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
271 { |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
272 llvm::raw_svector_ostream Out(FnName); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
273 CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&D, Out); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
274 } |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
275 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
276 const CGFunctionInfo &FI = CGM.getTypes().arrangeLLVMFunctionInfo( |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
277 getContext().IntTy, /*instanceMethod=*/false, /*chainCall=*/false, |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
278 {getContext().IntTy}, FunctionType::ExtInfo(), {}, RequiredArgs::All); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
279 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
280 // Get the stub function type, int(*)(int,...). |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
281 llvm::FunctionType *StubTy = |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
282 llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy}, true); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
283 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
284 llvm::Function *DtorStub = CGM.CreateGlobalInitOrCleanUpFunction( |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
285 StubTy, FnName.str(), FI, D.getLocation()); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
286 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
287 CodeGenFunction CGF(CGM); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
288 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
289 FunctionArgList Args; |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
290 ImplicitParamDecl IPD(CGM.getContext(), CGM.getContext().IntTy, |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
291 ImplicitParamDecl::Other); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
292 Args.push_back(&IPD); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
293 QualType ResTy = CGM.getContext().IntTy; |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
294 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
295 CGF.StartFunction(GlobalDecl(&D, DynamicInitKind::AtExit), ResTy, DtorStub, |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
296 FI, Args, D.getLocation(), D.getInit()->getExprLoc()); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
297 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
298 // Emit an artificial location for this function. |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
299 auto AL = ApplyDebugLocation::CreateArtificial(CGF); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
300 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
301 llvm::CallInst *call = CGF.Builder.CreateCall(Dtor, Addr); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
302 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
303 // Make sure the call and the callee agree on calling convention. |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
304 if (auto *DtorFn = dyn_cast<llvm::Function>( |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
305 Dtor.getCallee()->stripPointerCastsAndAliases())) |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
306 call->setCallingConv(DtorFn->getCallingConv()); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
307 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
308 // Return 0 from function |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
309 CGF.Builder.CreateStore(llvm::Constant::getNullValue(CGM.IntTy), |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
310 CGF.ReturnValue); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
311 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
312 CGF.FinishFunction(); |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
313 |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
314 return DtorStub; |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
315 } |
70dce7da266c
llvm original Jul 20 16:41:34 2021
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
221
diff
changeset
|
316 |
150 | 317 /// Register a global destructor using the C atexit runtime function. |
318 void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD, | |
319 llvm::FunctionCallee dtor, | |
320 llvm::Constant *addr) { | |
321 // Create a function which calls the destructor. | |
322 llvm::Constant *dtorStub = createAtExitStub(VD, dtor, addr); | |
323 registerGlobalDtorWithAtExit(dtorStub); | |
324 } | |
325 | |
326 void CodeGenFunction::registerGlobalDtorWithAtExit(llvm::Constant *dtorStub) { | |
327 // extern "C" int atexit(void (*f)(void)); | |
221 | 328 assert(dtorStub->getType() == |
329 llvm::PointerType::get( | |
330 llvm::FunctionType::get(CGM.VoidTy, false), | |
331 dtorStub->getType()->getPointerAddressSpace()) && | |
332 "Argument to atexit has a wrong type."); | |
333 | |
150 | 334 llvm::FunctionType *atexitTy = |
221 | 335 llvm::FunctionType::get(IntTy, dtorStub->getType(), false); |
150 | 336 |
337 llvm::FunctionCallee atexit = | |
338 CGM.CreateRuntimeFunction(atexitTy, "atexit", llvm::AttributeList(), | |
339 /*Local=*/true); | |
340 if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit.getCallee())) | |
341 atexitFn->setDoesNotThrow(); | |
342 | |
343 EmitNounwindRuntimeCall(atexit, dtorStub); | |
344 } | |
345 | |
221 | 346 llvm::Value * |
347 CodeGenFunction::unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub) { | |
348 // The unatexit subroutine unregisters __dtor functions that were previously | |
349 // registered by the atexit subroutine. If the referenced function is found, | |
350 // it is removed from the list of functions that are called at normal program | |
351 // termination and the unatexit returns a value of 0, otherwise a non-zero | |
352 // value is returned. | |
353 // | |
354 // extern "C" int unatexit(void (*f)(void)); | |
355 assert(dtorStub->getType() == | |
356 llvm::PointerType::get( | |
357 llvm::FunctionType::get(CGM.VoidTy, false), | |
358 dtorStub->getType()->getPointerAddressSpace()) && | |
359 "Argument to unatexit has a wrong type."); | |
360 | |
361 llvm::FunctionType *unatexitTy = | |
362 llvm::FunctionType::get(IntTy, {dtorStub->getType()}, /*isVarArg=*/false); | |
363 | |
364 llvm::FunctionCallee unatexit = | |
365 CGM.CreateRuntimeFunction(unatexitTy, "unatexit", llvm::AttributeList()); | |
366 | |
367 cast<llvm::Function>(unatexit.getCallee())->setDoesNotThrow(); | |
368 | |
369 return EmitNounwindRuntimeCall(unatexit, dtorStub); | |
370 } | |
371 | |
150 | 372 void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D, |
373 llvm::GlobalVariable *DeclPtr, | |
374 bool PerformInit) { | |
375 // If we've been asked to forbid guard variables, emit an error now. | |
376 // This diagnostic is hard-coded for Darwin's use case; we can find | |
377 // better phrasing if someone else needs it. | |
378 if (CGM.getCodeGenOpts().ForbidGuardVariables) | |
379 CGM.Error(D.getLocation(), | |
380 "this initialization requires a guard variable, which " | |
381 "the kernel does not support"); | |
382 | |
383 CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr, PerformInit); | |
384 } | |
385 | |
386 void CodeGenFunction::EmitCXXGuardedInitBranch(llvm::Value *NeedsInit, | |
387 llvm::BasicBlock *InitBlock, | |
388 llvm::BasicBlock *NoInitBlock, | |
389 GuardKind Kind, | |
390 const VarDecl *D) { | |
391 assert((Kind == GuardKind::TlsGuard || D) && "no guarded variable"); | |
392 | |
393 // A guess at how many times we will enter the initialization of a | |
394 // variable, depending on the kind of variable. | |
395 static const uint64_t InitsPerTLSVar = 1024; | |
396 static const uint64_t InitsPerLocalVar = 1024 * 1024; | |
397 | |
398 llvm::MDNode *Weights; | |
399 if (Kind == GuardKind::VariableGuard && !D->isLocalVarDecl()) { | |
400 // For non-local variables, don't apply any weighting for now. Due to our | |
401 // use of COMDATs, we expect there to be at most one initialization of the | |
402 // variable per DSO, but we have no way to know how many DSOs will try to | |
403 // initialize the variable. | |
404 Weights = nullptr; | |
405 } else { | |
406 uint64_t NumInits; | |
407 // FIXME: For the TLS case, collect and use profiling information to | |
408 // determine a more accurate brach weight. | |
409 if (Kind == GuardKind::TlsGuard || D->getTLSKind()) | |
410 NumInits = InitsPerTLSVar; | |
411 else | |
412 NumInits = InitsPerLocalVar; | |
413 | |
414 // The probability of us entering the initializer is | |
415 // 1 / (total number of times we attempt to initialize the variable). | |
416 llvm::MDBuilder MDHelper(CGM.getLLVMContext()); | |
417 Weights = MDHelper.createBranchWeights(1, NumInits - 1); | |
418 } | |
419 | |
420 Builder.CreateCondBr(NeedsInit, InitBlock, NoInitBlock, Weights); | |
421 } | |
422 | |
221 | 423 llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction( |
150 | 424 llvm::FunctionType *FTy, const Twine &Name, const CGFunctionInfo &FI, |
425 SourceLocation Loc, bool TLS) { | |
221 | 426 llvm::Function *Fn = llvm::Function::Create( |
427 FTy, llvm::GlobalValue::InternalLinkage, Name, &getModule()); | |
428 | |
150 | 429 if (!getLangOpts().AppleKext && !TLS) { |
430 // Set the section if needed. | |
431 if (const char *Section = getTarget().getStaticInitSectionSpecifier()) | |
432 Fn->setSection(Section); | |
433 } | |
434 | |
435 SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); | |
436 | |
437 Fn->setCallingConv(getRuntimeCC()); | |
438 | |
439 if (!getLangOpts().Exceptions) | |
440 Fn->setDoesNotThrow(); | |
441 | |
442 if (getLangOpts().Sanitize.has(SanitizerKind::Address) && | |
221 | 443 !isInNoSanitizeList(SanitizerKind::Address, Fn, Loc)) |
150 | 444 Fn->addFnAttr(llvm::Attribute::SanitizeAddress); |
445 | |
446 if (getLangOpts().Sanitize.has(SanitizerKind::KernelAddress) && | |
221 | 447 !isInNoSanitizeList(SanitizerKind::KernelAddress, Fn, Loc)) |
150 | 448 Fn->addFnAttr(llvm::Attribute::SanitizeAddress); |
449 | |
450 if (getLangOpts().Sanitize.has(SanitizerKind::HWAddress) && | |
221 | 451 !isInNoSanitizeList(SanitizerKind::HWAddress, Fn, Loc)) |
150 | 452 Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); |
453 | |
454 if (getLangOpts().Sanitize.has(SanitizerKind::KernelHWAddress) && | |
221 | 455 !isInNoSanitizeList(SanitizerKind::KernelHWAddress, Fn, Loc)) |
150 | 456 Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); |
457 | |
458 if (getLangOpts().Sanitize.has(SanitizerKind::MemTag) && | |
221 | 459 !isInNoSanitizeList(SanitizerKind::MemTag, Fn, Loc)) |
150 | 460 Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); |
461 | |
462 if (getLangOpts().Sanitize.has(SanitizerKind::Thread) && | |
221 | 463 !isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc)) |
150 | 464 Fn->addFnAttr(llvm::Attribute::SanitizeThread); |
465 | |
466 if (getLangOpts().Sanitize.has(SanitizerKind::Memory) && | |
221 | 467 !isInNoSanitizeList(SanitizerKind::Memory, Fn, Loc)) |
150 | 468 Fn->addFnAttr(llvm::Attribute::SanitizeMemory); |
469 | |
470 if (getLangOpts().Sanitize.has(SanitizerKind::KernelMemory) && | |
221 | 471 !isInNoSanitizeList(SanitizerKind::KernelMemory, Fn, Loc)) |
150 | 472 Fn->addFnAttr(llvm::Attribute::SanitizeMemory); |
473 | |
474 if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack) && | |
221 | 475 !isInNoSanitizeList(SanitizerKind::SafeStack, Fn, Loc)) |
150 | 476 Fn->addFnAttr(llvm::Attribute::SafeStack); |
477 | |
478 if (getLangOpts().Sanitize.has(SanitizerKind::ShadowCallStack) && | |
221 | 479 !isInNoSanitizeList(SanitizerKind::ShadowCallStack, Fn, Loc)) |
150 | 480 Fn->addFnAttr(llvm::Attribute::ShadowCallStack); |
481 | |
482 return Fn; | |
483 } | |
484 | |
485 /// Create a global pointer to a function that will initialize a global | |
486 /// variable. The user has requested that this pointer be emitted in a specific | |
487 /// section. | |
488 void CodeGenModule::EmitPointerToInitFunc(const VarDecl *D, | |
489 llvm::GlobalVariable *GV, | |
490 llvm::Function *InitFunc, | |
491 InitSegAttr *ISA) { | |
492 llvm::GlobalVariable *PtrArray = new llvm::GlobalVariable( | |
493 TheModule, InitFunc->getType(), /*isConstant=*/true, | |
494 llvm::GlobalValue::PrivateLinkage, InitFunc, "__cxx_init_fn_ptr"); | |
495 PtrArray->setSection(ISA->getSection()); | |
496 addUsedGlobal(PtrArray); | |
497 | |
498 // If the GV is already in a comdat group, then we have to join it. | |
499 if (llvm::Comdat *C = GV->getComdat()) | |
500 PtrArray->setComdat(C); | |
501 } | |
502 | |
503 void | |
504 CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, | |
505 llvm::GlobalVariable *Addr, | |
506 bool PerformInit) { | |
507 | |
508 // According to E.2.3.1 in CUDA-7.5 Programming guide: __device__, | |
509 // __constant__ and __shared__ variables defined in namespace scope, | |
510 // that are of class type, cannot have a non-empty constructor. All | |
511 // the checks have been done in Sema by now. Whatever initializers | |
512 // are allowed are empty and we just need to ignore them here. | |
513 if (getLangOpts().CUDAIsDevice && !getLangOpts().GPUAllowDeviceInit && | |
514 (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() || | |
515 D->hasAttr<CUDASharedAttr>())) | |
516 return; | |
517 | |
518 if (getLangOpts().OpenMP && | |
519 getOpenMPRuntime().emitDeclareTargetVarDefinition(D, Addr, PerformInit)) | |
520 return; | |
521 | |
522 // Check if we've already initialized this decl. | |
523 auto I = DelayedCXXInitPosition.find(D); | |
524 if (I != DelayedCXXInitPosition.end() && I->second == ~0U) | |
525 return; | |
526 | |
527 llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); | |
528 SmallString<256> FnName; | |
529 { | |
530 llvm::raw_svector_ostream Out(FnName); | |
531 getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out); | |
532 } | |
533 | |
534 // Create a variable initialization function. | |
221 | 535 llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction( |
536 FTy, FnName.str(), getTypes().arrangeNullaryFunction(), D->getLocation()); | |
150 | 537 |
538 auto *ISA = D->getAttr<InitSegAttr>(); | |
539 CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr, | |
540 PerformInit); | |
541 | |
542 llvm::GlobalVariable *COMDATKey = | |
543 supportsCOMDAT() && D->isExternallyVisible() ? Addr : nullptr; | |
544 | |
545 if (D->getTLSKind()) { | |
546 // FIXME: Should we support init_priority for thread_local? | |
547 // FIXME: We only need to register one __cxa_thread_atexit function for the | |
548 // entire TU. | |
549 CXXThreadLocalInits.push_back(Fn); | |
550 CXXThreadLocalInitVars.push_back(D); | |
551 } else if (PerformInit && ISA) { | |
552 EmitPointerToInitFunc(D, Addr, Fn, ISA); | |
553 } else if (auto *IPA = D->getAttr<InitPriorityAttr>()) { | |
221 | 554 OrderGlobalInitsOrStermFinalizers Key(IPA->getPriority(), |
555 PrioritizedCXXGlobalInits.size()); | |
150 | 556 PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); |
557 } else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) || | |
558 getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR) { | |
559 // C++ [basic.start.init]p2: | |
560 // Definitions of explicitly specialized class template static data | |
561 // members have ordered initialization. Other class template static data | |
562 // members (i.e., implicitly or explicitly instantiated specializations) | |
563 // have unordered initialization. | |
564 // | |
565 // As a consequence, we can put them into their own llvm.global_ctors entry. | |
566 // | |
567 // If the global is externally visible, put the initializer into a COMDAT | |
568 // group with the global being initialized. On most platforms, this is a | |
569 // minor startup time optimization. In the MS C++ ABI, there are no guard | |
570 // variables, so this COMDAT key is required for correctness. | |
571 AddGlobalCtor(Fn, 65535, COMDATKey); | |
572 if (getTarget().getCXXABI().isMicrosoft() && COMDATKey) { | |
573 // In The MS C++, MS add template static data member in the linker | |
574 // drective. | |
575 addUsedGlobal(COMDATKey); | |
576 } | |
577 } else if (D->hasAttr<SelectAnyAttr>()) { | |
578 // SelectAny globals will be comdat-folded. Put the initializer into a | |
579 // COMDAT group associated with the global, so the initializers get folded | |
580 // too. | |
581 AddGlobalCtor(Fn, 65535, COMDATKey); | |
582 } else { | |
583 I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash. | |
584 if (I == DelayedCXXInitPosition.end()) { | |
585 CXXGlobalInits.push_back(Fn); | |
586 } else if (I->second != ~0U) { | |
587 assert(I->second < CXXGlobalInits.size() && | |
588 CXXGlobalInits[I->second] == nullptr); | |
589 CXXGlobalInits[I->second] = Fn; | |
590 } | |
591 } | |
592 | |
593 // Remember that we already emitted the initializer for this global. | |
594 DelayedCXXInitPosition[D] = ~0U; | |
595 } | |
596 | |
597 void CodeGenModule::EmitCXXThreadLocalInitFunc() { | |
598 getCXXABI().EmitThreadLocalInitFuncs( | |
599 *this, CXXThreadLocals, CXXThreadLocalInits, CXXThreadLocalInitVars); | |
600 | |
601 CXXThreadLocalInits.clear(); | |
602 CXXThreadLocalInitVars.clear(); | |
603 CXXThreadLocals.clear(); | |
604 } | |
605 | |
221 | 606 static SmallString<128> getTransformedFileName(llvm::Module &M) { |
607 SmallString<128> FileName = llvm::sys::path::filename(M.getName()); | |
608 | |
609 if (FileName.empty()) | |
610 FileName = "<null>"; | |
611 | |
612 for (size_t i = 0; i < FileName.size(); ++i) { | |
613 // Replace everything that's not [a-zA-Z0-9._] with a _. This set happens | |
614 // to be the set of C preprocessing numbers. | |
615 if (!isPreprocessingNumberBody(FileName[i])) | |
616 FileName[i] = '_'; | |
617 } | |
618 | |
619 return FileName; | |
620 } | |
621 | |
622 static std::string getPrioritySuffix(unsigned int Priority) { | |
623 assert(Priority <= 65535 && "Priority should always be <= 65535."); | |
624 | |
625 // Compute the function suffix from priority. Prepend with zeroes to make | |
626 // sure the function names are also ordered as priorities. | |
627 std::string PrioritySuffix = llvm::utostr(Priority); | |
628 PrioritySuffix = std::string(6 - PrioritySuffix.size(), '0') + PrioritySuffix; | |
629 | |
630 return PrioritySuffix; | |
631 } | |
632 | |
150 | 633 void |
634 CodeGenModule::EmitCXXGlobalInitFunc() { | |
635 while (!CXXGlobalInits.empty() && !CXXGlobalInits.back()) | |
636 CXXGlobalInits.pop_back(); | |
637 | |
638 if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty()) | |
639 return; | |
640 | |
641 llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); | |
642 const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction(); | |
643 | |
221 | 644 // Create our global prioritized initialization function. |
150 | 645 if (!PrioritizedCXXGlobalInits.empty()) { |
646 SmallVector<llvm::Function *, 8> LocalCXXGlobalInits; | |
647 llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(), | |
648 PrioritizedCXXGlobalInits.end()); | |
649 // Iterate over "chunks" of ctors with same priority and emit each chunk | |
650 // into separate function. Note - everything is sorted first by priority, | |
651 // second - by lex order, so we emit ctor functions in proper order. | |
652 for (SmallVectorImpl<GlobalInitData >::iterator | |
653 I = PrioritizedCXXGlobalInits.begin(), | |
654 E = PrioritizedCXXGlobalInits.end(); I != E; ) { | |
655 SmallVectorImpl<GlobalInitData >::iterator | |
656 PrioE = std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp()); | |
657 | |
658 LocalCXXGlobalInits.clear(); | |
221 | 659 |
660 unsigned int Priority = I->first.priority; | |
661 llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction( | |
662 FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI); | |
150 | 663 |
664 for (; I < PrioE; ++I) | |
665 LocalCXXGlobalInits.push_back(I->second); | |
666 | |
667 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, LocalCXXGlobalInits); | |
668 AddGlobalCtor(Fn, Priority); | |
669 } | |
670 PrioritizedCXXGlobalInits.clear(); | |
671 } | |
672 | |
221 | 673 if (getCXXABI().useSinitAndSterm() && CXXGlobalInits.empty()) |
674 return; | |
150 | 675 |
221 | 676 // Include the filename in the symbol name. Including "sub_" matches gcc |
677 // and makes sure these symbols appear lexicographically behind the symbols | |
678 // with priority emitted above. | |
679 llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction( | |
680 FTy, llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())), | |
681 FI); | |
150 | 682 |
683 CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits); | |
684 AddGlobalCtor(Fn); | |
685 | |
686 // In OpenCL global init functions must be converted to kernels in order to | |
687 // be able to launch them from the host. | |
688 // FIXME: Some more work might be needed to handle destructors correctly. | |
689 // Current initialization function makes use of function pointers callbacks. | |
690 // We can't support function pointers especially between host and device. | |
691 // However it seems global destruction has little meaning without any | |
692 // dynamic resource allocation on the device and program scope variables are | |
693 // destroyed by the runtime when program is released. | |
694 if (getLangOpts().OpenCL) { | |
695 GenOpenCLArgMetadata(Fn); | |
696 Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL); | |
697 } | |
698 | |
221 | 699 assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice || |
700 getLangOpts().GPUAllowDeviceInit); | |
701 if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) { | |
150 | 702 Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); |
703 Fn->addFnAttr("device-init"); | |
704 } | |
705 | |
706 CXXGlobalInits.clear(); | |
707 } | |
708 | |
221 | 709 void CodeGenModule::EmitCXXGlobalCleanUpFunc() { |
710 if (CXXGlobalDtorsOrStermFinalizers.empty() && | |
711 PrioritizedCXXStermFinalizers.empty()) | |
150 | 712 return; |
713 | |
714 llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); | |
221 | 715 const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction(); |
150 | 716 |
221 | 717 // Create our global prioritized cleanup function. |
718 if (!PrioritizedCXXStermFinalizers.empty()) { | |
719 SmallVector<CXXGlobalDtorsOrStermFinalizer_t, 8> LocalCXXStermFinalizers; | |
720 llvm::array_pod_sort(PrioritizedCXXStermFinalizers.begin(), | |
721 PrioritizedCXXStermFinalizers.end()); | |
722 // Iterate over "chunks" of dtors with same priority and emit each chunk | |
723 // into separate function. Note - everything is sorted first by priority, | |
724 // second - by lex order, so we emit dtor functions in proper order. | |
725 for (SmallVectorImpl<StermFinalizerData>::iterator | |
726 I = PrioritizedCXXStermFinalizers.begin(), | |
727 E = PrioritizedCXXStermFinalizers.end(); | |
728 I != E;) { | |
729 SmallVectorImpl<StermFinalizerData>::iterator PrioE = | |
730 std::upper_bound(I + 1, E, *I, StermFinalizerPriorityCmp()); | |
731 | |
732 LocalCXXStermFinalizers.clear(); | |
733 | |
734 unsigned int Priority = I->first.priority; | |
735 llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction( | |
736 FTy, "_GLOBAL__a_" + getPrioritySuffix(Priority), FI); | |
737 | |
738 for (; I < PrioE; ++I) { | |
739 llvm::FunctionCallee DtorFn = I->second; | |
740 LocalCXXStermFinalizers.emplace_back(DtorFn.getFunctionType(), | |
741 DtorFn.getCallee(), nullptr); | |
742 } | |
743 | |
744 CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc( | |
745 Fn, LocalCXXStermFinalizers); | |
746 AddGlobalDtor(Fn, Priority); | |
747 } | |
748 PrioritizedCXXStermFinalizers.clear(); | |
749 } | |
750 | |
751 if (CXXGlobalDtorsOrStermFinalizers.empty()) | |
752 return; | |
753 | |
754 // Create our global cleanup function. | |
150 | 755 llvm::Function *Fn = |
221 | 756 CreateGlobalInitOrCleanUpFunction(FTy, "_GLOBAL__D_a", FI); |
150 | 757 |
221 | 758 CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc( |
759 Fn, CXXGlobalDtorsOrStermFinalizers); | |
150 | 760 AddGlobalDtor(Fn); |
221 | 761 CXXGlobalDtorsOrStermFinalizers.clear(); |
150 | 762 } |
763 | |
764 /// Emit the code necessary to initialize the given global variable. | |
765 void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, | |
766 const VarDecl *D, | |
767 llvm::GlobalVariable *Addr, | |
768 bool PerformInit) { | |
769 // Check if we need to emit debug info for variable initializer. | |
770 if (D->hasAttr<NoDebugAttr>()) | |
771 DebugInfo = nullptr; // disable debug info indefinitely for this function | |
772 | |
773 CurEHLocation = D->getBeginLoc(); | |
774 | |
775 StartFunction(GlobalDecl(D, DynamicInitKind::Initializer), | |
776 getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(), | |
221 | 777 FunctionArgList()); |
778 // Emit an artificial location for this function. | |
779 auto AL = ApplyDebugLocation::CreateArtificial(*this); | |
150 | 780 |
781 // Use guarded initialization if the global variable is weak. This | |
782 // occurs for, e.g., instantiated static data members and | |
783 // definitions explicitly marked weak. | |
784 // | |
785 // Also use guarded initialization for a variable with dynamic TLS and | |
786 // unordered initialization. (If the initialization is ordered, the ABI | |
787 // layer will guard the whole-TU initialization for us.) | |
788 if (Addr->hasWeakLinkage() || Addr->hasLinkOnceLinkage() || | |
789 (D->getTLSKind() == VarDecl::TLS_Dynamic && | |
790 isTemplateInstantiation(D->getTemplateSpecializationKind()))) { | |
791 EmitCXXGuardedInit(*D, Addr, PerformInit); | |
792 } else { | |
793 EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit); | |
794 } | |
795 | |
796 FinishFunction(); | |
797 } | |
798 | |
799 void | |
800 CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, | |
801 ArrayRef<llvm::Function *> Decls, | |
802 ConstantAddress Guard) { | |
803 { | |
804 auto NL = ApplyDebugLocation::CreateEmpty(*this); | |
805 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, | |
806 getTypes().arrangeNullaryFunction(), FunctionArgList()); | |
807 // Emit an artificial location for this function. | |
808 auto AL = ApplyDebugLocation::CreateArtificial(*this); | |
809 | |
810 llvm::BasicBlock *ExitBlock = nullptr; | |
811 if (Guard.isValid()) { | |
812 // If we have a guard variable, check whether we've already performed | |
813 // these initializations. This happens for TLS initialization functions. | |
814 llvm::Value *GuardVal = Builder.CreateLoad(Guard); | |
815 llvm::Value *Uninit = Builder.CreateIsNull(GuardVal, | |
816 "guard.uninitialized"); | |
817 llvm::BasicBlock *InitBlock = createBasicBlock("init"); | |
818 ExitBlock = createBasicBlock("exit"); | |
819 EmitCXXGuardedInitBranch(Uninit, InitBlock, ExitBlock, | |
820 GuardKind::TlsGuard, nullptr); | |
821 EmitBlock(InitBlock); | |
822 // Mark as initialized before initializing anything else. If the | |
823 // initializers use previously-initialized thread_local vars, that's | |
824 // probably supposed to be OK, but the standard doesn't say. | |
825 Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard); | |
826 | |
827 // The guard variable can't ever change again. | |
828 EmitInvariantStart( | |
829 Guard.getPointer(), | |
830 CharUnits::fromQuantity( | |
831 CGM.getDataLayout().getTypeAllocSize(GuardVal->getType()))); | |
832 } | |
833 | |
834 RunCleanupsScope Scope(*this); | |
835 | |
836 // When building in Objective-C++ ARC mode, create an autorelease pool | |
837 // around the global initializers. | |
838 if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) { | |
839 llvm::Value *token = EmitObjCAutoreleasePoolPush(); | |
840 EmitObjCAutoreleasePoolCleanup(token); | |
841 } | |
842 | |
843 for (unsigned i = 0, e = Decls.size(); i != e; ++i) | |
844 if (Decls[i]) | |
845 EmitRuntimeCall(Decls[i]); | |
846 | |
847 Scope.ForceCleanup(); | |
848 | |
849 if (ExitBlock) { | |
850 Builder.CreateBr(ExitBlock); | |
851 EmitBlock(ExitBlock); | |
852 } | |
853 } | |
854 | |
855 FinishFunction(); | |
856 } | |
857 | |
221 | 858 void CodeGenFunction::GenerateCXXGlobalCleanUpFunc( |
150 | 859 llvm::Function *Fn, |
221 | 860 ArrayRef<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH, |
861 llvm::Constant *>> | |
862 DtorsOrStermFinalizers) { | |
150 | 863 { |
864 auto NL = ApplyDebugLocation::CreateEmpty(*this); | |
865 StartFunction(GlobalDecl(), getContext().VoidTy, Fn, | |
866 getTypes().arrangeNullaryFunction(), FunctionArgList()); | |
867 // Emit an artificial location for this function. | |
868 auto AL = ApplyDebugLocation::CreateArtificial(*this); | |
869 | |
221 | 870 // Emit the cleanups, in reverse order from construction. |
871 for (unsigned i = 0, e = DtorsOrStermFinalizers.size(); i != e; ++i) { | |
150 | 872 llvm::FunctionType *CalleeTy; |
873 llvm::Value *Callee; | |
874 llvm::Constant *Arg; | |
221 | 875 std::tie(CalleeTy, Callee, Arg) = DtorsOrStermFinalizers[e - i - 1]; |
876 | |
877 llvm::CallInst *CI = nullptr; | |
878 if (Arg == nullptr) { | |
879 assert( | |
880 CGM.getCXXABI().useSinitAndSterm() && | |
881 "Arg could not be nullptr unless using sinit and sterm functions."); | |
882 CI = Builder.CreateCall(CalleeTy, Callee); | |
883 } else | |
884 CI = Builder.CreateCall(CalleeTy, Callee, Arg); | |
885 | |
150 | 886 // Make sure the call and the callee agree on calling convention. |
887 if (llvm::Function *F = dyn_cast<llvm::Function>(Callee)) | |
888 CI->setCallingConv(F->getCallingConv()); | |
889 } | |
890 } | |
891 | |
892 FinishFunction(); | |
893 } | |
894 | |
895 /// generateDestroyHelper - Generates a helper function which, when | |
896 /// invoked, destroys the given object. The address of the object | |
897 /// should be in global memory. | |
898 llvm::Function *CodeGenFunction::generateDestroyHelper( | |
899 Address addr, QualType type, Destroyer *destroyer, | |
900 bool useEHCleanupForArray, const VarDecl *VD) { | |
901 FunctionArgList args; | |
902 ImplicitParamDecl Dst(getContext(), getContext().VoidPtrTy, | |
903 ImplicitParamDecl::Other); | |
904 args.push_back(&Dst); | |
905 | |
906 const CGFunctionInfo &FI = | |
907 CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, args); | |
908 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); | |
221 | 909 llvm::Function *fn = CGM.CreateGlobalInitOrCleanUpFunction( |
150 | 910 FTy, "__cxx_global_array_dtor", FI, VD->getLocation()); |
911 | |
912 CurEHLocation = VD->getBeginLoc(); | |
913 | |
221 | 914 StartFunction(GlobalDecl(VD, DynamicInitKind::GlobalArrayDestructor), |
915 getContext().VoidTy, fn, FI, args); | |
916 // Emit an artificial location for this function. | |
917 auto AL = ApplyDebugLocation::CreateArtificial(*this); | |
150 | 918 |
919 emitDestroy(addr, type, destroyer, useEHCleanupForArray); | |
920 | |
921 FinishFunction(); | |
922 | |
923 return fn; | |
924 } |