1e5dd7070Spatrick //===------- ItaniumCXXABI.cpp - Emit LLVM Code from ASTs for a Module ----===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This provides C++ code generation targeting the Itanium C++ ABI. The class
10e5dd7070Spatrick // in this file generates structures that follow the Itanium C++ ABI, which is
11e5dd7070Spatrick // documented at:
12a9ac8606Spatrick // https://itanium-cxx-abi.github.io/cxx-abi/abi.html
13a9ac8606Spatrick // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
14e5dd7070Spatrick //
15e5dd7070Spatrick // It also supports the closely-related ARM ABI, documented at:
16a9ac8606Spatrick // https://developer.arm.com/documentation/ihi0041/g/
17e5dd7070Spatrick //
18e5dd7070Spatrick //===----------------------------------------------------------------------===//
19e5dd7070Spatrick
20e5dd7070Spatrick #include "CGCXXABI.h"
21e5dd7070Spatrick #include "CGCleanup.h"
22e5dd7070Spatrick #include "CGRecordLayout.h"
23e5dd7070Spatrick #include "CGVTables.h"
24e5dd7070Spatrick #include "CodeGenFunction.h"
25e5dd7070Spatrick #include "CodeGenModule.h"
26e5dd7070Spatrick #include "TargetInfo.h"
27e5dd7070Spatrick #include "clang/AST/Attr.h"
28e5dd7070Spatrick #include "clang/AST/Mangle.h"
29e5dd7070Spatrick #include "clang/AST/StmtCXX.h"
30e5dd7070Spatrick #include "clang/AST/Type.h"
31e5dd7070Spatrick #include "clang/CodeGen/ConstantInitBuilder.h"
32e5dd7070Spatrick #include "llvm/IR/DataLayout.h"
33e5dd7070Spatrick #include "llvm/IR/GlobalValue.h"
34e5dd7070Spatrick #include "llvm/IR/Instructions.h"
35e5dd7070Spatrick #include "llvm/IR/Intrinsics.h"
36e5dd7070Spatrick #include "llvm/IR/Value.h"
37e5dd7070Spatrick #include "llvm/Support/ScopedPrinter.h"
38e5dd7070Spatrick
39e5dd7070Spatrick using namespace clang;
40e5dd7070Spatrick using namespace CodeGen;
41e5dd7070Spatrick
42e5dd7070Spatrick namespace {
43e5dd7070Spatrick class ItaniumCXXABI : public CodeGen::CGCXXABI {
44e5dd7070Spatrick /// VTables - All the vtables which have been defined.
45e5dd7070Spatrick llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
46e5dd7070Spatrick
47e5dd7070Spatrick /// All the thread wrapper functions that have been used.
48e5dd7070Spatrick llvm::SmallVector<std::pair<const VarDecl *, llvm::Function *>, 8>
49e5dd7070Spatrick ThreadWrappers;
50e5dd7070Spatrick
51e5dd7070Spatrick protected:
52e5dd7070Spatrick bool UseARMMethodPtrABI;
53e5dd7070Spatrick bool UseARMGuardVarABI;
54e5dd7070Spatrick bool Use32BitVTableOffsetABI;
55e5dd7070Spatrick
getMangleContext()56e5dd7070Spatrick ItaniumMangleContext &getMangleContext() {
57e5dd7070Spatrick return cast<ItaniumMangleContext>(CodeGen::CGCXXABI::getMangleContext());
58e5dd7070Spatrick }
59e5dd7070Spatrick
60e5dd7070Spatrick public:
ItaniumCXXABI(CodeGen::CodeGenModule & CGM,bool UseARMMethodPtrABI=false,bool UseARMGuardVarABI=false)61e5dd7070Spatrick ItaniumCXXABI(CodeGen::CodeGenModule &CGM,
62e5dd7070Spatrick bool UseARMMethodPtrABI = false,
63e5dd7070Spatrick bool UseARMGuardVarABI = false) :
64e5dd7070Spatrick CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
65e5dd7070Spatrick UseARMGuardVarABI(UseARMGuardVarABI),
66e5dd7070Spatrick Use32BitVTableOffsetABI(false) { }
67e5dd7070Spatrick
68e5dd7070Spatrick bool classifyReturnType(CGFunctionInfo &FI) const override;
69e5dd7070Spatrick
getRecordArgABI(const CXXRecordDecl * RD) const70e5dd7070Spatrick RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
71e5dd7070Spatrick // If C++ prohibits us from making a copy, pass by address.
72e5dd7070Spatrick if (!RD->canPassInRegisters())
73e5dd7070Spatrick return RAA_Indirect;
74e5dd7070Spatrick return RAA_Default;
75e5dd7070Spatrick }
76e5dd7070Spatrick
isThisCompleteObject(GlobalDecl GD) const77e5dd7070Spatrick bool isThisCompleteObject(GlobalDecl GD) const override {
78e5dd7070Spatrick // The Itanium ABI has separate complete-object vs. base-object
79e5dd7070Spatrick // variants of both constructors and destructors.
80e5dd7070Spatrick if (isa<CXXDestructorDecl>(GD.getDecl())) {
81e5dd7070Spatrick switch (GD.getDtorType()) {
82e5dd7070Spatrick case Dtor_Complete:
83e5dd7070Spatrick case Dtor_Deleting:
84e5dd7070Spatrick return true;
85e5dd7070Spatrick
86e5dd7070Spatrick case Dtor_Base:
87e5dd7070Spatrick return false;
88e5dd7070Spatrick
89e5dd7070Spatrick case Dtor_Comdat:
90e5dd7070Spatrick llvm_unreachable("emitting dtor comdat as function?");
91e5dd7070Spatrick }
92e5dd7070Spatrick llvm_unreachable("bad dtor kind");
93e5dd7070Spatrick }
94e5dd7070Spatrick if (isa<CXXConstructorDecl>(GD.getDecl())) {
95e5dd7070Spatrick switch (GD.getCtorType()) {
96e5dd7070Spatrick case Ctor_Complete:
97e5dd7070Spatrick return true;
98e5dd7070Spatrick
99e5dd7070Spatrick case Ctor_Base:
100e5dd7070Spatrick return false;
101e5dd7070Spatrick
102e5dd7070Spatrick case Ctor_CopyingClosure:
103e5dd7070Spatrick case Ctor_DefaultClosure:
104e5dd7070Spatrick llvm_unreachable("closure ctors in Itanium ABI?");
105e5dd7070Spatrick
106e5dd7070Spatrick case Ctor_Comdat:
107e5dd7070Spatrick llvm_unreachable("emitting ctor comdat as function?");
108e5dd7070Spatrick }
109e5dd7070Spatrick llvm_unreachable("bad dtor kind");
110e5dd7070Spatrick }
111e5dd7070Spatrick
112e5dd7070Spatrick // No other kinds.
113e5dd7070Spatrick return false;
114e5dd7070Spatrick }
115e5dd7070Spatrick
116e5dd7070Spatrick bool isZeroInitializable(const MemberPointerType *MPT) override;
117e5dd7070Spatrick
118e5dd7070Spatrick llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
119e5dd7070Spatrick
120e5dd7070Spatrick CGCallee
121e5dd7070Spatrick EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
122e5dd7070Spatrick const Expr *E,
123e5dd7070Spatrick Address This,
124e5dd7070Spatrick llvm::Value *&ThisPtrForCall,
125e5dd7070Spatrick llvm::Value *MemFnPtr,
126e5dd7070Spatrick const MemberPointerType *MPT) override;
127e5dd7070Spatrick
128e5dd7070Spatrick llvm::Value *
129e5dd7070Spatrick EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
130e5dd7070Spatrick Address Base,
131e5dd7070Spatrick llvm::Value *MemPtr,
132e5dd7070Spatrick const MemberPointerType *MPT) override;
133e5dd7070Spatrick
134e5dd7070Spatrick llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
135e5dd7070Spatrick const CastExpr *E,
136e5dd7070Spatrick llvm::Value *Src) override;
137e5dd7070Spatrick llvm::Constant *EmitMemberPointerConversion(const CastExpr *E,
138e5dd7070Spatrick llvm::Constant *Src) override;
139e5dd7070Spatrick
140e5dd7070Spatrick llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;
141e5dd7070Spatrick
142e5dd7070Spatrick llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override;
143e5dd7070Spatrick llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
144e5dd7070Spatrick CharUnits offset) override;
145e5dd7070Spatrick llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override;
146e5dd7070Spatrick llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD,
147e5dd7070Spatrick CharUnits ThisAdjustment);
148e5dd7070Spatrick
149e5dd7070Spatrick llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
150e5dd7070Spatrick llvm::Value *L, llvm::Value *R,
151e5dd7070Spatrick const MemberPointerType *MPT,
152e5dd7070Spatrick bool Inequality) override;
153e5dd7070Spatrick
154e5dd7070Spatrick llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
155e5dd7070Spatrick llvm::Value *Addr,
156e5dd7070Spatrick const MemberPointerType *MPT) override;
157e5dd7070Spatrick
158e5dd7070Spatrick void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
159e5dd7070Spatrick Address Ptr, QualType ElementType,
160e5dd7070Spatrick const CXXDestructorDecl *Dtor) override;
161e5dd7070Spatrick
162e5dd7070Spatrick void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;
163e5dd7070Spatrick void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override;
164e5dd7070Spatrick
165e5dd7070Spatrick void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
166e5dd7070Spatrick
167e5dd7070Spatrick llvm::CallInst *
168e5dd7070Spatrick emitTerminateForUnexpectedException(CodeGenFunction &CGF,
169e5dd7070Spatrick llvm::Value *Exn) override;
170e5dd7070Spatrick
171e5dd7070Spatrick void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD);
172e5dd7070Spatrick llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
173e5dd7070Spatrick CatchTypeInfo
getAddrOfCXXCatchHandlerType(QualType Ty,QualType CatchHandlerType)174e5dd7070Spatrick getAddrOfCXXCatchHandlerType(QualType Ty,
175e5dd7070Spatrick QualType CatchHandlerType) override {
176e5dd7070Spatrick return CatchTypeInfo{getAddrOfRTTIDescriptor(Ty), 0};
177e5dd7070Spatrick }
178e5dd7070Spatrick
179e5dd7070Spatrick bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
180e5dd7070Spatrick void EmitBadTypeidCall(CodeGenFunction &CGF) override;
181e5dd7070Spatrick llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
182e5dd7070Spatrick Address ThisPtr,
183e5dd7070Spatrick llvm::Type *StdTypeInfoPtrTy) override;
184e5dd7070Spatrick
185e5dd7070Spatrick bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
186e5dd7070Spatrick QualType SrcRecordTy) override;
187e5dd7070Spatrick
188e5dd7070Spatrick llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, Address Value,
189e5dd7070Spatrick QualType SrcRecordTy, QualType DestTy,
190e5dd7070Spatrick QualType DestRecordTy,
191e5dd7070Spatrick llvm::BasicBlock *CastEnd) override;
192e5dd7070Spatrick
193e5dd7070Spatrick llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value,
194e5dd7070Spatrick QualType SrcRecordTy,
195e5dd7070Spatrick QualType DestTy) override;
196e5dd7070Spatrick
197e5dd7070Spatrick bool EmitBadCastCall(CodeGenFunction &CGF) override;
198e5dd7070Spatrick
199e5dd7070Spatrick llvm::Value *
200e5dd7070Spatrick GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
201e5dd7070Spatrick const CXXRecordDecl *ClassDecl,
202e5dd7070Spatrick const CXXRecordDecl *BaseClassDecl) override;
203e5dd7070Spatrick
204e5dd7070Spatrick void EmitCXXConstructors(const CXXConstructorDecl *D) override;
205e5dd7070Spatrick
206ec727ea7Spatrick AddedStructorArgCounts
207e5dd7070Spatrick buildStructorSignature(GlobalDecl GD,
208e5dd7070Spatrick SmallVectorImpl<CanQualType> &ArgTys) override;
209e5dd7070Spatrick
useThunkForDtorVariant(const CXXDestructorDecl * Dtor,CXXDtorType DT) const210e5dd7070Spatrick bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
211e5dd7070Spatrick CXXDtorType DT) const override {
212e5dd7070Spatrick // Itanium does not emit any destructor variant as an inline thunk.
213e5dd7070Spatrick // Delegating may occur as an optimization, but all variants are either
214e5dd7070Spatrick // emitted with external linkage or as linkonce if they are inline and used.
215e5dd7070Spatrick return false;
216e5dd7070Spatrick }
217e5dd7070Spatrick
218e5dd7070Spatrick void EmitCXXDestructors(const CXXDestructorDecl *D) override;
219e5dd7070Spatrick
220e5dd7070Spatrick void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
221e5dd7070Spatrick FunctionArgList &Params) override;
222e5dd7070Spatrick
223e5dd7070Spatrick void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;
224e5dd7070Spatrick
225ec727ea7Spatrick AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
226ec727ea7Spatrick const CXXConstructorDecl *D,
227ec727ea7Spatrick CXXCtorType Type,
228ec727ea7Spatrick bool ForVirtualBase,
229ec727ea7Spatrick bool Delegating) override;
230ec727ea7Spatrick
231ec727ea7Spatrick llvm::Value *getCXXDestructorImplicitParam(CodeGenFunction &CGF,
232ec727ea7Spatrick const CXXDestructorDecl *DD,
233ec727ea7Spatrick CXXDtorType Type,
234ec727ea7Spatrick bool ForVirtualBase,
235ec727ea7Spatrick bool Delegating) override;
236e5dd7070Spatrick
237e5dd7070Spatrick void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
238e5dd7070Spatrick CXXDtorType Type, bool ForVirtualBase,
239e5dd7070Spatrick bool Delegating, Address This,
240e5dd7070Spatrick QualType ThisTy) override;
241e5dd7070Spatrick
242e5dd7070Spatrick void emitVTableDefinitions(CodeGenVTables &CGVT,
243e5dd7070Spatrick const CXXRecordDecl *RD) override;
244e5dd7070Spatrick
245e5dd7070Spatrick bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
246e5dd7070Spatrick CodeGenFunction::VPtr Vptr) override;
247e5dd7070Spatrick
doStructorsInitializeVPtrs(const CXXRecordDecl * VTableClass)248e5dd7070Spatrick bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override {
249e5dd7070Spatrick return true;
250e5dd7070Spatrick }
251e5dd7070Spatrick
252e5dd7070Spatrick llvm::Constant *
253e5dd7070Spatrick getVTableAddressPoint(BaseSubobject Base,
254e5dd7070Spatrick const CXXRecordDecl *VTableClass) override;
255e5dd7070Spatrick
256e5dd7070Spatrick llvm::Value *getVTableAddressPointInStructor(
257e5dd7070Spatrick CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
258e5dd7070Spatrick BaseSubobject Base, const CXXRecordDecl *NearestVBase) override;
259e5dd7070Spatrick
260e5dd7070Spatrick llvm::Value *getVTableAddressPointInStructorWithVTT(
261e5dd7070Spatrick CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
262e5dd7070Spatrick BaseSubobject Base, const CXXRecordDecl *NearestVBase);
263e5dd7070Spatrick
264e5dd7070Spatrick llvm::Constant *
265e5dd7070Spatrick getVTableAddressPointForConstExpr(BaseSubobject Base,
266e5dd7070Spatrick const CXXRecordDecl *VTableClass) override;
267e5dd7070Spatrick
268e5dd7070Spatrick llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
269e5dd7070Spatrick CharUnits VPtrOffset) override;
270e5dd7070Spatrick
271e5dd7070Spatrick CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
272e5dd7070Spatrick Address This, llvm::Type *Ty,
273e5dd7070Spatrick SourceLocation Loc) override;
274e5dd7070Spatrick
275e5dd7070Spatrick llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
276e5dd7070Spatrick const CXXDestructorDecl *Dtor,
277e5dd7070Spatrick CXXDtorType DtorType, Address This,
278e5dd7070Spatrick DeleteOrMemberCallExpr E) override;
279e5dd7070Spatrick
280e5dd7070Spatrick void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
281e5dd7070Spatrick
282e5dd7070Spatrick bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;
283e5dd7070Spatrick bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const;
284e5dd7070Spatrick
setThunkLinkage(llvm::Function * Thunk,bool ForVTable,GlobalDecl GD,bool ReturnAdjustment)285e5dd7070Spatrick void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
286e5dd7070Spatrick bool ReturnAdjustment) override {
287e5dd7070Spatrick // Allow inlining of thunks by emitting them with available_externally
288e5dd7070Spatrick // linkage together with vtables when needed.
289e5dd7070Spatrick if (ForVTable && !Thunk->hasLocalLinkage())
290e5dd7070Spatrick Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
291e5dd7070Spatrick CGM.setGVProperties(Thunk, GD);
292e5dd7070Spatrick }
293e5dd7070Spatrick
exportThunk()294e5dd7070Spatrick bool exportThunk() override { return true; }
295e5dd7070Spatrick
296e5dd7070Spatrick llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
297e5dd7070Spatrick const ThisAdjustment &TA) override;
298e5dd7070Spatrick
299e5dd7070Spatrick llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
300e5dd7070Spatrick const ReturnAdjustment &RA) override;
301e5dd7070Spatrick
getSrcArgforCopyCtor(const CXXConstructorDecl *,FunctionArgList & Args) const302e5dd7070Spatrick size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
303e5dd7070Spatrick FunctionArgList &Args) const override {
304e5dd7070Spatrick assert(!Args.empty() && "expected the arglist to not be empty!");
305e5dd7070Spatrick return Args.size() - 1;
306e5dd7070Spatrick }
307e5dd7070Spatrick
GetPureVirtualCallName()308e5dd7070Spatrick StringRef GetPureVirtualCallName() override { return "__cxa_pure_virtual"; }
GetDeletedVirtualCallName()309e5dd7070Spatrick StringRef GetDeletedVirtualCallName() override
310e5dd7070Spatrick { return "__cxa_deleted_virtual"; }
311e5dd7070Spatrick
312e5dd7070Spatrick CharUnits getArrayCookieSizeImpl(QualType elementType) override;
313e5dd7070Spatrick Address InitializeArrayCookie(CodeGenFunction &CGF,
314e5dd7070Spatrick Address NewPtr,
315e5dd7070Spatrick llvm::Value *NumElements,
316e5dd7070Spatrick const CXXNewExpr *expr,
317e5dd7070Spatrick QualType ElementType) override;
318e5dd7070Spatrick llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
319e5dd7070Spatrick Address allocPtr,
320e5dd7070Spatrick CharUnits cookieSize) override;
321e5dd7070Spatrick
322e5dd7070Spatrick void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
323e5dd7070Spatrick llvm::GlobalVariable *DeclPtr,
324e5dd7070Spatrick bool PerformInit) override;
325e5dd7070Spatrick void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
326e5dd7070Spatrick llvm::FunctionCallee dtor,
327e5dd7070Spatrick llvm::Constant *addr) override;
328e5dd7070Spatrick
329e5dd7070Spatrick llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD,
330e5dd7070Spatrick llvm::Value *Val);
331e5dd7070Spatrick void EmitThreadLocalInitFuncs(
332e5dd7070Spatrick CodeGenModule &CGM,
333e5dd7070Spatrick ArrayRef<const VarDecl *> CXXThreadLocals,
334e5dd7070Spatrick ArrayRef<llvm::Function *> CXXThreadLocalInits,
335e5dd7070Spatrick ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;
336e5dd7070Spatrick
usesThreadWrapperFunction(const VarDecl * VD) const337e5dd7070Spatrick bool usesThreadWrapperFunction(const VarDecl *VD) const override {
338e5dd7070Spatrick return !isEmittedWithConstantInitializer(VD) ||
339*12c85518Srobert mayNeedDestruction(VD);
340e5dd7070Spatrick }
341e5dd7070Spatrick LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
342e5dd7070Spatrick QualType LValType) override;
343e5dd7070Spatrick
344e5dd7070Spatrick bool NeedsVTTParameter(GlobalDecl GD) override;
345e5dd7070Spatrick
346e5dd7070Spatrick /**************************** RTTI Uniqueness ******************************/
347e5dd7070Spatrick
348e5dd7070Spatrick protected:
349e5dd7070Spatrick /// Returns true if the ABI requires RTTI type_info objects to be unique
350e5dd7070Spatrick /// across a program.
shouldRTTIBeUnique() const351e5dd7070Spatrick virtual bool shouldRTTIBeUnique() const { return true; }
352e5dd7070Spatrick
353e5dd7070Spatrick public:
354e5dd7070Spatrick /// What sort of unique-RTTI behavior should we use?
355e5dd7070Spatrick enum RTTIUniquenessKind {
356e5dd7070Spatrick /// We are guaranteeing, or need to guarantee, that the RTTI string
357e5dd7070Spatrick /// is unique.
358e5dd7070Spatrick RUK_Unique,
359e5dd7070Spatrick
360e5dd7070Spatrick /// We are not guaranteeing uniqueness for the RTTI string, so we
361e5dd7070Spatrick /// can demote to hidden visibility but must use string comparisons.
362e5dd7070Spatrick RUK_NonUniqueHidden,
363e5dd7070Spatrick
364e5dd7070Spatrick /// We are not guaranteeing uniqueness for the RTTI string, so we
365e5dd7070Spatrick /// have to use string comparisons, but we also have to emit it with
366e5dd7070Spatrick /// non-hidden visibility.
367e5dd7070Spatrick RUK_NonUniqueVisible
368e5dd7070Spatrick };
369e5dd7070Spatrick
370e5dd7070Spatrick /// Return the required visibility status for the given type and linkage in
371e5dd7070Spatrick /// the current ABI.
372e5dd7070Spatrick RTTIUniquenessKind
373e5dd7070Spatrick classifyRTTIUniqueness(QualType CanTy,
374e5dd7070Spatrick llvm::GlobalValue::LinkageTypes Linkage) const;
375e5dd7070Spatrick friend class ItaniumRTTIBuilder;
376e5dd7070Spatrick
377e5dd7070Spatrick void emitCXXStructor(GlobalDecl GD) override;
378e5dd7070Spatrick
379e5dd7070Spatrick std::pair<llvm::Value *, const CXXRecordDecl *>
380e5dd7070Spatrick LoadVTablePtr(CodeGenFunction &CGF, Address This,
381e5dd7070Spatrick const CXXRecordDecl *RD) override;
382e5dd7070Spatrick
383e5dd7070Spatrick private:
hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl * RD) const384e5dd7070Spatrick bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
385e5dd7070Spatrick const auto &VtableLayout =
386e5dd7070Spatrick CGM.getItaniumVTableContext().getVTableLayout(RD);
387e5dd7070Spatrick
388e5dd7070Spatrick for (const auto &VtableComponent : VtableLayout.vtable_components()) {
389e5dd7070Spatrick // Skip empty slot.
390e5dd7070Spatrick if (!VtableComponent.isUsedFunctionPointerKind())
391e5dd7070Spatrick continue;
392e5dd7070Spatrick
393e5dd7070Spatrick const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
394e5dd7070Spatrick if (!Method->getCanonicalDecl()->isInlined())
395e5dd7070Spatrick continue;
396e5dd7070Spatrick
397e5dd7070Spatrick StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
398e5dd7070Spatrick auto *Entry = CGM.GetGlobalValue(Name);
399e5dd7070Spatrick // This checks if virtual inline function has already been emitted.
400e5dd7070Spatrick // Note that it is possible that this inline function would be emitted
401e5dd7070Spatrick // after trying to emit vtable speculatively. Because of this we do
402e5dd7070Spatrick // an extra pass after emitting all deferred vtables to find and emit
403e5dd7070Spatrick // these vtables opportunistically.
404e5dd7070Spatrick if (!Entry || Entry->isDeclaration())
405e5dd7070Spatrick return true;
406e5dd7070Spatrick }
407e5dd7070Spatrick return false;
408e5dd7070Spatrick }
409e5dd7070Spatrick
isVTableHidden(const CXXRecordDecl * RD) const410e5dd7070Spatrick bool isVTableHidden(const CXXRecordDecl *RD) const {
411e5dd7070Spatrick const auto &VtableLayout =
412e5dd7070Spatrick CGM.getItaniumVTableContext().getVTableLayout(RD);
413e5dd7070Spatrick
414e5dd7070Spatrick for (const auto &VtableComponent : VtableLayout.vtable_components()) {
415e5dd7070Spatrick if (VtableComponent.isRTTIKind()) {
416e5dd7070Spatrick const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();
417e5dd7070Spatrick if (RTTIDecl->getVisibility() == Visibility::HiddenVisibility)
418e5dd7070Spatrick return true;
419e5dd7070Spatrick } else if (VtableComponent.isUsedFunctionPointerKind()) {
420e5dd7070Spatrick const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
421e5dd7070Spatrick if (Method->getVisibility() == Visibility::HiddenVisibility &&
422e5dd7070Spatrick !Method->isDefined())
423e5dd7070Spatrick return true;
424e5dd7070Spatrick }
425e5dd7070Spatrick }
426e5dd7070Spatrick return false;
427e5dd7070Spatrick }
428e5dd7070Spatrick };
429e5dd7070Spatrick
430e5dd7070Spatrick class ARMCXXABI : public ItaniumCXXABI {
431e5dd7070Spatrick public:
ARMCXXABI(CodeGen::CodeGenModule & CGM)432e5dd7070Spatrick ARMCXXABI(CodeGen::CodeGenModule &CGM) :
433e5dd7070Spatrick ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
434e5dd7070Spatrick /*UseARMGuardVarABI=*/true) {}
435e5dd7070Spatrick
constructorsAndDestructorsReturnThis() const436*12c85518Srobert bool constructorsAndDestructorsReturnThis() const override { return true; }
437e5dd7070Spatrick
438e5dd7070Spatrick void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV,
439e5dd7070Spatrick QualType ResTy) override;
440e5dd7070Spatrick
441e5dd7070Spatrick CharUnits getArrayCookieSizeImpl(QualType elementType) override;
442e5dd7070Spatrick Address InitializeArrayCookie(CodeGenFunction &CGF,
443e5dd7070Spatrick Address NewPtr,
444e5dd7070Spatrick llvm::Value *NumElements,
445e5dd7070Spatrick const CXXNewExpr *expr,
446e5dd7070Spatrick QualType ElementType) override;
447e5dd7070Spatrick llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr,
448e5dd7070Spatrick CharUnits cookieSize) override;
449e5dd7070Spatrick };
450e5dd7070Spatrick
451a9ac8606Spatrick class AppleARM64CXXABI : public ARMCXXABI {
452e5dd7070Spatrick public:
AppleARM64CXXABI(CodeGen::CodeGenModule & CGM)453a9ac8606Spatrick AppleARM64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {
454e5dd7070Spatrick Use32BitVTableOffsetABI = true;
455e5dd7070Spatrick }
456e5dd7070Spatrick
457e5dd7070Spatrick // ARM64 libraries are prepared for non-unique RTTI.
shouldRTTIBeUnique() const458e5dd7070Spatrick bool shouldRTTIBeUnique() const override { return false; }
459e5dd7070Spatrick };
460e5dd7070Spatrick
461e5dd7070Spatrick class FuchsiaCXXABI final : public ItaniumCXXABI {
462e5dd7070Spatrick public:
FuchsiaCXXABI(CodeGen::CodeGenModule & CGM)463e5dd7070Spatrick explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM)
464e5dd7070Spatrick : ItaniumCXXABI(CGM) {}
465e5dd7070Spatrick
466e5dd7070Spatrick private:
constructorsAndDestructorsReturnThis() const467*12c85518Srobert bool constructorsAndDestructorsReturnThis() const override { return true; }
468e5dd7070Spatrick };
469e5dd7070Spatrick
470e5dd7070Spatrick class WebAssemblyCXXABI final : public ItaniumCXXABI {
471e5dd7070Spatrick public:
WebAssemblyCXXABI(CodeGen::CodeGenModule & CGM)472e5dd7070Spatrick explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM)
473e5dd7070Spatrick : ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
474e5dd7070Spatrick /*UseARMGuardVarABI=*/true) {}
475e5dd7070Spatrick void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
476a9ac8606Spatrick llvm::CallInst *
477a9ac8606Spatrick emitTerminateForUnexpectedException(CodeGenFunction &CGF,
478a9ac8606Spatrick llvm::Value *Exn) override;
479e5dd7070Spatrick
480e5dd7070Spatrick private:
constructorsAndDestructorsReturnThis() const481*12c85518Srobert bool constructorsAndDestructorsReturnThis() const override { return true; }
canCallMismatchedFunctionType() const482e5dd7070Spatrick bool canCallMismatchedFunctionType() const override { return false; }
483e5dd7070Spatrick };
484ec727ea7Spatrick
485ec727ea7Spatrick class XLCXXABI final : public ItaniumCXXABI {
486ec727ea7Spatrick public:
XLCXXABI(CodeGen::CodeGenModule & CGM)487ec727ea7Spatrick explicit XLCXXABI(CodeGen::CodeGenModule &CGM)
488ec727ea7Spatrick : ItaniumCXXABI(CGM) {}
489ec727ea7Spatrick
490ec727ea7Spatrick void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
491ec727ea7Spatrick llvm::FunctionCallee dtor,
492ec727ea7Spatrick llvm::Constant *addr) override;
493ec727ea7Spatrick
useSinitAndSterm() const494ec727ea7Spatrick bool useSinitAndSterm() const override { return true; }
495ec727ea7Spatrick
496ec727ea7Spatrick private:
497ec727ea7Spatrick void emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
498ec727ea7Spatrick llvm::Constant *addr);
499ec727ea7Spatrick };
500e5dd7070Spatrick }
501e5dd7070Spatrick
CreateItaniumCXXABI(CodeGenModule & CGM)502e5dd7070Spatrick CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
503a9ac8606Spatrick switch (CGM.getContext().getCXXABIKind()) {
504e5dd7070Spatrick // For IR-generation purposes, there's no significant difference
505e5dd7070Spatrick // between the ARM and iOS ABIs.
506e5dd7070Spatrick case TargetCXXABI::GenericARM:
507e5dd7070Spatrick case TargetCXXABI::iOS:
508e5dd7070Spatrick case TargetCXXABI::WatchOS:
509e5dd7070Spatrick return new ARMCXXABI(CGM);
510e5dd7070Spatrick
511a9ac8606Spatrick case TargetCXXABI::AppleARM64:
512a9ac8606Spatrick return new AppleARM64CXXABI(CGM);
513e5dd7070Spatrick
514e5dd7070Spatrick case TargetCXXABI::Fuchsia:
515e5dd7070Spatrick return new FuchsiaCXXABI(CGM);
516e5dd7070Spatrick
517e5dd7070Spatrick // Note that AArch64 uses the generic ItaniumCXXABI class since it doesn't
518e5dd7070Spatrick // include the other 32-bit ARM oddities: constructor/destructor return values
519e5dd7070Spatrick // and array cookies.
520e5dd7070Spatrick case TargetCXXABI::GenericAArch64:
521e5dd7070Spatrick return new ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
522e5dd7070Spatrick /*UseARMGuardVarABI=*/true);
523e5dd7070Spatrick
524e5dd7070Spatrick case TargetCXXABI::GenericMIPS:
525e5dd7070Spatrick return new ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true);
526e5dd7070Spatrick
527e5dd7070Spatrick case TargetCXXABI::WebAssembly:
528e5dd7070Spatrick return new WebAssemblyCXXABI(CGM);
529e5dd7070Spatrick
530ec727ea7Spatrick case TargetCXXABI::XL:
531ec727ea7Spatrick return new XLCXXABI(CGM);
532ec727ea7Spatrick
533e5dd7070Spatrick case TargetCXXABI::GenericItanium:
534e5dd7070Spatrick if (CGM.getContext().getTargetInfo().getTriple().getArch()
535e5dd7070Spatrick == llvm::Triple::le32) {
536e5dd7070Spatrick // For PNaCl, use ARM-style method pointers so that PNaCl code
537e5dd7070Spatrick // does not assume anything about the alignment of function
538e5dd7070Spatrick // pointers.
539e5dd7070Spatrick return new ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true);
540e5dd7070Spatrick }
541e5dd7070Spatrick return new ItaniumCXXABI(CGM);
542e5dd7070Spatrick
543e5dd7070Spatrick case TargetCXXABI::Microsoft:
544e5dd7070Spatrick llvm_unreachable("Microsoft ABI is not Itanium-based");
545e5dd7070Spatrick }
546e5dd7070Spatrick llvm_unreachable("bad ABI kind");
547e5dd7070Spatrick }
548e5dd7070Spatrick
549e5dd7070Spatrick llvm::Type *
ConvertMemberPointerType(const MemberPointerType * MPT)550e5dd7070Spatrick ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
551e5dd7070Spatrick if (MPT->isMemberDataPointer())
552e5dd7070Spatrick return CGM.PtrDiffTy;
553e5dd7070Spatrick return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);
554e5dd7070Spatrick }
555e5dd7070Spatrick
556e5dd7070Spatrick /// In the Itanium and ARM ABIs, method pointers have the form:
557e5dd7070Spatrick /// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr;
558e5dd7070Spatrick ///
559e5dd7070Spatrick /// In the Itanium ABI:
560e5dd7070Spatrick /// - method pointers are virtual if (memptr.ptr & 1) is nonzero
561e5dd7070Spatrick /// - the this-adjustment is (memptr.adj)
562e5dd7070Spatrick /// - the virtual offset is (memptr.ptr - 1)
563e5dd7070Spatrick ///
564e5dd7070Spatrick /// In the ARM ABI:
565e5dd7070Spatrick /// - method pointers are virtual if (memptr.adj & 1) is nonzero
566e5dd7070Spatrick /// - the this-adjustment is (memptr.adj >> 1)
567e5dd7070Spatrick /// - the virtual offset is (memptr.ptr)
568e5dd7070Spatrick /// ARM uses 'adj' for the virtual flag because Thumb functions
569e5dd7070Spatrick /// may be only single-byte aligned.
570e5dd7070Spatrick ///
571e5dd7070Spatrick /// If the member is virtual, the adjusted 'this' pointer points
572e5dd7070Spatrick /// to a vtable pointer from which the virtual offset is applied.
573e5dd7070Spatrick ///
574e5dd7070Spatrick /// If the member is non-virtual, memptr.ptr is the address of
575e5dd7070Spatrick /// the function to call.
EmitLoadOfMemberFunctionPointer(CodeGenFunction & CGF,const Expr * E,Address ThisAddr,llvm::Value * & ThisPtrForCall,llvm::Value * MemFnPtr,const MemberPointerType * MPT)576e5dd7070Spatrick CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
577e5dd7070Spatrick CodeGenFunction &CGF, const Expr *E, Address ThisAddr,
578e5dd7070Spatrick llvm::Value *&ThisPtrForCall,
579e5dd7070Spatrick llvm::Value *MemFnPtr, const MemberPointerType *MPT) {
580e5dd7070Spatrick CGBuilderTy &Builder = CGF.Builder;
581e5dd7070Spatrick
582e5dd7070Spatrick const FunctionProtoType *FPT =
583e5dd7070Spatrick MPT->getPointeeType()->getAs<FunctionProtoType>();
584e5dd7070Spatrick auto *RD =
585e5dd7070Spatrick cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl());
586e5dd7070Spatrick
587e5dd7070Spatrick llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
588e5dd7070Spatrick CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr));
589e5dd7070Spatrick
590e5dd7070Spatrick llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
591e5dd7070Spatrick
592e5dd7070Spatrick llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual");
593e5dd7070Spatrick llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");
594e5dd7070Spatrick llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");
595e5dd7070Spatrick
596e5dd7070Spatrick // Extract memptr.adj, which is in the second field.
597e5dd7070Spatrick llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj");
598e5dd7070Spatrick
599e5dd7070Spatrick // Compute the true adjustment.
600e5dd7070Spatrick llvm::Value *Adj = RawAdj;
601e5dd7070Spatrick if (UseARMMethodPtrABI)
602e5dd7070Spatrick Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
603e5dd7070Spatrick
604e5dd7070Spatrick // Apply the adjustment and cast back to the original struct type
605e5dd7070Spatrick // for consistency.
606e5dd7070Spatrick llvm::Value *This = ThisAddr.getPointer();
607e5dd7070Spatrick llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
608a9ac8606Spatrick Ptr = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), Ptr, Adj);
609e5dd7070Spatrick This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
610e5dd7070Spatrick ThisPtrForCall = This;
611e5dd7070Spatrick
612e5dd7070Spatrick // Load the function pointer.
613e5dd7070Spatrick llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");
614e5dd7070Spatrick
615e5dd7070Spatrick // If the LSB in the function pointer is 1, the function pointer points to
616e5dd7070Spatrick // a virtual function.
617e5dd7070Spatrick llvm::Value *IsVirtual;
618e5dd7070Spatrick if (UseARMMethodPtrABI)
619e5dd7070Spatrick IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
620e5dd7070Spatrick else
621e5dd7070Spatrick IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
622e5dd7070Spatrick IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual");
623e5dd7070Spatrick Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
624e5dd7070Spatrick
625e5dd7070Spatrick // In the virtual path, the adjustment left 'This' pointing to the
626e5dd7070Spatrick // vtable of the correct base subobject. The "function pointer" is an
627e5dd7070Spatrick // offset within the vtable (+1 for the virtual flag on non-ARM).
628e5dd7070Spatrick CGF.EmitBlock(FnVirtual);
629e5dd7070Spatrick
630e5dd7070Spatrick // Cast the adjusted this to a pointer to vtable pointer and load.
631e5dd7070Spatrick llvm::Type *VTableTy = Builder.getInt8PtrTy();
632e5dd7070Spatrick CharUnits VTablePtrAlign =
633e5dd7070Spatrick CGF.CGM.getDynamicOffsetAlignment(ThisAddr.getAlignment(), RD,
634e5dd7070Spatrick CGF.getPointerAlign());
635*12c85518Srobert llvm::Value *VTable = CGF.GetVTablePtr(
636*12c85518Srobert Address(This, ThisAddr.getElementType(), VTablePtrAlign), VTableTy, RD);
637e5dd7070Spatrick
638e5dd7070Spatrick // Apply the offset.
639e5dd7070Spatrick // On ARM64, to reserve extra space in virtual member function pointers,
640e5dd7070Spatrick // we only pay attention to the low 32 bits of the offset.
641e5dd7070Spatrick llvm::Value *VTableOffset = FnAsInt;
642e5dd7070Spatrick if (!UseARMMethodPtrABI)
643e5dd7070Spatrick VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
644e5dd7070Spatrick if (Use32BitVTableOffsetABI) {
645e5dd7070Spatrick VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty);
646e5dd7070Spatrick VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
647e5dd7070Spatrick }
648e5dd7070Spatrick
649e5dd7070Spatrick // Check the address of the function pointer if CFI on member function
650e5dd7070Spatrick // pointers is enabled.
651e5dd7070Spatrick llvm::Constant *CheckSourceLocation;
652e5dd7070Spatrick llvm::Constant *CheckTypeDesc;
653e5dd7070Spatrick bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) &&
654e5dd7070Spatrick CGM.HasHiddenLTOVisibility(RD);
655e5dd7070Spatrick bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
656e5dd7070Spatrick CGM.HasHiddenLTOVisibility(RD);
657ec727ea7Spatrick bool ShouldEmitWPDInfo =
658ec727ea7Spatrick CGM.getCodeGenOpts().WholeProgramVTables &&
659*12c85518Srobert // Don't insert type tests if we are forcing public visibility.
660*12c85518Srobert !CGM.AlwaysHasLTOVisibilityPublic(RD);
661e5dd7070Spatrick llvm::Value *VirtualFn = nullptr;
662e5dd7070Spatrick
663e5dd7070Spatrick {
664e5dd7070Spatrick CodeGenFunction::SanitizerScope SanScope(&CGF);
665e5dd7070Spatrick llvm::Value *TypeId = nullptr;
666e5dd7070Spatrick llvm::Value *CheckResult = nullptr;
667e5dd7070Spatrick
668ec727ea7Spatrick if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
669ec727ea7Spatrick // If doing CFI, VFE or WPD, we will need the metadata node to check
670ec727ea7Spatrick // against.
671e5dd7070Spatrick llvm::Metadata *MD =
672e5dd7070Spatrick CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
673e5dd7070Spatrick TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
674e5dd7070Spatrick }
675e5dd7070Spatrick
676ec727ea7Spatrick if (ShouldEmitVFEInfo) {
677a9ac8606Spatrick llvm::Value *VFPAddr =
678a9ac8606Spatrick Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
679e5dd7070Spatrick
680e5dd7070Spatrick // If doing VFE, load from the vtable with a type.checked.load intrinsic
681e5dd7070Spatrick // call. Note that we use the GEP to calculate the address to load from
682e5dd7070Spatrick // and pass 0 as the offset to the intrinsic. This is because every
683e5dd7070Spatrick // vtable slot of the correct type is marked with matching metadata, and
684e5dd7070Spatrick // we know that the load must be from one of these slots.
685e5dd7070Spatrick llvm::Value *CheckedLoad = Builder.CreateCall(
686e5dd7070Spatrick CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
687e5dd7070Spatrick {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
688e5dd7070Spatrick CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
689e5dd7070Spatrick VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
690e5dd7070Spatrick VirtualFn = Builder.CreateBitCast(VirtualFn, FTy->getPointerTo(),
691e5dd7070Spatrick "memptr.virtualfn");
692e5dd7070Spatrick } else {
693e5dd7070Spatrick // When not doing VFE, emit a normal load, as it allows more
694e5dd7070Spatrick // optimisations than type.checked.load.
695ec727ea7Spatrick if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
696a9ac8606Spatrick llvm::Value *VFPAddr =
697a9ac8606Spatrick Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
698*12c85518Srobert llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
699*12c85518Srobert ? llvm::Intrinsic::type_test
700*12c85518Srobert : llvm::Intrinsic::public_type_test;
701*12c85518Srobert
702e5dd7070Spatrick CheckResult = Builder.CreateCall(
703*12c85518Srobert CGM.getIntrinsic(IID),
704e5dd7070Spatrick {Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId});
705e5dd7070Spatrick }
706ec727ea7Spatrick
707ec727ea7Spatrick if (CGM.getItaniumVTableContext().isRelativeLayout()) {
708ec727ea7Spatrick VirtualFn = CGF.Builder.CreateCall(
709ec727ea7Spatrick CGM.getIntrinsic(llvm::Intrinsic::load_relative,
710ec727ea7Spatrick {VTableOffset->getType()}),
711ec727ea7Spatrick {VTable, VTableOffset});
712ec727ea7Spatrick VirtualFn = CGF.Builder.CreateBitCast(VirtualFn, FTy->getPointerTo());
713ec727ea7Spatrick } else {
714a9ac8606Spatrick llvm::Value *VFPAddr =
715a9ac8606Spatrick CGF.Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
716ec727ea7Spatrick VFPAddr = CGF.Builder.CreateBitCast(
717ec727ea7Spatrick VFPAddr, FTy->getPointerTo()->getPointerTo());
718ec727ea7Spatrick VirtualFn = CGF.Builder.CreateAlignedLoad(
719a9ac8606Spatrick FTy->getPointerTo(), VFPAddr, CGF.getPointerAlign(),
720a9ac8606Spatrick "memptr.virtualfn");
721ec727ea7Spatrick }
722e5dd7070Spatrick }
723e5dd7070Spatrick assert(VirtualFn && "Virtual fuction pointer not created!");
724ec727ea7Spatrick assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
725ec727ea7Spatrick CheckResult) &&
726e5dd7070Spatrick "Check result required but not created!");
727e5dd7070Spatrick
728e5dd7070Spatrick if (ShouldEmitCFICheck) {
729e5dd7070Spatrick // If doing CFI, emit the check.
730e5dd7070Spatrick CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getBeginLoc());
731e5dd7070Spatrick CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0));
732e5dd7070Spatrick llvm::Constant *StaticData[] = {
733e5dd7070Spatrick llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall),
734e5dd7070Spatrick CheckSourceLocation,
735e5dd7070Spatrick CheckTypeDesc,
736e5dd7070Spatrick };
737e5dd7070Spatrick
738e5dd7070Spatrick if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
739a9ac8606Spatrick CGF.EmitTrapCheck(CheckResult, SanitizerHandler::CFICheckFail);
740e5dd7070Spatrick } else {
741e5dd7070Spatrick llvm::Value *AllVtables = llvm::MetadataAsValue::get(
742e5dd7070Spatrick CGM.getLLVMContext(),
743e5dd7070Spatrick llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
744e5dd7070Spatrick llvm::Value *ValidVtable = Builder.CreateCall(
745e5dd7070Spatrick CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
746e5dd7070Spatrick CGF.EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIMFCall),
747e5dd7070Spatrick SanitizerHandler::CFICheckFail, StaticData,
748e5dd7070Spatrick {VTable, ValidVtable});
749e5dd7070Spatrick }
750e5dd7070Spatrick
751e5dd7070Spatrick FnVirtual = Builder.GetInsertBlock();
752e5dd7070Spatrick }
753e5dd7070Spatrick } // End of sanitizer scope
754e5dd7070Spatrick
755e5dd7070Spatrick CGF.EmitBranch(FnEnd);
756e5dd7070Spatrick
757e5dd7070Spatrick // In the non-virtual path, the function pointer is actually a
758e5dd7070Spatrick // function pointer.
759e5dd7070Spatrick CGF.EmitBlock(FnNonVirtual);
760e5dd7070Spatrick llvm::Value *NonVirtualFn =
761e5dd7070Spatrick Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn");
762e5dd7070Spatrick
763e5dd7070Spatrick // Check the function pointer if CFI on member function pointers is enabled.
764e5dd7070Spatrick if (ShouldEmitCFICheck) {
765e5dd7070Spatrick CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
766e5dd7070Spatrick if (RD->hasDefinition()) {
767e5dd7070Spatrick CodeGenFunction::SanitizerScope SanScope(&CGF);
768e5dd7070Spatrick
769e5dd7070Spatrick llvm::Constant *StaticData[] = {
770e5dd7070Spatrick llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_NVMFCall),
771e5dd7070Spatrick CheckSourceLocation,
772e5dd7070Spatrick CheckTypeDesc,
773e5dd7070Spatrick };
774e5dd7070Spatrick
775e5dd7070Spatrick llvm::Value *Bit = Builder.getFalse();
776e5dd7070Spatrick llvm::Value *CastedNonVirtualFn =
777e5dd7070Spatrick Builder.CreateBitCast(NonVirtualFn, CGF.Int8PtrTy);
778e5dd7070Spatrick for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {
779e5dd7070Spatrick llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
780e5dd7070Spatrick getContext().getMemberPointerType(
781e5dd7070Spatrick MPT->getPointeeType(),
782e5dd7070Spatrick getContext().getRecordType(Base).getTypePtr()));
783e5dd7070Spatrick llvm::Value *TypeId =
784e5dd7070Spatrick llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
785e5dd7070Spatrick
786e5dd7070Spatrick llvm::Value *TypeTest =
787e5dd7070Spatrick Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
788e5dd7070Spatrick {CastedNonVirtualFn, TypeId});
789e5dd7070Spatrick Bit = Builder.CreateOr(Bit, TypeTest);
790e5dd7070Spatrick }
791e5dd7070Spatrick
792e5dd7070Spatrick CGF.EmitCheck(std::make_pair(Bit, SanitizerKind::CFIMFCall),
793e5dd7070Spatrick SanitizerHandler::CFICheckFail, StaticData,
794e5dd7070Spatrick {CastedNonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)});
795e5dd7070Spatrick
796e5dd7070Spatrick FnNonVirtual = Builder.GetInsertBlock();
797e5dd7070Spatrick }
798e5dd7070Spatrick }
799e5dd7070Spatrick
800e5dd7070Spatrick // We're done.
801e5dd7070Spatrick CGF.EmitBlock(FnEnd);
802e5dd7070Spatrick llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2);
803e5dd7070Spatrick CalleePtr->addIncoming(VirtualFn, FnVirtual);
804e5dd7070Spatrick CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
805e5dd7070Spatrick
806e5dd7070Spatrick CGCallee Callee(FPT, CalleePtr);
807e5dd7070Spatrick return Callee;
808e5dd7070Spatrick }
809e5dd7070Spatrick
810e5dd7070Spatrick /// Compute an l-value by applying the given pointer-to-member to a
811e5dd7070Spatrick /// base object.
EmitMemberDataPointerAddress(CodeGenFunction & CGF,const Expr * E,Address Base,llvm::Value * MemPtr,const MemberPointerType * MPT)812e5dd7070Spatrick llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
813e5dd7070Spatrick CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr,
814e5dd7070Spatrick const MemberPointerType *MPT) {
815e5dd7070Spatrick assert(MemPtr->getType() == CGM.PtrDiffTy);
816e5dd7070Spatrick
817e5dd7070Spatrick CGBuilderTy &Builder = CGF.Builder;
818e5dd7070Spatrick
819e5dd7070Spatrick // Cast to char*.
820e5dd7070Spatrick Base = Builder.CreateElementBitCast(Base, CGF.Int8Ty);
821e5dd7070Spatrick
822e5dd7070Spatrick // Apply the offset, which we assume is non-null.
823a9ac8606Spatrick llvm::Value *Addr = Builder.CreateInBoundsGEP(
824a9ac8606Spatrick Base.getElementType(), Base.getPointer(), MemPtr, "memptr.offset");
825e5dd7070Spatrick
826e5dd7070Spatrick // Cast the address to the appropriate pointer type, adopting the
827e5dd7070Spatrick // address space of the base pointer.
828e5dd7070Spatrick llvm::Type *PType = CGF.ConvertTypeForMem(MPT->getPointeeType())
829e5dd7070Spatrick ->getPointerTo(Base.getAddressSpace());
830e5dd7070Spatrick return Builder.CreateBitCast(Addr, PType);
831e5dd7070Spatrick }
832e5dd7070Spatrick
833e5dd7070Spatrick /// Perform a bitcast, derived-to-base, or base-to-derived member pointer
834e5dd7070Spatrick /// conversion.
835e5dd7070Spatrick ///
836e5dd7070Spatrick /// Bitcast conversions are always a no-op under Itanium.
837e5dd7070Spatrick ///
838e5dd7070Spatrick /// Obligatory offset/adjustment diagram:
839e5dd7070Spatrick /// <-- offset --> <-- adjustment -->
840e5dd7070Spatrick /// |--------------------------|----------------------|--------------------|
841e5dd7070Spatrick /// ^Derived address point ^Base address point ^Member address point
842e5dd7070Spatrick ///
843e5dd7070Spatrick /// So when converting a base member pointer to a derived member pointer,
844e5dd7070Spatrick /// we add the offset to the adjustment because the address point has
845e5dd7070Spatrick /// decreased; and conversely, when converting a derived MP to a base MP
846e5dd7070Spatrick /// we subtract the offset from the adjustment because the address point
847e5dd7070Spatrick /// has increased.
848e5dd7070Spatrick ///
849e5dd7070Spatrick /// The standard forbids (at compile time) conversion to and from
850e5dd7070Spatrick /// virtual bases, which is why we don't have to consider them here.
851e5dd7070Spatrick ///
852e5dd7070Spatrick /// The standard forbids (at run time) casting a derived MP to a base
853e5dd7070Spatrick /// MP when the derived MP does not point to a member of the base.
854e5dd7070Spatrick /// This is why -1 is a reasonable choice for null data member
855e5dd7070Spatrick /// pointers.
856e5dd7070Spatrick llvm::Value *
EmitMemberPointerConversion(CodeGenFunction & CGF,const CastExpr * E,llvm::Value * src)857e5dd7070Spatrick ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
858e5dd7070Spatrick const CastExpr *E,
859e5dd7070Spatrick llvm::Value *src) {
860e5dd7070Spatrick assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
861e5dd7070Spatrick E->getCastKind() == CK_BaseToDerivedMemberPointer ||
862e5dd7070Spatrick E->getCastKind() == CK_ReinterpretMemberPointer);
863e5dd7070Spatrick
864e5dd7070Spatrick // Under Itanium, reinterprets don't require any additional processing.
865e5dd7070Spatrick if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
866e5dd7070Spatrick
867e5dd7070Spatrick // Use constant emission if we can.
868e5dd7070Spatrick if (isa<llvm::Constant>(src))
869e5dd7070Spatrick return EmitMemberPointerConversion(E, cast<llvm::Constant>(src));
870e5dd7070Spatrick
871e5dd7070Spatrick llvm::Constant *adj = getMemberPointerAdjustment(E);
872e5dd7070Spatrick if (!adj) return src;
873e5dd7070Spatrick
874e5dd7070Spatrick CGBuilderTy &Builder = CGF.Builder;
875e5dd7070Spatrick bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
876e5dd7070Spatrick
877e5dd7070Spatrick const MemberPointerType *destTy =
878e5dd7070Spatrick E->getType()->castAs<MemberPointerType>();
879e5dd7070Spatrick
880e5dd7070Spatrick // For member data pointers, this is just a matter of adding the
881e5dd7070Spatrick // offset if the source is non-null.
882e5dd7070Spatrick if (destTy->isMemberDataPointer()) {
883e5dd7070Spatrick llvm::Value *dst;
884e5dd7070Spatrick if (isDerivedToBase)
885e5dd7070Spatrick dst = Builder.CreateNSWSub(src, adj, "adj");
886e5dd7070Spatrick else
887e5dd7070Spatrick dst = Builder.CreateNSWAdd(src, adj, "adj");
888e5dd7070Spatrick
889e5dd7070Spatrick // Null check.
890e5dd7070Spatrick llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType());
891e5dd7070Spatrick llvm::Value *isNull = Builder.CreateICmpEQ(src, null, "memptr.isnull");
892e5dd7070Spatrick return Builder.CreateSelect(isNull, src, dst);
893e5dd7070Spatrick }
894e5dd7070Spatrick
895e5dd7070Spatrick // The this-adjustment is left-shifted by 1 on ARM.
896e5dd7070Spatrick if (UseARMMethodPtrABI) {
897e5dd7070Spatrick uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
898e5dd7070Spatrick offset <<= 1;
899e5dd7070Spatrick adj = llvm::ConstantInt::get(adj->getType(), offset);
900e5dd7070Spatrick }
901e5dd7070Spatrick
902e5dd7070Spatrick llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1, "src.adj");
903e5dd7070Spatrick llvm::Value *dstAdj;
904e5dd7070Spatrick if (isDerivedToBase)
905e5dd7070Spatrick dstAdj = Builder.CreateNSWSub(srcAdj, adj, "adj");
906e5dd7070Spatrick else
907e5dd7070Spatrick dstAdj = Builder.CreateNSWAdd(srcAdj, adj, "adj");
908e5dd7070Spatrick
909e5dd7070Spatrick return Builder.CreateInsertValue(src, dstAdj, 1);
910e5dd7070Spatrick }
911e5dd7070Spatrick
912e5dd7070Spatrick llvm::Constant *
EmitMemberPointerConversion(const CastExpr * E,llvm::Constant * src)913e5dd7070Spatrick ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,
914e5dd7070Spatrick llvm::Constant *src) {
915e5dd7070Spatrick assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
916e5dd7070Spatrick E->getCastKind() == CK_BaseToDerivedMemberPointer ||
917e5dd7070Spatrick E->getCastKind() == CK_ReinterpretMemberPointer);
918e5dd7070Spatrick
919e5dd7070Spatrick // Under Itanium, reinterprets don't require any additional processing.
920e5dd7070Spatrick if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
921e5dd7070Spatrick
922e5dd7070Spatrick // If the adjustment is trivial, we don't need to do anything.
923e5dd7070Spatrick llvm::Constant *adj = getMemberPointerAdjustment(E);
924e5dd7070Spatrick if (!adj) return src;
925e5dd7070Spatrick
926e5dd7070Spatrick bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
927e5dd7070Spatrick
928e5dd7070Spatrick const MemberPointerType *destTy =
929e5dd7070Spatrick E->getType()->castAs<MemberPointerType>();
930e5dd7070Spatrick
931e5dd7070Spatrick // For member data pointers, this is just a matter of adding the
932e5dd7070Spatrick // offset if the source is non-null.
933e5dd7070Spatrick if (destTy->isMemberDataPointer()) {
934e5dd7070Spatrick // null maps to null.
935e5dd7070Spatrick if (src->isAllOnesValue()) return src;
936e5dd7070Spatrick
937e5dd7070Spatrick if (isDerivedToBase)
938e5dd7070Spatrick return llvm::ConstantExpr::getNSWSub(src, adj);
939e5dd7070Spatrick else
940e5dd7070Spatrick return llvm::ConstantExpr::getNSWAdd(src, adj);
941e5dd7070Spatrick }
942e5dd7070Spatrick
943e5dd7070Spatrick // The this-adjustment is left-shifted by 1 on ARM.
944e5dd7070Spatrick if (UseARMMethodPtrABI) {
945e5dd7070Spatrick uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
946e5dd7070Spatrick offset <<= 1;
947e5dd7070Spatrick adj = llvm::ConstantInt::get(adj->getType(), offset);
948e5dd7070Spatrick }
949e5dd7070Spatrick
950*12c85518Srobert llvm::Constant *srcAdj = src->getAggregateElement(1);
951e5dd7070Spatrick llvm::Constant *dstAdj;
952e5dd7070Spatrick if (isDerivedToBase)
953e5dd7070Spatrick dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);
954e5dd7070Spatrick else
955e5dd7070Spatrick dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);
956e5dd7070Spatrick
957*12c85518Srobert llvm::Constant *res = ConstantFoldInsertValueInstruction(src, dstAdj, 1);
958*12c85518Srobert assert(res != nullptr && "Folding must succeed");
959*12c85518Srobert return res;
960e5dd7070Spatrick }
961e5dd7070Spatrick
962e5dd7070Spatrick llvm::Constant *
EmitNullMemberPointer(const MemberPointerType * MPT)963e5dd7070Spatrick ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
964e5dd7070Spatrick // Itanium C++ ABI 2.3:
965e5dd7070Spatrick // A NULL pointer is represented as -1.
966e5dd7070Spatrick if (MPT->isMemberDataPointer())
967e5dd7070Spatrick return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, /*isSigned=*/true);
968e5dd7070Spatrick
969e5dd7070Spatrick llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
970e5dd7070Spatrick llvm::Constant *Values[2] = { Zero, Zero };
971e5dd7070Spatrick return llvm::ConstantStruct::getAnon(Values);
972e5dd7070Spatrick }
973e5dd7070Spatrick
974e5dd7070Spatrick llvm::Constant *
EmitMemberDataPointer(const MemberPointerType * MPT,CharUnits offset)975e5dd7070Spatrick ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
976e5dd7070Spatrick CharUnits offset) {
977e5dd7070Spatrick // Itanium C++ ABI 2.3:
978e5dd7070Spatrick // A pointer to data member is an offset from the base address of
979e5dd7070Spatrick // the class object containing it, represented as a ptrdiff_t
980e5dd7070Spatrick return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity());
981e5dd7070Spatrick }
982e5dd7070Spatrick
983e5dd7070Spatrick llvm::Constant *
EmitMemberFunctionPointer(const CXXMethodDecl * MD)984e5dd7070Spatrick ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
985e5dd7070Spatrick return BuildMemberPointer(MD, CharUnits::Zero());
986e5dd7070Spatrick }
987e5dd7070Spatrick
BuildMemberPointer(const CXXMethodDecl * MD,CharUnits ThisAdjustment)988e5dd7070Spatrick llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
989e5dd7070Spatrick CharUnits ThisAdjustment) {
990e5dd7070Spatrick assert(MD->isInstance() && "Member function must not be static!");
991e5dd7070Spatrick
992e5dd7070Spatrick CodeGenTypes &Types = CGM.getTypes();
993e5dd7070Spatrick
994e5dd7070Spatrick // Get the function pointer (or index if this is a virtual function).
995e5dd7070Spatrick llvm::Constant *MemPtr[2];
996e5dd7070Spatrick if (MD->isVirtual()) {
997e5dd7070Spatrick uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
998ec727ea7Spatrick uint64_t VTableOffset;
999ec727ea7Spatrick if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1000ec727ea7Spatrick // Multiply by 4-byte relative offsets.
1001ec727ea7Spatrick VTableOffset = Index * 4;
1002ec727ea7Spatrick } else {
1003e5dd7070Spatrick const ASTContext &Context = getContext();
1004ec727ea7Spatrick CharUnits PointerWidth = Context.toCharUnitsFromBits(
1005*12c85518Srobert Context.getTargetInfo().getPointerWidth(LangAS::Default));
1006ec727ea7Spatrick VTableOffset = Index * PointerWidth.getQuantity();
1007ec727ea7Spatrick }
1008e5dd7070Spatrick
1009e5dd7070Spatrick if (UseARMMethodPtrABI) {
1010e5dd7070Spatrick // ARM C++ ABI 3.2.1:
1011e5dd7070Spatrick // This ABI specifies that adj contains twice the this
1012e5dd7070Spatrick // adjustment, plus 1 if the member function is virtual. The
1013e5dd7070Spatrick // least significant bit of adj then makes exactly the same
1014e5dd7070Spatrick // discrimination as the least significant bit of ptr does for
1015e5dd7070Spatrick // Itanium.
1016e5dd7070Spatrick MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);
1017e5dd7070Spatrick MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1018e5dd7070Spatrick 2 * ThisAdjustment.getQuantity() + 1);
1019e5dd7070Spatrick } else {
1020e5dd7070Spatrick // Itanium C++ ABI 2.3:
1021e5dd7070Spatrick // For a virtual function, [the pointer field] is 1 plus the
1022e5dd7070Spatrick // virtual table offset (in bytes) of the function,
1023e5dd7070Spatrick // represented as a ptrdiff_t.
1024e5dd7070Spatrick MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
1025e5dd7070Spatrick MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1026e5dd7070Spatrick ThisAdjustment.getQuantity());
1027e5dd7070Spatrick }
1028e5dd7070Spatrick } else {
1029e5dd7070Spatrick const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
1030e5dd7070Spatrick llvm::Type *Ty;
1031e5dd7070Spatrick // Check whether the function has a computable LLVM signature.
1032e5dd7070Spatrick if (Types.isFuncTypeConvertible(FPT)) {
1033e5dd7070Spatrick // The function has a computable LLVM signature; use the correct type.
1034e5dd7070Spatrick Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
1035e5dd7070Spatrick } else {
1036e5dd7070Spatrick // Use an arbitrary non-function type to tell GetAddrOfFunction that the
1037e5dd7070Spatrick // function type is incomplete.
1038e5dd7070Spatrick Ty = CGM.PtrDiffTy;
1039e5dd7070Spatrick }
1040e5dd7070Spatrick llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty);
1041e5dd7070Spatrick
1042e5dd7070Spatrick MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
1043e5dd7070Spatrick MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1044e5dd7070Spatrick (UseARMMethodPtrABI ? 2 : 1) *
1045e5dd7070Spatrick ThisAdjustment.getQuantity());
1046e5dd7070Spatrick }
1047e5dd7070Spatrick
1048e5dd7070Spatrick return llvm::ConstantStruct::getAnon(MemPtr);
1049e5dd7070Spatrick }
1050e5dd7070Spatrick
EmitMemberPointer(const APValue & MP,QualType MPType)1051e5dd7070Spatrick llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
1052e5dd7070Spatrick QualType MPType) {
1053e5dd7070Spatrick const MemberPointerType *MPT = MPType->castAs<MemberPointerType>();
1054e5dd7070Spatrick const ValueDecl *MPD = MP.getMemberPointerDecl();
1055e5dd7070Spatrick if (!MPD)
1056e5dd7070Spatrick return EmitNullMemberPointer(MPT);
1057e5dd7070Spatrick
1058a9ac8606Spatrick CharUnits ThisAdjustment = getContext().getMemberPointerPathAdjustment(MP);
1059e5dd7070Spatrick
1060e5dd7070Spatrick if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
1061e5dd7070Spatrick return BuildMemberPointer(MD, ThisAdjustment);
1062e5dd7070Spatrick
1063e5dd7070Spatrick CharUnits FieldOffset =
1064e5dd7070Spatrick getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
1065e5dd7070Spatrick return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
1066e5dd7070Spatrick }
1067e5dd7070Spatrick
1068e5dd7070Spatrick /// The comparison algorithm is pretty easy: the member pointers are
1069e5dd7070Spatrick /// the same if they're either bitwise identical *or* both null.
1070e5dd7070Spatrick ///
1071e5dd7070Spatrick /// ARM is different here only because null-ness is more complicated.
1072e5dd7070Spatrick llvm::Value *
EmitMemberPointerComparison(CodeGenFunction & CGF,llvm::Value * L,llvm::Value * R,const MemberPointerType * MPT,bool Inequality)1073e5dd7070Spatrick ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
1074e5dd7070Spatrick llvm::Value *L,
1075e5dd7070Spatrick llvm::Value *R,
1076e5dd7070Spatrick const MemberPointerType *MPT,
1077e5dd7070Spatrick bool Inequality) {
1078e5dd7070Spatrick CGBuilderTy &Builder = CGF.Builder;
1079e5dd7070Spatrick
1080e5dd7070Spatrick llvm::ICmpInst::Predicate Eq;
1081e5dd7070Spatrick llvm::Instruction::BinaryOps And, Or;
1082e5dd7070Spatrick if (Inequality) {
1083e5dd7070Spatrick Eq = llvm::ICmpInst::ICMP_NE;
1084e5dd7070Spatrick And = llvm::Instruction::Or;
1085e5dd7070Spatrick Or = llvm::Instruction::And;
1086e5dd7070Spatrick } else {
1087e5dd7070Spatrick Eq = llvm::ICmpInst::ICMP_EQ;
1088e5dd7070Spatrick And = llvm::Instruction::And;
1089e5dd7070Spatrick Or = llvm::Instruction::Or;
1090e5dd7070Spatrick }
1091e5dd7070Spatrick
1092e5dd7070Spatrick // Member data pointers are easy because there's a unique null
1093e5dd7070Spatrick // value, so it just comes down to bitwise equality.
1094e5dd7070Spatrick if (MPT->isMemberDataPointer())
1095e5dd7070Spatrick return Builder.CreateICmp(Eq, L, R);
1096e5dd7070Spatrick
1097e5dd7070Spatrick // For member function pointers, the tautologies are more complex.
1098e5dd7070Spatrick // The Itanium tautology is:
1099e5dd7070Spatrick // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj))
1100e5dd7070Spatrick // The ARM tautology is:
1101e5dd7070Spatrick // (L == R) <==> (L.ptr == R.ptr &&
1102e5dd7070Spatrick // (L.adj == R.adj ||
1103e5dd7070Spatrick // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0)))
1104e5dd7070Spatrick // The inequality tautologies have exactly the same structure, except
1105e5dd7070Spatrick // applying De Morgan's laws.
1106e5dd7070Spatrick
1107e5dd7070Spatrick llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr");
1108e5dd7070Spatrick llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr");
1109e5dd7070Spatrick
1110e5dd7070Spatrick // This condition tests whether L.ptr == R.ptr. This must always be
1111e5dd7070Spatrick // true for equality to hold.
1112e5dd7070Spatrick llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr");
1113e5dd7070Spatrick
1114e5dd7070Spatrick // This condition, together with the assumption that L.ptr == R.ptr,
1115e5dd7070Spatrick // tests whether the pointers are both null. ARM imposes an extra
1116e5dd7070Spatrick // condition.
1117e5dd7070Spatrick llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType());
1118e5dd7070Spatrick llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null");
1119e5dd7070Spatrick
1120e5dd7070Spatrick // This condition tests whether L.adj == R.adj. If this isn't
1121e5dd7070Spatrick // true, the pointers are unequal unless they're both null.
1122e5dd7070Spatrick llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj");
1123e5dd7070Spatrick llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj");
1124e5dd7070Spatrick llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj");
1125e5dd7070Spatrick
1126e5dd7070Spatrick // Null member function pointers on ARM clear the low bit of Adj,
1127e5dd7070Spatrick // so the zero condition has to check that neither low bit is set.
1128e5dd7070Spatrick if (UseARMMethodPtrABI) {
1129e5dd7070Spatrick llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
1130e5dd7070Spatrick
1131e5dd7070Spatrick // Compute (l.adj | r.adj) & 1 and test it against zero.
1132e5dd7070Spatrick llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");
1133e5dd7070Spatrick llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
1134e5dd7070Spatrick llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,
1135e5dd7070Spatrick "cmp.or.adj");
1136e5dd7070Spatrick EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
1137e5dd7070Spatrick }
1138e5dd7070Spatrick
1139e5dd7070Spatrick // Tie together all our conditions.
1140e5dd7070Spatrick llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
1141e5dd7070Spatrick Result = Builder.CreateBinOp(And, PtrEq, Result,
1142e5dd7070Spatrick Inequality ? "memptr.ne" : "memptr.eq");
1143e5dd7070Spatrick return Result;
1144e5dd7070Spatrick }
1145e5dd7070Spatrick
1146e5dd7070Spatrick llvm::Value *
EmitMemberPointerIsNotNull(CodeGenFunction & CGF,llvm::Value * MemPtr,const MemberPointerType * MPT)1147e5dd7070Spatrick ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
1148e5dd7070Spatrick llvm::Value *MemPtr,
1149e5dd7070Spatrick const MemberPointerType *MPT) {
1150e5dd7070Spatrick CGBuilderTy &Builder = CGF.Builder;
1151e5dd7070Spatrick
1152e5dd7070Spatrick /// For member data pointers, this is just a check against -1.
1153e5dd7070Spatrick if (MPT->isMemberDataPointer()) {
1154e5dd7070Spatrick assert(MemPtr->getType() == CGM.PtrDiffTy);
1155e5dd7070Spatrick llvm::Value *NegativeOne =
1156e5dd7070Spatrick llvm::Constant::getAllOnesValue(MemPtr->getType());
1157e5dd7070Spatrick return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");
1158e5dd7070Spatrick }
1159e5dd7070Spatrick
1160e5dd7070Spatrick // In Itanium, a member function pointer is not null if 'ptr' is not null.
1161e5dd7070Spatrick llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr");
1162e5dd7070Spatrick
1163e5dd7070Spatrick llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
1164e5dd7070Spatrick llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool");
1165e5dd7070Spatrick
1166e5dd7070Spatrick // On ARM, a member function pointer is also non-null if the low bit of 'adj'
1167e5dd7070Spatrick // (the virtual bit) is set.
1168e5dd7070Spatrick if (UseARMMethodPtrABI) {
1169e5dd7070Spatrick llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
1170e5dd7070Spatrick llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
1171e5dd7070Spatrick llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
1172e5dd7070Spatrick llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,
1173e5dd7070Spatrick "memptr.isvirtual");
1174e5dd7070Spatrick Result = Builder.CreateOr(Result, IsVirtual);
1175e5dd7070Spatrick }
1176e5dd7070Spatrick
1177e5dd7070Spatrick return Result;
1178e5dd7070Spatrick }
1179e5dd7070Spatrick
classifyReturnType(CGFunctionInfo & FI) const1180e5dd7070Spatrick bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
1181e5dd7070Spatrick const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
1182e5dd7070Spatrick if (!RD)
1183e5dd7070Spatrick return false;
1184e5dd7070Spatrick
1185e5dd7070Spatrick // If C++ prohibits us from making a copy, return by address.
1186e5dd7070Spatrick if (!RD->canPassInRegisters()) {
1187e5dd7070Spatrick auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
1188e5dd7070Spatrick FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
1189e5dd7070Spatrick return true;
1190e5dd7070Spatrick }
1191e5dd7070Spatrick return false;
1192e5dd7070Spatrick }
1193e5dd7070Spatrick
1194e5dd7070Spatrick /// The Itanium ABI requires non-zero initialization only for data
1195e5dd7070Spatrick /// member pointers, for which '0' is a valid offset.
isZeroInitializable(const MemberPointerType * MPT)1196e5dd7070Spatrick bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
1197e5dd7070Spatrick return MPT->isMemberFunctionPointer();
1198e5dd7070Spatrick }
1199e5dd7070Spatrick
1200e5dd7070Spatrick /// The Itanium ABI always places an offset to the complete object
1201e5dd7070Spatrick /// at entry -2 in the vtable.
emitVirtualObjectDelete(CodeGenFunction & CGF,const CXXDeleteExpr * DE,Address Ptr,QualType ElementType,const CXXDestructorDecl * Dtor)1202e5dd7070Spatrick void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
1203e5dd7070Spatrick const CXXDeleteExpr *DE,
1204e5dd7070Spatrick Address Ptr,
1205e5dd7070Spatrick QualType ElementType,
1206e5dd7070Spatrick const CXXDestructorDecl *Dtor) {
1207e5dd7070Spatrick bool UseGlobalDelete = DE->isGlobalDelete();
1208e5dd7070Spatrick if (UseGlobalDelete) {
1209e5dd7070Spatrick // Derive the complete-object pointer, which is what we need
1210e5dd7070Spatrick // to pass to the deallocation function.
1211e5dd7070Spatrick
1212e5dd7070Spatrick // Grab the vtable pointer as an intptr_t*.
1213e5dd7070Spatrick auto *ClassDecl =
1214e5dd7070Spatrick cast<CXXRecordDecl>(ElementType->castAs<RecordType>()->getDecl());
1215e5dd7070Spatrick llvm::Value *VTable =
1216e5dd7070Spatrick CGF.GetVTablePtr(Ptr, CGF.IntPtrTy->getPointerTo(), ClassDecl);
1217e5dd7070Spatrick
1218e5dd7070Spatrick // Track back to entry -2 and pull out the offset there.
1219e5dd7070Spatrick llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
1220a9ac8606Spatrick CGF.IntPtrTy, VTable, -2, "complete-offset.ptr");
1221a9ac8606Spatrick llvm::Value *Offset = CGF.Builder.CreateAlignedLoad(CGF.IntPtrTy, OffsetPtr, CGF.getPointerAlign());
1222e5dd7070Spatrick
1223e5dd7070Spatrick // Apply the offset.
1224e5dd7070Spatrick llvm::Value *CompletePtr =
1225e5dd7070Spatrick CGF.Builder.CreateBitCast(Ptr.getPointer(), CGF.Int8PtrTy);
1226a9ac8606Spatrick CompletePtr =
1227a9ac8606Spatrick CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, CompletePtr, Offset);
1228e5dd7070Spatrick
1229e5dd7070Spatrick // If we're supposed to call the global delete, make sure we do so
1230e5dd7070Spatrick // even if the destructor throws.
1231e5dd7070Spatrick CGF.pushCallObjectDeleteCleanup(DE->getOperatorDelete(), CompletePtr,
1232e5dd7070Spatrick ElementType);
1233e5dd7070Spatrick }
1234e5dd7070Spatrick
1235e5dd7070Spatrick // FIXME: Provide a source location here even though there's no
1236e5dd7070Spatrick // CXXMemberCallExpr for dtor call.
1237e5dd7070Spatrick CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
1238e5dd7070Spatrick EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE);
1239e5dd7070Spatrick
1240e5dd7070Spatrick if (UseGlobalDelete)
1241e5dd7070Spatrick CGF.PopCleanupBlock();
1242e5dd7070Spatrick }
1243e5dd7070Spatrick
emitRethrow(CodeGenFunction & CGF,bool isNoReturn)1244e5dd7070Spatrick void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
1245e5dd7070Spatrick // void __cxa_rethrow();
1246e5dd7070Spatrick
1247e5dd7070Spatrick llvm::FunctionType *FTy =
1248e5dd7070Spatrick llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
1249e5dd7070Spatrick
1250e5dd7070Spatrick llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
1251e5dd7070Spatrick
1252e5dd7070Spatrick if (isNoReturn)
1253*12c85518Srobert CGF.EmitNoreturnRuntimeCallOrInvoke(Fn, std::nullopt);
1254e5dd7070Spatrick else
1255e5dd7070Spatrick CGF.EmitRuntimeCallOrInvoke(Fn);
1256e5dd7070Spatrick }
1257e5dd7070Spatrick
getAllocateExceptionFn(CodeGenModule & CGM)1258e5dd7070Spatrick static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM) {
1259e5dd7070Spatrick // void *__cxa_allocate_exception(size_t thrown_size);
1260e5dd7070Spatrick
1261e5dd7070Spatrick llvm::FunctionType *FTy =
1262e5dd7070Spatrick llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*isVarArg=*/false);
1263e5dd7070Spatrick
1264e5dd7070Spatrick return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
1265e5dd7070Spatrick }
1266e5dd7070Spatrick
getThrowFn(CodeGenModule & CGM)1267e5dd7070Spatrick static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM) {
1268e5dd7070Spatrick // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
1269e5dd7070Spatrick // void (*dest) (void *));
1270e5dd7070Spatrick
1271e5dd7070Spatrick llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.Int8PtrTy, CGM.Int8PtrTy };
1272e5dd7070Spatrick llvm::FunctionType *FTy =
1273e5dd7070Spatrick llvm::FunctionType::get(CGM.VoidTy, Args, /*isVarArg=*/false);
1274e5dd7070Spatrick
1275e5dd7070Spatrick return CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
1276e5dd7070Spatrick }
1277e5dd7070Spatrick
emitThrow(CodeGenFunction & CGF,const CXXThrowExpr * E)1278e5dd7070Spatrick void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
1279e5dd7070Spatrick QualType ThrowType = E->getSubExpr()->getType();
1280e5dd7070Spatrick // Now allocate the exception object.
1281e5dd7070Spatrick llvm::Type *SizeTy = CGF.ConvertType(getContext().getSizeType());
1282e5dd7070Spatrick uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
1283e5dd7070Spatrick
1284e5dd7070Spatrick llvm::FunctionCallee AllocExceptionFn = getAllocateExceptionFn(CGM);
1285e5dd7070Spatrick llvm::CallInst *ExceptionPtr = CGF.EmitNounwindRuntimeCall(
1286e5dd7070Spatrick AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception");
1287e5dd7070Spatrick
1288e5dd7070Spatrick CharUnits ExnAlign = CGF.getContext().getExnObjectAlignment();
1289*12c85518Srobert CGF.EmitAnyExprToExn(
1290*12c85518Srobert E->getSubExpr(), Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
1291e5dd7070Spatrick
1292e5dd7070Spatrick // Now throw the exception.
1293e5dd7070Spatrick llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
1294e5dd7070Spatrick /*ForEH=*/true);
1295e5dd7070Spatrick
1296e5dd7070Spatrick // The address of the destructor. If the exception type has a
1297e5dd7070Spatrick // trivial destructor (or isn't a record), we just pass null.
1298e5dd7070Spatrick llvm::Constant *Dtor = nullptr;
1299e5dd7070Spatrick if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
1300e5dd7070Spatrick CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
1301e5dd7070Spatrick if (!Record->hasTrivialDestructor()) {
1302e5dd7070Spatrick CXXDestructorDecl *DtorD = Record->getDestructor();
1303e5dd7070Spatrick Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete));
1304e5dd7070Spatrick Dtor = llvm::ConstantExpr::getBitCast(Dtor, CGM.Int8PtrTy);
1305e5dd7070Spatrick }
1306e5dd7070Spatrick }
1307e5dd7070Spatrick if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1308e5dd7070Spatrick
1309e5dd7070Spatrick llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };
1310e5dd7070Spatrick CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args);
1311e5dd7070Spatrick }
1312e5dd7070Spatrick
getItaniumDynamicCastFn(CodeGenFunction & CGF)1313e5dd7070Spatrick static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF) {
1314e5dd7070Spatrick // void *__dynamic_cast(const void *sub,
1315e5dd7070Spatrick // const abi::__class_type_info *src,
1316e5dd7070Spatrick // const abi::__class_type_info *dst,
1317e5dd7070Spatrick // std::ptrdiff_t src2dst_offset);
1318e5dd7070Spatrick
1319e5dd7070Spatrick llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
1320e5dd7070Spatrick llvm::Type *PtrDiffTy =
1321e5dd7070Spatrick CGF.ConvertType(CGF.getContext().getPointerDiffType());
1322e5dd7070Spatrick
1323e5dd7070Spatrick llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy };
1324e5dd7070Spatrick
1325e5dd7070Spatrick llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
1326e5dd7070Spatrick
1327e5dd7070Spatrick // Mark the function as nounwind readonly.
1328*12c85518Srobert llvm::AttrBuilder FuncAttrs(CGF.getLLVMContext());
1329*12c85518Srobert FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
1330*12c85518Srobert FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
1331e5dd7070Spatrick llvm::AttributeList Attrs = llvm::AttributeList::get(
1332e5dd7070Spatrick CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
1333e5dd7070Spatrick
1334e5dd7070Spatrick return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs);
1335e5dd7070Spatrick }
1336e5dd7070Spatrick
getBadCastFn(CodeGenFunction & CGF)1337e5dd7070Spatrick static llvm::FunctionCallee getBadCastFn(CodeGenFunction &CGF) {
1338e5dd7070Spatrick // void __cxa_bad_cast();
1339e5dd7070Spatrick llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
1340e5dd7070Spatrick return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
1341e5dd7070Spatrick }
1342e5dd7070Spatrick
1343e5dd7070Spatrick /// Compute the src2dst_offset hint as described in the
1344e5dd7070Spatrick /// Itanium C++ ABI [2.9.7]
computeOffsetHint(ASTContext & Context,const CXXRecordDecl * Src,const CXXRecordDecl * Dst)1345e5dd7070Spatrick static CharUnits computeOffsetHint(ASTContext &Context,
1346e5dd7070Spatrick const CXXRecordDecl *Src,
1347e5dd7070Spatrick const CXXRecordDecl *Dst) {
1348e5dd7070Spatrick CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
1349e5dd7070Spatrick /*DetectVirtual=*/false);
1350e5dd7070Spatrick
1351e5dd7070Spatrick // If Dst is not derived from Src we can skip the whole computation below and
1352e5dd7070Spatrick // return that Src is not a public base of Dst. Record all inheritance paths.
1353e5dd7070Spatrick if (!Dst->isDerivedFrom(Src, Paths))
1354e5dd7070Spatrick return CharUnits::fromQuantity(-2ULL);
1355e5dd7070Spatrick
1356e5dd7070Spatrick unsigned NumPublicPaths = 0;
1357e5dd7070Spatrick CharUnits Offset;
1358e5dd7070Spatrick
1359e5dd7070Spatrick // Now walk all possible inheritance paths.
1360e5dd7070Spatrick for (const CXXBasePath &Path : Paths) {
1361e5dd7070Spatrick if (Path.Access != AS_public) // Ignore non-public inheritance.
1362e5dd7070Spatrick continue;
1363e5dd7070Spatrick
1364e5dd7070Spatrick ++NumPublicPaths;
1365e5dd7070Spatrick
1366e5dd7070Spatrick for (const CXXBasePathElement &PathElement : Path) {
1367e5dd7070Spatrick // If the path contains a virtual base class we can't give any hint.
1368e5dd7070Spatrick // -1: no hint.
1369e5dd7070Spatrick if (PathElement.Base->isVirtual())
1370e5dd7070Spatrick return CharUnits::fromQuantity(-1ULL);
1371e5dd7070Spatrick
1372e5dd7070Spatrick if (NumPublicPaths > 1) // Won't use offsets, skip computation.
1373e5dd7070Spatrick continue;
1374e5dd7070Spatrick
1375e5dd7070Spatrick // Accumulate the base class offsets.
1376e5dd7070Spatrick const ASTRecordLayout &L = Context.getASTRecordLayout(PathElement.Class);
1377e5dd7070Spatrick Offset += L.getBaseClassOffset(
1378e5dd7070Spatrick PathElement.Base->getType()->getAsCXXRecordDecl());
1379e5dd7070Spatrick }
1380e5dd7070Spatrick }
1381e5dd7070Spatrick
1382e5dd7070Spatrick // -2: Src is not a public base of Dst.
1383e5dd7070Spatrick if (NumPublicPaths == 0)
1384e5dd7070Spatrick return CharUnits::fromQuantity(-2ULL);
1385e5dd7070Spatrick
1386e5dd7070Spatrick // -3: Src is a multiple public base type but never a virtual base type.
1387e5dd7070Spatrick if (NumPublicPaths > 1)
1388e5dd7070Spatrick return CharUnits::fromQuantity(-3ULL);
1389e5dd7070Spatrick
1390e5dd7070Spatrick // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
1391e5dd7070Spatrick // Return the offset of Src from the origin of Dst.
1392e5dd7070Spatrick return Offset;
1393e5dd7070Spatrick }
1394e5dd7070Spatrick
getBadTypeidFn(CodeGenFunction & CGF)1395e5dd7070Spatrick static llvm::FunctionCallee getBadTypeidFn(CodeGenFunction &CGF) {
1396e5dd7070Spatrick // void __cxa_bad_typeid();
1397e5dd7070Spatrick llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
1398e5dd7070Spatrick
1399e5dd7070Spatrick return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
1400e5dd7070Spatrick }
1401e5dd7070Spatrick
shouldTypeidBeNullChecked(bool IsDeref,QualType SrcRecordTy)1402e5dd7070Spatrick bool ItaniumCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
1403e5dd7070Spatrick QualType SrcRecordTy) {
1404e5dd7070Spatrick return IsDeref;
1405e5dd7070Spatrick }
1406e5dd7070Spatrick
EmitBadTypeidCall(CodeGenFunction & CGF)1407e5dd7070Spatrick void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
1408e5dd7070Spatrick llvm::FunctionCallee Fn = getBadTypeidFn(CGF);
1409e5dd7070Spatrick llvm::CallBase *Call = CGF.EmitRuntimeCallOrInvoke(Fn);
1410e5dd7070Spatrick Call->setDoesNotReturn();
1411e5dd7070Spatrick CGF.Builder.CreateUnreachable();
1412e5dd7070Spatrick }
1413e5dd7070Spatrick
EmitTypeid(CodeGenFunction & CGF,QualType SrcRecordTy,Address ThisPtr,llvm::Type * StdTypeInfoPtrTy)1414e5dd7070Spatrick llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
1415e5dd7070Spatrick QualType SrcRecordTy,
1416e5dd7070Spatrick Address ThisPtr,
1417e5dd7070Spatrick llvm::Type *StdTypeInfoPtrTy) {
1418e5dd7070Spatrick auto *ClassDecl =
1419e5dd7070Spatrick cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
1420e5dd7070Spatrick llvm::Value *Value =
1421e5dd7070Spatrick CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo(), ClassDecl);
1422e5dd7070Spatrick
1423ec727ea7Spatrick if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1424ec727ea7Spatrick // Load the type info.
1425ec727ea7Spatrick Value = CGF.Builder.CreateBitCast(Value, CGM.Int8PtrTy);
1426ec727ea7Spatrick Value = CGF.Builder.CreateCall(
1427ec727ea7Spatrick CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1428ec727ea7Spatrick {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
1429ec727ea7Spatrick
1430ec727ea7Spatrick // Setup to dereference again since this is a proxy we accessed.
1431ec727ea7Spatrick Value = CGF.Builder.CreateBitCast(Value, StdTypeInfoPtrTy->getPointerTo());
1432ec727ea7Spatrick } else {
1433e5dd7070Spatrick // Load the type info.
1434a9ac8606Spatrick Value =
1435a9ac8606Spatrick CGF.Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy, Value, -1ULL);
1436ec727ea7Spatrick }
1437a9ac8606Spatrick return CGF.Builder.CreateAlignedLoad(StdTypeInfoPtrTy, Value,
1438a9ac8606Spatrick CGF.getPointerAlign());
1439e5dd7070Spatrick }
1440e5dd7070Spatrick
shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,QualType SrcRecordTy)1441e5dd7070Spatrick bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
1442e5dd7070Spatrick QualType SrcRecordTy) {
1443e5dd7070Spatrick return SrcIsPtr;
1444e5dd7070Spatrick }
1445e5dd7070Spatrick
EmitDynamicCastCall(CodeGenFunction & CGF,Address ThisAddr,QualType SrcRecordTy,QualType DestTy,QualType DestRecordTy,llvm::BasicBlock * CastEnd)1446e5dd7070Spatrick llvm::Value *ItaniumCXXABI::EmitDynamicCastCall(
1447e5dd7070Spatrick CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
1448e5dd7070Spatrick QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
1449e5dd7070Spatrick llvm::Type *PtrDiffLTy =
1450e5dd7070Spatrick CGF.ConvertType(CGF.getContext().getPointerDiffType());
1451e5dd7070Spatrick llvm::Type *DestLTy = CGF.ConvertType(DestTy);
1452e5dd7070Spatrick
1453e5dd7070Spatrick llvm::Value *SrcRTTI =
1454e5dd7070Spatrick CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
1455e5dd7070Spatrick llvm::Value *DestRTTI =
1456e5dd7070Spatrick CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
1457e5dd7070Spatrick
1458e5dd7070Spatrick // Compute the offset hint.
1459e5dd7070Spatrick const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
1460e5dd7070Spatrick const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
1461e5dd7070Spatrick llvm::Value *OffsetHint = llvm::ConstantInt::get(
1462e5dd7070Spatrick PtrDiffLTy,
1463e5dd7070Spatrick computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity());
1464e5dd7070Spatrick
1465e5dd7070Spatrick // Emit the call to __dynamic_cast.
1466e5dd7070Spatrick llvm::Value *Value = ThisAddr.getPointer();
1467e5dd7070Spatrick Value = CGF.EmitCastToVoidPtr(Value);
1468e5dd7070Spatrick
1469e5dd7070Spatrick llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint};
1470e5dd7070Spatrick Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), args);
1471e5dd7070Spatrick Value = CGF.Builder.CreateBitCast(Value, DestLTy);
1472e5dd7070Spatrick
1473e5dd7070Spatrick /// C++ [expr.dynamic.cast]p9:
1474e5dd7070Spatrick /// A failed cast to reference type throws std::bad_cast
1475e5dd7070Spatrick if (DestTy->isReferenceType()) {
1476e5dd7070Spatrick llvm::BasicBlock *BadCastBlock =
1477e5dd7070Spatrick CGF.createBasicBlock("dynamic_cast.bad_cast");
1478e5dd7070Spatrick
1479e5dd7070Spatrick llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value);
1480e5dd7070Spatrick CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
1481e5dd7070Spatrick
1482e5dd7070Spatrick CGF.EmitBlock(BadCastBlock);
1483e5dd7070Spatrick EmitBadCastCall(CGF);
1484e5dd7070Spatrick }
1485e5dd7070Spatrick
1486e5dd7070Spatrick return Value;
1487e5dd7070Spatrick }
1488e5dd7070Spatrick
EmitDynamicCastToVoid(CodeGenFunction & CGF,Address ThisAddr,QualType SrcRecordTy,QualType DestTy)1489e5dd7070Spatrick llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF,
1490e5dd7070Spatrick Address ThisAddr,
1491e5dd7070Spatrick QualType SrcRecordTy,
1492e5dd7070Spatrick QualType DestTy) {
1493e5dd7070Spatrick llvm::Type *DestLTy = CGF.ConvertType(DestTy);
1494e5dd7070Spatrick auto *ClassDecl =
1495e5dd7070Spatrick cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
1496ec727ea7Spatrick llvm::Value *OffsetToTop;
1497ec727ea7Spatrick if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1498e5dd7070Spatrick // Get the vtable pointer.
1499ec727ea7Spatrick llvm::Value *VTable =
1500ec727ea7Spatrick CGF.GetVTablePtr(ThisAddr, CGM.Int32Ty->getPointerTo(), ClassDecl);
1501e5dd7070Spatrick
1502e5dd7070Spatrick // Get the offset-to-top from the vtable.
1503e5dd7070Spatrick OffsetToTop =
1504a9ac8606Spatrick CGF.Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);
1505ec727ea7Spatrick OffsetToTop = CGF.Builder.CreateAlignedLoad(
1506a9ac8606Spatrick CGM.Int32Ty, OffsetToTop, CharUnits::fromQuantity(4), "offset.to.top");
1507ec727ea7Spatrick } else {
1508ec727ea7Spatrick llvm::Type *PtrDiffLTy =
1509ec727ea7Spatrick CGF.ConvertType(CGF.getContext().getPointerDiffType());
1510e5dd7070Spatrick
1511ec727ea7Spatrick // Get the vtable pointer.
1512ec727ea7Spatrick llvm::Value *VTable =
1513ec727ea7Spatrick CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), ClassDecl);
1514ec727ea7Spatrick
1515ec727ea7Spatrick // Get the offset-to-top from the vtable.
1516a9ac8606Spatrick OffsetToTop =
1517a9ac8606Spatrick CGF.Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
1518ec727ea7Spatrick OffsetToTop = CGF.Builder.CreateAlignedLoad(
1519a9ac8606Spatrick PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top");
1520ec727ea7Spatrick }
1521e5dd7070Spatrick // Finally, add the offset to the pointer.
1522e5dd7070Spatrick llvm::Value *Value = ThisAddr.getPointer();
1523e5dd7070Spatrick Value = CGF.EmitCastToVoidPtr(Value);
1524a9ac8606Spatrick Value = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, Value, OffsetToTop);
1525e5dd7070Spatrick return CGF.Builder.CreateBitCast(Value, DestLTy);
1526e5dd7070Spatrick }
1527e5dd7070Spatrick
EmitBadCastCall(CodeGenFunction & CGF)1528e5dd7070Spatrick bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
1529e5dd7070Spatrick llvm::FunctionCallee Fn = getBadCastFn(CGF);
1530e5dd7070Spatrick llvm::CallBase *Call = CGF.EmitRuntimeCallOrInvoke(Fn);
1531e5dd7070Spatrick Call->setDoesNotReturn();
1532e5dd7070Spatrick CGF.Builder.CreateUnreachable();
1533e5dd7070Spatrick return true;
1534e5dd7070Spatrick }
1535e5dd7070Spatrick
1536e5dd7070Spatrick llvm::Value *
GetVirtualBaseClassOffset(CodeGenFunction & CGF,Address This,const CXXRecordDecl * ClassDecl,const CXXRecordDecl * BaseClassDecl)1537e5dd7070Spatrick ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
1538e5dd7070Spatrick Address This,
1539e5dd7070Spatrick const CXXRecordDecl *ClassDecl,
1540e5dd7070Spatrick const CXXRecordDecl *BaseClassDecl) {
1541e5dd7070Spatrick llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
1542e5dd7070Spatrick CharUnits VBaseOffsetOffset =
1543e5dd7070Spatrick CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
1544e5dd7070Spatrick BaseClassDecl);
1545e5dd7070Spatrick llvm::Value *VBaseOffsetPtr =
1546a9ac8606Spatrick CGF.Builder.CreateConstGEP1_64(
1547a9ac8606Spatrick CGF.Int8Ty, VTablePtr, VBaseOffsetOffset.getQuantity(),
1548e5dd7070Spatrick "vbase.offset.ptr");
1549ec727ea7Spatrick
1550ec727ea7Spatrick llvm::Value *VBaseOffset;
1551ec727ea7Spatrick if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1552ec727ea7Spatrick VBaseOffsetPtr =
1553ec727ea7Spatrick CGF.Builder.CreateBitCast(VBaseOffsetPtr, CGF.Int32Ty->getPointerTo());
1554ec727ea7Spatrick VBaseOffset = CGF.Builder.CreateAlignedLoad(
1555a9ac8606Spatrick CGF.Int32Ty, VBaseOffsetPtr, CharUnits::fromQuantity(4),
1556a9ac8606Spatrick "vbase.offset");
1557ec727ea7Spatrick } else {
1558e5dd7070Spatrick VBaseOffsetPtr = CGF.Builder.CreateBitCast(VBaseOffsetPtr,
1559e5dd7070Spatrick CGM.PtrDiffTy->getPointerTo());
1560ec727ea7Spatrick VBaseOffset = CGF.Builder.CreateAlignedLoad(
1561a9ac8606Spatrick CGM.PtrDiffTy, VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");
1562ec727ea7Spatrick }
1563e5dd7070Spatrick return VBaseOffset;
1564e5dd7070Spatrick }
1565e5dd7070Spatrick
EmitCXXConstructors(const CXXConstructorDecl * D)1566e5dd7070Spatrick void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
1567e5dd7070Spatrick // Just make sure we're in sync with TargetCXXABI.
1568e5dd7070Spatrick assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
1569e5dd7070Spatrick
1570e5dd7070Spatrick // The constructor used for constructing this as a base class;
1571e5dd7070Spatrick // ignores virtual bases.
1572e5dd7070Spatrick CGM.EmitGlobal(GlobalDecl(D, Ctor_Base));
1573e5dd7070Spatrick
1574e5dd7070Spatrick // The constructor used for constructing this as a complete class;
1575e5dd7070Spatrick // constructs the virtual bases, then calls the base constructor.
1576e5dd7070Spatrick if (!D->getParent()->isAbstract()) {
1577e5dd7070Spatrick // We don't need to emit the complete ctor if the class is abstract.
1578e5dd7070Spatrick CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));
1579e5dd7070Spatrick }
1580e5dd7070Spatrick }
1581e5dd7070Spatrick
1582ec727ea7Spatrick CGCXXABI::AddedStructorArgCounts
buildStructorSignature(GlobalDecl GD,SmallVectorImpl<CanQualType> & ArgTys)1583e5dd7070Spatrick ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
1584e5dd7070Spatrick SmallVectorImpl<CanQualType> &ArgTys) {
1585e5dd7070Spatrick ASTContext &Context = getContext();
1586e5dd7070Spatrick
1587e5dd7070Spatrick // All parameters are already in place except VTT, which goes after 'this'.
1588e5dd7070Spatrick // These are Clang types, so we don't need to worry about sret yet.
1589e5dd7070Spatrick
1590e5dd7070Spatrick // Check if we need to add a VTT parameter (which has type void **).
1591e5dd7070Spatrick if ((isa<CXXConstructorDecl>(GD.getDecl()) ? GD.getCtorType() == Ctor_Base
1592e5dd7070Spatrick : GD.getDtorType() == Dtor_Base) &&
1593e5dd7070Spatrick cast<CXXMethodDecl>(GD.getDecl())->getParent()->getNumVBases() != 0) {
1594e5dd7070Spatrick ArgTys.insert(ArgTys.begin() + 1,
1595e5dd7070Spatrick Context.getPointerType(Context.VoidPtrTy));
1596ec727ea7Spatrick return AddedStructorArgCounts::prefix(1);
1597e5dd7070Spatrick }
1598ec727ea7Spatrick return AddedStructorArgCounts{};
1599e5dd7070Spatrick }
1600e5dd7070Spatrick
EmitCXXDestructors(const CXXDestructorDecl * D)1601e5dd7070Spatrick void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
1602e5dd7070Spatrick // The destructor used for destructing this as a base class; ignores
1603e5dd7070Spatrick // virtual bases.
1604e5dd7070Spatrick CGM.EmitGlobal(GlobalDecl(D, Dtor_Base));
1605e5dd7070Spatrick
1606e5dd7070Spatrick // The destructor used for destructing this as a most-derived class;
1607e5dd7070Spatrick // call the base destructor and then destructs any virtual bases.
1608e5dd7070Spatrick CGM.EmitGlobal(GlobalDecl(D, Dtor_Complete));
1609e5dd7070Spatrick
1610e5dd7070Spatrick // The destructor in a virtual table is always a 'deleting'
1611e5dd7070Spatrick // destructor, which calls the complete destructor and then uses the
1612e5dd7070Spatrick // appropriate operator delete.
1613e5dd7070Spatrick if (D->isVirtual())
1614e5dd7070Spatrick CGM.EmitGlobal(GlobalDecl(D, Dtor_Deleting));
1615e5dd7070Spatrick }
1616e5dd7070Spatrick
addImplicitStructorParams(CodeGenFunction & CGF,QualType & ResTy,FunctionArgList & Params)1617e5dd7070Spatrick void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
1618e5dd7070Spatrick QualType &ResTy,
1619e5dd7070Spatrick FunctionArgList &Params) {
1620e5dd7070Spatrick const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
1621e5dd7070Spatrick assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
1622e5dd7070Spatrick
1623e5dd7070Spatrick // Check if we need a VTT parameter as well.
1624e5dd7070Spatrick if (NeedsVTTParameter(CGF.CurGD)) {
1625e5dd7070Spatrick ASTContext &Context = getContext();
1626e5dd7070Spatrick
1627e5dd7070Spatrick // FIXME: avoid the fake decl
1628e5dd7070Spatrick QualType T = Context.getPointerType(Context.VoidPtrTy);
1629e5dd7070Spatrick auto *VTTDecl = ImplicitParamDecl::Create(
1630e5dd7070Spatrick Context, /*DC=*/nullptr, MD->getLocation(), &Context.Idents.get("vtt"),
1631e5dd7070Spatrick T, ImplicitParamDecl::CXXVTT);
1632e5dd7070Spatrick Params.insert(Params.begin() + 1, VTTDecl);
1633e5dd7070Spatrick getStructorImplicitParamDecl(CGF) = VTTDecl;
1634e5dd7070Spatrick }
1635e5dd7070Spatrick }
1636e5dd7070Spatrick
EmitInstanceFunctionProlog(CodeGenFunction & CGF)1637e5dd7070Spatrick void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
1638e5dd7070Spatrick // Naked functions have no prolog.
1639e5dd7070Spatrick if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>())
1640e5dd7070Spatrick return;
1641e5dd7070Spatrick
1642e5dd7070Spatrick /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
1643e5dd7070Spatrick /// adjustments are required, because they are all handled by thunks.
1644e5dd7070Spatrick setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
1645e5dd7070Spatrick
1646e5dd7070Spatrick /// Initialize the 'vtt' slot if needed.
1647e5dd7070Spatrick if (getStructorImplicitParamDecl(CGF)) {
1648e5dd7070Spatrick getStructorImplicitParamValue(CGF) = CGF.Builder.CreateLoad(
1649e5dd7070Spatrick CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), "vtt");
1650e5dd7070Spatrick }
1651e5dd7070Spatrick
1652e5dd7070Spatrick /// If this is a function that the ABI specifies returns 'this', initialize
1653e5dd7070Spatrick /// the return slot to 'this' at the start of the function.
1654e5dd7070Spatrick ///
1655e5dd7070Spatrick /// Unlike the setting of return types, this is done within the ABI
1656e5dd7070Spatrick /// implementation instead of by clients of CGCXXABI because:
1657e5dd7070Spatrick /// 1) getThisValue is currently protected
1658e5dd7070Spatrick /// 2) in theory, an ABI could implement 'this' returns some other way;
1659e5dd7070Spatrick /// HasThisReturn only specifies a contract, not the implementation
1660e5dd7070Spatrick if (HasThisReturn(CGF.CurGD))
1661e5dd7070Spatrick CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
1662e5dd7070Spatrick }
1663e5dd7070Spatrick
getImplicitConstructorArgs(CodeGenFunction & CGF,const CXXConstructorDecl * D,CXXCtorType Type,bool ForVirtualBase,bool Delegating)1664ec727ea7Spatrick CGCXXABI::AddedStructorArgs ItaniumCXXABI::getImplicitConstructorArgs(
1665e5dd7070Spatrick CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
1666ec727ea7Spatrick bool ForVirtualBase, bool Delegating) {
1667e5dd7070Spatrick if (!NeedsVTTParameter(GlobalDecl(D, Type)))
1668e5dd7070Spatrick return AddedStructorArgs{};
1669e5dd7070Spatrick
1670e5dd7070Spatrick // Insert the implicit 'vtt' argument as the second argument.
1671e5dd7070Spatrick llvm::Value *VTT =
1672e5dd7070Spatrick CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, Delegating);
1673e5dd7070Spatrick QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1674ec727ea7Spatrick return AddedStructorArgs::prefix({{VTT, VTTTy}});
1675ec727ea7Spatrick }
1676ec727ea7Spatrick
getCXXDestructorImplicitParam(CodeGenFunction & CGF,const CXXDestructorDecl * DD,CXXDtorType Type,bool ForVirtualBase,bool Delegating)1677ec727ea7Spatrick llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(
1678ec727ea7Spatrick CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type,
1679ec727ea7Spatrick bool ForVirtualBase, bool Delegating) {
1680ec727ea7Spatrick GlobalDecl GD(DD, Type);
1681ec727ea7Spatrick return CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);
1682e5dd7070Spatrick }
1683e5dd7070Spatrick
EmitDestructorCall(CodeGenFunction & CGF,const CXXDestructorDecl * DD,CXXDtorType Type,bool ForVirtualBase,bool Delegating,Address This,QualType ThisTy)1684e5dd7070Spatrick void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
1685e5dd7070Spatrick const CXXDestructorDecl *DD,
1686e5dd7070Spatrick CXXDtorType Type, bool ForVirtualBase,
1687e5dd7070Spatrick bool Delegating, Address This,
1688e5dd7070Spatrick QualType ThisTy) {
1689e5dd7070Spatrick GlobalDecl GD(DD, Type);
1690ec727ea7Spatrick llvm::Value *VTT =
1691ec727ea7Spatrick getCXXDestructorImplicitParam(CGF, DD, Type, ForVirtualBase, Delegating);
1692e5dd7070Spatrick QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1693e5dd7070Spatrick
1694e5dd7070Spatrick CGCallee Callee;
1695e5dd7070Spatrick if (getContext().getLangOpts().AppleKext &&
1696e5dd7070Spatrick Type != Dtor_Base && DD->isVirtual())
1697e5dd7070Spatrick Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent());
1698e5dd7070Spatrick else
1699e5dd7070Spatrick Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD);
1700e5dd7070Spatrick
1701e5dd7070Spatrick CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy,
1702e5dd7070Spatrick nullptr);
1703e5dd7070Spatrick }
1704e5dd7070Spatrick
emitVTableDefinitions(CodeGenVTables & CGVT,const CXXRecordDecl * RD)1705e5dd7070Spatrick void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
1706e5dd7070Spatrick const CXXRecordDecl *RD) {
1707e5dd7070Spatrick llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits());
1708e5dd7070Spatrick if (VTable->hasInitializer())
1709e5dd7070Spatrick return;
1710e5dd7070Spatrick
1711e5dd7070Spatrick ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
1712e5dd7070Spatrick const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
1713e5dd7070Spatrick llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
1714e5dd7070Spatrick llvm::Constant *RTTI =
1715e5dd7070Spatrick CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
1716e5dd7070Spatrick
1717e5dd7070Spatrick // Create and set the initializer.
1718ec727ea7Spatrick ConstantInitBuilder builder(CGM);
1719ec727ea7Spatrick auto components = builder.beginStruct();
1720ec727ea7Spatrick CGVT.createVTableInitializer(components, VTLayout, RTTI,
1721ec727ea7Spatrick llvm::GlobalValue::isLocalLinkage(Linkage));
1722ec727ea7Spatrick components.finishAndSetAsInitializer(VTable);
1723e5dd7070Spatrick
1724e5dd7070Spatrick // Set the correct linkage.
1725e5dd7070Spatrick VTable->setLinkage(Linkage);
1726e5dd7070Spatrick
1727e5dd7070Spatrick if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
1728e5dd7070Spatrick VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
1729e5dd7070Spatrick
1730e5dd7070Spatrick // Set the right visibility.
1731e5dd7070Spatrick CGM.setGVProperties(VTable, RD);
1732e5dd7070Spatrick
1733e5dd7070Spatrick // If this is the magic class __cxxabiv1::__fundamental_type_info,
1734e5dd7070Spatrick // we will emit the typeinfo for the fundamental types. This is the
1735e5dd7070Spatrick // same behaviour as GCC.
1736e5dd7070Spatrick const DeclContext *DC = RD->getDeclContext();
1737e5dd7070Spatrick if (RD->getIdentifier() &&
1738e5dd7070Spatrick RD->getIdentifier()->isStr("__fundamental_type_info") &&
1739e5dd7070Spatrick isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
1740e5dd7070Spatrick cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
1741e5dd7070Spatrick DC->getParent()->isTranslationUnit())
1742e5dd7070Spatrick EmitFundamentalRTTIDescriptors(RD);
1743e5dd7070Spatrick
1744a9ac8606Spatrick // Always emit type metadata on non-available_externally definitions, and on
1745a9ac8606Spatrick // available_externally definitions if we are performing whole program
1746a9ac8606Spatrick // devirtualization. For WPD we need the type metadata on all vtable
1747a9ac8606Spatrick // definitions to ensure we associate derived classes with base classes
1748a9ac8606Spatrick // defined in headers but with a strong definition only in a shared library.
1749a9ac8606Spatrick if (!VTable->isDeclarationForLinker() ||
1750a9ac8606Spatrick CGM.getCodeGenOpts().WholeProgramVTables) {
1751e5dd7070Spatrick CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
1752a9ac8606Spatrick // For available_externally definitions, add the vtable to
1753a9ac8606Spatrick // @llvm.compiler.used so that it isn't deleted before whole program
1754a9ac8606Spatrick // analysis.
1755a9ac8606Spatrick if (VTable->isDeclarationForLinker()) {
1756a9ac8606Spatrick assert(CGM.getCodeGenOpts().WholeProgramVTables);
1757a9ac8606Spatrick CGM.addCompilerUsedGlobal(VTable);
1758a9ac8606Spatrick }
1759a9ac8606Spatrick }
1760ec727ea7Spatrick
1761*12c85518Srobert if (VTContext.isRelativeLayout()) {
1762*12c85518Srobert CGVT.RemoveHwasanMetadata(VTable);
1763*12c85518Srobert if (!VTable->isDSOLocal())
1764ec727ea7Spatrick CGVT.GenerateRelativeVTableAlias(VTable, VTable->getName());
1765e5dd7070Spatrick }
1766*12c85518Srobert }
1767e5dd7070Spatrick
isVirtualOffsetNeededForVTableField(CodeGenFunction & CGF,CodeGenFunction::VPtr Vptr)1768e5dd7070Spatrick bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
1769e5dd7070Spatrick CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
1770e5dd7070Spatrick if (Vptr.NearestVBase == nullptr)
1771e5dd7070Spatrick return false;
1772e5dd7070Spatrick return NeedsVTTParameter(CGF.CurGD);
1773e5dd7070Spatrick }
1774e5dd7070Spatrick
getVTableAddressPointInStructor(CodeGenFunction & CGF,const CXXRecordDecl * VTableClass,BaseSubobject Base,const CXXRecordDecl * NearestVBase)1775e5dd7070Spatrick llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
1776e5dd7070Spatrick CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
1777e5dd7070Spatrick const CXXRecordDecl *NearestVBase) {
1778e5dd7070Spatrick
1779e5dd7070Spatrick if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
1780e5dd7070Spatrick NeedsVTTParameter(CGF.CurGD)) {
1781e5dd7070Spatrick return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base,
1782e5dd7070Spatrick NearestVBase);
1783e5dd7070Spatrick }
1784e5dd7070Spatrick return getVTableAddressPoint(Base, VTableClass);
1785e5dd7070Spatrick }
1786e5dd7070Spatrick
1787e5dd7070Spatrick llvm::Constant *
getVTableAddressPoint(BaseSubobject Base,const CXXRecordDecl * VTableClass)1788e5dd7070Spatrick ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
1789e5dd7070Spatrick const CXXRecordDecl *VTableClass) {
1790e5dd7070Spatrick llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());
1791e5dd7070Spatrick
1792e5dd7070Spatrick // Find the appropriate vtable within the vtable group, and the address point
1793e5dd7070Spatrick // within that vtable.
1794e5dd7070Spatrick VTableLayout::AddressPointLocation AddressPoint =
1795e5dd7070Spatrick CGM.getItaniumVTableContext()
1796e5dd7070Spatrick .getVTableLayout(VTableClass)
1797e5dd7070Spatrick .getAddressPoint(Base);
1798e5dd7070Spatrick llvm::Value *Indices[] = {
1799e5dd7070Spatrick llvm::ConstantInt::get(CGM.Int32Ty, 0),
1800e5dd7070Spatrick llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
1801e5dd7070Spatrick llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
1802e5dd7070Spatrick };
1803e5dd7070Spatrick
1804e5dd7070Spatrick return llvm::ConstantExpr::getGetElementPtr(VTable->getValueType(), VTable,
1805e5dd7070Spatrick Indices, /*InBounds=*/true,
1806e5dd7070Spatrick /*InRangeIndex=*/1);
1807e5dd7070Spatrick }
1808e5dd7070Spatrick
1809a9ac8606Spatrick // Check whether all the non-inline virtual methods for the class have the
1810a9ac8606Spatrick // specified attribute.
1811a9ac8606Spatrick template <typename T>
CXXRecordAllNonInlineVirtualsHaveAttr(const CXXRecordDecl * RD)1812a9ac8606Spatrick static bool CXXRecordAllNonInlineVirtualsHaveAttr(const CXXRecordDecl *RD) {
1813a9ac8606Spatrick bool FoundNonInlineVirtualMethodWithAttr = false;
1814a9ac8606Spatrick for (const auto *D : RD->noload_decls()) {
1815a9ac8606Spatrick if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
1816a9ac8606Spatrick if (!FD->isVirtualAsWritten() || FD->isInlineSpecified() ||
1817a9ac8606Spatrick FD->doesThisDeclarationHaveABody())
1818a9ac8606Spatrick continue;
1819a9ac8606Spatrick if (!D->hasAttr<T>())
1820a9ac8606Spatrick return false;
1821a9ac8606Spatrick FoundNonInlineVirtualMethodWithAttr = true;
1822a9ac8606Spatrick }
1823a9ac8606Spatrick }
1824a9ac8606Spatrick
1825a9ac8606Spatrick // We didn't find any non-inline virtual methods missing the attribute. We
1826a9ac8606Spatrick // will return true when we found at least one non-inline virtual with the
1827a9ac8606Spatrick // attribute. (This lets our caller know that the attribute needs to be
1828a9ac8606Spatrick // propagated up to the vtable.)
1829a9ac8606Spatrick return FoundNonInlineVirtualMethodWithAttr;
1830a9ac8606Spatrick }
1831a9ac8606Spatrick
getVTableAddressPointInStructorWithVTT(CodeGenFunction & CGF,const CXXRecordDecl * VTableClass,BaseSubobject Base,const CXXRecordDecl * NearestVBase)1832e5dd7070Spatrick llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
1833e5dd7070Spatrick CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
1834e5dd7070Spatrick const CXXRecordDecl *NearestVBase) {
1835e5dd7070Spatrick assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
1836e5dd7070Spatrick NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT");
1837e5dd7070Spatrick
1838e5dd7070Spatrick // Get the secondary vpointer index.
1839e5dd7070Spatrick uint64_t VirtualPointerIndex =
1840e5dd7070Spatrick CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
1841e5dd7070Spatrick
1842e5dd7070Spatrick /// Load the VTT.
1843e5dd7070Spatrick llvm::Value *VTT = CGF.LoadCXXVTT();
1844e5dd7070Spatrick if (VirtualPointerIndex)
1845a9ac8606Spatrick VTT = CGF.Builder.CreateConstInBoundsGEP1_64(
1846a9ac8606Spatrick CGF.VoidPtrTy, VTT, VirtualPointerIndex);
1847e5dd7070Spatrick
1848e5dd7070Spatrick // And load the address point from the VTT.
1849a9ac8606Spatrick return CGF.Builder.CreateAlignedLoad(CGF.VoidPtrTy, VTT,
1850a9ac8606Spatrick CGF.getPointerAlign());
1851e5dd7070Spatrick }
1852e5dd7070Spatrick
getVTableAddressPointForConstExpr(BaseSubobject Base,const CXXRecordDecl * VTableClass)1853e5dd7070Spatrick llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
1854e5dd7070Spatrick BaseSubobject Base, const CXXRecordDecl *VTableClass) {
1855e5dd7070Spatrick return getVTableAddressPoint(Base, VTableClass);
1856e5dd7070Spatrick }
1857e5dd7070Spatrick
getAddrOfVTable(const CXXRecordDecl * RD,CharUnits VPtrOffset)1858e5dd7070Spatrick llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
1859e5dd7070Spatrick CharUnits VPtrOffset) {
1860e5dd7070Spatrick assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
1861e5dd7070Spatrick
1862e5dd7070Spatrick llvm::GlobalVariable *&VTable = VTables[RD];
1863e5dd7070Spatrick if (VTable)
1864e5dd7070Spatrick return VTable;
1865e5dd7070Spatrick
1866e5dd7070Spatrick // Queue up this vtable for possible deferred emission.
1867e5dd7070Spatrick CGM.addDeferredVTable(RD);
1868e5dd7070Spatrick
1869e5dd7070Spatrick SmallString<256> Name;
1870e5dd7070Spatrick llvm::raw_svector_ostream Out(Name);
1871e5dd7070Spatrick getMangleContext().mangleCXXVTable(RD, Out);
1872e5dd7070Spatrick
1873e5dd7070Spatrick const VTableLayout &VTLayout =
1874e5dd7070Spatrick CGM.getItaniumVTableContext().getVTableLayout(RD);
1875e5dd7070Spatrick llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
1876e5dd7070Spatrick
1877e5dd7070Spatrick // Use pointer alignment for the vtable. Otherwise we would align them based
1878e5dd7070Spatrick // on the size of the initializer which doesn't make sense as only single
1879e5dd7070Spatrick // values are read.
1880ec727ea7Spatrick unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()
1881ec727ea7Spatrick ? 32
1882*12c85518Srobert : CGM.getTarget().getPointerAlign(LangAS::Default);
1883e5dd7070Spatrick
1884e5dd7070Spatrick VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
1885e5dd7070Spatrick Name, VTableType, llvm::GlobalValue::ExternalLinkage,
1886*12c85518Srobert getContext().toCharUnitsFromBits(PAlign).getAsAlign());
1887e5dd7070Spatrick VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1888e5dd7070Spatrick
1889a9ac8606Spatrick // In MS C++ if you have a class with virtual functions in which you are using
1890a9ac8606Spatrick // selective member import/export, then all virtual functions must be exported
1891a9ac8606Spatrick // unless they are inline, otherwise a link error will result. To match this
1892a9ac8606Spatrick // behavior, for such classes, we dllimport the vtable if it is defined
1893a9ac8606Spatrick // externally and all the non-inline virtual methods are marked dllimport, and
1894a9ac8606Spatrick // we dllexport the vtable if it is defined in this TU and all the non-inline
1895a9ac8606Spatrick // virtual methods are marked dllexport.
1896a9ac8606Spatrick if (CGM.getTarget().hasPS4DLLImportExport()) {
1897a9ac8606Spatrick if ((!RD->hasAttr<DLLImportAttr>()) && (!RD->hasAttr<DLLExportAttr>())) {
1898a9ac8606Spatrick if (CGM.getVTables().isVTableExternal(RD)) {
1899a9ac8606Spatrick if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD))
1900a9ac8606Spatrick VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
1901a9ac8606Spatrick } else {
1902a9ac8606Spatrick if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD))
1903a9ac8606Spatrick VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1904a9ac8606Spatrick }
1905a9ac8606Spatrick }
1906a9ac8606Spatrick }
1907e5dd7070Spatrick CGM.setGVProperties(VTable, RD);
1908e5dd7070Spatrick
1909e5dd7070Spatrick return VTable;
1910e5dd7070Spatrick }
1911e5dd7070Spatrick
getVirtualFunctionPointer(CodeGenFunction & CGF,GlobalDecl GD,Address This,llvm::Type * Ty,SourceLocation Loc)1912e5dd7070Spatrick CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
1913e5dd7070Spatrick GlobalDecl GD,
1914e5dd7070Spatrick Address This,
1915e5dd7070Spatrick llvm::Type *Ty,
1916e5dd7070Spatrick SourceLocation Loc) {
1917a9ac8606Spatrick llvm::Type *TyPtr = Ty->getPointerTo();
1918e5dd7070Spatrick auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
1919ec727ea7Spatrick llvm::Value *VTable = CGF.GetVTablePtr(
1920a9ac8606Spatrick This, TyPtr->getPointerTo(), MethodDecl->getParent());
1921e5dd7070Spatrick
1922e5dd7070Spatrick uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
1923e5dd7070Spatrick llvm::Value *VFunc;
1924e5dd7070Spatrick if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) {
1925e5dd7070Spatrick VFunc = CGF.EmitVTableTypeCheckedLoad(
1926*12c85518Srobert MethodDecl->getParent(), VTable, TyPtr,
1927*12c85518Srobert VTableIndex *
1928*12c85518Srobert CGM.getContext().getTargetInfo().getPointerWidth(LangAS::Default) /
1929*12c85518Srobert 8);
1930e5dd7070Spatrick } else {
1931e5dd7070Spatrick CGF.EmitTypeMetadataCodeForVCall(MethodDecl->getParent(), VTable, Loc);
1932e5dd7070Spatrick
1933ec727ea7Spatrick llvm::Value *VFuncLoad;
1934ec727ea7Spatrick if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1935ec727ea7Spatrick VTable = CGF.Builder.CreateBitCast(VTable, CGM.Int8PtrTy);
1936ec727ea7Spatrick llvm::Value *Load = CGF.Builder.CreateCall(
1937ec727ea7Spatrick CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1938ec727ea7Spatrick {VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)});
1939a9ac8606Spatrick VFuncLoad = CGF.Builder.CreateBitCast(Load, TyPtr);
1940ec727ea7Spatrick } else {
1941ec727ea7Spatrick VTable =
1942a9ac8606Spatrick CGF.Builder.CreateBitCast(VTable, TyPtr->getPointerTo());
1943a9ac8606Spatrick llvm::Value *VTableSlotPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
1944a9ac8606Spatrick TyPtr, VTable, VTableIndex, "vfn");
1945ec727ea7Spatrick VFuncLoad =
1946a9ac8606Spatrick CGF.Builder.CreateAlignedLoad(TyPtr, VTableSlotPtr,
1947a9ac8606Spatrick CGF.getPointerAlign());
1948ec727ea7Spatrick }
1949e5dd7070Spatrick
1950e5dd7070Spatrick // Add !invariant.load md to virtual function load to indicate that
1951e5dd7070Spatrick // function didn't change inside vtable.
1952e5dd7070Spatrick // It's safe to add it without -fstrict-vtable-pointers, but it would not
1953e5dd7070Spatrick // help in devirtualization because it will only matter if we will have 2
1954e5dd7070Spatrick // the same virtual function loads from the same vtable load, which won't
1955e5dd7070Spatrick // happen without enabled devirtualization with -fstrict-vtable-pointers.
1956e5dd7070Spatrick if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1957ec727ea7Spatrick CGM.getCodeGenOpts().StrictVTablePointers) {
1958ec727ea7Spatrick if (auto *VFuncLoadInstr = dyn_cast<llvm::Instruction>(VFuncLoad)) {
1959ec727ea7Spatrick VFuncLoadInstr->setMetadata(
1960e5dd7070Spatrick llvm::LLVMContext::MD_invariant_load,
1961e5dd7070Spatrick llvm::MDNode::get(CGM.getLLVMContext(),
1962e5dd7070Spatrick llvm::ArrayRef<llvm::Metadata *>()));
1963ec727ea7Spatrick }
1964ec727ea7Spatrick }
1965e5dd7070Spatrick VFunc = VFuncLoad;
1966e5dd7070Spatrick }
1967e5dd7070Spatrick
1968e5dd7070Spatrick CGCallee Callee(GD, VFunc);
1969e5dd7070Spatrick return Callee;
1970e5dd7070Spatrick }
1971e5dd7070Spatrick
EmitVirtualDestructorCall(CodeGenFunction & CGF,const CXXDestructorDecl * Dtor,CXXDtorType DtorType,Address This,DeleteOrMemberCallExpr E)1972e5dd7070Spatrick llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
1973e5dd7070Spatrick CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
1974e5dd7070Spatrick Address This, DeleteOrMemberCallExpr E) {
1975e5dd7070Spatrick auto *CE = E.dyn_cast<const CXXMemberCallExpr *>();
1976e5dd7070Spatrick auto *D = E.dyn_cast<const CXXDeleteExpr *>();
1977e5dd7070Spatrick assert((CE != nullptr) ^ (D != nullptr));
1978e5dd7070Spatrick assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
1979e5dd7070Spatrick assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
1980e5dd7070Spatrick
1981e5dd7070Spatrick GlobalDecl GD(Dtor, DtorType);
1982e5dd7070Spatrick const CGFunctionInfo *FInfo =
1983e5dd7070Spatrick &CGM.getTypes().arrangeCXXStructorDeclaration(GD);
1984e5dd7070Spatrick llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
1985e5dd7070Spatrick CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty);
1986e5dd7070Spatrick
1987e5dd7070Spatrick QualType ThisTy;
1988e5dd7070Spatrick if (CE) {
1989e5dd7070Spatrick ThisTy = CE->getObjectType();
1990e5dd7070Spatrick } else {
1991e5dd7070Spatrick ThisTy = D->getDestroyedType();
1992e5dd7070Spatrick }
1993e5dd7070Spatrick
1994e5dd7070Spatrick CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr,
1995e5dd7070Spatrick QualType(), nullptr);
1996e5dd7070Spatrick return nullptr;
1997e5dd7070Spatrick }
1998e5dd7070Spatrick
emitVirtualInheritanceTables(const CXXRecordDecl * RD)1999e5dd7070Spatrick void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
2000e5dd7070Spatrick CodeGenVTables &VTables = CGM.getVTables();
2001e5dd7070Spatrick llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD);
2002e5dd7070Spatrick VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
2003e5dd7070Spatrick }
2004e5dd7070Spatrick
canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl * RD) const2005e5dd7070Spatrick bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
2006e5dd7070Spatrick const CXXRecordDecl *RD) const {
2007e5dd7070Spatrick // We don't emit available_externally vtables if we are in -fapple-kext mode
2008e5dd7070Spatrick // because kext mode does not permit devirtualization.
2009e5dd7070Spatrick if (CGM.getLangOpts().AppleKext)
2010e5dd7070Spatrick return false;
2011e5dd7070Spatrick
2012e5dd7070Spatrick // If the vtable is hidden then it is not safe to emit an available_externally
2013e5dd7070Spatrick // copy of vtable.
2014e5dd7070Spatrick if (isVTableHidden(RD))
2015e5dd7070Spatrick return false;
2016e5dd7070Spatrick
2017e5dd7070Spatrick if (CGM.getCodeGenOpts().ForceEmitVTables)
2018e5dd7070Spatrick return true;
2019e5dd7070Spatrick
2020e5dd7070Spatrick // If we don't have any not emitted inline virtual function then we are safe
2021e5dd7070Spatrick // to emit an available_externally copy of vtable.
2022e5dd7070Spatrick // FIXME we can still emit a copy of the vtable if we
2023e5dd7070Spatrick // can emit definition of the inline functions.
2024e5dd7070Spatrick if (hasAnyUnusedVirtualInlineFunction(RD))
2025e5dd7070Spatrick return false;
2026e5dd7070Spatrick
2027e5dd7070Spatrick // For a class with virtual bases, we must also be able to speculatively
2028e5dd7070Spatrick // emit the VTT, because CodeGen doesn't have separate notions of "can emit
2029e5dd7070Spatrick // the vtable" and "can emit the VTT". For a base subobject, this means we
2030e5dd7070Spatrick // need to be able to emit non-virtual base vtables.
2031e5dd7070Spatrick if (RD->getNumVBases()) {
2032e5dd7070Spatrick for (const auto &B : RD->bases()) {
2033e5dd7070Spatrick auto *BRD = B.getType()->getAsCXXRecordDecl();
2034e5dd7070Spatrick assert(BRD && "no class for base specifier");
2035e5dd7070Spatrick if (B.isVirtual() || !BRD->isDynamicClass())
2036e5dd7070Spatrick continue;
2037e5dd7070Spatrick if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2038e5dd7070Spatrick return false;
2039e5dd7070Spatrick }
2040e5dd7070Spatrick }
2041e5dd7070Spatrick
2042e5dd7070Spatrick return true;
2043e5dd7070Spatrick }
2044e5dd7070Spatrick
canSpeculativelyEmitVTable(const CXXRecordDecl * RD) const2045e5dd7070Spatrick bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
2046e5dd7070Spatrick if (!canSpeculativelyEmitVTableAsBaseClass(RD))
2047e5dd7070Spatrick return false;
2048e5dd7070Spatrick
2049e5dd7070Spatrick // For a complete-object vtable (or more specifically, for the VTT), we need
2050e5dd7070Spatrick // to be able to speculatively emit the vtables of all dynamic virtual bases.
2051e5dd7070Spatrick for (const auto &B : RD->vbases()) {
2052e5dd7070Spatrick auto *BRD = B.getType()->getAsCXXRecordDecl();
2053e5dd7070Spatrick assert(BRD && "no class for base specifier");
2054e5dd7070Spatrick if (!BRD->isDynamicClass())
2055e5dd7070Spatrick continue;
2056e5dd7070Spatrick if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2057e5dd7070Spatrick return false;
2058e5dd7070Spatrick }
2059e5dd7070Spatrick
2060e5dd7070Spatrick return true;
2061e5dd7070Spatrick }
performTypeAdjustment(CodeGenFunction & CGF,Address InitialPtr,int64_t NonVirtualAdjustment,int64_t VirtualAdjustment,bool IsReturnAdjustment)2062e5dd7070Spatrick static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
2063e5dd7070Spatrick Address InitialPtr,
2064e5dd7070Spatrick int64_t NonVirtualAdjustment,
2065e5dd7070Spatrick int64_t VirtualAdjustment,
2066e5dd7070Spatrick bool IsReturnAdjustment) {
2067e5dd7070Spatrick if (!NonVirtualAdjustment && !VirtualAdjustment)
2068e5dd7070Spatrick return InitialPtr.getPointer();
2069e5dd7070Spatrick
2070e5dd7070Spatrick Address V = CGF.Builder.CreateElementBitCast(InitialPtr, CGF.Int8Ty);
2071e5dd7070Spatrick
2072e5dd7070Spatrick // In a base-to-derived cast, the non-virtual adjustment is applied first.
2073e5dd7070Spatrick if (NonVirtualAdjustment && !IsReturnAdjustment) {
2074e5dd7070Spatrick V = CGF.Builder.CreateConstInBoundsByteGEP(V,
2075e5dd7070Spatrick CharUnits::fromQuantity(NonVirtualAdjustment));
2076e5dd7070Spatrick }
2077e5dd7070Spatrick
2078e5dd7070Spatrick // Perform the virtual adjustment if we have one.
2079e5dd7070Spatrick llvm::Value *ResultPtr;
2080e5dd7070Spatrick if (VirtualAdjustment) {
2081e5dd7070Spatrick Address VTablePtrPtr = CGF.Builder.CreateElementBitCast(V, CGF.Int8PtrTy);
2082e5dd7070Spatrick llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr);
2083e5dd7070Spatrick
2084ec727ea7Spatrick llvm::Value *Offset;
2085a9ac8606Spatrick llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
2086a9ac8606Spatrick CGF.Int8Ty, VTablePtr, VirtualAdjustment);
2087ec727ea7Spatrick if (CGF.CGM.getItaniumVTableContext().isRelativeLayout()) {
2088ec727ea7Spatrick // Load the adjustment offset from the vtable as a 32-bit int.
2089ec727ea7Spatrick OffsetPtr =
2090ec727ea7Spatrick CGF.Builder.CreateBitCast(OffsetPtr, CGF.Int32Ty->getPointerTo());
2091ec727ea7Spatrick Offset =
2092a9ac8606Spatrick CGF.Builder.CreateAlignedLoad(CGF.Int32Ty, OffsetPtr,
2093a9ac8606Spatrick CharUnits::fromQuantity(4));
2094ec727ea7Spatrick } else {
2095ec727ea7Spatrick llvm::Type *PtrDiffTy =
2096ec727ea7Spatrick CGF.ConvertType(CGF.getContext().getPointerDiffType());
2097e5dd7070Spatrick
2098ec727ea7Spatrick OffsetPtr =
2099ec727ea7Spatrick CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo());
2100e5dd7070Spatrick
2101e5dd7070Spatrick // Load the adjustment offset from the vtable.
2102a9ac8606Spatrick Offset = CGF.Builder.CreateAlignedLoad(PtrDiffTy, OffsetPtr,
2103a9ac8606Spatrick CGF.getPointerAlign());
2104ec727ea7Spatrick }
2105e5dd7070Spatrick // Adjust our pointer.
2106a9ac8606Spatrick ResultPtr = CGF.Builder.CreateInBoundsGEP(
2107a9ac8606Spatrick V.getElementType(), V.getPointer(), Offset);
2108e5dd7070Spatrick } else {
2109e5dd7070Spatrick ResultPtr = V.getPointer();
2110e5dd7070Spatrick }
2111e5dd7070Spatrick
2112e5dd7070Spatrick // In a derived-to-base conversion, the non-virtual adjustment is
2113e5dd7070Spatrick // applied second.
2114e5dd7070Spatrick if (NonVirtualAdjustment && IsReturnAdjustment) {
2115a9ac8606Spatrick ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.Int8Ty, ResultPtr,
2116e5dd7070Spatrick NonVirtualAdjustment);
2117e5dd7070Spatrick }
2118e5dd7070Spatrick
2119e5dd7070Spatrick // Cast back to the original type.
2120e5dd7070Spatrick return CGF.Builder.CreateBitCast(ResultPtr, InitialPtr.getType());
2121e5dd7070Spatrick }
2122e5dd7070Spatrick
performThisAdjustment(CodeGenFunction & CGF,Address This,const ThisAdjustment & TA)2123e5dd7070Spatrick llvm::Value *ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF,
2124e5dd7070Spatrick Address This,
2125e5dd7070Spatrick const ThisAdjustment &TA) {
2126e5dd7070Spatrick return performTypeAdjustment(CGF, This, TA.NonVirtual,
2127e5dd7070Spatrick TA.Virtual.Itanium.VCallOffsetOffset,
2128e5dd7070Spatrick /*IsReturnAdjustment=*/false);
2129e5dd7070Spatrick }
2130e5dd7070Spatrick
2131e5dd7070Spatrick llvm::Value *
performReturnAdjustment(CodeGenFunction & CGF,Address Ret,const ReturnAdjustment & RA)2132e5dd7070Spatrick ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
2133e5dd7070Spatrick const ReturnAdjustment &RA) {
2134e5dd7070Spatrick return performTypeAdjustment(CGF, Ret, RA.NonVirtual,
2135e5dd7070Spatrick RA.Virtual.Itanium.VBaseOffsetOffset,
2136e5dd7070Spatrick /*IsReturnAdjustment=*/true);
2137e5dd7070Spatrick }
2138e5dd7070Spatrick
EmitReturnFromThunk(CodeGenFunction & CGF,RValue RV,QualType ResultType)2139e5dd7070Spatrick void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
2140e5dd7070Spatrick RValue RV, QualType ResultType) {
2141e5dd7070Spatrick if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
2142e5dd7070Spatrick return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
2143e5dd7070Spatrick
2144e5dd7070Spatrick // Destructor thunks in the ARM ABI have indeterminate results.
2145e5dd7070Spatrick llvm::Type *T = CGF.ReturnValue.getElementType();
2146e5dd7070Spatrick RValue Undef = RValue::get(llvm::UndefValue::get(T));
2147e5dd7070Spatrick return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
2148e5dd7070Spatrick }
2149e5dd7070Spatrick
2150e5dd7070Spatrick /************************** Array allocation cookies **************************/
2151e5dd7070Spatrick
getArrayCookieSizeImpl(QualType elementType)2152e5dd7070Spatrick CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2153e5dd7070Spatrick // The array cookie is a size_t; pad that up to the element alignment.
2154e5dd7070Spatrick // The cookie is actually right-justified in that space.
2155e5dd7070Spatrick return std::max(CharUnits::fromQuantity(CGM.SizeSizeInBytes),
2156a9ac8606Spatrick CGM.getContext().getPreferredTypeAlignInChars(elementType));
2157e5dd7070Spatrick }
2158e5dd7070Spatrick
InitializeArrayCookie(CodeGenFunction & CGF,Address NewPtr,llvm::Value * NumElements,const CXXNewExpr * expr,QualType ElementType)2159e5dd7070Spatrick Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
2160e5dd7070Spatrick Address NewPtr,
2161e5dd7070Spatrick llvm::Value *NumElements,
2162e5dd7070Spatrick const CXXNewExpr *expr,
2163e5dd7070Spatrick QualType ElementType) {
2164e5dd7070Spatrick assert(requiresArrayCookie(expr));
2165e5dd7070Spatrick
2166e5dd7070Spatrick unsigned AS = NewPtr.getAddressSpace();
2167e5dd7070Spatrick
2168e5dd7070Spatrick ASTContext &Ctx = getContext();
2169e5dd7070Spatrick CharUnits SizeSize = CGF.getSizeSize();
2170e5dd7070Spatrick
2171e5dd7070Spatrick // The size of the cookie.
2172e5dd7070Spatrick CharUnits CookieSize =
2173a9ac8606Spatrick std::max(SizeSize, Ctx.getPreferredTypeAlignInChars(ElementType));
2174e5dd7070Spatrick assert(CookieSize == getArrayCookieSizeImpl(ElementType));
2175e5dd7070Spatrick
2176e5dd7070Spatrick // Compute an offset to the cookie.
2177e5dd7070Spatrick Address CookiePtr = NewPtr;
2178e5dd7070Spatrick CharUnits CookieOffset = CookieSize - SizeSize;
2179e5dd7070Spatrick if (!CookieOffset.isZero())
2180e5dd7070Spatrick CookiePtr = CGF.Builder.CreateConstInBoundsByteGEP(CookiePtr, CookieOffset);
2181e5dd7070Spatrick
2182e5dd7070Spatrick // Write the number of elements into the appropriate slot.
2183e5dd7070Spatrick Address NumElementsPtr =
2184e5dd7070Spatrick CGF.Builder.CreateElementBitCast(CookiePtr, CGF.SizeTy);
2185e5dd7070Spatrick llvm::Instruction *SI = CGF.Builder.CreateStore(NumElements, NumElementsPtr);
2186e5dd7070Spatrick
2187e5dd7070Spatrick // Handle the array cookie specially in ASan.
2188e5dd7070Spatrick if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
2189e5dd7070Spatrick (expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||
2190e5dd7070Spatrick CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {
2191e5dd7070Spatrick // The store to the CookiePtr does not need to be instrumented.
2192e5dd7070Spatrick CGM.getSanitizerMetadata()->disableSanitizerForInstruction(SI);
2193e5dd7070Spatrick llvm::FunctionType *FTy =
2194e5dd7070Spatrick llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false);
2195e5dd7070Spatrick llvm::FunctionCallee F =
2196e5dd7070Spatrick CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie");
2197e5dd7070Spatrick CGF.Builder.CreateCall(F, NumElementsPtr.getPointer());
2198e5dd7070Spatrick }
2199e5dd7070Spatrick
2200e5dd7070Spatrick // Finally, compute a pointer to the actual data buffer by skipping
2201e5dd7070Spatrick // over the cookie completely.
2202e5dd7070Spatrick return CGF.Builder.CreateConstInBoundsByteGEP(NewPtr, CookieSize);
2203e5dd7070Spatrick }
2204e5dd7070Spatrick
readArrayCookieImpl(CodeGenFunction & CGF,Address allocPtr,CharUnits cookieSize)2205e5dd7070Spatrick llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2206e5dd7070Spatrick Address allocPtr,
2207e5dd7070Spatrick CharUnits cookieSize) {
2208e5dd7070Spatrick // The element size is right-justified in the cookie.
2209e5dd7070Spatrick Address numElementsPtr = allocPtr;
2210e5dd7070Spatrick CharUnits numElementsOffset = cookieSize - CGF.getSizeSize();
2211e5dd7070Spatrick if (!numElementsOffset.isZero())
2212e5dd7070Spatrick numElementsPtr =
2213e5dd7070Spatrick CGF.Builder.CreateConstInBoundsByteGEP(numElementsPtr, numElementsOffset);
2214e5dd7070Spatrick
2215e5dd7070Spatrick unsigned AS = allocPtr.getAddressSpace();
2216e5dd7070Spatrick numElementsPtr = CGF.Builder.CreateElementBitCast(numElementsPtr, CGF.SizeTy);
2217e5dd7070Spatrick if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0)
2218e5dd7070Spatrick return CGF.Builder.CreateLoad(numElementsPtr);
2219e5dd7070Spatrick // In asan mode emit a function call instead of a regular load and let the
2220e5dd7070Spatrick // run-time deal with it: if the shadow is properly poisoned return the
2221e5dd7070Spatrick // cookie, otherwise return 0 to avoid an infinite loop calling DTORs.
2222e5dd7070Spatrick // We can't simply ignore this load using nosanitize metadata because
2223e5dd7070Spatrick // the metadata may be lost.
2224e5dd7070Spatrick llvm::FunctionType *FTy =
2225e5dd7070Spatrick llvm::FunctionType::get(CGF.SizeTy, CGF.SizeTy->getPointerTo(0), false);
2226e5dd7070Spatrick llvm::FunctionCallee F =
2227e5dd7070Spatrick CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie");
2228e5dd7070Spatrick return CGF.Builder.CreateCall(F, numElementsPtr.getPointer());
2229e5dd7070Spatrick }
2230e5dd7070Spatrick
getArrayCookieSizeImpl(QualType elementType)2231e5dd7070Spatrick CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2232e5dd7070Spatrick // ARM says that the cookie is always:
2233e5dd7070Spatrick // struct array_cookie {
2234e5dd7070Spatrick // std::size_t element_size; // element_size != 0
2235e5dd7070Spatrick // std::size_t element_count;
2236e5dd7070Spatrick // };
2237e5dd7070Spatrick // But the base ABI doesn't give anything an alignment greater than
2238e5dd7070Spatrick // 8, so we can dismiss this as typical ABI-author blindness to
2239e5dd7070Spatrick // actual language complexity and round up to the element alignment.
2240e5dd7070Spatrick return std::max(CharUnits::fromQuantity(2 * CGM.SizeSizeInBytes),
2241e5dd7070Spatrick CGM.getContext().getTypeAlignInChars(elementType));
2242e5dd7070Spatrick }
2243e5dd7070Spatrick
InitializeArrayCookie(CodeGenFunction & CGF,Address newPtr,llvm::Value * numElements,const CXXNewExpr * expr,QualType elementType)2244e5dd7070Spatrick Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
2245e5dd7070Spatrick Address newPtr,
2246e5dd7070Spatrick llvm::Value *numElements,
2247e5dd7070Spatrick const CXXNewExpr *expr,
2248e5dd7070Spatrick QualType elementType) {
2249e5dd7070Spatrick assert(requiresArrayCookie(expr));
2250e5dd7070Spatrick
2251e5dd7070Spatrick // The cookie is always at the start of the buffer.
2252e5dd7070Spatrick Address cookie = newPtr;
2253e5dd7070Spatrick
2254e5dd7070Spatrick // The first element is the element size.
2255e5dd7070Spatrick cookie = CGF.Builder.CreateElementBitCast(cookie, CGF.SizeTy);
2256e5dd7070Spatrick llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,
2257e5dd7070Spatrick getContext().getTypeSizeInChars(elementType).getQuantity());
2258e5dd7070Spatrick CGF.Builder.CreateStore(elementSize, cookie);
2259e5dd7070Spatrick
2260e5dd7070Spatrick // The second element is the element count.
2261e5dd7070Spatrick cookie = CGF.Builder.CreateConstInBoundsGEP(cookie, 1);
2262e5dd7070Spatrick CGF.Builder.CreateStore(numElements, cookie);
2263e5dd7070Spatrick
2264e5dd7070Spatrick // Finally, compute a pointer to the actual data buffer by skipping
2265e5dd7070Spatrick // over the cookie completely.
2266e5dd7070Spatrick CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
2267e5dd7070Spatrick return CGF.Builder.CreateConstInBoundsByteGEP(newPtr, cookieSize);
2268e5dd7070Spatrick }
2269e5dd7070Spatrick
readArrayCookieImpl(CodeGenFunction & CGF,Address allocPtr,CharUnits cookieSize)2270e5dd7070Spatrick llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2271e5dd7070Spatrick Address allocPtr,
2272e5dd7070Spatrick CharUnits cookieSize) {
2273e5dd7070Spatrick // The number of elements is at offset sizeof(size_t) relative to
2274e5dd7070Spatrick // the allocated pointer.
2275e5dd7070Spatrick Address numElementsPtr
2276e5dd7070Spatrick = CGF.Builder.CreateConstInBoundsByteGEP(allocPtr, CGF.getSizeSize());
2277e5dd7070Spatrick
2278e5dd7070Spatrick numElementsPtr = CGF.Builder.CreateElementBitCast(numElementsPtr, CGF.SizeTy);
2279e5dd7070Spatrick return CGF.Builder.CreateLoad(numElementsPtr);
2280e5dd7070Spatrick }
2281e5dd7070Spatrick
2282e5dd7070Spatrick /*********************** Static local initialization **************************/
2283e5dd7070Spatrick
getGuardAcquireFn(CodeGenModule & CGM,llvm::PointerType * GuardPtrTy)2284e5dd7070Spatrick static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM,
2285e5dd7070Spatrick llvm::PointerType *GuardPtrTy) {
2286e5dd7070Spatrick // int __cxa_guard_acquire(__guard *guard_object);
2287e5dd7070Spatrick llvm::FunctionType *FTy =
2288e5dd7070Spatrick llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy),
2289e5dd7070Spatrick GuardPtrTy, /*isVarArg=*/false);
2290e5dd7070Spatrick return CGM.CreateRuntimeFunction(
2291e5dd7070Spatrick FTy, "__cxa_guard_acquire",
2292e5dd7070Spatrick llvm::AttributeList::get(CGM.getLLVMContext(),
2293e5dd7070Spatrick llvm::AttributeList::FunctionIndex,
2294e5dd7070Spatrick llvm::Attribute::NoUnwind));
2295e5dd7070Spatrick }
2296e5dd7070Spatrick
getGuardReleaseFn(CodeGenModule & CGM,llvm::PointerType * GuardPtrTy)2297e5dd7070Spatrick static llvm::FunctionCallee getGuardReleaseFn(CodeGenModule &CGM,
2298e5dd7070Spatrick llvm::PointerType *GuardPtrTy) {
2299e5dd7070Spatrick // void __cxa_guard_release(__guard *guard_object);
2300e5dd7070Spatrick llvm::FunctionType *FTy =
2301e5dd7070Spatrick llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
2302e5dd7070Spatrick return CGM.CreateRuntimeFunction(
2303e5dd7070Spatrick FTy, "__cxa_guard_release",
2304e5dd7070Spatrick llvm::AttributeList::get(CGM.getLLVMContext(),
2305e5dd7070Spatrick llvm::AttributeList::FunctionIndex,
2306e5dd7070Spatrick llvm::Attribute::NoUnwind));
2307e5dd7070Spatrick }
2308e5dd7070Spatrick
getGuardAbortFn(CodeGenModule & CGM,llvm::PointerType * GuardPtrTy)2309e5dd7070Spatrick static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM,
2310e5dd7070Spatrick llvm::PointerType *GuardPtrTy) {
2311e5dd7070Spatrick // void __cxa_guard_abort(__guard *guard_object);
2312e5dd7070Spatrick llvm::FunctionType *FTy =
2313e5dd7070Spatrick llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
2314e5dd7070Spatrick return CGM.CreateRuntimeFunction(
2315e5dd7070Spatrick FTy, "__cxa_guard_abort",
2316e5dd7070Spatrick llvm::AttributeList::get(CGM.getLLVMContext(),
2317e5dd7070Spatrick llvm::AttributeList::FunctionIndex,
2318e5dd7070Spatrick llvm::Attribute::NoUnwind));
2319e5dd7070Spatrick }
2320e5dd7070Spatrick
2321e5dd7070Spatrick namespace {
2322e5dd7070Spatrick struct CallGuardAbort final : EHScopeStack::Cleanup {
2323e5dd7070Spatrick llvm::GlobalVariable *Guard;
CallGuardAbort__anon449188eb0211::CallGuardAbort2324e5dd7070Spatrick CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
2325e5dd7070Spatrick
Emit__anon449188eb0211::CallGuardAbort2326e5dd7070Spatrick void Emit(CodeGenFunction &CGF, Flags flags) override {
2327e5dd7070Spatrick CGF.EmitNounwindRuntimeCall(getGuardAbortFn(CGF.CGM, Guard->getType()),
2328e5dd7070Spatrick Guard);
2329e5dd7070Spatrick }
2330e5dd7070Spatrick };
2331e5dd7070Spatrick }
2332e5dd7070Spatrick
2333e5dd7070Spatrick /// The ARM code here follows the Itanium code closely enough that we
2334e5dd7070Spatrick /// just special-case it at particular places.
EmitGuardedInit(CodeGenFunction & CGF,const VarDecl & D,llvm::GlobalVariable * var,bool shouldPerformInit)2335e5dd7070Spatrick void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
2336e5dd7070Spatrick const VarDecl &D,
2337e5dd7070Spatrick llvm::GlobalVariable *var,
2338e5dd7070Spatrick bool shouldPerformInit) {
2339e5dd7070Spatrick CGBuilderTy &Builder = CGF.Builder;
2340e5dd7070Spatrick
2341e5dd7070Spatrick // Inline variables that weren't instantiated from variable templates have
2342e5dd7070Spatrick // partially-ordered initialization within their translation unit.
2343e5dd7070Spatrick bool NonTemplateInline =
2344e5dd7070Spatrick D.isInline() &&
2345e5dd7070Spatrick !isTemplateInstantiation(D.getTemplateSpecializationKind());
2346e5dd7070Spatrick
2347e5dd7070Spatrick // We only need to use thread-safe statics for local non-TLS variables and
2348e5dd7070Spatrick // inline variables; other global initialization is always single-threaded
2349e5dd7070Spatrick // or (through lazy dynamic loading in multiple threads) unsequenced.
2350e5dd7070Spatrick bool threadsafe = getContext().getLangOpts().ThreadsafeStatics &&
2351e5dd7070Spatrick (D.isLocalVarDecl() || NonTemplateInline) &&
2352e5dd7070Spatrick !D.getTLSKind();
2353e5dd7070Spatrick
2354e5dd7070Spatrick // If we have a global variable with internal linkage and thread-safe statics
2355e5dd7070Spatrick // are disabled, we can just let the guard variable be of type i8.
2356e5dd7070Spatrick bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage();
2357e5dd7070Spatrick
2358e5dd7070Spatrick llvm::IntegerType *guardTy;
2359e5dd7070Spatrick CharUnits guardAlignment;
2360e5dd7070Spatrick if (useInt8GuardVariable) {
2361e5dd7070Spatrick guardTy = CGF.Int8Ty;
2362e5dd7070Spatrick guardAlignment = CharUnits::One();
2363e5dd7070Spatrick } else {
2364e5dd7070Spatrick // Guard variables are 64 bits in the generic ABI and size width on ARM
2365e5dd7070Spatrick // (i.e. 32-bit on AArch32, 64-bit on AArch64).
2366e5dd7070Spatrick if (UseARMGuardVarABI) {
2367e5dd7070Spatrick guardTy = CGF.SizeTy;
2368e5dd7070Spatrick guardAlignment = CGF.getSizeAlign();
2369e5dd7070Spatrick } else {
2370e5dd7070Spatrick guardTy = CGF.Int64Ty;
2371*12c85518Srobert guardAlignment =
2372*12c85518Srobert CharUnits::fromQuantity(CGM.getDataLayout().getABITypeAlign(guardTy));
2373e5dd7070Spatrick }
2374e5dd7070Spatrick }
2375a9ac8606Spatrick llvm::PointerType *guardPtrTy = guardTy->getPointerTo(
2376a9ac8606Spatrick CGF.CGM.getDataLayout().getDefaultGlobalsAddressSpace());
2377e5dd7070Spatrick
2378e5dd7070Spatrick // Create the guard variable if we don't already have it (as we
2379e5dd7070Spatrick // might if we're double-emitting this function body).
2380e5dd7070Spatrick llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D);
2381e5dd7070Spatrick if (!guard) {
2382e5dd7070Spatrick // Mangle the name for the guard.
2383e5dd7070Spatrick SmallString<256> guardName;
2384e5dd7070Spatrick {
2385e5dd7070Spatrick llvm::raw_svector_ostream out(guardName);
2386e5dd7070Spatrick getMangleContext().mangleStaticGuardVariable(&D, out);
2387e5dd7070Spatrick }
2388e5dd7070Spatrick
2389e5dd7070Spatrick // Create the guard variable with a zero-initializer.
2390*12c85518Srobert // Just absorb linkage, visibility and dll storage class from the guarded
2391*12c85518Srobert // variable.
2392e5dd7070Spatrick guard = new llvm::GlobalVariable(CGM.getModule(), guardTy,
2393e5dd7070Spatrick false, var->getLinkage(),
2394e5dd7070Spatrick llvm::ConstantInt::get(guardTy, 0),
2395e5dd7070Spatrick guardName.str());
2396e5dd7070Spatrick guard->setDSOLocal(var->isDSOLocal());
2397e5dd7070Spatrick guard->setVisibility(var->getVisibility());
2398*12c85518Srobert guard->setDLLStorageClass(var->getDLLStorageClass());
2399e5dd7070Spatrick // If the variable is thread-local, so is its guard variable.
2400e5dd7070Spatrick guard->setThreadLocalMode(var->getThreadLocalMode());
2401e5dd7070Spatrick guard->setAlignment(guardAlignment.getAsAlign());
2402e5dd7070Spatrick
2403e5dd7070Spatrick // The ABI says: "It is suggested that it be emitted in the same COMDAT
2404e5dd7070Spatrick // group as the associated data object." In practice, this doesn't work for
2405e5dd7070Spatrick // non-ELF and non-Wasm object formats, so only do it for ELF and Wasm.
2406e5dd7070Spatrick llvm::Comdat *C = var->getComdat();
2407e5dd7070Spatrick if (!D.isLocalVarDecl() && C &&
2408e5dd7070Spatrick (CGM.getTarget().getTriple().isOSBinFormatELF() ||
2409e5dd7070Spatrick CGM.getTarget().getTriple().isOSBinFormatWasm())) {
2410e5dd7070Spatrick guard->setComdat(C);
2411e5dd7070Spatrick } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
2412e5dd7070Spatrick guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));
2413e5dd7070Spatrick }
2414e5dd7070Spatrick
2415e5dd7070Spatrick CGM.setStaticLocalDeclGuardAddress(&D, guard);
2416e5dd7070Spatrick }
2417e5dd7070Spatrick
2418*12c85518Srobert Address guardAddr = Address(guard, guard->getValueType(), guardAlignment);
2419e5dd7070Spatrick
2420e5dd7070Spatrick // Test whether the variable has completed initialization.
2421e5dd7070Spatrick //
2422e5dd7070Spatrick // Itanium C++ ABI 3.3.2:
2423e5dd7070Spatrick // The following is pseudo-code showing how these functions can be used:
2424e5dd7070Spatrick // if (obj_guard.first_byte == 0) {
2425e5dd7070Spatrick // if ( __cxa_guard_acquire (&obj_guard) ) {
2426e5dd7070Spatrick // try {
2427e5dd7070Spatrick // ... initialize the object ...;
2428e5dd7070Spatrick // } catch (...) {
2429e5dd7070Spatrick // __cxa_guard_abort (&obj_guard);
2430e5dd7070Spatrick // throw;
2431e5dd7070Spatrick // }
2432e5dd7070Spatrick // ... queue object destructor with __cxa_atexit() ...;
2433e5dd7070Spatrick // __cxa_guard_release (&obj_guard);
2434e5dd7070Spatrick // }
2435e5dd7070Spatrick // }
2436*12c85518Srobert //
2437*12c85518Srobert // If threadsafe statics are enabled, but we don't have inline atomics, just
2438*12c85518Srobert // call __cxa_guard_acquire unconditionally. The "inline" check isn't
2439*12c85518Srobert // actually inline, and the user might not expect calls to __atomic libcalls.
2440e5dd7070Spatrick
2441*12c85518Srobert unsigned MaxInlineWidthInBits = CGF.getTarget().getMaxAtomicInlineWidth();
2442*12c85518Srobert llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
2443*12c85518Srobert if (!threadsafe || MaxInlineWidthInBits) {
2444e5dd7070Spatrick // Load the first byte of the guard variable.
2445e5dd7070Spatrick llvm::LoadInst *LI =
2446e5dd7070Spatrick Builder.CreateLoad(Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
2447e5dd7070Spatrick
2448e5dd7070Spatrick // Itanium ABI:
2449e5dd7070Spatrick // An implementation supporting thread-safety on multiprocessor
2450e5dd7070Spatrick // systems must also guarantee that references to the initialized
2451e5dd7070Spatrick // object do not occur before the load of the initialization flag.
2452e5dd7070Spatrick //
2453e5dd7070Spatrick // In LLVM, we do this by marking the load Acquire.
2454e5dd7070Spatrick if (threadsafe)
2455e5dd7070Spatrick LI->setAtomic(llvm::AtomicOrdering::Acquire);
2456e5dd7070Spatrick
2457e5dd7070Spatrick // For ARM, we should only check the first bit, rather than the entire byte:
2458e5dd7070Spatrick //
2459e5dd7070Spatrick // ARM C++ ABI 3.2.3.1:
2460e5dd7070Spatrick // To support the potential use of initialization guard variables
2461e5dd7070Spatrick // as semaphores that are the target of ARM SWP and LDREX/STREX
2462e5dd7070Spatrick // synchronizing instructions we define a static initialization
2463e5dd7070Spatrick // guard variable to be a 4-byte aligned, 4-byte word with the
2464e5dd7070Spatrick // following inline access protocol.
2465e5dd7070Spatrick // #define INITIALIZED 1
2466e5dd7070Spatrick // if ((obj_guard & INITIALIZED) != INITIALIZED) {
2467e5dd7070Spatrick // if (__cxa_guard_acquire(&obj_guard))
2468e5dd7070Spatrick // ...
2469e5dd7070Spatrick // }
2470e5dd7070Spatrick //
2471e5dd7070Spatrick // and similarly for ARM64:
2472e5dd7070Spatrick //
2473e5dd7070Spatrick // ARM64 C++ ABI 3.2.2:
2474e5dd7070Spatrick // This ABI instead only specifies the value bit 0 of the static guard
2475e5dd7070Spatrick // variable; all other bits are platform defined. Bit 0 shall be 0 when the
2476e5dd7070Spatrick // variable is not initialized and 1 when it is.
2477e5dd7070Spatrick llvm::Value *V =
2478e5dd7070Spatrick (UseARMGuardVarABI && !useInt8GuardVariable)
2479e5dd7070Spatrick ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
2480e5dd7070Spatrick : LI;
2481e5dd7070Spatrick llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized");
2482e5dd7070Spatrick
2483e5dd7070Spatrick llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
2484e5dd7070Spatrick
2485e5dd7070Spatrick // Check if the first byte of the guard variable is zero.
2486e5dd7070Spatrick CGF.EmitCXXGuardedInitBranch(NeedsInit, InitCheckBlock, EndBlock,
2487e5dd7070Spatrick CodeGenFunction::GuardKind::VariableGuard, &D);
2488e5dd7070Spatrick
2489e5dd7070Spatrick CGF.EmitBlock(InitCheckBlock);
2490*12c85518Srobert }
2491*12c85518Srobert
2492*12c85518Srobert // The semantics of dynamic initialization of variables with static or thread
2493*12c85518Srobert // storage duration depends on whether they are declared at block-scope. The
2494*12c85518Srobert // initialization of such variables at block-scope can be aborted with an
2495*12c85518Srobert // exception and later retried (per C++20 [stmt.dcl]p4), and recursive entry
2496*12c85518Srobert // to their initialization has undefined behavior (also per C++20
2497*12c85518Srobert // [stmt.dcl]p4). For such variables declared at non-block scope, exceptions
2498*12c85518Srobert // lead to termination (per C++20 [except.terminate]p1), and recursive
2499*12c85518Srobert // references to the variables are governed only by the lifetime rules (per
2500*12c85518Srobert // C++20 [class.cdtor]p2), which means such references are perfectly fine as
2501*12c85518Srobert // long as they avoid touching memory. As a result, block-scope variables must
2502*12c85518Srobert // not be marked as initialized until after initialization completes (unless
2503*12c85518Srobert // the mark is reverted following an exception), but non-block-scope variables
2504*12c85518Srobert // must be marked prior to initialization so that recursive accesses during
2505*12c85518Srobert // initialization do not restart initialization.
2506e5dd7070Spatrick
2507e5dd7070Spatrick // Variables used when coping with thread-safe statics and exceptions.
2508e5dd7070Spatrick if (threadsafe) {
2509e5dd7070Spatrick // Call __cxa_guard_acquire.
2510e5dd7070Spatrick llvm::Value *V
2511e5dd7070Spatrick = CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard);
2512e5dd7070Spatrick
2513e5dd7070Spatrick llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
2514e5dd7070Spatrick
2515e5dd7070Spatrick Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
2516e5dd7070Spatrick InitBlock, EndBlock);
2517e5dd7070Spatrick
2518e5dd7070Spatrick // Call __cxa_guard_abort along the exceptional edge.
2519e5dd7070Spatrick CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard);
2520e5dd7070Spatrick
2521e5dd7070Spatrick CGF.EmitBlock(InitBlock);
2522*12c85518Srobert } else if (!D.isLocalVarDecl()) {
2523*12c85518Srobert // For non-local variables, store 1 into the first byte of the guard
2524*12c85518Srobert // variable before the object initialization begins so that references
2525*12c85518Srobert // to the variable during initialization don't restart initialization.
2526*12c85518Srobert Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2527*12c85518Srobert Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
2528e5dd7070Spatrick }
2529e5dd7070Spatrick
2530e5dd7070Spatrick // Emit the initializer and add a global destructor if appropriate.
2531e5dd7070Spatrick CGF.EmitCXXGlobalVarDeclInit(D, var, shouldPerformInit);
2532e5dd7070Spatrick
2533e5dd7070Spatrick if (threadsafe) {
2534e5dd7070Spatrick // Pop the guard-abort cleanup if we pushed one.
2535e5dd7070Spatrick CGF.PopCleanupBlock();
2536e5dd7070Spatrick
2537e5dd7070Spatrick // Call __cxa_guard_release. This cannot throw.
2538e5dd7070Spatrick CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy),
2539e5dd7070Spatrick guardAddr.getPointer());
2540*12c85518Srobert } else if (D.isLocalVarDecl()) {
2541*12c85518Srobert // For local variables, store 1 into the first byte of the guard variable
2542*12c85518Srobert // after the object initialization completes so that initialization is
2543*12c85518Srobert // retried if initialization is interrupted by an exception.
2544a9ac8606Spatrick Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2545a9ac8606Spatrick Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
2546e5dd7070Spatrick }
2547e5dd7070Spatrick
2548e5dd7070Spatrick CGF.EmitBlock(EndBlock);
2549e5dd7070Spatrick }
2550e5dd7070Spatrick
2551e5dd7070Spatrick /// Register a global destructor using __cxa_atexit.
emitGlobalDtorWithCXAAtExit(CodeGenFunction & CGF,llvm::FunctionCallee dtor,llvm::Constant * addr,bool TLS)2552e5dd7070Spatrick static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
2553e5dd7070Spatrick llvm::FunctionCallee dtor,
2554e5dd7070Spatrick llvm::Constant *addr, bool TLS) {
2555a9ac8606Spatrick assert(!CGF.getTarget().getTriple().isOSAIX() &&
2556a9ac8606Spatrick "unexpected call to emitGlobalDtorWithCXAAtExit");
2557e5dd7070Spatrick assert((TLS || CGF.getTypes().getCodeGenOpts().CXAAtExit) &&
2558e5dd7070Spatrick "__cxa_atexit is disabled");
2559e5dd7070Spatrick const char *Name = "__cxa_atexit";
2560e5dd7070Spatrick if (TLS) {
2561e5dd7070Spatrick const llvm::Triple &T = CGF.getTarget().getTriple();
2562e5dd7070Spatrick Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit";
2563e5dd7070Spatrick }
2564e5dd7070Spatrick
2565e5dd7070Spatrick // We're assuming that the destructor function is something we can
2566e5dd7070Spatrick // reasonably call with the default CC. Go ahead and cast it to the
2567e5dd7070Spatrick // right prototype.
2568e5dd7070Spatrick llvm::Type *dtorTy =
2569e5dd7070Spatrick llvm::FunctionType::get(CGF.VoidTy, CGF.Int8PtrTy, false)->getPointerTo();
2570e5dd7070Spatrick
2571e5dd7070Spatrick // Preserve address space of addr.
2572e5dd7070Spatrick auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0;
2573e5dd7070Spatrick auto AddrInt8PtrTy =
2574e5dd7070Spatrick AddrAS ? CGF.Int8Ty->getPointerTo(AddrAS) : CGF.Int8PtrTy;
2575e5dd7070Spatrick
2576e5dd7070Spatrick // Create a variable that binds the atexit to this shared object.
2577e5dd7070Spatrick llvm::Constant *handle =
2578e5dd7070Spatrick CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "__dso_handle");
2579e5dd7070Spatrick auto *GV = cast<llvm::GlobalValue>(handle->stripPointerCasts());
2580e5dd7070Spatrick GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
2581e5dd7070Spatrick
2582e5dd7070Spatrick // extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d);
2583e5dd7070Spatrick llvm::Type *paramTys[] = {dtorTy, AddrInt8PtrTy, handle->getType()};
2584e5dd7070Spatrick llvm::FunctionType *atexitTy =
2585e5dd7070Spatrick llvm::FunctionType::get(CGF.IntTy, paramTys, false);
2586e5dd7070Spatrick
2587e5dd7070Spatrick // Fetch the actual function.
2588e5dd7070Spatrick llvm::FunctionCallee atexit = CGF.CGM.CreateRuntimeFunction(atexitTy, Name);
2589e5dd7070Spatrick if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee()))
2590e5dd7070Spatrick fn->setDoesNotThrow();
2591e5dd7070Spatrick
2592e5dd7070Spatrick if (!addr)
2593e5dd7070Spatrick // addr is null when we are trying to register a dtor annotated with
2594e5dd7070Spatrick // __attribute__((destructor)) in a constructor function. Using null here is
2595e5dd7070Spatrick // okay because this argument is just passed back to the destructor
2596e5dd7070Spatrick // function.
2597e5dd7070Spatrick addr = llvm::Constant::getNullValue(CGF.Int8PtrTy);
2598e5dd7070Spatrick
2599e5dd7070Spatrick llvm::Value *args[] = {llvm::ConstantExpr::getBitCast(
2600e5dd7070Spatrick cast<llvm::Constant>(dtor.getCallee()), dtorTy),
2601e5dd7070Spatrick llvm::ConstantExpr::getBitCast(addr, AddrInt8PtrTy),
2602e5dd7070Spatrick handle};
2603e5dd7070Spatrick CGF.EmitNounwindRuntimeCall(atexit, args);
2604e5dd7070Spatrick }
2605e5dd7070Spatrick
createGlobalInitOrCleanupFn(CodeGen::CodeGenModule & CGM,StringRef FnName)2606a9ac8606Spatrick static llvm::Function *createGlobalInitOrCleanupFn(CodeGen::CodeGenModule &CGM,
2607a9ac8606Spatrick StringRef FnName) {
2608a9ac8606Spatrick // Create a function that registers/unregisters destructors that have the same
2609a9ac8606Spatrick // priority.
2610a9ac8606Spatrick llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
2611a9ac8606Spatrick llvm::Function *GlobalInitOrCleanupFn = CGM.CreateGlobalInitOrCleanUpFunction(
2612a9ac8606Spatrick FTy, FnName, CGM.getTypes().arrangeNullaryFunction(), SourceLocation());
2613a9ac8606Spatrick
2614a9ac8606Spatrick return GlobalInitOrCleanupFn;
2615a9ac8606Spatrick }
2616a9ac8606Spatrick
unregisterGlobalDtorsWithUnAtExit()2617a9ac8606Spatrick void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {
2618a9ac8606Spatrick for (const auto &I : DtorsUsingAtExit) {
2619a9ac8606Spatrick int Priority = I.first;
2620a9ac8606Spatrick std::string GlobalCleanupFnName =
2621a9ac8606Spatrick std::string("__GLOBAL_cleanup_") + llvm::to_string(Priority);
2622a9ac8606Spatrick
2623a9ac8606Spatrick llvm::Function *GlobalCleanupFn =
2624a9ac8606Spatrick createGlobalInitOrCleanupFn(*this, GlobalCleanupFnName);
2625a9ac8606Spatrick
2626a9ac8606Spatrick CodeGenFunction CGF(*this);
2627a9ac8606Spatrick CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalCleanupFn,
2628a9ac8606Spatrick getTypes().arrangeNullaryFunction(), FunctionArgList(),
2629a9ac8606Spatrick SourceLocation(), SourceLocation());
2630a9ac8606Spatrick auto AL = ApplyDebugLocation::CreateArtificial(CGF);
2631a9ac8606Spatrick
2632a9ac8606Spatrick // Get the destructor function type, void(*)(void).
2633a9ac8606Spatrick llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.VoidTy, false);
2634a9ac8606Spatrick llvm::Type *dtorTy = dtorFuncTy->getPointerTo();
2635a9ac8606Spatrick
2636a9ac8606Spatrick // Destructor functions are run/unregistered in non-ascending
2637a9ac8606Spatrick // order of their priorities.
2638a9ac8606Spatrick const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2639a9ac8606Spatrick auto itv = Dtors.rbegin();
2640a9ac8606Spatrick while (itv != Dtors.rend()) {
2641a9ac8606Spatrick llvm::Function *Dtor = *itv;
2642a9ac8606Spatrick
2643a9ac8606Spatrick // We're assuming that the destructor function is something we can
2644a9ac8606Spatrick // reasonably call with the correct CC. Go ahead and cast it to the
2645a9ac8606Spatrick // right prototype.
2646a9ac8606Spatrick llvm::Constant *dtor = llvm::ConstantExpr::getBitCast(Dtor, dtorTy);
2647a9ac8606Spatrick llvm::Value *V = CGF.unregisterGlobalDtorWithUnAtExit(dtor);
2648a9ac8606Spatrick llvm::Value *NeedsDestruct =
2649a9ac8606Spatrick CGF.Builder.CreateIsNull(V, "needs_destruct");
2650a9ac8606Spatrick
2651a9ac8606Spatrick llvm::BasicBlock *DestructCallBlock =
2652a9ac8606Spatrick CGF.createBasicBlock("destruct.call");
2653a9ac8606Spatrick llvm::BasicBlock *EndBlock = CGF.createBasicBlock(
2654a9ac8606Spatrick (itv + 1) != Dtors.rend() ? "unatexit.call" : "destruct.end");
2655a9ac8606Spatrick // Check if unatexit returns a value of 0. If it does, jump to
2656a9ac8606Spatrick // DestructCallBlock, otherwise jump to EndBlock directly.
2657a9ac8606Spatrick CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
2658a9ac8606Spatrick
2659a9ac8606Spatrick CGF.EmitBlock(DestructCallBlock);
2660a9ac8606Spatrick
2661a9ac8606Spatrick // Emit the call to casted Dtor.
2662a9ac8606Spatrick llvm::CallInst *CI = CGF.Builder.CreateCall(dtorFuncTy, dtor);
2663a9ac8606Spatrick // Make sure the call and the callee agree on calling convention.
2664a9ac8606Spatrick CI->setCallingConv(Dtor->getCallingConv());
2665a9ac8606Spatrick
2666a9ac8606Spatrick CGF.EmitBlock(EndBlock);
2667a9ac8606Spatrick
2668a9ac8606Spatrick itv++;
2669a9ac8606Spatrick }
2670a9ac8606Spatrick
2671a9ac8606Spatrick CGF.FinishFunction();
2672a9ac8606Spatrick AddGlobalDtor(GlobalCleanupFn, Priority);
2673a9ac8606Spatrick }
2674a9ac8606Spatrick }
2675a9ac8606Spatrick
registerGlobalDtorsWithAtExit()2676e5dd7070Spatrick void CodeGenModule::registerGlobalDtorsWithAtExit() {
2677e5dd7070Spatrick for (const auto &I : DtorsUsingAtExit) {
2678e5dd7070Spatrick int Priority = I.first;
2679a9ac8606Spatrick std::string GlobalInitFnName =
2680a9ac8606Spatrick std::string("__GLOBAL_init_") + llvm::to_string(Priority);
2681a9ac8606Spatrick llvm::Function *GlobalInitFn =
2682a9ac8606Spatrick createGlobalInitOrCleanupFn(*this, GlobalInitFnName);
2683e5dd7070Spatrick
2684a9ac8606Spatrick CodeGenFunction CGF(*this);
2685a9ac8606Spatrick CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalInitFn,
2686a9ac8606Spatrick getTypes().arrangeNullaryFunction(), FunctionArgList(),
2687a9ac8606Spatrick SourceLocation(), SourceLocation());
2688a9ac8606Spatrick auto AL = ApplyDebugLocation::CreateArtificial(CGF);
2689a9ac8606Spatrick
2690e5dd7070Spatrick // Since constructor functions are run in non-descending order of their
2691e5dd7070Spatrick // priorities, destructors are registered in non-descending order of their
2692e5dd7070Spatrick // priorities, and since destructor functions are run in the reverse order
2693e5dd7070Spatrick // of their registration, destructor functions are run in non-ascending
2694e5dd7070Spatrick // order of their priorities.
2695a9ac8606Spatrick const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2696e5dd7070Spatrick for (auto *Dtor : Dtors) {
2697e5dd7070Spatrick // Register the destructor function calling __cxa_atexit if it is
2698e5dd7070Spatrick // available. Otherwise fall back on calling atexit.
2699a9ac8606Spatrick if (getCodeGenOpts().CXAAtExit) {
2700e5dd7070Spatrick emitGlobalDtorWithCXAAtExit(CGF, Dtor, nullptr, false);
2701a9ac8606Spatrick } else {
2702a9ac8606Spatrick // Get the destructor function type, void(*)(void).
2703a9ac8606Spatrick llvm::Type *dtorTy =
2704a9ac8606Spatrick llvm::FunctionType::get(CGF.VoidTy, false)->getPointerTo();
2705a9ac8606Spatrick
2706a9ac8606Spatrick // We're assuming that the destructor function is something we can
2707a9ac8606Spatrick // reasonably call with the correct CC. Go ahead and cast it to the
2708a9ac8606Spatrick // right prototype.
2709a9ac8606Spatrick CGF.registerGlobalDtorWithAtExit(
2710a9ac8606Spatrick llvm::ConstantExpr::getBitCast(Dtor, dtorTy));
2711a9ac8606Spatrick }
2712e5dd7070Spatrick }
2713e5dd7070Spatrick
2714e5dd7070Spatrick CGF.FinishFunction();
2715*12c85518Srobert AddGlobalCtor(GlobalInitFn, Priority);
2716e5dd7070Spatrick }
2717a9ac8606Spatrick
2718a9ac8606Spatrick if (getCXXABI().useSinitAndSterm())
2719a9ac8606Spatrick unregisterGlobalDtorsWithUnAtExit();
2720e5dd7070Spatrick }
2721e5dd7070Spatrick
2722e5dd7070Spatrick /// Register a global destructor as best as we know how.
registerGlobalDtor(CodeGenFunction & CGF,const VarDecl & D,llvm::FunctionCallee dtor,llvm::Constant * addr)2723e5dd7070Spatrick void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
2724e5dd7070Spatrick llvm::FunctionCallee dtor,
2725e5dd7070Spatrick llvm::Constant *addr) {
2726e5dd7070Spatrick if (D.isNoDestroy(CGM.getContext()))
2727e5dd7070Spatrick return;
2728e5dd7070Spatrick
2729e5dd7070Spatrick // emitGlobalDtorWithCXAAtExit will emit a call to either __cxa_thread_atexit
2730e5dd7070Spatrick // or __cxa_atexit depending on whether this VarDecl is a thread-local storage
2731e5dd7070Spatrick // or not. CXAAtExit controls only __cxa_atexit, so use it if it is enabled.
2732e5dd7070Spatrick // We can always use __cxa_thread_atexit.
2733e5dd7070Spatrick if (CGM.getCodeGenOpts().CXAAtExit || D.getTLSKind())
2734e5dd7070Spatrick return emitGlobalDtorWithCXAAtExit(CGF, dtor, addr, D.getTLSKind());
2735e5dd7070Spatrick
2736e5dd7070Spatrick // In Apple kexts, we want to add a global destructor entry.
2737e5dd7070Spatrick // FIXME: shouldn't this be guarded by some variable?
2738e5dd7070Spatrick if (CGM.getLangOpts().AppleKext) {
2739e5dd7070Spatrick // Generate a global destructor entry.
2740e5dd7070Spatrick return CGM.AddCXXDtorEntry(dtor, addr);
2741e5dd7070Spatrick }
2742e5dd7070Spatrick
2743e5dd7070Spatrick CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
2744e5dd7070Spatrick }
2745e5dd7070Spatrick
isThreadWrapperReplaceable(const VarDecl * VD,CodeGen::CodeGenModule & CGM)2746e5dd7070Spatrick static bool isThreadWrapperReplaceable(const VarDecl *VD,
2747e5dd7070Spatrick CodeGen::CodeGenModule &CGM) {
2748e5dd7070Spatrick assert(!VD->isStaticLocal() && "static local VarDecls don't need wrappers!");
2749e5dd7070Spatrick // Darwin prefers to have references to thread local variables to go through
2750e5dd7070Spatrick // the thread wrapper instead of directly referencing the backing variable.
2751e5dd7070Spatrick return VD->getTLSKind() == VarDecl::TLS_Dynamic &&
2752e5dd7070Spatrick CGM.getTarget().getTriple().isOSDarwin();
2753e5dd7070Spatrick }
2754e5dd7070Spatrick
2755e5dd7070Spatrick /// Get the appropriate linkage for the wrapper function. This is essentially
2756e5dd7070Spatrick /// the weak form of the variable's linkage; every translation unit which needs
2757e5dd7070Spatrick /// the wrapper emits a copy, and we want the linker to merge them.
2758e5dd7070Spatrick static llvm::GlobalValue::LinkageTypes
getThreadLocalWrapperLinkage(const VarDecl * VD,CodeGen::CodeGenModule & CGM)2759e5dd7070Spatrick getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) {
2760e5dd7070Spatrick llvm::GlobalValue::LinkageTypes VarLinkage =
2761e5dd7070Spatrick CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
2762e5dd7070Spatrick
2763e5dd7070Spatrick // For internal linkage variables, we don't need an external or weak wrapper.
2764e5dd7070Spatrick if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
2765e5dd7070Spatrick return VarLinkage;
2766e5dd7070Spatrick
2767e5dd7070Spatrick // If the thread wrapper is replaceable, give it appropriate linkage.
2768e5dd7070Spatrick if (isThreadWrapperReplaceable(VD, CGM))
2769e5dd7070Spatrick if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
2770e5dd7070Spatrick !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
2771e5dd7070Spatrick return VarLinkage;
2772e5dd7070Spatrick return llvm::GlobalValue::WeakODRLinkage;
2773e5dd7070Spatrick }
2774e5dd7070Spatrick
2775e5dd7070Spatrick llvm::Function *
getOrCreateThreadLocalWrapper(const VarDecl * VD,llvm::Value * Val)2776e5dd7070Spatrick ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
2777e5dd7070Spatrick llvm::Value *Val) {
2778e5dd7070Spatrick // Mangle the name for the thread_local wrapper function.
2779e5dd7070Spatrick SmallString<256> WrapperName;
2780e5dd7070Spatrick {
2781e5dd7070Spatrick llvm::raw_svector_ostream Out(WrapperName);
2782e5dd7070Spatrick getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);
2783e5dd7070Spatrick }
2784e5dd7070Spatrick
2785e5dd7070Spatrick // FIXME: If VD is a definition, we should regenerate the function attributes
2786e5dd7070Spatrick // before returning.
2787e5dd7070Spatrick if (llvm::Value *V = CGM.getModule().getNamedValue(WrapperName))
2788e5dd7070Spatrick return cast<llvm::Function>(V);
2789e5dd7070Spatrick
2790e5dd7070Spatrick QualType RetQT = VD->getType();
2791e5dd7070Spatrick if (RetQT->isReferenceType())
2792e5dd7070Spatrick RetQT = RetQT.getNonReferenceType();
2793e5dd7070Spatrick
2794e5dd7070Spatrick const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
2795e5dd7070Spatrick getContext().getPointerType(RetQT), FunctionArgList());
2796e5dd7070Spatrick
2797e5dd7070Spatrick llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI);
2798e5dd7070Spatrick llvm::Function *Wrapper =
2799e5dd7070Spatrick llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM),
2800e5dd7070Spatrick WrapperName.str(), &CGM.getModule());
2801e5dd7070Spatrick
2802e5dd7070Spatrick if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())
2803e5dd7070Spatrick Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));
2804e5dd7070Spatrick
2805a9ac8606Spatrick CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper, /*IsThunk=*/false);
2806e5dd7070Spatrick
2807e5dd7070Spatrick // Always resolve references to the wrapper at link time.
2808e5dd7070Spatrick if (!Wrapper->hasLocalLinkage())
2809e5dd7070Spatrick if (!isThreadWrapperReplaceable(VD, CGM) ||
2810e5dd7070Spatrick llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
2811e5dd7070Spatrick llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
2812e5dd7070Spatrick VD->getVisibility() == HiddenVisibility)
2813e5dd7070Spatrick Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
2814e5dd7070Spatrick
2815e5dd7070Spatrick if (isThreadWrapperReplaceable(VD, CGM)) {
2816e5dd7070Spatrick Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2817e5dd7070Spatrick Wrapper->addFnAttr(llvm::Attribute::NoUnwind);
2818e5dd7070Spatrick }
2819e5dd7070Spatrick
2820e5dd7070Spatrick ThreadWrappers.push_back({VD, Wrapper});
2821e5dd7070Spatrick return Wrapper;
2822e5dd7070Spatrick }
2823e5dd7070Spatrick
EmitThreadLocalInitFuncs(CodeGenModule & CGM,ArrayRef<const VarDecl * > CXXThreadLocals,ArrayRef<llvm::Function * > CXXThreadLocalInits,ArrayRef<const VarDecl * > CXXThreadLocalInitVars)2824e5dd7070Spatrick void ItaniumCXXABI::EmitThreadLocalInitFuncs(
2825e5dd7070Spatrick CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
2826e5dd7070Spatrick ArrayRef<llvm::Function *> CXXThreadLocalInits,
2827e5dd7070Spatrick ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
2828e5dd7070Spatrick llvm::Function *InitFunc = nullptr;
2829e5dd7070Spatrick
2830e5dd7070Spatrick // Separate initializers into those with ordered (or partially-ordered)
2831e5dd7070Spatrick // initialization and those with unordered initialization.
2832e5dd7070Spatrick llvm::SmallVector<llvm::Function *, 8> OrderedInits;
2833e5dd7070Spatrick llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;
2834e5dd7070Spatrick for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {
2835e5dd7070Spatrick if (isTemplateInstantiation(
2836e5dd7070Spatrick CXXThreadLocalInitVars[I]->getTemplateSpecializationKind()))
2837e5dd7070Spatrick UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =
2838e5dd7070Spatrick CXXThreadLocalInits[I];
2839e5dd7070Spatrick else
2840e5dd7070Spatrick OrderedInits.push_back(CXXThreadLocalInits[I]);
2841e5dd7070Spatrick }
2842e5dd7070Spatrick
2843e5dd7070Spatrick if (!OrderedInits.empty()) {
2844e5dd7070Spatrick // Generate a guarded initialization function.
2845e5dd7070Spatrick llvm::FunctionType *FTy =
2846e5dd7070Spatrick llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
2847e5dd7070Spatrick const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2848ec727ea7Spatrick InitFunc = CGM.CreateGlobalInitOrCleanUpFunction(FTy, "__tls_init", FI,
2849e5dd7070Spatrick SourceLocation(),
2850e5dd7070Spatrick /*TLS=*/true);
2851e5dd7070Spatrick llvm::GlobalVariable *Guard = new llvm::GlobalVariable(
2852e5dd7070Spatrick CGM.getModule(), CGM.Int8Ty, /*isConstant=*/false,
2853e5dd7070Spatrick llvm::GlobalVariable::InternalLinkage,
2854e5dd7070Spatrick llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard");
2855e5dd7070Spatrick Guard->setThreadLocal(true);
2856ec727ea7Spatrick Guard->setThreadLocalMode(CGM.GetDefaultLLVMTLSModel());
2857e5dd7070Spatrick
2858e5dd7070Spatrick CharUnits GuardAlign = CharUnits::One();
2859e5dd7070Spatrick Guard->setAlignment(GuardAlign.getAsAlign());
2860e5dd7070Spatrick
2861e5dd7070Spatrick CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(
2862*12c85518Srobert InitFunc, OrderedInits, ConstantAddress(Guard, CGM.Int8Ty, GuardAlign));
2863e5dd7070Spatrick // On Darwin platforms, use CXX_FAST_TLS calling convention.
2864e5dd7070Spatrick if (CGM.getTarget().getTriple().isOSDarwin()) {
2865e5dd7070Spatrick InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2866e5dd7070Spatrick InitFunc->addFnAttr(llvm::Attribute::NoUnwind);
2867e5dd7070Spatrick }
2868e5dd7070Spatrick }
2869e5dd7070Spatrick
2870e5dd7070Spatrick // Create declarations for thread wrappers for all thread-local variables
2871e5dd7070Spatrick // with non-discardable definitions in this translation unit.
2872e5dd7070Spatrick for (const VarDecl *VD : CXXThreadLocals) {
2873e5dd7070Spatrick if (VD->hasDefinition() &&
2874e5dd7070Spatrick !isDiscardableGVALinkage(getContext().GetGVALinkageForVariable(VD))) {
2875e5dd7070Spatrick llvm::GlobalValue *GV = CGM.GetGlobalValue(CGM.getMangledName(VD));
2876e5dd7070Spatrick getOrCreateThreadLocalWrapper(VD, GV);
2877e5dd7070Spatrick }
2878e5dd7070Spatrick }
2879e5dd7070Spatrick
2880e5dd7070Spatrick // Emit all referenced thread wrappers.
2881e5dd7070Spatrick for (auto VDAndWrapper : ThreadWrappers) {
2882e5dd7070Spatrick const VarDecl *VD = VDAndWrapper.first;
2883e5dd7070Spatrick llvm::GlobalVariable *Var =
2884e5dd7070Spatrick cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD)));
2885e5dd7070Spatrick llvm::Function *Wrapper = VDAndWrapper.second;
2886e5dd7070Spatrick
2887e5dd7070Spatrick // Some targets require that all access to thread local variables go through
2888e5dd7070Spatrick // the thread wrapper. This means that we cannot attempt to create a thread
2889e5dd7070Spatrick // wrapper or a thread helper.
2890e5dd7070Spatrick if (!VD->hasDefinition()) {
2891e5dd7070Spatrick if (isThreadWrapperReplaceable(VD, CGM)) {
2892e5dd7070Spatrick Wrapper->setLinkage(llvm::Function::ExternalLinkage);
2893e5dd7070Spatrick continue;
2894e5dd7070Spatrick }
2895e5dd7070Spatrick
2896e5dd7070Spatrick // If this isn't a TU in which this variable is defined, the thread
2897e5dd7070Spatrick // wrapper is discardable.
2898e5dd7070Spatrick if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)
2899e5dd7070Spatrick Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);
2900e5dd7070Spatrick }
2901e5dd7070Spatrick
2902e5dd7070Spatrick CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Wrapper);
2903e5dd7070Spatrick
2904e5dd7070Spatrick // Mangle the name for the thread_local initialization function.
2905e5dd7070Spatrick SmallString<256> InitFnName;
2906e5dd7070Spatrick {
2907e5dd7070Spatrick llvm::raw_svector_ostream Out(InitFnName);
2908e5dd7070Spatrick getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
2909e5dd7070Spatrick }
2910e5dd7070Spatrick
2911e5dd7070Spatrick llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.VoidTy, false);
2912e5dd7070Spatrick
2913e5dd7070Spatrick // If we have a definition for the variable, emit the initialization
2914e5dd7070Spatrick // function as an alias to the global Init function (if any). Otherwise,
2915e5dd7070Spatrick // produce a declaration of the initialization function.
2916e5dd7070Spatrick llvm::GlobalValue *Init = nullptr;
2917e5dd7070Spatrick bool InitIsInitFunc = false;
2918e5dd7070Spatrick bool HasConstantInitialization = false;
2919e5dd7070Spatrick if (!usesThreadWrapperFunction(VD)) {
2920e5dd7070Spatrick HasConstantInitialization = true;
2921e5dd7070Spatrick } else if (VD->hasDefinition()) {
2922e5dd7070Spatrick InitIsInitFunc = true;
2923e5dd7070Spatrick llvm::Function *InitFuncToUse = InitFunc;
2924e5dd7070Spatrick if (isTemplateInstantiation(VD->getTemplateSpecializationKind()))
2925e5dd7070Spatrick InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl());
2926e5dd7070Spatrick if (InitFuncToUse)
2927e5dd7070Spatrick Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),
2928e5dd7070Spatrick InitFuncToUse);
2929e5dd7070Spatrick } else {
2930e5dd7070Spatrick // Emit a weak global function referring to the initialization function.
2931e5dd7070Spatrick // This function will not exist if the TU defining the thread_local
2932e5dd7070Spatrick // variable in question does not need any dynamic initialization for
2933e5dd7070Spatrick // its thread_local variables.
2934e5dd7070Spatrick Init = llvm::Function::Create(InitFnTy,
2935e5dd7070Spatrick llvm::GlobalVariable::ExternalWeakLinkage,
2936e5dd7070Spatrick InitFnName.str(), &CGM.getModule());
2937e5dd7070Spatrick const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2938a9ac8606Spatrick CGM.SetLLVMFunctionAttributes(
2939a9ac8606Spatrick GlobalDecl(), FI, cast<llvm::Function>(Init), /*IsThunk=*/false);
2940e5dd7070Spatrick }
2941e5dd7070Spatrick
2942e5dd7070Spatrick if (Init) {
2943e5dd7070Spatrick Init->setVisibility(Var->getVisibility());
2944e5dd7070Spatrick // Don't mark an extern_weak function DSO local on windows.
2945e5dd7070Spatrick if (!CGM.getTriple().isOSWindows() || !Init->hasExternalWeakLinkage())
2946e5dd7070Spatrick Init->setDSOLocal(Var->isDSOLocal());
2947e5dd7070Spatrick }
2948e5dd7070Spatrick
2949e5dd7070Spatrick llvm::LLVMContext &Context = CGM.getModule().getContext();
2950a9ac8606Spatrick
2951a9ac8606Spatrick // The linker on AIX is not happy with missing weak symbols. However,
2952a9ac8606Spatrick // other TUs will not know whether the initialization routine exists
2953a9ac8606Spatrick // so create an empty, init function to satisfy the linker.
2954a9ac8606Spatrick // This is needed whenever a thread wrapper function is not used, and
2955a9ac8606Spatrick // also when the symbol is weak.
2956a9ac8606Spatrick if (CGM.getTriple().isOSAIX() && VD->hasDefinition() &&
2957a9ac8606Spatrick isEmittedWithConstantInitializer(VD, true) &&
2958*12c85518Srobert !mayNeedDestruction(VD)) {
2959a9ac8606Spatrick // Init should be null. If it were non-null, then the logic above would
2960a9ac8606Spatrick // either be defining the function to be an alias or declaring the
2961a9ac8606Spatrick // function with the expectation that the definition of the variable
2962a9ac8606Spatrick // is elsewhere.
2963a9ac8606Spatrick assert(Init == nullptr && "Expected Init to be null.");
2964a9ac8606Spatrick
2965a9ac8606Spatrick llvm::Function *Func = llvm::Function::Create(
2966a9ac8606Spatrick InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.getModule());
2967a9ac8606Spatrick const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2968a9ac8606Spatrick CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI,
2969a9ac8606Spatrick cast<llvm::Function>(Func),
2970a9ac8606Spatrick /*IsThunk=*/false);
2971a9ac8606Spatrick // Create a function body that just returns
2972a9ac8606Spatrick llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Func);
2973a9ac8606Spatrick CGBuilderTy Builder(CGM, Entry);
2974a9ac8606Spatrick Builder.CreateRetVoid();
2975a9ac8606Spatrick }
2976a9ac8606Spatrick
2977e5dd7070Spatrick llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);
2978e5dd7070Spatrick CGBuilderTy Builder(CGM, Entry);
2979e5dd7070Spatrick if (HasConstantInitialization) {
2980e5dd7070Spatrick // No dynamic initialization to invoke.
2981e5dd7070Spatrick } else if (InitIsInitFunc) {
2982e5dd7070Spatrick if (Init) {
2983e5dd7070Spatrick llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init);
2984e5dd7070Spatrick if (isThreadWrapperReplaceable(VD, CGM)) {
2985e5dd7070Spatrick CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2986e5dd7070Spatrick llvm::Function *Fn =
2987e5dd7070Spatrick cast<llvm::Function>(cast<llvm::GlobalAlias>(Init)->getAliasee());
2988e5dd7070Spatrick Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2989e5dd7070Spatrick }
2990e5dd7070Spatrick }
2991a9ac8606Spatrick } else if (CGM.getTriple().isOSAIX()) {
2992a9ac8606Spatrick // On AIX, except if constinit and also neither of class type or of
2993a9ac8606Spatrick // (possibly multi-dimensional) array of class type, thread_local vars
2994a9ac8606Spatrick // will have init routines regardless of whether they are
2995a9ac8606Spatrick // const-initialized. Since the routine is guaranteed to exist, we can
2996a9ac8606Spatrick // unconditionally call it without testing for its existance. This
2997a9ac8606Spatrick // avoids potentially unresolved weak symbols which the AIX linker
2998a9ac8606Spatrick // isn't happy with.
2999a9ac8606Spatrick Builder.CreateCall(InitFnTy, Init);
3000e5dd7070Spatrick } else {
3001e5dd7070Spatrick // Don't know whether we have an init function. Call it if it exists.
3002e5dd7070Spatrick llvm::Value *Have = Builder.CreateIsNotNull(Init);
3003e5dd7070Spatrick llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context, "", Wrapper);
3004e5dd7070Spatrick llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context, "", Wrapper);
3005e5dd7070Spatrick Builder.CreateCondBr(Have, InitBB, ExitBB);
3006e5dd7070Spatrick
3007e5dd7070Spatrick Builder.SetInsertPoint(InitBB);
3008e5dd7070Spatrick Builder.CreateCall(InitFnTy, Init);
3009e5dd7070Spatrick Builder.CreateBr(ExitBB);
3010e5dd7070Spatrick
3011e5dd7070Spatrick Builder.SetInsertPoint(ExitBB);
3012e5dd7070Spatrick }
3013e5dd7070Spatrick
3014e5dd7070Spatrick // For a reference, the result of the wrapper function is a pointer to
3015e5dd7070Spatrick // the referenced object.
3016*12c85518Srobert llvm::Value *Val = Builder.CreateThreadLocalAddress(Var);
3017*12c85518Srobert
3018e5dd7070Spatrick if (VD->getType()->isReferenceType()) {
3019e5dd7070Spatrick CharUnits Align = CGM.getContext().getDeclAlign(VD);
3020*12c85518Srobert Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align);
3021e5dd7070Spatrick }
3022e5dd7070Spatrick if (Val->getType() != Wrapper->getReturnType())
3023e5dd7070Spatrick Val = Builder.CreatePointerBitCastOrAddrSpaceCast(
3024e5dd7070Spatrick Val, Wrapper->getReturnType(), "");
3025*12c85518Srobert
3026e5dd7070Spatrick Builder.CreateRet(Val);
3027e5dd7070Spatrick }
3028e5dd7070Spatrick }
3029e5dd7070Spatrick
EmitThreadLocalVarDeclLValue(CodeGenFunction & CGF,const VarDecl * VD,QualType LValType)3030e5dd7070Spatrick LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
3031e5dd7070Spatrick const VarDecl *VD,
3032e5dd7070Spatrick QualType LValType) {
3033e5dd7070Spatrick llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD);
3034e5dd7070Spatrick llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
3035e5dd7070Spatrick
3036e5dd7070Spatrick llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper);
3037e5dd7070Spatrick CallVal->setCallingConv(Wrapper->getCallingConv());
3038e5dd7070Spatrick
3039e5dd7070Spatrick LValue LV;
3040e5dd7070Spatrick if (VD->getType()->isReferenceType())
3041e5dd7070Spatrick LV = CGF.MakeNaturalAlignAddrLValue(CallVal, LValType);
3042e5dd7070Spatrick else
3043e5dd7070Spatrick LV = CGF.MakeAddrLValue(CallVal, LValType,
3044e5dd7070Spatrick CGF.getContext().getDeclAlign(VD));
3045e5dd7070Spatrick // FIXME: need setObjCGCLValueClass?
3046e5dd7070Spatrick return LV;
3047e5dd7070Spatrick }
3048e5dd7070Spatrick
3049e5dd7070Spatrick /// Return whether the given global decl needs a VTT parameter, which it does
3050e5dd7070Spatrick /// if it's a base constructor or destructor with virtual bases.
NeedsVTTParameter(GlobalDecl GD)3051e5dd7070Spatrick bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {
3052e5dd7070Spatrick const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
3053e5dd7070Spatrick
3054e5dd7070Spatrick // We don't have any virtual bases, just return early.
3055e5dd7070Spatrick if (!MD->getParent()->getNumVBases())
3056e5dd7070Spatrick return false;
3057e5dd7070Spatrick
3058e5dd7070Spatrick // Check if we have a base constructor.
3059e5dd7070Spatrick if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
3060e5dd7070Spatrick return true;
3061e5dd7070Spatrick
3062e5dd7070Spatrick // Check if we have a base destructor.
3063e5dd7070Spatrick if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
3064e5dd7070Spatrick return true;
3065e5dd7070Spatrick
3066e5dd7070Spatrick return false;
3067e5dd7070Spatrick }
3068e5dd7070Spatrick
3069e5dd7070Spatrick namespace {
3070e5dd7070Spatrick class ItaniumRTTIBuilder {
3071e5dd7070Spatrick CodeGenModule &CGM; // Per-module state.
3072e5dd7070Spatrick llvm::LLVMContext &VMContext;
3073e5dd7070Spatrick const ItaniumCXXABI &CXXABI; // Per-module state.
3074e5dd7070Spatrick
3075e5dd7070Spatrick /// Fields - The fields of the RTTI descriptor currently being built.
3076e5dd7070Spatrick SmallVector<llvm::Constant *, 16> Fields;
3077e5dd7070Spatrick
3078e5dd7070Spatrick /// GetAddrOfTypeName - Returns the mangled type name of the given type.
3079e5dd7070Spatrick llvm::GlobalVariable *
3080e5dd7070Spatrick GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
3081e5dd7070Spatrick
3082e5dd7070Spatrick /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI
3083e5dd7070Spatrick /// descriptor of the given type.
3084e5dd7070Spatrick llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
3085e5dd7070Spatrick
3086e5dd7070Spatrick /// BuildVTablePointer - Build the vtable pointer for the given type.
3087e5dd7070Spatrick void BuildVTablePointer(const Type *Ty);
3088e5dd7070Spatrick
3089e5dd7070Spatrick /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
3090e5dd7070Spatrick /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b.
3091e5dd7070Spatrick void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
3092e5dd7070Spatrick
3093e5dd7070Spatrick /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
3094e5dd7070Spatrick /// classes with bases that do not satisfy the abi::__si_class_type_info
3095e5dd7070Spatrick /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
3096e5dd7070Spatrick void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
3097e5dd7070Spatrick
3098e5dd7070Spatrick /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used
3099e5dd7070Spatrick /// for pointer types.
3100e5dd7070Spatrick void BuildPointerTypeInfo(QualType PointeeTy);
3101e5dd7070Spatrick
3102e5dd7070Spatrick /// BuildObjCObjectTypeInfo - Build the appropriate kind of
3103e5dd7070Spatrick /// type_info for an object type.
3104e5dd7070Spatrick void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
3105e5dd7070Spatrick
3106e5dd7070Spatrick /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
3107e5dd7070Spatrick /// struct, used for member pointer types.
3108e5dd7070Spatrick void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
3109e5dd7070Spatrick
3110e5dd7070Spatrick public:
ItaniumRTTIBuilder(const ItaniumCXXABI & ABI)3111e5dd7070Spatrick ItaniumRTTIBuilder(const ItaniumCXXABI &ABI)
3112e5dd7070Spatrick : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {}
3113e5dd7070Spatrick
3114e5dd7070Spatrick // Pointer type info flags.
3115e5dd7070Spatrick enum {
3116e5dd7070Spatrick /// PTI_Const - Type has const qualifier.
3117e5dd7070Spatrick PTI_Const = 0x1,
3118e5dd7070Spatrick
3119e5dd7070Spatrick /// PTI_Volatile - Type has volatile qualifier.
3120e5dd7070Spatrick PTI_Volatile = 0x2,
3121e5dd7070Spatrick
3122e5dd7070Spatrick /// PTI_Restrict - Type has restrict qualifier.
3123e5dd7070Spatrick PTI_Restrict = 0x4,
3124e5dd7070Spatrick
3125e5dd7070Spatrick /// PTI_Incomplete - Type is incomplete.
3126e5dd7070Spatrick PTI_Incomplete = 0x8,
3127e5dd7070Spatrick
3128e5dd7070Spatrick /// PTI_ContainingClassIncomplete - Containing class is incomplete.
3129e5dd7070Spatrick /// (in pointer to member).
3130e5dd7070Spatrick PTI_ContainingClassIncomplete = 0x10,
3131e5dd7070Spatrick
3132e5dd7070Spatrick /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
3133e5dd7070Spatrick //PTI_TransactionSafe = 0x20,
3134e5dd7070Spatrick
3135e5dd7070Spatrick /// PTI_Noexcept - Pointee is noexcept function (C++1z).
3136e5dd7070Spatrick PTI_Noexcept = 0x40,
3137e5dd7070Spatrick };
3138e5dd7070Spatrick
3139e5dd7070Spatrick // VMI type info flags.
3140e5dd7070Spatrick enum {
3141e5dd7070Spatrick /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
3142e5dd7070Spatrick VMI_NonDiamondRepeat = 0x1,
3143e5dd7070Spatrick
3144e5dd7070Spatrick /// VMI_DiamondShaped - Class is diamond shaped.
3145e5dd7070Spatrick VMI_DiamondShaped = 0x2
3146e5dd7070Spatrick };
3147e5dd7070Spatrick
3148e5dd7070Spatrick // Base class type info flags.
3149e5dd7070Spatrick enum {
3150e5dd7070Spatrick /// BCTI_Virtual - Base class is virtual.
3151e5dd7070Spatrick BCTI_Virtual = 0x1,
3152e5dd7070Spatrick
3153e5dd7070Spatrick /// BCTI_Public - Base class is public.
3154e5dd7070Spatrick BCTI_Public = 0x2
3155e5dd7070Spatrick };
3156e5dd7070Spatrick
3157e5dd7070Spatrick /// BuildTypeInfo - Build the RTTI type info struct for the given type, or
3158e5dd7070Spatrick /// link to an existing RTTI descriptor if one already exists.
3159e5dd7070Spatrick llvm::Constant *BuildTypeInfo(QualType Ty);
3160e5dd7070Spatrick
3161e5dd7070Spatrick /// BuildTypeInfo - Build the RTTI type info struct for the given type.
3162e5dd7070Spatrick llvm::Constant *BuildTypeInfo(
3163e5dd7070Spatrick QualType Ty,
3164e5dd7070Spatrick llvm::GlobalVariable::LinkageTypes Linkage,
3165e5dd7070Spatrick llvm::GlobalValue::VisibilityTypes Visibility,
3166e5dd7070Spatrick llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
3167e5dd7070Spatrick };
3168e5dd7070Spatrick }
3169e5dd7070Spatrick
GetAddrOfTypeName(QualType Ty,llvm::GlobalVariable::LinkageTypes Linkage)3170e5dd7070Spatrick llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
3171e5dd7070Spatrick QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {
3172e5dd7070Spatrick SmallString<256> Name;
3173e5dd7070Spatrick llvm::raw_svector_ostream Out(Name);
3174e5dd7070Spatrick CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
3175e5dd7070Spatrick
3176e5dd7070Spatrick // We know that the mangled name of the type starts at index 4 of the
3177e5dd7070Spatrick // mangled name of the typename, so we can just index into it in order to
3178e5dd7070Spatrick // get the mangled name of the type.
3179e5dd7070Spatrick llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
3180e5dd7070Spatrick Name.substr(4));
3181e5dd7070Spatrick auto Align = CGM.getContext().getTypeAlignInChars(CGM.getContext().CharTy);
3182e5dd7070Spatrick
3183e5dd7070Spatrick llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable(
3184*12c85518Srobert Name, Init->getType(), Linkage, Align.getAsAlign());
3185e5dd7070Spatrick
3186e5dd7070Spatrick GV->setInitializer(Init);
3187e5dd7070Spatrick
3188e5dd7070Spatrick return GV;
3189e5dd7070Spatrick }
3190e5dd7070Spatrick
3191e5dd7070Spatrick llvm::Constant *
GetAddrOfExternalRTTIDescriptor(QualType Ty)3192e5dd7070Spatrick ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
3193e5dd7070Spatrick // Mangle the RTTI name.
3194e5dd7070Spatrick SmallString<256> Name;
3195e5dd7070Spatrick llvm::raw_svector_ostream Out(Name);
3196e5dd7070Spatrick CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
3197e5dd7070Spatrick
3198e5dd7070Spatrick // Look for an existing global.
3199e5dd7070Spatrick llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
3200e5dd7070Spatrick
3201e5dd7070Spatrick if (!GV) {
3202e5dd7070Spatrick // Create a new global variable.
3203e5dd7070Spatrick // Note for the future: If we would ever like to do deferred emission of
3204e5dd7070Spatrick // RTTI, check if emitting vtables opportunistically need any adjustment.
3205e5dd7070Spatrick
3206e5dd7070Spatrick GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
3207e5dd7070Spatrick /*isConstant=*/true,
3208e5dd7070Spatrick llvm::GlobalValue::ExternalLinkage, nullptr,
3209e5dd7070Spatrick Name);
3210e5dd7070Spatrick const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
3211e5dd7070Spatrick CGM.setGVProperties(GV, RD);
3212a9ac8606Spatrick // Import the typeinfo symbol when all non-inline virtual methods are
3213a9ac8606Spatrick // imported.
3214a9ac8606Spatrick if (CGM.getTarget().hasPS4DLLImportExport()) {
3215a9ac8606Spatrick if (RD && CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD)) {
3216a9ac8606Spatrick GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
3217a9ac8606Spatrick CGM.setDSOLocal(GV);
3218a9ac8606Spatrick }
3219a9ac8606Spatrick }
3220e5dd7070Spatrick }
3221e5dd7070Spatrick
3222e5dd7070Spatrick return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
3223e5dd7070Spatrick }
3224e5dd7070Spatrick
3225e5dd7070Spatrick /// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
3226e5dd7070Spatrick /// info for that type is defined in the standard library.
TypeInfoIsInStandardLibrary(const BuiltinType * Ty)3227e5dd7070Spatrick static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
3228e5dd7070Spatrick // Itanium C++ ABI 2.9.2:
3229e5dd7070Spatrick // Basic type information (e.g. for "int", "bool", etc.) will be kept in
3230e5dd7070Spatrick // the run-time support library. Specifically, the run-time support
3231e5dd7070Spatrick // library should contain type_info objects for the types X, X* and
3232e5dd7070Spatrick // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
3233e5dd7070Spatrick // unsigned char, signed char, short, unsigned short, int, unsigned int,
3234e5dd7070Spatrick // long, unsigned long, long long, unsigned long long, float, double,
3235e5dd7070Spatrick // long double, char16_t, char32_t, and the IEEE 754r decimal and
3236e5dd7070Spatrick // half-precision floating point types.
3237e5dd7070Spatrick //
3238e5dd7070Spatrick // GCC also emits RTTI for __int128.
3239e5dd7070Spatrick // FIXME: We do not emit RTTI information for decimal types here.
3240e5dd7070Spatrick
3241e5dd7070Spatrick // Types added here must also be added to EmitFundamentalRTTIDescriptors.
3242e5dd7070Spatrick switch (Ty->getKind()) {
3243e5dd7070Spatrick case BuiltinType::Void:
3244e5dd7070Spatrick case BuiltinType::NullPtr:
3245e5dd7070Spatrick case BuiltinType::Bool:
3246e5dd7070Spatrick case BuiltinType::WChar_S:
3247e5dd7070Spatrick case BuiltinType::WChar_U:
3248e5dd7070Spatrick case BuiltinType::Char_U:
3249e5dd7070Spatrick case BuiltinType::Char_S:
3250e5dd7070Spatrick case BuiltinType::UChar:
3251e5dd7070Spatrick case BuiltinType::SChar:
3252e5dd7070Spatrick case BuiltinType::Short:
3253e5dd7070Spatrick case BuiltinType::UShort:
3254e5dd7070Spatrick case BuiltinType::Int:
3255e5dd7070Spatrick case BuiltinType::UInt:
3256e5dd7070Spatrick case BuiltinType::Long:
3257e5dd7070Spatrick case BuiltinType::ULong:
3258e5dd7070Spatrick case BuiltinType::LongLong:
3259e5dd7070Spatrick case BuiltinType::ULongLong:
3260e5dd7070Spatrick case BuiltinType::Half:
3261e5dd7070Spatrick case BuiltinType::Float:
3262e5dd7070Spatrick case BuiltinType::Double:
3263e5dd7070Spatrick case BuiltinType::LongDouble:
3264e5dd7070Spatrick case BuiltinType::Float16:
3265e5dd7070Spatrick case BuiltinType::Float128:
3266*12c85518Srobert case BuiltinType::Ibm128:
3267e5dd7070Spatrick case BuiltinType::Char8:
3268e5dd7070Spatrick case BuiltinType::Char16:
3269e5dd7070Spatrick case BuiltinType::Char32:
3270e5dd7070Spatrick case BuiltinType::Int128:
3271e5dd7070Spatrick case BuiltinType::UInt128:
3272e5dd7070Spatrick return true;
3273e5dd7070Spatrick
3274e5dd7070Spatrick #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
3275e5dd7070Spatrick case BuiltinType::Id:
3276e5dd7070Spatrick #include "clang/Basic/OpenCLImageTypes.def"
3277e5dd7070Spatrick #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
3278e5dd7070Spatrick case BuiltinType::Id:
3279e5dd7070Spatrick #include "clang/Basic/OpenCLExtensionTypes.def"
3280e5dd7070Spatrick case BuiltinType::OCLSampler:
3281e5dd7070Spatrick case BuiltinType::OCLEvent:
3282e5dd7070Spatrick case BuiltinType::OCLClkEvent:
3283e5dd7070Spatrick case BuiltinType::OCLQueue:
3284e5dd7070Spatrick case BuiltinType::OCLReserveID:
3285e5dd7070Spatrick #define SVE_TYPE(Name, Id, SingletonId) \
3286e5dd7070Spatrick case BuiltinType::Id:
3287e5dd7070Spatrick #include "clang/Basic/AArch64SVEACLETypes.def"
3288a9ac8606Spatrick #define PPC_VECTOR_TYPE(Name, Id, Size) \
3289a9ac8606Spatrick case BuiltinType::Id:
3290a9ac8606Spatrick #include "clang/Basic/PPCTypes.def"
3291a9ac8606Spatrick #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3292a9ac8606Spatrick #include "clang/Basic/RISCVVTypes.def"
3293e5dd7070Spatrick case BuiltinType::ShortAccum:
3294e5dd7070Spatrick case BuiltinType::Accum:
3295e5dd7070Spatrick case BuiltinType::LongAccum:
3296e5dd7070Spatrick case BuiltinType::UShortAccum:
3297e5dd7070Spatrick case BuiltinType::UAccum:
3298e5dd7070Spatrick case BuiltinType::ULongAccum:
3299e5dd7070Spatrick case BuiltinType::ShortFract:
3300e5dd7070Spatrick case BuiltinType::Fract:
3301e5dd7070Spatrick case BuiltinType::LongFract:
3302e5dd7070Spatrick case BuiltinType::UShortFract:
3303e5dd7070Spatrick case BuiltinType::UFract:
3304e5dd7070Spatrick case BuiltinType::ULongFract:
3305e5dd7070Spatrick case BuiltinType::SatShortAccum:
3306e5dd7070Spatrick case BuiltinType::SatAccum:
3307e5dd7070Spatrick case BuiltinType::SatLongAccum:
3308e5dd7070Spatrick case BuiltinType::SatUShortAccum:
3309e5dd7070Spatrick case BuiltinType::SatUAccum:
3310e5dd7070Spatrick case BuiltinType::SatULongAccum:
3311e5dd7070Spatrick case BuiltinType::SatShortFract:
3312e5dd7070Spatrick case BuiltinType::SatFract:
3313e5dd7070Spatrick case BuiltinType::SatLongFract:
3314e5dd7070Spatrick case BuiltinType::SatUShortFract:
3315e5dd7070Spatrick case BuiltinType::SatUFract:
3316e5dd7070Spatrick case BuiltinType::SatULongFract:
3317ec727ea7Spatrick case BuiltinType::BFloat16:
3318e5dd7070Spatrick return false;
3319e5dd7070Spatrick
3320e5dd7070Spatrick case BuiltinType::Dependent:
3321e5dd7070Spatrick #define BUILTIN_TYPE(Id, SingletonId)
3322e5dd7070Spatrick #define PLACEHOLDER_TYPE(Id, SingletonId) \
3323e5dd7070Spatrick case BuiltinType::Id:
3324e5dd7070Spatrick #include "clang/AST/BuiltinTypes.def"
3325e5dd7070Spatrick llvm_unreachable("asking for RRTI for a placeholder type!");
3326e5dd7070Spatrick
3327e5dd7070Spatrick case BuiltinType::ObjCId:
3328e5dd7070Spatrick case BuiltinType::ObjCClass:
3329e5dd7070Spatrick case BuiltinType::ObjCSel:
3330e5dd7070Spatrick llvm_unreachable("FIXME: Objective-C types are unsupported!");
3331e5dd7070Spatrick }
3332e5dd7070Spatrick
3333e5dd7070Spatrick llvm_unreachable("Invalid BuiltinType Kind!");
3334e5dd7070Spatrick }
3335e5dd7070Spatrick
TypeInfoIsInStandardLibrary(const PointerType * PointerTy)3336e5dd7070Spatrick static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
3337e5dd7070Spatrick QualType PointeeTy = PointerTy->getPointeeType();
3338e5dd7070Spatrick const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
3339e5dd7070Spatrick if (!BuiltinTy)
3340e5dd7070Spatrick return false;
3341e5dd7070Spatrick
3342e5dd7070Spatrick // Check the qualifiers.
3343e5dd7070Spatrick Qualifiers Quals = PointeeTy.getQualifiers();
3344e5dd7070Spatrick Quals.removeConst();
3345e5dd7070Spatrick
3346e5dd7070Spatrick if (!Quals.empty())
3347e5dd7070Spatrick return false;
3348e5dd7070Spatrick
3349e5dd7070Spatrick return TypeInfoIsInStandardLibrary(BuiltinTy);
3350e5dd7070Spatrick }
3351e5dd7070Spatrick
3352e5dd7070Spatrick /// IsStandardLibraryRTTIDescriptor - Returns whether the type
3353e5dd7070Spatrick /// information for the given type exists in the standard library.
IsStandardLibraryRTTIDescriptor(QualType Ty)3354e5dd7070Spatrick static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
3355e5dd7070Spatrick // Type info for builtin types is defined in the standard library.
3356e5dd7070Spatrick if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
3357e5dd7070Spatrick return TypeInfoIsInStandardLibrary(BuiltinTy);
3358e5dd7070Spatrick
3359e5dd7070Spatrick // Type info for some pointer types to builtin types is defined in the
3360e5dd7070Spatrick // standard library.
3361e5dd7070Spatrick if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3362e5dd7070Spatrick return TypeInfoIsInStandardLibrary(PointerTy);
3363e5dd7070Spatrick
3364e5dd7070Spatrick return false;
3365e5dd7070Spatrick }
3366e5dd7070Spatrick
3367e5dd7070Spatrick /// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
3368e5dd7070Spatrick /// the given type exists somewhere else, and that we should not emit the type
3369e5dd7070Spatrick /// information in this translation unit. Assumes that it is not a
3370e5dd7070Spatrick /// standard-library type.
ShouldUseExternalRTTIDescriptor(CodeGenModule & CGM,QualType Ty)3371e5dd7070Spatrick static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
3372e5dd7070Spatrick QualType Ty) {
3373e5dd7070Spatrick ASTContext &Context = CGM.getContext();
3374e5dd7070Spatrick
3375e5dd7070Spatrick // If RTTI is disabled, assume it might be disabled in the
3376e5dd7070Spatrick // translation unit that defines any potential key function, too.
3377e5dd7070Spatrick if (!Context.getLangOpts().RTTI) return false;
3378e5dd7070Spatrick
3379e5dd7070Spatrick if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3380e5dd7070Spatrick const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
3381e5dd7070Spatrick if (!RD->hasDefinition())
3382e5dd7070Spatrick return false;
3383e5dd7070Spatrick
3384e5dd7070Spatrick if (!RD->isDynamicClass())
3385e5dd7070Spatrick return false;
3386e5dd7070Spatrick
3387e5dd7070Spatrick // FIXME: this may need to be reconsidered if the key function
3388e5dd7070Spatrick // changes.
3389e5dd7070Spatrick // N.B. We must always emit the RTTI data ourselves if there exists a key
3390e5dd7070Spatrick // function.
3391e5dd7070Spatrick bool IsDLLImport = RD->hasAttr<DLLImportAttr>();
3392e5dd7070Spatrick
3393e5dd7070Spatrick // Don't import the RTTI but emit it locally.
3394e5dd7070Spatrick if (CGM.getTriple().isWindowsGNUEnvironment())
3395e5dd7070Spatrick return false;
3396e5dd7070Spatrick
3397a9ac8606Spatrick if (CGM.getVTables().isVTableExternal(RD)) {
3398a9ac8606Spatrick if (CGM.getTarget().hasPS4DLLImportExport())
3399a9ac8606Spatrick return true;
3400a9ac8606Spatrick
3401e5dd7070Spatrick return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment()
3402e5dd7070Spatrick ? false
3403e5dd7070Spatrick : true;
3404a9ac8606Spatrick }
3405e5dd7070Spatrick if (IsDLLImport)
3406e5dd7070Spatrick return true;
3407e5dd7070Spatrick }
3408e5dd7070Spatrick
3409e5dd7070Spatrick return false;
3410e5dd7070Spatrick }
3411e5dd7070Spatrick
3412e5dd7070Spatrick /// IsIncompleteClassType - Returns whether the given record type is incomplete.
IsIncompleteClassType(const RecordType * RecordTy)3413e5dd7070Spatrick static bool IsIncompleteClassType(const RecordType *RecordTy) {
3414e5dd7070Spatrick return !RecordTy->getDecl()->isCompleteDefinition();
3415e5dd7070Spatrick }
3416e5dd7070Spatrick
3417e5dd7070Spatrick /// ContainsIncompleteClassType - Returns whether the given type contains an
3418e5dd7070Spatrick /// incomplete class type. This is true if
3419e5dd7070Spatrick ///
3420e5dd7070Spatrick /// * The given type is an incomplete class type.
3421e5dd7070Spatrick /// * The given type is a pointer type whose pointee type contains an
3422e5dd7070Spatrick /// incomplete class type.
3423e5dd7070Spatrick /// * The given type is a member pointer type whose class is an incomplete
3424e5dd7070Spatrick /// class type.
3425e5dd7070Spatrick /// * The given type is a member pointer type whoise pointee type contains an
3426e5dd7070Spatrick /// incomplete class type.
3427e5dd7070Spatrick /// is an indirect or direct pointer to an incomplete class type.
ContainsIncompleteClassType(QualType Ty)3428e5dd7070Spatrick static bool ContainsIncompleteClassType(QualType Ty) {
3429e5dd7070Spatrick if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3430e5dd7070Spatrick if (IsIncompleteClassType(RecordTy))
3431e5dd7070Spatrick return true;
3432e5dd7070Spatrick }
3433e5dd7070Spatrick
3434e5dd7070Spatrick if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3435e5dd7070Spatrick return ContainsIncompleteClassType(PointerTy->getPointeeType());
3436e5dd7070Spatrick
3437e5dd7070Spatrick if (const MemberPointerType *MemberPointerTy =
3438e5dd7070Spatrick dyn_cast<MemberPointerType>(Ty)) {
3439e5dd7070Spatrick // Check if the class type is incomplete.
3440e5dd7070Spatrick const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
3441e5dd7070Spatrick if (IsIncompleteClassType(ClassType))
3442e5dd7070Spatrick return true;
3443e5dd7070Spatrick
3444e5dd7070Spatrick return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
3445e5dd7070Spatrick }
3446e5dd7070Spatrick
3447e5dd7070Spatrick return false;
3448e5dd7070Spatrick }
3449e5dd7070Spatrick
3450e5dd7070Spatrick // CanUseSingleInheritance - Return whether the given record decl has a "single,
3451e5dd7070Spatrick // public, non-virtual base at offset zero (i.e. the derived class is dynamic
3452e5dd7070Spatrick // iff the base is)", according to Itanium C++ ABI, 2.95p6b.
CanUseSingleInheritance(const CXXRecordDecl * RD)3453e5dd7070Spatrick static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
3454e5dd7070Spatrick // Check the number of bases.
3455e5dd7070Spatrick if (RD->getNumBases() != 1)
3456e5dd7070Spatrick return false;
3457e5dd7070Spatrick
3458e5dd7070Spatrick // Get the base.
3459e5dd7070Spatrick CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
3460e5dd7070Spatrick
3461e5dd7070Spatrick // Check that the base is not virtual.
3462e5dd7070Spatrick if (Base->isVirtual())
3463e5dd7070Spatrick return false;
3464e5dd7070Spatrick
3465e5dd7070Spatrick // Check that the base is public.
3466e5dd7070Spatrick if (Base->getAccessSpecifier() != AS_public)
3467e5dd7070Spatrick return false;
3468e5dd7070Spatrick
3469e5dd7070Spatrick // Check that the class is dynamic iff the base is.
3470e5dd7070Spatrick auto *BaseDecl =
3471e5dd7070Spatrick cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
3472e5dd7070Spatrick if (!BaseDecl->isEmpty() &&
3473e5dd7070Spatrick BaseDecl->isDynamicClass() != RD->isDynamicClass())
3474e5dd7070Spatrick return false;
3475e5dd7070Spatrick
3476e5dd7070Spatrick return true;
3477e5dd7070Spatrick }
3478e5dd7070Spatrick
BuildVTablePointer(const Type * Ty)3479e5dd7070Spatrick void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
3480e5dd7070Spatrick // abi::__class_type_info.
3481e5dd7070Spatrick static const char * const ClassTypeInfo =
3482e5dd7070Spatrick "_ZTVN10__cxxabiv117__class_type_infoE";
3483e5dd7070Spatrick // abi::__si_class_type_info.
3484e5dd7070Spatrick static const char * const SIClassTypeInfo =
3485e5dd7070Spatrick "_ZTVN10__cxxabiv120__si_class_type_infoE";
3486e5dd7070Spatrick // abi::__vmi_class_type_info.
3487e5dd7070Spatrick static const char * const VMIClassTypeInfo =
3488e5dd7070Spatrick "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
3489e5dd7070Spatrick
3490e5dd7070Spatrick const char *VTableName = nullptr;
3491e5dd7070Spatrick
3492e5dd7070Spatrick switch (Ty->getTypeClass()) {
3493e5dd7070Spatrick #define TYPE(Class, Base)
3494e5dd7070Spatrick #define ABSTRACT_TYPE(Class, Base)
3495e5dd7070Spatrick #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3496e5dd7070Spatrick #define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3497e5dd7070Spatrick #define DEPENDENT_TYPE(Class, Base) case Type::Class:
3498e5dd7070Spatrick #include "clang/AST/TypeNodes.inc"
3499e5dd7070Spatrick llvm_unreachable("Non-canonical and dependent types shouldn't get here");
3500e5dd7070Spatrick
3501e5dd7070Spatrick case Type::LValueReference:
3502e5dd7070Spatrick case Type::RValueReference:
3503e5dd7070Spatrick llvm_unreachable("References shouldn't get here");
3504e5dd7070Spatrick
3505e5dd7070Spatrick case Type::Auto:
3506e5dd7070Spatrick case Type::DeducedTemplateSpecialization:
3507e5dd7070Spatrick llvm_unreachable("Undeduced type shouldn't get here");
3508e5dd7070Spatrick
3509e5dd7070Spatrick case Type::Pipe:
3510e5dd7070Spatrick llvm_unreachable("Pipe types shouldn't get here");
3511e5dd7070Spatrick
3512e5dd7070Spatrick case Type::Builtin:
3513*12c85518Srobert case Type::BitInt:
3514e5dd7070Spatrick // GCC treats vector and complex types as fundamental types.
3515e5dd7070Spatrick case Type::Vector:
3516e5dd7070Spatrick case Type::ExtVector:
3517ec727ea7Spatrick case Type::ConstantMatrix:
3518e5dd7070Spatrick case Type::Complex:
3519e5dd7070Spatrick case Type::Atomic:
3520e5dd7070Spatrick // FIXME: GCC treats block pointers as fundamental types?!
3521e5dd7070Spatrick case Type::BlockPointer:
3522e5dd7070Spatrick // abi::__fundamental_type_info.
3523e5dd7070Spatrick VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
3524e5dd7070Spatrick break;
3525e5dd7070Spatrick
3526e5dd7070Spatrick case Type::ConstantArray:
3527e5dd7070Spatrick case Type::IncompleteArray:
3528e5dd7070Spatrick case Type::VariableArray:
3529e5dd7070Spatrick // abi::__array_type_info.
3530e5dd7070Spatrick VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
3531e5dd7070Spatrick break;
3532e5dd7070Spatrick
3533e5dd7070Spatrick case Type::FunctionNoProto:
3534e5dd7070Spatrick case Type::FunctionProto:
3535e5dd7070Spatrick // abi::__function_type_info.
3536e5dd7070Spatrick VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
3537e5dd7070Spatrick break;
3538e5dd7070Spatrick
3539e5dd7070Spatrick case Type::Enum:
3540e5dd7070Spatrick // abi::__enum_type_info.
3541e5dd7070Spatrick VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
3542e5dd7070Spatrick break;
3543e5dd7070Spatrick
3544e5dd7070Spatrick case Type::Record: {
3545e5dd7070Spatrick const CXXRecordDecl *RD =
3546e5dd7070Spatrick cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
3547e5dd7070Spatrick
3548e5dd7070Spatrick if (!RD->hasDefinition() || !RD->getNumBases()) {
3549e5dd7070Spatrick VTableName = ClassTypeInfo;
3550e5dd7070Spatrick } else if (CanUseSingleInheritance(RD)) {
3551e5dd7070Spatrick VTableName = SIClassTypeInfo;
3552e5dd7070Spatrick } else {
3553e5dd7070Spatrick VTableName = VMIClassTypeInfo;
3554e5dd7070Spatrick }
3555e5dd7070Spatrick
3556e5dd7070Spatrick break;
3557e5dd7070Spatrick }
3558e5dd7070Spatrick
3559e5dd7070Spatrick case Type::ObjCObject:
3560e5dd7070Spatrick // Ignore protocol qualifiers.
3561e5dd7070Spatrick Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
3562e5dd7070Spatrick
3563e5dd7070Spatrick // Handle id and Class.
3564e5dd7070Spatrick if (isa<BuiltinType>(Ty)) {
3565e5dd7070Spatrick VTableName = ClassTypeInfo;
3566e5dd7070Spatrick break;
3567e5dd7070Spatrick }
3568e5dd7070Spatrick
3569e5dd7070Spatrick assert(isa<ObjCInterfaceType>(Ty));
3570*12c85518Srobert [[fallthrough]];
3571e5dd7070Spatrick
3572e5dd7070Spatrick case Type::ObjCInterface:
3573e5dd7070Spatrick if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
3574e5dd7070Spatrick VTableName = SIClassTypeInfo;
3575e5dd7070Spatrick } else {
3576e5dd7070Spatrick VTableName = ClassTypeInfo;
3577e5dd7070Spatrick }
3578e5dd7070Spatrick break;
3579e5dd7070Spatrick
3580e5dd7070Spatrick case Type::ObjCObjectPointer:
3581e5dd7070Spatrick case Type::Pointer:
3582e5dd7070Spatrick // abi::__pointer_type_info.
3583e5dd7070Spatrick VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
3584e5dd7070Spatrick break;
3585e5dd7070Spatrick
3586e5dd7070Spatrick case Type::MemberPointer:
3587e5dd7070Spatrick // abi::__pointer_to_member_type_info.
3588e5dd7070Spatrick VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
3589e5dd7070Spatrick break;
3590e5dd7070Spatrick }
3591e5dd7070Spatrick
3592ec727ea7Spatrick llvm::Constant *VTable = nullptr;
3593ec727ea7Spatrick
3594ec727ea7Spatrick // Check if the alias exists. If it doesn't, then get or create the global.
3595ec727ea7Spatrick if (CGM.getItaniumVTableContext().isRelativeLayout())
3596ec727ea7Spatrick VTable = CGM.getModule().getNamedAlias(VTableName);
3597ec727ea7Spatrick if (!VTable)
3598ec727ea7Spatrick VTable = CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
3599ec727ea7Spatrick
3600e5dd7070Spatrick CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
3601e5dd7070Spatrick
3602e5dd7070Spatrick llvm::Type *PtrDiffTy =
3603e5dd7070Spatrick CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
3604e5dd7070Spatrick
3605e5dd7070Spatrick // The vtable address point is 2.
3606ec727ea7Spatrick if (CGM.getItaniumVTableContext().isRelativeLayout()) {
3607ec727ea7Spatrick // The vtable address point is 8 bytes after its start:
3608ec727ea7Spatrick // 4 for the offset to top + 4 for the relative offset to rtti.
3609ec727ea7Spatrick llvm::Constant *Eight = llvm::ConstantInt::get(CGM.Int32Ty, 8);
3610ec727ea7Spatrick VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
3611e5dd7070Spatrick VTable =
3612ec727ea7Spatrick llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8Ty, VTable, Eight);
3613ec727ea7Spatrick } else {
3614ec727ea7Spatrick llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
3615ec727ea7Spatrick VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8PtrTy, VTable,
3616ec727ea7Spatrick Two);
3617ec727ea7Spatrick }
3618e5dd7070Spatrick VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
3619e5dd7070Spatrick
3620e5dd7070Spatrick Fields.push_back(VTable);
3621e5dd7070Spatrick }
3622e5dd7070Spatrick
3623e5dd7070Spatrick /// Return the linkage that the type info and type info name constants
3624e5dd7070Spatrick /// should have for the given type.
getTypeInfoLinkage(CodeGenModule & CGM,QualType Ty)3625e5dd7070Spatrick static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
3626e5dd7070Spatrick QualType Ty) {
3627e5dd7070Spatrick // Itanium C++ ABI 2.9.5p7:
3628e5dd7070Spatrick // In addition, it and all of the intermediate abi::__pointer_type_info
3629e5dd7070Spatrick // structs in the chain down to the abi::__class_type_info for the
3630e5dd7070Spatrick // incomplete class type must be prevented from resolving to the
3631e5dd7070Spatrick // corresponding type_info structs for the complete class type, possibly
3632e5dd7070Spatrick // by making them local static objects. Finally, a dummy class RTTI is
3633e5dd7070Spatrick // generated for the incomplete type that will not resolve to the final
3634e5dd7070Spatrick // complete class RTTI (because the latter need not exist), possibly by
3635e5dd7070Spatrick // making it a local static object.
3636e5dd7070Spatrick if (ContainsIncompleteClassType(Ty))
3637e5dd7070Spatrick return llvm::GlobalValue::InternalLinkage;
3638e5dd7070Spatrick
3639e5dd7070Spatrick switch (Ty->getLinkage()) {
3640e5dd7070Spatrick case NoLinkage:
3641e5dd7070Spatrick case InternalLinkage:
3642e5dd7070Spatrick case UniqueExternalLinkage:
3643e5dd7070Spatrick return llvm::GlobalValue::InternalLinkage;
3644e5dd7070Spatrick
3645e5dd7070Spatrick case VisibleNoLinkage:
3646e5dd7070Spatrick case ModuleInternalLinkage:
3647e5dd7070Spatrick case ModuleLinkage:
3648e5dd7070Spatrick case ExternalLinkage:
3649e5dd7070Spatrick // RTTI is not enabled, which means that this type info struct is going
3650e5dd7070Spatrick // to be used for exception handling. Give it linkonce_odr linkage.
3651e5dd7070Spatrick if (!CGM.getLangOpts().RTTI)
3652e5dd7070Spatrick return llvm::GlobalValue::LinkOnceODRLinkage;
3653e5dd7070Spatrick
3654e5dd7070Spatrick if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
3655e5dd7070Spatrick const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
3656e5dd7070Spatrick if (RD->hasAttr<WeakAttr>())
3657e5dd7070Spatrick return llvm::GlobalValue::WeakODRLinkage;
3658e5dd7070Spatrick if (CGM.getTriple().isWindowsItaniumEnvironment())
3659e5dd7070Spatrick if (RD->hasAttr<DLLImportAttr>() &&
3660e5dd7070Spatrick ShouldUseExternalRTTIDescriptor(CGM, Ty))
3661e5dd7070Spatrick return llvm::GlobalValue::ExternalLinkage;
3662e5dd7070Spatrick // MinGW always uses LinkOnceODRLinkage for type info.
3663e5dd7070Spatrick if (RD->isDynamicClass() &&
3664e5dd7070Spatrick !CGM.getContext()
3665e5dd7070Spatrick .getTargetInfo()
3666e5dd7070Spatrick .getTriple()
3667e5dd7070Spatrick .isWindowsGNUEnvironment())
3668e5dd7070Spatrick return CGM.getVTableLinkage(RD);
3669e5dd7070Spatrick }
3670e5dd7070Spatrick
3671e5dd7070Spatrick return llvm::GlobalValue::LinkOnceODRLinkage;
3672e5dd7070Spatrick }
3673e5dd7070Spatrick
3674e5dd7070Spatrick llvm_unreachable("Invalid linkage!");
3675e5dd7070Spatrick }
3676e5dd7070Spatrick
BuildTypeInfo(QualType Ty)3677e5dd7070Spatrick llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
3678e5dd7070Spatrick // We want to operate on the canonical type.
3679e5dd7070Spatrick Ty = Ty.getCanonicalType();
3680e5dd7070Spatrick
3681e5dd7070Spatrick // Check if we've already emitted an RTTI descriptor for this type.
3682e5dd7070Spatrick SmallString<256> Name;
3683e5dd7070Spatrick llvm::raw_svector_ostream Out(Name);
3684e5dd7070Spatrick CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
3685e5dd7070Spatrick
3686e5dd7070Spatrick llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
3687e5dd7070Spatrick if (OldGV && !OldGV->isDeclaration()) {
3688e5dd7070Spatrick assert(!OldGV->hasAvailableExternallyLinkage() &&
3689e5dd7070Spatrick "available_externally typeinfos not yet implemented");
3690e5dd7070Spatrick
3691e5dd7070Spatrick return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy);
3692e5dd7070Spatrick }
3693e5dd7070Spatrick
3694e5dd7070Spatrick // Check if there is already an external RTTI descriptor for this type.
3695e5dd7070Spatrick if (IsStandardLibraryRTTIDescriptor(Ty) ||
3696e5dd7070Spatrick ShouldUseExternalRTTIDescriptor(CGM, Ty))
3697e5dd7070Spatrick return GetAddrOfExternalRTTIDescriptor(Ty);
3698e5dd7070Spatrick
3699e5dd7070Spatrick // Emit the standard library with external linkage.
3700e5dd7070Spatrick llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);
3701e5dd7070Spatrick
3702e5dd7070Spatrick // Give the type_info object and name the formal visibility of the
3703e5dd7070Spatrick // type itself.
3704e5dd7070Spatrick llvm::GlobalValue::VisibilityTypes llvmVisibility;
3705e5dd7070Spatrick if (llvm::GlobalValue::isLocalLinkage(Linkage))
3706e5dd7070Spatrick // If the linkage is local, only default visibility makes sense.
3707e5dd7070Spatrick llvmVisibility = llvm::GlobalValue::DefaultVisibility;
3708e5dd7070Spatrick else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) ==
3709e5dd7070Spatrick ItaniumCXXABI::RUK_NonUniqueHidden)
3710e5dd7070Spatrick llvmVisibility = llvm::GlobalValue::HiddenVisibility;
3711e5dd7070Spatrick else
3712e5dd7070Spatrick llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
3713e5dd7070Spatrick
3714e5dd7070Spatrick llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
3715e5dd7070Spatrick llvm::GlobalValue::DefaultStorageClass;
3716*12c85518Srobert if (auto RD = Ty->getAsCXXRecordDecl()) {
3717*12c85518Srobert if ((CGM.getTriple().isWindowsItaniumEnvironment() &&
3718*12c85518Srobert RD->hasAttr<DLLExportAttr>()) ||
3719*12c85518Srobert (CGM.shouldMapVisibilityToDLLExport(RD) &&
3720*12c85518Srobert !llvm::GlobalValue::isLocalLinkage(Linkage) &&
3721*12c85518Srobert llvmVisibility == llvm::GlobalValue::DefaultVisibility))
3722e5dd7070Spatrick DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
3723e5dd7070Spatrick }
3724e5dd7070Spatrick return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass);
3725e5dd7070Spatrick }
3726e5dd7070Spatrick
BuildTypeInfo(QualType Ty,llvm::GlobalVariable::LinkageTypes Linkage,llvm::GlobalValue::VisibilityTypes Visibility,llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass)3727e5dd7070Spatrick llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
3728e5dd7070Spatrick QualType Ty,
3729e5dd7070Spatrick llvm::GlobalVariable::LinkageTypes Linkage,
3730e5dd7070Spatrick llvm::GlobalValue::VisibilityTypes Visibility,
3731e5dd7070Spatrick llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
3732e5dd7070Spatrick // Add the vtable pointer.
3733e5dd7070Spatrick BuildVTablePointer(cast<Type>(Ty));
3734e5dd7070Spatrick
3735e5dd7070Spatrick // And the name.
3736e5dd7070Spatrick llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
3737e5dd7070Spatrick llvm::Constant *TypeNameField;
3738e5dd7070Spatrick
3739e5dd7070Spatrick // If we're supposed to demote the visibility, be sure to set a flag
3740e5dd7070Spatrick // to use a string comparison for type_info comparisons.
3741e5dd7070Spatrick ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =
3742e5dd7070Spatrick CXXABI.classifyRTTIUniqueness(Ty, Linkage);
3743e5dd7070Spatrick if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {
3744e5dd7070Spatrick // The flag is the sign bit, which on ARM64 is defined to be clear
3745e5dd7070Spatrick // for global pointers. This is very ARM64-specific.
3746e5dd7070Spatrick TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty);
3747e5dd7070Spatrick llvm::Constant *flag =
3748e5dd7070Spatrick llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63);
3749e5dd7070Spatrick TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
3750e5dd7070Spatrick TypeNameField =
3751e5dd7070Spatrick llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.Int8PtrTy);
3752e5dd7070Spatrick } else {
3753e5dd7070Spatrick TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy);
3754e5dd7070Spatrick }
3755e5dd7070Spatrick Fields.push_back(TypeNameField);
3756e5dd7070Spatrick
3757e5dd7070Spatrick switch (Ty->getTypeClass()) {
3758e5dd7070Spatrick #define TYPE(Class, Base)
3759e5dd7070Spatrick #define ABSTRACT_TYPE(Class, Base)
3760e5dd7070Spatrick #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3761e5dd7070Spatrick #define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3762e5dd7070Spatrick #define DEPENDENT_TYPE(Class, Base) case Type::Class:
3763e5dd7070Spatrick #include "clang/AST/TypeNodes.inc"
3764e5dd7070Spatrick llvm_unreachable("Non-canonical and dependent types shouldn't get here");
3765e5dd7070Spatrick
3766e5dd7070Spatrick // GCC treats vector types as fundamental types.
3767e5dd7070Spatrick case Type::Builtin:
3768e5dd7070Spatrick case Type::Vector:
3769e5dd7070Spatrick case Type::ExtVector:
3770ec727ea7Spatrick case Type::ConstantMatrix:
3771e5dd7070Spatrick case Type::Complex:
3772e5dd7070Spatrick case Type::BlockPointer:
3773e5dd7070Spatrick // Itanium C++ ABI 2.9.5p4:
3774e5dd7070Spatrick // abi::__fundamental_type_info adds no data members to std::type_info.
3775e5dd7070Spatrick break;
3776e5dd7070Spatrick
3777e5dd7070Spatrick case Type::LValueReference:
3778e5dd7070Spatrick case Type::RValueReference:
3779e5dd7070Spatrick llvm_unreachable("References shouldn't get here");
3780e5dd7070Spatrick
3781e5dd7070Spatrick case Type::Auto:
3782e5dd7070Spatrick case Type::DeducedTemplateSpecialization:
3783e5dd7070Spatrick llvm_unreachable("Undeduced type shouldn't get here");
3784e5dd7070Spatrick
3785e5dd7070Spatrick case Type::Pipe:
3786ec727ea7Spatrick break;
3787ec727ea7Spatrick
3788*12c85518Srobert case Type::BitInt:
3789ec727ea7Spatrick break;
3790e5dd7070Spatrick
3791e5dd7070Spatrick case Type::ConstantArray:
3792e5dd7070Spatrick case Type::IncompleteArray:
3793e5dd7070Spatrick case Type::VariableArray:
3794e5dd7070Spatrick // Itanium C++ ABI 2.9.5p5:
3795e5dd7070Spatrick // abi::__array_type_info adds no data members to std::type_info.
3796e5dd7070Spatrick break;
3797e5dd7070Spatrick
3798e5dd7070Spatrick case Type::FunctionNoProto:
3799e5dd7070Spatrick case Type::FunctionProto:
3800e5dd7070Spatrick // Itanium C++ ABI 2.9.5p5:
3801e5dd7070Spatrick // abi::__function_type_info adds no data members to std::type_info.
3802e5dd7070Spatrick break;
3803e5dd7070Spatrick
3804e5dd7070Spatrick case Type::Enum:
3805e5dd7070Spatrick // Itanium C++ ABI 2.9.5p5:
3806e5dd7070Spatrick // abi::__enum_type_info adds no data members to std::type_info.
3807e5dd7070Spatrick break;
3808e5dd7070Spatrick
3809e5dd7070Spatrick case Type::Record: {
3810e5dd7070Spatrick const CXXRecordDecl *RD =
3811e5dd7070Spatrick cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
3812e5dd7070Spatrick if (!RD->hasDefinition() || !RD->getNumBases()) {
3813e5dd7070Spatrick // We don't need to emit any fields.
3814e5dd7070Spatrick break;
3815e5dd7070Spatrick }
3816e5dd7070Spatrick
3817e5dd7070Spatrick if (CanUseSingleInheritance(RD))
3818e5dd7070Spatrick BuildSIClassTypeInfo(RD);
3819e5dd7070Spatrick else
3820e5dd7070Spatrick BuildVMIClassTypeInfo(RD);
3821e5dd7070Spatrick
3822e5dd7070Spatrick break;
3823e5dd7070Spatrick }
3824e5dd7070Spatrick
3825e5dd7070Spatrick case Type::ObjCObject:
3826e5dd7070Spatrick case Type::ObjCInterface:
3827e5dd7070Spatrick BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
3828e5dd7070Spatrick break;
3829e5dd7070Spatrick
3830e5dd7070Spatrick case Type::ObjCObjectPointer:
3831e5dd7070Spatrick BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
3832e5dd7070Spatrick break;
3833e5dd7070Spatrick
3834e5dd7070Spatrick case Type::Pointer:
3835e5dd7070Spatrick BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
3836e5dd7070Spatrick break;
3837e5dd7070Spatrick
3838e5dd7070Spatrick case Type::MemberPointer:
3839e5dd7070Spatrick BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
3840e5dd7070Spatrick break;
3841e5dd7070Spatrick
3842e5dd7070Spatrick case Type::Atomic:
3843e5dd7070Spatrick // No fields, at least for the moment.
3844e5dd7070Spatrick break;
3845e5dd7070Spatrick }
3846e5dd7070Spatrick
3847e5dd7070Spatrick llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
3848e5dd7070Spatrick
3849e5dd7070Spatrick SmallString<256> Name;
3850e5dd7070Spatrick llvm::raw_svector_ostream Out(Name);
3851e5dd7070Spatrick CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
3852e5dd7070Spatrick llvm::Module &M = CGM.getModule();
3853e5dd7070Spatrick llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
3854e5dd7070Spatrick llvm::GlobalVariable *GV =
3855e5dd7070Spatrick new llvm::GlobalVariable(M, Init->getType(),
3856e5dd7070Spatrick /*isConstant=*/true, Linkage, Init, Name);
3857e5dd7070Spatrick
3858a9ac8606Spatrick // Export the typeinfo in the same circumstances as the vtable is exported.
3859a9ac8606Spatrick auto GVDLLStorageClass = DLLStorageClass;
3860a9ac8606Spatrick if (CGM.getTarget().hasPS4DLLImportExport()) {
3861a9ac8606Spatrick if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3862a9ac8606Spatrick const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
3863a9ac8606Spatrick if (RD->hasAttr<DLLExportAttr>() ||
3864a9ac8606Spatrick CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD)) {
3865a9ac8606Spatrick GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
3866a9ac8606Spatrick }
3867a9ac8606Spatrick }
3868a9ac8606Spatrick }
3869a9ac8606Spatrick
3870e5dd7070Spatrick // If there's already an old global variable, replace it with the new one.
3871e5dd7070Spatrick if (OldGV) {
3872e5dd7070Spatrick GV->takeName(OldGV);
3873e5dd7070Spatrick llvm::Constant *NewPtr =
3874e5dd7070Spatrick llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
3875e5dd7070Spatrick OldGV->replaceAllUsesWith(NewPtr);
3876e5dd7070Spatrick OldGV->eraseFromParent();
3877e5dd7070Spatrick }
3878e5dd7070Spatrick
3879e5dd7070Spatrick if (CGM.supportsCOMDAT() && GV->isWeakForLinker())
3880e5dd7070Spatrick GV->setComdat(M.getOrInsertComdat(GV->getName()));
3881e5dd7070Spatrick
3882*12c85518Srobert CharUnits Align = CGM.getContext().toCharUnitsFromBits(
3883*12c85518Srobert CGM.getTarget().getPointerAlign(LangAS::Default));
3884e5dd7070Spatrick GV->setAlignment(Align.getAsAlign());
3885e5dd7070Spatrick
3886e5dd7070Spatrick // The Itanium ABI specifies that type_info objects must be globally
3887e5dd7070Spatrick // unique, with one exception: if the type is an incomplete class
3888e5dd7070Spatrick // type or a (possibly indirect) pointer to one. That exception
3889e5dd7070Spatrick // affects the general case of comparing type_info objects produced
3890e5dd7070Spatrick // by the typeid operator, which is why the comparison operators on
3891e5dd7070Spatrick // std::type_info generally use the type_info name pointers instead
3892e5dd7070Spatrick // of the object addresses. However, the language's built-in uses
3893e5dd7070Spatrick // of RTTI generally require class types to be complete, even when
3894e5dd7070Spatrick // manipulating pointers to those class types. This allows the
3895e5dd7070Spatrick // implementation of dynamic_cast to rely on address equality tests,
3896e5dd7070Spatrick // which is much faster.
3897e5dd7070Spatrick
3898e5dd7070Spatrick // All of this is to say that it's important that both the type_info
3899e5dd7070Spatrick // object and the type_info name be uniqued when weakly emitted.
3900e5dd7070Spatrick
3901e5dd7070Spatrick TypeName->setVisibility(Visibility);
3902e5dd7070Spatrick CGM.setDSOLocal(TypeName);
3903e5dd7070Spatrick
3904e5dd7070Spatrick GV->setVisibility(Visibility);
3905e5dd7070Spatrick CGM.setDSOLocal(GV);
3906e5dd7070Spatrick
3907e5dd7070Spatrick TypeName->setDLLStorageClass(DLLStorageClass);
3908a9ac8606Spatrick GV->setDLLStorageClass(CGM.getTarget().hasPS4DLLImportExport()
3909a9ac8606Spatrick ? GVDLLStorageClass
3910a9ac8606Spatrick : DLLStorageClass);
3911e5dd7070Spatrick
3912e5dd7070Spatrick TypeName->setPartition(CGM.getCodeGenOpts().SymbolPartition);
3913e5dd7070Spatrick GV->setPartition(CGM.getCodeGenOpts().SymbolPartition);
3914e5dd7070Spatrick
3915e5dd7070Spatrick return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
3916e5dd7070Spatrick }
3917e5dd7070Spatrick
3918e5dd7070Spatrick /// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
3919e5dd7070Spatrick /// for the given Objective-C object type.
BuildObjCObjectTypeInfo(const ObjCObjectType * OT)3920e5dd7070Spatrick void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
3921e5dd7070Spatrick // Drop qualifiers.
3922e5dd7070Spatrick const Type *T = OT->getBaseType().getTypePtr();
3923e5dd7070Spatrick assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
3924e5dd7070Spatrick
3925e5dd7070Spatrick // The builtin types are abi::__class_type_infos and don't require
3926e5dd7070Spatrick // extra fields.
3927e5dd7070Spatrick if (isa<BuiltinType>(T)) return;
3928e5dd7070Spatrick
3929e5dd7070Spatrick ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
3930e5dd7070Spatrick ObjCInterfaceDecl *Super = Class->getSuperClass();
3931e5dd7070Spatrick
3932e5dd7070Spatrick // Root classes are also __class_type_info.
3933e5dd7070Spatrick if (!Super) return;
3934e5dd7070Spatrick
3935e5dd7070Spatrick QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
3936e5dd7070Spatrick
3937e5dd7070Spatrick // Everything else is single inheritance.
3938e5dd7070Spatrick llvm::Constant *BaseTypeInfo =
3939e5dd7070Spatrick ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(SuperTy);
3940e5dd7070Spatrick Fields.push_back(BaseTypeInfo);
3941e5dd7070Spatrick }
3942e5dd7070Spatrick
3943e5dd7070Spatrick /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
3944e5dd7070Spatrick /// inheritance, according to the Itanium C++ ABI, 2.95p6b.
BuildSIClassTypeInfo(const CXXRecordDecl * RD)3945e5dd7070Spatrick void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
3946e5dd7070Spatrick // Itanium C++ ABI 2.9.5p6b:
3947e5dd7070Spatrick // It adds to abi::__class_type_info a single member pointing to the
3948e5dd7070Spatrick // type_info structure for the base type,
3949e5dd7070Spatrick llvm::Constant *BaseTypeInfo =
3950e5dd7070Spatrick ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType());
3951e5dd7070Spatrick Fields.push_back(BaseTypeInfo);
3952e5dd7070Spatrick }
3953e5dd7070Spatrick
3954e5dd7070Spatrick namespace {
3955e5dd7070Spatrick /// SeenBases - Contains virtual and non-virtual bases seen when traversing
3956e5dd7070Spatrick /// a class hierarchy.
3957e5dd7070Spatrick struct SeenBases {
3958e5dd7070Spatrick llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
3959e5dd7070Spatrick llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
3960e5dd7070Spatrick };
3961e5dd7070Spatrick }
3962e5dd7070Spatrick
3963e5dd7070Spatrick /// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
3964e5dd7070Spatrick /// abi::__vmi_class_type_info.
3965e5dd7070Spatrick ///
ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier * Base,SeenBases & Bases)3966e5dd7070Spatrick static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
3967e5dd7070Spatrick SeenBases &Bases) {
3968e5dd7070Spatrick
3969e5dd7070Spatrick unsigned Flags = 0;
3970e5dd7070Spatrick
3971e5dd7070Spatrick auto *BaseDecl =
3972e5dd7070Spatrick cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
3973e5dd7070Spatrick
3974e5dd7070Spatrick if (Base->isVirtual()) {
3975e5dd7070Spatrick // Mark the virtual base as seen.
3976e5dd7070Spatrick if (!Bases.VirtualBases.insert(BaseDecl).second) {
3977e5dd7070Spatrick // If this virtual base has been seen before, then the class is diamond
3978e5dd7070Spatrick // shaped.
3979e5dd7070Spatrick Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
3980e5dd7070Spatrick } else {
3981e5dd7070Spatrick if (Bases.NonVirtualBases.count(BaseDecl))
3982e5dd7070Spatrick Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
3983e5dd7070Spatrick }
3984e5dd7070Spatrick } else {
3985e5dd7070Spatrick // Mark the non-virtual base as seen.
3986e5dd7070Spatrick if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
3987e5dd7070Spatrick // If this non-virtual base has been seen before, then the class has non-
3988e5dd7070Spatrick // diamond shaped repeated inheritance.
3989e5dd7070Spatrick Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
3990e5dd7070Spatrick } else {
3991e5dd7070Spatrick if (Bases.VirtualBases.count(BaseDecl))
3992e5dd7070Spatrick Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
3993e5dd7070Spatrick }
3994e5dd7070Spatrick }
3995e5dd7070Spatrick
3996e5dd7070Spatrick // Walk all bases.
3997e5dd7070Spatrick for (const auto &I : BaseDecl->bases())
3998e5dd7070Spatrick Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
3999e5dd7070Spatrick
4000e5dd7070Spatrick return Flags;
4001e5dd7070Spatrick }
4002e5dd7070Spatrick
ComputeVMIClassTypeInfoFlags(const CXXRecordDecl * RD)4003e5dd7070Spatrick static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
4004e5dd7070Spatrick unsigned Flags = 0;
4005e5dd7070Spatrick SeenBases Bases;
4006e5dd7070Spatrick
4007e5dd7070Spatrick // Walk all bases.
4008e5dd7070Spatrick for (const auto &I : RD->bases())
4009e5dd7070Spatrick Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
4010e5dd7070Spatrick
4011e5dd7070Spatrick return Flags;
4012e5dd7070Spatrick }
4013e5dd7070Spatrick
4014e5dd7070Spatrick /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
4015e5dd7070Spatrick /// classes with bases that do not satisfy the abi::__si_class_type_info
4016e5dd7070Spatrick /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
BuildVMIClassTypeInfo(const CXXRecordDecl * RD)4017e5dd7070Spatrick void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
4018e5dd7070Spatrick llvm::Type *UnsignedIntLTy =
4019e5dd7070Spatrick CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
4020e5dd7070Spatrick
4021e5dd7070Spatrick // Itanium C++ ABI 2.9.5p6c:
4022e5dd7070Spatrick // __flags is a word with flags describing details about the class
4023e5dd7070Spatrick // structure, which may be referenced by using the __flags_masks
4024e5dd7070Spatrick // enumeration. These flags refer to both direct and indirect bases.
4025e5dd7070Spatrick unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);
4026e5dd7070Spatrick Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4027e5dd7070Spatrick
4028e5dd7070Spatrick // Itanium C++ ABI 2.9.5p6c:
4029e5dd7070Spatrick // __base_count is a word with the number of direct proper base class
4030e5dd7070Spatrick // descriptions that follow.
4031e5dd7070Spatrick Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
4032e5dd7070Spatrick
4033e5dd7070Spatrick if (!RD->getNumBases())
4034e5dd7070Spatrick return;
4035e5dd7070Spatrick
4036e5dd7070Spatrick // Now add the base class descriptions.
4037e5dd7070Spatrick
4038e5dd7070Spatrick // Itanium C++ ABI 2.9.5p6c:
4039e5dd7070Spatrick // __base_info[] is an array of base class descriptions -- one for every
4040e5dd7070Spatrick // direct proper base. Each description is of the type:
4041e5dd7070Spatrick //
4042e5dd7070Spatrick // struct abi::__base_class_type_info {
4043e5dd7070Spatrick // public:
4044e5dd7070Spatrick // const __class_type_info *__base_type;
4045e5dd7070Spatrick // long __offset_flags;
4046e5dd7070Spatrick //
4047e5dd7070Spatrick // enum __offset_flags_masks {
4048e5dd7070Spatrick // __virtual_mask = 0x1,
4049e5dd7070Spatrick // __public_mask = 0x2,
4050e5dd7070Spatrick // __offset_shift = 8
4051e5dd7070Spatrick // };
4052e5dd7070Spatrick // };
4053e5dd7070Spatrick
4054e5dd7070Spatrick // If we're in mingw and 'long' isn't wide enough for a pointer, use 'long
4055e5dd7070Spatrick // long' instead of 'long' for __offset_flags. libstdc++abi uses long long on
4056e5dd7070Spatrick // LLP64 platforms.
4057e5dd7070Spatrick // FIXME: Consider updating libc++abi to match, and extend this logic to all
4058e5dd7070Spatrick // LLP64 platforms.
4059e5dd7070Spatrick QualType OffsetFlagsTy = CGM.getContext().LongTy;
4060e5dd7070Spatrick const TargetInfo &TI = CGM.getContext().getTargetInfo();
4061*12c85518Srobert if (TI.getTriple().isOSCygMing() &&
4062*12c85518Srobert TI.getPointerWidth(LangAS::Default) > TI.getLongWidth())
4063e5dd7070Spatrick OffsetFlagsTy = CGM.getContext().LongLongTy;
4064e5dd7070Spatrick llvm::Type *OffsetFlagsLTy =
4065e5dd7070Spatrick CGM.getTypes().ConvertType(OffsetFlagsTy);
4066e5dd7070Spatrick
4067e5dd7070Spatrick for (const auto &Base : RD->bases()) {
4068e5dd7070Spatrick // The __base_type member points to the RTTI for the base type.
4069e5dd7070Spatrick Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));
4070e5dd7070Spatrick
4071e5dd7070Spatrick auto *BaseDecl =
4072e5dd7070Spatrick cast<CXXRecordDecl>(Base.getType()->castAs<RecordType>()->getDecl());
4073e5dd7070Spatrick
4074e5dd7070Spatrick int64_t OffsetFlags = 0;
4075e5dd7070Spatrick
4076e5dd7070Spatrick // All but the lower 8 bits of __offset_flags are a signed offset.
4077e5dd7070Spatrick // For a non-virtual base, this is the offset in the object of the base
4078e5dd7070Spatrick // subobject. For a virtual base, this is the offset in the virtual table of
4079e5dd7070Spatrick // the virtual base offset for the virtual base referenced (negative).
4080e5dd7070Spatrick CharUnits Offset;
4081e5dd7070Spatrick if (Base.isVirtual())
4082e5dd7070Spatrick Offset =
4083e5dd7070Spatrick CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
4084e5dd7070Spatrick else {
4085e5dd7070Spatrick const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
4086e5dd7070Spatrick Offset = Layout.getBaseClassOffset(BaseDecl);
4087e5dd7070Spatrick };
4088e5dd7070Spatrick
4089e5dd7070Spatrick OffsetFlags = uint64_t(Offset.getQuantity()) << 8;
4090e5dd7070Spatrick
4091e5dd7070Spatrick // The low-order byte of __offset_flags contains flags, as given by the
4092e5dd7070Spatrick // masks from the enumeration __offset_flags_masks.
4093e5dd7070Spatrick if (Base.isVirtual())
4094e5dd7070Spatrick OffsetFlags |= BCTI_Virtual;
4095e5dd7070Spatrick if (Base.getAccessSpecifier() == AS_public)
4096e5dd7070Spatrick OffsetFlags |= BCTI_Public;
4097e5dd7070Spatrick
4098e5dd7070Spatrick Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags));
4099e5dd7070Spatrick }
4100e5dd7070Spatrick }
4101e5dd7070Spatrick
4102e5dd7070Spatrick /// Compute the flags for a __pbase_type_info, and remove the corresponding
4103e5dd7070Spatrick /// pieces from \p Type.
extractPBaseFlags(ASTContext & Ctx,QualType & Type)4104e5dd7070Spatrick static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) {
4105e5dd7070Spatrick unsigned Flags = 0;
4106e5dd7070Spatrick
4107e5dd7070Spatrick if (Type.isConstQualified())
4108e5dd7070Spatrick Flags |= ItaniumRTTIBuilder::PTI_Const;
4109e5dd7070Spatrick if (Type.isVolatileQualified())
4110e5dd7070Spatrick Flags |= ItaniumRTTIBuilder::PTI_Volatile;
4111e5dd7070Spatrick if (Type.isRestrictQualified())
4112e5dd7070Spatrick Flags |= ItaniumRTTIBuilder::PTI_Restrict;
4113e5dd7070Spatrick Type = Type.getUnqualifiedType();
4114e5dd7070Spatrick
4115e5dd7070Spatrick // Itanium C++ ABI 2.9.5p7:
4116e5dd7070Spatrick // When the abi::__pbase_type_info is for a direct or indirect pointer to an
4117e5dd7070Spatrick // incomplete class type, the incomplete target type flag is set.
4118e5dd7070Spatrick if (ContainsIncompleteClassType(Type))
4119e5dd7070Spatrick Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
4120e5dd7070Spatrick
4121e5dd7070Spatrick if (auto *Proto = Type->getAs<FunctionProtoType>()) {
4122e5dd7070Spatrick if (Proto->isNothrow()) {
4123e5dd7070Spatrick Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
4124e5dd7070Spatrick Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None);
4125e5dd7070Spatrick }
4126e5dd7070Spatrick }
4127e5dd7070Spatrick
4128e5dd7070Spatrick return Flags;
4129e5dd7070Spatrick }
4130e5dd7070Spatrick
4131e5dd7070Spatrick /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
4132e5dd7070Spatrick /// used for pointer types.
BuildPointerTypeInfo(QualType PointeeTy)4133e5dd7070Spatrick void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
4134e5dd7070Spatrick // Itanium C++ ABI 2.9.5p7:
4135e5dd7070Spatrick // __flags is a flag word describing the cv-qualification and other
4136e5dd7070Spatrick // attributes of the type pointed to
4137e5dd7070Spatrick unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
4138e5dd7070Spatrick
4139e5dd7070Spatrick llvm::Type *UnsignedIntLTy =
4140e5dd7070Spatrick CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
4141e5dd7070Spatrick Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4142e5dd7070Spatrick
4143e5dd7070Spatrick // Itanium C++ ABI 2.9.5p7:
4144e5dd7070Spatrick // __pointee is a pointer to the std::type_info derivation for the
4145e5dd7070Spatrick // unqualified type being pointed to.
4146e5dd7070Spatrick llvm::Constant *PointeeTypeInfo =
4147e5dd7070Spatrick ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
4148e5dd7070Spatrick Fields.push_back(PointeeTypeInfo);
4149e5dd7070Spatrick }
4150e5dd7070Spatrick
4151e5dd7070Spatrick /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
4152e5dd7070Spatrick /// struct, used for member pointer types.
4153e5dd7070Spatrick void
BuildPointerToMemberTypeInfo(const MemberPointerType * Ty)4154e5dd7070Spatrick ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
4155e5dd7070Spatrick QualType PointeeTy = Ty->getPointeeType();
4156e5dd7070Spatrick
4157e5dd7070Spatrick // Itanium C++ ABI 2.9.5p7:
4158e5dd7070Spatrick // __flags is a flag word describing the cv-qualification and other
4159e5dd7070Spatrick // attributes of the type pointed to.
4160e5dd7070Spatrick unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
4161e5dd7070Spatrick
4162e5dd7070Spatrick const RecordType *ClassType = cast<RecordType>(Ty->getClass());
4163e5dd7070Spatrick if (IsIncompleteClassType(ClassType))
4164e5dd7070Spatrick Flags |= PTI_ContainingClassIncomplete;
4165e5dd7070Spatrick
4166e5dd7070Spatrick llvm::Type *UnsignedIntLTy =
4167e5dd7070Spatrick CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
4168e5dd7070Spatrick Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4169e5dd7070Spatrick
4170e5dd7070Spatrick // Itanium C++ ABI 2.9.5p7:
4171e5dd7070Spatrick // __pointee is a pointer to the std::type_info derivation for the
4172e5dd7070Spatrick // unqualified type being pointed to.
4173e5dd7070Spatrick llvm::Constant *PointeeTypeInfo =
4174e5dd7070Spatrick ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
4175e5dd7070Spatrick Fields.push_back(PointeeTypeInfo);
4176e5dd7070Spatrick
4177e5dd7070Spatrick // Itanium C++ ABI 2.9.5p9:
4178e5dd7070Spatrick // __context is a pointer to an abi::__class_type_info corresponding to the
4179e5dd7070Spatrick // class type containing the member pointed to
4180e5dd7070Spatrick // (e.g., the "A" in "int A::*").
4181e5dd7070Spatrick Fields.push_back(
4182e5dd7070Spatrick ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0)));
4183e5dd7070Spatrick }
4184e5dd7070Spatrick
getAddrOfRTTIDescriptor(QualType Ty)4185e5dd7070Spatrick llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
4186e5dd7070Spatrick return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
4187e5dd7070Spatrick }
4188e5dd7070Spatrick
EmitFundamentalRTTIDescriptors(const CXXRecordDecl * RD)4189e5dd7070Spatrick void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
4190e5dd7070Spatrick // Types added here must also be added to TypeInfoIsInStandardLibrary.
4191e5dd7070Spatrick QualType FundamentalTypes[] = {
4192e5dd7070Spatrick getContext().VoidTy, getContext().NullPtrTy,
4193e5dd7070Spatrick getContext().BoolTy, getContext().WCharTy,
4194e5dd7070Spatrick getContext().CharTy, getContext().UnsignedCharTy,
4195e5dd7070Spatrick getContext().SignedCharTy, getContext().ShortTy,
4196e5dd7070Spatrick getContext().UnsignedShortTy, getContext().IntTy,
4197e5dd7070Spatrick getContext().UnsignedIntTy, getContext().LongTy,
4198e5dd7070Spatrick getContext().UnsignedLongTy, getContext().LongLongTy,
4199e5dd7070Spatrick getContext().UnsignedLongLongTy, getContext().Int128Ty,
4200e5dd7070Spatrick getContext().UnsignedInt128Ty, getContext().HalfTy,
4201e5dd7070Spatrick getContext().FloatTy, getContext().DoubleTy,
4202e5dd7070Spatrick getContext().LongDoubleTy, getContext().Float128Ty,
4203e5dd7070Spatrick getContext().Char8Ty, getContext().Char16Ty,
4204e5dd7070Spatrick getContext().Char32Ty
4205e5dd7070Spatrick };
4206e5dd7070Spatrick llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4207*12c85518Srobert RD->hasAttr<DLLExportAttr>() || CGM.shouldMapVisibilityToDLLExport(RD)
4208e5dd7070Spatrick ? llvm::GlobalValue::DLLExportStorageClass
4209e5dd7070Spatrick : llvm::GlobalValue::DefaultStorageClass;
4210e5dd7070Spatrick llvm::GlobalValue::VisibilityTypes Visibility =
4211e5dd7070Spatrick CodeGenModule::GetLLVMVisibility(RD->getVisibility());
4212e5dd7070Spatrick for (const QualType &FundamentalType : FundamentalTypes) {
4213e5dd7070Spatrick QualType PointerType = getContext().getPointerType(FundamentalType);
4214e5dd7070Spatrick QualType PointerTypeConst = getContext().getPointerType(
4215e5dd7070Spatrick FundamentalType.withConst());
4216e5dd7070Spatrick for (QualType Type : {FundamentalType, PointerType, PointerTypeConst})
4217e5dd7070Spatrick ItaniumRTTIBuilder(*this).BuildTypeInfo(
4218e5dd7070Spatrick Type, llvm::GlobalValue::ExternalLinkage,
4219e5dd7070Spatrick Visibility, DLLStorageClass);
4220e5dd7070Spatrick }
4221e5dd7070Spatrick }
4222e5dd7070Spatrick
4223e5dd7070Spatrick /// What sort of uniqueness rules should we use for the RTTI for the
4224e5dd7070Spatrick /// given type?
classifyRTTIUniqueness(QualType CanTy,llvm::GlobalValue::LinkageTypes Linkage) const4225e5dd7070Spatrick ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
4226e5dd7070Spatrick QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const {
4227e5dd7070Spatrick if (shouldRTTIBeUnique())
4228e5dd7070Spatrick return RUK_Unique;
4229e5dd7070Spatrick
4230e5dd7070Spatrick // It's only necessary for linkonce_odr or weak_odr linkage.
4231e5dd7070Spatrick if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
4232e5dd7070Spatrick Linkage != llvm::GlobalValue::WeakODRLinkage)
4233e5dd7070Spatrick return RUK_Unique;
4234e5dd7070Spatrick
4235e5dd7070Spatrick // It's only necessary with default visibility.
4236e5dd7070Spatrick if (CanTy->getVisibility() != DefaultVisibility)
4237e5dd7070Spatrick return RUK_Unique;
4238e5dd7070Spatrick
4239e5dd7070Spatrick // If we're not required to publish this symbol, hide it.
4240e5dd7070Spatrick if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
4241e5dd7070Spatrick return RUK_NonUniqueHidden;
4242e5dd7070Spatrick
4243e5dd7070Spatrick // If we're required to publish this symbol, as we might be under an
4244e5dd7070Spatrick // explicit instantiation, leave it with default visibility but
4245e5dd7070Spatrick // enable string-comparisons.
4246e5dd7070Spatrick assert(Linkage == llvm::GlobalValue::WeakODRLinkage);
4247e5dd7070Spatrick return RUK_NonUniqueVisible;
4248e5dd7070Spatrick }
4249e5dd7070Spatrick
4250e5dd7070Spatrick // Find out how to codegen the complete destructor and constructor
4251e5dd7070Spatrick namespace {
4252e5dd7070Spatrick enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
4253e5dd7070Spatrick }
getCodegenToUse(CodeGenModule & CGM,const CXXMethodDecl * MD)4254e5dd7070Spatrick static StructorCodegen getCodegenToUse(CodeGenModule &CGM,
4255e5dd7070Spatrick const CXXMethodDecl *MD) {
4256e5dd7070Spatrick if (!CGM.getCodeGenOpts().CXXCtorDtorAliases)
4257e5dd7070Spatrick return StructorCodegen::Emit;
4258e5dd7070Spatrick
4259e5dd7070Spatrick // The complete and base structors are not equivalent if there are any virtual
4260e5dd7070Spatrick // bases, so emit separate functions.
4261e5dd7070Spatrick if (MD->getParent()->getNumVBases())
4262e5dd7070Spatrick return StructorCodegen::Emit;
4263e5dd7070Spatrick
4264e5dd7070Spatrick GlobalDecl AliasDecl;
4265e5dd7070Spatrick if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
4266e5dd7070Spatrick AliasDecl = GlobalDecl(DD, Dtor_Complete);
4267e5dd7070Spatrick } else {
4268e5dd7070Spatrick const auto *CD = cast<CXXConstructorDecl>(MD);
4269e5dd7070Spatrick AliasDecl = GlobalDecl(CD, Ctor_Complete);
4270e5dd7070Spatrick }
4271e5dd7070Spatrick llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl);
4272e5dd7070Spatrick
4273e5dd7070Spatrick if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))
4274e5dd7070Spatrick return StructorCodegen::RAUW;
4275e5dd7070Spatrick
4276e5dd7070Spatrick // FIXME: Should we allow available_externally aliases?
4277e5dd7070Spatrick if (!llvm::GlobalAlias::isValidLinkage(Linkage))
4278e5dd7070Spatrick return StructorCodegen::RAUW;
4279e5dd7070Spatrick
4280e5dd7070Spatrick if (llvm::GlobalValue::isWeakForLinker(Linkage)) {
4281e5dd7070Spatrick // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
4282e5dd7070Spatrick if (CGM.getTarget().getTriple().isOSBinFormatELF() ||
4283e5dd7070Spatrick CGM.getTarget().getTriple().isOSBinFormatWasm())
4284e5dd7070Spatrick return StructorCodegen::COMDAT;
4285e5dd7070Spatrick return StructorCodegen::Emit;
4286e5dd7070Spatrick }
4287e5dd7070Spatrick
4288e5dd7070Spatrick return StructorCodegen::Alias;
4289e5dd7070Spatrick }
4290e5dd7070Spatrick
emitConstructorDestructorAlias(CodeGenModule & CGM,GlobalDecl AliasDecl,GlobalDecl TargetDecl)4291e5dd7070Spatrick static void emitConstructorDestructorAlias(CodeGenModule &CGM,
4292e5dd7070Spatrick GlobalDecl AliasDecl,
4293e5dd7070Spatrick GlobalDecl TargetDecl) {
4294e5dd7070Spatrick llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl);
4295e5dd7070Spatrick
4296e5dd7070Spatrick StringRef MangledName = CGM.getMangledName(AliasDecl);
4297e5dd7070Spatrick llvm::GlobalValue *Entry = CGM.GetGlobalValue(MangledName);
4298e5dd7070Spatrick if (Entry && !Entry->isDeclaration())
4299e5dd7070Spatrick return;
4300e5dd7070Spatrick
4301e5dd7070Spatrick auto *Aliasee = cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(TargetDecl));
4302e5dd7070Spatrick
4303e5dd7070Spatrick // Create the alias with no name.
4304e5dd7070Spatrick auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee);
4305e5dd7070Spatrick
4306e5dd7070Spatrick // Constructors and destructors are always unnamed_addr.
4307e5dd7070Spatrick Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4308e5dd7070Spatrick
4309e5dd7070Spatrick // Switch any previous uses to the alias.
4310e5dd7070Spatrick if (Entry) {
4311e5dd7070Spatrick assert(Entry->getType() == Aliasee->getType() &&
4312e5dd7070Spatrick "declaration exists with different type");
4313e5dd7070Spatrick Alias->takeName(Entry);
4314e5dd7070Spatrick Entry->replaceAllUsesWith(Alias);
4315e5dd7070Spatrick Entry->eraseFromParent();
4316e5dd7070Spatrick } else {
4317e5dd7070Spatrick Alias->setName(MangledName);
4318e5dd7070Spatrick }
4319e5dd7070Spatrick
4320e5dd7070Spatrick // Finally, set up the alias with its proper name and attributes.
4321e5dd7070Spatrick CGM.SetCommonAttributes(AliasDecl, Alias);
4322e5dd7070Spatrick }
4323e5dd7070Spatrick
emitCXXStructor(GlobalDecl GD)4324e5dd7070Spatrick void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {
4325e5dd7070Spatrick auto *MD = cast<CXXMethodDecl>(GD.getDecl());
4326e5dd7070Spatrick auto *CD = dyn_cast<CXXConstructorDecl>(MD);
4327e5dd7070Spatrick const CXXDestructorDecl *DD = CD ? nullptr : cast<CXXDestructorDecl>(MD);
4328e5dd7070Spatrick
4329e5dd7070Spatrick StructorCodegen CGType = getCodegenToUse(CGM, MD);
4330e5dd7070Spatrick
4331e5dd7070Spatrick if (CD ? GD.getCtorType() == Ctor_Complete
4332e5dd7070Spatrick : GD.getDtorType() == Dtor_Complete) {
4333e5dd7070Spatrick GlobalDecl BaseDecl;
4334e5dd7070Spatrick if (CD)
4335e5dd7070Spatrick BaseDecl = GD.getWithCtorType(Ctor_Base);
4336e5dd7070Spatrick else
4337e5dd7070Spatrick BaseDecl = GD.getWithDtorType(Dtor_Base);
4338e5dd7070Spatrick
4339e5dd7070Spatrick if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {
4340e5dd7070Spatrick emitConstructorDestructorAlias(CGM, GD, BaseDecl);
4341e5dd7070Spatrick return;
4342e5dd7070Spatrick }
4343e5dd7070Spatrick
4344e5dd7070Spatrick if (CGType == StructorCodegen::RAUW) {
4345e5dd7070Spatrick StringRef MangledName = CGM.getMangledName(GD);
4346e5dd7070Spatrick auto *Aliasee = CGM.GetAddrOfGlobal(BaseDecl);
4347e5dd7070Spatrick CGM.addReplacement(MangledName, Aliasee);
4348e5dd7070Spatrick return;
4349e5dd7070Spatrick }
4350e5dd7070Spatrick }
4351e5dd7070Spatrick
4352e5dd7070Spatrick // The base destructor is equivalent to the base destructor of its
4353e5dd7070Spatrick // base class if there is exactly one non-virtual base class with a
4354e5dd7070Spatrick // non-trivial destructor, there are no fields with a non-trivial
4355e5dd7070Spatrick // destructor, and the body of the destructor is trivial.
4356e5dd7070Spatrick if (DD && GD.getDtorType() == Dtor_Base &&
4357e5dd7070Spatrick CGType != StructorCodegen::COMDAT &&
4358e5dd7070Spatrick !CGM.TryEmitBaseDestructorAsAlias(DD))
4359e5dd7070Spatrick return;
4360e5dd7070Spatrick
4361e5dd7070Spatrick // FIXME: The deleting destructor is equivalent to the selected operator
4362e5dd7070Spatrick // delete if:
4363e5dd7070Spatrick // * either the delete is a destroying operator delete or the destructor
4364e5dd7070Spatrick // would be trivial if it weren't virtual,
4365e5dd7070Spatrick // * the conversion from the 'this' parameter to the first parameter of the
4366e5dd7070Spatrick // destructor is equivalent to a bitcast,
4367e5dd7070Spatrick // * the destructor does not have an implicit "this" return, and
4368e5dd7070Spatrick // * the operator delete has the same calling convention and IR function type
4369e5dd7070Spatrick // as the destructor.
4370e5dd7070Spatrick // In such cases we should try to emit the deleting dtor as an alias to the
4371e5dd7070Spatrick // selected 'operator delete'.
4372e5dd7070Spatrick
4373e5dd7070Spatrick llvm::Function *Fn = CGM.codegenCXXStructor(GD);
4374e5dd7070Spatrick
4375e5dd7070Spatrick if (CGType == StructorCodegen::COMDAT) {
4376e5dd7070Spatrick SmallString<256> Buffer;
4377e5dd7070Spatrick llvm::raw_svector_ostream Out(Buffer);
4378e5dd7070Spatrick if (DD)
4379e5dd7070Spatrick getMangleContext().mangleCXXDtorComdat(DD, Out);
4380e5dd7070Spatrick else
4381e5dd7070Spatrick getMangleContext().mangleCXXCtorComdat(CD, Out);
4382e5dd7070Spatrick llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str());
4383e5dd7070Spatrick Fn->setComdat(C);
4384e5dd7070Spatrick } else {
4385e5dd7070Spatrick CGM.maybeSetTrivialComdat(*MD, *Fn);
4386e5dd7070Spatrick }
4387e5dd7070Spatrick }
4388e5dd7070Spatrick
getBeginCatchFn(CodeGenModule & CGM)4389e5dd7070Spatrick static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM) {
4390e5dd7070Spatrick // void *__cxa_begin_catch(void*);
4391e5dd7070Spatrick llvm::FunctionType *FTy = llvm::FunctionType::get(
4392e5dd7070Spatrick CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
4393e5dd7070Spatrick
4394e5dd7070Spatrick return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
4395e5dd7070Spatrick }
4396e5dd7070Spatrick
getEndCatchFn(CodeGenModule & CGM)4397e5dd7070Spatrick static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) {
4398e5dd7070Spatrick // void __cxa_end_catch();
4399e5dd7070Spatrick llvm::FunctionType *FTy =
4400e5dd7070Spatrick llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
4401e5dd7070Spatrick
4402e5dd7070Spatrick return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");
4403e5dd7070Spatrick }
4404e5dd7070Spatrick
getGetExceptionPtrFn(CodeGenModule & CGM)4405e5dd7070Spatrick static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM) {
4406e5dd7070Spatrick // void *__cxa_get_exception_ptr(void*);
4407e5dd7070Spatrick llvm::FunctionType *FTy = llvm::FunctionType::get(
4408e5dd7070Spatrick CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
4409e5dd7070Spatrick
4410e5dd7070Spatrick return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");
4411e5dd7070Spatrick }
4412e5dd7070Spatrick
4413e5dd7070Spatrick namespace {
4414e5dd7070Spatrick /// A cleanup to call __cxa_end_catch. In many cases, the caught
4415e5dd7070Spatrick /// exception type lets us state definitively that the thrown exception
4416e5dd7070Spatrick /// type does not have a destructor. In particular:
4417e5dd7070Spatrick /// - Catch-alls tell us nothing, so we have to conservatively
4418e5dd7070Spatrick /// assume that the thrown exception might have a destructor.
4419e5dd7070Spatrick /// - Catches by reference behave according to their base types.
4420e5dd7070Spatrick /// - Catches of non-record types will only trigger for exceptions
4421e5dd7070Spatrick /// of non-record types, which never have destructors.
4422e5dd7070Spatrick /// - Catches of record types can trigger for arbitrary subclasses
4423e5dd7070Spatrick /// of the caught type, so we have to assume the actual thrown
4424e5dd7070Spatrick /// exception type might have a throwing destructor, even if the
4425e5dd7070Spatrick /// caught type's destructor is trivial or nothrow.
4426e5dd7070Spatrick struct CallEndCatch final : EHScopeStack::Cleanup {
CallEndCatch__anon449188eb0911::CallEndCatch4427e5dd7070Spatrick CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
4428e5dd7070Spatrick bool MightThrow;
4429e5dd7070Spatrick
Emit__anon449188eb0911::CallEndCatch4430e5dd7070Spatrick void Emit(CodeGenFunction &CGF, Flags flags) override {
4431e5dd7070Spatrick if (!MightThrow) {
4432e5dd7070Spatrick CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));
4433e5dd7070Spatrick return;
4434e5dd7070Spatrick }
4435e5dd7070Spatrick
4436e5dd7070Spatrick CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));
4437e5dd7070Spatrick }
4438e5dd7070Spatrick };
4439e5dd7070Spatrick }
4440e5dd7070Spatrick
4441e5dd7070Spatrick /// Emits a call to __cxa_begin_catch and enters a cleanup to call
4442e5dd7070Spatrick /// __cxa_end_catch.
4443e5dd7070Spatrick ///
4444e5dd7070Spatrick /// \param EndMightThrow - true if __cxa_end_catch might throw
CallBeginCatch(CodeGenFunction & CGF,llvm::Value * Exn,bool EndMightThrow)4445e5dd7070Spatrick static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
4446e5dd7070Spatrick llvm::Value *Exn,
4447e5dd7070Spatrick bool EndMightThrow) {
4448e5dd7070Spatrick llvm::CallInst *call =
4449e5dd7070Spatrick CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);
4450e5dd7070Spatrick
4451e5dd7070Spatrick CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);
4452e5dd7070Spatrick
4453e5dd7070Spatrick return call;
4454e5dd7070Spatrick }
4455e5dd7070Spatrick
4456e5dd7070Spatrick /// A "special initializer" callback for initializing a catch
4457e5dd7070Spatrick /// parameter during catch initialization.
InitCatchParam(CodeGenFunction & CGF,const VarDecl & CatchParam,Address ParamAddr,SourceLocation Loc)4458e5dd7070Spatrick static void InitCatchParam(CodeGenFunction &CGF,
4459e5dd7070Spatrick const VarDecl &CatchParam,
4460e5dd7070Spatrick Address ParamAddr,
4461e5dd7070Spatrick SourceLocation Loc) {
4462e5dd7070Spatrick // Load the exception from where the landing pad saved it.
4463e5dd7070Spatrick llvm::Value *Exn = CGF.getExceptionFromSlot();
4464e5dd7070Spatrick
4465e5dd7070Spatrick CanQualType CatchType =
4466e5dd7070Spatrick CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
4467e5dd7070Spatrick llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);
4468e5dd7070Spatrick
4469e5dd7070Spatrick // If we're catching by reference, we can just cast the object
4470e5dd7070Spatrick // pointer to the appropriate pointer.
4471e5dd7070Spatrick if (isa<ReferenceType>(CatchType)) {
4472e5dd7070Spatrick QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();
4473e5dd7070Spatrick bool EndCatchMightThrow = CaughtType->isRecordType();
4474e5dd7070Spatrick
4475e5dd7070Spatrick // __cxa_begin_catch returns the adjusted object pointer.
4476e5dd7070Spatrick llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);
4477e5dd7070Spatrick
4478e5dd7070Spatrick // We have no way to tell the personality function that we're
4479e5dd7070Spatrick // catching by reference, so if we're catching a pointer,
4480e5dd7070Spatrick // __cxa_begin_catch will actually return that pointer by value.
4481e5dd7070Spatrick if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
4482e5dd7070Spatrick QualType PointeeType = PT->getPointeeType();
4483e5dd7070Spatrick
4484e5dd7070Spatrick // When catching by reference, generally we should just ignore
4485e5dd7070Spatrick // this by-value pointer and use the exception object instead.
4486e5dd7070Spatrick if (!PointeeType->isRecordType()) {
4487e5dd7070Spatrick
4488e5dd7070Spatrick // Exn points to the struct _Unwind_Exception header, which
4489e5dd7070Spatrick // we have to skip past in order to reach the exception data.
4490e5dd7070Spatrick unsigned HeaderSize =
4491e5dd7070Spatrick CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
4492a9ac8606Spatrick AdjustedExn =
4493a9ac8606Spatrick CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, Exn, HeaderSize);
4494e5dd7070Spatrick
4495e5dd7070Spatrick // However, if we're catching a pointer-to-record type that won't
4496e5dd7070Spatrick // work, because the personality function might have adjusted
4497e5dd7070Spatrick // the pointer. There's actually no way for us to fully satisfy
4498e5dd7070Spatrick // the language/ABI contract here: we can't use Exn because it
4499e5dd7070Spatrick // might have the wrong adjustment, but we can't use the by-value
4500e5dd7070Spatrick // pointer because it's off by a level of abstraction.
4501e5dd7070Spatrick //
4502e5dd7070Spatrick // The current solution is to dump the adjusted pointer into an
4503e5dd7070Spatrick // alloca, which breaks language semantics (because changing the
4504e5dd7070Spatrick // pointer doesn't change the exception) but at least works.
4505e5dd7070Spatrick // The better solution would be to filter out non-exact matches
4506e5dd7070Spatrick // and rethrow them, but this is tricky because the rethrow
4507e5dd7070Spatrick // really needs to be catchable by other sites at this landing
4508e5dd7070Spatrick // pad. The best solution is to fix the personality function.
4509e5dd7070Spatrick } else {
4510e5dd7070Spatrick // Pull the pointer for the reference type off.
4511*12c85518Srobert llvm::Type *PtrTy = CGF.ConvertTypeForMem(CaughtType);
4512e5dd7070Spatrick
4513e5dd7070Spatrick // Create the temporary and write the adjusted pointer into it.
4514e5dd7070Spatrick Address ExnPtrTmp =
4515e5dd7070Spatrick CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp");
4516e5dd7070Spatrick llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
4517e5dd7070Spatrick CGF.Builder.CreateStore(Casted, ExnPtrTmp);
4518e5dd7070Spatrick
4519e5dd7070Spatrick // Bind the reference to the temporary.
4520e5dd7070Spatrick AdjustedExn = ExnPtrTmp.getPointer();
4521e5dd7070Spatrick }
4522e5dd7070Spatrick }
4523e5dd7070Spatrick
4524e5dd7070Spatrick llvm::Value *ExnCast =
4525e5dd7070Spatrick CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
4526e5dd7070Spatrick CGF.Builder.CreateStore(ExnCast, ParamAddr);
4527e5dd7070Spatrick return;
4528e5dd7070Spatrick }
4529e5dd7070Spatrick
4530e5dd7070Spatrick // Scalars and complexes.
4531e5dd7070Spatrick TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType);
4532e5dd7070Spatrick if (TEK != TEK_Aggregate) {
4533e5dd7070Spatrick llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);
4534e5dd7070Spatrick
4535e5dd7070Spatrick // If the catch type is a pointer type, __cxa_begin_catch returns
4536e5dd7070Spatrick // the pointer by value.
4537e5dd7070Spatrick if (CatchType->hasPointerRepresentation()) {
4538e5dd7070Spatrick llvm::Value *CastExn =
4539e5dd7070Spatrick CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
4540e5dd7070Spatrick
4541e5dd7070Spatrick switch (CatchType.getQualifiers().getObjCLifetime()) {
4542e5dd7070Spatrick case Qualifiers::OCL_Strong:
4543e5dd7070Spatrick CastExn = CGF.EmitARCRetainNonBlock(CastExn);
4544*12c85518Srobert [[fallthrough]];
4545e5dd7070Spatrick
4546e5dd7070Spatrick case Qualifiers::OCL_None:
4547e5dd7070Spatrick case Qualifiers::OCL_ExplicitNone:
4548e5dd7070Spatrick case Qualifiers::OCL_Autoreleasing:
4549e5dd7070Spatrick CGF.Builder.CreateStore(CastExn, ParamAddr);
4550e5dd7070Spatrick return;
4551e5dd7070Spatrick
4552e5dd7070Spatrick case Qualifiers::OCL_Weak:
4553e5dd7070Spatrick CGF.EmitARCInitWeak(ParamAddr, CastExn);
4554e5dd7070Spatrick return;
4555e5dd7070Spatrick }
4556e5dd7070Spatrick llvm_unreachable("bad ownership qualifier!");
4557e5dd7070Spatrick }
4558e5dd7070Spatrick
4559e5dd7070Spatrick // Otherwise, it returns a pointer into the exception object.
4560e5dd7070Spatrick
4561e5dd7070Spatrick llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
4562e5dd7070Spatrick llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
4563e5dd7070Spatrick
4564e5dd7070Spatrick LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType);
4565e5dd7070Spatrick LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType);
4566e5dd7070Spatrick switch (TEK) {
4567e5dd7070Spatrick case TEK_Complex:
4568e5dd7070Spatrick CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV,
4569e5dd7070Spatrick /*init*/ true);
4570e5dd7070Spatrick return;
4571e5dd7070Spatrick case TEK_Scalar: {
4572e5dd7070Spatrick llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc);
4573e5dd7070Spatrick CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true);
4574e5dd7070Spatrick return;
4575e5dd7070Spatrick }
4576e5dd7070Spatrick case TEK_Aggregate:
4577e5dd7070Spatrick llvm_unreachable("evaluation kind filtered out!");
4578e5dd7070Spatrick }
4579e5dd7070Spatrick llvm_unreachable("bad evaluation kind");
4580e5dd7070Spatrick }
4581e5dd7070Spatrick
4582e5dd7070Spatrick assert(isa<RecordType>(CatchType) && "unexpected catch type!");
4583e5dd7070Spatrick auto catchRD = CatchType->getAsCXXRecordDecl();
4584e5dd7070Spatrick CharUnits caughtExnAlignment = CGF.CGM.getClassPointerAlignment(catchRD);
4585e5dd7070Spatrick
4586e5dd7070Spatrick llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
4587e5dd7070Spatrick
4588e5dd7070Spatrick // Check for a copy expression. If we don't have a copy expression,
4589e5dd7070Spatrick // that means a trivial copy is okay.
4590e5dd7070Spatrick const Expr *copyExpr = CatchParam.getInit();
4591e5dd7070Spatrick if (!copyExpr) {
4592e5dd7070Spatrick llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);
4593e5dd7070Spatrick Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4594*12c85518Srobert LLVMCatchTy, caughtExnAlignment);
4595e5dd7070Spatrick LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType);
4596e5dd7070Spatrick LValue Src = CGF.MakeAddrLValue(adjustedExn, CatchType);
4597e5dd7070Spatrick CGF.EmitAggregateCopy(Dest, Src, CatchType, AggValueSlot::DoesNotOverlap);
4598e5dd7070Spatrick return;
4599e5dd7070Spatrick }
4600e5dd7070Spatrick
4601e5dd7070Spatrick // We have to call __cxa_get_exception_ptr to get the adjusted
4602e5dd7070Spatrick // pointer before copying.
4603e5dd7070Spatrick llvm::CallInst *rawAdjustedExn =
4604e5dd7070Spatrick CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
4605e5dd7070Spatrick
4606e5dd7070Spatrick // Cast that to the appropriate type.
4607e5dd7070Spatrick Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4608*12c85518Srobert LLVMCatchTy, caughtExnAlignment);
4609e5dd7070Spatrick
4610e5dd7070Spatrick // The copy expression is defined in terms of an OpaqueValueExpr.
4611e5dd7070Spatrick // Find it and map it to the adjusted expression.
4612e5dd7070Spatrick CodeGenFunction::OpaqueValueMapping
4613e5dd7070Spatrick opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
4614e5dd7070Spatrick CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
4615e5dd7070Spatrick
4616e5dd7070Spatrick // Call the copy ctor in a terminate scope.
4617e5dd7070Spatrick CGF.EHStack.pushTerminate();
4618e5dd7070Spatrick
4619e5dd7070Spatrick // Perform the copy construction.
4620e5dd7070Spatrick CGF.EmitAggExpr(copyExpr,
4621e5dd7070Spatrick AggValueSlot::forAddr(ParamAddr, Qualifiers(),
4622e5dd7070Spatrick AggValueSlot::IsNotDestructed,
4623e5dd7070Spatrick AggValueSlot::DoesNotNeedGCBarriers,
4624e5dd7070Spatrick AggValueSlot::IsNotAliased,
4625e5dd7070Spatrick AggValueSlot::DoesNotOverlap));
4626e5dd7070Spatrick
4627e5dd7070Spatrick // Leave the terminate scope.
4628e5dd7070Spatrick CGF.EHStack.popTerminate();
4629e5dd7070Spatrick
4630e5dd7070Spatrick // Undo the opaque value mapping.
4631e5dd7070Spatrick opaque.pop();
4632e5dd7070Spatrick
4633e5dd7070Spatrick // Finally we can call __cxa_begin_catch.
4634e5dd7070Spatrick CallBeginCatch(CGF, Exn, true);
4635e5dd7070Spatrick }
4636e5dd7070Spatrick
4637e5dd7070Spatrick /// Begins a catch statement by initializing the catch variable and
4638e5dd7070Spatrick /// calling __cxa_begin_catch.
emitBeginCatch(CodeGenFunction & CGF,const CXXCatchStmt * S)4639e5dd7070Spatrick void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,
4640e5dd7070Spatrick const CXXCatchStmt *S) {
4641e5dd7070Spatrick // We have to be very careful with the ordering of cleanups here:
4642e5dd7070Spatrick // C++ [except.throw]p4:
4643e5dd7070Spatrick // The destruction [of the exception temporary] occurs
4644e5dd7070Spatrick // immediately after the destruction of the object declared in
4645e5dd7070Spatrick // the exception-declaration in the handler.
4646e5dd7070Spatrick //
4647e5dd7070Spatrick // So the precise ordering is:
4648e5dd7070Spatrick // 1. Construct catch variable.
4649e5dd7070Spatrick // 2. __cxa_begin_catch
4650e5dd7070Spatrick // 3. Enter __cxa_end_catch cleanup
4651e5dd7070Spatrick // 4. Enter dtor cleanup
4652e5dd7070Spatrick //
4653e5dd7070Spatrick // We do this by using a slightly abnormal initialization process.
4654e5dd7070Spatrick // Delegation sequence:
4655e5dd7070Spatrick // - ExitCXXTryStmt opens a RunCleanupsScope
4656e5dd7070Spatrick // - EmitAutoVarAlloca creates the variable and debug info
4657e5dd7070Spatrick // - InitCatchParam initializes the variable from the exception
4658e5dd7070Spatrick // - CallBeginCatch calls __cxa_begin_catch
4659e5dd7070Spatrick // - CallBeginCatch enters the __cxa_end_catch cleanup
4660e5dd7070Spatrick // - EmitAutoVarCleanups enters the variable destructor cleanup
4661e5dd7070Spatrick // - EmitCXXTryStmt emits the code for the catch body
4662e5dd7070Spatrick // - EmitCXXTryStmt close the RunCleanupsScope
4663e5dd7070Spatrick
4664e5dd7070Spatrick VarDecl *CatchParam = S->getExceptionDecl();
4665e5dd7070Spatrick if (!CatchParam) {
4666e5dd7070Spatrick llvm::Value *Exn = CGF.getExceptionFromSlot();
4667e5dd7070Spatrick CallBeginCatch(CGF, Exn, true);
4668e5dd7070Spatrick return;
4669e5dd7070Spatrick }
4670e5dd7070Spatrick
4671e5dd7070Spatrick // Emit the local.
4672e5dd7070Spatrick CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
4673e5dd7070Spatrick InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc());
4674e5dd7070Spatrick CGF.EmitAutoVarCleanups(var);
4675e5dd7070Spatrick }
4676e5dd7070Spatrick
4677e5dd7070Spatrick /// Get or define the following function:
4678e5dd7070Spatrick /// void @__clang_call_terminate(i8* %exn) nounwind noreturn
4679e5dd7070Spatrick /// This code is used only in C++.
getClangCallTerminateFn(CodeGenModule & CGM)4680e5dd7070Spatrick static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM) {
4681*12c85518Srobert ASTContext &C = CGM.getContext();
4682*12c85518Srobert const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
4683*12c85518Srobert C.VoidTy, {C.getPointerType(C.CharTy)});
4684*12c85518Srobert llvm::FunctionType *fnTy = CGM.getTypes().GetFunctionType(FI);
4685e5dd7070Spatrick llvm::FunctionCallee fnRef = CGM.CreateRuntimeFunction(
4686e5dd7070Spatrick fnTy, "__clang_call_terminate", llvm::AttributeList(), /*Local=*/true);
4687e5dd7070Spatrick llvm::Function *fn =
4688e5dd7070Spatrick cast<llvm::Function>(fnRef.getCallee()->stripPointerCasts());
4689e5dd7070Spatrick if (fn->empty()) {
4690*12c85518Srobert CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, fn, /*IsThunk=*/false);
4691e5dd7070Spatrick fn->setDoesNotThrow();
4692e5dd7070Spatrick fn->setDoesNotReturn();
4693e5dd7070Spatrick
4694e5dd7070Spatrick // What we really want is to massively penalize inlining without
4695e5dd7070Spatrick // forbidding it completely. The difference between that and
4696e5dd7070Spatrick // 'noinline' is negligible.
4697e5dd7070Spatrick fn->addFnAttr(llvm::Attribute::NoInline);
4698e5dd7070Spatrick
4699e5dd7070Spatrick // Allow this function to be shared across translation units, but
4700e5dd7070Spatrick // we don't want it to turn into an exported symbol.
4701e5dd7070Spatrick fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
4702e5dd7070Spatrick fn->setVisibility(llvm::Function::HiddenVisibility);
4703e5dd7070Spatrick if (CGM.supportsCOMDAT())
4704e5dd7070Spatrick fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName()));
4705e5dd7070Spatrick
4706e5dd7070Spatrick // Set up the function.
4707e5dd7070Spatrick llvm::BasicBlock *entry =
4708e5dd7070Spatrick llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);
4709e5dd7070Spatrick CGBuilderTy builder(CGM, entry);
4710e5dd7070Spatrick
4711e5dd7070Spatrick // Pull the exception pointer out of the parameter list.
4712e5dd7070Spatrick llvm::Value *exn = &*fn->arg_begin();
4713e5dd7070Spatrick
4714e5dd7070Spatrick // Call __cxa_begin_catch(exn).
4715e5dd7070Spatrick llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);
4716e5dd7070Spatrick catchCall->setDoesNotThrow();
4717e5dd7070Spatrick catchCall->setCallingConv(CGM.getRuntimeCC());
4718e5dd7070Spatrick
4719e5dd7070Spatrick // Call std::terminate().
4720e5dd7070Spatrick llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn());
4721e5dd7070Spatrick termCall->setDoesNotThrow();
4722e5dd7070Spatrick termCall->setDoesNotReturn();
4723e5dd7070Spatrick termCall->setCallingConv(CGM.getRuntimeCC());
4724e5dd7070Spatrick
4725e5dd7070Spatrick // std::terminate cannot return.
4726e5dd7070Spatrick builder.CreateUnreachable();
4727e5dd7070Spatrick }
4728e5dd7070Spatrick return fnRef;
4729e5dd7070Spatrick }
4730e5dd7070Spatrick
4731e5dd7070Spatrick llvm::CallInst *
emitTerminateForUnexpectedException(CodeGenFunction & CGF,llvm::Value * Exn)4732e5dd7070Spatrick ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
4733e5dd7070Spatrick llvm::Value *Exn) {
4734e5dd7070Spatrick // In C++, we want to call __cxa_begin_catch() before terminating.
4735e5dd7070Spatrick if (Exn) {
4736e5dd7070Spatrick assert(CGF.CGM.getLangOpts().CPlusPlus);
4737e5dd7070Spatrick return CGF.EmitNounwindRuntimeCall(getClangCallTerminateFn(CGF.CGM), Exn);
4738e5dd7070Spatrick }
4739e5dd7070Spatrick return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());
4740e5dd7070Spatrick }
4741e5dd7070Spatrick
4742e5dd7070Spatrick std::pair<llvm::Value *, const CXXRecordDecl *>
LoadVTablePtr(CodeGenFunction & CGF,Address This,const CXXRecordDecl * RD)4743e5dd7070Spatrick ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
4744e5dd7070Spatrick const CXXRecordDecl *RD) {
4745e5dd7070Spatrick return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD};
4746e5dd7070Spatrick }
4747e5dd7070Spatrick
emitBeginCatch(CodeGenFunction & CGF,const CXXCatchStmt * C)4748e5dd7070Spatrick void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,
4749e5dd7070Spatrick const CXXCatchStmt *C) {
4750e5dd7070Spatrick if (CGF.getTarget().hasFeature("exception-handling"))
4751e5dd7070Spatrick CGF.EHStack.pushCleanup<CatchRetScope>(
4752e5dd7070Spatrick NormalCleanup, cast<llvm::CatchPadInst>(CGF.CurrentFuncletPad));
4753e5dd7070Spatrick ItaniumCXXABI::emitBeginCatch(CGF, C);
4754e5dd7070Spatrick }
4755ec727ea7Spatrick
4756a9ac8606Spatrick llvm::CallInst *
emitTerminateForUnexpectedException(CodeGenFunction & CGF,llvm::Value * Exn)4757a9ac8606Spatrick WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
4758a9ac8606Spatrick llvm::Value *Exn) {
4759a9ac8606Spatrick // Itanium ABI calls __clang_call_terminate(), which __cxa_begin_catch() on
4760a9ac8606Spatrick // the violating exception to mark it handled, but it is currently hard to do
4761a9ac8606Spatrick // with wasm EH instruction structure with catch/catch_all, we just call
4762a9ac8606Spatrick // std::terminate and ignore the violating exception as in CGCXXABI.
4763a9ac8606Spatrick // TODO Consider code transformation that makes calling __clang_call_terminate
4764a9ac8606Spatrick // possible.
4765a9ac8606Spatrick return CGCXXABI::emitTerminateForUnexpectedException(CGF, Exn);
4766a9ac8606Spatrick }
4767a9ac8606Spatrick
4768ec727ea7Spatrick /// Register a global destructor as best as we know how.
registerGlobalDtor(CodeGenFunction & CGF,const VarDecl & D,llvm::FunctionCallee Dtor,llvm::Constant * Addr)4769ec727ea7Spatrick void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
4770a9ac8606Spatrick llvm::FunctionCallee Dtor,
4771a9ac8606Spatrick llvm::Constant *Addr) {
4772a9ac8606Spatrick if (D.getTLSKind() != VarDecl::TLS_None) {
4773a9ac8606Spatrick // atexit routine expects "int(*)(int,...)"
4774a9ac8606Spatrick llvm::FunctionType *FTy =
4775a9ac8606Spatrick llvm::FunctionType::get(CGM.IntTy, CGM.IntTy, true);
4776a9ac8606Spatrick llvm::PointerType *FpTy = FTy->getPointerTo();
4777a9ac8606Spatrick
4778a9ac8606Spatrick // extern "C" int __pt_atexit_np(int flags, int(*)(int,...), ...);
4779a9ac8606Spatrick llvm::FunctionType *AtExitTy =
4780a9ac8606Spatrick llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy, FpTy}, true);
4781a9ac8606Spatrick
4782a9ac8606Spatrick // Fetch the actual function.
4783a9ac8606Spatrick llvm::FunctionCallee AtExit =
4784a9ac8606Spatrick CGM.CreateRuntimeFunction(AtExitTy, "__pt_atexit_np");
4785ec727ea7Spatrick
4786ec727ea7Spatrick // Create __dtor function for the var decl.
4787a9ac8606Spatrick llvm::Function *DtorStub = CGF.createTLSAtExitStub(D, Dtor, Addr, AtExit);
4788ec727ea7Spatrick
4789ec727ea7Spatrick // Register above __dtor with atexit().
4790a9ac8606Spatrick // First param is flags and must be 0, second param is function ptr
4791a9ac8606Spatrick llvm::Value *NV = llvm::Constant::getNullValue(CGM.IntTy);
4792a9ac8606Spatrick CGF.EmitNounwindRuntimeCall(AtExit, {NV, DtorStub});
4793a9ac8606Spatrick
4794a9ac8606Spatrick // Cannot unregister TLS __dtor so done
4795a9ac8606Spatrick return;
4796a9ac8606Spatrick }
4797a9ac8606Spatrick
4798a9ac8606Spatrick // Create __dtor function for the var decl.
4799a9ac8606Spatrick llvm::Function *DtorStub = CGF.createAtExitStub(D, Dtor, Addr);
4800a9ac8606Spatrick
4801a9ac8606Spatrick // Register above __dtor with atexit().
4802a9ac8606Spatrick CGF.registerGlobalDtorWithAtExit(DtorStub);
4803ec727ea7Spatrick
4804ec727ea7Spatrick // Emit __finalize function to unregister __dtor and (as appropriate) call
4805ec727ea7Spatrick // __dtor.
4806a9ac8606Spatrick emitCXXStermFinalizer(D, DtorStub, Addr);
4807ec727ea7Spatrick }
4808ec727ea7Spatrick
emitCXXStermFinalizer(const VarDecl & D,llvm::Function * dtorStub,llvm::Constant * addr)4809ec727ea7Spatrick void XLCXXABI::emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
4810ec727ea7Spatrick llvm::Constant *addr) {
4811ec727ea7Spatrick llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
4812ec727ea7Spatrick SmallString<256> FnName;
4813ec727ea7Spatrick {
4814ec727ea7Spatrick llvm::raw_svector_ostream Out(FnName);
4815ec727ea7Spatrick getMangleContext().mangleDynamicStermFinalizer(&D, Out);
4816ec727ea7Spatrick }
4817ec727ea7Spatrick
4818ec727ea7Spatrick // Create the finalization action associated with a variable.
4819ec727ea7Spatrick const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
4820ec727ea7Spatrick llvm::Function *StermFinalizer = CGM.CreateGlobalInitOrCleanUpFunction(
4821ec727ea7Spatrick FTy, FnName.str(), FI, D.getLocation());
4822ec727ea7Spatrick
4823ec727ea7Spatrick CodeGenFunction CGF(CGM);
4824ec727ea7Spatrick
4825ec727ea7Spatrick CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, StermFinalizer, FI,
4826a9ac8606Spatrick FunctionArgList(), D.getLocation(),
4827a9ac8606Spatrick D.getInit()->getExprLoc());
4828ec727ea7Spatrick
4829ec727ea7Spatrick // The unatexit subroutine unregisters __dtor functions that were previously
4830ec727ea7Spatrick // registered by the atexit subroutine. If the referenced function is found,
4831ec727ea7Spatrick // the unatexit returns a value of 0, meaning that the cleanup is still
4832ec727ea7Spatrick // pending (and we should call the __dtor function).
4833ec727ea7Spatrick llvm::Value *V = CGF.unregisterGlobalDtorWithUnAtExit(dtorStub);
4834ec727ea7Spatrick
4835ec727ea7Spatrick llvm::Value *NeedsDestruct = CGF.Builder.CreateIsNull(V, "needs_destruct");
4836ec727ea7Spatrick
4837ec727ea7Spatrick llvm::BasicBlock *DestructCallBlock = CGF.createBasicBlock("destruct.call");
4838ec727ea7Spatrick llvm::BasicBlock *EndBlock = CGF.createBasicBlock("destruct.end");
4839ec727ea7Spatrick
4840ec727ea7Spatrick // Check if unatexit returns a value of 0. If it does, jump to
4841ec727ea7Spatrick // DestructCallBlock, otherwise jump to EndBlock directly.
4842ec727ea7Spatrick CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
4843ec727ea7Spatrick
4844ec727ea7Spatrick CGF.EmitBlock(DestructCallBlock);
4845ec727ea7Spatrick
4846ec727ea7Spatrick // Emit the call to dtorStub.
4847ec727ea7Spatrick llvm::CallInst *CI = CGF.Builder.CreateCall(dtorStub);
4848ec727ea7Spatrick
4849ec727ea7Spatrick // Make sure the call and the callee agree on calling convention.
4850ec727ea7Spatrick CI->setCallingConv(dtorStub->getCallingConv());
4851ec727ea7Spatrick
4852ec727ea7Spatrick CGF.EmitBlock(EndBlock);
4853ec727ea7Spatrick
4854ec727ea7Spatrick CGF.FinishFunction();
4855ec727ea7Spatrick
4856a9ac8606Spatrick if (auto *IPA = D.getAttr<InitPriorityAttr>()) {
4857a9ac8606Spatrick CGM.AddCXXPrioritizedStermFinalizerEntry(StermFinalizer,
4858a9ac8606Spatrick IPA->getPriority());
4859a9ac8606Spatrick } else if (isTemplateInstantiation(D.getTemplateSpecializationKind()) ||
4860a9ac8606Spatrick getContext().GetGVALinkageForVariable(&D) == GVA_DiscardableODR) {
4861a9ac8606Spatrick // According to C++ [basic.start.init]p2, class template static data
4862a9ac8606Spatrick // members (i.e., implicitly or explicitly instantiated specializations)
4863a9ac8606Spatrick // have unordered initialization. As a consequence, we can put them into
4864a9ac8606Spatrick // their own llvm.global_dtors entry.
4865a9ac8606Spatrick CGM.AddCXXStermFinalizerToGlobalDtor(StermFinalizer, 65535);
4866a9ac8606Spatrick } else {
4867ec727ea7Spatrick CGM.AddCXXStermFinalizerEntry(StermFinalizer);
4868ec727ea7Spatrick }
4869a9ac8606Spatrick }
4870