1 | //===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===// |
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 provides an abstract class for C++ code generation. Concrete subclasses |
10 | // of this implement code generation for specific C++ ABIs. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "CGCXXABI.h" |
15 | #include "CGCleanup.h" |
16 | #include "clang/AST/Attr.h" |
17 | |
18 | using namespace clang; |
19 | using namespace CodeGen; |
20 | |
21 | CGCXXABI::~CGCXXABI() { } |
22 | |
23 | Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) { |
24 | return CGF.makeNaturalAddressForPointer( |
25 | Ptr: CGF.CXXABIThisValue, T: CGF.CXXABIThisDecl->getType()->getPointeeType(), |
26 | Alignment: CGF.CXXABIThisAlignment); |
27 | } |
28 | |
29 | void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { |
30 | DiagnosticsEngine &Diags = CGF.CGM.getDiags(); |
31 | unsigned DiagID = Diags.getCustomDiagID(L: DiagnosticsEngine::Error, |
32 | FormatString: "cannot yet compile %0 in this ABI" ); |
33 | Diags.Report(Loc: CGF.getContext().getFullLoc(Loc: CGF.CurCodeDecl->getLocation()), |
34 | DiagID) |
35 | << S; |
36 | } |
37 | |
38 | llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) { |
39 | return llvm::Constant::getNullValue(Ty: CGM.getTypes().ConvertType(T)); |
40 | } |
41 | |
42 | llvm::Type * |
43 | CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { |
44 | return CGM.getTypes().ConvertType(T: CGM.getContext().getPointerDiffType()); |
45 | } |
46 | |
47 | CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( |
48 | CodeGenFunction &CGF, const Expr *E, Address This, |
49 | llvm::Value *&ThisPtrForCall, |
50 | llvm::Value *MemPtr, const MemberPointerType *MPT) { |
51 | ErrorUnsupportedABI(CGF, S: "calls through member pointers" ); |
52 | |
53 | const auto *RD = |
54 | cast<CXXRecordDecl>(Val: MPT->getClass()->castAs<RecordType>()->getDecl()); |
55 | ThisPtrForCall = |
56 | CGF.getAsNaturalPointerTo(Addr: This, PointeeType: CGF.getContext().getRecordType(Decl: RD)); |
57 | const FunctionProtoType *FPT = |
58 | MPT->getPointeeType()->getAs<FunctionProtoType>(); |
59 | llvm::Constant *FnPtr = llvm::Constant::getNullValue( |
60 | Ty: llvm::PointerType::getUnqual(C&: CGM.getLLVMContext())); |
61 | return CGCallee::forDirect(functionPtr: FnPtr, abstractInfo: FPT); |
62 | } |
63 | |
64 | llvm::Value * |
65 | CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, |
66 | Address Base, llvm::Value *MemPtr, |
67 | const MemberPointerType *MPT) { |
68 | ErrorUnsupportedABI(CGF, S: "loads of member pointers" ); |
69 | llvm::Type *Ty = |
70 | llvm::PointerType::get(C&: CGF.getLLVMContext(), AddressSpace: Base.getAddressSpace()); |
71 | return llvm::Constant::getNullValue(Ty); |
72 | } |
73 | |
74 | llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, |
75 | const CastExpr *E, |
76 | llvm::Value *Src) { |
77 | ErrorUnsupportedABI(CGF, S: "member function pointer conversions" ); |
78 | return GetBogusMemberPointer(T: E->getType()); |
79 | } |
80 | |
81 | llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E, |
82 | llvm::Constant *Src) { |
83 | return GetBogusMemberPointer(T: E->getType()); |
84 | } |
85 | |
86 | llvm::Value * |
87 | CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, |
88 | llvm::Value *L, |
89 | llvm::Value *R, |
90 | const MemberPointerType *MPT, |
91 | bool Inequality) { |
92 | ErrorUnsupportedABI(CGF, S: "member function pointer comparison" ); |
93 | return CGF.Builder.getFalse(); |
94 | } |
95 | |
96 | llvm::Value * |
97 | CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, |
98 | llvm::Value *MemPtr, |
99 | const MemberPointerType *MPT) { |
100 | ErrorUnsupportedABI(CGF, S: "member function pointer null testing" ); |
101 | return CGF.Builder.getFalse(); |
102 | } |
103 | |
104 | llvm::Constant * |
105 | CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { |
106 | return GetBogusMemberPointer(T: QualType(MPT, 0)); |
107 | } |
108 | |
109 | llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { |
110 | return GetBogusMemberPointer(T: CGM.getContext().getMemberPointerType( |
111 | T: MD->getType(), Cls: MD->getParent()->getTypeForDecl())); |
112 | } |
113 | |
114 | llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, |
115 | CharUnits offset) { |
116 | return GetBogusMemberPointer(T: QualType(MPT, 0)); |
117 | } |
118 | |
119 | llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) { |
120 | return GetBogusMemberPointer(T: MPT); |
121 | } |
122 | |
123 | bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) { |
124 | // Fake answer. |
125 | return true; |
126 | } |
127 | |
128 | void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { |
129 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(Val: CGF.CurGD.getDecl()); |
130 | |
131 | // FIXME: I'm not entirely sure I like using a fake decl just for code |
132 | // generation. Maybe we can come up with a better way? |
133 | auto *ThisDecl = |
134 | ImplicitParamDecl::Create(C&: CGM.getContext(), DC: nullptr, IdLoc: MD->getLocation(), |
135 | Id: &CGM.getContext().Idents.get(Name: "this" ), |
136 | T: MD->getThisType(), ParamKind: ImplicitParamKind::CXXThis); |
137 | params.push_back(Elt: ThisDecl); |
138 | CGF.CXXABIThisDecl = ThisDecl; |
139 | |
140 | // Compute the presumed alignment of 'this', which basically comes |
141 | // down to whether we know it's a complete object or not. |
142 | auto &Layout = CGF.getContext().getASTRecordLayout(D: MD->getParent()); |
143 | if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case |
144 | MD->getParent()->isEffectivelyFinal() || |
145 | isThisCompleteObject(GD: CGF.CurGD)) { |
146 | CGF.CXXABIThisAlignment = Layout.getAlignment(); |
147 | } else { |
148 | CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment(); |
149 | } |
150 | } |
151 | |
152 | llvm::Value *CGCXXABI::loadIncomingCXXThis(CodeGenFunction &CGF) { |
153 | return CGF.Builder.CreateLoad(Addr: CGF.GetAddrOfLocalVar(VD: getThisDecl(CGF)), |
154 | Name: "this" ); |
155 | } |
156 | |
157 | void CGCXXABI::setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr) { |
158 | /// Initialize the 'this' slot. |
159 | assert(getThisDecl(CGF) && "no 'this' variable for function" ); |
160 | CGF.CXXABIThisValue = ThisPtr; |
161 | } |
162 | |
163 | bool CGCXXABI::mayNeedDestruction(const VarDecl *VD) const { |
164 | if (VD->needsDestruction(Ctx: getContext())) |
165 | return true; |
166 | |
167 | // If the variable has an incomplete class type (or array thereof), it |
168 | // might need destruction. |
169 | const Type *T = VD->getType()->getBaseElementTypeUnsafe(); |
170 | if (T->getAs<RecordType>() && T->isIncompleteType()) |
171 | return true; |
172 | |
173 | return false; |
174 | } |
175 | |
176 | bool CGCXXABI::isEmittedWithConstantInitializer( |
177 | const VarDecl *VD, bool InspectInitForWeakDef) const { |
178 | VD = VD->getMostRecentDecl(); |
179 | if (VD->hasAttr<ConstInitAttr>()) |
180 | return true; |
181 | |
182 | // All later checks examine the initializer specified on the variable. If |
183 | // the variable is weak, such examination would not be correct. |
184 | if (!InspectInitForWeakDef && (VD->isWeak() || VD->hasAttr<SelectAnyAttr>())) |
185 | return false; |
186 | |
187 | const VarDecl *InitDecl = VD->getInitializingDeclaration(); |
188 | if (!InitDecl) |
189 | return false; |
190 | |
191 | // If there's no initializer to run, this is constant initialization. |
192 | if (!InitDecl->hasInit()) |
193 | return true; |
194 | |
195 | // If we have the only definition, we don't need a thread wrapper if we |
196 | // will emit the value as a constant. |
197 | if (isUniqueGVALinkage(L: getContext().GetGVALinkageForVariable(VD))) |
198 | return !mayNeedDestruction(VD) && InitDecl->evaluateValue(); |
199 | |
200 | // Otherwise, we need a thread wrapper unless we know that every |
201 | // translation unit will emit the value as a constant. We rely on the |
202 | // variable being constant-initialized in every translation unit if it's |
203 | // constant-initialized in any translation unit, which isn't actually |
204 | // guaranteed by the standard but is necessary for sanity. |
205 | return InitDecl->hasConstantInitialization(); |
206 | } |
207 | |
208 | void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, |
209 | RValue RV, QualType ResultType) { |
210 | assert(!CGF.hasAggregateEvaluationKind(ResultType) && |
211 | "cannot handle aggregates" ); |
212 | CGF.EmitReturnOfRValue(RV, Ty: ResultType); |
213 | } |
214 | |
215 | CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { |
216 | if (!requiresArrayCookie(E: expr)) |
217 | return CharUnits::Zero(); |
218 | return getArrayCookieSizeImpl(elementType: expr->getAllocatedType()); |
219 | } |
220 | |
221 | CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) { |
222 | // BOGUS |
223 | return CharUnits::Zero(); |
224 | } |
225 | |
226 | Address CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, |
227 | Address NewPtr, |
228 | llvm::Value *NumElements, |
229 | const CXXNewExpr *expr, |
230 | QualType ElementType) { |
231 | // Should never be called. |
232 | ErrorUnsupportedABI(CGF, S: "array cookie initialization" ); |
233 | return Address::invalid(); |
234 | } |
235 | |
236 | bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr, |
237 | QualType elementType) { |
238 | // If the class's usual deallocation function takes two arguments, |
239 | // it needs a cookie. |
240 | if (expr->doesUsualArrayDeleteWantSize()) |
241 | return true; |
242 | |
243 | return elementType.isDestructedType(); |
244 | } |
245 | |
246 | bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) { |
247 | // If the class's usual deallocation function takes two arguments, |
248 | // it needs a cookie. |
249 | if (expr->doesUsualArrayDeleteWantSize()) |
250 | return true; |
251 | |
252 | return expr->getAllocatedType().isDestructedType(); |
253 | } |
254 | |
255 | void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, |
256 | const CXXDeleteExpr *expr, QualType eltTy, |
257 | llvm::Value *&numElements, |
258 | llvm::Value *&allocPtr, CharUnits &cookieSize) { |
259 | // Derive a char* in the same address space as the pointer. |
260 | ptr = ptr.withElementType(ElemTy: CGF.Int8Ty); |
261 | |
262 | // If we don't need an array cookie, bail out early. |
263 | if (!requiresArrayCookie(expr, elementType: eltTy)) { |
264 | allocPtr = ptr.emitRawPointer(CGF); |
265 | numElements = nullptr; |
266 | cookieSize = CharUnits::Zero(); |
267 | return; |
268 | } |
269 | |
270 | cookieSize = getArrayCookieSizeImpl(elementType: eltTy); |
271 | Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(Addr: ptr, Offset: -cookieSize); |
272 | allocPtr = allocAddr.emitRawPointer(CGF); |
273 | numElements = readArrayCookieImpl(IGF&: CGF, ptr: allocAddr, cookieSize); |
274 | } |
275 | |
276 | llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, |
277 | Address ptr, |
278 | CharUnits cookieSize) { |
279 | ErrorUnsupportedABI(CGF, S: "reading a new[] cookie" ); |
280 | return llvm::ConstantInt::get(Ty: CGF.SizeTy, V: 0); |
281 | } |
282 | |
283 | /// Returns the adjustment, in bytes, required for the given |
284 | /// member-pointer operation. Returns null if no adjustment is |
285 | /// required. |
286 | llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) { |
287 | assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || |
288 | E->getCastKind() == CK_BaseToDerivedMemberPointer); |
289 | |
290 | QualType derivedType; |
291 | if (E->getCastKind() == CK_DerivedToBaseMemberPointer) |
292 | derivedType = E->getSubExpr()->getType(); |
293 | else |
294 | derivedType = E->getType(); |
295 | |
296 | const CXXRecordDecl *derivedClass = |
297 | derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl(); |
298 | |
299 | return CGM.GetNonVirtualBaseClassOffset(ClassDecl: derivedClass, |
300 | PathBegin: E->path_begin(), |
301 | PathEnd: E->path_end()); |
302 | } |
303 | |
304 | llvm::BasicBlock * |
305 | CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, |
306 | const CXXRecordDecl *RD) { |
307 | if (CGM.getTarget().getCXXABI().hasConstructorVariants()) |
308 | llvm_unreachable("shouldn't be called in this ABI" ); |
309 | |
310 | ErrorUnsupportedABI(CGF, S: "complete object detection in ctor" ); |
311 | return nullptr; |
312 | } |
313 | |
314 | void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, |
315 | const CXXDestructorDecl *Dtor, |
316 | CXXDtorType DT) const { |
317 | // Assume the base C++ ABI has no special rules for destructor variants. |
318 | CGM.setDLLImportDLLExport(GV, D: Dtor); |
319 | } |
320 | |
321 | llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage( |
322 | GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { |
323 | // Delegate back to CGM by default. |
324 | return CGM.getLLVMLinkageForDeclarator(D: Dtor, Linkage); |
325 | } |
326 | |
327 | bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { |
328 | return false; |
329 | } |
330 | |
331 | llvm::CallInst * |
332 | CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, |
333 | llvm::Value *Exn) { |
334 | // Just call std::terminate and ignore the violating exception. |
335 | return CGF.EmitNounwindRuntimeCall(callee: CGF.CGM.getTerminateFn()); |
336 | } |
337 | |
338 | CatchTypeInfo CGCXXABI::getCatchAllTypeInfo() { |
339 | return CatchTypeInfo{.RTTI: nullptr, .Flags: 0}; |
340 | } |
341 | |
342 | std::vector<CharUnits> CGCXXABI::getVBPtrOffsets(const CXXRecordDecl *RD) { |
343 | return std::vector<CharUnits>(); |
344 | } |
345 | |
346 | CGCXXABI::AddedStructorArgCounts CGCXXABI::addImplicitConstructorArgs( |
347 | CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, |
348 | bool ForVirtualBase, bool Delegating, CallArgList &Args) { |
349 | AddedStructorArgs AddedArgs = |
350 | getImplicitConstructorArgs(CGF, D, Type, ForVirtualBase, Delegating); |
351 | for (size_t i = 0; i < AddedArgs.Prefix.size(); ++i) { |
352 | Args.insert(I: Args.begin() + 1 + i, |
353 | Elt: CallArg(RValue::get(V: AddedArgs.Prefix[i].Value), |
354 | AddedArgs.Prefix[i].Type)); |
355 | } |
356 | for (const auto &arg : AddedArgs.Suffix) { |
357 | Args.add(rvalue: RValue::get(V: arg.Value), type: arg.Type); |
358 | } |
359 | return AddedStructorArgCounts(AddedArgs.Prefix.size(), |
360 | AddedArgs.Suffix.size()); |
361 | } |
362 | |