File: | clang/include/clang/CodeGen/CGFunctionInfo.h |
Warning: | line 429, column 10 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- CGVTables.cpp - Emit LLVM Code for C++ vtables -------------------===// | ||||
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 C++ code generation of virtual tables. | ||||
10 | // | ||||
11 | //===----------------------------------------------------------------------===// | ||||
12 | |||||
13 | #include "CGCXXABI.h" | ||||
14 | #include "CodeGenFunction.h" | ||||
15 | #include "CodeGenModule.h" | ||||
16 | #include "clang/AST/Attr.h" | ||||
17 | #include "clang/AST/CXXInheritance.h" | ||||
18 | #include "clang/AST/RecordLayout.h" | ||||
19 | #include "clang/Basic/CodeGenOptions.h" | ||||
20 | #include "clang/CodeGen/CGFunctionInfo.h" | ||||
21 | #include "clang/CodeGen/ConstantInitBuilder.h" | ||||
22 | #include "llvm/IR/IntrinsicInst.h" | ||||
23 | #include "llvm/Support/Format.h" | ||||
24 | #include "llvm/Transforms/Utils/Cloning.h" | ||||
25 | #include <algorithm> | ||||
26 | #include <cstdio> | ||||
27 | |||||
28 | using namespace clang; | ||||
29 | using namespace CodeGen; | ||||
30 | |||||
31 | CodeGenVTables::CodeGenVTables(CodeGenModule &CGM) | ||||
32 | : CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {} | ||||
33 | |||||
34 | llvm::Constant *CodeGenModule::GetAddrOfThunk(StringRef Name, llvm::Type *FnTy, | ||||
35 | GlobalDecl GD) { | ||||
36 | return GetOrCreateLLVMFunction(Name, FnTy, GD, /*ForVTable=*/true, | ||||
37 | /*DontDefer=*/true, /*IsThunk=*/true); | ||||
38 | } | ||||
39 | |||||
40 | static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk, | ||||
41 | llvm::Function *ThunkFn, bool ForVTable, | ||||
42 | GlobalDecl GD) { | ||||
43 | CGM.setFunctionLinkage(GD, ThunkFn); | ||||
44 | CGM.getCXXABI().setThunkLinkage(ThunkFn, ForVTable, GD, | ||||
45 | !Thunk.Return.isEmpty()); | ||||
46 | |||||
47 | // Set the right visibility. | ||||
48 | CGM.setGVProperties(ThunkFn, GD); | ||||
49 | |||||
50 | if (!CGM.getCXXABI().exportThunk()) { | ||||
51 | ThunkFn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); | ||||
52 | ThunkFn->setDSOLocal(true); | ||||
53 | } | ||||
54 | |||||
55 | if (CGM.supportsCOMDAT() && ThunkFn->isWeakForLinker()) | ||||
56 | ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName())); | ||||
57 | } | ||||
58 | |||||
59 | #ifndef NDEBUG | ||||
60 | static bool similar(const ABIArgInfo &infoL, CanQualType typeL, | ||||
61 | const ABIArgInfo &infoR, CanQualType typeR) { | ||||
62 | return (infoL.getKind() == infoR.getKind() && | ||||
63 | (typeL == typeR || | ||||
64 | (isa<PointerType>(typeL) && isa<PointerType>(typeR)) || | ||||
65 | (isa<ReferenceType>(typeL) && isa<ReferenceType>(typeR)))); | ||||
66 | } | ||||
67 | #endif | ||||
68 | |||||
69 | static RValue PerformReturnAdjustment(CodeGenFunction &CGF, | ||||
70 | QualType ResultType, RValue RV, | ||||
71 | const ThunkInfo &Thunk) { | ||||
72 | // Emit the return adjustment. | ||||
73 | bool NullCheckValue = !ResultType->isReferenceType(); | ||||
74 | |||||
75 | llvm::BasicBlock *AdjustNull = nullptr; | ||||
76 | llvm::BasicBlock *AdjustNotNull = nullptr; | ||||
77 | llvm::BasicBlock *AdjustEnd = nullptr; | ||||
78 | |||||
79 | llvm::Value *ReturnValue = RV.getScalarVal(); | ||||
80 | |||||
81 | if (NullCheckValue) { | ||||
82 | AdjustNull = CGF.createBasicBlock("adjust.null"); | ||||
83 | AdjustNotNull = CGF.createBasicBlock("adjust.notnull"); | ||||
84 | AdjustEnd = CGF.createBasicBlock("adjust.end"); | ||||
85 | |||||
86 | llvm::Value *IsNull = CGF.Builder.CreateIsNull(ReturnValue); | ||||
87 | CGF.Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull); | ||||
88 | CGF.EmitBlock(AdjustNotNull); | ||||
89 | } | ||||
90 | |||||
91 | auto ClassDecl = ResultType->getPointeeType()->getAsCXXRecordDecl(); | ||||
92 | auto ClassAlign = CGF.CGM.getClassPointerAlignment(ClassDecl); | ||||
93 | ReturnValue = CGF.CGM.getCXXABI().performReturnAdjustment(CGF, | ||||
94 | Address(ReturnValue, ClassAlign), | ||||
95 | Thunk.Return); | ||||
96 | |||||
97 | if (NullCheckValue) { | ||||
98 | CGF.Builder.CreateBr(AdjustEnd); | ||||
99 | CGF.EmitBlock(AdjustNull); | ||||
100 | CGF.Builder.CreateBr(AdjustEnd); | ||||
101 | CGF.EmitBlock(AdjustEnd); | ||||
102 | |||||
103 | llvm::PHINode *PHI = CGF.Builder.CreatePHI(ReturnValue->getType(), 2); | ||||
104 | PHI->addIncoming(ReturnValue, AdjustNotNull); | ||||
105 | PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()), | ||||
106 | AdjustNull); | ||||
107 | ReturnValue = PHI; | ||||
108 | } | ||||
109 | |||||
110 | return RValue::get(ReturnValue); | ||||
111 | } | ||||
112 | |||||
113 | /// This function clones a function's DISubprogram node and enters it into | ||||
114 | /// a value map with the intent that the map can be utilized by the cloner | ||||
115 | /// to short-circuit Metadata node mapping. | ||||
116 | /// Furthermore, the function resolves any DILocalVariable nodes referenced | ||||
117 | /// by dbg.value intrinsics so they can be properly mapped during cloning. | ||||
118 | static void resolveTopLevelMetadata(llvm::Function *Fn, | ||||
119 | llvm::ValueToValueMapTy &VMap) { | ||||
120 | // Clone the DISubprogram node and put it into the Value map. | ||||
121 | auto *DIS = Fn->getSubprogram(); | ||||
122 | if (!DIS) | ||||
123 | return; | ||||
124 | auto *NewDIS = DIS->replaceWithDistinct(DIS->clone()); | ||||
125 | VMap.MD()[DIS].reset(NewDIS); | ||||
126 | |||||
127 | // Find all llvm.dbg.declare intrinsics and resolve the DILocalVariable nodes | ||||
128 | // they are referencing. | ||||
129 | for (auto &BB : Fn->getBasicBlockList()) { | ||||
130 | for (auto &I : BB) { | ||||
131 | if (auto *DII = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) { | ||||
132 | auto *DILocal = DII->getVariable(); | ||||
133 | if (!DILocal->isResolved()) | ||||
134 | DILocal->resolve(); | ||||
135 | } | ||||
136 | } | ||||
137 | } | ||||
138 | } | ||||
139 | |||||
140 | // This function does roughly the same thing as GenerateThunk, but in a | ||||
141 | // very different way, so that va_start and va_end work correctly. | ||||
142 | // FIXME: This function assumes "this" is the first non-sret LLVM argument of | ||||
143 | // a function, and that there is an alloca built in the entry block | ||||
144 | // for all accesses to "this". | ||||
145 | // FIXME: This function assumes there is only one "ret" statement per function. | ||||
146 | // FIXME: Cloning isn't correct in the presence of indirect goto! | ||||
147 | // FIXME: This implementation of thunks bloats codesize by duplicating the | ||||
148 | // function definition. There are alternatives: | ||||
149 | // 1. Add some sort of stub support to LLVM for cases where we can | ||||
150 | // do a this adjustment, then a sibcall. | ||||
151 | // 2. We could transform the definition to take a va_list instead of an | ||||
152 | // actual variable argument list, then have the thunks (including a | ||||
153 | // no-op thunk for the regular definition) call va_start/va_end. | ||||
154 | // There's a bit of per-call overhead for this solution, but it's | ||||
155 | // better for codesize if the definition is long. | ||||
156 | llvm::Function * | ||||
157 | CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, | ||||
158 | const CGFunctionInfo &FnInfo, | ||||
159 | GlobalDecl GD, const ThunkInfo &Thunk) { | ||||
160 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); | ||||
161 | const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); | ||||
162 | QualType ResultType = FPT->getReturnType(); | ||||
163 | |||||
164 | // Get the original function | ||||
165 | assert(FnInfo.isVariadic())((FnInfo.isVariadic()) ? static_cast<void> (0) : __assert_fail ("FnInfo.isVariadic()", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 165, __PRETTY_FUNCTION__)); | ||||
166 | llvm::Type *Ty = CGM.getTypes().GetFunctionType(FnInfo); | ||||
167 | llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); | ||||
168 | llvm::Function *BaseFn = cast<llvm::Function>(Callee); | ||||
169 | |||||
170 | // Cloning can't work if we don't have a definition. The Microsoft ABI may | ||||
171 | // require thunks when a definition is not available. Emit an error in these | ||||
172 | // cases. | ||||
173 | if (!MD->isDefined()) { | ||||
174 | CGM.ErrorUnsupported(MD, "return-adjusting thunk with variadic arguments"); | ||||
175 | return Fn; | ||||
176 | } | ||||
177 | assert(!BaseFn->isDeclaration() && "cannot clone undefined variadic method")((!BaseFn->isDeclaration() && "cannot clone undefined variadic method" ) ? static_cast<void> (0) : __assert_fail ("!BaseFn->isDeclaration() && \"cannot clone undefined variadic method\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 177, __PRETTY_FUNCTION__)); | ||||
178 | |||||
179 | // Clone to thunk. | ||||
180 | llvm::ValueToValueMapTy VMap; | ||||
181 | |||||
182 | // We are cloning a function while some Metadata nodes are still unresolved. | ||||
183 | // Ensure that the value mapper does not encounter any of them. | ||||
184 | resolveTopLevelMetadata(BaseFn, VMap); | ||||
185 | llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap); | ||||
186 | Fn->replaceAllUsesWith(NewFn); | ||||
187 | NewFn->takeName(Fn); | ||||
188 | Fn->eraseFromParent(); | ||||
189 | Fn = NewFn; | ||||
190 | |||||
191 | // "Initialize" CGF (minimally). | ||||
192 | CurFn = Fn; | ||||
193 | |||||
194 | // Get the "this" value | ||||
195 | llvm::Function::arg_iterator AI = Fn->arg_begin(); | ||||
196 | if (CGM.ReturnTypeUsesSRet(FnInfo)) | ||||
197 | ++AI; | ||||
198 | |||||
199 | // Find the first store of "this", which will be to the alloca associated | ||||
200 | // with "this". | ||||
201 | Address ThisPtr(&*AI, CGM.getClassPointerAlignment(MD->getParent())); | ||||
202 | llvm::BasicBlock *EntryBB = &Fn->front(); | ||||
203 | llvm::BasicBlock::iterator ThisStore = | ||||
204 | std::find_if(EntryBB->begin(), EntryBB->end(), [&](llvm::Instruction &I) { | ||||
205 | return isa<llvm::StoreInst>(I) && | ||||
206 | I.getOperand(0) == ThisPtr.getPointer(); | ||||
207 | }); | ||||
208 | assert(ThisStore != EntryBB->end() &&((ThisStore != EntryBB->end() && "Store of this should be in entry block?" ) ? static_cast<void> (0) : __assert_fail ("ThisStore != EntryBB->end() && \"Store of this should be in entry block?\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 209, __PRETTY_FUNCTION__)) | ||||
209 | "Store of this should be in entry block?")((ThisStore != EntryBB->end() && "Store of this should be in entry block?" ) ? static_cast<void> (0) : __assert_fail ("ThisStore != EntryBB->end() && \"Store of this should be in entry block?\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 209, __PRETTY_FUNCTION__)); | ||||
210 | // Adjust "this", if necessary. | ||||
211 | Builder.SetInsertPoint(&*ThisStore); | ||||
212 | llvm::Value *AdjustedThisPtr = | ||||
213 | CGM.getCXXABI().performThisAdjustment(*this, ThisPtr, Thunk.This); | ||||
214 | AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, | ||||
215 | ThisStore->getOperand(0)->getType()); | ||||
216 | ThisStore->setOperand(0, AdjustedThisPtr); | ||||
217 | |||||
218 | if (!Thunk.Return.isEmpty()) { | ||||
219 | // Fix up the returned value, if necessary. | ||||
220 | for (llvm::BasicBlock &BB : *Fn) { | ||||
221 | llvm::Instruction *T = BB.getTerminator(); | ||||
222 | if (isa<llvm::ReturnInst>(T)) { | ||||
223 | RValue RV = RValue::get(T->getOperand(0)); | ||||
224 | T->eraseFromParent(); | ||||
225 | Builder.SetInsertPoint(&BB); | ||||
226 | RV = PerformReturnAdjustment(*this, ResultType, RV, Thunk); | ||||
227 | Builder.CreateRet(RV.getScalarVal()); | ||||
228 | break; | ||||
229 | } | ||||
230 | } | ||||
231 | } | ||||
232 | |||||
233 | return Fn; | ||||
234 | } | ||||
235 | |||||
236 | void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, | ||||
237 | const CGFunctionInfo &FnInfo, | ||||
238 | bool IsUnprototyped) { | ||||
239 | assert(!CurGD.getDecl() && "CurGD was already set!")((!CurGD.getDecl() && "CurGD was already set!") ? static_cast <void> (0) : __assert_fail ("!CurGD.getDecl() && \"CurGD was already set!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 239, __PRETTY_FUNCTION__)); | ||||
240 | CurGD = GD; | ||||
241 | CurFuncIsThunk = true; | ||||
242 | |||||
243 | // Build FunctionArgs. | ||||
244 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); | ||||
245 | QualType ThisType = MD->getThisType(); | ||||
246 | QualType ResultType; | ||||
247 | if (IsUnprototyped) | ||||
248 | ResultType = CGM.getContext().VoidTy; | ||||
249 | else if (CGM.getCXXABI().HasThisReturn(GD)) | ||||
250 | ResultType = ThisType; | ||||
251 | else if (CGM.getCXXABI().hasMostDerivedReturn(GD)) | ||||
252 | ResultType = CGM.getContext().VoidPtrTy; | ||||
253 | else | ||||
254 | ResultType = MD->getType()->castAs<FunctionProtoType>()->getReturnType(); | ||||
255 | FunctionArgList FunctionArgs; | ||||
256 | |||||
257 | // Create the implicit 'this' parameter declaration. | ||||
258 | CGM.getCXXABI().buildThisParam(*this, FunctionArgs); | ||||
259 | |||||
260 | // Add the rest of the parameters, if we have a prototype to work with. | ||||
261 | if (!IsUnprototyped) { | ||||
262 | FunctionArgs.append(MD->param_begin(), MD->param_end()); | ||||
263 | |||||
264 | if (isa<CXXDestructorDecl>(MD)) | ||||
265 | CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, | ||||
266 | FunctionArgs); | ||||
267 | } | ||||
268 | |||||
269 | // Start defining the function. | ||||
270 | auto NL = ApplyDebugLocation::CreateEmpty(*this); | ||||
271 | StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, | ||||
272 | MD->getLocation()); | ||||
273 | // Create a scope with an artificial location for the body of this function. | ||||
274 | auto AL = ApplyDebugLocation::CreateArtificial(*this); | ||||
275 | |||||
276 | // Since we didn't pass a GlobalDecl to StartFunction, do this ourselves. | ||||
277 | CGM.getCXXABI().EmitInstanceFunctionProlog(*this); | ||||
278 | CXXThisValue = CXXABIThisValue; | ||||
279 | CurCodeDecl = MD; | ||||
280 | CurFuncDecl = MD; | ||||
281 | } | ||||
282 | |||||
283 | void CodeGenFunction::FinishThunk() { | ||||
284 | // Clear these to restore the invariants expected by | ||||
285 | // StartFunction/FinishFunction. | ||||
286 | CurCodeDecl = nullptr; | ||||
287 | CurFuncDecl = nullptr; | ||||
288 | |||||
289 | FinishFunction(); | ||||
290 | } | ||||
291 | |||||
292 | void CodeGenFunction::EmitCallAndReturnForThunk(llvm::FunctionCallee Callee, | ||||
293 | const ThunkInfo *Thunk, | ||||
294 | bool IsUnprototyped) { | ||||
295 | assert(isa<CXXMethodDecl>(CurGD.getDecl()) &&((isa<CXXMethodDecl>(CurGD.getDecl()) && "Please use a new CGF for this thunk" ) ? static_cast<void> (0) : __assert_fail ("isa<CXXMethodDecl>(CurGD.getDecl()) && \"Please use a new CGF for this thunk\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 296, __PRETTY_FUNCTION__)) | ||||
296 | "Please use a new CGF for this thunk")((isa<CXXMethodDecl>(CurGD.getDecl()) && "Please use a new CGF for this thunk" ) ? static_cast<void> (0) : __assert_fail ("isa<CXXMethodDecl>(CurGD.getDecl()) && \"Please use a new CGF for this thunk\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 296, __PRETTY_FUNCTION__)); | ||||
297 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(CurGD.getDecl()); | ||||
298 | |||||
299 | // Adjust the 'this' pointer if necessary | ||||
300 | llvm::Value *AdjustedThisPtr = | ||||
301 | Thunk
| ||||
302 | *this, LoadCXXThisAddress(), Thunk->This) | ||||
303 | : LoadCXXThis(); | ||||
304 | |||||
305 | // If perfect forwarding is required a variadic method, a method using | ||||
306 | // inalloca, or an unprototyped thunk, use musttail. Emit an error if this | ||||
307 | // thunk requires a return adjustment, since that is impossible with musttail. | ||||
308 | if (CurFnInfo->usesInAlloca() || CurFnInfo->isVariadic() || IsUnprototyped
| ||||
309 | if (Thunk && !Thunk->Return.isEmpty()) { | ||||
310 | if (IsUnprototyped) | ||||
311 | CGM.ErrorUnsupported( | ||||
312 | MD, "return-adjusting thunk with incomplete parameter type"); | ||||
313 | else if (CurFnInfo->isVariadic()) | ||||
314 | llvm_unreachable("shouldn't try to emit musttail return-adjusting "::llvm::llvm_unreachable_internal("shouldn't try to emit musttail return-adjusting " "thunks for variadic functions", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 315) | ||||
315 | "thunks for variadic functions")::llvm::llvm_unreachable_internal("shouldn't try to emit musttail return-adjusting " "thunks for variadic functions", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 315); | ||||
316 | else | ||||
317 | CGM.ErrorUnsupported( | ||||
318 | MD, "non-trivial argument copy for return-adjusting thunk"); | ||||
319 | } | ||||
320 | EmitMustTailThunk(CurGD, AdjustedThisPtr, Callee); | ||||
321 | return; | ||||
322 | } | ||||
323 | |||||
324 | // Start building CallArgs. | ||||
325 | CallArgList CallArgs; | ||||
326 | QualType ThisType = MD->getThisType(); | ||||
327 | CallArgs.add(RValue::get(AdjustedThisPtr), ThisType); | ||||
328 | |||||
329 | if (isa<CXXDestructorDecl>(MD)) | ||||
330 | CGM.getCXXABI().adjustCallArgsForDestructorThunk(*this, CurGD, CallArgs); | ||||
331 | |||||
332 | #ifndef NDEBUG | ||||
333 | unsigned PrefixArgs = CallArgs.size() - 1; | ||||
334 | #endif | ||||
335 | // Add the rest of the arguments. | ||||
336 | for (const ParmVarDecl *PD : MD->parameters()) | ||||
337 | EmitDelegateCallArg(CallArgs, PD, SourceLocation()); | ||||
338 | |||||
339 | const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); | ||||
340 | |||||
341 | #ifndef NDEBUG | ||||
342 | const CGFunctionInfo &CallFnInfo = CGM.getTypes().arrangeCXXMethodCall( | ||||
343 | CallArgs, FPT, RequiredArgs::forPrototypePlus(FPT, 1), PrefixArgs); | ||||
344 | assert(CallFnInfo.getRegParm() == CurFnInfo->getRegParm() &&((CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention ()) ? static_cast<void> (0) : __assert_fail ("CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention()" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 346, __PRETTY_FUNCTION__)) | ||||
345 | CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() &&((CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention ()) ? static_cast<void> (0) : __assert_fail ("CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention()" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 346, __PRETTY_FUNCTION__)) | ||||
346 | CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention())((CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention ()) ? static_cast<void> (0) : __assert_fail ("CallFnInfo.getRegParm() == CurFnInfo->getRegParm() && CallFnInfo.isNoReturn() == CurFnInfo->isNoReturn() && CallFnInfo.getCallingConvention() == CurFnInfo->getCallingConvention()" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 346, __PRETTY_FUNCTION__)); | ||||
347 | assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types((isa<CXXDestructorDecl>(MD) || similar(CallFnInfo.getReturnInfo (), CallFnInfo.getReturnType(), CurFnInfo->getReturnInfo() , CurFnInfo->getReturnType())) ? static_cast<void> ( 0) : __assert_fail ("isa<CXXDestructorDecl>(MD) || similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType())" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 349, __PRETTY_FUNCTION__)) | ||||
348 | similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),((isa<CXXDestructorDecl>(MD) || similar(CallFnInfo.getReturnInfo (), CallFnInfo.getReturnType(), CurFnInfo->getReturnInfo() , CurFnInfo->getReturnType())) ? static_cast<void> ( 0) : __assert_fail ("isa<CXXDestructorDecl>(MD) || similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType())" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 349, __PRETTY_FUNCTION__)) | ||||
349 | CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType()))((isa<CXXDestructorDecl>(MD) || similar(CallFnInfo.getReturnInfo (), CallFnInfo.getReturnType(), CurFnInfo->getReturnInfo() , CurFnInfo->getReturnType())) ? static_cast<void> ( 0) : __assert_fail ("isa<CXXDestructorDecl>(MD) || similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), CurFnInfo->getReturnInfo(), CurFnInfo->getReturnType())" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 349, __PRETTY_FUNCTION__)); | ||||
350 | assert(CallFnInfo.arg_size() == CurFnInfo->arg_size())((CallFnInfo.arg_size() == CurFnInfo->arg_size()) ? static_cast <void> (0) : __assert_fail ("CallFnInfo.arg_size() == CurFnInfo->arg_size()" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 350, __PRETTY_FUNCTION__)); | ||||
351 | for (unsigned i = 0, e = CurFnInfo->arg_size(); i != e; ++i) | ||||
352 | assert(similar(CallFnInfo.arg_begin()[i].info,((similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin ()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo-> arg_begin()[i].type)) ? static_cast<void> (0) : __assert_fail ("similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo->arg_begin()[i].type)" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 355, __PRETTY_FUNCTION__)) | ||||
353 | CallFnInfo.arg_begin()[i].type,((similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin ()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo-> arg_begin()[i].type)) ? static_cast<void> (0) : __assert_fail ("similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo->arg_begin()[i].type)" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 355, __PRETTY_FUNCTION__)) | ||||
354 | CurFnInfo->arg_begin()[i].info,((similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin ()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo-> arg_begin()[i].type)) ? static_cast<void> (0) : __assert_fail ("similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo->arg_begin()[i].type)" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 355, __PRETTY_FUNCTION__)) | ||||
355 | CurFnInfo->arg_begin()[i].type))((similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin ()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo-> arg_begin()[i].type)) ? static_cast<void> (0) : __assert_fail ("similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin()[i].type, CurFnInfo->arg_begin()[i].info, CurFnInfo->arg_begin()[i].type)" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 355, __PRETTY_FUNCTION__)); | ||||
356 | #endif | ||||
357 | |||||
358 | // Determine whether we have a return value slot to use. | ||||
359 | QualType ResultType = CGM.getCXXABI().HasThisReturn(CurGD) | ||||
360 | ? ThisType | ||||
361 | : CGM.getCXXABI().hasMostDerivedReturn(CurGD) | ||||
362 | ? CGM.getContext().VoidPtrTy | ||||
363 | : FPT->getReturnType(); | ||||
364 | ReturnValueSlot Slot; | ||||
365 | if (!ResultType->isVoidType() && | ||||
366 | CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) | ||||
367 | Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified()); | ||||
368 | |||||
369 | // Now emit our call. | ||||
370 | llvm::CallBase *CallOrInvoke; | ||||
371 | RValue RV = EmitCall(*CurFnInfo, CGCallee::forDirect(Callee, CurGD), Slot, | ||||
372 | CallArgs, &CallOrInvoke); | ||||
373 | |||||
374 | // Consider return adjustment if we have ThunkInfo. | ||||
375 | if (Thunk && !Thunk->Return.isEmpty()) | ||||
376 | RV = PerformReturnAdjustment(*this, ResultType, RV, *Thunk); | ||||
377 | else if (llvm::CallInst* Call = dyn_cast<llvm::CallInst>(CallOrInvoke)) | ||||
378 | Call->setTailCallKind(llvm::CallInst::TCK_Tail); | ||||
379 | |||||
380 | // Emit return. | ||||
381 | if (!ResultType->isVoidType() && Slot.isNull()) | ||||
382 | CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType); | ||||
383 | |||||
384 | // Disable the final ARC autorelease. | ||||
385 | AutoreleaseResult = false; | ||||
386 | |||||
387 | FinishThunk(); | ||||
388 | } | ||||
389 | |||||
390 | void CodeGenFunction::EmitMustTailThunk(GlobalDecl GD, | ||||
391 | llvm::Value *AdjustedThisPtr, | ||||
392 | llvm::FunctionCallee Callee) { | ||||
393 | // Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery | ||||
394 | // to translate AST arguments into LLVM IR arguments. For thunks, we know | ||||
395 | // that the caller prototype more or less matches the callee prototype with | ||||
396 | // the exception of 'this'. | ||||
397 | SmallVector<llvm::Value *, 8> Args; | ||||
398 | for (llvm::Argument &A : CurFn->args()) | ||||
399 | Args.push_back(&A); | ||||
400 | |||||
401 | // Set the adjusted 'this' pointer. | ||||
402 | const ABIArgInfo &ThisAI = CurFnInfo->arg_begin()->info; | ||||
403 | if (ThisAI.isDirect()) { | ||||
404 | const ABIArgInfo &RetAI = CurFnInfo->getReturnInfo(); | ||||
405 | int ThisArgNo = RetAI.isIndirect() && !RetAI.isSRetAfterThis() ? 1 : 0; | ||||
406 | llvm::Type *ThisType = Args[ThisArgNo]->getType(); | ||||
407 | if (ThisType != AdjustedThisPtr->getType()) | ||||
408 | AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, ThisType); | ||||
409 | Args[ThisArgNo] = AdjustedThisPtr; | ||||
410 | } else { | ||||
411 | assert(ThisAI.isInAlloca() && "this is passed directly or inalloca")((ThisAI.isInAlloca() && "this is passed directly or inalloca" ) ? static_cast<void> (0) : __assert_fail ("ThisAI.isInAlloca() && \"this is passed directly or inalloca\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 411, __PRETTY_FUNCTION__)); | ||||
412 | Address ThisAddr = GetAddrOfLocalVar(CXXABIThisDecl); | ||||
413 | llvm::Type *ThisType = ThisAddr.getElementType(); | ||||
414 | if (ThisType != AdjustedThisPtr->getType()) | ||||
415 | AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, ThisType); | ||||
416 | Builder.CreateStore(AdjustedThisPtr, ThisAddr); | ||||
417 | } | ||||
418 | |||||
419 | // Emit the musttail call manually. Even if the prologue pushed cleanups, we | ||||
420 | // don't actually want to run them. | ||||
421 | llvm::CallInst *Call = Builder.CreateCall(Callee, Args); | ||||
422 | Call->setTailCallKind(llvm::CallInst::TCK_MustTail); | ||||
423 | |||||
424 | // Apply the standard set of call attributes. | ||||
425 | unsigned CallingConv; | ||||
426 | llvm::AttributeList Attrs; | ||||
427 | CGM.ConstructAttributeList(Callee.getCallee()->getName(), *CurFnInfo, GD, | ||||
428 | Attrs, CallingConv, /*AttrOnCallSite=*/true); | ||||
429 | Call->setAttributes(Attrs); | ||||
430 | Call->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); | ||||
431 | |||||
432 | if (Call->getType()->isVoidTy()) | ||||
433 | Builder.CreateRetVoid(); | ||||
434 | else | ||||
435 | Builder.CreateRet(Call); | ||||
436 | |||||
437 | // Finish the function to maintain CodeGenFunction invariants. | ||||
438 | // FIXME: Don't emit unreachable code. | ||||
439 | EmitBlock(createBasicBlock()); | ||||
440 | FinishFunction(); | ||||
441 | } | ||||
442 | |||||
443 | void CodeGenFunction::generateThunk(llvm::Function *Fn, | ||||
444 | const CGFunctionInfo &FnInfo, GlobalDecl GD, | ||||
445 | const ThunkInfo &Thunk, | ||||
446 | bool IsUnprototyped) { | ||||
447 | StartThunk(Fn, GD, FnInfo, IsUnprototyped); | ||||
448 | // Create a scope with an artificial location for the body of this function. | ||||
449 | auto AL = ApplyDebugLocation::CreateArtificial(*this); | ||||
450 | |||||
451 | // Get our callee. Use a placeholder type if this method is unprototyped so | ||||
452 | // that CodeGenModule doesn't try to set attributes. | ||||
453 | llvm::Type *Ty; | ||||
454 | if (IsUnprototyped
| ||||
455 | Ty = llvm::StructType::get(getLLVMContext()); | ||||
456 | else | ||||
457 | Ty = CGM.getTypes().GetFunctionType(FnInfo); | ||||
458 | |||||
459 | llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); | ||||
460 | |||||
461 | // Fix up the function type for an unprototyped musttail call. | ||||
462 | if (IsUnprototyped
| ||||
463 | Callee = llvm::ConstantExpr::getBitCast(Callee, Fn->getType()); | ||||
464 | |||||
465 | // Make the call and return the result. | ||||
466 | EmitCallAndReturnForThunk(llvm::FunctionCallee(Fn->getFunctionType(), Callee), | ||||
467 | &Thunk, IsUnprototyped); | ||||
468 | } | ||||
469 | |||||
470 | static bool shouldEmitVTableThunk(CodeGenModule &CGM, const CXXMethodDecl *MD, | ||||
471 | bool IsUnprototyped, bool ForVTable) { | ||||
472 | // Always emit thunks in the MS C++ ABI. We cannot rely on other TUs to | ||||
473 | // provide thunks for us. | ||||
474 | if (CGM.getTarget().getCXXABI().isMicrosoft()) | ||||
475 | return true; | ||||
476 | |||||
477 | // In the Itanium C++ ABI, vtable thunks are provided by TUs that provide | ||||
478 | // definitions of the main method. Therefore, emitting thunks with the vtable | ||||
479 | // is purely an optimization. Emit the thunk if optimizations are enabled and | ||||
480 | // all of the parameter types are complete. | ||||
481 | if (ForVTable) | ||||
482 | return CGM.getCodeGenOpts().OptimizationLevel && !IsUnprototyped; | ||||
483 | |||||
484 | // Always emit thunks along with the method definition. | ||||
485 | return true; | ||||
486 | } | ||||
487 | |||||
488 | llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD, | ||||
489 | const ThunkInfo &TI, | ||||
490 | bool ForVTable) { | ||||
491 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); | ||||
492 | |||||
493 | // First, get a declaration. Compute the mangled name. Don't worry about | ||||
494 | // getting the function prototype right, since we may only need this | ||||
495 | // declaration to fill in a vtable slot. | ||||
496 | SmallString<256> Name; | ||||
497 | MangleContext &MCtx = CGM.getCXXABI().getMangleContext(); | ||||
498 | llvm::raw_svector_ostream Out(Name); | ||||
499 | if (const CXXDestructorDecl *DD
| ||||
500 | MCtx.mangleCXXDtorThunk(DD, GD.getDtorType(), TI.This, Out); | ||||
501 | else | ||||
502 | MCtx.mangleThunk(MD, TI, Out); | ||||
503 | llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD); | ||||
504 | llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD); | ||||
505 | |||||
506 | // If we don't need to emit a definition, return this declaration as is. | ||||
507 | bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible( | ||||
508 | MD->getType()->castAs<FunctionType>()); | ||||
509 | if (!shouldEmitVTableThunk(CGM, MD, IsUnprototyped, ForVTable)) | ||||
510 | return Thunk; | ||||
511 | |||||
512 | // Arrange a function prototype appropriate for a function definition. In some | ||||
513 | // cases in the MS ABI, we may need to build an unprototyped musttail thunk. | ||||
514 | const CGFunctionInfo &FnInfo = | ||||
515 | IsUnprototyped
| ||||
516 | : CGM.getTypes().arrangeGlobalDeclaration(GD); | ||||
517 | llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo); | ||||
518 | |||||
519 | // If the type of the underlying GlobalValue is wrong, we'll have to replace | ||||
520 | // it. It should be a declaration. | ||||
521 | llvm::Function *ThunkFn = cast<llvm::Function>(Thunk->stripPointerCasts()); | ||||
522 | if (ThunkFn->getFunctionType() != ThunkFnTy) { | ||||
523 | llvm::GlobalValue *OldThunkFn = ThunkFn; | ||||
524 | |||||
525 | assert(OldThunkFn->isDeclaration() && "Shouldn't replace non-declaration")((OldThunkFn->isDeclaration() && "Shouldn't replace non-declaration" ) ? static_cast<void> (0) : __assert_fail ("OldThunkFn->isDeclaration() && \"Shouldn't replace non-declaration\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 525, __PRETTY_FUNCTION__)); | ||||
526 | |||||
527 | // Remove the name from the old thunk function and get a new thunk. | ||||
528 | OldThunkFn->setName(StringRef()); | ||||
529 | ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage, | ||||
530 | Name.str(), &CGM.getModule()); | ||||
531 | CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn); | ||||
532 | |||||
533 | // If needed, replace the old thunk with a bitcast. | ||||
534 | if (!OldThunkFn->use_empty()) { | ||||
535 | llvm::Constant *NewPtrForOldDecl = | ||||
536 | llvm::ConstantExpr::getBitCast(ThunkFn, OldThunkFn->getType()); | ||||
537 | OldThunkFn->replaceAllUsesWith(NewPtrForOldDecl); | ||||
538 | } | ||||
539 | |||||
540 | // Remove the old thunk. | ||||
541 | OldThunkFn->eraseFromParent(); | ||||
542 | } | ||||
543 | |||||
544 | bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions(); | ||||
545 | bool UseAvailableExternallyLinkage = ForVTable
| ||||
546 | |||||
547 | if (!ThunkFn->isDeclaration()) { | ||||
548 | if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) { | ||||
549 | // There is already a thunk emitted for this function, do nothing. | ||||
550 | return ThunkFn; | ||||
551 | } | ||||
552 | |||||
553 | setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD); | ||||
554 | return ThunkFn; | ||||
555 | } | ||||
556 | |||||
557 | // If this will be unprototyped, add the "thunk" attribute so that LLVM knows | ||||
558 | // that the return type is meaningless. These thunks can be used to call | ||||
559 | // functions with differing return types, and the caller is required to cast | ||||
560 | // the prototype appropriately to extract the correct value. | ||||
561 | if (IsUnprototyped
| ||||
562 | ThunkFn->addFnAttr("thunk"); | ||||
563 | |||||
564 | CGM.SetLLVMFunctionAttributesForDefinition(GD.getDecl(), ThunkFn); | ||||
565 | |||||
566 | // Thunks for variadic methods are special because in general variadic | ||||
567 | // arguments cannot be perferctly forwarded. In the general case, clang | ||||
568 | // implements such thunks by cloning the original function body. However, for | ||||
569 | // thunks with no return adjustment on targets that support musttail, we can | ||||
570 | // use musttail to perfectly forward the variadic arguments. | ||||
571 | bool ShouldCloneVarArgs = false; | ||||
572 | if (!IsUnprototyped
| ||||
573 | ShouldCloneVarArgs = true; | ||||
574 | if (TI.Return.isEmpty()) { | ||||
575 | switch (CGM.getTriple().getArch()) { | ||||
576 | case llvm::Triple::x86_64: | ||||
577 | case llvm::Triple::x86: | ||||
578 | case llvm::Triple::aarch64: | ||||
579 | ShouldCloneVarArgs = false; | ||||
580 | break; | ||||
581 | default: | ||||
582 | break; | ||||
583 | } | ||||
584 | } | ||||
585 | } | ||||
586 | |||||
587 | if (ShouldCloneVarArgs
| ||||
588 | if (UseAvailableExternallyLinkage) | ||||
589 | return ThunkFn; | ||||
590 | ThunkFn = | ||||
591 | CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI); | ||||
592 | } else { | ||||
593 | // Normal thunk body generation. | ||||
594 | CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped); | ||||
595 | } | ||||
596 | |||||
597 | setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD); | ||||
598 | return ThunkFn; | ||||
599 | } | ||||
600 | |||||
601 | void CodeGenVTables::EmitThunks(GlobalDecl GD) { | ||||
602 | const CXXMethodDecl *MD = | ||||
603 | cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl(); | ||||
| |||||
604 | |||||
605 | // We don't need to generate thunks for the base destructor. | ||||
606 | if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) | ||||
607 | return; | ||||
608 | |||||
609 | const VTableContextBase::ThunkInfoVectorTy *ThunkInfoVector = | ||||
610 | VTContext->getThunkInfo(GD); | ||||
611 | |||||
612 | if (!ThunkInfoVector) | ||||
613 | return; | ||||
614 | |||||
615 | for (const ThunkInfo& Thunk : *ThunkInfoVector) | ||||
616 | maybeEmitThunk(GD, Thunk, /*ForVTable=*/false); | ||||
617 | } | ||||
618 | |||||
619 | void CodeGenVTables::addVTableComponent( | ||||
620 | ConstantArrayBuilder &builder, const VTableLayout &layout, | ||||
621 | unsigned idx, llvm::Constant *rtti, unsigned &nextVTableThunkIndex) { | ||||
622 | auto &component = layout.vtable_components()[idx]; | ||||
623 | |||||
624 | auto addOffsetConstant = [&](CharUnits offset) { | ||||
625 | builder.add(llvm::ConstantExpr::getIntToPtr( | ||||
626 | llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()), | ||||
627 | CGM.Int8PtrTy)); | ||||
628 | }; | ||||
629 | |||||
630 | switch (component.getKind()) { | ||||
631 | case VTableComponent::CK_VCallOffset: | ||||
632 | return addOffsetConstant(component.getVCallOffset()); | ||||
633 | |||||
634 | case VTableComponent::CK_VBaseOffset: | ||||
635 | return addOffsetConstant(component.getVBaseOffset()); | ||||
636 | |||||
637 | case VTableComponent::CK_OffsetToTop: | ||||
638 | return addOffsetConstant(component.getOffsetToTop()); | ||||
639 | |||||
640 | case VTableComponent::CK_RTTI: | ||||
641 | return builder.add(llvm::ConstantExpr::getBitCast(rtti, CGM.Int8PtrTy)); | ||||
642 | |||||
643 | case VTableComponent::CK_FunctionPointer: | ||||
644 | case VTableComponent::CK_CompleteDtorPointer: | ||||
645 | case VTableComponent::CK_DeletingDtorPointer: { | ||||
646 | GlobalDecl GD; | ||||
647 | |||||
648 | // Get the right global decl. | ||||
649 | switch (component.getKind()) { | ||||
650 | default: | ||||
651 | llvm_unreachable("Unexpected vtable component kind")::llvm::llvm_unreachable_internal("Unexpected vtable component kind" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 651); | ||||
652 | case VTableComponent::CK_FunctionPointer: | ||||
653 | GD = component.getFunctionDecl(); | ||||
654 | break; | ||||
655 | case VTableComponent::CK_CompleteDtorPointer: | ||||
656 | GD = GlobalDecl(component.getDestructorDecl(), Dtor_Complete); | ||||
657 | break; | ||||
658 | case VTableComponent::CK_DeletingDtorPointer: | ||||
659 | GD = GlobalDecl(component.getDestructorDecl(), Dtor_Deleting); | ||||
660 | break; | ||||
661 | } | ||||
662 | |||||
663 | if (CGM.getLangOpts().CUDA) { | ||||
664 | // Emit NULL for methods we can't codegen on this | ||||
665 | // side. Otherwise we'd end up with vtable with unresolved | ||||
666 | // references. | ||||
667 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); | ||||
668 | // OK on device side: functions w/ __device__ attribute | ||||
669 | // OK on host side: anything except __device__-only functions. | ||||
670 | bool CanEmitMethod = | ||||
671 | CGM.getLangOpts().CUDAIsDevice | ||||
672 | ? MD->hasAttr<CUDADeviceAttr>() | ||||
673 | : (MD->hasAttr<CUDAHostAttr>() || !MD->hasAttr<CUDADeviceAttr>()); | ||||
674 | if (!CanEmitMethod) | ||||
675 | return builder.addNullPointer(CGM.Int8PtrTy); | ||||
676 | // Method is acceptable, continue processing as usual. | ||||
677 | } | ||||
678 | |||||
679 | auto getSpecialVirtualFn = [&](StringRef name) { | ||||
680 | llvm::FunctionType *fnTy = | ||||
681 | llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); | ||||
682 | llvm::Constant *fn = cast<llvm::Constant>( | ||||
683 | CGM.CreateRuntimeFunction(fnTy, name).getCallee()); | ||||
684 | if (auto f = dyn_cast<llvm::Function>(fn)) | ||||
685 | f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); | ||||
686 | return llvm::ConstantExpr::getBitCast(fn, CGM.Int8PtrTy); | ||||
687 | }; | ||||
688 | |||||
689 | llvm::Constant *fnPtr; | ||||
690 | |||||
691 | // Pure virtual member functions. | ||||
692 | if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) { | ||||
693 | if (!PureVirtualFn) | ||||
694 | PureVirtualFn = | ||||
695 | getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName()); | ||||
696 | fnPtr = PureVirtualFn; | ||||
697 | |||||
698 | // Deleted virtual member functions. | ||||
699 | } else if (cast<CXXMethodDecl>(GD.getDecl())->isDeleted()) { | ||||
700 | if (!DeletedVirtualFn) | ||||
701 | DeletedVirtualFn = | ||||
702 | getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName()); | ||||
703 | fnPtr = DeletedVirtualFn; | ||||
704 | |||||
705 | // Thunks. | ||||
706 | } else if (nextVTableThunkIndex < layout.vtable_thunks().size() && | ||||
707 | layout.vtable_thunks()[nextVTableThunkIndex].first == idx) { | ||||
708 | auto &thunkInfo = layout.vtable_thunks()[nextVTableThunkIndex].second; | ||||
709 | |||||
710 | nextVTableThunkIndex++; | ||||
711 | fnPtr = maybeEmitThunk(GD, thunkInfo, /*ForVTable=*/true); | ||||
712 | |||||
713 | // Otherwise we can use the method definition directly. | ||||
714 | } else { | ||||
715 | llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD); | ||||
716 | fnPtr = CGM.GetAddrOfFunction(GD, fnTy, /*ForVTable=*/true); | ||||
717 | } | ||||
718 | |||||
719 | fnPtr = llvm::ConstantExpr::getBitCast(fnPtr, CGM.Int8PtrTy); | ||||
720 | builder.add(fnPtr); | ||||
721 | return; | ||||
722 | } | ||||
723 | |||||
724 | case VTableComponent::CK_UnusedFunctionPointer: | ||||
725 | return builder.addNullPointer(CGM.Int8PtrTy); | ||||
726 | } | ||||
727 | |||||
728 | llvm_unreachable("Unexpected vtable component kind")::llvm::llvm_unreachable_internal("Unexpected vtable component kind" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 728); | ||||
729 | } | ||||
730 | |||||
731 | llvm::Type *CodeGenVTables::getVTableType(const VTableLayout &layout) { | ||||
732 | SmallVector<llvm::Type *, 4> tys; | ||||
733 | for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) { | ||||
734 | tys.push_back(llvm::ArrayType::get(CGM.Int8PtrTy, layout.getVTableSize(i))); | ||||
735 | } | ||||
736 | |||||
737 | return llvm::StructType::get(CGM.getLLVMContext(), tys); | ||||
738 | } | ||||
739 | |||||
740 | void CodeGenVTables::createVTableInitializer(ConstantStructBuilder &builder, | ||||
741 | const VTableLayout &layout, | ||||
742 | llvm::Constant *rtti) { | ||||
743 | unsigned nextVTableThunkIndex = 0; | ||||
744 | for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) { | ||||
745 | auto vtableElem = builder.beginArray(CGM.Int8PtrTy); | ||||
746 | size_t thisIndex = layout.getVTableOffset(i); | ||||
747 | size_t nextIndex = thisIndex + layout.getVTableSize(i); | ||||
748 | for (unsigned i = thisIndex; i != nextIndex; ++i) { | ||||
749 | addVTableComponent(vtableElem, layout, i, rtti, nextVTableThunkIndex); | ||||
750 | } | ||||
751 | vtableElem.finishAndAddTo(builder); | ||||
752 | } | ||||
753 | } | ||||
754 | |||||
755 | llvm::GlobalVariable * | ||||
756 | CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, | ||||
757 | const BaseSubobject &Base, | ||||
758 | bool BaseIsVirtual, | ||||
759 | llvm::GlobalVariable::LinkageTypes Linkage, | ||||
760 | VTableAddressPointsMapTy& AddressPoints) { | ||||
761 | if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) | ||||
762 | DI->completeClassData(Base.getBase()); | ||||
763 | |||||
764 | std::unique_ptr<VTableLayout> VTLayout( | ||||
765 | getItaniumVTableContext().createConstructionVTableLayout( | ||||
766 | Base.getBase(), Base.getBaseOffset(), BaseIsVirtual, RD)); | ||||
767 | |||||
768 | // Add the address points. | ||||
769 | AddressPoints = VTLayout->getAddressPoints(); | ||||
770 | |||||
771 | // Get the mangled construction vtable name. | ||||
772 | SmallString<256> OutName; | ||||
773 | llvm::raw_svector_ostream Out(OutName); | ||||
774 | cast<ItaniumMangleContext>(CGM.getCXXABI().getMangleContext()) | ||||
775 | .mangleCXXCtorVTable(RD, Base.getBaseOffset().getQuantity(), | ||||
776 | Base.getBase(), Out); | ||||
777 | StringRef Name = OutName.str(); | ||||
778 | |||||
779 | llvm::Type *VTType = getVTableType(*VTLayout); | ||||
780 | |||||
781 | // Construction vtable symbols are not part of the Itanium ABI, so we cannot | ||||
782 | // guarantee that they actually will be available externally. Instead, when | ||||
783 | // emitting an available_externally VTT, we provide references to an internal | ||||
784 | // linkage construction vtable. The ABI only requires complete-object vtables | ||||
785 | // to be the same for all instances of a type, not construction vtables. | ||||
786 | if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage) | ||||
787 | Linkage = llvm::GlobalVariable::InternalLinkage; | ||||
788 | |||||
789 | unsigned Align = CGM.getDataLayout().getABITypeAlignment(VTType); | ||||
790 | |||||
791 | // Create the variable that will hold the construction vtable. | ||||
792 | llvm::GlobalVariable *VTable = | ||||
793 | CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage, Align); | ||||
794 | |||||
795 | // V-tables are always unnamed_addr. | ||||
796 | VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); | ||||
797 | |||||
798 | llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor( | ||||
799 | CGM.getContext().getTagDeclType(Base.getBase())); | ||||
800 | |||||
801 | // Create and set the initializer. | ||||
802 | ConstantInitBuilder builder(CGM); | ||||
803 | auto components = builder.beginStruct(); | ||||
804 | createVTableInitializer(components, *VTLayout, RTTI); | ||||
805 | components.finishAndSetAsInitializer(VTable); | ||||
806 | |||||
807 | // Set properties only after the initializer has been set to ensure that the | ||||
808 | // GV is treated as definition and not declaration. | ||||
809 | assert(!VTable->isDeclaration() && "Shouldn't set properties on declaration")((!VTable->isDeclaration() && "Shouldn't set properties on declaration" ) ? static_cast<void> (0) : __assert_fail ("!VTable->isDeclaration() && \"Shouldn't set properties on declaration\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 809, __PRETTY_FUNCTION__)); | ||||
810 | CGM.setGVProperties(VTable, RD); | ||||
811 | |||||
812 | CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout.get()); | ||||
813 | |||||
814 | return VTable; | ||||
815 | } | ||||
816 | |||||
817 | static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM, | ||||
818 | const CXXRecordDecl *RD) { | ||||
819 | return CGM.getCodeGenOpts().OptimizationLevel > 0 && | ||||
820 | CGM.getCXXABI().canSpeculativelyEmitVTable(RD); | ||||
821 | } | ||||
822 | |||||
823 | /// Compute the required linkage of the vtable for the given class. | ||||
824 | /// | ||||
825 | /// Note that we only call this at the end of the translation unit. | ||||
826 | llvm::GlobalVariable::LinkageTypes | ||||
827 | CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) { | ||||
828 | if (!RD->isExternallyVisible()) | ||||
829 | return llvm::GlobalVariable::InternalLinkage; | ||||
830 | |||||
831 | // We're at the end of the translation unit, so the current key | ||||
832 | // function is fully correct. | ||||
833 | const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD); | ||||
834 | if (keyFunction && !RD->hasAttr<DLLImportAttr>()) { | ||||
835 | // If this class has a key function, use that to determine the | ||||
836 | // linkage of the vtable. | ||||
837 | const FunctionDecl *def = nullptr; | ||||
838 | if (keyFunction->hasBody(def)) | ||||
839 | keyFunction = cast<CXXMethodDecl>(def); | ||||
840 | |||||
841 | switch (keyFunction->getTemplateSpecializationKind()) { | ||||
842 | case TSK_Undeclared: | ||||
843 | case TSK_ExplicitSpecialization: | ||||
844 | assert((def || CodeGenOpts.OptimizationLevel > 0 ||(((def || CodeGenOpts.OptimizationLevel > 0 || CodeGenOpts .getDebugInfo() != codegenoptions::NoDebugInfo) && "Shouldn't query vtable linkage without key function, " "optimizations, or debug info") ? static_cast<void> (0 ) : __assert_fail ("(def || CodeGenOpts.OptimizationLevel > 0 || CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo) && \"Shouldn't query vtable linkage without key function, \" \"optimizations, or debug info\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 847, __PRETTY_FUNCTION__)) | ||||
845 | CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo) &&(((def || CodeGenOpts.OptimizationLevel > 0 || CodeGenOpts .getDebugInfo() != codegenoptions::NoDebugInfo) && "Shouldn't query vtable linkage without key function, " "optimizations, or debug info") ? static_cast<void> (0 ) : __assert_fail ("(def || CodeGenOpts.OptimizationLevel > 0 || CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo) && \"Shouldn't query vtable linkage without key function, \" \"optimizations, or debug info\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 847, __PRETTY_FUNCTION__)) | ||||
846 | "Shouldn't query vtable linkage without key function, "(((def || CodeGenOpts.OptimizationLevel > 0 || CodeGenOpts .getDebugInfo() != codegenoptions::NoDebugInfo) && "Shouldn't query vtable linkage without key function, " "optimizations, or debug info") ? static_cast<void> (0 ) : __assert_fail ("(def || CodeGenOpts.OptimizationLevel > 0 || CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo) && \"Shouldn't query vtable linkage without key function, \" \"optimizations, or debug info\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 847, __PRETTY_FUNCTION__)) | ||||
847 | "optimizations, or debug info")(((def || CodeGenOpts.OptimizationLevel > 0 || CodeGenOpts .getDebugInfo() != codegenoptions::NoDebugInfo) && "Shouldn't query vtable linkage without key function, " "optimizations, or debug info") ? static_cast<void> (0 ) : __assert_fail ("(def || CodeGenOpts.OptimizationLevel > 0 || CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo) && \"Shouldn't query vtable linkage without key function, \" \"optimizations, or debug info\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 847, __PRETTY_FUNCTION__)); | ||||
848 | if (!def && CodeGenOpts.OptimizationLevel > 0) | ||||
849 | return llvm::GlobalVariable::AvailableExternallyLinkage; | ||||
850 | |||||
851 | if (keyFunction->isInlined()) | ||||
852 | return !Context.getLangOpts().AppleKext ? | ||||
853 | llvm::GlobalVariable::LinkOnceODRLinkage : | ||||
854 | llvm::Function::InternalLinkage; | ||||
855 | |||||
856 | return llvm::GlobalVariable::ExternalLinkage; | ||||
857 | |||||
858 | case TSK_ImplicitInstantiation: | ||||
859 | return !Context.getLangOpts().AppleKext ? | ||||
860 | llvm::GlobalVariable::LinkOnceODRLinkage : | ||||
861 | llvm::Function::InternalLinkage; | ||||
862 | |||||
863 | case TSK_ExplicitInstantiationDefinition: | ||||
864 | return !Context.getLangOpts().AppleKext ? | ||||
865 | llvm::GlobalVariable::WeakODRLinkage : | ||||
866 | llvm::Function::InternalLinkage; | ||||
867 | |||||
868 | case TSK_ExplicitInstantiationDeclaration: | ||||
869 | llvm_unreachable("Should not have been asked to emit this")::llvm::llvm_unreachable_internal("Should not have been asked to emit this" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 869); | ||||
870 | } | ||||
871 | } | ||||
872 | |||||
873 | // -fapple-kext mode does not support weak linkage, so we must use | ||||
874 | // internal linkage. | ||||
875 | if (Context.getLangOpts().AppleKext) | ||||
876 | return llvm::Function::InternalLinkage; | ||||
877 | |||||
878 | llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage = | ||||
879 | llvm::GlobalValue::LinkOnceODRLinkage; | ||||
880 | llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage = | ||||
881 | llvm::GlobalValue::WeakODRLinkage; | ||||
882 | if (RD->hasAttr<DLLExportAttr>()) { | ||||
883 | // Cannot discard exported vtables. | ||||
884 | DiscardableODRLinkage = NonDiscardableODRLinkage; | ||||
885 | } else if (RD->hasAttr<DLLImportAttr>()) { | ||||
886 | // Imported vtables are available externally. | ||||
887 | DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage; | ||||
888 | NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage; | ||||
889 | } | ||||
890 | |||||
891 | switch (RD->getTemplateSpecializationKind()) { | ||||
892 | case TSK_Undeclared: | ||||
893 | case TSK_ExplicitSpecialization: | ||||
894 | case TSK_ImplicitInstantiation: | ||||
895 | return DiscardableODRLinkage; | ||||
896 | |||||
897 | case TSK_ExplicitInstantiationDeclaration: | ||||
898 | // Explicit instantiations in MSVC do not provide vtables, so we must emit | ||||
899 | // our own. | ||||
900 | if (getTarget().getCXXABI().isMicrosoft()) | ||||
901 | return DiscardableODRLinkage; | ||||
902 | return shouldEmitAvailableExternallyVTable(*this, RD) | ||||
903 | ? llvm::GlobalVariable::AvailableExternallyLinkage | ||||
904 | : llvm::GlobalVariable::ExternalLinkage; | ||||
905 | |||||
906 | case TSK_ExplicitInstantiationDefinition: | ||||
907 | return NonDiscardableODRLinkage; | ||||
908 | } | ||||
909 | |||||
910 | llvm_unreachable("Invalid TemplateSpecializationKind!")::llvm::llvm_unreachable_internal("Invalid TemplateSpecializationKind!" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 910); | ||||
911 | } | ||||
912 | |||||
913 | /// This is a callback from Sema to tell us that a particular vtable is | ||||
914 | /// required to be emitted in this translation unit. | ||||
915 | /// | ||||
916 | /// This is only called for vtables that _must_ be emitted (mainly due to key | ||||
917 | /// functions). For weak vtables, CodeGen tracks when they are needed and | ||||
918 | /// emits them as-needed. | ||||
919 | void CodeGenModule::EmitVTable(CXXRecordDecl *theClass) { | ||||
920 | VTables.GenerateClassData(theClass); | ||||
921 | } | ||||
922 | |||||
923 | void | ||||
924 | CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) { | ||||
925 | if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) | ||||
926 | DI->completeClassData(RD); | ||||
927 | |||||
928 | if (RD->getNumVBases()) | ||||
929 | CGM.getCXXABI().emitVirtualInheritanceTables(RD); | ||||
930 | |||||
931 | CGM.getCXXABI().emitVTableDefinitions(*this, RD); | ||||
932 | } | ||||
933 | |||||
934 | /// At this point in the translation unit, does it appear that can we | ||||
935 | /// rely on the vtable being defined elsewhere in the program? | ||||
936 | /// | ||||
937 | /// The response is really only definitive when called at the end of | ||||
938 | /// the translation unit. | ||||
939 | /// | ||||
940 | /// The only semantic restriction here is that the object file should | ||||
941 | /// not contain a vtable definition when that vtable is defined | ||||
942 | /// strongly elsewhere. Otherwise, we'd just like to avoid emitting | ||||
943 | /// vtables when unnecessary. | ||||
944 | bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) { | ||||
945 | assert(RD->isDynamicClass() && "Non-dynamic classes have no VTable.")((RD->isDynamicClass() && "Non-dynamic classes have no VTable." ) ? static_cast<void> (0) : __assert_fail ("RD->isDynamicClass() && \"Non-dynamic classes have no VTable.\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 945, __PRETTY_FUNCTION__)); | ||||
946 | |||||
947 | // We always synthesize vtables if they are needed in the MS ABI. MSVC doesn't | ||||
948 | // emit them even if there is an explicit template instantiation. | ||||
949 | if (CGM.getTarget().getCXXABI().isMicrosoft()) | ||||
950 | return false; | ||||
951 | |||||
952 | // If we have an explicit instantiation declaration (and not a | ||||
953 | // definition), the vtable is defined elsewhere. | ||||
954 | TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind(); | ||||
955 | if (TSK == TSK_ExplicitInstantiationDeclaration) | ||||
956 | return true; | ||||
957 | |||||
958 | // Otherwise, if the class is an instantiated template, the | ||||
959 | // vtable must be defined here. | ||||
960 | if (TSK == TSK_ImplicitInstantiation || | ||||
961 | TSK == TSK_ExplicitInstantiationDefinition) | ||||
962 | return false; | ||||
963 | |||||
964 | // Otherwise, if the class doesn't have a key function (possibly | ||||
965 | // anymore), the vtable must be defined here. | ||||
966 | const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD); | ||||
967 | if (!keyFunction) | ||||
968 | return false; | ||||
969 | |||||
970 | // Otherwise, if we don't have a definition of the key function, the | ||||
971 | // vtable must be defined somewhere else. | ||||
972 | return !keyFunction->hasBody(); | ||||
973 | } | ||||
974 | |||||
975 | /// Given that we're currently at the end of the translation unit, and | ||||
976 | /// we've emitted a reference to the vtable for this class, should | ||||
977 | /// we define that vtable? | ||||
978 | static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM, | ||||
979 | const CXXRecordDecl *RD) { | ||||
980 | // If vtable is internal then it has to be done. | ||||
981 | if (!CGM.getVTables().isVTableExternal(RD)) | ||||
982 | return true; | ||||
983 | |||||
984 | // If it's external then maybe we will need it as available_externally. | ||||
985 | return shouldEmitAvailableExternallyVTable(CGM, RD); | ||||
986 | } | ||||
987 | |||||
988 | /// Given that at some point we emitted a reference to one or more | ||||
989 | /// vtables, and that we are now at the end of the translation unit, | ||||
990 | /// decide whether we should emit them. | ||||
991 | void CodeGenModule::EmitDeferredVTables() { | ||||
992 | #ifndef NDEBUG | ||||
993 | // Remember the size of DeferredVTables, because we're going to assume | ||||
994 | // that this entire operation doesn't modify it. | ||||
995 | size_t savedSize = DeferredVTables.size(); | ||||
996 | #endif | ||||
997 | |||||
998 | for (const CXXRecordDecl *RD : DeferredVTables) | ||||
999 | if (shouldEmitVTableAtEndOfTranslationUnit(*this, RD)) | ||||
1000 | VTables.GenerateClassData(RD); | ||||
1001 | else if (shouldOpportunisticallyEmitVTables()) | ||||
1002 | OpportunisticVTables.push_back(RD); | ||||
1003 | |||||
1004 | assert(savedSize == DeferredVTables.size() &&((savedSize == DeferredVTables.size() && "deferred extra vtables during vtable emission?" ) ? static_cast<void> (0) : __assert_fail ("savedSize == DeferredVTables.size() && \"deferred extra vtables during vtable emission?\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 1005, __PRETTY_FUNCTION__)) | ||||
1005 | "deferred extra vtables during vtable emission?")((savedSize == DeferredVTables.size() && "deferred extra vtables during vtable emission?" ) ? static_cast<void> (0) : __assert_fail ("savedSize == DeferredVTables.size() && \"deferred extra vtables during vtable emission?\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/lib/CodeGen/CGVTables.cpp" , 1005, __PRETTY_FUNCTION__)); | ||||
1006 | DeferredVTables.clear(); | ||||
1007 | } | ||||
1008 | |||||
1009 | bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) { | ||||
1010 | LinkageInfo LV = RD->getLinkageAndVisibility(); | ||||
1011 | if (!isExternallyVisible(LV.getLinkage())) | ||||
1012 | return true; | ||||
1013 | |||||
1014 | if (RD->hasAttr<LTOVisibilityPublicAttr>() || RD->hasAttr<UuidAttr>()) | ||||
1015 | return false; | ||||
1016 | |||||
1017 | if (getTriple().isOSBinFormatCOFF()) { | ||||
1018 | if (RD->hasAttr<DLLExportAttr>() || RD->hasAttr<DLLImportAttr>()) | ||||
1019 | return false; | ||||
1020 | } else { | ||||
1021 | if (LV.getVisibility() != HiddenVisibility) | ||||
1022 | return false; | ||||
1023 | } | ||||
1024 | |||||
1025 | if (getCodeGenOpts().LTOVisibilityPublicStd) { | ||||
1026 | const DeclContext *DC = RD; | ||||
1027 | while (1) { | ||||
1028 | auto *D = cast<Decl>(DC); | ||||
1029 | DC = DC->getParent(); | ||||
1030 | if (isa<TranslationUnitDecl>(DC->getRedeclContext())) { | ||||
1031 | if (auto *ND = dyn_cast<NamespaceDecl>(D)) | ||||
1032 | if (const IdentifierInfo *II = ND->getIdentifier()) | ||||
1033 | if (II->isStr("std") || II->isStr("stdext")) | ||||
1034 | return false; | ||||
1035 | break; | ||||
1036 | } | ||||
1037 | } | ||||
1038 | } | ||||
1039 | |||||
1040 | return true; | ||||
1041 | } | ||||
1042 | |||||
1043 | llvm::GlobalObject::VCallVisibility | ||||
1044 | CodeGenModule::GetVCallVisibilityLevel(const CXXRecordDecl *RD) { | ||||
1045 | LinkageInfo LV = RD->getLinkageAndVisibility(); | ||||
1046 | llvm::GlobalObject::VCallVisibility TypeVis; | ||||
1047 | if (!isExternallyVisible(LV.getLinkage())) | ||||
1048 | TypeVis = llvm::GlobalObject::VCallVisibilityTranslationUnit; | ||||
1049 | else if (HasHiddenLTOVisibility(RD)) | ||||
1050 | TypeVis = llvm::GlobalObject::VCallVisibilityLinkageUnit; | ||||
1051 | else | ||||
1052 | TypeVis = llvm::GlobalObject::VCallVisibilityPublic; | ||||
1053 | |||||
1054 | for (auto B : RD->bases()) | ||||
1055 | if (B.getType()->getAsCXXRecordDecl()->isDynamicClass()) | ||||
1056 | TypeVis = std::min(TypeVis, | ||||
1057 | GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl())); | ||||
1058 | |||||
1059 | for (auto B : RD->vbases()) | ||||
1060 | if (B.getType()->getAsCXXRecordDecl()->isDynamicClass()) | ||||
1061 | TypeVis = std::min(TypeVis, | ||||
1062 | GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl())); | ||||
1063 | |||||
1064 | return TypeVis; | ||||
1065 | } | ||||
1066 | |||||
1067 | void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, | ||||
1068 | llvm::GlobalVariable *VTable, | ||||
1069 | const VTableLayout &VTLayout) { | ||||
1070 | if (!getCodeGenOpts().LTOUnit) | ||||
1071 | return; | ||||
1072 | |||||
1073 | CharUnits PointerWidth = | ||||
1074 | Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); | ||||
1075 | |||||
1076 | typedef std::pair<const CXXRecordDecl *, unsigned> AddressPoint; | ||||
1077 | std::vector<AddressPoint> AddressPoints; | ||||
1078 | for (auto &&AP : VTLayout.getAddressPoints()) | ||||
1079 | AddressPoints.push_back(std::make_pair( | ||||
1080 | AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) + | ||||
1081 | AP.second.AddressPointIndex)); | ||||
1082 | |||||
1083 | // Sort the address points for determinism. | ||||
1084 | llvm::sort(AddressPoints, [this](const AddressPoint &AP1, | ||||
1085 | const AddressPoint &AP2) { | ||||
1086 | if (&AP1 == &AP2) | ||||
1087 | return false; | ||||
1088 | |||||
1089 | std::string S1; | ||||
1090 | llvm::raw_string_ostream O1(S1); | ||||
1091 | getCXXABI().getMangleContext().mangleTypeName( | ||||
1092 | QualType(AP1.first->getTypeForDecl(), 0), O1); | ||||
1093 | O1.flush(); | ||||
1094 | |||||
1095 | std::string S2; | ||||
1096 | llvm::raw_string_ostream O2(S2); | ||||
1097 | getCXXABI().getMangleContext().mangleTypeName( | ||||
1098 | QualType(AP2.first->getTypeForDecl(), 0), O2); | ||||
1099 | O2.flush(); | ||||
1100 | |||||
1101 | if (S1 < S2) | ||||
1102 | return true; | ||||
1103 | if (S1 != S2) | ||||
1104 | return false; | ||||
1105 | |||||
1106 | return AP1.second < AP2.second; | ||||
1107 | }); | ||||
1108 | |||||
1109 | ArrayRef<VTableComponent> Comps = VTLayout.vtable_components(); | ||||
1110 | for (auto AP : AddressPoints) { | ||||
1111 | // Create type metadata for the address point. | ||||
1112 | AddVTableTypeMetadata(VTable, PointerWidth * AP.second, AP.first); | ||||
1113 | |||||
1114 | // The class associated with each address point could also potentially be | ||||
1115 | // used for indirect calls via a member function pointer, so we need to | ||||
1116 | // annotate the address of each function pointer with the appropriate member | ||||
1117 | // function pointer type. | ||||
1118 | for (unsigned I = 0; I != Comps.size(); ++I) { | ||||
1119 | if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer) | ||||
1120 | continue; | ||||
1121 | llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( | ||||
1122 | Context.getMemberPointerType( | ||||
1123 | Comps[I].getFunctionDecl()->getType(), | ||||
1124 | Context.getRecordType(AP.first).getTypePtr())); | ||||
1125 | VTable->addTypeMetadata((PointerWidth * I).getQuantity(), MD); | ||||
1126 | } | ||||
1127 | } | ||||
1128 | |||||
1129 | if (getCodeGenOpts().VirtualFunctionElimination) { | ||||
1130 | llvm::GlobalObject::VCallVisibility TypeVis = GetVCallVisibilityLevel(RD); | ||||
1131 | if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic) | ||||
1132 | VTable->addVCallVisibilityMetadata(TypeVis); | ||||
1133 | } | ||||
1134 | } |
1 | //==-- CGFunctionInfo.h - Representation of function argument/return types -==// | |||
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 | // Defines CGFunctionInfo and associated types used in representing the | |||
10 | // LLVM source types and ABI-coerced types for function arguments and | |||
11 | // return values. | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H | |||
16 | #define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H | |||
17 | ||||
18 | #include "clang/AST/CanonicalType.h" | |||
19 | #include "clang/AST/CharUnits.h" | |||
20 | #include "clang/AST/Decl.h" | |||
21 | #include "clang/AST/Type.h" | |||
22 | #include "llvm/IR/DerivedTypes.h" | |||
23 | #include "llvm/ADT/FoldingSet.h" | |||
24 | #include "llvm/Support/TrailingObjects.h" | |||
25 | #include <cassert> | |||
26 | ||||
27 | namespace clang { | |||
28 | namespace CodeGen { | |||
29 | ||||
30 | /// ABIArgInfo - Helper class to encapsulate information about how a | |||
31 | /// specific C type should be passed to or returned from a function. | |||
32 | class ABIArgInfo { | |||
33 | public: | |||
34 | enum Kind : uint8_t { | |||
35 | /// Direct - Pass the argument directly using the normal converted LLVM | |||
36 | /// type, or by coercing to another specified type stored in | |||
37 | /// 'CoerceToType'). If an offset is specified (in UIntData), then the | |||
38 | /// argument passed is offset by some number of bytes in the memory | |||
39 | /// representation. A dummy argument is emitted before the real argument | |||
40 | /// if the specified type stored in "PaddingType" is not zero. | |||
41 | Direct, | |||
42 | ||||
43 | /// Extend - Valid only for integer argument types. Same as 'direct' | |||
44 | /// but also emit a zero/sign extension attribute. | |||
45 | Extend, | |||
46 | ||||
47 | /// Indirect - Pass the argument indirectly via a hidden pointer | |||
48 | /// with the specified alignment (0 indicates default alignment). | |||
49 | Indirect, | |||
50 | ||||
51 | /// Ignore - Ignore the argument (treat as void). Useful for void and | |||
52 | /// empty structs. | |||
53 | Ignore, | |||
54 | ||||
55 | /// Expand - Only valid for aggregate argument types. The structure should | |||
56 | /// be expanded into consecutive arguments for its constituent fields. | |||
57 | /// Currently expand is only allowed on structures whose fields | |||
58 | /// are all scalar types or are themselves expandable types. | |||
59 | Expand, | |||
60 | ||||
61 | /// CoerceAndExpand - Only valid for aggregate argument types. The | |||
62 | /// structure should be expanded into consecutive arguments corresponding | |||
63 | /// to the non-array elements of the type stored in CoerceToType. | |||
64 | /// Array elements in the type are assumed to be padding and skipped. | |||
65 | CoerceAndExpand, | |||
66 | ||||
67 | /// InAlloca - Pass the argument directly using the LLVM inalloca attribute. | |||
68 | /// This is similar to indirect with byval, except it only applies to | |||
69 | /// arguments stored in memory and forbids any implicit copies. When | |||
70 | /// applied to a return type, it means the value is returned indirectly via | |||
71 | /// an implicit sret parameter stored in the argument struct. | |||
72 | InAlloca, | |||
73 | KindFirst = Direct, | |||
74 | KindLast = InAlloca | |||
75 | }; | |||
76 | ||||
77 | private: | |||
78 | llvm::Type *TypeData; // canHaveCoerceToType() | |||
79 | union { | |||
80 | llvm::Type *PaddingType; // canHavePaddingType() | |||
81 | llvm::Type *UnpaddedCoerceAndExpandType; // isCoerceAndExpand() | |||
82 | }; | |||
83 | union { | |||
84 | unsigned DirectOffset; // isDirect() || isExtend() | |||
85 | unsigned IndirectAlign; // isIndirect() | |||
86 | unsigned AllocaFieldIndex; // isInAlloca() | |||
87 | }; | |||
88 | Kind TheKind; | |||
89 | bool PaddingInReg : 1; | |||
90 | bool InAllocaSRet : 1; // isInAlloca() | |||
91 | bool IndirectByVal : 1; // isIndirect() | |||
92 | bool IndirectRealign : 1; // isIndirect() | |||
93 | bool SRetAfterThis : 1; // isIndirect() | |||
94 | bool InReg : 1; // isDirect() || isExtend() || isIndirect() | |||
95 | bool CanBeFlattened: 1; // isDirect() | |||
96 | bool SignExt : 1; // isExtend() | |||
97 | ||||
98 | bool canHavePaddingType() const { | |||
99 | return isDirect() || isExtend() || isIndirect() || isExpand(); | |||
100 | } | |||
101 | void setPaddingType(llvm::Type *T) { | |||
102 | assert(canHavePaddingType())((canHavePaddingType()) ? static_cast<void> (0) : __assert_fail ("canHavePaddingType()", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 102, __PRETTY_FUNCTION__)); | |||
103 | PaddingType = T; | |||
104 | } | |||
105 | ||||
106 | void setUnpaddedCoerceToType(llvm::Type *T) { | |||
107 | assert(isCoerceAndExpand())((isCoerceAndExpand()) ? static_cast<void> (0) : __assert_fail ("isCoerceAndExpand()", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 107, __PRETTY_FUNCTION__)); | |||
108 | UnpaddedCoerceAndExpandType = T; | |||
109 | } | |||
110 | ||||
111 | public: | |||
112 | ABIArgInfo(Kind K = Direct) | |||
113 | : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0), | |||
114 | TheKind(K), PaddingInReg(false), InAllocaSRet(false), | |||
115 | IndirectByVal(false), IndirectRealign(false), SRetAfterThis(false), | |||
116 | InReg(false), CanBeFlattened(false), SignExt(false) {} | |||
117 | ||||
118 | static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, | |||
119 | llvm::Type *Padding = nullptr, | |||
120 | bool CanBeFlattened = true) { | |||
121 | auto AI = ABIArgInfo(Direct); | |||
122 | AI.setCoerceToType(T); | |||
123 | AI.setPaddingType(Padding); | |||
124 | AI.setDirectOffset(Offset); | |||
125 | AI.setCanBeFlattened(CanBeFlattened); | |||
126 | return AI; | |||
127 | } | |||
128 | static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) { | |||
129 | auto AI = getDirect(T); | |||
130 | AI.setInReg(true); | |||
131 | return AI; | |||
132 | } | |||
133 | ||||
134 | static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) { | |||
135 | assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType")((Ty->isIntegralOrEnumerationType() && "Unexpected QualType" ) ? static_cast<void> (0) : __assert_fail ("Ty->isIntegralOrEnumerationType() && \"Unexpected QualType\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 135, __PRETTY_FUNCTION__)); | |||
136 | auto AI = ABIArgInfo(Extend); | |||
137 | AI.setCoerceToType(T); | |||
138 | AI.setPaddingType(nullptr); | |||
139 | AI.setDirectOffset(0); | |||
140 | AI.setSignExt(true); | |||
141 | return AI; | |||
142 | } | |||
143 | ||||
144 | static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) { | |||
145 | assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType")((Ty->isIntegralOrEnumerationType() && "Unexpected QualType" ) ? static_cast<void> (0) : __assert_fail ("Ty->isIntegralOrEnumerationType() && \"Unexpected QualType\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 145, __PRETTY_FUNCTION__)); | |||
146 | auto AI = ABIArgInfo(Extend); | |||
147 | AI.setCoerceToType(T); | |||
148 | AI.setPaddingType(nullptr); | |||
149 | AI.setDirectOffset(0); | |||
150 | AI.setSignExt(false); | |||
151 | return AI; | |||
152 | } | |||
153 | ||||
154 | // ABIArgInfo will record the argument as being extended based on the sign | |||
155 | // of its type. | |||
156 | static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) { | |||
157 | assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType")((Ty->isIntegralOrEnumerationType() && "Unexpected QualType" ) ? static_cast<void> (0) : __assert_fail ("Ty->isIntegralOrEnumerationType() && \"Unexpected QualType\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 157, __PRETTY_FUNCTION__)); | |||
158 | if (Ty->hasSignedIntegerRepresentation()) | |||
159 | return getSignExtend(Ty, T); | |||
160 | return getZeroExtend(Ty, T); | |||
161 | } | |||
162 | ||||
163 | static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) { | |||
164 | auto AI = getExtend(Ty, T); | |||
165 | AI.setInReg(true); | |||
166 | return AI; | |||
167 | } | |||
168 | static ABIArgInfo getIgnore() { | |||
169 | return ABIArgInfo(Ignore); | |||
170 | } | |||
171 | static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true, | |||
172 | bool Realign = false, | |||
173 | llvm::Type *Padding = nullptr) { | |||
174 | auto AI = ABIArgInfo(Indirect); | |||
175 | AI.setIndirectAlign(Alignment); | |||
176 | AI.setIndirectByVal(ByVal); | |||
177 | AI.setIndirectRealign(Realign); | |||
178 | AI.setSRetAfterThis(false); | |||
179 | AI.setPaddingType(Padding); | |||
180 | return AI; | |||
181 | } | |||
182 | static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true, | |||
183 | bool Realign = false) { | |||
184 | auto AI = getIndirect(Alignment, ByVal, Realign); | |||
185 | AI.setInReg(true); | |||
186 | return AI; | |||
187 | } | |||
188 | static ABIArgInfo getInAlloca(unsigned FieldIndex) { | |||
189 | auto AI = ABIArgInfo(InAlloca); | |||
190 | AI.setInAllocaFieldIndex(FieldIndex); | |||
191 | return AI; | |||
192 | } | |||
193 | static ABIArgInfo getExpand() { | |||
194 | auto AI = ABIArgInfo(Expand); | |||
195 | AI.setPaddingType(nullptr); | |||
196 | return AI; | |||
197 | } | |||
198 | static ABIArgInfo getExpandWithPadding(bool PaddingInReg, | |||
199 | llvm::Type *Padding) { | |||
200 | auto AI = getExpand(); | |||
201 | AI.setPaddingInReg(PaddingInReg); | |||
202 | AI.setPaddingType(Padding); | |||
203 | return AI; | |||
204 | } | |||
205 | ||||
206 | /// \param unpaddedCoerceToType The coerce-to type with padding elements | |||
207 | /// removed, canonicalized to a single element if it would otherwise | |||
208 | /// have exactly one element. | |||
209 | static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, | |||
210 | llvm::Type *unpaddedCoerceToType) { | |||
211 | #ifndef NDEBUG | |||
212 | // Sanity checks on unpaddedCoerceToType. | |||
213 | ||||
214 | // Assert that we only have a struct type if there are multiple elements. | |||
215 | auto unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoerceToType); | |||
216 | assert(!unpaddedStruct || unpaddedStruct->getNumElements() != 1)((!unpaddedStruct || unpaddedStruct->getNumElements() != 1 ) ? static_cast<void> (0) : __assert_fail ("!unpaddedStruct || unpaddedStruct->getNumElements() != 1" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 216, __PRETTY_FUNCTION__)); | |||
217 | ||||
218 | // Assert that all the non-padding elements have a corresponding element | |||
219 | // in the unpadded type. | |||
220 | unsigned unpaddedIndex = 0; | |||
221 | for (auto eltType : coerceToType->elements()) { | |||
222 | if (isPaddingForCoerceAndExpand(eltType)) continue; | |||
223 | if (unpaddedStruct) { | |||
224 | assert(unpaddedStruct->getElementType(unpaddedIndex) == eltType)((unpaddedStruct->getElementType(unpaddedIndex) == eltType ) ? static_cast<void> (0) : __assert_fail ("unpaddedStruct->getElementType(unpaddedIndex) == eltType" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 224, __PRETTY_FUNCTION__)); | |||
225 | } else { | |||
226 | assert(unpaddedIndex == 0 && unpaddedCoerceToType == eltType)((unpaddedIndex == 0 && unpaddedCoerceToType == eltType ) ? static_cast<void> (0) : __assert_fail ("unpaddedIndex == 0 && unpaddedCoerceToType == eltType" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 226, __PRETTY_FUNCTION__)); | |||
227 | } | |||
228 | unpaddedIndex++; | |||
229 | } | |||
230 | ||||
231 | // Assert that there aren't extra elements in the unpadded type. | |||
232 | if (unpaddedStruct) { | |||
233 | assert(unpaddedStruct->getNumElements() == unpaddedIndex)((unpaddedStruct->getNumElements() == unpaddedIndex) ? static_cast <void> (0) : __assert_fail ("unpaddedStruct->getNumElements() == unpaddedIndex" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 233, __PRETTY_FUNCTION__)); | |||
234 | } else { | |||
235 | assert(unpaddedIndex == 1)((unpaddedIndex == 1) ? static_cast<void> (0) : __assert_fail ("unpaddedIndex == 1", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 235, __PRETTY_FUNCTION__)); | |||
236 | } | |||
237 | #endif | |||
238 | ||||
239 | auto AI = ABIArgInfo(CoerceAndExpand); | |||
240 | AI.setCoerceToType(coerceToType); | |||
241 | AI.setUnpaddedCoerceToType(unpaddedCoerceToType); | |||
242 | return AI; | |||
243 | } | |||
244 | ||||
245 | static bool isPaddingForCoerceAndExpand(llvm::Type *eltType) { | |||
246 | if (eltType->isArrayTy()) { | |||
247 | assert(eltType->getArrayElementType()->isIntegerTy(8))((eltType->getArrayElementType()->isIntegerTy(8)) ? static_cast <void> (0) : __assert_fail ("eltType->getArrayElementType()->isIntegerTy(8)" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 247, __PRETTY_FUNCTION__)); | |||
248 | return true; | |||
249 | } else { | |||
250 | return false; | |||
251 | } | |||
252 | } | |||
253 | ||||
254 | Kind getKind() const { return TheKind; } | |||
255 | bool isDirect() const { return TheKind == Direct; } | |||
256 | bool isInAlloca() const { return TheKind == InAlloca; } | |||
257 | bool isExtend() const { return TheKind == Extend; } | |||
258 | bool isIgnore() const { return TheKind == Ignore; } | |||
259 | bool isIndirect() const { return TheKind == Indirect; } | |||
260 | bool isExpand() const { return TheKind == Expand; } | |||
261 | bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; } | |||
262 | ||||
263 | bool canHaveCoerceToType() const { | |||
264 | return isDirect() || isExtend() || isCoerceAndExpand(); | |||
265 | } | |||
266 | ||||
267 | // Direct/Extend accessors | |||
268 | unsigned getDirectOffset() const { | |||
269 | assert((isDirect() || isExtend()) && "Not a direct or extend kind")(((isDirect() || isExtend()) && "Not a direct or extend kind" ) ? static_cast<void> (0) : __assert_fail ("(isDirect() || isExtend()) && \"Not a direct or extend kind\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 269, __PRETTY_FUNCTION__)); | |||
270 | return DirectOffset; | |||
271 | } | |||
272 | void setDirectOffset(unsigned Offset) { | |||
273 | assert((isDirect() || isExtend()) && "Not a direct or extend kind")(((isDirect() || isExtend()) && "Not a direct or extend kind" ) ? static_cast<void> (0) : __assert_fail ("(isDirect() || isExtend()) && \"Not a direct or extend kind\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 273, __PRETTY_FUNCTION__)); | |||
274 | DirectOffset = Offset; | |||
275 | } | |||
276 | ||||
277 | bool isSignExt() const { | |||
278 | assert(isExtend() && "Invalid kind!")((isExtend() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isExtend() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 278, __PRETTY_FUNCTION__)); | |||
279 | return SignExt; | |||
280 | } | |||
281 | void setSignExt(bool SExt) { | |||
282 | assert(isExtend() && "Invalid kind!")((isExtend() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isExtend() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 282, __PRETTY_FUNCTION__)); | |||
283 | SignExt = SExt; | |||
284 | } | |||
285 | ||||
286 | llvm::Type *getPaddingType() const { | |||
287 | return (canHavePaddingType() ? PaddingType : nullptr); | |||
288 | } | |||
289 | ||||
290 | bool getPaddingInReg() const { | |||
291 | return PaddingInReg; | |||
292 | } | |||
293 | void setPaddingInReg(bool PIR) { | |||
294 | PaddingInReg = PIR; | |||
295 | } | |||
296 | ||||
297 | llvm::Type *getCoerceToType() const { | |||
298 | assert(canHaveCoerceToType() && "Invalid kind!")((canHaveCoerceToType() && "Invalid kind!") ? static_cast <void> (0) : __assert_fail ("canHaveCoerceToType() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 298, __PRETTY_FUNCTION__)); | |||
299 | return TypeData; | |||
300 | } | |||
301 | ||||
302 | void setCoerceToType(llvm::Type *T) { | |||
303 | assert(canHaveCoerceToType() && "Invalid kind!")((canHaveCoerceToType() && "Invalid kind!") ? static_cast <void> (0) : __assert_fail ("canHaveCoerceToType() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 303, __PRETTY_FUNCTION__)); | |||
304 | TypeData = T; | |||
305 | } | |||
306 | ||||
307 | llvm::StructType *getCoerceAndExpandType() const { | |||
308 | assert(isCoerceAndExpand())((isCoerceAndExpand()) ? static_cast<void> (0) : __assert_fail ("isCoerceAndExpand()", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 308, __PRETTY_FUNCTION__)); | |||
309 | return cast<llvm::StructType>(TypeData); | |||
310 | } | |||
311 | ||||
312 | llvm::Type *getUnpaddedCoerceAndExpandType() const { | |||
313 | assert(isCoerceAndExpand())((isCoerceAndExpand()) ? static_cast<void> (0) : __assert_fail ("isCoerceAndExpand()", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 313, __PRETTY_FUNCTION__)); | |||
314 | return UnpaddedCoerceAndExpandType; | |||
315 | } | |||
316 | ||||
317 | ArrayRef<llvm::Type *>getCoerceAndExpandTypeSequence() const { | |||
318 | assert(isCoerceAndExpand())((isCoerceAndExpand()) ? static_cast<void> (0) : __assert_fail ("isCoerceAndExpand()", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 318, __PRETTY_FUNCTION__)); | |||
319 | if (auto structTy = | |||
320 | dyn_cast<llvm::StructType>(UnpaddedCoerceAndExpandType)) { | |||
321 | return structTy->elements(); | |||
322 | } else { | |||
323 | return llvm::makeArrayRef(&UnpaddedCoerceAndExpandType, 1); | |||
324 | } | |||
325 | } | |||
326 | ||||
327 | bool getInReg() const { | |||
328 | assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!")(((isDirect() || isExtend() || isIndirect()) && "Invalid kind!" ) ? static_cast<void> (0) : __assert_fail ("(isDirect() || isExtend() || isIndirect()) && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 328, __PRETTY_FUNCTION__)); | |||
329 | return InReg; | |||
330 | } | |||
331 | ||||
332 | void setInReg(bool IR) { | |||
333 | assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!")(((isDirect() || isExtend() || isIndirect()) && "Invalid kind!" ) ? static_cast<void> (0) : __assert_fail ("(isDirect() || isExtend() || isIndirect()) && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 333, __PRETTY_FUNCTION__)); | |||
334 | InReg = IR; | |||
335 | } | |||
336 | ||||
337 | // Indirect accessors | |||
338 | CharUnits getIndirectAlign() const { | |||
339 | assert(isIndirect() && "Invalid kind!")((isIndirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isIndirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 339, __PRETTY_FUNCTION__)); | |||
340 | return CharUnits::fromQuantity(IndirectAlign); | |||
341 | } | |||
342 | void setIndirectAlign(CharUnits IA) { | |||
343 | assert(isIndirect() && "Invalid kind!")((isIndirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isIndirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 343, __PRETTY_FUNCTION__)); | |||
344 | IndirectAlign = IA.getQuantity(); | |||
345 | } | |||
346 | ||||
347 | bool getIndirectByVal() const { | |||
348 | assert(isIndirect() && "Invalid kind!")((isIndirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isIndirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 348, __PRETTY_FUNCTION__)); | |||
349 | return IndirectByVal; | |||
350 | } | |||
351 | void setIndirectByVal(bool IBV) { | |||
352 | assert(isIndirect() && "Invalid kind!")((isIndirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isIndirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 352, __PRETTY_FUNCTION__)); | |||
353 | IndirectByVal = IBV; | |||
354 | } | |||
355 | ||||
356 | bool getIndirectRealign() const { | |||
357 | assert(isIndirect() && "Invalid kind!")((isIndirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isIndirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 357, __PRETTY_FUNCTION__)); | |||
358 | return IndirectRealign; | |||
359 | } | |||
360 | void setIndirectRealign(bool IR) { | |||
361 | assert(isIndirect() && "Invalid kind!")((isIndirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isIndirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 361, __PRETTY_FUNCTION__)); | |||
362 | IndirectRealign = IR; | |||
363 | } | |||
364 | ||||
365 | bool isSRetAfterThis() const { | |||
366 | assert(isIndirect() && "Invalid kind!")((isIndirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isIndirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 366, __PRETTY_FUNCTION__)); | |||
367 | return SRetAfterThis; | |||
368 | } | |||
369 | void setSRetAfterThis(bool AfterThis) { | |||
370 | assert(isIndirect() && "Invalid kind!")((isIndirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isIndirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 370, __PRETTY_FUNCTION__)); | |||
371 | SRetAfterThis = AfterThis; | |||
372 | } | |||
373 | ||||
374 | unsigned getInAllocaFieldIndex() const { | |||
375 | assert(isInAlloca() && "Invalid kind!")((isInAlloca() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isInAlloca() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 375, __PRETTY_FUNCTION__)); | |||
376 | return AllocaFieldIndex; | |||
377 | } | |||
378 | void setInAllocaFieldIndex(unsigned FieldIndex) { | |||
379 | assert(isInAlloca() && "Invalid kind!")((isInAlloca() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isInAlloca() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 379, __PRETTY_FUNCTION__)); | |||
380 | AllocaFieldIndex = FieldIndex; | |||
381 | } | |||
382 | ||||
383 | /// Return true if this field of an inalloca struct should be returned | |||
384 | /// to implement a struct return calling convention. | |||
385 | bool getInAllocaSRet() const { | |||
386 | assert(isInAlloca() && "Invalid kind!")((isInAlloca() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isInAlloca() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 386, __PRETTY_FUNCTION__)); | |||
387 | return InAllocaSRet; | |||
388 | } | |||
389 | ||||
390 | void setInAllocaSRet(bool SRet) { | |||
391 | assert(isInAlloca() && "Invalid kind!")((isInAlloca() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isInAlloca() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 391, __PRETTY_FUNCTION__)); | |||
392 | InAllocaSRet = SRet; | |||
393 | } | |||
394 | ||||
395 | bool getCanBeFlattened() const { | |||
396 | assert(isDirect() && "Invalid kind!")((isDirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isDirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 396, __PRETTY_FUNCTION__)); | |||
397 | return CanBeFlattened; | |||
398 | } | |||
399 | ||||
400 | void setCanBeFlattened(bool Flatten) { | |||
401 | assert(isDirect() && "Invalid kind!")((isDirect() && "Invalid kind!") ? static_cast<void > (0) : __assert_fail ("isDirect() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 401, __PRETTY_FUNCTION__)); | |||
402 | CanBeFlattened = Flatten; | |||
403 | } | |||
404 | ||||
405 | void dump() const; | |||
406 | }; | |||
407 | ||||
408 | /// A class for recording the number of arguments that a function | |||
409 | /// signature requires. | |||
410 | class RequiredArgs { | |||
411 | /// The number of required arguments, or ~0 if the signature does | |||
412 | /// not permit optional arguments. | |||
413 | unsigned NumRequired; | |||
414 | public: | |||
415 | enum All_t { All }; | |||
416 | ||||
417 | RequiredArgs(All_t _) : NumRequired(~0U) {} | |||
418 | explicit RequiredArgs(unsigned n) : NumRequired(n) { | |||
419 | assert(n != ~0U)((n != ~0U) ? static_cast<void> (0) : __assert_fail ("n != ~0U" , "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 419, __PRETTY_FUNCTION__)); | |||
420 | } | |||
421 | ||||
422 | /// Compute the arguments required by the given formal prototype, | |||
423 | /// given that there may be some additional, non-formal arguments | |||
424 | /// in play. | |||
425 | /// | |||
426 | /// If FD is not null, this will consider pass_object_size params in FD. | |||
427 | static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, | |||
428 | unsigned additional) { | |||
429 | if (!prototype->isVariadic()) return All; | |||
| ||||
430 | ||||
431 | if (prototype->hasExtParameterInfos()) | |||
432 | additional += llvm::count_if( | |||
433 | prototype->getExtParameterInfos(), | |||
434 | [](const FunctionProtoType::ExtParameterInfo &ExtInfo) { | |||
435 | return ExtInfo.hasPassObjectSize(); | |||
436 | }); | |||
437 | ||||
438 | return RequiredArgs(prototype->getNumParams() + additional); | |||
439 | } | |||
440 | ||||
441 | static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype, | |||
442 | unsigned additional) { | |||
443 | return forPrototypePlus(prototype.getTypePtr(), additional); | |||
444 | } | |||
445 | ||||
446 | static RequiredArgs forPrototype(const FunctionProtoType *prototype) { | |||
447 | return forPrototypePlus(prototype, 0); | |||
448 | } | |||
449 | ||||
450 | static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) { | |||
451 | return forPrototypePlus(prototype.getTypePtr(), 0); | |||
452 | } | |||
453 | ||||
454 | bool allowsOptionalArgs() const { return NumRequired != ~0U; } | |||
455 | unsigned getNumRequiredArgs() const { | |||
456 | assert(allowsOptionalArgs())((allowsOptionalArgs()) ? static_cast<void> (0) : __assert_fail ("allowsOptionalArgs()", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 456, __PRETTY_FUNCTION__)); | |||
457 | return NumRequired; | |||
458 | } | |||
459 | ||||
460 | unsigned getOpaqueData() const { return NumRequired; } | |||
461 | static RequiredArgs getFromOpaqueData(unsigned value) { | |||
462 | if (value == ~0U) return All; | |||
463 | return RequiredArgs(value); | |||
464 | } | |||
465 | }; | |||
466 | ||||
467 | // Implementation detail of CGFunctionInfo, factored out so it can be named | |||
468 | // in the TrailingObjects base class of CGFunctionInfo. | |||
469 | struct CGFunctionInfoArgInfo { | |||
470 | CanQualType type; | |||
471 | ABIArgInfo info; | |||
472 | }; | |||
473 | ||||
474 | /// CGFunctionInfo - Class to encapsulate the information about a | |||
475 | /// function definition. | |||
476 | class CGFunctionInfo final | |||
477 | : public llvm::FoldingSetNode, | |||
478 | private llvm::TrailingObjects<CGFunctionInfo, CGFunctionInfoArgInfo, | |||
479 | FunctionProtoType::ExtParameterInfo> { | |||
480 | typedef CGFunctionInfoArgInfo ArgInfo; | |||
481 | typedef FunctionProtoType::ExtParameterInfo ExtParameterInfo; | |||
482 | ||||
483 | /// The LLVM::CallingConv to use for this function (as specified by the | |||
484 | /// user). | |||
485 | unsigned CallingConvention : 8; | |||
486 | ||||
487 | /// The LLVM::CallingConv to actually use for this function, which may | |||
488 | /// depend on the ABI. | |||
489 | unsigned EffectiveCallingConvention : 8; | |||
490 | ||||
491 | /// The clang::CallingConv that this was originally created with. | |||
492 | unsigned ASTCallingConvention : 6; | |||
493 | ||||
494 | /// Whether this is an instance method. | |||
495 | unsigned InstanceMethod : 1; | |||
496 | ||||
497 | /// Whether this is a chain call. | |||
498 | unsigned ChainCall : 1; | |||
499 | ||||
500 | /// Whether this function is noreturn. | |||
501 | unsigned NoReturn : 1; | |||
502 | ||||
503 | /// Whether this function is returns-retained. | |||
504 | unsigned ReturnsRetained : 1; | |||
505 | ||||
506 | /// Whether this function saved caller registers. | |||
507 | unsigned NoCallerSavedRegs : 1; | |||
508 | ||||
509 | /// How many arguments to pass inreg. | |||
510 | unsigned HasRegParm : 1; | |||
511 | unsigned RegParm : 3; | |||
512 | ||||
513 | /// Whether this function has nocf_check attribute. | |||
514 | unsigned NoCfCheck : 1; | |||
515 | ||||
516 | RequiredArgs Required; | |||
517 | ||||
518 | /// The struct representing all arguments passed in memory. Only used when | |||
519 | /// passing non-trivial types with inalloca. Not part of the profile. | |||
520 | llvm::StructType *ArgStruct; | |||
521 | unsigned ArgStructAlign : 31; | |||
522 | unsigned HasExtParameterInfos : 1; | |||
523 | ||||
524 | unsigned NumArgs; | |||
525 | ||||
526 | ArgInfo *getArgsBuffer() { | |||
527 | return getTrailingObjects<ArgInfo>(); | |||
528 | } | |||
529 | const ArgInfo *getArgsBuffer() const { | |||
530 | return getTrailingObjects<ArgInfo>(); | |||
531 | } | |||
532 | ||||
533 | ExtParameterInfo *getExtParameterInfosBuffer() { | |||
534 | return getTrailingObjects<ExtParameterInfo>(); | |||
535 | } | |||
536 | const ExtParameterInfo *getExtParameterInfosBuffer() const{ | |||
537 | return getTrailingObjects<ExtParameterInfo>(); | |||
538 | } | |||
539 | ||||
540 | CGFunctionInfo() : Required(RequiredArgs::All) {} | |||
541 | ||||
542 | public: | |||
543 | static CGFunctionInfo *create(unsigned llvmCC, | |||
544 | bool instanceMethod, | |||
545 | bool chainCall, | |||
546 | const FunctionType::ExtInfo &extInfo, | |||
547 | ArrayRef<ExtParameterInfo> paramInfos, | |||
548 | CanQualType resultType, | |||
549 | ArrayRef<CanQualType> argTypes, | |||
550 | RequiredArgs required); | |||
551 | void operator delete(void *p) { ::operator delete(p); } | |||
552 | ||||
553 | // Friending class TrailingObjects is apparently not good enough for MSVC, | |||
554 | // so these have to be public. | |||
555 | friend class TrailingObjects; | |||
556 | size_t numTrailingObjects(OverloadToken<ArgInfo>) const { | |||
557 | return NumArgs + 1; | |||
558 | } | |||
559 | size_t numTrailingObjects(OverloadToken<ExtParameterInfo>) const { | |||
560 | return (HasExtParameterInfos ? NumArgs : 0); | |||
561 | } | |||
562 | ||||
563 | typedef const ArgInfo *const_arg_iterator; | |||
564 | typedef ArgInfo *arg_iterator; | |||
565 | ||||
566 | typedef llvm::iterator_range<arg_iterator> arg_range; | |||
567 | typedef llvm::iterator_range<const_arg_iterator> const_arg_range; | |||
568 | ||||
569 | arg_range arguments() { return arg_range(arg_begin(), arg_end()); } | |||
570 | const_arg_range arguments() const { | |||
571 | return const_arg_range(arg_begin(), arg_end()); | |||
572 | } | |||
573 | ||||
574 | const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; } | |||
575 | const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; } | |||
576 | arg_iterator arg_begin() { return getArgsBuffer() + 1; } | |||
577 | arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; } | |||
578 | ||||
579 | unsigned arg_size() const { return NumArgs; } | |||
580 | ||||
581 | bool isVariadic() const { return Required.allowsOptionalArgs(); } | |||
582 | RequiredArgs getRequiredArgs() const { return Required; } | |||
583 | unsigned getNumRequiredArgs() const { | |||
584 | return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size(); | |||
585 | } | |||
586 | ||||
587 | bool isInstanceMethod() const { return InstanceMethod; } | |||
588 | ||||
589 | bool isChainCall() const { return ChainCall; } | |||
590 | ||||
591 | bool isNoReturn() const { return NoReturn; } | |||
592 | ||||
593 | /// In ARC, whether this function retains its return value. This | |||
594 | /// is not always reliable for call sites. | |||
595 | bool isReturnsRetained() const { return ReturnsRetained; } | |||
596 | ||||
597 | /// Whether this function no longer saves caller registers. | |||
598 | bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; } | |||
599 | ||||
600 | /// Whether this function has nocf_check attribute. | |||
601 | bool isNoCfCheck() const { return NoCfCheck; } | |||
602 | ||||
603 | /// getASTCallingConvention() - Return the AST-specified calling | |||
604 | /// convention. | |||
605 | CallingConv getASTCallingConvention() const { | |||
606 | return CallingConv(ASTCallingConvention); | |||
607 | } | |||
608 | ||||
609 | /// getCallingConvention - Return the user specified calling | |||
610 | /// convention, which has been translated into an LLVM CC. | |||
611 | unsigned getCallingConvention() const { return CallingConvention; } | |||
612 | ||||
613 | /// getEffectiveCallingConvention - Return the actual calling convention to | |||
614 | /// use, which may depend on the ABI. | |||
615 | unsigned getEffectiveCallingConvention() const { | |||
616 | return EffectiveCallingConvention; | |||
617 | } | |||
618 | void setEffectiveCallingConvention(unsigned Value) { | |||
619 | EffectiveCallingConvention = Value; | |||
620 | } | |||
621 | ||||
622 | bool getHasRegParm() const { return HasRegParm; } | |||
623 | unsigned getRegParm() const { return RegParm; } | |||
624 | ||||
625 | FunctionType::ExtInfo getExtInfo() const { | |||
626 | return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(), | |||
627 | getASTCallingConvention(), isReturnsRetained(), | |||
628 | isNoCallerSavedRegs(), isNoCfCheck()); | |||
629 | } | |||
630 | ||||
631 | CanQualType getReturnType() const { return getArgsBuffer()[0].type; } | |||
632 | ||||
633 | ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; } | |||
634 | const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; } | |||
635 | ||||
636 | ArrayRef<ExtParameterInfo> getExtParameterInfos() const { | |||
637 | if (!HasExtParameterInfos) return {}; | |||
638 | return llvm::makeArrayRef(getExtParameterInfosBuffer(), NumArgs); | |||
639 | } | |||
640 | ExtParameterInfo getExtParameterInfo(unsigned argIndex) const { | |||
641 | assert(argIndex <= NumArgs)((argIndex <= NumArgs) ? static_cast<void> (0) : __assert_fail ("argIndex <= NumArgs", "/build/llvm-toolchain-snapshot-10~++20200110111110+a1cc19b5814/clang/include/clang/CodeGen/CGFunctionInfo.h" , 641, __PRETTY_FUNCTION__)); | |||
642 | if (!HasExtParameterInfos) return ExtParameterInfo(); | |||
643 | return getExtParameterInfos()[argIndex]; | |||
644 | } | |||
645 | ||||
646 | /// Return true if this function uses inalloca arguments. | |||
647 | bool usesInAlloca() const { return ArgStruct; } | |||
648 | ||||
649 | /// Get the struct type used to represent all the arguments in memory. | |||
650 | llvm::StructType *getArgStruct() const { return ArgStruct; } | |||
651 | CharUnits getArgStructAlignment() const { | |||
652 | return CharUnits::fromQuantity(ArgStructAlign); | |||
653 | } | |||
654 | void setArgStruct(llvm::StructType *Ty, CharUnits Align) { | |||
655 | ArgStruct = Ty; | |||
656 | ArgStructAlign = Align.getQuantity(); | |||
657 | } | |||
658 | ||||
659 | void Profile(llvm::FoldingSetNodeID &ID) { | |||
660 | ID.AddInteger(getASTCallingConvention()); | |||
661 | ID.AddBoolean(InstanceMethod); | |||
662 | ID.AddBoolean(ChainCall); | |||
663 | ID.AddBoolean(NoReturn); | |||
664 | ID.AddBoolean(ReturnsRetained); | |||
665 | ID.AddBoolean(NoCallerSavedRegs); | |||
666 | ID.AddBoolean(HasRegParm); | |||
667 | ID.AddInteger(RegParm); | |||
668 | ID.AddBoolean(NoCfCheck); | |||
669 | ID.AddInteger(Required.getOpaqueData()); | |||
670 | ID.AddBoolean(HasExtParameterInfos); | |||
671 | if (HasExtParameterInfos) { | |||
672 | for (auto paramInfo : getExtParameterInfos()) | |||
673 | ID.AddInteger(paramInfo.getOpaqueValue()); | |||
674 | } | |||
675 | getReturnType().Profile(ID); | |||
676 | for (const auto &I : arguments()) | |||
677 | I.type.Profile(ID); | |||
678 | } | |||
679 | static void Profile(llvm::FoldingSetNodeID &ID, | |||
680 | bool InstanceMethod, | |||
681 | bool ChainCall, | |||
682 | const FunctionType::ExtInfo &info, | |||
683 | ArrayRef<ExtParameterInfo> paramInfos, | |||
684 | RequiredArgs required, | |||
685 | CanQualType resultType, | |||
686 | ArrayRef<CanQualType> argTypes) { | |||
687 | ID.AddInteger(info.getCC()); | |||
688 | ID.AddBoolean(InstanceMethod); | |||
689 | ID.AddBoolean(ChainCall); | |||
690 | ID.AddBoolean(info.getNoReturn()); | |||
691 | ID.AddBoolean(info.getProducesResult()); | |||
692 | ID.AddBoolean(info.getNoCallerSavedRegs()); | |||
693 | ID.AddBoolean(info.getHasRegParm()); | |||
694 | ID.AddInteger(info.getRegParm()); | |||
695 | ID.AddBoolean(info.getNoCfCheck()); | |||
696 | ID.AddInteger(required.getOpaqueData()); | |||
697 | ID.AddBoolean(!paramInfos.empty()); | |||
698 | if (!paramInfos.empty()) { | |||
699 | for (auto paramInfo : paramInfos) | |||
700 | ID.AddInteger(paramInfo.getOpaqueValue()); | |||
701 | } | |||
702 | resultType.Profile(ID); | |||
703 | for (ArrayRef<CanQualType>::iterator | |||
704 | i = argTypes.begin(), e = argTypes.end(); i != e; ++i) { | |||
705 | i->Profile(ID); | |||
706 | } | |||
707 | } | |||
708 | }; | |||
709 | ||||
710 | } // end namespace CodeGen | |||
711 | } // end namespace clang | |||
712 | ||||
713 | #endif |