xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
10b57cec5SDimitry Andric //===------- ItaniumCXXABI.cpp - Emit LLVM Code from ASTs for a Module ----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This provides C++ code generation targeting the Itanium C++ ABI.  The class
100b57cec5SDimitry Andric // in this file generates structures that follow the Itanium C++ ABI, which is
110b57cec5SDimitry Andric // documented at:
12e8d8bef9SDimitry Andric //  https://itanium-cxx-abi.github.io/cxx-abi/abi.html
13e8d8bef9SDimitry Andric //  https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
140b57cec5SDimitry Andric //
150b57cec5SDimitry Andric // It also supports the closely-related ARM ABI, documented at:
16e8d8bef9SDimitry Andric // https://developer.arm.com/documentation/ihi0041/g/
170b57cec5SDimitry Andric //
180b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "CGCXXABI.h"
210b57cec5SDimitry Andric #include "CGCleanup.h"
220b57cec5SDimitry Andric #include "CGRecordLayout.h"
230b57cec5SDimitry Andric #include "CGVTables.h"
240b57cec5SDimitry Andric #include "CodeGenFunction.h"
250b57cec5SDimitry Andric #include "CodeGenModule.h"
260fca6ea1SDimitry Andric #include "ConstantEmitter.h"
270b57cec5SDimitry Andric #include "TargetInfo.h"
28480093f4SDimitry Andric #include "clang/AST/Attr.h"
290b57cec5SDimitry Andric #include "clang/AST/Mangle.h"
300b57cec5SDimitry Andric #include "clang/AST/StmtCXX.h"
31480093f4SDimitry Andric #include "clang/AST/Type.h"
32480093f4SDimitry Andric #include "clang/CodeGen/ConstantInitBuilder.h"
330b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
340b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
350b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
360b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
370b57cec5SDimitry Andric #include "llvm/IR/Value.h"
380b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
390b57cec5SDimitry Andric 
4006c3fb27SDimitry Andric #include <optional>
4106c3fb27SDimitry Andric 
420b57cec5SDimitry Andric using namespace clang;
430b57cec5SDimitry Andric using namespace CodeGen;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric namespace {
460b57cec5SDimitry Andric class ItaniumCXXABI : public CodeGen::CGCXXABI {
470b57cec5SDimitry Andric   /// VTables - All the vtables which have been defined.
480b57cec5SDimitry Andric   llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
490b57cec5SDimitry Andric 
50a7dea167SDimitry Andric   /// All the thread wrapper functions that have been used.
51a7dea167SDimitry Andric   llvm::SmallVector<std::pair<const VarDecl *, llvm::Function *>, 8>
52a7dea167SDimitry Andric       ThreadWrappers;
53a7dea167SDimitry Andric 
540b57cec5SDimitry Andric protected:
550b57cec5SDimitry Andric   bool UseARMMethodPtrABI;
560b57cec5SDimitry Andric   bool UseARMGuardVarABI;
570b57cec5SDimitry Andric   bool Use32BitVTableOffsetABI;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   ItaniumMangleContext &getMangleContext() {
600b57cec5SDimitry Andric     return cast<ItaniumMangleContext>(CodeGen::CGCXXABI::getMangleContext());
610b57cec5SDimitry Andric   }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric public:
640b57cec5SDimitry Andric   ItaniumCXXABI(CodeGen::CodeGenModule &CGM,
650b57cec5SDimitry Andric                 bool UseARMMethodPtrABI = false,
660b57cec5SDimitry Andric                 bool UseARMGuardVarABI = false) :
670b57cec5SDimitry Andric     CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
680b57cec5SDimitry Andric     UseARMGuardVarABI(UseARMGuardVarABI),
690b57cec5SDimitry Andric     Use32BitVTableOffsetABI(false) { }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   bool classifyReturnType(CGFunctionInfo &FI) const override;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
740b57cec5SDimitry Andric     // If C++ prohibits us from making a copy, pass by address.
750b57cec5SDimitry Andric     if (!RD->canPassInRegisters())
760b57cec5SDimitry Andric       return RAA_Indirect;
770b57cec5SDimitry Andric     return RAA_Default;
780b57cec5SDimitry Andric   }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   bool isThisCompleteObject(GlobalDecl GD) const override {
810b57cec5SDimitry Andric     // The Itanium ABI has separate complete-object vs.  base-object
820b57cec5SDimitry Andric     // variants of both constructors and destructors.
830b57cec5SDimitry Andric     if (isa<CXXDestructorDecl>(GD.getDecl())) {
840b57cec5SDimitry Andric       switch (GD.getDtorType()) {
850b57cec5SDimitry Andric       case Dtor_Complete:
860b57cec5SDimitry Andric       case Dtor_Deleting:
870b57cec5SDimitry Andric         return true;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric       case Dtor_Base:
900b57cec5SDimitry Andric         return false;
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric       case Dtor_Comdat:
930b57cec5SDimitry Andric         llvm_unreachable("emitting dtor comdat as function?");
940b57cec5SDimitry Andric       }
950b57cec5SDimitry Andric       llvm_unreachable("bad dtor kind");
960b57cec5SDimitry Andric     }
970b57cec5SDimitry Andric     if (isa<CXXConstructorDecl>(GD.getDecl())) {
980b57cec5SDimitry Andric       switch (GD.getCtorType()) {
990b57cec5SDimitry Andric       case Ctor_Complete:
1000b57cec5SDimitry Andric         return true;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric       case Ctor_Base:
1030b57cec5SDimitry Andric         return false;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric       case Ctor_CopyingClosure:
1060b57cec5SDimitry Andric       case Ctor_DefaultClosure:
1070b57cec5SDimitry Andric         llvm_unreachable("closure ctors in Itanium ABI?");
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric       case Ctor_Comdat:
1100b57cec5SDimitry Andric         llvm_unreachable("emitting ctor comdat as function?");
1110b57cec5SDimitry Andric       }
1120b57cec5SDimitry Andric       llvm_unreachable("bad dtor kind");
1130b57cec5SDimitry Andric     }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     // No other kinds.
1160b57cec5SDimitry Andric     return false;
1170b57cec5SDimitry Andric   }
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   bool isZeroInitializable(const MemberPointerType *MPT) override;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   CGCallee
1240b57cec5SDimitry Andric     EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
1250b57cec5SDimitry Andric                                     const Expr *E,
1260b57cec5SDimitry Andric                                     Address This,
1270b57cec5SDimitry Andric                                     llvm::Value *&ThisPtrForCall,
1280b57cec5SDimitry Andric                                     llvm::Value *MemFnPtr,
1290b57cec5SDimitry Andric                                     const MemberPointerType *MPT) override;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   llvm::Value *
1320b57cec5SDimitry Andric     EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
1330b57cec5SDimitry Andric                                  Address Base,
1340b57cec5SDimitry Andric                                  llvm::Value *MemPtr,
1350b57cec5SDimitry Andric                                  const MemberPointerType *MPT) override;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
1380b57cec5SDimitry Andric                                            const CastExpr *E,
1390b57cec5SDimitry Andric                                            llvm::Value *Src) override;
1400b57cec5SDimitry Andric   llvm::Constant *EmitMemberPointerConversion(const CastExpr *E,
1410b57cec5SDimitry Andric                                               llvm::Constant *Src) override;
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD) override;
1460b57cec5SDimitry Andric   llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
1470b57cec5SDimitry Andric                                         CharUnits offset) override;
1480b57cec5SDimitry Andric   llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT) override;
1490b57cec5SDimitry Andric   llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD,
1500b57cec5SDimitry Andric                                      CharUnits ThisAdjustment);
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
1530b57cec5SDimitry Andric                                            llvm::Value *L, llvm::Value *R,
1540b57cec5SDimitry Andric                                            const MemberPointerType *MPT,
1550b57cec5SDimitry Andric                                            bool Inequality) override;
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
1580b57cec5SDimitry Andric                                          llvm::Value *Addr,
1590b57cec5SDimitry Andric                                          const MemberPointerType *MPT) override;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
1620b57cec5SDimitry Andric                                Address Ptr, QualType ElementType,
1630b57cec5SDimitry Andric                                const CXXDestructorDecl *Dtor) override;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   void emitRethrow(CodeGenFunction &CGF, bool isNoReturn) override;
1660b57cec5SDimitry Andric   void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) override;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   llvm::CallInst *
1710b57cec5SDimitry Andric   emitTerminateForUnexpectedException(CodeGenFunction &CGF,
1720b57cec5SDimitry Andric                                       llvm::Value *Exn) override;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD);
1750b57cec5SDimitry Andric   llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
1760b57cec5SDimitry Andric   CatchTypeInfo
1770b57cec5SDimitry Andric   getAddrOfCXXCatchHandlerType(QualType Ty,
1780b57cec5SDimitry Andric                                QualType CatchHandlerType) override {
1790b57cec5SDimitry Andric     return CatchTypeInfo{getAddrOfRTTIDescriptor(Ty), 0};
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric 
1820fca6ea1SDimitry Andric   bool shouldTypeidBeNullChecked(QualType SrcRecordTy) override;
1830b57cec5SDimitry Andric   void EmitBadTypeidCall(CodeGenFunction &CGF) override;
1840b57cec5SDimitry Andric   llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
1850b57cec5SDimitry Andric                           Address ThisPtr,
1860b57cec5SDimitry Andric                           llvm::Type *StdTypeInfoPtrTy) override;
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
1890b57cec5SDimitry Andric                                           QualType SrcRecordTy) override;
1900b57cec5SDimitry Andric 
19106c3fb27SDimitry Andric   /// Determine whether we know that all instances of type RecordTy will have
19206c3fb27SDimitry Andric   /// the same vtable pointer values, that is distinct from all other vtable
19306c3fb27SDimitry Andric   /// pointers. While this is required by the Itanium ABI, it doesn't happen in
19406c3fb27SDimitry Andric   /// practice in some cases due to language extensions.
19506c3fb27SDimitry Andric   bool hasUniqueVTablePointer(QualType RecordTy) {
19606c3fb27SDimitry Andric     const CXXRecordDecl *RD = RecordTy->getAsCXXRecordDecl();
19706c3fb27SDimitry Andric 
19806c3fb27SDimitry Andric     // Under -fapple-kext, multiple definitions of the same vtable may be
19906c3fb27SDimitry Andric     // emitted.
20006c3fb27SDimitry Andric     if (!CGM.getCodeGenOpts().AssumeUniqueVTables ||
20106c3fb27SDimitry Andric         getContext().getLangOpts().AppleKext)
20206c3fb27SDimitry Andric       return false;
20306c3fb27SDimitry Andric 
20406c3fb27SDimitry Andric     // If the type_info* would be null, the vtable might be merged with that of
20506c3fb27SDimitry Andric     // another type.
20606c3fb27SDimitry Andric     if (!CGM.shouldEmitRTTI())
20706c3fb27SDimitry Andric       return false;
20806c3fb27SDimitry Andric 
20906c3fb27SDimitry Andric     // If there's only one definition of the vtable in the program, it has a
21006c3fb27SDimitry Andric     // unique address.
21106c3fb27SDimitry Andric     if (!llvm::GlobalValue::isWeakForLinker(CGM.getVTableLinkage(RD)))
21206c3fb27SDimitry Andric       return true;
21306c3fb27SDimitry Andric 
21406c3fb27SDimitry Andric     // Even if there are multiple definitions of the vtable, they are required
21506c3fb27SDimitry Andric     // by the ABI to use the same symbol name, so should be merged at load
21606c3fb27SDimitry Andric     // time. However, if the class has hidden visibility, there can be
21706c3fb27SDimitry Andric     // different versions of the class in different modules, and the ABI
21806c3fb27SDimitry Andric     // library might treat them as being the same.
21906c3fb27SDimitry Andric     if (CGM.GetLLVMVisibility(RD->getVisibility()) !=
22006c3fb27SDimitry Andric         llvm::GlobalValue::DefaultVisibility)
22106c3fb27SDimitry Andric       return false;
22206c3fb27SDimitry Andric 
22306c3fb27SDimitry Andric     return true;
22406c3fb27SDimitry Andric   }
22506c3fb27SDimitry Andric 
22606c3fb27SDimitry Andric   bool shouldEmitExactDynamicCast(QualType DestRecordTy) override {
22706c3fb27SDimitry Andric     return hasUniqueVTablePointer(DestRecordTy);
22806c3fb27SDimitry Andric   }
22906c3fb27SDimitry Andric 
23006c3fb27SDimitry Andric   llvm::Value *emitDynamicCastCall(CodeGenFunction &CGF, Address Value,
2310b57cec5SDimitry Andric                                    QualType SrcRecordTy, QualType DestTy,
2320b57cec5SDimitry Andric                                    QualType DestRecordTy,
2330b57cec5SDimitry Andric                                    llvm::BasicBlock *CastEnd) override;
2340b57cec5SDimitry Andric 
23506c3fb27SDimitry Andric   llvm::Value *emitExactDynamicCast(CodeGenFunction &CGF, Address ThisAddr,
23606c3fb27SDimitry Andric                                     QualType SrcRecordTy, QualType DestTy,
23706c3fb27SDimitry Andric                                     QualType DestRecordTy,
23806c3fb27SDimitry Andric                                     llvm::BasicBlock *CastSuccess,
23906c3fb27SDimitry Andric                                     llvm::BasicBlock *CastFail) override;
24006c3fb27SDimitry Andric 
24106c3fb27SDimitry Andric   llvm::Value *emitDynamicCastToVoid(CodeGenFunction &CGF, Address Value,
24206c3fb27SDimitry Andric                                      QualType SrcRecordTy) override;
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   bool EmitBadCastCall(CodeGenFunction &CGF) override;
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   llvm::Value *
2470b57cec5SDimitry Andric     GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
2480b57cec5SDimitry Andric                               const CXXRecordDecl *ClassDecl,
2490b57cec5SDimitry Andric                               const CXXRecordDecl *BaseClassDecl) override;
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   void EmitCXXConstructors(const CXXConstructorDecl *D) override;
2520b57cec5SDimitry Andric 
2535ffd83dbSDimitry Andric   AddedStructorArgCounts
2540b57cec5SDimitry Andric   buildStructorSignature(GlobalDecl GD,
2550b57cec5SDimitry Andric                          SmallVectorImpl<CanQualType> &ArgTys) override;
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
2580b57cec5SDimitry Andric                               CXXDtorType DT) const override {
2590b57cec5SDimitry Andric     // Itanium does not emit any destructor variant as an inline thunk.
2600b57cec5SDimitry Andric     // Delegating may occur as an optimization, but all variants are either
2610b57cec5SDimitry Andric     // emitted with external linkage or as linkonce if they are inline and used.
2620b57cec5SDimitry Andric     return false;
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   void EmitCXXDestructors(const CXXDestructorDecl *D) override;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
2680b57cec5SDimitry Andric                                  FunctionArgList &Params) override;
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   void EmitInstanceFunctionProlog(CodeGenFunction &CGF) override;
2710b57cec5SDimitry Andric 
2725ffd83dbSDimitry Andric   AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
2735ffd83dbSDimitry Andric                                                const CXXConstructorDecl *D,
2745ffd83dbSDimitry Andric                                                CXXCtorType Type,
2755ffd83dbSDimitry Andric                                                bool ForVirtualBase,
2765ffd83dbSDimitry Andric                                                bool Delegating) override;
2775ffd83dbSDimitry Andric 
2785ffd83dbSDimitry Andric   llvm::Value *getCXXDestructorImplicitParam(CodeGenFunction &CGF,
2795ffd83dbSDimitry Andric                                              const CXXDestructorDecl *DD,
2805ffd83dbSDimitry Andric                                              CXXDtorType Type,
2815ffd83dbSDimitry Andric                                              bool ForVirtualBase,
2825ffd83dbSDimitry Andric                                              bool Delegating) override;
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
2850b57cec5SDimitry Andric                           CXXDtorType Type, bool ForVirtualBase,
2860b57cec5SDimitry Andric                           bool Delegating, Address This,
2870b57cec5SDimitry Andric                           QualType ThisTy) override;
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   void emitVTableDefinitions(CodeGenVTables &CGVT,
2900b57cec5SDimitry Andric                              const CXXRecordDecl *RD) override;
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
2930b57cec5SDimitry Andric                                            CodeGenFunction::VPtr Vptr) override;
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override {
2960b57cec5SDimitry Andric     return true;
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   llvm::Constant *
3000b57cec5SDimitry Andric   getVTableAddressPoint(BaseSubobject Base,
3010b57cec5SDimitry Andric                         const CXXRecordDecl *VTableClass) override;
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   llvm::Value *getVTableAddressPointInStructor(
3040b57cec5SDimitry Andric       CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
3050b57cec5SDimitry Andric       BaseSubobject Base, const CXXRecordDecl *NearestVBase) override;
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   llvm::Value *getVTableAddressPointInStructorWithVTT(
3080b57cec5SDimitry Andric       CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
3090b57cec5SDimitry Andric       BaseSubobject Base, const CXXRecordDecl *NearestVBase);
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
3120b57cec5SDimitry Andric                                         CharUnits VPtrOffset) override;
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric   CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
3150b57cec5SDimitry Andric                                      Address This, llvm::Type *Ty,
3160b57cec5SDimitry Andric                                      SourceLocation Loc) override;
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
3190b57cec5SDimitry Andric                                          const CXXDestructorDecl *Dtor,
3200b57cec5SDimitry Andric                                          CXXDtorType DtorType, Address This,
3210b57cec5SDimitry Andric                                          DeleteOrMemberCallExpr E) override;
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;
3260b57cec5SDimitry Andric   bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const;
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
3290b57cec5SDimitry Andric                        bool ReturnAdjustment) override {
3300b57cec5SDimitry Andric     // Allow inlining of thunks by emitting them with available_externally
3310b57cec5SDimitry Andric     // linkage together with vtables when needed.
3320b57cec5SDimitry Andric     if (ForVTable && !Thunk->hasLocalLinkage())
3330b57cec5SDimitry Andric       Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
3340b57cec5SDimitry Andric     CGM.setGVProperties(Thunk, GD);
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   bool exportThunk() override { return true; }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
3400fca6ea1SDimitry Andric                                      const CXXRecordDecl *UnadjustedThisClass,
3410fca6ea1SDimitry Andric                                      const ThunkInfo &TI) override;
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
3440fca6ea1SDimitry Andric                                        const CXXRecordDecl *UnadjustedRetClass,
3450b57cec5SDimitry Andric                                        const ReturnAdjustment &RA) override;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
3480b57cec5SDimitry Andric                               FunctionArgList &Args) const override {
3490b57cec5SDimitry Andric     assert(!Args.empty() && "expected the arglist to not be empty!");
3500b57cec5SDimitry Andric     return Args.size() - 1;
3510b57cec5SDimitry Andric   }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   StringRef GetPureVirtualCallName() override { return "__cxa_pure_virtual"; }
3540b57cec5SDimitry Andric   StringRef GetDeletedVirtualCallName() override
3550b57cec5SDimitry Andric     { return "__cxa_deleted_virtual"; }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   CharUnits getArrayCookieSizeImpl(QualType elementType) override;
3580b57cec5SDimitry Andric   Address InitializeArrayCookie(CodeGenFunction &CGF,
3590b57cec5SDimitry Andric                                 Address NewPtr,
3600b57cec5SDimitry Andric                                 llvm::Value *NumElements,
3610b57cec5SDimitry Andric                                 const CXXNewExpr *expr,
3620b57cec5SDimitry Andric                                 QualType ElementType) override;
3630b57cec5SDimitry Andric   llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
3640b57cec5SDimitry Andric                                    Address allocPtr,
3650b57cec5SDimitry Andric                                    CharUnits cookieSize) override;
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
3680b57cec5SDimitry Andric                        llvm::GlobalVariable *DeclPtr,
3690b57cec5SDimitry Andric                        bool PerformInit) override;
3700b57cec5SDimitry Andric   void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
3710b57cec5SDimitry Andric                           llvm::FunctionCallee dtor,
3720b57cec5SDimitry Andric                           llvm::Constant *addr) override;
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD,
3750b57cec5SDimitry Andric                                                 llvm::Value *Val);
3760b57cec5SDimitry Andric   void EmitThreadLocalInitFuncs(
3770b57cec5SDimitry Andric       CodeGenModule &CGM,
3780b57cec5SDimitry Andric       ArrayRef<const VarDecl *> CXXThreadLocals,
3790b57cec5SDimitry Andric       ArrayRef<llvm::Function *> CXXThreadLocalInits,
3800b57cec5SDimitry Andric       ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;
3810b57cec5SDimitry Andric 
382a7dea167SDimitry Andric   bool usesThreadWrapperFunction(const VarDecl *VD) const override {
383a7dea167SDimitry Andric     return !isEmittedWithConstantInitializer(VD) ||
384349cc55cSDimitry Andric            mayNeedDestruction(VD);
385a7dea167SDimitry Andric   }
3860b57cec5SDimitry Andric   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
3870b57cec5SDimitry Andric                                       QualType LValType) override;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   bool NeedsVTTParameter(GlobalDecl GD) override;
3900b57cec5SDimitry Andric 
3910fca6ea1SDimitry Andric   llvm::Constant *
3920fca6ea1SDimitry Andric   getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD);
3930fca6ea1SDimitry Andric 
3940b57cec5SDimitry Andric   /**************************** RTTI Uniqueness ******************************/
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric protected:
3970b57cec5SDimitry Andric   /// Returns true if the ABI requires RTTI type_info objects to be unique
3980b57cec5SDimitry Andric   /// across a program.
3990b57cec5SDimitry Andric   virtual bool shouldRTTIBeUnique() const { return true; }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric public:
4020b57cec5SDimitry Andric   /// What sort of unique-RTTI behavior should we use?
4030b57cec5SDimitry Andric   enum RTTIUniquenessKind {
4040b57cec5SDimitry Andric     /// We are guaranteeing, or need to guarantee, that the RTTI string
4050b57cec5SDimitry Andric     /// is unique.
4060b57cec5SDimitry Andric     RUK_Unique,
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric     /// We are not guaranteeing uniqueness for the RTTI string, so we
4090b57cec5SDimitry Andric     /// can demote to hidden visibility but must use string comparisons.
4100b57cec5SDimitry Andric     RUK_NonUniqueHidden,
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric     /// We are not guaranteeing uniqueness for the RTTI string, so we
4130b57cec5SDimitry Andric     /// have to use string comparisons, but we also have to emit it with
4140b57cec5SDimitry Andric     /// non-hidden visibility.
4150b57cec5SDimitry Andric     RUK_NonUniqueVisible
4160b57cec5SDimitry Andric   };
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   /// Return the required visibility status for the given type and linkage in
4190b57cec5SDimitry Andric   /// the current ABI.
4200b57cec5SDimitry Andric   RTTIUniquenessKind
4210b57cec5SDimitry Andric   classifyRTTIUniqueness(QualType CanTy,
4220b57cec5SDimitry Andric                          llvm::GlobalValue::LinkageTypes Linkage) const;
4230b57cec5SDimitry Andric   friend class ItaniumRTTIBuilder;
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   void emitCXXStructor(GlobalDecl GD) override;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   std::pair<llvm::Value *, const CXXRecordDecl *>
4280b57cec5SDimitry Andric   LoadVTablePtr(CodeGenFunction &CGF, Address This,
4290b57cec5SDimitry Andric                 const CXXRecordDecl *RD) override;
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric  private:
4320fca6ea1SDimitry Andric    llvm::Constant *
4330fca6ea1SDimitry Andric    getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD);
4340fca6ea1SDimitry Andric 
4350b57cec5SDimitry Andric    bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
4360b57cec5SDimitry Andric      const auto &VtableLayout =
4370b57cec5SDimitry Andric          CGM.getItaniumVTableContext().getVTableLayout(RD);
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric      for (const auto &VtableComponent : VtableLayout.vtable_components()) {
4400b57cec5SDimitry Andric        // Skip empty slot.
4410b57cec5SDimitry Andric        if (!VtableComponent.isUsedFunctionPointerKind())
4420b57cec5SDimitry Andric          continue;
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric        const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
4450b57cec5SDimitry Andric        if (!Method->getCanonicalDecl()->isInlined())
4460b57cec5SDimitry Andric          continue;
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric        StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
4490b57cec5SDimitry Andric        auto *Entry = CGM.GetGlobalValue(Name);
4500b57cec5SDimitry Andric        // This checks if virtual inline function has already been emitted.
4510b57cec5SDimitry Andric        // Note that it is possible that this inline function would be emitted
4520b57cec5SDimitry Andric        // after trying to emit vtable speculatively. Because of this we do
4530b57cec5SDimitry Andric        // an extra pass after emitting all deferred vtables to find and emit
4540b57cec5SDimitry Andric        // these vtables opportunistically.
4550b57cec5SDimitry Andric        if (!Entry || Entry->isDeclaration())
4560b57cec5SDimitry Andric          return true;
4570b57cec5SDimitry Andric      }
4580b57cec5SDimitry Andric      return false;
4590b57cec5SDimitry Andric   }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   bool isVTableHidden(const CXXRecordDecl *RD) const {
4620b57cec5SDimitry Andric     const auto &VtableLayout =
4630b57cec5SDimitry Andric             CGM.getItaniumVTableContext().getVTableLayout(RD);
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric     for (const auto &VtableComponent : VtableLayout.vtable_components()) {
4660b57cec5SDimitry Andric       if (VtableComponent.isRTTIKind()) {
4670b57cec5SDimitry Andric         const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();
4680b57cec5SDimitry Andric         if (RTTIDecl->getVisibility() == Visibility::HiddenVisibility)
4690b57cec5SDimitry Andric           return true;
4700b57cec5SDimitry Andric       } else if (VtableComponent.isUsedFunctionPointerKind()) {
4710b57cec5SDimitry Andric         const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
4720b57cec5SDimitry Andric         if (Method->getVisibility() == Visibility::HiddenVisibility &&
4730b57cec5SDimitry Andric             !Method->isDefined())
4740b57cec5SDimitry Andric           return true;
4750b57cec5SDimitry Andric       }
4760b57cec5SDimitry Andric     }
4770b57cec5SDimitry Andric     return false;
4780b57cec5SDimitry Andric   }
4790b57cec5SDimitry Andric };
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric class ARMCXXABI : public ItaniumCXXABI {
4820b57cec5SDimitry Andric public:
4830b57cec5SDimitry Andric   ARMCXXABI(CodeGen::CodeGenModule &CGM) :
4840b57cec5SDimitry Andric     ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
4850b57cec5SDimitry Andric                   /*UseARMGuardVarABI=*/true) {}
4860b57cec5SDimitry Andric 
487bdd1243dSDimitry Andric   bool constructorsAndDestructorsReturnThis() const override { return true; }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV,
4900b57cec5SDimitry Andric                            QualType ResTy) override;
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   CharUnits getArrayCookieSizeImpl(QualType elementType) override;
4930b57cec5SDimitry Andric   Address InitializeArrayCookie(CodeGenFunction &CGF,
4940b57cec5SDimitry Andric                                 Address NewPtr,
4950b57cec5SDimitry Andric                                 llvm::Value *NumElements,
4960b57cec5SDimitry Andric                                 const CXXNewExpr *expr,
4970b57cec5SDimitry Andric                                 QualType ElementType) override;
4980b57cec5SDimitry Andric   llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr,
4990b57cec5SDimitry Andric                                    CharUnits cookieSize) override;
5000b57cec5SDimitry Andric };
5010b57cec5SDimitry Andric 
502e8d8bef9SDimitry Andric class AppleARM64CXXABI : public ARMCXXABI {
5030b57cec5SDimitry Andric public:
504e8d8bef9SDimitry Andric   AppleARM64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {
5050b57cec5SDimitry Andric     Use32BitVTableOffsetABI = true;
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   // ARM64 libraries are prepared for non-unique RTTI.
5090b57cec5SDimitry Andric   bool shouldRTTIBeUnique() const override { return false; }
5100b57cec5SDimitry Andric };
5110b57cec5SDimitry Andric 
512480093f4SDimitry Andric class FuchsiaCXXABI final : public ItaniumCXXABI {
513480093f4SDimitry Andric public:
514480093f4SDimitry Andric   explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM)
515480093f4SDimitry Andric       : ItaniumCXXABI(CGM) {}
516480093f4SDimitry Andric 
517480093f4SDimitry Andric private:
518bdd1243dSDimitry Andric   bool constructorsAndDestructorsReturnThis() const override { return true; }
519480093f4SDimitry Andric };
520480093f4SDimitry Andric 
5210b57cec5SDimitry Andric class WebAssemblyCXXABI final : public ItaniumCXXABI {
5220b57cec5SDimitry Andric public:
5230b57cec5SDimitry Andric   explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM)
5240b57cec5SDimitry Andric       : ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
5250b57cec5SDimitry Andric                       /*UseARMGuardVarABI=*/true) {}
5260b57cec5SDimitry Andric   void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
527fe6060f1SDimitry Andric   llvm::CallInst *
528fe6060f1SDimitry Andric   emitTerminateForUnexpectedException(CodeGenFunction &CGF,
529fe6060f1SDimitry Andric                                       llvm::Value *Exn) override;
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric private:
532bdd1243dSDimitry Andric   bool constructorsAndDestructorsReturnThis() const override { return true; }
5330b57cec5SDimitry Andric   bool canCallMismatchedFunctionType() const override { return false; }
5340b57cec5SDimitry Andric };
5355ffd83dbSDimitry Andric 
5365ffd83dbSDimitry Andric class XLCXXABI final : public ItaniumCXXABI {
5375ffd83dbSDimitry Andric public:
5385ffd83dbSDimitry Andric   explicit XLCXXABI(CodeGen::CodeGenModule &CGM)
5395ffd83dbSDimitry Andric       : ItaniumCXXABI(CGM) {}
5405ffd83dbSDimitry Andric 
5415ffd83dbSDimitry Andric   void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
5425ffd83dbSDimitry Andric                           llvm::FunctionCallee dtor,
5435ffd83dbSDimitry Andric                           llvm::Constant *addr) override;
5445ffd83dbSDimitry Andric 
5455ffd83dbSDimitry Andric   bool useSinitAndSterm() const override { return true; }
5465ffd83dbSDimitry Andric 
5475ffd83dbSDimitry Andric private:
5485ffd83dbSDimitry Andric   void emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
5495ffd83dbSDimitry Andric                              llvm::Constant *addr);
5505ffd83dbSDimitry Andric };
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
554fe6060f1SDimitry Andric   switch (CGM.getContext().getCXXABIKind()) {
5550b57cec5SDimitry Andric   // For IR-generation purposes, there's no significant difference
5560b57cec5SDimitry Andric   // between the ARM and iOS ABIs.
5570b57cec5SDimitry Andric   case TargetCXXABI::GenericARM:
5580b57cec5SDimitry Andric   case TargetCXXABI::iOS:
5590b57cec5SDimitry Andric   case TargetCXXABI::WatchOS:
5600b57cec5SDimitry Andric     return new ARMCXXABI(CGM);
5610b57cec5SDimitry Andric 
562e8d8bef9SDimitry Andric   case TargetCXXABI::AppleARM64:
563e8d8bef9SDimitry Andric     return new AppleARM64CXXABI(CGM);
5640b57cec5SDimitry Andric 
565480093f4SDimitry Andric   case TargetCXXABI::Fuchsia:
566480093f4SDimitry Andric     return new FuchsiaCXXABI(CGM);
567480093f4SDimitry Andric 
5680b57cec5SDimitry Andric   // Note that AArch64 uses the generic ItaniumCXXABI class since it doesn't
5690b57cec5SDimitry Andric   // include the other 32-bit ARM oddities: constructor/destructor return values
5700b57cec5SDimitry Andric   // and array cookies.
5710b57cec5SDimitry Andric   case TargetCXXABI::GenericAArch64:
5720b57cec5SDimitry Andric     return new ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
5730b57cec5SDimitry Andric                              /*UseARMGuardVarABI=*/true);
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   case TargetCXXABI::GenericMIPS:
5760b57cec5SDimitry Andric     return new ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true);
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric   case TargetCXXABI::WebAssembly:
5790b57cec5SDimitry Andric     return new WebAssemblyCXXABI(CGM);
5800b57cec5SDimitry Andric 
5815ffd83dbSDimitry Andric   case TargetCXXABI::XL:
5825ffd83dbSDimitry Andric     return new XLCXXABI(CGM);
5835ffd83dbSDimitry Andric 
5840b57cec5SDimitry Andric   case TargetCXXABI::GenericItanium:
5850b57cec5SDimitry Andric     if (CGM.getContext().getTargetInfo().getTriple().getArch()
5860b57cec5SDimitry Andric         == llvm::Triple::le32) {
5870b57cec5SDimitry Andric       // For PNaCl, use ARM-style method pointers so that PNaCl code
5880b57cec5SDimitry Andric       // does not assume anything about the alignment of function
5890b57cec5SDimitry Andric       // pointers.
590a7dea167SDimitry Andric       return new ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true);
5910b57cec5SDimitry Andric     }
5920b57cec5SDimitry Andric     return new ItaniumCXXABI(CGM);
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric   case TargetCXXABI::Microsoft:
5950b57cec5SDimitry Andric     llvm_unreachable("Microsoft ABI is not Itanium-based");
5960b57cec5SDimitry Andric   }
5970b57cec5SDimitry Andric   llvm_unreachable("bad ABI kind");
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric llvm::Type *
6010b57cec5SDimitry Andric ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
6020b57cec5SDimitry Andric   if (MPT->isMemberDataPointer())
6030b57cec5SDimitry Andric     return CGM.PtrDiffTy;
6040b57cec5SDimitry Andric   return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);
6050b57cec5SDimitry Andric }
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric /// In the Itanium and ARM ABIs, method pointers have the form:
6080b57cec5SDimitry Andric ///   struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr;
6090b57cec5SDimitry Andric ///
6100b57cec5SDimitry Andric /// In the Itanium ABI:
6110b57cec5SDimitry Andric ///  - method pointers are virtual if (memptr.ptr & 1) is nonzero
6120b57cec5SDimitry Andric ///  - the this-adjustment is (memptr.adj)
6130b57cec5SDimitry Andric ///  - the virtual offset is (memptr.ptr - 1)
6140b57cec5SDimitry Andric ///
6150b57cec5SDimitry Andric /// In the ARM ABI:
6160b57cec5SDimitry Andric ///  - method pointers are virtual if (memptr.adj & 1) is nonzero
6170b57cec5SDimitry Andric ///  - the this-adjustment is (memptr.adj >> 1)
6180b57cec5SDimitry Andric ///  - the virtual offset is (memptr.ptr)
6190b57cec5SDimitry Andric /// ARM uses 'adj' for the virtual flag because Thumb functions
6200b57cec5SDimitry Andric /// may be only single-byte aligned.
6210b57cec5SDimitry Andric ///
6220b57cec5SDimitry Andric /// If the member is virtual, the adjusted 'this' pointer points
6230b57cec5SDimitry Andric /// to a vtable pointer from which the virtual offset is applied.
6240b57cec5SDimitry Andric ///
6250b57cec5SDimitry Andric /// If the member is non-virtual, memptr.ptr is the address of
6260b57cec5SDimitry Andric /// the function to call.
6270b57cec5SDimitry Andric CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
6280b57cec5SDimitry Andric     CodeGenFunction &CGF, const Expr *E, Address ThisAddr,
6290b57cec5SDimitry Andric     llvm::Value *&ThisPtrForCall,
6300b57cec5SDimitry Andric     llvm::Value *MemFnPtr, const MemberPointerType *MPT) {
6310b57cec5SDimitry Andric   CGBuilderTy &Builder = CGF.Builder;
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   const FunctionProtoType *FPT =
63406c3fb27SDimitry Andric       MPT->getPointeeType()->castAs<FunctionProtoType>();
635a7dea167SDimitry Andric   auto *RD =
636a7dea167SDimitry Andric       cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl());
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual");
6410b57cec5SDimitry Andric   llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");
6420b57cec5SDimitry Andric   llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   // Extract memptr.adj, which is in the second field.
6450b57cec5SDimitry Andric   llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj");
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric   // Compute the true adjustment.
6480b57cec5SDimitry Andric   llvm::Value *Adj = RawAdj;
6490b57cec5SDimitry Andric   if (UseARMMethodPtrABI)
6500b57cec5SDimitry Andric     Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric   // Apply the adjustment and cast back to the original struct type
6530b57cec5SDimitry Andric   // for consistency.
6540fca6ea1SDimitry Andric   llvm::Value *This = ThisAddr.emitRawPointer(CGF);
6555f757f3fSDimitry Andric   This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj);
6560b57cec5SDimitry Andric   ThisPtrForCall = This;
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric   // Load the function pointer.
6590b57cec5SDimitry Andric   llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   // If the LSB in the function pointer is 1, the function pointer points to
6620b57cec5SDimitry Andric   // a virtual function.
6630b57cec5SDimitry Andric   llvm::Value *IsVirtual;
6640b57cec5SDimitry Andric   if (UseARMMethodPtrABI)
6650b57cec5SDimitry Andric     IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
6660b57cec5SDimitry Andric   else
6670b57cec5SDimitry Andric     IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
6680b57cec5SDimitry Andric   IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual");
6690b57cec5SDimitry Andric   Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric   // In the virtual path, the adjustment left 'This' pointing to the
6720b57cec5SDimitry Andric   // vtable of the correct base subobject.  The "function pointer" is an
6730b57cec5SDimitry Andric   // offset within the vtable (+1 for the virtual flag on non-ARM).
6740b57cec5SDimitry Andric   CGF.EmitBlock(FnVirtual);
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   // Cast the adjusted this to a pointer to vtable pointer and load.
67706c3fb27SDimitry Andric   llvm::Type *VTableTy = CGF.CGM.GlobalsInt8PtrTy;
6780b57cec5SDimitry Andric   CharUnits VTablePtrAlign =
6790b57cec5SDimitry Andric     CGF.CGM.getDynamicOffsetAlignment(ThisAddr.getAlignment(), RD,
6800b57cec5SDimitry Andric                                       CGF.getPointerAlign());
68104eeddc0SDimitry Andric   llvm::Value *VTable = CGF.GetVTablePtr(
68204eeddc0SDimitry Andric       Address(This, ThisAddr.getElementType(), VTablePtrAlign), VTableTy, RD);
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   // Apply the offset.
6850b57cec5SDimitry Andric   // On ARM64, to reserve extra space in virtual member function pointers,
6860b57cec5SDimitry Andric   // we only pay attention to the low 32 bits of the offset.
6870b57cec5SDimitry Andric   llvm::Value *VTableOffset = FnAsInt;
6880b57cec5SDimitry Andric   if (!UseARMMethodPtrABI)
6890b57cec5SDimitry Andric     VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
6900b57cec5SDimitry Andric   if (Use32BitVTableOffsetABI) {
6910b57cec5SDimitry Andric     VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty);
6920b57cec5SDimitry Andric     VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
6930b57cec5SDimitry Andric   }
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric   // Check the address of the function pointer if CFI on member function
6960b57cec5SDimitry Andric   // pointers is enabled.
6970b57cec5SDimitry Andric   llvm::Constant *CheckSourceLocation;
6980b57cec5SDimitry Andric   llvm::Constant *CheckTypeDesc;
6990b57cec5SDimitry Andric   bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) &&
7000b57cec5SDimitry Andric                             CGM.HasHiddenLTOVisibility(RD);
701a7dea167SDimitry Andric   bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
702a7dea167SDimitry Andric                            CGM.HasHiddenLTOVisibility(RD);
7035ffd83dbSDimitry Andric   bool ShouldEmitWPDInfo =
7045ffd83dbSDimitry Andric       CGM.getCodeGenOpts().WholeProgramVTables &&
70581ad6265SDimitry Andric       // Don't insert type tests if we are forcing public visibility.
70681ad6265SDimitry Andric       !CGM.AlwaysHasLTOVisibilityPublic(RD);
707a7dea167SDimitry Andric   llvm::Value *VirtualFn = nullptr;
7080b57cec5SDimitry Andric 
709a7dea167SDimitry Andric   {
710a7dea167SDimitry Andric     CodeGenFunction::SanitizerScope SanScope(&CGF);
711a7dea167SDimitry Andric     llvm::Value *TypeId = nullptr;
712a7dea167SDimitry Andric     llvm::Value *CheckResult = nullptr;
713a7dea167SDimitry Andric 
7145ffd83dbSDimitry Andric     if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
7155ffd83dbSDimitry Andric       // If doing CFI, VFE or WPD, we will need the metadata node to check
7165ffd83dbSDimitry Andric       // against.
717a7dea167SDimitry Andric       llvm::Metadata *MD =
718a7dea167SDimitry Andric           CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
719a7dea167SDimitry Andric       TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
720a7dea167SDimitry Andric     }
721a7dea167SDimitry Andric 
7225ffd83dbSDimitry Andric     if (ShouldEmitVFEInfo) {
723fe6060f1SDimitry Andric       llvm::Value *VFPAddr =
724fe6060f1SDimitry Andric           Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
725a7dea167SDimitry Andric 
726a7dea167SDimitry Andric       // If doing VFE, load from the vtable with a type.checked.load intrinsic
727a7dea167SDimitry Andric       // call. Note that we use the GEP to calculate the address to load from
728a7dea167SDimitry Andric       // and pass 0 as the offset to the intrinsic. This is because every
729a7dea167SDimitry Andric       // vtable slot of the correct type is marked with matching metadata, and
730a7dea167SDimitry Andric       // we know that the load must be from one of these slots.
731a7dea167SDimitry Andric       llvm::Value *CheckedLoad = Builder.CreateCall(
732a7dea167SDimitry Andric           CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
733a7dea167SDimitry Andric           {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
734a7dea167SDimitry Andric       CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
735a7dea167SDimitry Andric       VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
736a7dea167SDimitry Andric     } else {
737a7dea167SDimitry Andric       // When not doing VFE, emit a normal load, as it allows more
738a7dea167SDimitry Andric       // optimisations than type.checked.load.
7395ffd83dbSDimitry Andric       if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
740fe6060f1SDimitry Andric         llvm::Value *VFPAddr =
741fe6060f1SDimitry Andric             Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
742972a253aSDimitry Andric         llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
743972a253aSDimitry Andric                                       ? llvm::Intrinsic::type_test
744972a253aSDimitry Andric                                       : llvm::Intrinsic::public_type_test;
745972a253aSDimitry Andric 
7465f757f3fSDimitry Andric         CheckResult =
7475f757f3fSDimitry Andric             Builder.CreateCall(CGM.getIntrinsic(IID), {VFPAddr, TypeId});
748a7dea167SDimitry Andric       }
7495ffd83dbSDimitry Andric 
7505ffd83dbSDimitry Andric       if (CGM.getItaniumVTableContext().isRelativeLayout()) {
7515ffd83dbSDimitry Andric         VirtualFn = CGF.Builder.CreateCall(
7525ffd83dbSDimitry Andric             CGM.getIntrinsic(llvm::Intrinsic::load_relative,
7535ffd83dbSDimitry Andric                              {VTableOffset->getType()}),
7545ffd83dbSDimitry Andric             {VTable, VTableOffset});
7555ffd83dbSDimitry Andric       } else {
756fe6060f1SDimitry Andric         llvm::Value *VFPAddr =
757fe6060f1SDimitry Andric             CGF.Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
7585f757f3fSDimitry Andric         VirtualFn = CGF.Builder.CreateAlignedLoad(CGF.UnqualPtrTy, VFPAddr,
7595f757f3fSDimitry Andric                                                   CGF.getPointerAlign(),
7605f757f3fSDimitry Andric                                                   "memptr.virtualfn");
7615ffd83dbSDimitry Andric       }
762a7dea167SDimitry Andric     }
763a7dea167SDimitry Andric     assert(VirtualFn && "Virtual fuction pointer not created!");
7645ffd83dbSDimitry Andric     assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
7655ffd83dbSDimitry Andric             CheckResult) &&
766a7dea167SDimitry Andric            "Check result required but not created!");
767a7dea167SDimitry Andric 
768a7dea167SDimitry Andric     if (ShouldEmitCFICheck) {
769a7dea167SDimitry Andric       // If doing CFI, emit the check.
7700b57cec5SDimitry Andric       CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getBeginLoc());
7710b57cec5SDimitry Andric       CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0));
7720b57cec5SDimitry Andric       llvm::Constant *StaticData[] = {
7730b57cec5SDimitry Andric           llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall),
7740b57cec5SDimitry Andric           CheckSourceLocation,
7750b57cec5SDimitry Andric           CheckTypeDesc,
7760b57cec5SDimitry Andric       };
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric       if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
779e8d8bef9SDimitry Andric         CGF.EmitTrapCheck(CheckResult, SanitizerHandler::CFICheckFail);
7800b57cec5SDimitry Andric       } else {
7810b57cec5SDimitry Andric         llvm::Value *AllVtables = llvm::MetadataAsValue::get(
7820b57cec5SDimitry Andric             CGM.getLLVMContext(),
7830b57cec5SDimitry Andric             llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
7840b57cec5SDimitry Andric         llvm::Value *ValidVtable = Builder.CreateCall(
7850b57cec5SDimitry Andric             CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
786a7dea167SDimitry Andric         CGF.EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIMFCall),
7870b57cec5SDimitry Andric                       SanitizerHandler::CFICheckFail, StaticData,
7880b57cec5SDimitry Andric                       {VTable, ValidVtable});
7890b57cec5SDimitry Andric       }
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric       FnVirtual = Builder.GetInsertBlock();
7920b57cec5SDimitry Andric     }
793a7dea167SDimitry Andric   } // End of sanitizer scope
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric   CGF.EmitBranch(FnEnd);
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric   // In the non-virtual path, the function pointer is actually a
7980b57cec5SDimitry Andric   // function pointer.
7990b57cec5SDimitry Andric   CGF.EmitBlock(FnNonVirtual);
8005f757f3fSDimitry Andric   llvm::Value *NonVirtualFn =
8015f757f3fSDimitry Andric       Builder.CreateIntToPtr(FnAsInt, CGF.UnqualPtrTy, "memptr.nonvirtualfn");
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric   // Check the function pointer if CFI on member function pointers is enabled.
8040b57cec5SDimitry Andric   if (ShouldEmitCFICheck) {
8050b57cec5SDimitry Andric     CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
8060b57cec5SDimitry Andric     if (RD->hasDefinition()) {
8070b57cec5SDimitry Andric       CodeGenFunction::SanitizerScope SanScope(&CGF);
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric       llvm::Constant *StaticData[] = {
8100b57cec5SDimitry Andric           llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_NVMFCall),
8110b57cec5SDimitry Andric           CheckSourceLocation,
8120b57cec5SDimitry Andric           CheckTypeDesc,
8130b57cec5SDimitry Andric       };
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric       llvm::Value *Bit = Builder.getFalse();
8160b57cec5SDimitry Andric       for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {
8170b57cec5SDimitry Andric         llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
8180b57cec5SDimitry Andric             getContext().getMemberPointerType(
8190b57cec5SDimitry Andric                 MPT->getPointeeType(),
8200b57cec5SDimitry Andric                 getContext().getRecordType(Base).getTypePtr()));
8210b57cec5SDimitry Andric         llvm::Value *TypeId =
8220b57cec5SDimitry Andric             llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric         llvm::Value *TypeTest =
8250b57cec5SDimitry Andric             Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
8265f757f3fSDimitry Andric                                {NonVirtualFn, TypeId});
8270b57cec5SDimitry Andric         Bit = Builder.CreateOr(Bit, TypeTest);
8280b57cec5SDimitry Andric       }
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric       CGF.EmitCheck(std::make_pair(Bit, SanitizerKind::CFIMFCall),
8310b57cec5SDimitry Andric                     SanitizerHandler::CFICheckFail, StaticData,
8325f757f3fSDimitry Andric                     {NonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)});
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric       FnNonVirtual = Builder.GetInsertBlock();
8350b57cec5SDimitry Andric     }
8360b57cec5SDimitry Andric   }
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric   // We're done.
8390b57cec5SDimitry Andric   CGF.EmitBlock(FnEnd);
8405f757f3fSDimitry Andric   llvm::PHINode *CalleePtr = Builder.CreatePHI(CGF.UnqualPtrTy, 2);
8410b57cec5SDimitry Andric   CalleePtr->addIncoming(VirtualFn, FnVirtual);
8420b57cec5SDimitry Andric   CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
8430b57cec5SDimitry Andric 
8440fca6ea1SDimitry Andric   CGPointerAuthInfo PointerAuth;
8450fca6ea1SDimitry Andric 
8460fca6ea1SDimitry Andric   if (const auto &Schema =
8470fca6ea1SDimitry Andric           CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers) {
8480fca6ea1SDimitry Andric     llvm::PHINode *DiscriminatorPHI = Builder.CreatePHI(CGF.IntPtrTy, 2);
8490fca6ea1SDimitry Andric     DiscriminatorPHI->addIncoming(llvm::ConstantInt::get(CGF.IntPtrTy, 0),
8500fca6ea1SDimitry Andric                                   FnVirtual);
8510fca6ea1SDimitry Andric     const auto &AuthInfo =
8520fca6ea1SDimitry Andric         CGM.getMemberFunctionPointerAuthInfo(QualType(MPT, 0));
8530fca6ea1SDimitry Andric     assert(Schema.getKey() == AuthInfo.getKey() &&
8540fca6ea1SDimitry Andric            "Keys for virtual and non-virtual member functions must match");
8550fca6ea1SDimitry Andric     auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator();
8560fca6ea1SDimitry Andric     DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual);
8570fca6ea1SDimitry Andric     PointerAuth = CGPointerAuthInfo(
8580fca6ea1SDimitry Andric         Schema.getKey(), Schema.getAuthenticationMode(), Schema.isIsaPointer(),
8590fca6ea1SDimitry Andric         Schema.authenticatesNullValues(), DiscriminatorPHI);
8600fca6ea1SDimitry Andric   }
8610fca6ea1SDimitry Andric 
8620fca6ea1SDimitry Andric   CGCallee Callee(FPT, CalleePtr, PointerAuth);
8630b57cec5SDimitry Andric   return Callee;
8640b57cec5SDimitry Andric }
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric /// Compute an l-value by applying the given pointer-to-member to a
8670b57cec5SDimitry Andric /// base object.
8680b57cec5SDimitry Andric llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
8690b57cec5SDimitry Andric     CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr,
8700b57cec5SDimitry Andric     const MemberPointerType *MPT) {
8710b57cec5SDimitry Andric   assert(MemPtr->getType() == CGM.PtrDiffTy);
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   CGBuilderTy &Builder = CGF.Builder;
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric   // Apply the offset, which we assume is non-null.
8760fca6ea1SDimitry Andric   return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.emitRawPointer(CGF), MemPtr,
87706c3fb27SDimitry Andric                                    "memptr.offset");
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric 
8800fca6ea1SDimitry Andric // See if it's possible to return a constant signed pointer.
8810fca6ea1SDimitry Andric static llvm::Constant *pointerAuthResignConstant(
8820fca6ea1SDimitry Andric     llvm::Value *Ptr, const CGPointerAuthInfo &CurAuthInfo,
8830fca6ea1SDimitry Andric     const CGPointerAuthInfo &NewAuthInfo, CodeGenModule &CGM) {
8840fca6ea1SDimitry Andric   const auto *CPA = dyn_cast<llvm::ConstantPtrAuth>(Ptr);
8850fca6ea1SDimitry Andric 
8860fca6ea1SDimitry Andric   if (!CPA)
8870fca6ea1SDimitry Andric     return nullptr;
8880fca6ea1SDimitry Andric 
8890fca6ea1SDimitry Andric   assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() &&
8900fca6ea1SDimitry Andric          CPA->getAddrDiscriminator()->isZeroValue() &&
8910fca6ea1SDimitry Andric          CPA->getDiscriminator() == CurAuthInfo.getDiscriminator() &&
8920fca6ea1SDimitry Andric          "unexpected key or discriminators");
8930fca6ea1SDimitry Andric 
8940fca6ea1SDimitry Andric   return CGM.getConstantSignedPointer(
8950fca6ea1SDimitry Andric       CPA->getPointer(), NewAuthInfo.getKey(), nullptr,
8960fca6ea1SDimitry Andric       cast<llvm::ConstantInt>(NewAuthInfo.getDiscriminator()));
8970fca6ea1SDimitry Andric }
8980fca6ea1SDimitry Andric 
8990b57cec5SDimitry Andric /// Perform a bitcast, derived-to-base, or base-to-derived member pointer
9000b57cec5SDimitry Andric /// conversion.
9010b57cec5SDimitry Andric ///
9020b57cec5SDimitry Andric /// Bitcast conversions are always a no-op under Itanium.
9030b57cec5SDimitry Andric ///
9040b57cec5SDimitry Andric /// Obligatory offset/adjustment diagram:
9050b57cec5SDimitry Andric ///         <-- offset -->          <-- adjustment -->
9060b57cec5SDimitry Andric ///   |--------------------------|----------------------|--------------------|
9070b57cec5SDimitry Andric ///   ^Derived address point     ^Base address point    ^Member address point
9080b57cec5SDimitry Andric ///
9090b57cec5SDimitry Andric /// So when converting a base member pointer to a derived member pointer,
9100b57cec5SDimitry Andric /// we add the offset to the adjustment because the address point has
9110b57cec5SDimitry Andric /// decreased;  and conversely, when converting a derived MP to a base MP
9120b57cec5SDimitry Andric /// we subtract the offset from the adjustment because the address point
9130b57cec5SDimitry Andric /// has increased.
9140b57cec5SDimitry Andric ///
9150b57cec5SDimitry Andric /// The standard forbids (at compile time) conversion to and from
9160b57cec5SDimitry Andric /// virtual bases, which is why we don't have to consider them here.
9170b57cec5SDimitry Andric ///
9180b57cec5SDimitry Andric /// The standard forbids (at run time) casting a derived MP to a base
9190b57cec5SDimitry Andric /// MP when the derived MP does not point to a member of the base.
9200b57cec5SDimitry Andric /// This is why -1 is a reasonable choice for null data member
9210b57cec5SDimitry Andric /// pointers.
9220b57cec5SDimitry Andric llvm::Value *
9230b57cec5SDimitry Andric ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
9240b57cec5SDimitry Andric                                            const CastExpr *E,
9250b57cec5SDimitry Andric                                            llvm::Value *src) {
9260b57cec5SDimitry Andric   // Use constant emission if we can.
9270b57cec5SDimitry Andric   if (isa<llvm::Constant>(src))
9280b57cec5SDimitry Andric     return EmitMemberPointerConversion(E, cast<llvm::Constant>(src));
9290b57cec5SDimitry Andric 
9300fca6ea1SDimitry Andric   assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
9310fca6ea1SDimitry Andric          E->getCastKind() == CK_BaseToDerivedMemberPointer ||
9320fca6ea1SDimitry Andric          E->getCastKind() == CK_ReinterpretMemberPointer);
9330fca6ea1SDimitry Andric 
9340fca6ea1SDimitry Andric   CGBuilderTy &Builder = CGF.Builder;
9350fca6ea1SDimitry Andric   QualType DstType = E->getType();
9360fca6ea1SDimitry Andric 
9370fca6ea1SDimitry Andric   if (DstType->isMemberFunctionPointerType()) {
9380fca6ea1SDimitry Andric     if (const auto &NewAuthInfo =
9390fca6ea1SDimitry Andric             CGM.getMemberFunctionPointerAuthInfo(DstType)) {
9400fca6ea1SDimitry Andric       QualType SrcType = E->getSubExpr()->getType();
9410fca6ea1SDimitry Andric       assert(SrcType->isMemberFunctionPointerType());
9420fca6ea1SDimitry Andric       const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType);
9430fca6ea1SDimitry Andric       llvm::Value *MemFnPtr = Builder.CreateExtractValue(src, 0, "memptr.ptr");
9440fca6ea1SDimitry Andric       llvm::Type *OrigTy = MemFnPtr->getType();
9450fca6ea1SDimitry Andric 
9460fca6ea1SDimitry Andric       llvm::BasicBlock *StartBB = Builder.GetInsertBlock();
9470fca6ea1SDimitry Andric       llvm::BasicBlock *ResignBB = CGF.createBasicBlock("resign");
9480fca6ea1SDimitry Andric       llvm::BasicBlock *MergeBB = CGF.createBasicBlock("merge");
9490fca6ea1SDimitry Andric 
9500fca6ea1SDimitry Andric       // Check whether we have a virtual offset or a pointer to a function.
9510fca6ea1SDimitry Andric       assert(UseARMMethodPtrABI && "ARM ABI expected");
9520fca6ea1SDimitry Andric       llvm::Value *Adj = Builder.CreateExtractValue(src, 1, "memptr.adj");
9530fca6ea1SDimitry Andric       llvm::Constant *Ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
9540fca6ea1SDimitry Andric       llvm::Value *AndVal = Builder.CreateAnd(Adj, Ptrdiff_1);
9550fca6ea1SDimitry Andric       llvm::Value *IsVirtualOffset =
9560fca6ea1SDimitry Andric           Builder.CreateIsNotNull(AndVal, "is.virtual.offset");
9570fca6ea1SDimitry Andric       Builder.CreateCondBr(IsVirtualOffset, MergeBB, ResignBB);
9580fca6ea1SDimitry Andric 
9590fca6ea1SDimitry Andric       CGF.EmitBlock(ResignBB);
9600fca6ea1SDimitry Andric       llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGM.Int8Ty);
9610fca6ea1SDimitry Andric       MemFnPtr = Builder.CreateIntToPtr(MemFnPtr, PtrTy);
9620fca6ea1SDimitry Andric       MemFnPtr =
9630fca6ea1SDimitry Andric           CGF.emitPointerAuthResign(MemFnPtr, SrcType, CurAuthInfo, NewAuthInfo,
9640fca6ea1SDimitry Andric                                     isa<llvm::Constant>(src));
9650fca6ea1SDimitry Andric       MemFnPtr = Builder.CreatePtrToInt(MemFnPtr, OrigTy);
9660fca6ea1SDimitry Andric       llvm::Value *ResignedVal = Builder.CreateInsertValue(src, MemFnPtr, 0);
9670fca6ea1SDimitry Andric       ResignBB = Builder.GetInsertBlock();
9680fca6ea1SDimitry Andric 
9690fca6ea1SDimitry Andric       CGF.EmitBlock(MergeBB);
9700fca6ea1SDimitry Andric       llvm::PHINode *NewSrc = Builder.CreatePHI(src->getType(), 2);
9710fca6ea1SDimitry Andric       NewSrc->addIncoming(src, StartBB);
9720fca6ea1SDimitry Andric       NewSrc->addIncoming(ResignedVal, ResignBB);
9730fca6ea1SDimitry Andric       src = NewSrc;
9740fca6ea1SDimitry Andric     }
9750fca6ea1SDimitry Andric   }
9760fca6ea1SDimitry Andric 
9770fca6ea1SDimitry Andric   // Under Itanium, reinterprets don't require any additional processing.
9780fca6ea1SDimitry Andric   if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
9790fca6ea1SDimitry Andric 
9800b57cec5SDimitry Andric   llvm::Constant *adj = getMemberPointerAdjustment(E);
9810b57cec5SDimitry Andric   if (!adj) return src;
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric   bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric   const MemberPointerType *destTy =
9860b57cec5SDimitry Andric     E->getType()->castAs<MemberPointerType>();
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric   // For member data pointers, this is just a matter of adding the
9890b57cec5SDimitry Andric   // offset if the source is non-null.
9900b57cec5SDimitry Andric   if (destTy->isMemberDataPointer()) {
9910b57cec5SDimitry Andric     llvm::Value *dst;
9920b57cec5SDimitry Andric     if (isDerivedToBase)
9930b57cec5SDimitry Andric       dst = Builder.CreateNSWSub(src, adj, "adj");
9940b57cec5SDimitry Andric     else
9950b57cec5SDimitry Andric       dst = Builder.CreateNSWAdd(src, adj, "adj");
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric     // Null check.
9980b57cec5SDimitry Andric     llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType());
9990b57cec5SDimitry Andric     llvm::Value *isNull = Builder.CreateICmpEQ(src, null, "memptr.isnull");
10000b57cec5SDimitry Andric     return Builder.CreateSelect(isNull, src, dst);
10010b57cec5SDimitry Andric   }
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric   // The this-adjustment is left-shifted by 1 on ARM.
10040b57cec5SDimitry Andric   if (UseARMMethodPtrABI) {
10050b57cec5SDimitry Andric     uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
10060b57cec5SDimitry Andric     offset <<= 1;
10070b57cec5SDimitry Andric     adj = llvm::ConstantInt::get(adj->getType(), offset);
10080b57cec5SDimitry Andric   }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric   llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1, "src.adj");
10110b57cec5SDimitry Andric   llvm::Value *dstAdj;
10120b57cec5SDimitry Andric   if (isDerivedToBase)
10130b57cec5SDimitry Andric     dstAdj = Builder.CreateNSWSub(srcAdj, adj, "adj");
10140b57cec5SDimitry Andric   else
10150b57cec5SDimitry Andric     dstAdj = Builder.CreateNSWAdd(srcAdj, adj, "adj");
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric   return Builder.CreateInsertValue(src, dstAdj, 1);
10180b57cec5SDimitry Andric }
10190b57cec5SDimitry Andric 
10200fca6ea1SDimitry Andric static llvm::Constant *
10210fca6ea1SDimitry Andric pointerAuthResignMemberFunctionPointer(llvm::Constant *Src, QualType DestType,
10220fca6ea1SDimitry Andric                                        QualType SrcType, CodeGenModule &CGM) {
10230fca6ea1SDimitry Andric   assert(DestType->isMemberFunctionPointerType() &&
10240fca6ea1SDimitry Andric          SrcType->isMemberFunctionPointerType() &&
10250fca6ea1SDimitry Andric          "member function pointers expected");
10260fca6ea1SDimitry Andric   if (DestType == SrcType)
10270fca6ea1SDimitry Andric     return Src;
10280fca6ea1SDimitry Andric 
10290fca6ea1SDimitry Andric   const auto &NewAuthInfo = CGM.getMemberFunctionPointerAuthInfo(DestType);
10300fca6ea1SDimitry Andric   const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType);
10310fca6ea1SDimitry Andric 
10320fca6ea1SDimitry Andric   if (!NewAuthInfo && !CurAuthInfo)
10330fca6ea1SDimitry Andric     return Src;
10340fca6ea1SDimitry Andric 
10350fca6ea1SDimitry Andric   llvm::Constant *MemFnPtr = Src->getAggregateElement(0u);
10360fca6ea1SDimitry Andric   if (MemFnPtr->getNumOperands() == 0) {
10370fca6ea1SDimitry Andric     // src must be a pair of null pointers.
10380fca6ea1SDimitry Andric     assert(isa<llvm::ConstantInt>(MemFnPtr) && "constant int expected");
10390fca6ea1SDimitry Andric     return Src;
10400fca6ea1SDimitry Andric   }
10410fca6ea1SDimitry Andric 
10420fca6ea1SDimitry Andric   llvm::Constant *ConstPtr = pointerAuthResignConstant(
10430fca6ea1SDimitry Andric       cast<llvm::User>(MemFnPtr)->getOperand(0), CurAuthInfo, NewAuthInfo, CGM);
10440fca6ea1SDimitry Andric   ConstPtr = llvm::ConstantExpr::getPtrToInt(ConstPtr, MemFnPtr->getType());
10450fca6ea1SDimitry Andric   return ConstantFoldInsertValueInstruction(Src, ConstPtr, 0);
10460fca6ea1SDimitry Andric }
10470fca6ea1SDimitry Andric 
10480b57cec5SDimitry Andric llvm::Constant *
10490b57cec5SDimitry Andric ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,
10500b57cec5SDimitry Andric                                            llvm::Constant *src) {
10510b57cec5SDimitry Andric   assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
10520b57cec5SDimitry Andric          E->getCastKind() == CK_BaseToDerivedMemberPointer ||
10530b57cec5SDimitry Andric          E->getCastKind() == CK_ReinterpretMemberPointer);
10540b57cec5SDimitry Andric 
10550fca6ea1SDimitry Andric   QualType DstType = E->getType();
10560fca6ea1SDimitry Andric 
10570fca6ea1SDimitry Andric   if (DstType->isMemberFunctionPointerType())
10580fca6ea1SDimitry Andric     src = pointerAuthResignMemberFunctionPointer(
10590fca6ea1SDimitry Andric         src, DstType, E->getSubExpr()->getType(), CGM);
10600fca6ea1SDimitry Andric 
10610b57cec5SDimitry Andric   // Under Itanium, reinterprets don't require any additional processing.
10620b57cec5SDimitry Andric   if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
10630b57cec5SDimitry Andric 
10640b57cec5SDimitry Andric   // If the adjustment is trivial, we don't need to do anything.
10650b57cec5SDimitry Andric   llvm::Constant *adj = getMemberPointerAdjustment(E);
10660b57cec5SDimitry Andric   if (!adj) return src;
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric   bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric   const MemberPointerType *destTy =
10710b57cec5SDimitry Andric     E->getType()->castAs<MemberPointerType>();
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric   // For member data pointers, this is just a matter of adding the
10740b57cec5SDimitry Andric   // offset if the source is non-null.
10750b57cec5SDimitry Andric   if (destTy->isMemberDataPointer()) {
10760b57cec5SDimitry Andric     // null maps to null.
10770b57cec5SDimitry Andric     if (src->isAllOnesValue()) return src;
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric     if (isDerivedToBase)
10800b57cec5SDimitry Andric       return llvm::ConstantExpr::getNSWSub(src, adj);
10810b57cec5SDimitry Andric     else
10820b57cec5SDimitry Andric       return llvm::ConstantExpr::getNSWAdd(src, adj);
10830b57cec5SDimitry Andric   }
10840b57cec5SDimitry Andric 
10850b57cec5SDimitry Andric   // The this-adjustment is left-shifted by 1 on ARM.
10860b57cec5SDimitry Andric   if (UseARMMethodPtrABI) {
10870b57cec5SDimitry Andric     uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
10880b57cec5SDimitry Andric     offset <<= 1;
10890b57cec5SDimitry Andric     adj = llvm::ConstantInt::get(adj->getType(), offset);
10900b57cec5SDimitry Andric   }
10910b57cec5SDimitry Andric 
109281ad6265SDimitry Andric   llvm::Constant *srcAdj = src->getAggregateElement(1);
10930b57cec5SDimitry Andric   llvm::Constant *dstAdj;
10940b57cec5SDimitry Andric   if (isDerivedToBase)
10950b57cec5SDimitry Andric     dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);
10960b57cec5SDimitry Andric   else
10970b57cec5SDimitry Andric     dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);
10980b57cec5SDimitry Andric 
109981ad6265SDimitry Andric   llvm::Constant *res = ConstantFoldInsertValueInstruction(src, dstAdj, 1);
110081ad6265SDimitry Andric   assert(res != nullptr && "Folding must succeed");
110181ad6265SDimitry Andric   return res;
11020b57cec5SDimitry Andric }
11030b57cec5SDimitry Andric 
11040b57cec5SDimitry Andric llvm::Constant *
11050b57cec5SDimitry Andric ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
11060b57cec5SDimitry Andric   // Itanium C++ ABI 2.3:
11070b57cec5SDimitry Andric   //   A NULL pointer is represented as -1.
11080b57cec5SDimitry Andric   if (MPT->isMemberDataPointer())
11090b57cec5SDimitry Andric     return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, /*isSigned=*/true);
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric   llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
11120b57cec5SDimitry Andric   llvm::Constant *Values[2] = { Zero, Zero };
11130b57cec5SDimitry Andric   return llvm::ConstantStruct::getAnon(Values);
11140b57cec5SDimitry Andric }
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric llvm::Constant *
11170b57cec5SDimitry Andric ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
11180b57cec5SDimitry Andric                                      CharUnits offset) {
11190b57cec5SDimitry Andric   // Itanium C++ ABI 2.3:
11200b57cec5SDimitry Andric   //   A pointer to data member is an offset from the base address of
11210b57cec5SDimitry Andric   //   the class object containing it, represented as a ptrdiff_t
11220b57cec5SDimitry Andric   return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity());
11230b57cec5SDimitry Andric }
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric llvm::Constant *
11260b57cec5SDimitry Andric ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
11270b57cec5SDimitry Andric   return BuildMemberPointer(MD, CharUnits::Zero());
11280b57cec5SDimitry Andric }
11290b57cec5SDimitry Andric 
11300b57cec5SDimitry Andric llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
11310b57cec5SDimitry Andric                                                   CharUnits ThisAdjustment) {
11320b57cec5SDimitry Andric   assert(MD->isInstance() && "Member function must not be static!");
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   CodeGenTypes &Types = CGM.getTypes();
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric   // Get the function pointer (or index if this is a virtual function).
11370b57cec5SDimitry Andric   llvm::Constant *MemPtr[2];
11380b57cec5SDimitry Andric   if (MD->isVirtual()) {
11390b57cec5SDimitry Andric     uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
11405ffd83dbSDimitry Andric     uint64_t VTableOffset;
11415ffd83dbSDimitry Andric     if (CGM.getItaniumVTableContext().isRelativeLayout()) {
11425ffd83dbSDimitry Andric       // Multiply by 4-byte relative offsets.
11435ffd83dbSDimitry Andric       VTableOffset = Index * 4;
11445ffd83dbSDimitry Andric     } else {
11450b57cec5SDimitry Andric       const ASTContext &Context = getContext();
11465ffd83dbSDimitry Andric       CharUnits PointerWidth = Context.toCharUnitsFromBits(
1147bdd1243dSDimitry Andric           Context.getTargetInfo().getPointerWidth(LangAS::Default));
11485ffd83dbSDimitry Andric       VTableOffset = Index * PointerWidth.getQuantity();
11495ffd83dbSDimitry Andric     }
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric     if (UseARMMethodPtrABI) {
11520b57cec5SDimitry Andric       // ARM C++ ABI 3.2.1:
11530b57cec5SDimitry Andric       //   This ABI specifies that adj contains twice the this
11540b57cec5SDimitry Andric       //   adjustment, plus 1 if the member function is virtual. The
11550b57cec5SDimitry Andric       //   least significant bit of adj then makes exactly the same
11560b57cec5SDimitry Andric       //   discrimination as the least significant bit of ptr does for
11570b57cec5SDimitry Andric       //   Itanium.
11580fca6ea1SDimitry Andric 
11590fca6ea1SDimitry Andric       // We cannot use the Itanium ABI's representation for virtual member
11600fca6ea1SDimitry Andric       // function pointers under pointer authentication because it would
11610fca6ea1SDimitry Andric       // require us to store both the virtual offset and the constant
11620fca6ea1SDimitry Andric       // discriminator in the pointer, which would be immediately vulnerable
11630fca6ea1SDimitry Andric       // to attack.  Instead we introduce a thunk that does the virtual dispatch
11640fca6ea1SDimitry Andric       // and store it as if it were a non-virtual member function.  This means
11650fca6ea1SDimitry Andric       // that virtual function pointers may not compare equal anymore, but
11660fca6ea1SDimitry Andric       // fortunately they aren't required to by the standard, and we do make
11670fca6ea1SDimitry Andric       // a best-effort attempt to re-use the thunk.
11680fca6ea1SDimitry Andric       //
11690fca6ea1SDimitry Andric       // To support interoperation with code in which pointer authentication
11700fca6ea1SDimitry Andric       // is disabled, derefencing a member function pointer must still handle
11710fca6ea1SDimitry Andric       // the virtual case, but it can use a discriminator which should never
11720fca6ea1SDimitry Andric       // be valid.
11730fca6ea1SDimitry Andric       const auto &Schema =
11740fca6ea1SDimitry Andric           CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers;
11750fca6ea1SDimitry Andric       if (Schema)
11760fca6ea1SDimitry Andric         MemPtr[0] = llvm::ConstantExpr::getPtrToInt(
11770fca6ea1SDimitry Andric             getSignedVirtualMemberFunctionPointer(MD), CGM.PtrDiffTy);
11780fca6ea1SDimitry Andric       else
11790b57cec5SDimitry Andric         MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);
11800fca6ea1SDimitry Andric       // Don't set the LSB of adj to 1 if pointer authentication for member
11810fca6ea1SDimitry Andric       // function pointers is enabled.
11820fca6ea1SDimitry Andric       MemPtr[1] = llvm::ConstantInt::get(
11830fca6ea1SDimitry Andric           CGM.PtrDiffTy, 2 * ThisAdjustment.getQuantity() + !Schema);
11840b57cec5SDimitry Andric     } else {
11850b57cec5SDimitry Andric       // Itanium C++ ABI 2.3:
11860b57cec5SDimitry Andric       //   For a virtual function, [the pointer field] is 1 plus the
11870b57cec5SDimitry Andric       //   virtual table offset (in bytes) of the function,
11880b57cec5SDimitry Andric       //   represented as a ptrdiff_t.
11890b57cec5SDimitry Andric       MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
11900b57cec5SDimitry Andric       MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
11910b57cec5SDimitry Andric                                          ThisAdjustment.getQuantity());
11920b57cec5SDimitry Andric     }
11930b57cec5SDimitry Andric   } else {
11940b57cec5SDimitry Andric     const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
11950b57cec5SDimitry Andric     llvm::Type *Ty;
11960b57cec5SDimitry Andric     // Check whether the function has a computable LLVM signature.
11970b57cec5SDimitry Andric     if (Types.isFuncTypeConvertible(FPT)) {
11980b57cec5SDimitry Andric       // The function has a computable LLVM signature; use the correct type.
11990b57cec5SDimitry Andric       Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
12000b57cec5SDimitry Andric     } else {
12010b57cec5SDimitry Andric       // Use an arbitrary non-function type to tell GetAddrOfFunction that the
12020b57cec5SDimitry Andric       // function type is incomplete.
12030b57cec5SDimitry Andric       Ty = CGM.PtrDiffTy;
12040b57cec5SDimitry Andric     }
12050fca6ea1SDimitry Andric     llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty);
12060b57cec5SDimitry Andric 
12070b57cec5SDimitry Andric     MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
12080b57cec5SDimitry Andric     MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
12090b57cec5SDimitry Andric                                        (UseARMMethodPtrABI ? 2 : 1) *
12100b57cec5SDimitry Andric                                        ThisAdjustment.getQuantity());
12110b57cec5SDimitry Andric   }
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric   return llvm::ConstantStruct::getAnon(MemPtr);
12140b57cec5SDimitry Andric }
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
12170b57cec5SDimitry Andric                                                  QualType MPType) {
12180b57cec5SDimitry Andric   const MemberPointerType *MPT = MPType->castAs<MemberPointerType>();
12190b57cec5SDimitry Andric   const ValueDecl *MPD = MP.getMemberPointerDecl();
12200b57cec5SDimitry Andric   if (!MPD)
12210b57cec5SDimitry Andric     return EmitNullMemberPointer(MPT);
12220b57cec5SDimitry Andric 
1223e8d8bef9SDimitry Andric   CharUnits ThisAdjustment = getContext().getMemberPointerPathAdjustment(MP);
12240b57cec5SDimitry Andric 
12250fca6ea1SDimitry Andric   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
12260fca6ea1SDimitry Andric     llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment);
12270fca6ea1SDimitry Andric     QualType SrcType = getContext().getMemberPointerType(
12280fca6ea1SDimitry Andric         MD->getType(), MD->getParent()->getTypeForDecl());
12290fca6ea1SDimitry Andric     return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM);
12300fca6ea1SDimitry Andric   }
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric   CharUnits FieldOffset =
12330b57cec5SDimitry Andric     getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
12340b57cec5SDimitry Andric   return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
12350b57cec5SDimitry Andric }
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric /// The comparison algorithm is pretty easy: the member pointers are
12380b57cec5SDimitry Andric /// the same if they're either bitwise identical *or* both null.
12390b57cec5SDimitry Andric ///
12400b57cec5SDimitry Andric /// ARM is different here only because null-ness is more complicated.
12410b57cec5SDimitry Andric llvm::Value *
12420b57cec5SDimitry Andric ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
12430b57cec5SDimitry Andric                                            llvm::Value *L,
12440b57cec5SDimitry Andric                                            llvm::Value *R,
12450b57cec5SDimitry Andric                                            const MemberPointerType *MPT,
12460b57cec5SDimitry Andric                                            bool Inequality) {
12470b57cec5SDimitry Andric   CGBuilderTy &Builder = CGF.Builder;
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric   llvm::ICmpInst::Predicate Eq;
12500b57cec5SDimitry Andric   llvm::Instruction::BinaryOps And, Or;
12510b57cec5SDimitry Andric   if (Inequality) {
12520b57cec5SDimitry Andric     Eq = llvm::ICmpInst::ICMP_NE;
12530b57cec5SDimitry Andric     And = llvm::Instruction::Or;
12540b57cec5SDimitry Andric     Or = llvm::Instruction::And;
12550b57cec5SDimitry Andric   } else {
12560b57cec5SDimitry Andric     Eq = llvm::ICmpInst::ICMP_EQ;
12570b57cec5SDimitry Andric     And = llvm::Instruction::And;
12580b57cec5SDimitry Andric     Or = llvm::Instruction::Or;
12590b57cec5SDimitry Andric   }
12600b57cec5SDimitry Andric 
12610b57cec5SDimitry Andric   // Member data pointers are easy because there's a unique null
12620b57cec5SDimitry Andric   // value, so it just comes down to bitwise equality.
12630b57cec5SDimitry Andric   if (MPT->isMemberDataPointer())
12640b57cec5SDimitry Andric     return Builder.CreateICmp(Eq, L, R);
12650b57cec5SDimitry Andric 
12660b57cec5SDimitry Andric   // For member function pointers, the tautologies are more complex.
12670b57cec5SDimitry Andric   // The Itanium tautology is:
12680b57cec5SDimitry Andric   //   (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj))
12690b57cec5SDimitry Andric   // The ARM tautology is:
12700b57cec5SDimitry Andric   //   (L == R) <==> (L.ptr == R.ptr &&
12710b57cec5SDimitry Andric   //                  (L.adj == R.adj ||
12720b57cec5SDimitry Andric   //                   (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0)))
12730b57cec5SDimitry Andric   // The inequality tautologies have exactly the same structure, except
12740b57cec5SDimitry Andric   // applying De Morgan's laws.
12750b57cec5SDimitry Andric 
12760b57cec5SDimitry Andric   llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr");
12770b57cec5SDimitry Andric   llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr");
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric   // This condition tests whether L.ptr == R.ptr.  This must always be
12800b57cec5SDimitry Andric   // true for equality to hold.
12810b57cec5SDimitry Andric   llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr");
12820b57cec5SDimitry Andric 
12830b57cec5SDimitry Andric   // This condition, together with the assumption that L.ptr == R.ptr,
12840b57cec5SDimitry Andric   // tests whether the pointers are both null.  ARM imposes an extra
12850b57cec5SDimitry Andric   // condition.
12860b57cec5SDimitry Andric   llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType());
12870b57cec5SDimitry Andric   llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null");
12880b57cec5SDimitry Andric 
12890b57cec5SDimitry Andric   // This condition tests whether L.adj == R.adj.  If this isn't
12900b57cec5SDimitry Andric   // true, the pointers are unequal unless they're both null.
12910b57cec5SDimitry Andric   llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj");
12920b57cec5SDimitry Andric   llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj");
12930b57cec5SDimitry Andric   llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj");
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric   // Null member function pointers on ARM clear the low bit of Adj,
12960b57cec5SDimitry Andric   // so the zero condition has to check that neither low bit is set.
12970b57cec5SDimitry Andric   if (UseARMMethodPtrABI) {
12980b57cec5SDimitry Andric     llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric     // Compute (l.adj | r.adj) & 1 and test it against zero.
13010b57cec5SDimitry Andric     llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");
13020b57cec5SDimitry Andric     llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
13030b57cec5SDimitry Andric     llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,
13040b57cec5SDimitry Andric                                                       "cmp.or.adj");
13050b57cec5SDimitry Andric     EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
13060b57cec5SDimitry Andric   }
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric   // Tie together all our conditions.
13090b57cec5SDimitry Andric   llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
13100b57cec5SDimitry Andric   Result = Builder.CreateBinOp(And, PtrEq, Result,
13110b57cec5SDimitry Andric                                Inequality ? "memptr.ne" : "memptr.eq");
13120b57cec5SDimitry Andric   return Result;
13130b57cec5SDimitry Andric }
13140b57cec5SDimitry Andric 
13150b57cec5SDimitry Andric llvm::Value *
13160b57cec5SDimitry Andric ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
13170b57cec5SDimitry Andric                                           llvm::Value *MemPtr,
13180b57cec5SDimitry Andric                                           const MemberPointerType *MPT) {
13190b57cec5SDimitry Andric   CGBuilderTy &Builder = CGF.Builder;
13200b57cec5SDimitry Andric 
13210b57cec5SDimitry Andric   /// For member data pointers, this is just a check against -1.
13220b57cec5SDimitry Andric   if (MPT->isMemberDataPointer()) {
13230b57cec5SDimitry Andric     assert(MemPtr->getType() == CGM.PtrDiffTy);
13240b57cec5SDimitry Andric     llvm::Value *NegativeOne =
13250b57cec5SDimitry Andric       llvm::Constant::getAllOnesValue(MemPtr->getType());
13260b57cec5SDimitry Andric     return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");
13270b57cec5SDimitry Andric   }
13280b57cec5SDimitry Andric 
13290b57cec5SDimitry Andric   // In Itanium, a member function pointer is not null if 'ptr' is not null.
13300b57cec5SDimitry Andric   llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr");
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric   llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
13330b57cec5SDimitry Andric   llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool");
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric   // On ARM, a member function pointer is also non-null if the low bit of 'adj'
13360b57cec5SDimitry Andric   // (the virtual bit) is set.
13370b57cec5SDimitry Andric   if (UseARMMethodPtrABI) {
13380b57cec5SDimitry Andric     llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
13390b57cec5SDimitry Andric     llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
13400b57cec5SDimitry Andric     llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
13410b57cec5SDimitry Andric     llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,
13420b57cec5SDimitry Andric                                                   "memptr.isvirtual");
13430b57cec5SDimitry Andric     Result = Builder.CreateOr(Result, IsVirtual);
13440b57cec5SDimitry Andric   }
13450b57cec5SDimitry Andric 
13460b57cec5SDimitry Andric   return Result;
13470b57cec5SDimitry Andric }
13480b57cec5SDimitry Andric 
13490b57cec5SDimitry Andric bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
13500b57cec5SDimitry Andric   const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
13510b57cec5SDimitry Andric   if (!RD)
13520b57cec5SDimitry Andric     return false;
13530b57cec5SDimitry Andric 
13540b57cec5SDimitry Andric   // If C++ prohibits us from making a copy, return by address.
13550b57cec5SDimitry Andric   if (!RD->canPassInRegisters()) {
13560b57cec5SDimitry Andric     auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
13570b57cec5SDimitry Andric     FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
13580b57cec5SDimitry Andric     return true;
13590b57cec5SDimitry Andric   }
13600b57cec5SDimitry Andric   return false;
13610b57cec5SDimitry Andric }
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric /// The Itanium ABI requires non-zero initialization only for data
13640b57cec5SDimitry Andric /// member pointers, for which '0' is a valid offset.
13650b57cec5SDimitry Andric bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
13660b57cec5SDimitry Andric   return MPT->isMemberFunctionPointer();
13670b57cec5SDimitry Andric }
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric /// The Itanium ABI always places an offset to the complete object
13700b57cec5SDimitry Andric /// at entry -2 in the vtable.
13710b57cec5SDimitry Andric void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
13720b57cec5SDimitry Andric                                             const CXXDeleteExpr *DE,
13730b57cec5SDimitry Andric                                             Address Ptr,
13740b57cec5SDimitry Andric                                             QualType ElementType,
13750b57cec5SDimitry Andric                                             const CXXDestructorDecl *Dtor) {
13760b57cec5SDimitry Andric   bool UseGlobalDelete = DE->isGlobalDelete();
13770b57cec5SDimitry Andric   if (UseGlobalDelete) {
13780b57cec5SDimitry Andric     // Derive the complete-object pointer, which is what we need
13790b57cec5SDimitry Andric     // to pass to the deallocation function.
13800b57cec5SDimitry Andric 
13810b57cec5SDimitry Andric     // Grab the vtable pointer as an intptr_t*.
13820b57cec5SDimitry Andric     auto *ClassDecl =
1383a7dea167SDimitry Andric         cast<CXXRecordDecl>(ElementType->castAs<RecordType>()->getDecl());
13845f757f3fSDimitry Andric     llvm::Value *VTable = CGF.GetVTablePtr(Ptr, CGF.UnqualPtrTy, ClassDecl);
13850b57cec5SDimitry Andric 
13860b57cec5SDimitry Andric     // Track back to entry -2 and pull out the offset there.
13870b57cec5SDimitry Andric     llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
1388fe6060f1SDimitry Andric         CGF.IntPtrTy, VTable, -2, "complete-offset.ptr");
138906c3fb27SDimitry Andric     llvm::Value *Offset = CGF.Builder.CreateAlignedLoad(CGF.IntPtrTy, OffsetPtr,
139006c3fb27SDimitry Andric                                                         CGF.getPointerAlign());
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric     // Apply the offset.
13930fca6ea1SDimitry Andric     llvm::Value *CompletePtr = Ptr.emitRawPointer(CGF);
1394fe6060f1SDimitry Andric     CompletePtr =
1395fe6060f1SDimitry Andric         CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, CompletePtr, Offset);
13960b57cec5SDimitry Andric 
13970b57cec5SDimitry Andric     // If we're supposed to call the global delete, make sure we do so
13980b57cec5SDimitry Andric     // even if the destructor throws.
13990b57cec5SDimitry Andric     CGF.pushCallObjectDeleteCleanup(DE->getOperatorDelete(), CompletePtr,
14000b57cec5SDimitry Andric                                     ElementType);
14010b57cec5SDimitry Andric   }
14020b57cec5SDimitry Andric 
14030b57cec5SDimitry Andric   // FIXME: Provide a source location here even though there's no
14040b57cec5SDimitry Andric   // CXXMemberCallExpr for dtor call.
14050b57cec5SDimitry Andric   CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
14060b57cec5SDimitry Andric   EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE);
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric   if (UseGlobalDelete)
14090b57cec5SDimitry Andric     CGF.PopCleanupBlock();
14100b57cec5SDimitry Andric }
14110b57cec5SDimitry Andric 
14120b57cec5SDimitry Andric void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
14130b57cec5SDimitry Andric   // void __cxa_rethrow();
14140b57cec5SDimitry Andric 
14150b57cec5SDimitry Andric   llvm::FunctionType *FTy =
14160b57cec5SDimitry Andric     llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric   llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
14190b57cec5SDimitry Andric 
14200b57cec5SDimitry Andric   if (isNoReturn)
1421bdd1243dSDimitry Andric     CGF.EmitNoreturnRuntimeCallOrInvoke(Fn, std::nullopt);
14220b57cec5SDimitry Andric   else
14230b57cec5SDimitry Andric     CGF.EmitRuntimeCallOrInvoke(Fn);
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM) {
14270b57cec5SDimitry Andric   // void *__cxa_allocate_exception(size_t thrown_size);
14280b57cec5SDimitry Andric 
14290b57cec5SDimitry Andric   llvm::FunctionType *FTy =
14300b57cec5SDimitry Andric     llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*isVarArg=*/false);
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric   return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
14330b57cec5SDimitry Andric }
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM) {
14360b57cec5SDimitry Andric   // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
14370b57cec5SDimitry Andric   //                  void (*dest) (void *));
14380b57cec5SDimitry Andric 
143906c3fb27SDimitry Andric   llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.GlobalsInt8PtrTy, CGM.Int8PtrTy };
14400b57cec5SDimitry Andric   llvm::FunctionType *FTy =
14410b57cec5SDimitry Andric     llvm::FunctionType::get(CGM.VoidTy, Args, /*isVarArg=*/false);
14420b57cec5SDimitry Andric 
14430b57cec5SDimitry Andric   return CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
14440b57cec5SDimitry Andric }
14450b57cec5SDimitry Andric 
14460b57cec5SDimitry Andric void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
14470b57cec5SDimitry Andric   QualType ThrowType = E->getSubExpr()->getType();
14480b57cec5SDimitry Andric   // Now allocate the exception object.
14490b57cec5SDimitry Andric   llvm::Type *SizeTy = CGF.ConvertType(getContext().getSizeType());
14500b57cec5SDimitry Andric   uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
14510b57cec5SDimitry Andric 
14520b57cec5SDimitry Andric   llvm::FunctionCallee AllocExceptionFn = getAllocateExceptionFn(CGM);
14530b57cec5SDimitry Andric   llvm::CallInst *ExceptionPtr = CGF.EmitNounwindRuntimeCall(
14540b57cec5SDimitry Andric       AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception");
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric   CharUnits ExnAlign = CGF.getContext().getExnObjectAlignment();
14570eae32dcSDimitry Andric   CGF.EmitAnyExprToExn(
14580eae32dcSDimitry Andric       E->getSubExpr(), Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
14590b57cec5SDimitry Andric 
14600b57cec5SDimitry Andric   // Now throw the exception.
14610b57cec5SDimitry Andric   llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
14620b57cec5SDimitry Andric                                                          /*ForEH=*/true);
14630b57cec5SDimitry Andric 
14640b57cec5SDimitry Andric   // The address of the destructor.  If the exception type has a
14650b57cec5SDimitry Andric   // trivial destructor (or isn't a record), we just pass null.
14660b57cec5SDimitry Andric   llvm::Constant *Dtor = nullptr;
14670b57cec5SDimitry Andric   if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
14680b57cec5SDimitry Andric     CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
14690b57cec5SDimitry Andric     if (!Record->hasTrivialDestructor()) {
14700fca6ea1SDimitry Andric       // __cxa_throw is declared to take its destructor as void (*)(void *). We
14710fca6ea1SDimitry Andric       // must match that if function pointers can be authenticated with a
14720fca6ea1SDimitry Andric       // discriminator based on their type.
14730fca6ea1SDimitry Andric       const ASTContext &Ctx = getContext();
14740fca6ea1SDimitry Andric       QualType DtorTy = Ctx.getFunctionType(Ctx.VoidTy, {Ctx.VoidPtrTy},
14750fca6ea1SDimitry Andric                                             FunctionProtoType::ExtProtoInfo());
14760fca6ea1SDimitry Andric 
14770b57cec5SDimitry Andric       CXXDestructorDecl *DtorD = Record->getDestructor();
14780b57cec5SDimitry Andric       Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete));
14790fca6ea1SDimitry Andric       Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
14800b57cec5SDimitry Andric     }
14810b57cec5SDimitry Andric   }
14820b57cec5SDimitry Andric   if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
14830b57cec5SDimitry Andric 
14840b57cec5SDimitry Andric   llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };
14850b57cec5SDimitry Andric   CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args);
14860b57cec5SDimitry Andric }
14870b57cec5SDimitry Andric 
14880b57cec5SDimitry Andric static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF) {
14890b57cec5SDimitry Andric   // void *__dynamic_cast(const void *sub,
14905f757f3fSDimitry Andric   //                      global_as const abi::__class_type_info *src,
14915f757f3fSDimitry Andric   //                      global_as const abi::__class_type_info *dst,
14920b57cec5SDimitry Andric   //                      std::ptrdiff_t src2dst_offset);
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric   llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
14955f757f3fSDimitry Andric   llvm::Type *GlobInt8PtrTy = CGF.GlobalsInt8PtrTy;
14960b57cec5SDimitry Andric   llvm::Type *PtrDiffTy =
14970b57cec5SDimitry Andric     CGF.ConvertType(CGF.getContext().getPointerDiffType());
14980b57cec5SDimitry Andric 
14995f757f3fSDimitry Andric   llvm::Type *Args[4] = { Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy };
15000b57cec5SDimitry Andric 
15010b57cec5SDimitry Andric   llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
15020b57cec5SDimitry Andric 
15030fca6ea1SDimitry Andric   // Mark the function as nounwind willreturn readonly.
1504bdd1243dSDimitry Andric   llvm::AttrBuilder FuncAttrs(CGF.getLLVMContext());
1505bdd1243dSDimitry Andric   FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
15060fca6ea1SDimitry Andric   FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
1507bdd1243dSDimitry Andric   FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
15080b57cec5SDimitry Andric   llvm::AttributeList Attrs = llvm::AttributeList::get(
15090b57cec5SDimitry Andric       CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
15100b57cec5SDimitry Andric 
15110b57cec5SDimitry Andric   return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs);
15120b57cec5SDimitry Andric }
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric static llvm::FunctionCallee getBadCastFn(CodeGenFunction &CGF) {
15150b57cec5SDimitry Andric   // void __cxa_bad_cast();
15160b57cec5SDimitry Andric   llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
15170b57cec5SDimitry Andric   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
15180b57cec5SDimitry Andric }
15190b57cec5SDimitry Andric 
15200b57cec5SDimitry Andric /// Compute the src2dst_offset hint as described in the
15210b57cec5SDimitry Andric /// Itanium C++ ABI [2.9.7]
15220b57cec5SDimitry Andric static CharUnits computeOffsetHint(ASTContext &Context,
15230b57cec5SDimitry Andric                                    const CXXRecordDecl *Src,
15240b57cec5SDimitry Andric                                    const CXXRecordDecl *Dst) {
15250b57cec5SDimitry Andric   CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
15260b57cec5SDimitry Andric                      /*DetectVirtual=*/false);
15270b57cec5SDimitry Andric 
15280b57cec5SDimitry Andric   // If Dst is not derived from Src we can skip the whole computation below and
15290b57cec5SDimitry Andric   // return that Src is not a public base of Dst.  Record all inheritance paths.
15300b57cec5SDimitry Andric   if (!Dst->isDerivedFrom(Src, Paths))
15310b57cec5SDimitry Andric     return CharUnits::fromQuantity(-2ULL);
15320b57cec5SDimitry Andric 
15330b57cec5SDimitry Andric   unsigned NumPublicPaths = 0;
15340b57cec5SDimitry Andric   CharUnits Offset;
15350b57cec5SDimitry Andric 
15360b57cec5SDimitry Andric   // Now walk all possible inheritance paths.
15370b57cec5SDimitry Andric   for (const CXXBasePath &Path : Paths) {
15380b57cec5SDimitry Andric     if (Path.Access != AS_public)  // Ignore non-public inheritance.
15390b57cec5SDimitry Andric       continue;
15400b57cec5SDimitry Andric 
15410b57cec5SDimitry Andric     ++NumPublicPaths;
15420b57cec5SDimitry Andric 
15430b57cec5SDimitry Andric     for (const CXXBasePathElement &PathElement : Path) {
15440b57cec5SDimitry Andric       // If the path contains a virtual base class we can't give any hint.
15450b57cec5SDimitry Andric       // -1: no hint.
15460b57cec5SDimitry Andric       if (PathElement.Base->isVirtual())
15470b57cec5SDimitry Andric         return CharUnits::fromQuantity(-1ULL);
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric       if (NumPublicPaths > 1) // Won't use offsets, skip computation.
15500b57cec5SDimitry Andric         continue;
15510b57cec5SDimitry Andric 
15520b57cec5SDimitry Andric       // Accumulate the base class offsets.
15530b57cec5SDimitry Andric       const ASTRecordLayout &L = Context.getASTRecordLayout(PathElement.Class);
15540b57cec5SDimitry Andric       Offset += L.getBaseClassOffset(
15550b57cec5SDimitry Andric           PathElement.Base->getType()->getAsCXXRecordDecl());
15560b57cec5SDimitry Andric     }
15570b57cec5SDimitry Andric   }
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric   // -2: Src is not a public base of Dst.
15600b57cec5SDimitry Andric   if (NumPublicPaths == 0)
15610b57cec5SDimitry Andric     return CharUnits::fromQuantity(-2ULL);
15620b57cec5SDimitry Andric 
15630b57cec5SDimitry Andric   // -3: Src is a multiple public base type but never a virtual base type.
15640b57cec5SDimitry Andric   if (NumPublicPaths > 1)
15650b57cec5SDimitry Andric     return CharUnits::fromQuantity(-3ULL);
15660b57cec5SDimitry Andric 
15670b57cec5SDimitry Andric   // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
15680b57cec5SDimitry Andric   // Return the offset of Src from the origin of Dst.
15690b57cec5SDimitry Andric   return Offset;
15700b57cec5SDimitry Andric }
15710b57cec5SDimitry Andric 
15720b57cec5SDimitry Andric static llvm::FunctionCallee getBadTypeidFn(CodeGenFunction &CGF) {
15730b57cec5SDimitry Andric   // void __cxa_bad_typeid();
15740b57cec5SDimitry Andric   llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
15770b57cec5SDimitry Andric }
15780b57cec5SDimitry Andric 
15790fca6ea1SDimitry Andric bool ItaniumCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {
15800fca6ea1SDimitry Andric   return true;
15810b57cec5SDimitry Andric }
15820b57cec5SDimitry Andric 
15830b57cec5SDimitry Andric void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
15840b57cec5SDimitry Andric   llvm::FunctionCallee Fn = getBadTypeidFn(CGF);
15850b57cec5SDimitry Andric   llvm::CallBase *Call = CGF.EmitRuntimeCallOrInvoke(Fn);
15860b57cec5SDimitry Andric   Call->setDoesNotReturn();
15870b57cec5SDimitry Andric   CGF.Builder.CreateUnreachable();
15880b57cec5SDimitry Andric }
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
15910b57cec5SDimitry Andric                                        QualType SrcRecordTy,
15920b57cec5SDimitry Andric                                        Address ThisPtr,
15930b57cec5SDimitry Andric                                        llvm::Type *StdTypeInfoPtrTy) {
15940b57cec5SDimitry Andric   auto *ClassDecl =
1595a7dea167SDimitry Andric       cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
15965f757f3fSDimitry Andric   llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,
15975f757f3fSDimitry Andric                                         ClassDecl);
15980b57cec5SDimitry Andric 
15995ffd83dbSDimitry Andric   if (CGM.getItaniumVTableContext().isRelativeLayout()) {
16005ffd83dbSDimitry Andric     // Load the type info.
16015ffd83dbSDimitry Andric     Value = CGF.Builder.CreateCall(
16025ffd83dbSDimitry Andric         CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
16035ffd83dbSDimitry Andric         {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
16045ffd83dbSDimitry Andric   } else {
16050b57cec5SDimitry Andric     // Load the type info.
1606fe6060f1SDimitry Andric     Value =
1607fe6060f1SDimitry Andric         CGF.Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy, Value, -1ULL);
16085ffd83dbSDimitry Andric   }
1609fe6060f1SDimitry Andric   return CGF.Builder.CreateAlignedLoad(StdTypeInfoPtrTy, Value,
1610fe6060f1SDimitry Andric                                        CGF.getPointerAlign());
16110b57cec5SDimitry Andric }
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
16140b57cec5SDimitry Andric                                                        QualType SrcRecordTy) {
16150b57cec5SDimitry Andric   return SrcIsPtr;
16160b57cec5SDimitry Andric }
16170b57cec5SDimitry Andric 
161806c3fb27SDimitry Andric llvm::Value *ItaniumCXXABI::emitDynamicCastCall(
16190b57cec5SDimitry Andric     CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
16200b57cec5SDimitry Andric     QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
16210b57cec5SDimitry Andric   llvm::Type *PtrDiffLTy =
16220b57cec5SDimitry Andric       CGF.ConvertType(CGF.getContext().getPointerDiffType());
16230b57cec5SDimitry Andric 
16240b57cec5SDimitry Andric   llvm::Value *SrcRTTI =
16250b57cec5SDimitry Andric       CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
16260b57cec5SDimitry Andric   llvm::Value *DestRTTI =
16270b57cec5SDimitry Andric       CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric   // Compute the offset hint.
16300b57cec5SDimitry Andric   const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
16310b57cec5SDimitry Andric   const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
16320b57cec5SDimitry Andric   llvm::Value *OffsetHint = llvm::ConstantInt::get(
16330b57cec5SDimitry Andric       PtrDiffLTy,
16340b57cec5SDimitry Andric       computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity());
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric   // Emit the call to __dynamic_cast.
16370fca6ea1SDimitry Andric   llvm::Value *Value = ThisAddr.emitRawPointer(CGF);
16380fca6ea1SDimitry Andric   if (CGM.getCodeGenOpts().PointerAuth.CXXVTablePointers) {
16390fca6ea1SDimitry Andric     // We perform a no-op load of the vtable pointer here to force an
16400fca6ea1SDimitry Andric     // authentication. In environments that do not support pointer
16410fca6ea1SDimitry Andric     // authentication this is a an actual no-op that will be elided. When
16420fca6ea1SDimitry Andric     // pointer authentication is supported and enforced on vtable pointers this
16430fca6ea1SDimitry Andric     // load can trap.
16440fca6ea1SDimitry Andric     llvm::Value *Vtable =
16450fca6ea1SDimitry Andric         CGF.GetVTablePtr(ThisAddr, CGM.Int8PtrTy, SrcDecl,
16460fca6ea1SDimitry Andric                          CodeGenFunction::VTableAuthMode::MustTrap);
16470fca6ea1SDimitry Andric     assert(Vtable);
16480fca6ea1SDimitry Andric     (void)Vtable;
16490fca6ea1SDimitry Andric   }
16500fca6ea1SDimitry Andric 
16510fca6ea1SDimitry Andric   llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint};
16520fca6ea1SDimitry Andric   Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), args);
16530b57cec5SDimitry Andric 
16540b57cec5SDimitry Andric   /// C++ [expr.dynamic.cast]p9:
16550b57cec5SDimitry Andric   ///   A failed cast to reference type throws std::bad_cast
16560b57cec5SDimitry Andric   if (DestTy->isReferenceType()) {
16570b57cec5SDimitry Andric     llvm::BasicBlock *BadCastBlock =
16580b57cec5SDimitry Andric         CGF.createBasicBlock("dynamic_cast.bad_cast");
16590b57cec5SDimitry Andric 
16600b57cec5SDimitry Andric     llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value);
16610b57cec5SDimitry Andric     CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
16620b57cec5SDimitry Andric 
16630b57cec5SDimitry Andric     CGF.EmitBlock(BadCastBlock);
16640b57cec5SDimitry Andric     EmitBadCastCall(CGF);
16650b57cec5SDimitry Andric   }
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric   return Value;
16680b57cec5SDimitry Andric }
16690b57cec5SDimitry Andric 
167006c3fb27SDimitry Andric llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
167106c3fb27SDimitry Andric     CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
167206c3fb27SDimitry Andric     QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastSuccess,
167306c3fb27SDimitry Andric     llvm::BasicBlock *CastFail) {
167406c3fb27SDimitry Andric   ASTContext &Context = getContext();
167506c3fb27SDimitry Andric 
167606c3fb27SDimitry Andric   // Find all the inheritance paths.
167706c3fb27SDimitry Andric   const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
167806c3fb27SDimitry Andric   const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
167906c3fb27SDimitry Andric   CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
168006c3fb27SDimitry Andric                      /*DetectVirtual=*/false);
168106c3fb27SDimitry Andric   (void)DestDecl->isDerivedFrom(SrcDecl, Paths);
168206c3fb27SDimitry Andric 
168306c3fb27SDimitry Andric   // Find an offset within `DestDecl` where a `SrcDecl` instance and its vptr
168406c3fb27SDimitry Andric   // might appear.
168506c3fb27SDimitry Andric   std::optional<CharUnits> Offset;
168606c3fb27SDimitry Andric   for (const CXXBasePath &Path : Paths) {
168706c3fb27SDimitry Andric     // dynamic_cast only finds public inheritance paths.
168806c3fb27SDimitry Andric     if (Path.Access != AS_public)
168906c3fb27SDimitry Andric       continue;
169006c3fb27SDimitry Andric 
169106c3fb27SDimitry Andric     CharUnits PathOffset;
169206c3fb27SDimitry Andric     for (const CXXBasePathElement &PathElement : Path) {
169306c3fb27SDimitry Andric       // Find the offset along this inheritance step.
169406c3fb27SDimitry Andric       const CXXRecordDecl *Base =
169506c3fb27SDimitry Andric           PathElement.Base->getType()->getAsCXXRecordDecl();
169606c3fb27SDimitry Andric       if (PathElement.Base->isVirtual()) {
169706c3fb27SDimitry Andric         // For a virtual base class, we know that the derived class is exactly
169806c3fb27SDimitry Andric         // DestDecl, so we can use the vbase offset from its layout.
169906c3fb27SDimitry Andric         const ASTRecordLayout &L = Context.getASTRecordLayout(DestDecl);
170006c3fb27SDimitry Andric         PathOffset = L.getVBaseClassOffset(Base);
170106c3fb27SDimitry Andric       } else {
170206c3fb27SDimitry Andric         const ASTRecordLayout &L =
170306c3fb27SDimitry Andric             Context.getASTRecordLayout(PathElement.Class);
170406c3fb27SDimitry Andric         PathOffset += L.getBaseClassOffset(Base);
170506c3fb27SDimitry Andric       }
170606c3fb27SDimitry Andric     }
170706c3fb27SDimitry Andric 
170806c3fb27SDimitry Andric     if (!Offset)
170906c3fb27SDimitry Andric       Offset = PathOffset;
171006c3fb27SDimitry Andric     else if (Offset != PathOffset) {
171106c3fb27SDimitry Andric       // Base appears in at least two different places. Find the most-derived
171206c3fb27SDimitry Andric       // object and see if it's a DestDecl. Note that the most-derived object
171306c3fb27SDimitry Andric       // must be at least as aligned as this base class subobject, and must
171406c3fb27SDimitry Andric       // have a vptr at offset 0.
171506c3fb27SDimitry Andric       ThisAddr = Address(emitDynamicCastToVoid(CGF, ThisAddr, SrcRecordTy),
171606c3fb27SDimitry Andric                          CGF.VoidPtrTy, ThisAddr.getAlignment());
171706c3fb27SDimitry Andric       SrcDecl = DestDecl;
171806c3fb27SDimitry Andric       Offset = CharUnits::Zero();
171906c3fb27SDimitry Andric       break;
172006c3fb27SDimitry Andric     }
172106c3fb27SDimitry Andric   }
172206c3fb27SDimitry Andric 
172306c3fb27SDimitry Andric   if (!Offset) {
172406c3fb27SDimitry Andric     // If there are no public inheritance paths, the cast always fails.
172506c3fb27SDimitry Andric     CGF.EmitBranch(CastFail);
172606c3fb27SDimitry Andric     return llvm::PoisonValue::get(CGF.VoidPtrTy);
172706c3fb27SDimitry Andric   }
172806c3fb27SDimitry Andric 
172906c3fb27SDimitry Andric   // Compare the vptr against the expected vptr for the destination type at
173006c3fb27SDimitry Andric   // this offset. Note that we do not know what type ThisAddr points to in
173106c3fb27SDimitry Andric   // the case where the derived class multiply inherits from the base class
173206c3fb27SDimitry Andric   // so we can't use GetVTablePtr, so we load the vptr directly instead.
173306c3fb27SDimitry Andric   llvm::Instruction *VPtr = CGF.Builder.CreateLoad(
173406c3fb27SDimitry Andric       ThisAddr.withElementType(CGF.VoidPtrPtrTy), "vtable");
173506c3fb27SDimitry Andric   CGM.DecorateInstructionWithTBAA(
173606c3fb27SDimitry Andric       VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.VoidPtrPtrTy));
173706c3fb27SDimitry Andric   llvm::Value *Success = CGF.Builder.CreateICmpEQ(
173806c3fb27SDimitry Andric       VPtr, getVTableAddressPoint(BaseSubobject(SrcDecl, *Offset), DestDecl));
17390fca6ea1SDimitry Andric   llvm::Value *Result = ThisAddr.emitRawPointer(CGF);
174006c3fb27SDimitry Andric   if (!Offset->isZero())
174106c3fb27SDimitry Andric     Result = CGF.Builder.CreateInBoundsGEP(
174206c3fb27SDimitry Andric         CGF.CharTy, Result,
174306c3fb27SDimitry Andric         {llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset->getQuantity())});
174406c3fb27SDimitry Andric   CGF.Builder.CreateCondBr(Success, CastSuccess, CastFail);
174506c3fb27SDimitry Andric   return Result;
174606c3fb27SDimitry Andric }
174706c3fb27SDimitry Andric 
174806c3fb27SDimitry Andric llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
17490b57cec5SDimitry Andric                                                   Address ThisAddr,
175006c3fb27SDimitry Andric                                                   QualType SrcRecordTy) {
17510b57cec5SDimitry Andric   auto *ClassDecl =
1752a7dea167SDimitry Andric       cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
17535ffd83dbSDimitry Andric   llvm::Value *OffsetToTop;
17545ffd83dbSDimitry Andric   if (CGM.getItaniumVTableContext().isRelativeLayout()) {
17550b57cec5SDimitry Andric     // Get the vtable pointer.
17565f757f3fSDimitry Andric     llvm::Value *VTable =
17575f757f3fSDimitry Andric         CGF.GetVTablePtr(ThisAddr, CGF.UnqualPtrTy, ClassDecl);
17580b57cec5SDimitry Andric 
17590b57cec5SDimitry Andric     // Get the offset-to-top from the vtable.
17600b57cec5SDimitry Andric     OffsetToTop =
1761fe6060f1SDimitry Andric         CGF.Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);
17625ffd83dbSDimitry Andric     OffsetToTop = CGF.Builder.CreateAlignedLoad(
1763fe6060f1SDimitry Andric         CGM.Int32Ty, OffsetToTop, CharUnits::fromQuantity(4), "offset.to.top");
17645ffd83dbSDimitry Andric   } else {
17655ffd83dbSDimitry Andric     llvm::Type *PtrDiffLTy =
17665ffd83dbSDimitry Andric         CGF.ConvertType(CGF.getContext().getPointerDiffType());
17670b57cec5SDimitry Andric 
17685ffd83dbSDimitry Andric     // Get the vtable pointer.
17695f757f3fSDimitry Andric     llvm::Value *VTable =
17705f757f3fSDimitry Andric         CGF.GetVTablePtr(ThisAddr, CGF.UnqualPtrTy, ClassDecl);
17715ffd83dbSDimitry Andric 
17725ffd83dbSDimitry Andric     // Get the offset-to-top from the vtable.
1773fe6060f1SDimitry Andric     OffsetToTop =
1774fe6060f1SDimitry Andric         CGF.Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
17755ffd83dbSDimitry Andric     OffsetToTop = CGF.Builder.CreateAlignedLoad(
1776fe6060f1SDimitry Andric         PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top");
17775ffd83dbSDimitry Andric   }
17780b57cec5SDimitry Andric   // Finally, add the offset to the pointer.
17790fca6ea1SDimitry Andric   return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.emitRawPointer(CGF),
178006c3fb27SDimitry Andric                                        OffsetToTop);
17810b57cec5SDimitry Andric }
17820b57cec5SDimitry Andric 
17830b57cec5SDimitry Andric bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
17840b57cec5SDimitry Andric   llvm::FunctionCallee Fn = getBadCastFn(CGF);
17850b57cec5SDimitry Andric   llvm::CallBase *Call = CGF.EmitRuntimeCallOrInvoke(Fn);
17860b57cec5SDimitry Andric   Call->setDoesNotReturn();
17870b57cec5SDimitry Andric   CGF.Builder.CreateUnreachable();
17880b57cec5SDimitry Andric   return true;
17890b57cec5SDimitry Andric }
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric llvm::Value *
17920b57cec5SDimitry Andric ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
17930b57cec5SDimitry Andric                                          Address This,
17940b57cec5SDimitry Andric                                          const CXXRecordDecl *ClassDecl,
17950b57cec5SDimitry Andric                                          const CXXRecordDecl *BaseClassDecl) {
17960b57cec5SDimitry Andric   llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
17970b57cec5SDimitry Andric   CharUnits VBaseOffsetOffset =
17980b57cec5SDimitry Andric       CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
17990b57cec5SDimitry Andric                                                                BaseClassDecl);
18000b57cec5SDimitry Andric   llvm::Value *VBaseOffsetPtr =
1801fe6060f1SDimitry Andric     CGF.Builder.CreateConstGEP1_64(
1802fe6060f1SDimitry Andric         CGF.Int8Ty, VTablePtr, VBaseOffsetOffset.getQuantity(),
18030b57cec5SDimitry Andric         "vbase.offset.ptr");
18045ffd83dbSDimitry Andric 
18055ffd83dbSDimitry Andric   llvm::Value *VBaseOffset;
18065ffd83dbSDimitry Andric   if (CGM.getItaniumVTableContext().isRelativeLayout()) {
18075ffd83dbSDimitry Andric     VBaseOffset = CGF.Builder.CreateAlignedLoad(
1808fe6060f1SDimitry Andric         CGF.Int32Ty, VBaseOffsetPtr, CharUnits::fromQuantity(4),
1809fe6060f1SDimitry Andric         "vbase.offset");
18105ffd83dbSDimitry Andric   } else {
18115ffd83dbSDimitry Andric     VBaseOffset = CGF.Builder.CreateAlignedLoad(
1812fe6060f1SDimitry Andric         CGM.PtrDiffTy, VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");
18135ffd83dbSDimitry Andric   }
18140b57cec5SDimitry Andric   return VBaseOffset;
18150b57cec5SDimitry Andric }
18160b57cec5SDimitry Andric 
18170b57cec5SDimitry Andric void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
18180b57cec5SDimitry Andric   // Just make sure we're in sync with TargetCXXABI.
18190b57cec5SDimitry Andric   assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric   // The constructor used for constructing this as a base class;
18220b57cec5SDimitry Andric   // ignores virtual bases.
18230b57cec5SDimitry Andric   CGM.EmitGlobal(GlobalDecl(D, Ctor_Base));
18240b57cec5SDimitry Andric 
18250b57cec5SDimitry Andric   // The constructor used for constructing this as a complete class;
18260b57cec5SDimitry Andric   // constructs the virtual bases, then calls the base constructor.
18270b57cec5SDimitry Andric   if (!D->getParent()->isAbstract()) {
18280b57cec5SDimitry Andric     // We don't need to emit the complete ctor if the class is abstract.
18290b57cec5SDimitry Andric     CGM.EmitGlobal(GlobalDecl(D, Ctor_Complete));
18300b57cec5SDimitry Andric   }
18310b57cec5SDimitry Andric }
18320b57cec5SDimitry Andric 
18335ffd83dbSDimitry Andric CGCXXABI::AddedStructorArgCounts
18340b57cec5SDimitry Andric ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
18350b57cec5SDimitry Andric                                       SmallVectorImpl<CanQualType> &ArgTys) {
18360b57cec5SDimitry Andric   ASTContext &Context = getContext();
18370b57cec5SDimitry Andric 
18380b57cec5SDimitry Andric   // All parameters are already in place except VTT, which goes after 'this'.
18390b57cec5SDimitry Andric   // These are Clang types, so we don't need to worry about sret yet.
18400b57cec5SDimitry Andric 
184106c3fb27SDimitry Andric   // Check if we need to add a VTT parameter (which has type global void **).
18420b57cec5SDimitry Andric   if ((isa<CXXConstructorDecl>(GD.getDecl()) ? GD.getCtorType() == Ctor_Base
18430b57cec5SDimitry Andric                                              : GD.getDtorType() == Dtor_Base) &&
18440b57cec5SDimitry Andric       cast<CXXMethodDecl>(GD.getDecl())->getParent()->getNumVBases() != 0) {
184506c3fb27SDimitry Andric     LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
184606c3fb27SDimitry Andric     QualType Q = Context.getAddrSpaceQualType(Context.VoidPtrTy, AS);
18470b57cec5SDimitry Andric     ArgTys.insert(ArgTys.begin() + 1,
184806c3fb27SDimitry Andric                   Context.getPointerType(CanQualType::CreateUnsafe(Q)));
18495ffd83dbSDimitry Andric     return AddedStructorArgCounts::prefix(1);
18500b57cec5SDimitry Andric   }
18515ffd83dbSDimitry Andric   return AddedStructorArgCounts{};
18520b57cec5SDimitry Andric }
18530b57cec5SDimitry Andric 
18540b57cec5SDimitry Andric void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
18550b57cec5SDimitry Andric   // The destructor used for destructing this as a base class; ignores
18560b57cec5SDimitry Andric   // virtual bases.
18570b57cec5SDimitry Andric   CGM.EmitGlobal(GlobalDecl(D, Dtor_Base));
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric   // The destructor used for destructing this as a most-derived class;
18600b57cec5SDimitry Andric   // call the base destructor and then destructs any virtual bases.
18610b57cec5SDimitry Andric   CGM.EmitGlobal(GlobalDecl(D, Dtor_Complete));
18620b57cec5SDimitry Andric 
18630b57cec5SDimitry Andric   // The destructor in a virtual table is always a 'deleting'
18640b57cec5SDimitry Andric   // destructor, which calls the complete destructor and then uses the
18650b57cec5SDimitry Andric   // appropriate operator delete.
18660b57cec5SDimitry Andric   if (D->isVirtual())
18670b57cec5SDimitry Andric     CGM.EmitGlobal(GlobalDecl(D, Dtor_Deleting));
18680b57cec5SDimitry Andric }
18690b57cec5SDimitry Andric 
18700b57cec5SDimitry Andric void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
18710b57cec5SDimitry Andric                                               QualType &ResTy,
18720b57cec5SDimitry Andric                                               FunctionArgList &Params) {
18730b57cec5SDimitry Andric   const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
18740b57cec5SDimitry Andric   assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
18750b57cec5SDimitry Andric 
18760b57cec5SDimitry Andric   // Check if we need a VTT parameter as well.
18770b57cec5SDimitry Andric   if (NeedsVTTParameter(CGF.CurGD)) {
18780b57cec5SDimitry Andric     ASTContext &Context = getContext();
18790b57cec5SDimitry Andric 
18800b57cec5SDimitry Andric     // FIXME: avoid the fake decl
188106c3fb27SDimitry Andric     LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
188206c3fb27SDimitry Andric     QualType Q = Context.getAddrSpaceQualType(Context.VoidPtrTy, AS);
188306c3fb27SDimitry Andric     QualType T = Context.getPointerType(Q);
18840b57cec5SDimitry Andric     auto *VTTDecl = ImplicitParamDecl::Create(
18850b57cec5SDimitry Andric         Context, /*DC=*/nullptr, MD->getLocation(), &Context.Idents.get("vtt"),
18865f757f3fSDimitry Andric         T, ImplicitParamKind::CXXVTT);
18870b57cec5SDimitry Andric     Params.insert(Params.begin() + 1, VTTDecl);
18880b57cec5SDimitry Andric     getStructorImplicitParamDecl(CGF) = VTTDecl;
18890b57cec5SDimitry Andric   }
18900b57cec5SDimitry Andric }
18910b57cec5SDimitry Andric 
18920b57cec5SDimitry Andric void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
18930b57cec5SDimitry Andric   // Naked functions have no prolog.
18940b57cec5SDimitry Andric   if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>())
18950b57cec5SDimitry Andric     return;
18960b57cec5SDimitry Andric 
18970b57cec5SDimitry Andric   /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
18980b57cec5SDimitry Andric   /// adjustments are required, because they are all handled by thunks.
18990b57cec5SDimitry Andric   setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
19000b57cec5SDimitry Andric 
19010b57cec5SDimitry Andric   /// Initialize the 'vtt' slot if needed.
19020b57cec5SDimitry Andric   if (getStructorImplicitParamDecl(CGF)) {
19030b57cec5SDimitry Andric     getStructorImplicitParamValue(CGF) = CGF.Builder.CreateLoad(
19040b57cec5SDimitry Andric         CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), "vtt");
19050b57cec5SDimitry Andric   }
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric   /// If this is a function that the ABI specifies returns 'this', initialize
19080b57cec5SDimitry Andric   /// the return slot to 'this' at the start of the function.
19090b57cec5SDimitry Andric   ///
19100b57cec5SDimitry Andric   /// Unlike the setting of return types, this is done within the ABI
19110b57cec5SDimitry Andric   /// implementation instead of by clients of CGCXXABI because:
19120b57cec5SDimitry Andric   /// 1) getThisValue is currently protected
19130b57cec5SDimitry Andric   /// 2) in theory, an ABI could implement 'this' returns some other way;
19140b57cec5SDimitry Andric   ///    HasThisReturn only specifies a contract, not the implementation
19150b57cec5SDimitry Andric   if (HasThisReturn(CGF.CurGD))
19160b57cec5SDimitry Andric     CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
19170b57cec5SDimitry Andric }
19180b57cec5SDimitry Andric 
19195ffd83dbSDimitry Andric CGCXXABI::AddedStructorArgs ItaniumCXXABI::getImplicitConstructorArgs(
19200b57cec5SDimitry Andric     CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type,
19215ffd83dbSDimitry Andric     bool ForVirtualBase, bool Delegating) {
19220b57cec5SDimitry Andric   if (!NeedsVTTParameter(GlobalDecl(D, Type)))
19230b57cec5SDimitry Andric     return AddedStructorArgs{};
19240b57cec5SDimitry Andric 
192506c3fb27SDimitry Andric   // Insert the implicit 'vtt' argument as the second argument. Make sure to
192606c3fb27SDimitry Andric   // correctly reflect its address space, which can differ from generic on
192706c3fb27SDimitry Andric   // some targets.
19280b57cec5SDimitry Andric   llvm::Value *VTT =
19290b57cec5SDimitry Andric       CGF.GetVTTParameter(GlobalDecl(D, Type), ForVirtualBase, Delegating);
193006c3fb27SDimitry Andric   LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
193106c3fb27SDimitry Andric   QualType Q = getContext().getAddrSpaceQualType(getContext().VoidPtrTy, AS);
193206c3fb27SDimitry Andric   QualType VTTTy = getContext().getPointerType(Q);
19335ffd83dbSDimitry Andric   return AddedStructorArgs::prefix({{VTT, VTTTy}});
19345ffd83dbSDimitry Andric }
19355ffd83dbSDimitry Andric 
19365ffd83dbSDimitry Andric llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(
19375ffd83dbSDimitry Andric     CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type,
19385ffd83dbSDimitry Andric     bool ForVirtualBase, bool Delegating) {
19395ffd83dbSDimitry Andric   GlobalDecl GD(DD, Type);
19405ffd83dbSDimitry Andric   return CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);
19410b57cec5SDimitry Andric }
19420b57cec5SDimitry Andric 
19430b57cec5SDimitry Andric void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
19440b57cec5SDimitry Andric                                        const CXXDestructorDecl *DD,
19450b57cec5SDimitry Andric                                        CXXDtorType Type, bool ForVirtualBase,
19460b57cec5SDimitry Andric                                        bool Delegating, Address This,
19470b57cec5SDimitry Andric                                        QualType ThisTy) {
19480b57cec5SDimitry Andric   GlobalDecl GD(DD, Type);
19495ffd83dbSDimitry Andric   llvm::Value *VTT =
19505ffd83dbSDimitry Andric       getCXXDestructorImplicitParam(CGF, DD, Type, ForVirtualBase, Delegating);
19510b57cec5SDimitry Andric   QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric   CGCallee Callee;
19540b57cec5SDimitry Andric   if (getContext().getLangOpts().AppleKext &&
19550b57cec5SDimitry Andric       Type != Dtor_Base && DD->isVirtual())
19560b57cec5SDimitry Andric     Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent());
19570b57cec5SDimitry Andric   else
19580b57cec5SDimitry Andric     Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD);
19590b57cec5SDimitry Andric 
19600fca6ea1SDimitry Andric   CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy),
19610fca6ea1SDimitry Andric                             ThisTy, VTT, VTTTy, nullptr);
19620fca6ea1SDimitry Andric }
19630fca6ea1SDimitry Andric 
19640fca6ea1SDimitry Andric // Check if any non-inline method has the specified attribute.
19650fca6ea1SDimitry Andric template <typename T>
19660fca6ea1SDimitry Andric static bool CXXRecordNonInlineHasAttr(const CXXRecordDecl *RD) {
19670fca6ea1SDimitry Andric   for (const auto *D : RD->noload_decls()) {
19680fca6ea1SDimitry Andric     if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
19690fca6ea1SDimitry Andric       if (FD->isInlined() || FD->doesThisDeclarationHaveABody() ||
19700fca6ea1SDimitry Andric           FD->isPureVirtual())
19710fca6ea1SDimitry Andric         continue;
19720fca6ea1SDimitry Andric       if (D->hasAttr<T>())
19730fca6ea1SDimitry Andric         return true;
19740fca6ea1SDimitry Andric     }
19750fca6ea1SDimitry Andric   }
19760fca6ea1SDimitry Andric 
19770fca6ea1SDimitry Andric   return false;
19780fca6ea1SDimitry Andric }
19790fca6ea1SDimitry Andric 
19800fca6ea1SDimitry Andric static void setVTableSelectiveDLLImportExport(CodeGenModule &CGM,
19810fca6ea1SDimitry Andric                                               llvm::GlobalVariable *VTable,
19820fca6ea1SDimitry Andric                                               const CXXRecordDecl *RD) {
19830fca6ea1SDimitry Andric   if (VTable->getDLLStorageClass() !=
19840fca6ea1SDimitry Andric           llvm::GlobalVariable::DefaultStorageClass ||
19850fca6ea1SDimitry Andric       RD->hasAttr<DLLImportAttr>() || RD->hasAttr<DLLExportAttr>())
19860fca6ea1SDimitry Andric     return;
19870fca6ea1SDimitry Andric 
19880fca6ea1SDimitry Andric   if (CGM.getVTables().isVTableExternal(RD)) {
19890fca6ea1SDimitry Andric     if (CXXRecordNonInlineHasAttr<DLLImportAttr>(RD))
19900fca6ea1SDimitry Andric       VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
19910fca6ea1SDimitry Andric   } else if (CXXRecordNonInlineHasAttr<DLLExportAttr>(RD))
19920fca6ea1SDimitry Andric     VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
19930b57cec5SDimitry Andric }
19940b57cec5SDimitry Andric 
19950b57cec5SDimitry Andric void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
19960b57cec5SDimitry Andric                                           const CXXRecordDecl *RD) {
19970b57cec5SDimitry Andric   llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits());
19980b57cec5SDimitry Andric   if (VTable->hasInitializer())
19990b57cec5SDimitry Andric     return;
20000b57cec5SDimitry Andric 
20010b57cec5SDimitry Andric   ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
20020b57cec5SDimitry Andric   const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
20030b57cec5SDimitry Andric   llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
20040b57cec5SDimitry Andric   llvm::Constant *RTTI =
20050b57cec5SDimitry Andric       CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
20060b57cec5SDimitry Andric 
20070b57cec5SDimitry Andric   // Create and set the initializer.
20085ffd83dbSDimitry Andric   ConstantInitBuilder builder(CGM);
20095ffd83dbSDimitry Andric   auto components = builder.beginStruct();
20105ffd83dbSDimitry Andric   CGVT.createVTableInitializer(components, VTLayout, RTTI,
20115ffd83dbSDimitry Andric                                llvm::GlobalValue::isLocalLinkage(Linkage));
20125ffd83dbSDimitry Andric   components.finishAndSetAsInitializer(VTable);
20130b57cec5SDimitry Andric 
20140b57cec5SDimitry Andric   // Set the correct linkage.
20150b57cec5SDimitry Andric   VTable->setLinkage(Linkage);
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric   if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
20180b57cec5SDimitry Andric     VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
20190b57cec5SDimitry Andric 
20200fca6ea1SDimitry Andric   if (CGM.getTarget().hasPS4DLLImportExport())
20210fca6ea1SDimitry Andric     setVTableSelectiveDLLImportExport(CGM, VTable, RD);
20220fca6ea1SDimitry Andric 
20230b57cec5SDimitry Andric   // Set the right visibility.
20240b57cec5SDimitry Andric   CGM.setGVProperties(VTable, RD);
20250b57cec5SDimitry Andric 
20260b57cec5SDimitry Andric   // If this is the magic class __cxxabiv1::__fundamental_type_info,
20270b57cec5SDimitry Andric   // we will emit the typeinfo for the fundamental types. This is the
20280b57cec5SDimitry Andric   // same behaviour as GCC.
20290b57cec5SDimitry Andric   const DeclContext *DC = RD->getDeclContext();
20300b57cec5SDimitry Andric   if (RD->getIdentifier() &&
20310b57cec5SDimitry Andric       RD->getIdentifier()->isStr("__fundamental_type_info") &&
20320b57cec5SDimitry Andric       isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
20330b57cec5SDimitry Andric       cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
20340b57cec5SDimitry Andric       DC->getParent()->isTranslationUnit())
20350b57cec5SDimitry Andric     EmitFundamentalRTTIDescriptors(RD);
20360b57cec5SDimitry Andric 
2037fe6060f1SDimitry Andric   // Always emit type metadata on non-available_externally definitions, and on
2038fe6060f1SDimitry Andric   // available_externally definitions if we are performing whole program
2039fe6060f1SDimitry Andric   // devirtualization. For WPD we need the type metadata on all vtable
2040fe6060f1SDimitry Andric   // definitions to ensure we associate derived classes with base classes
2041fe6060f1SDimitry Andric   // defined in headers but with a strong definition only in a shared library.
2042fe6060f1SDimitry Andric   if (!VTable->isDeclarationForLinker() ||
2043fe6060f1SDimitry Andric       CGM.getCodeGenOpts().WholeProgramVTables) {
2044a7dea167SDimitry Andric     CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
2045fe6060f1SDimitry Andric     // For available_externally definitions, add the vtable to
2046fe6060f1SDimitry Andric     // @llvm.compiler.used so that it isn't deleted before whole program
2047fe6060f1SDimitry Andric     // analysis.
2048fe6060f1SDimitry Andric     if (VTable->isDeclarationForLinker()) {
2049fe6060f1SDimitry Andric       assert(CGM.getCodeGenOpts().WholeProgramVTables);
2050fe6060f1SDimitry Andric       CGM.addCompilerUsedGlobal(VTable);
2051fe6060f1SDimitry Andric     }
2052fe6060f1SDimitry Andric   }
20535ffd83dbSDimitry Andric 
2054bdd1243dSDimitry Andric   if (VTContext.isRelativeLayout()) {
2055bdd1243dSDimitry Andric     CGVT.RemoveHwasanMetadata(VTable);
2056bdd1243dSDimitry Andric     if (!VTable->isDSOLocal())
20575ffd83dbSDimitry Andric       CGVT.GenerateRelativeVTableAlias(VTable, VTable->getName());
20580b57cec5SDimitry Andric   }
2059bdd1243dSDimitry Andric }
20600b57cec5SDimitry Andric 
20610b57cec5SDimitry Andric bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
20620b57cec5SDimitry Andric     CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
20630b57cec5SDimitry Andric   if (Vptr.NearestVBase == nullptr)
20640b57cec5SDimitry Andric     return false;
20650b57cec5SDimitry Andric   return NeedsVTTParameter(CGF.CurGD);
20660b57cec5SDimitry Andric }
20670b57cec5SDimitry Andric 
20680b57cec5SDimitry Andric llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
20690b57cec5SDimitry Andric     CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
20700b57cec5SDimitry Andric     const CXXRecordDecl *NearestVBase) {
20710b57cec5SDimitry Andric 
20720b57cec5SDimitry Andric   if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
20730b57cec5SDimitry Andric       NeedsVTTParameter(CGF.CurGD)) {
20740b57cec5SDimitry Andric     return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base,
20750b57cec5SDimitry Andric                                                   NearestVBase);
20760b57cec5SDimitry Andric   }
20770b57cec5SDimitry Andric   return getVTableAddressPoint(Base, VTableClass);
20780b57cec5SDimitry Andric }
20790b57cec5SDimitry Andric 
20800b57cec5SDimitry Andric llvm::Constant *
20810b57cec5SDimitry Andric ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
20820b57cec5SDimitry Andric                                      const CXXRecordDecl *VTableClass) {
20830b57cec5SDimitry Andric   llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());
20840b57cec5SDimitry Andric 
20850b57cec5SDimitry Andric   // Find the appropriate vtable within the vtable group, and the address point
20860b57cec5SDimitry Andric   // within that vtable.
20870fca6ea1SDimitry Andric   const VTableLayout &Layout =
20880fca6ea1SDimitry Andric       CGM.getItaniumVTableContext().getVTableLayout(VTableClass);
20890b57cec5SDimitry Andric   VTableLayout::AddressPointLocation AddressPoint =
20900fca6ea1SDimitry Andric       Layout.getAddressPoint(Base);
20910b57cec5SDimitry Andric   llvm::Value *Indices[] = {
20920b57cec5SDimitry Andric     llvm::ConstantInt::get(CGM.Int32Ty, 0),
20930b57cec5SDimitry Andric     llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
20940b57cec5SDimitry Andric     llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
20950b57cec5SDimitry Andric   };
20960b57cec5SDimitry Andric 
20970fca6ea1SDimitry Andric   // Add inrange attribute to indicate that only the VTableIndex can be
20980fca6ea1SDimitry Andric   // accessed.
20990fca6ea1SDimitry Andric   unsigned ComponentSize =
21000fca6ea1SDimitry Andric       CGM.getDataLayout().getTypeAllocSize(CGM.getVTableComponentType());
21010fca6ea1SDimitry Andric   unsigned VTableSize =
21020fca6ea1SDimitry Andric       ComponentSize * Layout.getVTableSize(AddressPoint.VTableIndex);
21030fca6ea1SDimitry Andric   unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
21040fca6ea1SDimitry Andric   llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true),
21050fca6ea1SDimitry Andric                               llvm::APInt(32, VTableSize - Offset, true));
21060fca6ea1SDimitry Andric   return llvm::ConstantExpr::getGetElementPtr(
21070fca6ea1SDimitry Andric       VTable->getValueType(), VTable, Indices, /*InBounds=*/true, InRange);
2108fe6060f1SDimitry Andric }
2109fe6060f1SDimitry Andric 
21100b57cec5SDimitry Andric llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
21110b57cec5SDimitry Andric     CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
21120b57cec5SDimitry Andric     const CXXRecordDecl *NearestVBase) {
21130b57cec5SDimitry Andric   assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
21140b57cec5SDimitry Andric          NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT");
21150b57cec5SDimitry Andric 
21160b57cec5SDimitry Andric   // Get the secondary vpointer index.
21170b57cec5SDimitry Andric   uint64_t VirtualPointerIndex =
21180b57cec5SDimitry Andric       CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
21190b57cec5SDimitry Andric 
21200b57cec5SDimitry Andric   /// Load the VTT.
21210b57cec5SDimitry Andric   llvm::Value *VTT = CGF.LoadCXXVTT();
21220b57cec5SDimitry Andric   if (VirtualPointerIndex)
212306c3fb27SDimitry Andric     VTT = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.GlobalsVoidPtrTy, VTT,
212406c3fb27SDimitry Andric                                                  VirtualPointerIndex);
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric   // And load the address point from the VTT.
21270fca6ea1SDimitry Andric   llvm::Value *AP =
21280fca6ea1SDimitry Andric       CGF.Builder.CreateAlignedLoad(CGF.GlobalsVoidPtrTy, VTT,
2129fe6060f1SDimitry Andric                                     CGF.getPointerAlign());
21300fca6ea1SDimitry Andric 
21310fca6ea1SDimitry Andric   if (auto &Schema = CGF.CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers) {
21320fca6ea1SDimitry Andric     CGPointerAuthInfo PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTT,
21330fca6ea1SDimitry Andric                                                             GlobalDecl(),
21340fca6ea1SDimitry Andric                                                             QualType());
21350fca6ea1SDimitry Andric     AP = CGF.EmitPointerAuthAuth(PointerAuth, AP);
21360b57cec5SDimitry Andric   }
21370b57cec5SDimitry Andric 
21380fca6ea1SDimitry Andric   return AP;
21390b57cec5SDimitry Andric }
21400b57cec5SDimitry Andric 
21410b57cec5SDimitry Andric llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
21420b57cec5SDimitry Andric                                                      CharUnits VPtrOffset) {
21430b57cec5SDimitry Andric   assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
21440b57cec5SDimitry Andric 
21450b57cec5SDimitry Andric   llvm::GlobalVariable *&VTable = VTables[RD];
21460b57cec5SDimitry Andric   if (VTable)
21470b57cec5SDimitry Andric     return VTable;
21480b57cec5SDimitry Andric 
21490b57cec5SDimitry Andric   // Queue up this vtable for possible deferred emission.
21500b57cec5SDimitry Andric   CGM.addDeferredVTable(RD);
21510b57cec5SDimitry Andric 
21520b57cec5SDimitry Andric   SmallString<256> Name;
21530b57cec5SDimitry Andric   llvm::raw_svector_ostream Out(Name);
21540b57cec5SDimitry Andric   getMangleContext().mangleCXXVTable(RD, Out);
21550b57cec5SDimitry Andric 
21560b57cec5SDimitry Andric   const VTableLayout &VTLayout =
21570b57cec5SDimitry Andric       CGM.getItaniumVTableContext().getVTableLayout(RD);
21580b57cec5SDimitry Andric   llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
21590b57cec5SDimitry Andric 
216006c3fb27SDimitry Andric   // Use pointer to global alignment for the vtable. Otherwise we would align
216106c3fb27SDimitry Andric   // them based on the size of the initializer which doesn't make sense as only
216206c3fb27SDimitry Andric   // single values are read.
216306c3fb27SDimitry Andric   LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
21645ffd83dbSDimitry Andric   unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()
21655ffd83dbSDimitry Andric                         ? 32
216606c3fb27SDimitry Andric                         : CGM.getTarget().getPointerAlign(AS);
21670b57cec5SDimitry Andric 
21680b57cec5SDimitry Andric   VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
21690b57cec5SDimitry Andric       Name, VTableType, llvm::GlobalValue::ExternalLinkage,
2170bdd1243dSDimitry Andric       getContext().toCharUnitsFromBits(PAlign).getAsAlign());
21710b57cec5SDimitry Andric   VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
21720b57cec5SDimitry Andric 
21730fca6ea1SDimitry Andric   if (CGM.getTarget().hasPS4DLLImportExport())
21740fca6ea1SDimitry Andric     setVTableSelectiveDLLImportExport(CGM, VTable, RD);
21750b57cec5SDimitry Andric 
21760fca6ea1SDimitry Andric   CGM.setGVProperties(VTable, RD);
21770b57cec5SDimitry Andric   return VTable;
21780b57cec5SDimitry Andric }
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
21810b57cec5SDimitry Andric                                                   GlobalDecl GD,
21820b57cec5SDimitry Andric                                                   Address This,
21830b57cec5SDimitry Andric                                                   llvm::Type *Ty,
21840b57cec5SDimitry Andric                                                   SourceLocation Loc) {
218506c3fb27SDimitry Andric   llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy;
21860b57cec5SDimitry Andric   auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
218706c3fb27SDimitry Andric   llvm::Value *VTable = CGF.GetVTablePtr(This, PtrTy, MethodDecl->getParent());
21880b57cec5SDimitry Andric 
21890b57cec5SDimitry Andric   uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
21900fca6ea1SDimitry Andric   llvm::Value *VFunc, *VTableSlotPtr = nullptr;
21910fca6ea1SDimitry Andric   auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers;
21920fca6ea1SDimitry Andric   if (!Schema && CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) {
21930b57cec5SDimitry Andric     VFunc = CGF.EmitVTableTypeCheckedLoad(
219406c3fb27SDimitry Andric         MethodDecl->getParent(), VTable, PtrTy,
2195bdd1243dSDimitry Andric         VTableIndex *
2196bdd1243dSDimitry Andric             CGM.getContext().getTargetInfo().getPointerWidth(LangAS::Default) /
2197bdd1243dSDimitry Andric             8);
21980b57cec5SDimitry Andric   } else {
21990b57cec5SDimitry Andric     CGF.EmitTypeMetadataCodeForVCall(MethodDecl->getParent(), VTable, Loc);
22000b57cec5SDimitry Andric 
22015ffd83dbSDimitry Andric     llvm::Value *VFuncLoad;
22025ffd83dbSDimitry Andric     if (CGM.getItaniumVTableContext().isRelativeLayout()) {
220306c3fb27SDimitry Andric       VFuncLoad = CGF.Builder.CreateCall(
22045ffd83dbSDimitry Andric           CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
22055ffd83dbSDimitry Andric           {VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)});
22065ffd83dbSDimitry Andric     } else {
22070fca6ea1SDimitry Andric       VTableSlotPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
220806c3fb27SDimitry Andric           PtrTy, VTable, VTableIndex, "vfn");
220906c3fb27SDimitry Andric       VFuncLoad = CGF.Builder.CreateAlignedLoad(PtrTy, VTableSlotPtr,
2210fe6060f1SDimitry Andric                                                 CGF.getPointerAlign());
22115ffd83dbSDimitry Andric     }
22120b57cec5SDimitry Andric 
22130b57cec5SDimitry Andric     // Add !invariant.load md to virtual function load to indicate that
22140b57cec5SDimitry Andric     // function didn't change inside vtable.
22150b57cec5SDimitry Andric     // It's safe to add it without -fstrict-vtable-pointers, but it would not
22160b57cec5SDimitry Andric     // help in devirtualization because it will only matter if we will have 2
22170b57cec5SDimitry Andric     // the same virtual function loads from the same vtable load, which won't
22180b57cec5SDimitry Andric     // happen without enabled devirtualization with -fstrict-vtable-pointers.
22190b57cec5SDimitry Andric     if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
22205ffd83dbSDimitry Andric         CGM.getCodeGenOpts().StrictVTablePointers) {
22215ffd83dbSDimitry Andric       if (auto *VFuncLoadInstr = dyn_cast<llvm::Instruction>(VFuncLoad)) {
22225ffd83dbSDimitry Andric         VFuncLoadInstr->setMetadata(
22230b57cec5SDimitry Andric             llvm::LLVMContext::MD_invariant_load,
22240b57cec5SDimitry Andric             llvm::MDNode::get(CGM.getLLVMContext(),
22250b57cec5SDimitry Andric                               llvm::ArrayRef<llvm::Metadata *>()));
22265ffd83dbSDimitry Andric       }
22275ffd83dbSDimitry Andric     }
22280b57cec5SDimitry Andric     VFunc = VFuncLoad;
22290b57cec5SDimitry Andric   }
22300b57cec5SDimitry Andric 
22310fca6ea1SDimitry Andric   CGPointerAuthInfo PointerAuth;
22320fca6ea1SDimitry Andric   if (Schema) {
22330fca6ea1SDimitry Andric     assert(VTableSlotPtr && "virtual function pointer not set");
22340fca6ea1SDimitry Andric     GD = CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl());
22350fca6ea1SDimitry Andric     PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTableSlotPtr, GD, QualType());
22360fca6ea1SDimitry Andric   }
22370fca6ea1SDimitry Andric   CGCallee Callee(GD, VFunc, PointerAuth);
22380b57cec5SDimitry Andric   return Callee;
22390b57cec5SDimitry Andric }
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
22420b57cec5SDimitry Andric     CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
22430b57cec5SDimitry Andric     Address This, DeleteOrMemberCallExpr E) {
22440b57cec5SDimitry Andric   auto *CE = E.dyn_cast<const CXXMemberCallExpr *>();
22450b57cec5SDimitry Andric   auto *D = E.dyn_cast<const CXXDeleteExpr *>();
22460b57cec5SDimitry Andric   assert((CE != nullptr) ^ (D != nullptr));
22470b57cec5SDimitry Andric   assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
22480b57cec5SDimitry Andric   assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
22490b57cec5SDimitry Andric 
22500b57cec5SDimitry Andric   GlobalDecl GD(Dtor, DtorType);
22510b57cec5SDimitry Andric   const CGFunctionInfo *FInfo =
22520b57cec5SDimitry Andric       &CGM.getTypes().arrangeCXXStructorDeclaration(GD);
22530b57cec5SDimitry Andric   llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
22540b57cec5SDimitry Andric   CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty);
22550b57cec5SDimitry Andric 
22560b57cec5SDimitry Andric   QualType ThisTy;
22570b57cec5SDimitry Andric   if (CE) {
22580b57cec5SDimitry Andric     ThisTy = CE->getObjectType();
22590b57cec5SDimitry Andric   } else {
22600b57cec5SDimitry Andric     ThisTy = D->getDestroyedType();
22610b57cec5SDimitry Andric   }
22620b57cec5SDimitry Andric 
22630fca6ea1SDimitry Andric   CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy,
22640fca6ea1SDimitry Andric                             nullptr, QualType(), nullptr);
22650b57cec5SDimitry Andric   return nullptr;
22660b57cec5SDimitry Andric }
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
22690b57cec5SDimitry Andric   CodeGenVTables &VTables = CGM.getVTables();
22700b57cec5SDimitry Andric   llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD);
22710b57cec5SDimitry Andric   VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
22720b57cec5SDimitry Andric }
22730b57cec5SDimitry Andric 
22740b57cec5SDimitry Andric bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
22750b57cec5SDimitry Andric     const CXXRecordDecl *RD) const {
22760b57cec5SDimitry Andric   // We don't emit available_externally vtables if we are in -fapple-kext mode
22770b57cec5SDimitry Andric   // because kext mode does not permit devirtualization.
22780b57cec5SDimitry Andric   if (CGM.getLangOpts().AppleKext)
22790b57cec5SDimitry Andric     return false;
22800b57cec5SDimitry Andric 
22810b57cec5SDimitry Andric   // If the vtable is hidden then it is not safe to emit an available_externally
22820b57cec5SDimitry Andric   // copy of vtable.
22830b57cec5SDimitry Andric   if (isVTableHidden(RD))
22840b57cec5SDimitry Andric     return false;
22850b57cec5SDimitry Andric 
22860b57cec5SDimitry Andric   if (CGM.getCodeGenOpts().ForceEmitVTables)
22870b57cec5SDimitry Andric     return true;
22880b57cec5SDimitry Andric 
22890b57cec5SDimitry Andric   // If we don't have any not emitted inline virtual function then we are safe
22900b57cec5SDimitry Andric   // to emit an available_externally copy of vtable.
22910b57cec5SDimitry Andric   // FIXME we can still emit a copy of the vtable if we
22920b57cec5SDimitry Andric   // can emit definition of the inline functions.
22930b57cec5SDimitry Andric   if (hasAnyUnusedVirtualInlineFunction(RD))
22940b57cec5SDimitry Andric     return false;
22950b57cec5SDimitry Andric 
22960b57cec5SDimitry Andric   // For a class with virtual bases, we must also be able to speculatively
22970b57cec5SDimitry Andric   // emit the VTT, because CodeGen doesn't have separate notions of "can emit
22980b57cec5SDimitry Andric   // the vtable" and "can emit the VTT". For a base subobject, this means we
22990b57cec5SDimitry Andric   // need to be able to emit non-virtual base vtables.
23000b57cec5SDimitry Andric   if (RD->getNumVBases()) {
23010b57cec5SDimitry Andric     for (const auto &B : RD->bases()) {
23020b57cec5SDimitry Andric       auto *BRD = B.getType()->getAsCXXRecordDecl();
23030b57cec5SDimitry Andric       assert(BRD && "no class for base specifier");
23040b57cec5SDimitry Andric       if (B.isVirtual() || !BRD->isDynamicClass())
23050b57cec5SDimitry Andric         continue;
23060b57cec5SDimitry Andric       if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
23070b57cec5SDimitry Andric         return false;
23080b57cec5SDimitry Andric     }
23090b57cec5SDimitry Andric   }
23100b57cec5SDimitry Andric 
23110b57cec5SDimitry Andric   return true;
23120b57cec5SDimitry Andric }
23130b57cec5SDimitry Andric 
23140b57cec5SDimitry Andric bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
23150b57cec5SDimitry Andric   if (!canSpeculativelyEmitVTableAsBaseClass(RD))
23160b57cec5SDimitry Andric     return false;
23170b57cec5SDimitry Andric 
2318*62987288SDimitry Andric   if (RD->shouldEmitInExternalSource())
2319*62987288SDimitry Andric     return false;
2320*62987288SDimitry Andric 
23210b57cec5SDimitry Andric   // For a complete-object vtable (or more specifically, for the VTT), we need
23220b57cec5SDimitry Andric   // to be able to speculatively emit the vtables of all dynamic virtual bases.
23230b57cec5SDimitry Andric   for (const auto &B : RD->vbases()) {
23240b57cec5SDimitry Andric     auto *BRD = B.getType()->getAsCXXRecordDecl();
23250b57cec5SDimitry Andric     assert(BRD && "no class for base specifier");
23260b57cec5SDimitry Andric     if (!BRD->isDynamicClass())
23270b57cec5SDimitry Andric       continue;
23280b57cec5SDimitry Andric     if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
23290b57cec5SDimitry Andric       return false;
23300b57cec5SDimitry Andric   }
23310b57cec5SDimitry Andric 
23320b57cec5SDimitry Andric   return true;
23330b57cec5SDimitry Andric }
23340b57cec5SDimitry Andric static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
23350b57cec5SDimitry Andric                                           Address InitialPtr,
23360fca6ea1SDimitry Andric                                           const CXXRecordDecl *UnadjustedClass,
23370b57cec5SDimitry Andric                                           int64_t NonVirtualAdjustment,
23380b57cec5SDimitry Andric                                           int64_t VirtualAdjustment,
23390b57cec5SDimitry Andric                                           bool IsReturnAdjustment) {
23400b57cec5SDimitry Andric   if (!NonVirtualAdjustment && !VirtualAdjustment)
23410fca6ea1SDimitry Andric     return InitialPtr.emitRawPointer(CGF);
23420b57cec5SDimitry Andric 
234306c3fb27SDimitry Andric   Address V = InitialPtr.withElementType(CGF.Int8Ty);
23440b57cec5SDimitry Andric 
23450b57cec5SDimitry Andric   // In a base-to-derived cast, the non-virtual adjustment is applied first.
23460b57cec5SDimitry Andric   if (NonVirtualAdjustment && !IsReturnAdjustment) {
23470b57cec5SDimitry Andric     V = CGF.Builder.CreateConstInBoundsByteGEP(V,
23480b57cec5SDimitry Andric                               CharUnits::fromQuantity(NonVirtualAdjustment));
23490b57cec5SDimitry Andric   }
23500b57cec5SDimitry Andric 
23510b57cec5SDimitry Andric   // Perform the virtual adjustment if we have one.
23520b57cec5SDimitry Andric   llvm::Value *ResultPtr;
23530b57cec5SDimitry Andric   if (VirtualAdjustment) {
23540fca6ea1SDimitry Andric     llvm::Value *VTablePtr =
23550fca6ea1SDimitry Andric         CGF.GetVTablePtr(V, CGF.Int8PtrTy, UnadjustedClass);
23560b57cec5SDimitry Andric 
23575ffd83dbSDimitry Andric     llvm::Value *Offset;
2358fe6060f1SDimitry Andric     llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
2359fe6060f1SDimitry Andric         CGF.Int8Ty, VTablePtr, VirtualAdjustment);
23605ffd83dbSDimitry Andric     if (CGF.CGM.getItaniumVTableContext().isRelativeLayout()) {
23615ffd83dbSDimitry Andric       // Load the adjustment offset from the vtable as a 32-bit int.
23625ffd83dbSDimitry Andric       Offset =
2363fe6060f1SDimitry Andric           CGF.Builder.CreateAlignedLoad(CGF.Int32Ty, OffsetPtr,
2364fe6060f1SDimitry Andric                                         CharUnits::fromQuantity(4));
23655ffd83dbSDimitry Andric     } else {
23665ffd83dbSDimitry Andric       llvm::Type *PtrDiffTy =
23675ffd83dbSDimitry Andric           CGF.ConvertType(CGF.getContext().getPointerDiffType());
23680b57cec5SDimitry Andric 
23690b57cec5SDimitry Andric       // Load the adjustment offset from the vtable.
2370fe6060f1SDimitry Andric       Offset = CGF.Builder.CreateAlignedLoad(PtrDiffTy, OffsetPtr,
2371fe6060f1SDimitry Andric                                              CGF.getPointerAlign());
23725ffd83dbSDimitry Andric     }
23730b57cec5SDimitry Andric     // Adjust our pointer.
23740fca6ea1SDimitry Andric     ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getElementType(),
23750fca6ea1SDimitry Andric                                               V.emitRawPointer(CGF), Offset);
23760b57cec5SDimitry Andric   } else {
23770fca6ea1SDimitry Andric     ResultPtr = V.emitRawPointer(CGF);
23780b57cec5SDimitry Andric   }
23790b57cec5SDimitry Andric 
23800b57cec5SDimitry Andric   // In a derived-to-base conversion, the non-virtual adjustment is
23810b57cec5SDimitry Andric   // applied second.
23820b57cec5SDimitry Andric   if (NonVirtualAdjustment && IsReturnAdjustment) {
2383fe6060f1SDimitry Andric     ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.Int8Ty, ResultPtr,
23840b57cec5SDimitry Andric                                                        NonVirtualAdjustment);
23850b57cec5SDimitry Andric   }
23860b57cec5SDimitry Andric 
23875f757f3fSDimitry Andric   return ResultPtr;
23880b57cec5SDimitry Andric }
23890b57cec5SDimitry Andric 
23900fca6ea1SDimitry Andric llvm::Value *
23910fca6ea1SDimitry Andric ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF, Address This,
23920fca6ea1SDimitry Andric                                      const CXXRecordDecl *UnadjustedClass,
23930fca6ea1SDimitry Andric                                      const ThunkInfo &TI) {
23940fca6ea1SDimitry Andric   return performTypeAdjustment(CGF, This, UnadjustedClass, TI.This.NonVirtual,
23950fca6ea1SDimitry Andric                                TI.This.Virtual.Itanium.VCallOffsetOffset,
23960b57cec5SDimitry Andric                                /*IsReturnAdjustment=*/false);
23970b57cec5SDimitry Andric }
23980b57cec5SDimitry Andric 
23990b57cec5SDimitry Andric llvm::Value *
24000b57cec5SDimitry Andric ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
24010fca6ea1SDimitry Andric                                        const CXXRecordDecl *UnadjustedClass,
24020b57cec5SDimitry Andric                                        const ReturnAdjustment &RA) {
24030fca6ea1SDimitry Andric   return performTypeAdjustment(CGF, Ret, UnadjustedClass, RA.NonVirtual,
24040b57cec5SDimitry Andric                                RA.Virtual.Itanium.VBaseOffsetOffset,
24050b57cec5SDimitry Andric                                /*IsReturnAdjustment=*/true);
24060b57cec5SDimitry Andric }
24070b57cec5SDimitry Andric 
24080b57cec5SDimitry Andric void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
24090b57cec5SDimitry Andric                                     RValue RV, QualType ResultType) {
24100b57cec5SDimitry Andric   if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
24110b57cec5SDimitry Andric     return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
24120b57cec5SDimitry Andric 
24130b57cec5SDimitry Andric   // Destructor thunks in the ARM ABI have indeterminate results.
24140b57cec5SDimitry Andric   llvm::Type *T = CGF.ReturnValue.getElementType();
24150b57cec5SDimitry Andric   RValue Undef = RValue::get(llvm::UndefValue::get(T));
24160b57cec5SDimitry Andric   return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
24170b57cec5SDimitry Andric }
24180b57cec5SDimitry Andric 
24190b57cec5SDimitry Andric /************************** Array allocation cookies **************************/
24200b57cec5SDimitry Andric 
24210b57cec5SDimitry Andric CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
24220b57cec5SDimitry Andric   // The array cookie is a size_t; pad that up to the element alignment.
24230b57cec5SDimitry Andric   // The cookie is actually right-justified in that space.
24240b57cec5SDimitry Andric   return std::max(CharUnits::fromQuantity(CGM.SizeSizeInBytes),
2425e8d8bef9SDimitry Andric                   CGM.getContext().getPreferredTypeAlignInChars(elementType));
24260b57cec5SDimitry Andric }
24270b57cec5SDimitry Andric 
24280b57cec5SDimitry Andric Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
24290b57cec5SDimitry Andric                                              Address NewPtr,
24300b57cec5SDimitry Andric                                              llvm::Value *NumElements,
24310b57cec5SDimitry Andric                                              const CXXNewExpr *expr,
24320b57cec5SDimitry Andric                                              QualType ElementType) {
24330b57cec5SDimitry Andric   assert(requiresArrayCookie(expr));
24340b57cec5SDimitry Andric 
24350b57cec5SDimitry Andric   unsigned AS = NewPtr.getAddressSpace();
24360b57cec5SDimitry Andric 
24370b57cec5SDimitry Andric   ASTContext &Ctx = getContext();
24380b57cec5SDimitry Andric   CharUnits SizeSize = CGF.getSizeSize();
24390b57cec5SDimitry Andric 
24400b57cec5SDimitry Andric   // The size of the cookie.
24410b57cec5SDimitry Andric   CharUnits CookieSize =
2442e8d8bef9SDimitry Andric       std::max(SizeSize, Ctx.getPreferredTypeAlignInChars(ElementType));
24430b57cec5SDimitry Andric   assert(CookieSize == getArrayCookieSizeImpl(ElementType));
24440b57cec5SDimitry Andric 
24450b57cec5SDimitry Andric   // Compute an offset to the cookie.
24460b57cec5SDimitry Andric   Address CookiePtr = NewPtr;
24470b57cec5SDimitry Andric   CharUnits CookieOffset = CookieSize - SizeSize;
24480b57cec5SDimitry Andric   if (!CookieOffset.isZero())
24490b57cec5SDimitry Andric     CookiePtr = CGF.Builder.CreateConstInBoundsByteGEP(CookiePtr, CookieOffset);
24500b57cec5SDimitry Andric 
24510b57cec5SDimitry Andric   // Write the number of elements into the appropriate slot.
245206c3fb27SDimitry Andric   Address NumElementsPtr = CookiePtr.withElementType(CGF.SizeTy);
24530b57cec5SDimitry Andric   llvm::Instruction *SI = CGF.Builder.CreateStore(NumElements, NumElementsPtr);
24540b57cec5SDimitry Andric 
24550b57cec5SDimitry Andric   // Handle the array cookie specially in ASan.
24560b57cec5SDimitry Andric   if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
24570b57cec5SDimitry Andric       (expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||
24580b57cec5SDimitry Andric        CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {
24590b57cec5SDimitry Andric     // The store to the CookiePtr does not need to be instrumented.
246006c3fb27SDimitry Andric     SI->setNoSanitizeMetadata();
24610b57cec5SDimitry Andric     llvm::FunctionType *FTy =
24620b57cec5SDimitry Andric         llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false);
24630b57cec5SDimitry Andric     llvm::FunctionCallee F =
24640b57cec5SDimitry Andric         CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie");
24650fca6ea1SDimitry Andric     CGF.Builder.CreateCall(F, NumElementsPtr.emitRawPointer(CGF));
24660b57cec5SDimitry Andric   }
24670b57cec5SDimitry Andric 
24680b57cec5SDimitry Andric   // Finally, compute a pointer to the actual data buffer by skipping
24690b57cec5SDimitry Andric   // over the cookie completely.
24700b57cec5SDimitry Andric   return CGF.Builder.CreateConstInBoundsByteGEP(NewPtr, CookieSize);
24710b57cec5SDimitry Andric }
24720b57cec5SDimitry Andric 
24730b57cec5SDimitry Andric llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
24740b57cec5SDimitry Andric                                                 Address allocPtr,
24750b57cec5SDimitry Andric                                                 CharUnits cookieSize) {
24760b57cec5SDimitry Andric   // The element size is right-justified in the cookie.
24770b57cec5SDimitry Andric   Address numElementsPtr = allocPtr;
24780b57cec5SDimitry Andric   CharUnits numElementsOffset = cookieSize - CGF.getSizeSize();
24790b57cec5SDimitry Andric   if (!numElementsOffset.isZero())
24800b57cec5SDimitry Andric     numElementsPtr =
24810b57cec5SDimitry Andric       CGF.Builder.CreateConstInBoundsByteGEP(numElementsPtr, numElementsOffset);
24820b57cec5SDimitry Andric 
24830b57cec5SDimitry Andric   unsigned AS = allocPtr.getAddressSpace();
248406c3fb27SDimitry Andric   numElementsPtr = numElementsPtr.withElementType(CGF.SizeTy);
24850b57cec5SDimitry Andric   if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0)
24860b57cec5SDimitry Andric     return CGF.Builder.CreateLoad(numElementsPtr);
24870b57cec5SDimitry Andric   // In asan mode emit a function call instead of a regular load and let the
24880b57cec5SDimitry Andric   // run-time deal with it: if the shadow is properly poisoned return the
24890b57cec5SDimitry Andric   // cookie, otherwise return 0 to avoid an infinite loop calling DTORs.
24900b57cec5SDimitry Andric   // We can't simply ignore this load using nosanitize metadata because
24910b57cec5SDimitry Andric   // the metadata may be lost.
24925f757f3fSDimitry Andric   llvm::FunctionType *FTy =
24935f757f3fSDimitry Andric       llvm::FunctionType::get(CGF.SizeTy, CGF.UnqualPtrTy, false);
24940b57cec5SDimitry Andric   llvm::FunctionCallee F =
24950b57cec5SDimitry Andric       CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie");
24960fca6ea1SDimitry Andric   return CGF.Builder.CreateCall(F, numElementsPtr.emitRawPointer(CGF));
24970b57cec5SDimitry Andric }
24980b57cec5SDimitry Andric 
24990b57cec5SDimitry Andric CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
25000b57cec5SDimitry Andric   // ARM says that the cookie is always:
25010b57cec5SDimitry Andric   //   struct array_cookie {
25020b57cec5SDimitry Andric   //     std::size_t element_size; // element_size != 0
25030b57cec5SDimitry Andric   //     std::size_t element_count;
25040b57cec5SDimitry Andric   //   };
25050b57cec5SDimitry Andric   // But the base ABI doesn't give anything an alignment greater than
25060b57cec5SDimitry Andric   // 8, so we can dismiss this as typical ABI-author blindness to
25070b57cec5SDimitry Andric   // actual language complexity and round up to the element alignment.
25080b57cec5SDimitry Andric   return std::max(CharUnits::fromQuantity(2 * CGM.SizeSizeInBytes),
25090b57cec5SDimitry Andric                   CGM.getContext().getTypeAlignInChars(elementType));
25100b57cec5SDimitry Andric }
25110b57cec5SDimitry Andric 
25120b57cec5SDimitry Andric Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
25130b57cec5SDimitry Andric                                          Address newPtr,
25140b57cec5SDimitry Andric                                          llvm::Value *numElements,
25150b57cec5SDimitry Andric                                          const CXXNewExpr *expr,
25160b57cec5SDimitry Andric                                          QualType elementType) {
25170b57cec5SDimitry Andric   assert(requiresArrayCookie(expr));
25180b57cec5SDimitry Andric 
25190b57cec5SDimitry Andric   // The cookie is always at the start of the buffer.
25200b57cec5SDimitry Andric   Address cookie = newPtr;
25210b57cec5SDimitry Andric 
25220b57cec5SDimitry Andric   // The first element is the element size.
252306c3fb27SDimitry Andric   cookie = cookie.withElementType(CGF.SizeTy);
25240b57cec5SDimitry Andric   llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,
25250b57cec5SDimitry Andric                  getContext().getTypeSizeInChars(elementType).getQuantity());
25260b57cec5SDimitry Andric   CGF.Builder.CreateStore(elementSize, cookie);
25270b57cec5SDimitry Andric 
25280b57cec5SDimitry Andric   // The second element is the element count.
25290b57cec5SDimitry Andric   cookie = CGF.Builder.CreateConstInBoundsGEP(cookie, 1);
25300b57cec5SDimitry Andric   CGF.Builder.CreateStore(numElements, cookie);
25310b57cec5SDimitry Andric 
25320b57cec5SDimitry Andric   // Finally, compute a pointer to the actual data buffer by skipping
25330b57cec5SDimitry Andric   // over the cookie completely.
25340b57cec5SDimitry Andric   CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
25350b57cec5SDimitry Andric   return CGF.Builder.CreateConstInBoundsByteGEP(newPtr, cookieSize);
25360b57cec5SDimitry Andric }
25370b57cec5SDimitry Andric 
25380b57cec5SDimitry Andric llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
25390b57cec5SDimitry Andric                                             Address allocPtr,
25400b57cec5SDimitry Andric                                             CharUnits cookieSize) {
25410b57cec5SDimitry Andric   // The number of elements is at offset sizeof(size_t) relative to
25420b57cec5SDimitry Andric   // the allocated pointer.
25430b57cec5SDimitry Andric   Address numElementsPtr
25440b57cec5SDimitry Andric     = CGF.Builder.CreateConstInBoundsByteGEP(allocPtr, CGF.getSizeSize());
25450b57cec5SDimitry Andric 
254606c3fb27SDimitry Andric   numElementsPtr = numElementsPtr.withElementType(CGF.SizeTy);
25470b57cec5SDimitry Andric   return CGF.Builder.CreateLoad(numElementsPtr);
25480b57cec5SDimitry Andric }
25490b57cec5SDimitry Andric 
25500b57cec5SDimitry Andric /*********************** Static local initialization **************************/
25510b57cec5SDimitry Andric 
25520b57cec5SDimitry Andric static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM,
25530b57cec5SDimitry Andric                                               llvm::PointerType *GuardPtrTy) {
25540b57cec5SDimitry Andric   // int __cxa_guard_acquire(__guard *guard_object);
25550b57cec5SDimitry Andric   llvm::FunctionType *FTy =
25560b57cec5SDimitry Andric     llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy),
25570b57cec5SDimitry Andric                             GuardPtrTy, /*isVarArg=*/false);
25580b57cec5SDimitry Andric   return CGM.CreateRuntimeFunction(
25590b57cec5SDimitry Andric       FTy, "__cxa_guard_acquire",
25600b57cec5SDimitry Andric       llvm::AttributeList::get(CGM.getLLVMContext(),
25610b57cec5SDimitry Andric                                llvm::AttributeList::FunctionIndex,
25620b57cec5SDimitry Andric                                llvm::Attribute::NoUnwind));
25630b57cec5SDimitry Andric }
25640b57cec5SDimitry Andric 
25650b57cec5SDimitry Andric static llvm::FunctionCallee getGuardReleaseFn(CodeGenModule &CGM,
25660b57cec5SDimitry Andric                                               llvm::PointerType *GuardPtrTy) {
25670b57cec5SDimitry Andric   // void __cxa_guard_release(__guard *guard_object);
25680b57cec5SDimitry Andric   llvm::FunctionType *FTy =
25690b57cec5SDimitry Andric     llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
25700b57cec5SDimitry Andric   return CGM.CreateRuntimeFunction(
25710b57cec5SDimitry Andric       FTy, "__cxa_guard_release",
25720b57cec5SDimitry Andric       llvm::AttributeList::get(CGM.getLLVMContext(),
25730b57cec5SDimitry Andric                                llvm::AttributeList::FunctionIndex,
25740b57cec5SDimitry Andric                                llvm::Attribute::NoUnwind));
25750b57cec5SDimitry Andric }
25760b57cec5SDimitry Andric 
25770b57cec5SDimitry Andric static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM,
25780b57cec5SDimitry Andric                                             llvm::PointerType *GuardPtrTy) {
25790b57cec5SDimitry Andric   // void __cxa_guard_abort(__guard *guard_object);
25800b57cec5SDimitry Andric   llvm::FunctionType *FTy =
25810b57cec5SDimitry Andric     llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
25820b57cec5SDimitry Andric   return CGM.CreateRuntimeFunction(
25830b57cec5SDimitry Andric       FTy, "__cxa_guard_abort",
25840b57cec5SDimitry Andric       llvm::AttributeList::get(CGM.getLLVMContext(),
25850b57cec5SDimitry Andric                                llvm::AttributeList::FunctionIndex,
25860b57cec5SDimitry Andric                                llvm::Attribute::NoUnwind));
25870b57cec5SDimitry Andric }
25880b57cec5SDimitry Andric 
25890b57cec5SDimitry Andric namespace {
25900b57cec5SDimitry Andric   struct CallGuardAbort final : EHScopeStack::Cleanup {
25910b57cec5SDimitry Andric     llvm::GlobalVariable *Guard;
25920b57cec5SDimitry Andric     CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
25930b57cec5SDimitry Andric 
25940b57cec5SDimitry Andric     void Emit(CodeGenFunction &CGF, Flags flags) override {
25950b57cec5SDimitry Andric       CGF.EmitNounwindRuntimeCall(getGuardAbortFn(CGF.CGM, Guard->getType()),
25960b57cec5SDimitry Andric                                   Guard);
25970b57cec5SDimitry Andric     }
25980b57cec5SDimitry Andric   };
25990b57cec5SDimitry Andric }
26000b57cec5SDimitry Andric 
26010b57cec5SDimitry Andric /// The ARM code here follows the Itanium code closely enough that we
26020b57cec5SDimitry Andric /// just special-case it at particular places.
26030b57cec5SDimitry Andric void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
26040b57cec5SDimitry Andric                                     const VarDecl &D,
26050b57cec5SDimitry Andric                                     llvm::GlobalVariable *var,
26060b57cec5SDimitry Andric                                     bool shouldPerformInit) {
26070b57cec5SDimitry Andric   CGBuilderTy &Builder = CGF.Builder;
26080b57cec5SDimitry Andric 
26090b57cec5SDimitry Andric   // Inline variables that weren't instantiated from variable templates have
26100b57cec5SDimitry Andric   // partially-ordered initialization within their translation unit.
26110b57cec5SDimitry Andric   bool NonTemplateInline =
26120b57cec5SDimitry Andric       D.isInline() &&
26130b57cec5SDimitry Andric       !isTemplateInstantiation(D.getTemplateSpecializationKind());
26140b57cec5SDimitry Andric 
26150b57cec5SDimitry Andric   // We only need to use thread-safe statics for local non-TLS variables and
26160b57cec5SDimitry Andric   // inline variables; other global initialization is always single-threaded
26170b57cec5SDimitry Andric   // or (through lazy dynamic loading in multiple threads) unsequenced.
26180b57cec5SDimitry Andric   bool threadsafe = getContext().getLangOpts().ThreadsafeStatics &&
26190b57cec5SDimitry Andric                     (D.isLocalVarDecl() || NonTemplateInline) &&
26200b57cec5SDimitry Andric                     !D.getTLSKind();
26210b57cec5SDimitry Andric 
26220b57cec5SDimitry Andric   // If we have a global variable with internal linkage and thread-safe statics
26230b57cec5SDimitry Andric   // are disabled, we can just let the guard variable be of type i8.
26240b57cec5SDimitry Andric   bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage();
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric   llvm::IntegerType *guardTy;
26270b57cec5SDimitry Andric   CharUnits guardAlignment;
26280b57cec5SDimitry Andric   if (useInt8GuardVariable) {
26290b57cec5SDimitry Andric     guardTy = CGF.Int8Ty;
26300b57cec5SDimitry Andric     guardAlignment = CharUnits::One();
26310b57cec5SDimitry Andric   } else {
26320b57cec5SDimitry Andric     // Guard variables are 64 bits in the generic ABI and size width on ARM
26330b57cec5SDimitry Andric     // (i.e. 32-bit on AArch32, 64-bit on AArch64).
26340b57cec5SDimitry Andric     if (UseARMGuardVarABI) {
26350b57cec5SDimitry Andric       guardTy = CGF.SizeTy;
26360b57cec5SDimitry Andric       guardAlignment = CGF.getSizeAlign();
26370b57cec5SDimitry Andric     } else {
26380b57cec5SDimitry Andric       guardTy = CGF.Int64Ty;
2639bdd1243dSDimitry Andric       guardAlignment =
2640bdd1243dSDimitry Andric           CharUnits::fromQuantity(CGM.getDataLayout().getABITypeAlign(guardTy));
26410b57cec5SDimitry Andric     }
26420b57cec5SDimitry Andric   }
264306c3fb27SDimitry Andric   llvm::PointerType *guardPtrTy = llvm::PointerType::get(
264406c3fb27SDimitry Andric       CGF.CGM.getLLVMContext(),
2645e8d8bef9SDimitry Andric       CGF.CGM.getDataLayout().getDefaultGlobalsAddressSpace());
26460b57cec5SDimitry Andric 
26470b57cec5SDimitry Andric   // Create the guard variable if we don't already have it (as we
26480b57cec5SDimitry Andric   // might if we're double-emitting this function body).
26490b57cec5SDimitry Andric   llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D);
26500b57cec5SDimitry Andric   if (!guard) {
26510b57cec5SDimitry Andric     // Mangle the name for the guard.
26520b57cec5SDimitry Andric     SmallString<256> guardName;
26530b57cec5SDimitry Andric     {
26540b57cec5SDimitry Andric       llvm::raw_svector_ostream out(guardName);
26550b57cec5SDimitry Andric       getMangleContext().mangleStaticGuardVariable(&D, out);
26560b57cec5SDimitry Andric     }
26570b57cec5SDimitry Andric 
26580b57cec5SDimitry Andric     // Create the guard variable with a zero-initializer.
2659bdd1243dSDimitry Andric     // Just absorb linkage, visibility and dll storage class  from the guarded
2660bdd1243dSDimitry Andric     // variable.
26610b57cec5SDimitry Andric     guard = new llvm::GlobalVariable(CGM.getModule(), guardTy,
26620b57cec5SDimitry Andric                                      false, var->getLinkage(),
26630b57cec5SDimitry Andric                                      llvm::ConstantInt::get(guardTy, 0),
26640b57cec5SDimitry Andric                                      guardName.str());
26650b57cec5SDimitry Andric     guard->setDSOLocal(var->isDSOLocal());
26660b57cec5SDimitry Andric     guard->setVisibility(var->getVisibility());
2667bdd1243dSDimitry Andric     guard->setDLLStorageClass(var->getDLLStorageClass());
26680b57cec5SDimitry Andric     // If the variable is thread-local, so is its guard variable.
26690b57cec5SDimitry Andric     guard->setThreadLocalMode(var->getThreadLocalMode());
2670a7dea167SDimitry Andric     guard->setAlignment(guardAlignment.getAsAlign());
26710b57cec5SDimitry Andric 
26720b57cec5SDimitry Andric     // The ABI says: "It is suggested that it be emitted in the same COMDAT
26730b57cec5SDimitry Andric     // group as the associated data object." In practice, this doesn't work for
26740b57cec5SDimitry Andric     // non-ELF and non-Wasm object formats, so only do it for ELF and Wasm.
26750b57cec5SDimitry Andric     llvm::Comdat *C = var->getComdat();
26760b57cec5SDimitry Andric     if (!D.isLocalVarDecl() && C &&
26770b57cec5SDimitry Andric         (CGM.getTarget().getTriple().isOSBinFormatELF() ||
26780b57cec5SDimitry Andric          CGM.getTarget().getTriple().isOSBinFormatWasm())) {
26790b57cec5SDimitry Andric       guard->setComdat(C);
26800b57cec5SDimitry Andric     } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
26810b57cec5SDimitry Andric       guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));
26820b57cec5SDimitry Andric     }
26830b57cec5SDimitry Andric 
26840b57cec5SDimitry Andric     CGM.setStaticLocalDeclGuardAddress(&D, guard);
26850b57cec5SDimitry Andric   }
26860b57cec5SDimitry Andric 
26870eae32dcSDimitry Andric   Address guardAddr = Address(guard, guard->getValueType(), guardAlignment);
26880b57cec5SDimitry Andric 
26890b57cec5SDimitry Andric   // Test whether the variable has completed initialization.
26900b57cec5SDimitry Andric   //
26910b57cec5SDimitry Andric   // Itanium C++ ABI 3.3.2:
26920b57cec5SDimitry Andric   //   The following is pseudo-code showing how these functions can be used:
26930b57cec5SDimitry Andric   //     if (obj_guard.first_byte == 0) {
26940b57cec5SDimitry Andric   //       if ( __cxa_guard_acquire (&obj_guard) ) {
26950b57cec5SDimitry Andric   //         try {
26960b57cec5SDimitry Andric   //           ... initialize the object ...;
26970b57cec5SDimitry Andric   //         } catch (...) {
26980b57cec5SDimitry Andric   //            __cxa_guard_abort (&obj_guard);
26990b57cec5SDimitry Andric   //            throw;
27000b57cec5SDimitry Andric   //         }
27010b57cec5SDimitry Andric   //         ... queue object destructor with __cxa_atexit() ...;
27020b57cec5SDimitry Andric   //         __cxa_guard_release (&obj_guard);
27030b57cec5SDimitry Andric   //       }
27040b57cec5SDimitry Andric   //     }
2705bdd1243dSDimitry Andric   //
2706bdd1243dSDimitry Andric   // If threadsafe statics are enabled, but we don't have inline atomics, just
2707bdd1243dSDimitry Andric   // call __cxa_guard_acquire unconditionally.  The "inline" check isn't
2708bdd1243dSDimitry Andric   // actually inline, and the user might not expect calls to __atomic libcalls.
27090b57cec5SDimitry Andric 
2710bdd1243dSDimitry Andric   unsigned MaxInlineWidthInBits = CGF.getTarget().getMaxAtomicInlineWidth();
2711bdd1243dSDimitry Andric   llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
2712bdd1243dSDimitry Andric   if (!threadsafe || MaxInlineWidthInBits) {
27130b57cec5SDimitry Andric     // Load the first byte of the guard variable.
27140b57cec5SDimitry Andric     llvm::LoadInst *LI =
271506c3fb27SDimitry Andric         Builder.CreateLoad(guardAddr.withElementType(CGM.Int8Ty));
27160b57cec5SDimitry Andric 
27170b57cec5SDimitry Andric     // Itanium ABI:
27180b57cec5SDimitry Andric     //   An implementation supporting thread-safety on multiprocessor
27190b57cec5SDimitry Andric     //   systems must also guarantee that references to the initialized
27200b57cec5SDimitry Andric     //   object do not occur before the load of the initialization flag.
27210b57cec5SDimitry Andric     //
27220b57cec5SDimitry Andric     // In LLVM, we do this by marking the load Acquire.
27230b57cec5SDimitry Andric     if (threadsafe)
27240b57cec5SDimitry Andric       LI->setAtomic(llvm::AtomicOrdering::Acquire);
27250b57cec5SDimitry Andric 
27260b57cec5SDimitry Andric     // For ARM, we should only check the first bit, rather than the entire byte:
27270b57cec5SDimitry Andric     //
27280b57cec5SDimitry Andric     // ARM C++ ABI 3.2.3.1:
27290b57cec5SDimitry Andric     //   To support the potential use of initialization guard variables
27300b57cec5SDimitry Andric     //   as semaphores that are the target of ARM SWP and LDREX/STREX
27310b57cec5SDimitry Andric     //   synchronizing instructions we define a static initialization
27320b57cec5SDimitry Andric     //   guard variable to be a 4-byte aligned, 4-byte word with the
27330b57cec5SDimitry Andric     //   following inline access protocol.
27340b57cec5SDimitry Andric     //     #define INITIALIZED 1
27350b57cec5SDimitry Andric     //     if ((obj_guard & INITIALIZED) != INITIALIZED) {
27360b57cec5SDimitry Andric     //       if (__cxa_guard_acquire(&obj_guard))
27370b57cec5SDimitry Andric     //         ...
27380b57cec5SDimitry Andric     //     }
27390b57cec5SDimitry Andric     //
27400b57cec5SDimitry Andric     // and similarly for ARM64:
27410b57cec5SDimitry Andric     //
27420b57cec5SDimitry Andric     // ARM64 C++ ABI 3.2.2:
27430b57cec5SDimitry Andric     //   This ABI instead only specifies the value bit 0 of the static guard
27440b57cec5SDimitry Andric     //   variable; all other bits are platform defined. Bit 0 shall be 0 when the
27450b57cec5SDimitry Andric     //   variable is not initialized and 1 when it is.
27460b57cec5SDimitry Andric     llvm::Value *V =
27470b57cec5SDimitry Andric         (UseARMGuardVarABI && !useInt8GuardVariable)
27480b57cec5SDimitry Andric             ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
27490b57cec5SDimitry Andric             : LI;
27500b57cec5SDimitry Andric     llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized");
27510b57cec5SDimitry Andric 
27520b57cec5SDimitry Andric     llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
27530b57cec5SDimitry Andric 
27540b57cec5SDimitry Andric     // Check if the first byte of the guard variable is zero.
27550b57cec5SDimitry Andric     CGF.EmitCXXGuardedInitBranch(NeedsInit, InitCheckBlock, EndBlock,
27560b57cec5SDimitry Andric                                  CodeGenFunction::GuardKind::VariableGuard, &D);
27570b57cec5SDimitry Andric 
27580b57cec5SDimitry Andric     CGF.EmitBlock(InitCheckBlock);
2759bdd1243dSDimitry Andric   }
2760bdd1243dSDimitry Andric 
2761bdd1243dSDimitry Andric   // The semantics of dynamic initialization of variables with static or thread
2762bdd1243dSDimitry Andric   // storage duration depends on whether they are declared at block-scope. The
2763bdd1243dSDimitry Andric   // initialization of such variables at block-scope can be aborted with an
2764bdd1243dSDimitry Andric   // exception and later retried (per C++20 [stmt.dcl]p4), and recursive entry
2765bdd1243dSDimitry Andric   // to their initialization has undefined behavior (also per C++20
2766bdd1243dSDimitry Andric   // [stmt.dcl]p4). For such variables declared at non-block scope, exceptions
2767bdd1243dSDimitry Andric   // lead to termination (per C++20 [except.terminate]p1), and recursive
2768bdd1243dSDimitry Andric   // references to the variables are governed only by the lifetime rules (per
2769bdd1243dSDimitry Andric   // C++20 [class.cdtor]p2), which means such references are perfectly fine as
2770bdd1243dSDimitry Andric   // long as they avoid touching memory. As a result, block-scope variables must
2771bdd1243dSDimitry Andric   // not be marked as initialized until after initialization completes (unless
2772bdd1243dSDimitry Andric   // the mark is reverted following an exception), but non-block-scope variables
2773bdd1243dSDimitry Andric   // must be marked prior to initialization so that recursive accesses during
2774bdd1243dSDimitry Andric   // initialization do not restart initialization.
27750b57cec5SDimitry Andric 
27760b57cec5SDimitry Andric   // Variables used when coping with thread-safe statics and exceptions.
27770b57cec5SDimitry Andric   if (threadsafe) {
27780b57cec5SDimitry Andric     // Call __cxa_guard_acquire.
27790b57cec5SDimitry Andric     llvm::Value *V
27800b57cec5SDimitry Andric       = CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard);
27810b57cec5SDimitry Andric 
27820b57cec5SDimitry Andric     llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
27830b57cec5SDimitry Andric 
27840b57cec5SDimitry Andric     Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
27850b57cec5SDimitry Andric                          InitBlock, EndBlock);
27860b57cec5SDimitry Andric 
27870b57cec5SDimitry Andric     // Call __cxa_guard_abort along the exceptional edge.
27880b57cec5SDimitry Andric     CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard);
27890b57cec5SDimitry Andric 
27900b57cec5SDimitry Andric     CGF.EmitBlock(InitBlock);
2791bdd1243dSDimitry Andric   } else if (!D.isLocalVarDecl()) {
2792bdd1243dSDimitry Andric     // For non-local variables, store 1 into the first byte of the guard
2793bdd1243dSDimitry Andric     // variable before the object initialization begins so that references
2794bdd1243dSDimitry Andric     // to the variable during initialization don't restart initialization.
2795bdd1243dSDimitry Andric     Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
279606c3fb27SDimitry Andric                         guardAddr.withElementType(CGM.Int8Ty));
27970b57cec5SDimitry Andric   }
27980b57cec5SDimitry Andric 
27990b57cec5SDimitry Andric   // Emit the initializer and add a global destructor if appropriate.
28000b57cec5SDimitry Andric   CGF.EmitCXXGlobalVarDeclInit(D, var, shouldPerformInit);
28010b57cec5SDimitry Andric 
28020b57cec5SDimitry Andric   if (threadsafe) {
28030b57cec5SDimitry Andric     // Pop the guard-abort cleanup if we pushed one.
28040b57cec5SDimitry Andric     CGF.PopCleanupBlock();
28050b57cec5SDimitry Andric 
28060b57cec5SDimitry Andric     // Call __cxa_guard_release.  This cannot throw.
28070b57cec5SDimitry Andric     CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy),
28080fca6ea1SDimitry Andric                                 guardAddr.emitRawPointer(CGF));
2809bdd1243dSDimitry Andric   } else if (D.isLocalVarDecl()) {
2810bdd1243dSDimitry Andric     // For local variables, store 1 into the first byte of the guard variable
2811bdd1243dSDimitry Andric     // after the object initialization completes so that initialization is
2812bdd1243dSDimitry Andric     // retried if initialization is interrupted by an exception.
2813fe6060f1SDimitry Andric     Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
281406c3fb27SDimitry Andric                         guardAddr.withElementType(CGM.Int8Ty));
28150b57cec5SDimitry Andric   }
28160b57cec5SDimitry Andric 
28170b57cec5SDimitry Andric   CGF.EmitBlock(EndBlock);
28180b57cec5SDimitry Andric }
28190b57cec5SDimitry Andric 
28200b57cec5SDimitry Andric /// Register a global destructor using __cxa_atexit.
28210b57cec5SDimitry Andric static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
28220b57cec5SDimitry Andric                                         llvm::FunctionCallee dtor,
28230b57cec5SDimitry Andric                                         llvm::Constant *addr, bool TLS) {
2824fe6060f1SDimitry Andric   assert(!CGF.getTarget().getTriple().isOSAIX() &&
2825fe6060f1SDimitry Andric          "unexpected call to emitGlobalDtorWithCXAAtExit");
28260b57cec5SDimitry Andric   assert((TLS || CGF.getTypes().getCodeGenOpts().CXAAtExit) &&
28270b57cec5SDimitry Andric          "__cxa_atexit is disabled");
28280b57cec5SDimitry Andric   const char *Name = "__cxa_atexit";
28290b57cec5SDimitry Andric   if (TLS) {
28300b57cec5SDimitry Andric     const llvm::Triple &T = CGF.getTarget().getTriple();
28310b57cec5SDimitry Andric     Name = T.isOSDarwin() ?  "_tlv_atexit" : "__cxa_thread_atexit";
28320b57cec5SDimitry Andric   }
28330b57cec5SDimitry Andric 
28340b57cec5SDimitry Andric   // We're assuming that the destructor function is something we can
283506c3fb27SDimitry Andric   // reasonably call with the default CC.
28365f757f3fSDimitry Andric   llvm::Type *dtorTy = CGF.UnqualPtrTy;
28370b57cec5SDimitry Andric 
28380b57cec5SDimitry Andric   // Preserve address space of addr.
28390b57cec5SDimitry Andric   auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0;
284006c3fb27SDimitry Andric   auto AddrPtrTy = AddrAS ? llvm::PointerType::get(CGF.getLLVMContext(), AddrAS)
284106c3fb27SDimitry Andric                           : CGF.Int8PtrTy;
28420b57cec5SDimitry Andric 
28430b57cec5SDimitry Andric   // Create a variable that binds the atexit to this shared object.
28440b57cec5SDimitry Andric   llvm::Constant *handle =
28450b57cec5SDimitry Andric       CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "__dso_handle");
28460b57cec5SDimitry Andric   auto *GV = cast<llvm::GlobalValue>(handle->stripPointerCasts());
28470b57cec5SDimitry Andric   GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
28480b57cec5SDimitry Andric 
28490b57cec5SDimitry Andric   // extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d);
285006c3fb27SDimitry Andric   llvm::Type *paramTys[] = {dtorTy, AddrPtrTy, handle->getType()};
28510b57cec5SDimitry Andric   llvm::FunctionType *atexitTy =
28520b57cec5SDimitry Andric     llvm::FunctionType::get(CGF.IntTy, paramTys, false);
28530b57cec5SDimitry Andric 
28540b57cec5SDimitry Andric   // Fetch the actual function.
28550b57cec5SDimitry Andric   llvm::FunctionCallee atexit = CGF.CGM.CreateRuntimeFunction(atexitTy, Name);
28560b57cec5SDimitry Andric   if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee()))
28570b57cec5SDimitry Andric     fn->setDoesNotThrow();
28580b57cec5SDimitry Andric 
28590fca6ea1SDimitry Andric   const auto &Context = CGF.CGM.getContext();
28600fca6ea1SDimitry Andric   FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
28610fca6ea1SDimitry Andric       /*IsVariadic=*/false, /*IsCXXMethod=*/false));
28620fca6ea1SDimitry Andric   QualType fnType =
28630fca6ea1SDimitry Andric       Context.getFunctionType(Context.VoidTy, {Context.VoidPtrTy}, EPI);
28640fca6ea1SDimitry Andric   llvm::Constant *dtorCallee = cast<llvm::Constant>(dtor.getCallee());
28650fca6ea1SDimitry Andric   dtorCallee = CGF.CGM.getFunctionPointer(dtorCallee, fnType);
28660fca6ea1SDimitry Andric 
28670b57cec5SDimitry Andric   if (!addr)
28680b57cec5SDimitry Andric     // addr is null when we are trying to register a dtor annotated with
28690b57cec5SDimitry Andric     // __attribute__((destructor)) in a constructor function. Using null here is
28700b57cec5SDimitry Andric     // okay because this argument is just passed back to the destructor
28710b57cec5SDimitry Andric     // function.
28720b57cec5SDimitry Andric     addr = llvm::Constant::getNullValue(CGF.Int8PtrTy);
28730b57cec5SDimitry Andric 
28740fca6ea1SDimitry Andric   llvm::Value *args[] = {dtorCallee, addr, handle};
28750b57cec5SDimitry Andric   CGF.EmitNounwindRuntimeCall(atexit, args);
28760b57cec5SDimitry Andric }
28770b57cec5SDimitry Andric 
2878e8d8bef9SDimitry Andric static llvm::Function *createGlobalInitOrCleanupFn(CodeGen::CodeGenModule &CGM,
2879e8d8bef9SDimitry Andric                                                    StringRef FnName) {
2880e8d8bef9SDimitry Andric   // Create a function that registers/unregisters destructors that have the same
2881e8d8bef9SDimitry Andric   // priority.
2882e8d8bef9SDimitry Andric   llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
2883e8d8bef9SDimitry Andric   llvm::Function *GlobalInitOrCleanupFn = CGM.CreateGlobalInitOrCleanUpFunction(
2884e8d8bef9SDimitry Andric       FTy, FnName, CGM.getTypes().arrangeNullaryFunction(), SourceLocation());
2885e8d8bef9SDimitry Andric 
2886e8d8bef9SDimitry Andric   return GlobalInitOrCleanupFn;
2887e8d8bef9SDimitry Andric }
2888e8d8bef9SDimitry Andric 
2889e8d8bef9SDimitry Andric void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {
2890e8d8bef9SDimitry Andric   for (const auto &I : DtorsUsingAtExit) {
2891e8d8bef9SDimitry Andric     int Priority = I.first;
2892e8d8bef9SDimitry Andric     std::string GlobalCleanupFnName =
2893e8d8bef9SDimitry Andric         std::string("__GLOBAL_cleanup_") + llvm::to_string(Priority);
2894e8d8bef9SDimitry Andric 
2895e8d8bef9SDimitry Andric     llvm::Function *GlobalCleanupFn =
2896e8d8bef9SDimitry Andric         createGlobalInitOrCleanupFn(*this, GlobalCleanupFnName);
2897e8d8bef9SDimitry Andric 
2898e8d8bef9SDimitry Andric     CodeGenFunction CGF(*this);
2899fe6060f1SDimitry Andric     CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalCleanupFn,
2900fe6060f1SDimitry Andric                       getTypes().arrangeNullaryFunction(), FunctionArgList(),
2901fe6060f1SDimitry Andric                       SourceLocation(), SourceLocation());
2902fe6060f1SDimitry Andric     auto AL = ApplyDebugLocation::CreateArtificial(CGF);
2903e8d8bef9SDimitry Andric 
2904e8d8bef9SDimitry Andric     // Get the destructor function type, void(*)(void).
2905e8d8bef9SDimitry Andric     llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.VoidTy, false);
2906e8d8bef9SDimitry Andric 
2907e8d8bef9SDimitry Andric     // Destructor functions are run/unregistered in non-ascending
2908e8d8bef9SDimitry Andric     // order of their priorities.
2909e8d8bef9SDimitry Andric     const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2910e8d8bef9SDimitry Andric     auto itv = Dtors.rbegin();
2911e8d8bef9SDimitry Andric     while (itv != Dtors.rend()) {
2912e8d8bef9SDimitry Andric       llvm::Function *Dtor = *itv;
2913e8d8bef9SDimitry Andric 
2914e8d8bef9SDimitry Andric       // We're assuming that the destructor function is something we can
291506c3fb27SDimitry Andric       // reasonably call with the correct CC.
291606c3fb27SDimitry Andric       llvm::Value *V = CGF.unregisterGlobalDtorWithUnAtExit(Dtor);
2917e8d8bef9SDimitry Andric       llvm::Value *NeedsDestruct =
2918e8d8bef9SDimitry Andric           CGF.Builder.CreateIsNull(V, "needs_destruct");
2919e8d8bef9SDimitry Andric 
2920e8d8bef9SDimitry Andric       llvm::BasicBlock *DestructCallBlock =
2921e8d8bef9SDimitry Andric           CGF.createBasicBlock("destruct.call");
2922e8d8bef9SDimitry Andric       llvm::BasicBlock *EndBlock = CGF.createBasicBlock(
2923e8d8bef9SDimitry Andric           (itv + 1) != Dtors.rend() ? "unatexit.call" : "destruct.end");
2924e8d8bef9SDimitry Andric       // Check if unatexit returns a value of 0. If it does, jump to
2925e8d8bef9SDimitry Andric       // DestructCallBlock, otherwise jump to EndBlock directly.
2926e8d8bef9SDimitry Andric       CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
2927e8d8bef9SDimitry Andric 
2928e8d8bef9SDimitry Andric       CGF.EmitBlock(DestructCallBlock);
2929e8d8bef9SDimitry Andric 
2930e8d8bef9SDimitry Andric       // Emit the call to casted Dtor.
293106c3fb27SDimitry Andric       llvm::CallInst *CI = CGF.Builder.CreateCall(dtorFuncTy, Dtor);
2932e8d8bef9SDimitry Andric       // Make sure the call and the callee agree on calling convention.
2933e8d8bef9SDimitry Andric       CI->setCallingConv(Dtor->getCallingConv());
2934e8d8bef9SDimitry Andric 
2935e8d8bef9SDimitry Andric       CGF.EmitBlock(EndBlock);
2936e8d8bef9SDimitry Andric 
2937e8d8bef9SDimitry Andric       itv++;
2938e8d8bef9SDimitry Andric     }
2939e8d8bef9SDimitry Andric 
2940e8d8bef9SDimitry Andric     CGF.FinishFunction();
2941e8d8bef9SDimitry Andric     AddGlobalDtor(GlobalCleanupFn, Priority);
2942e8d8bef9SDimitry Andric   }
2943e8d8bef9SDimitry Andric }
2944e8d8bef9SDimitry Andric 
29450b57cec5SDimitry Andric void CodeGenModule::registerGlobalDtorsWithAtExit() {
2946480093f4SDimitry Andric   for (const auto &I : DtorsUsingAtExit) {
29470b57cec5SDimitry Andric     int Priority = I.first;
2948e8d8bef9SDimitry Andric     std::string GlobalInitFnName =
2949e8d8bef9SDimitry Andric         std::string("__GLOBAL_init_") + llvm::to_string(Priority);
2950e8d8bef9SDimitry Andric     llvm::Function *GlobalInitFn =
2951e8d8bef9SDimitry Andric         createGlobalInitOrCleanupFn(*this, GlobalInitFnName);
29520b57cec5SDimitry Andric 
2953e8d8bef9SDimitry Andric     CodeGenFunction CGF(*this);
2954fe6060f1SDimitry Andric     CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalInitFn,
2955fe6060f1SDimitry Andric                       getTypes().arrangeNullaryFunction(), FunctionArgList(),
2956fe6060f1SDimitry Andric                       SourceLocation(), SourceLocation());
2957fe6060f1SDimitry Andric     auto AL = ApplyDebugLocation::CreateArtificial(CGF);
2958e8d8bef9SDimitry Andric 
29590b57cec5SDimitry Andric     // Since constructor functions are run in non-descending order of their
29600b57cec5SDimitry Andric     // priorities, destructors are registered in non-descending order of their
29610b57cec5SDimitry Andric     // priorities, and since destructor functions are run in the reverse order
29620b57cec5SDimitry Andric     // of their registration, destructor functions are run in non-ascending
29630b57cec5SDimitry Andric     // order of their priorities.
2964e8d8bef9SDimitry Andric     const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
29650b57cec5SDimitry Andric     for (auto *Dtor : Dtors) {
29660b57cec5SDimitry Andric       // Register the destructor function calling __cxa_atexit if it is
29670b57cec5SDimitry Andric       // available. Otherwise fall back on calling atexit.
2968e8d8bef9SDimitry Andric       if (getCodeGenOpts().CXAAtExit) {
29690b57cec5SDimitry Andric         emitGlobalDtorWithCXAAtExit(CGF, Dtor, nullptr, false);
2970e8d8bef9SDimitry Andric       } else {
2971e8d8bef9SDimitry Andric         // We're assuming that the destructor function is something we can
297206c3fb27SDimitry Andric         // reasonably call with the correct CC.
297306c3fb27SDimitry Andric         CGF.registerGlobalDtorWithAtExit(Dtor);
2974e8d8bef9SDimitry Andric       }
29750b57cec5SDimitry Andric     }
29760b57cec5SDimitry Andric 
29770b57cec5SDimitry Andric     CGF.FinishFunction();
2978bdd1243dSDimitry Andric     AddGlobalCtor(GlobalInitFn, Priority);
29790b57cec5SDimitry Andric   }
2980e8d8bef9SDimitry Andric 
2981e8d8bef9SDimitry Andric   if (getCXXABI().useSinitAndSterm())
2982e8d8bef9SDimitry Andric     unregisterGlobalDtorsWithUnAtExit();
29830b57cec5SDimitry Andric }
29840b57cec5SDimitry Andric 
29850b57cec5SDimitry Andric /// Register a global destructor as best as we know how.
29860b57cec5SDimitry Andric void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
29870b57cec5SDimitry Andric                                        llvm::FunctionCallee dtor,
29880b57cec5SDimitry Andric                                        llvm::Constant *addr) {
29890b57cec5SDimitry Andric   if (D.isNoDestroy(CGM.getContext()))
29900b57cec5SDimitry Andric     return;
29910b57cec5SDimitry Andric 
29925f757f3fSDimitry Andric   // OpenMP offloading supports C++ constructors and destructors but we do not
29935f757f3fSDimitry Andric   // always have 'atexit' available. Instead lower these to use the LLVM global
29945f757f3fSDimitry Andric   // destructors which we can handle directly in the runtime. Note that this is
29955f757f3fSDimitry Andric   // not strictly 1-to-1 with using `atexit` because we no longer tear down
29965f757f3fSDimitry Andric   // globals in reverse order of when they were constructed.
29975f757f3fSDimitry Andric   if (!CGM.getLangOpts().hasAtExit() && !D.isStaticLocal())
29985f757f3fSDimitry Andric     return CGF.registerGlobalDtorWithLLVM(D, dtor, addr);
29995f757f3fSDimitry Andric 
30000b57cec5SDimitry Andric   // emitGlobalDtorWithCXAAtExit will emit a call to either __cxa_thread_atexit
30010b57cec5SDimitry Andric   // or __cxa_atexit depending on whether this VarDecl is a thread-local storage
30020b57cec5SDimitry Andric   // or not. CXAAtExit controls only __cxa_atexit, so use it if it is enabled.
30030b57cec5SDimitry Andric   // We can always use __cxa_thread_atexit.
30040b57cec5SDimitry Andric   if (CGM.getCodeGenOpts().CXAAtExit || D.getTLSKind())
30050b57cec5SDimitry Andric     return emitGlobalDtorWithCXAAtExit(CGF, dtor, addr, D.getTLSKind());
30060b57cec5SDimitry Andric 
30070b57cec5SDimitry Andric   // In Apple kexts, we want to add a global destructor entry.
30080b57cec5SDimitry Andric   // FIXME: shouldn't this be guarded by some variable?
30090b57cec5SDimitry Andric   if (CGM.getLangOpts().AppleKext) {
30100b57cec5SDimitry Andric     // Generate a global destructor entry.
30110b57cec5SDimitry Andric     return CGM.AddCXXDtorEntry(dtor, addr);
30120b57cec5SDimitry Andric   }
30130b57cec5SDimitry Andric 
30140b57cec5SDimitry Andric   CGF.registerGlobalDtorWithAtExit(D, dtor, addr);
30150b57cec5SDimitry Andric }
30160b57cec5SDimitry Andric 
30170b57cec5SDimitry Andric static bool isThreadWrapperReplaceable(const VarDecl *VD,
30180b57cec5SDimitry Andric                                        CodeGen::CodeGenModule &CGM) {
30190b57cec5SDimitry Andric   assert(!VD->isStaticLocal() && "static local VarDecls don't need wrappers!");
30200b57cec5SDimitry Andric   // Darwin prefers to have references to thread local variables to go through
30210b57cec5SDimitry Andric   // the thread wrapper instead of directly referencing the backing variable.
30220b57cec5SDimitry Andric   return VD->getTLSKind() == VarDecl::TLS_Dynamic &&
30230b57cec5SDimitry Andric          CGM.getTarget().getTriple().isOSDarwin();
30240b57cec5SDimitry Andric }
30250b57cec5SDimitry Andric 
30260b57cec5SDimitry Andric /// Get the appropriate linkage for the wrapper function. This is essentially
30270b57cec5SDimitry Andric /// the weak form of the variable's linkage; every translation unit which needs
30280b57cec5SDimitry Andric /// the wrapper emits a copy, and we want the linker to merge them.
30290b57cec5SDimitry Andric static llvm::GlobalValue::LinkageTypes
30300b57cec5SDimitry Andric getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) {
30310b57cec5SDimitry Andric   llvm::GlobalValue::LinkageTypes VarLinkage =
30328a4dda33SDimitry Andric       CGM.getLLVMLinkageVarDefinition(VD);
30330b57cec5SDimitry Andric 
30340b57cec5SDimitry Andric   // For internal linkage variables, we don't need an external or weak wrapper.
30350b57cec5SDimitry Andric   if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
30360b57cec5SDimitry Andric     return VarLinkage;
30370b57cec5SDimitry Andric 
30380b57cec5SDimitry Andric   // If the thread wrapper is replaceable, give it appropriate linkage.
30390b57cec5SDimitry Andric   if (isThreadWrapperReplaceable(VD, CGM))
30400b57cec5SDimitry Andric     if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
30410b57cec5SDimitry Andric         !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
30420b57cec5SDimitry Andric       return VarLinkage;
30430b57cec5SDimitry Andric   return llvm::GlobalValue::WeakODRLinkage;
30440b57cec5SDimitry Andric }
30450b57cec5SDimitry Andric 
30460b57cec5SDimitry Andric llvm::Function *
30470b57cec5SDimitry Andric ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
30480b57cec5SDimitry Andric                                              llvm::Value *Val) {
30490b57cec5SDimitry Andric   // Mangle the name for the thread_local wrapper function.
30500b57cec5SDimitry Andric   SmallString<256> WrapperName;
30510b57cec5SDimitry Andric   {
30520b57cec5SDimitry Andric     llvm::raw_svector_ostream Out(WrapperName);
30530b57cec5SDimitry Andric     getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);
30540b57cec5SDimitry Andric   }
30550b57cec5SDimitry Andric 
30560b57cec5SDimitry Andric   // FIXME: If VD is a definition, we should regenerate the function attributes
30570b57cec5SDimitry Andric   // before returning.
30580b57cec5SDimitry Andric   if (llvm::Value *V = CGM.getModule().getNamedValue(WrapperName))
30590b57cec5SDimitry Andric     return cast<llvm::Function>(V);
30600b57cec5SDimitry Andric 
30610b57cec5SDimitry Andric   QualType RetQT = VD->getType();
30620b57cec5SDimitry Andric   if (RetQT->isReferenceType())
30630b57cec5SDimitry Andric     RetQT = RetQT.getNonReferenceType();
30640b57cec5SDimitry Andric 
30650b57cec5SDimitry Andric   const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
30660b57cec5SDimitry Andric       getContext().getPointerType(RetQT), FunctionArgList());
30670b57cec5SDimitry Andric 
30680b57cec5SDimitry Andric   llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI);
30690b57cec5SDimitry Andric   llvm::Function *Wrapper =
30700b57cec5SDimitry Andric       llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM),
30710b57cec5SDimitry Andric                              WrapperName.str(), &CGM.getModule());
30720b57cec5SDimitry Andric 
3073480093f4SDimitry Andric   if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())
3074480093f4SDimitry Andric     Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));
3075480093f4SDimitry Andric 
3076fe6060f1SDimitry Andric   CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper, /*IsThunk=*/false);
30770b57cec5SDimitry Andric 
30780b57cec5SDimitry Andric   // Always resolve references to the wrapper at link time.
30790b57cec5SDimitry Andric   if (!Wrapper->hasLocalLinkage())
30800b57cec5SDimitry Andric     if (!isThreadWrapperReplaceable(VD, CGM) ||
30810b57cec5SDimitry Andric         llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
30820b57cec5SDimitry Andric         llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
30830b57cec5SDimitry Andric         VD->getVisibility() == HiddenVisibility)
30840b57cec5SDimitry Andric       Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
30850b57cec5SDimitry Andric 
30860b57cec5SDimitry Andric   if (isThreadWrapperReplaceable(VD, CGM)) {
30870b57cec5SDimitry Andric     Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
30880b57cec5SDimitry Andric     Wrapper->addFnAttr(llvm::Attribute::NoUnwind);
30890b57cec5SDimitry Andric   }
3090a7dea167SDimitry Andric 
3091a7dea167SDimitry Andric   ThreadWrappers.push_back({VD, Wrapper});
30920b57cec5SDimitry Andric   return Wrapper;
30930b57cec5SDimitry Andric }
30940b57cec5SDimitry Andric 
30950b57cec5SDimitry Andric void ItaniumCXXABI::EmitThreadLocalInitFuncs(
30960b57cec5SDimitry Andric     CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
30970b57cec5SDimitry Andric     ArrayRef<llvm::Function *> CXXThreadLocalInits,
30980b57cec5SDimitry Andric     ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
30990b57cec5SDimitry Andric   llvm::Function *InitFunc = nullptr;
31000b57cec5SDimitry Andric 
31010b57cec5SDimitry Andric   // Separate initializers into those with ordered (or partially-ordered)
31020b57cec5SDimitry Andric   // initialization and those with unordered initialization.
31030b57cec5SDimitry Andric   llvm::SmallVector<llvm::Function *, 8> OrderedInits;
31040b57cec5SDimitry Andric   llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;
31050b57cec5SDimitry Andric   for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {
31060b57cec5SDimitry Andric     if (isTemplateInstantiation(
31070b57cec5SDimitry Andric             CXXThreadLocalInitVars[I]->getTemplateSpecializationKind()))
31080b57cec5SDimitry Andric       UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =
31090b57cec5SDimitry Andric           CXXThreadLocalInits[I];
31100b57cec5SDimitry Andric     else
31110b57cec5SDimitry Andric       OrderedInits.push_back(CXXThreadLocalInits[I]);
31120b57cec5SDimitry Andric   }
31130b57cec5SDimitry Andric 
31140b57cec5SDimitry Andric   if (!OrderedInits.empty()) {
31150b57cec5SDimitry Andric     // Generate a guarded initialization function.
31160b57cec5SDimitry Andric     llvm::FunctionType *FTy =
31170b57cec5SDimitry Andric         llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
31180b57cec5SDimitry Andric     const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
31195ffd83dbSDimitry Andric     InitFunc = CGM.CreateGlobalInitOrCleanUpFunction(FTy, "__tls_init", FI,
31200b57cec5SDimitry Andric                                                      SourceLocation(),
31210b57cec5SDimitry Andric                                                      /*TLS=*/true);
31220b57cec5SDimitry Andric     llvm::GlobalVariable *Guard = new llvm::GlobalVariable(
31230b57cec5SDimitry Andric         CGM.getModule(), CGM.Int8Ty, /*isConstant=*/false,
31240b57cec5SDimitry Andric         llvm::GlobalVariable::InternalLinkage,
31250b57cec5SDimitry Andric         llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard");
31260b57cec5SDimitry Andric     Guard->setThreadLocal(true);
31275ffd83dbSDimitry Andric     Guard->setThreadLocalMode(CGM.GetDefaultLLVMTLSModel());
31280b57cec5SDimitry Andric 
31290b57cec5SDimitry Andric     CharUnits GuardAlign = CharUnits::One();
3130a7dea167SDimitry Andric     Guard->setAlignment(GuardAlign.getAsAlign());
31310b57cec5SDimitry Andric 
31320b57cec5SDimitry Andric     CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(
31330eae32dcSDimitry Andric         InitFunc, OrderedInits, ConstantAddress(Guard, CGM.Int8Ty, GuardAlign));
31340b57cec5SDimitry Andric     // On Darwin platforms, use CXX_FAST_TLS calling convention.
31350b57cec5SDimitry Andric     if (CGM.getTarget().getTriple().isOSDarwin()) {
31360b57cec5SDimitry Andric       InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
31370b57cec5SDimitry Andric       InitFunc->addFnAttr(llvm::Attribute::NoUnwind);
31380b57cec5SDimitry Andric     }
31390b57cec5SDimitry Andric   }
31400b57cec5SDimitry Andric 
3141a7dea167SDimitry Andric   // Create declarations for thread wrappers for all thread-local variables
3142a7dea167SDimitry Andric   // with non-discardable definitions in this translation unit.
31430b57cec5SDimitry Andric   for (const VarDecl *VD : CXXThreadLocals) {
3144a7dea167SDimitry Andric     if (VD->hasDefinition() &&
3145a7dea167SDimitry Andric         !isDiscardableGVALinkage(getContext().GetGVALinkageForVariable(VD))) {
3146a7dea167SDimitry Andric       llvm::GlobalValue *GV = CGM.GetGlobalValue(CGM.getMangledName(VD));
3147a7dea167SDimitry Andric       getOrCreateThreadLocalWrapper(VD, GV);
3148a7dea167SDimitry Andric     }
3149a7dea167SDimitry Andric   }
3150a7dea167SDimitry Andric 
3151a7dea167SDimitry Andric   // Emit all referenced thread wrappers.
3152a7dea167SDimitry Andric   for (auto VDAndWrapper : ThreadWrappers) {
3153a7dea167SDimitry Andric     const VarDecl *VD = VDAndWrapper.first;
31540b57cec5SDimitry Andric     llvm::GlobalVariable *Var =
31550b57cec5SDimitry Andric         cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD)));
3156a7dea167SDimitry Andric     llvm::Function *Wrapper = VDAndWrapper.second;
31570b57cec5SDimitry Andric 
31580b57cec5SDimitry Andric     // Some targets require that all access to thread local variables go through
31590b57cec5SDimitry Andric     // the thread wrapper.  This means that we cannot attempt to create a thread
31600b57cec5SDimitry Andric     // wrapper or a thread helper.
3161a7dea167SDimitry Andric     if (!VD->hasDefinition()) {
3162a7dea167SDimitry Andric       if (isThreadWrapperReplaceable(VD, CGM)) {
31630b57cec5SDimitry Andric         Wrapper->setLinkage(llvm::Function::ExternalLinkage);
31640b57cec5SDimitry Andric         continue;
31650b57cec5SDimitry Andric       }
31660b57cec5SDimitry Andric 
3167a7dea167SDimitry Andric       // If this isn't a TU in which this variable is defined, the thread
3168a7dea167SDimitry Andric       // wrapper is discardable.
3169a7dea167SDimitry Andric       if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)
3170a7dea167SDimitry Andric         Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);
3171a7dea167SDimitry Andric     }
3172a7dea167SDimitry Andric 
3173a7dea167SDimitry Andric     CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Wrapper);
3174a7dea167SDimitry Andric 
31750b57cec5SDimitry Andric     // Mangle the name for the thread_local initialization function.
31760b57cec5SDimitry Andric     SmallString<256> InitFnName;
31770b57cec5SDimitry Andric     {
31780b57cec5SDimitry Andric       llvm::raw_svector_ostream Out(InitFnName);
31790b57cec5SDimitry Andric       getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
31800b57cec5SDimitry Andric     }
31810b57cec5SDimitry Andric 
31820b57cec5SDimitry Andric     llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.VoidTy, false);
31830b57cec5SDimitry Andric 
31840b57cec5SDimitry Andric     // If we have a definition for the variable, emit the initialization
31850b57cec5SDimitry Andric     // function as an alias to the global Init function (if any). Otherwise,
31860b57cec5SDimitry Andric     // produce a declaration of the initialization function.
31870b57cec5SDimitry Andric     llvm::GlobalValue *Init = nullptr;
31880b57cec5SDimitry Andric     bool InitIsInitFunc = false;
3189a7dea167SDimitry Andric     bool HasConstantInitialization = false;
3190a7dea167SDimitry Andric     if (!usesThreadWrapperFunction(VD)) {
3191a7dea167SDimitry Andric       HasConstantInitialization = true;
3192a7dea167SDimitry Andric     } else if (VD->hasDefinition()) {
31930b57cec5SDimitry Andric       InitIsInitFunc = true;
31940b57cec5SDimitry Andric       llvm::Function *InitFuncToUse = InitFunc;
31950b57cec5SDimitry Andric       if (isTemplateInstantiation(VD->getTemplateSpecializationKind()))
31960b57cec5SDimitry Andric         InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl());
31970b57cec5SDimitry Andric       if (InitFuncToUse)
31980b57cec5SDimitry Andric         Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),
31990b57cec5SDimitry Andric                                          InitFuncToUse);
32000b57cec5SDimitry Andric     } else {
32010b57cec5SDimitry Andric       // Emit a weak global function referring to the initialization function.
32020b57cec5SDimitry Andric       // This function will not exist if the TU defining the thread_local
32030b57cec5SDimitry Andric       // variable in question does not need any dynamic initialization for
32040b57cec5SDimitry Andric       // its thread_local variables.
32050b57cec5SDimitry Andric       Init = llvm::Function::Create(InitFnTy,
32060b57cec5SDimitry Andric                                     llvm::GlobalVariable::ExternalWeakLinkage,
32070b57cec5SDimitry Andric                                     InitFnName.str(), &CGM.getModule());
32080b57cec5SDimitry Andric       const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
3209fe6060f1SDimitry Andric       CGM.SetLLVMFunctionAttributes(
3210fe6060f1SDimitry Andric           GlobalDecl(), FI, cast<llvm::Function>(Init), /*IsThunk=*/false);
32110b57cec5SDimitry Andric     }
32120b57cec5SDimitry Andric 
32130b57cec5SDimitry Andric     if (Init) {
32140b57cec5SDimitry Andric       Init->setVisibility(Var->getVisibility());
3215480093f4SDimitry Andric       // Don't mark an extern_weak function DSO local on windows.
3216480093f4SDimitry Andric       if (!CGM.getTriple().isOSWindows() || !Init->hasExternalWeakLinkage())
32170b57cec5SDimitry Andric         Init->setDSOLocal(Var->isDSOLocal());
32180b57cec5SDimitry Andric     }
32190b57cec5SDimitry Andric 
32200b57cec5SDimitry Andric     llvm::LLVMContext &Context = CGM.getModule().getContext();
3221fe6060f1SDimitry Andric 
3222fe6060f1SDimitry Andric     // The linker on AIX is not happy with missing weak symbols.  However,
3223fe6060f1SDimitry Andric     // other TUs will not know whether the initialization routine exists
3224fe6060f1SDimitry Andric     // so create an empty, init function to satisfy the linker.
3225fe6060f1SDimitry Andric     // This is needed whenever a thread wrapper function is not used, and
3226fe6060f1SDimitry Andric     // also when the symbol is weak.
3227fe6060f1SDimitry Andric     if (CGM.getTriple().isOSAIX() && VD->hasDefinition() &&
3228fe6060f1SDimitry Andric         isEmittedWithConstantInitializer(VD, true) &&
3229349cc55cSDimitry Andric         !mayNeedDestruction(VD)) {
3230fe6060f1SDimitry Andric       // Init should be null.  If it were non-null, then the logic above would
3231fe6060f1SDimitry Andric       // either be defining the function to be an alias or declaring the
3232fe6060f1SDimitry Andric       // function with the expectation that the definition of the variable
3233fe6060f1SDimitry Andric       // is elsewhere.
3234fe6060f1SDimitry Andric       assert(Init == nullptr && "Expected Init to be null.");
3235fe6060f1SDimitry Andric 
3236fe6060f1SDimitry Andric       llvm::Function *Func = llvm::Function::Create(
3237fe6060f1SDimitry Andric           InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.getModule());
3238fe6060f1SDimitry Andric       const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
3239fe6060f1SDimitry Andric       CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI,
3240fe6060f1SDimitry Andric                                     cast<llvm::Function>(Func),
3241fe6060f1SDimitry Andric                                     /*IsThunk=*/false);
3242fe6060f1SDimitry Andric       // Create a function body that just returns
3243fe6060f1SDimitry Andric       llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Func);
3244fe6060f1SDimitry Andric       CGBuilderTy Builder(CGM, Entry);
3245fe6060f1SDimitry Andric       Builder.CreateRetVoid();
3246fe6060f1SDimitry Andric     }
3247fe6060f1SDimitry Andric 
32480b57cec5SDimitry Andric     llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);
32490b57cec5SDimitry Andric     CGBuilderTy Builder(CGM, Entry);
3250a7dea167SDimitry Andric     if (HasConstantInitialization) {
3251a7dea167SDimitry Andric       // No dynamic initialization to invoke.
3252a7dea167SDimitry Andric     } else if (InitIsInitFunc) {
32530b57cec5SDimitry Andric       if (Init) {
32540b57cec5SDimitry Andric         llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init);
32550b57cec5SDimitry Andric         if (isThreadWrapperReplaceable(VD, CGM)) {
32560b57cec5SDimitry Andric           CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
32570b57cec5SDimitry Andric           llvm::Function *Fn =
32580b57cec5SDimitry Andric               cast<llvm::Function>(cast<llvm::GlobalAlias>(Init)->getAliasee());
32590b57cec5SDimitry Andric           Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
32600b57cec5SDimitry Andric         }
32610b57cec5SDimitry Andric       }
3262fe6060f1SDimitry Andric     } else if (CGM.getTriple().isOSAIX()) {
3263fe6060f1SDimitry Andric       // On AIX, except if constinit and also neither of class type or of
3264fe6060f1SDimitry Andric       // (possibly multi-dimensional) array of class type, thread_local vars
3265fe6060f1SDimitry Andric       // will have init routines regardless of whether they are
3266fe6060f1SDimitry Andric       // const-initialized.  Since the routine is guaranteed to exist, we can
3267fe6060f1SDimitry Andric       // unconditionally call it without testing for its existance.  This
3268fe6060f1SDimitry Andric       // avoids potentially unresolved weak symbols which the AIX linker
3269fe6060f1SDimitry Andric       // isn't happy with.
3270fe6060f1SDimitry Andric       Builder.CreateCall(InitFnTy, Init);
32710b57cec5SDimitry Andric     } else {
32720b57cec5SDimitry Andric       // Don't know whether we have an init function. Call it if it exists.
32730b57cec5SDimitry Andric       llvm::Value *Have = Builder.CreateIsNotNull(Init);
32740b57cec5SDimitry Andric       llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context, "", Wrapper);
32750b57cec5SDimitry Andric       llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context, "", Wrapper);
32760b57cec5SDimitry Andric       Builder.CreateCondBr(Have, InitBB, ExitBB);
32770b57cec5SDimitry Andric 
32780b57cec5SDimitry Andric       Builder.SetInsertPoint(InitBB);
32790b57cec5SDimitry Andric       Builder.CreateCall(InitFnTy, Init);
32800b57cec5SDimitry Andric       Builder.CreateBr(ExitBB);
32810b57cec5SDimitry Andric 
32820b57cec5SDimitry Andric       Builder.SetInsertPoint(ExitBB);
32830b57cec5SDimitry Andric     }
32840b57cec5SDimitry Andric 
32850b57cec5SDimitry Andric     // For a reference, the result of the wrapper function is a pointer to
32860b57cec5SDimitry Andric     // the referenced object.
3287bdd1243dSDimitry Andric     llvm::Value *Val = Builder.CreateThreadLocalAddress(Var);
3288bdd1243dSDimitry Andric 
32890b57cec5SDimitry Andric     if (VD->getType()->isReferenceType()) {
32900b57cec5SDimitry Andric       CharUnits Align = CGM.getContext().getDeclAlign(VD);
3291bdd1243dSDimitry Andric       Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align);
32920b57cec5SDimitry Andric     }
3293bdd1243dSDimitry Andric 
32940b57cec5SDimitry Andric     Builder.CreateRet(Val);
32950b57cec5SDimitry Andric   }
32960b57cec5SDimitry Andric }
32970b57cec5SDimitry Andric 
32980b57cec5SDimitry Andric LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
32990b57cec5SDimitry Andric                                                    const VarDecl *VD,
33000b57cec5SDimitry Andric                                                    QualType LValType) {
33010b57cec5SDimitry Andric   llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD);
33020b57cec5SDimitry Andric   llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
33030b57cec5SDimitry Andric 
33040b57cec5SDimitry Andric   llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper);
33050b57cec5SDimitry Andric   CallVal->setCallingConv(Wrapper->getCallingConv());
33060b57cec5SDimitry Andric 
33070b57cec5SDimitry Andric   LValue LV;
33080b57cec5SDimitry Andric   if (VD->getType()->isReferenceType())
33090fca6ea1SDimitry Andric     LV = CGF.MakeNaturalAlignRawAddrLValue(CallVal, LValType);
33100b57cec5SDimitry Andric   else
33110fca6ea1SDimitry Andric     LV = CGF.MakeRawAddrLValue(CallVal, LValType,
33120b57cec5SDimitry Andric                                CGF.getContext().getDeclAlign(VD));
33130b57cec5SDimitry Andric   // FIXME: need setObjCGCLValueClass?
33140b57cec5SDimitry Andric   return LV;
33150b57cec5SDimitry Andric }
33160b57cec5SDimitry Andric 
33170b57cec5SDimitry Andric /// Return whether the given global decl needs a VTT parameter, which it does
33180b57cec5SDimitry Andric /// if it's a base constructor or destructor with virtual bases.
33190b57cec5SDimitry Andric bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {
33200b57cec5SDimitry Andric   const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
33210b57cec5SDimitry Andric 
33220b57cec5SDimitry Andric   // We don't have any virtual bases, just return early.
33230b57cec5SDimitry Andric   if (!MD->getParent()->getNumVBases())
33240b57cec5SDimitry Andric     return false;
33250b57cec5SDimitry Andric 
33260b57cec5SDimitry Andric   // Check if we have a base constructor.
33270b57cec5SDimitry Andric   if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
33280b57cec5SDimitry Andric     return true;
33290b57cec5SDimitry Andric 
33300b57cec5SDimitry Andric   // Check if we have a base destructor.
33310b57cec5SDimitry Andric   if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
33320b57cec5SDimitry Andric     return true;
33330b57cec5SDimitry Andric 
33340b57cec5SDimitry Andric   return false;
33350b57cec5SDimitry Andric }
33360b57cec5SDimitry Andric 
33370fca6ea1SDimitry Andric llvm::Constant *
33380fca6ea1SDimitry Andric ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) {
33390fca6ea1SDimitry Andric   SmallString<256> MethodName;
33400fca6ea1SDimitry Andric   llvm::raw_svector_ostream Out(MethodName);
33410fca6ea1SDimitry Andric   getMangleContext().mangleCXXName(MD, Out);
33420fca6ea1SDimitry Andric   MethodName += "_vfpthunk_";
33430fca6ea1SDimitry Andric   StringRef ThunkName = MethodName.str();
33440fca6ea1SDimitry Andric   llvm::Function *ThunkFn;
33450fca6ea1SDimitry Andric   if ((ThunkFn = cast_or_null<llvm::Function>(
33460fca6ea1SDimitry Andric            CGM.getModule().getNamedValue(ThunkName))))
33470fca6ea1SDimitry Andric     return ThunkFn;
33480fca6ea1SDimitry Andric 
33490fca6ea1SDimitry Andric   const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeCXXMethodDeclaration(MD);
33500fca6ea1SDimitry Andric   llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
33510fca6ea1SDimitry Andric   llvm::GlobalValue::LinkageTypes Linkage =
33520fca6ea1SDimitry Andric       MD->isExternallyVisible() ? llvm::GlobalValue::LinkOnceODRLinkage
33530fca6ea1SDimitry Andric                                 : llvm::GlobalValue::InternalLinkage;
33540fca6ea1SDimitry Andric   ThunkFn =
33550fca6ea1SDimitry Andric       llvm::Function::Create(ThunkTy, Linkage, ThunkName, &CGM.getModule());
33560fca6ea1SDimitry Andric   if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
33570fca6ea1SDimitry Andric     ThunkFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
33580fca6ea1SDimitry Andric   assert(ThunkFn->getName() == ThunkName && "name was uniqued!");
33590fca6ea1SDimitry Andric 
33600fca6ea1SDimitry Andric   CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn, /*IsThunk=*/true);
33610fca6ea1SDimitry Andric   CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn);
33620fca6ea1SDimitry Andric 
33630fca6ea1SDimitry Andric   // Stack protection sometimes gets inserted after the musttail call.
33640fca6ea1SDimitry Andric   ThunkFn->removeFnAttr(llvm::Attribute::StackProtect);
33650fca6ea1SDimitry Andric   ThunkFn->removeFnAttr(llvm::Attribute::StackProtectStrong);
33660fca6ea1SDimitry Andric   ThunkFn->removeFnAttr(llvm::Attribute::StackProtectReq);
33670fca6ea1SDimitry Andric 
33680fca6ea1SDimitry Andric   // Start codegen.
33690fca6ea1SDimitry Andric   CodeGenFunction CGF(CGM);
33700fca6ea1SDimitry Andric   CGF.CurGD = GlobalDecl(MD);
33710fca6ea1SDimitry Andric   CGF.CurFuncIsThunk = true;
33720fca6ea1SDimitry Andric 
33730fca6ea1SDimitry Andric   // Build FunctionArgs.
33740fca6ea1SDimitry Andric   FunctionArgList FunctionArgs;
33750fca6ea1SDimitry Andric   CGF.BuildFunctionArgList(CGF.CurGD, FunctionArgs);
33760fca6ea1SDimitry Andric 
33770fca6ea1SDimitry Andric   CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo,
33780fca6ea1SDimitry Andric                     FunctionArgs, MD->getLocation(), SourceLocation());
33790fca6ea1SDimitry Andric   llvm::Value *ThisVal = loadIncomingCXXThis(CGF);
33800fca6ea1SDimitry Andric   setCXXABIThisValue(CGF, ThisVal);
33810fca6ea1SDimitry Andric 
33820fca6ea1SDimitry Andric   CallArgList CallArgs;
33830fca6ea1SDimitry Andric   for (const VarDecl *VD : FunctionArgs)
33840fca6ea1SDimitry Andric     CGF.EmitDelegateCallArg(CallArgs, VD, SourceLocation());
33850fca6ea1SDimitry Andric 
33860fca6ea1SDimitry Andric   const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
33870fca6ea1SDimitry Andric   RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, /*this*/ 1);
33880fca6ea1SDimitry Andric   const CGFunctionInfo &CallInfo =
33890fca6ea1SDimitry Andric       CGM.getTypes().arrangeCXXMethodCall(CallArgs, FPT, Required, 0);
33900fca6ea1SDimitry Andric   CGCallee Callee = CGCallee::forVirtual(nullptr, GlobalDecl(MD),
33910fca6ea1SDimitry Andric                                          getThisAddress(CGF), ThunkTy);
33920fca6ea1SDimitry Andric   llvm::CallBase *CallOrInvoke;
33930fca6ea1SDimitry Andric   CGF.EmitCall(CallInfo, Callee, ReturnValueSlot(), CallArgs, &CallOrInvoke,
33940fca6ea1SDimitry Andric                /*IsMustTail=*/true, SourceLocation(), true);
33950fca6ea1SDimitry Andric   auto *Call = cast<llvm::CallInst>(CallOrInvoke);
33960fca6ea1SDimitry Andric   Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
33970fca6ea1SDimitry Andric   if (Call->getType()->isVoidTy())
33980fca6ea1SDimitry Andric     CGF.Builder.CreateRetVoid();
33990fca6ea1SDimitry Andric   else
34000fca6ea1SDimitry Andric     CGF.Builder.CreateRet(Call);
34010fca6ea1SDimitry Andric 
34020fca6ea1SDimitry Andric   // Finish the function to maintain CodeGenFunction invariants.
34030fca6ea1SDimitry Andric   // FIXME: Don't emit unreachable code.
34040fca6ea1SDimitry Andric   CGF.EmitBlock(CGF.createBasicBlock());
34050fca6ea1SDimitry Andric   CGF.FinishFunction();
34060fca6ea1SDimitry Andric   return ThunkFn;
34070fca6ea1SDimitry Andric }
34080fca6ea1SDimitry Andric 
34090b57cec5SDimitry Andric namespace {
34100b57cec5SDimitry Andric class ItaniumRTTIBuilder {
34110b57cec5SDimitry Andric   CodeGenModule &CGM;  // Per-module state.
34120b57cec5SDimitry Andric   llvm::LLVMContext &VMContext;
34130b57cec5SDimitry Andric   const ItaniumCXXABI &CXXABI;  // Per-module state.
34140b57cec5SDimitry Andric 
34150b57cec5SDimitry Andric   /// Fields - The fields of the RTTI descriptor currently being built.
34160b57cec5SDimitry Andric   SmallVector<llvm::Constant *, 16> Fields;
34170b57cec5SDimitry Andric 
34180b57cec5SDimitry Andric   /// GetAddrOfTypeName - Returns the mangled type name of the given type.
34190b57cec5SDimitry Andric   llvm::GlobalVariable *
34200b57cec5SDimitry Andric   GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
34210b57cec5SDimitry Andric 
34220b57cec5SDimitry Andric   /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI
34230b57cec5SDimitry Andric   /// descriptor of the given type.
34240b57cec5SDimitry Andric   llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
34250b57cec5SDimitry Andric 
34260b57cec5SDimitry Andric   /// BuildVTablePointer - Build the vtable pointer for the given type.
34270b57cec5SDimitry Andric   void BuildVTablePointer(const Type *Ty);
34280b57cec5SDimitry Andric 
34290b57cec5SDimitry Andric   /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
34300b57cec5SDimitry Andric   /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b.
34310b57cec5SDimitry Andric   void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
34320b57cec5SDimitry Andric 
34330b57cec5SDimitry Andric   /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
34340b57cec5SDimitry Andric   /// classes with bases that do not satisfy the abi::__si_class_type_info
34350b57cec5SDimitry Andric   /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
34360b57cec5SDimitry Andric   void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
34370b57cec5SDimitry Andric 
34380b57cec5SDimitry Andric   /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used
34390b57cec5SDimitry Andric   /// for pointer types.
34400b57cec5SDimitry Andric   void BuildPointerTypeInfo(QualType PointeeTy);
34410b57cec5SDimitry Andric 
34420b57cec5SDimitry Andric   /// BuildObjCObjectTypeInfo - Build the appropriate kind of
34430b57cec5SDimitry Andric   /// type_info for an object type.
34440b57cec5SDimitry Andric   void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
34450b57cec5SDimitry Andric 
34460b57cec5SDimitry Andric   /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
34470b57cec5SDimitry Andric   /// struct, used for member pointer types.
34480b57cec5SDimitry Andric   void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
34490b57cec5SDimitry Andric 
34500b57cec5SDimitry Andric public:
34510b57cec5SDimitry Andric   ItaniumRTTIBuilder(const ItaniumCXXABI &ABI)
34520b57cec5SDimitry Andric       : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {}
34530b57cec5SDimitry Andric 
34540b57cec5SDimitry Andric   // Pointer type info flags.
34550b57cec5SDimitry Andric   enum {
34560b57cec5SDimitry Andric     /// PTI_Const - Type has const qualifier.
34570b57cec5SDimitry Andric     PTI_Const = 0x1,
34580b57cec5SDimitry Andric 
34590b57cec5SDimitry Andric     /// PTI_Volatile - Type has volatile qualifier.
34600b57cec5SDimitry Andric     PTI_Volatile = 0x2,
34610b57cec5SDimitry Andric 
34620b57cec5SDimitry Andric     /// PTI_Restrict - Type has restrict qualifier.
34630b57cec5SDimitry Andric     PTI_Restrict = 0x4,
34640b57cec5SDimitry Andric 
34650b57cec5SDimitry Andric     /// PTI_Incomplete - Type is incomplete.
34660b57cec5SDimitry Andric     PTI_Incomplete = 0x8,
34670b57cec5SDimitry Andric 
34680b57cec5SDimitry Andric     /// PTI_ContainingClassIncomplete - Containing class is incomplete.
34690b57cec5SDimitry Andric     /// (in pointer to member).
34700b57cec5SDimitry Andric     PTI_ContainingClassIncomplete = 0x10,
34710b57cec5SDimitry Andric 
34720b57cec5SDimitry Andric     /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
34730b57cec5SDimitry Andric     //PTI_TransactionSafe = 0x20,
34740b57cec5SDimitry Andric 
34750b57cec5SDimitry Andric     /// PTI_Noexcept - Pointee is noexcept function (C++1z).
34760b57cec5SDimitry Andric     PTI_Noexcept = 0x40,
34770b57cec5SDimitry Andric   };
34780b57cec5SDimitry Andric 
34790b57cec5SDimitry Andric   // VMI type info flags.
34800b57cec5SDimitry Andric   enum {
34810b57cec5SDimitry Andric     /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
34820b57cec5SDimitry Andric     VMI_NonDiamondRepeat = 0x1,
34830b57cec5SDimitry Andric 
34840b57cec5SDimitry Andric     /// VMI_DiamondShaped - Class is diamond shaped.
34850b57cec5SDimitry Andric     VMI_DiamondShaped = 0x2
34860b57cec5SDimitry Andric   };
34870b57cec5SDimitry Andric 
34880b57cec5SDimitry Andric   // Base class type info flags.
34890b57cec5SDimitry Andric   enum {
34900b57cec5SDimitry Andric     /// BCTI_Virtual - Base class is virtual.
34910b57cec5SDimitry Andric     BCTI_Virtual = 0x1,
34920b57cec5SDimitry Andric 
34930b57cec5SDimitry Andric     /// BCTI_Public - Base class is public.
34940b57cec5SDimitry Andric     BCTI_Public = 0x2
34950b57cec5SDimitry Andric   };
34960b57cec5SDimitry Andric 
34970b57cec5SDimitry Andric   /// BuildTypeInfo - Build the RTTI type info struct for the given type, or
34980b57cec5SDimitry Andric   /// link to an existing RTTI descriptor if one already exists.
34990b57cec5SDimitry Andric   llvm::Constant *BuildTypeInfo(QualType Ty);
35000b57cec5SDimitry Andric 
35010b57cec5SDimitry Andric   /// BuildTypeInfo - Build the RTTI type info struct for the given type.
35020b57cec5SDimitry Andric   llvm::Constant *BuildTypeInfo(
35030b57cec5SDimitry Andric       QualType Ty,
35040b57cec5SDimitry Andric       llvm::GlobalVariable::LinkageTypes Linkage,
35050b57cec5SDimitry Andric       llvm::GlobalValue::VisibilityTypes Visibility,
35060b57cec5SDimitry Andric       llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
35070b57cec5SDimitry Andric };
35080b57cec5SDimitry Andric }
35090b57cec5SDimitry Andric 
35100b57cec5SDimitry Andric llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
35110b57cec5SDimitry Andric     QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {
35120b57cec5SDimitry Andric   SmallString<256> Name;
35130b57cec5SDimitry Andric   llvm::raw_svector_ostream Out(Name);
35140b57cec5SDimitry Andric   CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
35150b57cec5SDimitry Andric 
35160b57cec5SDimitry Andric   // We know that the mangled name of the type starts at index 4 of the
35170b57cec5SDimitry Andric   // mangled name of the typename, so we can just index into it in order to
35180b57cec5SDimitry Andric   // get the mangled name of the type.
35190b57cec5SDimitry Andric   llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
35200b57cec5SDimitry Andric                                                             Name.substr(4));
35210b57cec5SDimitry Andric   auto Align = CGM.getContext().getTypeAlignInChars(CGM.getContext().CharTy);
35220b57cec5SDimitry Andric 
35230b57cec5SDimitry Andric   llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable(
3524bdd1243dSDimitry Andric       Name, Init->getType(), Linkage, Align.getAsAlign());
35250b57cec5SDimitry Andric 
35260b57cec5SDimitry Andric   GV->setInitializer(Init);
35270b57cec5SDimitry Andric 
35280b57cec5SDimitry Andric   return GV;
35290b57cec5SDimitry Andric }
35300b57cec5SDimitry Andric 
35310b57cec5SDimitry Andric llvm::Constant *
35320b57cec5SDimitry Andric ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
35330b57cec5SDimitry Andric   // Mangle the RTTI name.
35340b57cec5SDimitry Andric   SmallString<256> Name;
35350b57cec5SDimitry Andric   llvm::raw_svector_ostream Out(Name);
35360b57cec5SDimitry Andric   CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
35370b57cec5SDimitry Andric 
35380b57cec5SDimitry Andric   // Look for an existing global.
35390b57cec5SDimitry Andric   llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
35400b57cec5SDimitry Andric 
35410b57cec5SDimitry Andric   if (!GV) {
35420b57cec5SDimitry Andric     // Create a new global variable.
35430b57cec5SDimitry Andric     // Note for the future: If we would ever like to do deferred emission of
35440b57cec5SDimitry Andric     // RTTI, check if emitting vtables opportunistically need any adjustment.
35450b57cec5SDimitry Andric 
354606c3fb27SDimitry Andric     GV = new llvm::GlobalVariable(
354706c3fb27SDimitry Andric         CGM.getModule(), CGM.GlobalsInt8PtrTy,
354806c3fb27SDimitry Andric         /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr, Name);
35490b57cec5SDimitry Andric     const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
35500b57cec5SDimitry Andric     CGM.setGVProperties(GV, RD);
3551fe6060f1SDimitry Andric     // Import the typeinfo symbol when all non-inline virtual methods are
3552fe6060f1SDimitry Andric     // imported.
3553fe6060f1SDimitry Andric     if (CGM.getTarget().hasPS4DLLImportExport()) {
35540fca6ea1SDimitry Andric       if (RD && CXXRecordNonInlineHasAttr<DLLImportAttr>(RD)) {
3555fe6060f1SDimitry Andric         GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
3556fe6060f1SDimitry Andric         CGM.setDSOLocal(GV);
3557fe6060f1SDimitry Andric       }
3558fe6060f1SDimitry Andric     }
35590b57cec5SDimitry Andric   }
35600b57cec5SDimitry Andric 
356106c3fb27SDimitry Andric   return GV;
35620b57cec5SDimitry Andric }
35630b57cec5SDimitry Andric 
35640b57cec5SDimitry Andric /// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
35650b57cec5SDimitry Andric /// info for that type is defined in the standard library.
35660b57cec5SDimitry Andric static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
35670b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.2:
35680b57cec5SDimitry Andric   //   Basic type information (e.g. for "int", "bool", etc.) will be kept in
35690b57cec5SDimitry Andric   //   the run-time support library. Specifically, the run-time support
35700b57cec5SDimitry Andric   //   library should contain type_info objects for the types X, X* and
35710b57cec5SDimitry Andric   //   X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
35720b57cec5SDimitry Andric   //   unsigned char, signed char, short, unsigned short, int, unsigned int,
35730b57cec5SDimitry Andric   //   long, unsigned long, long long, unsigned long long, float, double,
35740b57cec5SDimitry Andric   //   long double, char16_t, char32_t, and the IEEE 754r decimal and
35750b57cec5SDimitry Andric   //   half-precision floating point types.
35760b57cec5SDimitry Andric   //
35770b57cec5SDimitry Andric   // GCC also emits RTTI for __int128.
35780b57cec5SDimitry Andric   // FIXME: We do not emit RTTI information for decimal types here.
35790b57cec5SDimitry Andric 
35800b57cec5SDimitry Andric   // Types added here must also be added to EmitFundamentalRTTIDescriptors.
35810b57cec5SDimitry Andric   switch (Ty->getKind()) {
35820b57cec5SDimitry Andric     case BuiltinType::Void:
35830b57cec5SDimitry Andric     case BuiltinType::NullPtr:
35840b57cec5SDimitry Andric     case BuiltinType::Bool:
35850b57cec5SDimitry Andric     case BuiltinType::WChar_S:
35860b57cec5SDimitry Andric     case BuiltinType::WChar_U:
35870b57cec5SDimitry Andric     case BuiltinType::Char_U:
35880b57cec5SDimitry Andric     case BuiltinType::Char_S:
35890b57cec5SDimitry Andric     case BuiltinType::UChar:
35900b57cec5SDimitry Andric     case BuiltinType::SChar:
35910b57cec5SDimitry Andric     case BuiltinType::Short:
35920b57cec5SDimitry Andric     case BuiltinType::UShort:
35930b57cec5SDimitry Andric     case BuiltinType::Int:
35940b57cec5SDimitry Andric     case BuiltinType::UInt:
35950b57cec5SDimitry Andric     case BuiltinType::Long:
35960b57cec5SDimitry Andric     case BuiltinType::ULong:
35970b57cec5SDimitry Andric     case BuiltinType::LongLong:
35980b57cec5SDimitry Andric     case BuiltinType::ULongLong:
35990b57cec5SDimitry Andric     case BuiltinType::Half:
36000b57cec5SDimitry Andric     case BuiltinType::Float:
36010b57cec5SDimitry Andric     case BuiltinType::Double:
36020b57cec5SDimitry Andric     case BuiltinType::LongDouble:
36030b57cec5SDimitry Andric     case BuiltinType::Float16:
36040b57cec5SDimitry Andric     case BuiltinType::Float128:
3605349cc55cSDimitry Andric     case BuiltinType::Ibm128:
36060b57cec5SDimitry Andric     case BuiltinType::Char8:
36070b57cec5SDimitry Andric     case BuiltinType::Char16:
36080b57cec5SDimitry Andric     case BuiltinType::Char32:
36090b57cec5SDimitry Andric     case BuiltinType::Int128:
36100b57cec5SDimitry Andric     case BuiltinType::UInt128:
36110b57cec5SDimitry Andric       return true;
36120b57cec5SDimitry Andric 
36130b57cec5SDimitry Andric #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
36140b57cec5SDimitry Andric     case BuiltinType::Id:
36150b57cec5SDimitry Andric #include "clang/Basic/OpenCLImageTypes.def"
36160b57cec5SDimitry Andric #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
36170b57cec5SDimitry Andric     case BuiltinType::Id:
36180b57cec5SDimitry Andric #include "clang/Basic/OpenCLExtensionTypes.def"
36190b57cec5SDimitry Andric     case BuiltinType::OCLSampler:
36200b57cec5SDimitry Andric     case BuiltinType::OCLEvent:
36210b57cec5SDimitry Andric     case BuiltinType::OCLClkEvent:
36220b57cec5SDimitry Andric     case BuiltinType::OCLQueue:
36230b57cec5SDimitry Andric     case BuiltinType::OCLReserveID:
3624a7dea167SDimitry Andric #define SVE_TYPE(Name, Id, SingletonId) \
3625a7dea167SDimitry Andric     case BuiltinType::Id:
3626a7dea167SDimitry Andric #include "clang/Basic/AArch64SVEACLETypes.def"
3627e8d8bef9SDimitry Andric #define PPC_VECTOR_TYPE(Name, Id, Size) \
3628e8d8bef9SDimitry Andric     case BuiltinType::Id:
3629e8d8bef9SDimitry Andric #include "clang/Basic/PPCTypes.def"
3630fe6060f1SDimitry Andric #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3631fe6060f1SDimitry Andric #include "clang/Basic/RISCVVTypes.def"
363206c3fb27SDimitry Andric #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
363306c3fb27SDimitry Andric #include "clang/Basic/WebAssemblyReferenceTypes.def"
36340fca6ea1SDimitry Andric #define AMDGPU_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
36350fca6ea1SDimitry Andric #include "clang/Basic/AMDGPUTypes.def"
36360b57cec5SDimitry Andric     case BuiltinType::ShortAccum:
36370b57cec5SDimitry Andric     case BuiltinType::Accum:
36380b57cec5SDimitry Andric     case BuiltinType::LongAccum:
36390b57cec5SDimitry Andric     case BuiltinType::UShortAccum:
36400b57cec5SDimitry Andric     case BuiltinType::UAccum:
36410b57cec5SDimitry Andric     case BuiltinType::ULongAccum:
36420b57cec5SDimitry Andric     case BuiltinType::ShortFract:
36430b57cec5SDimitry Andric     case BuiltinType::Fract:
36440b57cec5SDimitry Andric     case BuiltinType::LongFract:
36450b57cec5SDimitry Andric     case BuiltinType::UShortFract:
36460b57cec5SDimitry Andric     case BuiltinType::UFract:
36470b57cec5SDimitry Andric     case BuiltinType::ULongFract:
36480b57cec5SDimitry Andric     case BuiltinType::SatShortAccum:
36490b57cec5SDimitry Andric     case BuiltinType::SatAccum:
36500b57cec5SDimitry Andric     case BuiltinType::SatLongAccum:
36510b57cec5SDimitry Andric     case BuiltinType::SatUShortAccum:
36520b57cec5SDimitry Andric     case BuiltinType::SatUAccum:
36530b57cec5SDimitry Andric     case BuiltinType::SatULongAccum:
36540b57cec5SDimitry Andric     case BuiltinType::SatShortFract:
36550b57cec5SDimitry Andric     case BuiltinType::SatFract:
36560b57cec5SDimitry Andric     case BuiltinType::SatLongFract:
36570b57cec5SDimitry Andric     case BuiltinType::SatUShortFract:
36580b57cec5SDimitry Andric     case BuiltinType::SatUFract:
36590b57cec5SDimitry Andric     case BuiltinType::SatULongFract:
36605ffd83dbSDimitry Andric     case BuiltinType::BFloat16:
36610b57cec5SDimitry Andric       return false;
36620b57cec5SDimitry Andric 
36630b57cec5SDimitry Andric     case BuiltinType::Dependent:
36640b57cec5SDimitry Andric #define BUILTIN_TYPE(Id, SingletonId)
36650b57cec5SDimitry Andric #define PLACEHOLDER_TYPE(Id, SingletonId) \
36660b57cec5SDimitry Andric     case BuiltinType::Id:
36670b57cec5SDimitry Andric #include "clang/AST/BuiltinTypes.def"
36680b57cec5SDimitry Andric       llvm_unreachable("asking for RRTI for a placeholder type!");
36690b57cec5SDimitry Andric 
36700b57cec5SDimitry Andric     case BuiltinType::ObjCId:
36710b57cec5SDimitry Andric     case BuiltinType::ObjCClass:
36720b57cec5SDimitry Andric     case BuiltinType::ObjCSel:
36730b57cec5SDimitry Andric       llvm_unreachable("FIXME: Objective-C types are unsupported!");
36740b57cec5SDimitry Andric   }
36750b57cec5SDimitry Andric 
36760b57cec5SDimitry Andric   llvm_unreachable("Invalid BuiltinType Kind!");
36770b57cec5SDimitry Andric }
36780b57cec5SDimitry Andric 
36790b57cec5SDimitry Andric static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
36800b57cec5SDimitry Andric   QualType PointeeTy = PointerTy->getPointeeType();
36810b57cec5SDimitry Andric   const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
36820b57cec5SDimitry Andric   if (!BuiltinTy)
36830b57cec5SDimitry Andric     return false;
36840b57cec5SDimitry Andric 
36850b57cec5SDimitry Andric   // Check the qualifiers.
36860b57cec5SDimitry Andric   Qualifiers Quals = PointeeTy.getQualifiers();
36870b57cec5SDimitry Andric   Quals.removeConst();
36880b57cec5SDimitry Andric 
36890b57cec5SDimitry Andric   if (!Quals.empty())
36900b57cec5SDimitry Andric     return false;
36910b57cec5SDimitry Andric 
36920b57cec5SDimitry Andric   return TypeInfoIsInStandardLibrary(BuiltinTy);
36930b57cec5SDimitry Andric }
36940b57cec5SDimitry Andric 
36950b57cec5SDimitry Andric /// IsStandardLibraryRTTIDescriptor - Returns whether the type
36960b57cec5SDimitry Andric /// information for the given type exists in the standard library.
36970b57cec5SDimitry Andric static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
36980b57cec5SDimitry Andric   // Type info for builtin types is defined in the standard library.
36990b57cec5SDimitry Andric   if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
37000b57cec5SDimitry Andric     return TypeInfoIsInStandardLibrary(BuiltinTy);
37010b57cec5SDimitry Andric 
37020b57cec5SDimitry Andric   // Type info for some pointer types to builtin types is defined in the
37030b57cec5SDimitry Andric   // standard library.
37040b57cec5SDimitry Andric   if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
37050b57cec5SDimitry Andric     return TypeInfoIsInStandardLibrary(PointerTy);
37060b57cec5SDimitry Andric 
37070b57cec5SDimitry Andric   return false;
37080b57cec5SDimitry Andric }
37090b57cec5SDimitry Andric 
37100b57cec5SDimitry Andric /// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
37110b57cec5SDimitry Andric /// the given type exists somewhere else, and that we should not emit the type
37120b57cec5SDimitry Andric /// information in this translation unit.  Assumes that it is not a
37130b57cec5SDimitry Andric /// standard-library type.
37140b57cec5SDimitry Andric static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
37150b57cec5SDimitry Andric                                             QualType Ty) {
37160b57cec5SDimitry Andric   ASTContext &Context = CGM.getContext();
37170b57cec5SDimitry Andric 
37180b57cec5SDimitry Andric   // If RTTI is disabled, assume it might be disabled in the
37190b57cec5SDimitry Andric   // translation unit that defines any potential key function, too.
37200b57cec5SDimitry Andric   if (!Context.getLangOpts().RTTI) return false;
37210b57cec5SDimitry Andric 
37220b57cec5SDimitry Andric   if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
37230b57cec5SDimitry Andric     const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
37240b57cec5SDimitry Andric     if (!RD->hasDefinition())
37250b57cec5SDimitry Andric       return false;
37260b57cec5SDimitry Andric 
37270b57cec5SDimitry Andric     if (!RD->isDynamicClass())
37280b57cec5SDimitry Andric       return false;
37290b57cec5SDimitry Andric 
37300b57cec5SDimitry Andric     // FIXME: this may need to be reconsidered if the key function
37310b57cec5SDimitry Andric     // changes.
37320b57cec5SDimitry Andric     // N.B. We must always emit the RTTI data ourselves if there exists a key
37330b57cec5SDimitry Andric     // function.
37340b57cec5SDimitry Andric     bool IsDLLImport = RD->hasAttr<DLLImportAttr>();
37350b57cec5SDimitry Andric 
37360b57cec5SDimitry Andric     // Don't import the RTTI but emit it locally.
37370b57cec5SDimitry Andric     if (CGM.getTriple().isWindowsGNUEnvironment())
37380b57cec5SDimitry Andric       return false;
37390b57cec5SDimitry Andric 
3740fe6060f1SDimitry Andric     if (CGM.getVTables().isVTableExternal(RD)) {
3741fe6060f1SDimitry Andric       if (CGM.getTarget().hasPS4DLLImportExport())
3742fe6060f1SDimitry Andric         return true;
3743fe6060f1SDimitry Andric 
37440b57cec5SDimitry Andric       return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment()
37450b57cec5SDimitry Andric                  ? false
37460b57cec5SDimitry Andric                  : true;
3747fe6060f1SDimitry Andric     }
37480b57cec5SDimitry Andric     if (IsDLLImport)
37490b57cec5SDimitry Andric       return true;
37500b57cec5SDimitry Andric   }
37510b57cec5SDimitry Andric 
37520b57cec5SDimitry Andric   return false;
37530b57cec5SDimitry Andric }
37540b57cec5SDimitry Andric 
37550b57cec5SDimitry Andric /// IsIncompleteClassType - Returns whether the given record type is incomplete.
37560b57cec5SDimitry Andric static bool IsIncompleteClassType(const RecordType *RecordTy) {
37570b57cec5SDimitry Andric   return !RecordTy->getDecl()->isCompleteDefinition();
37580b57cec5SDimitry Andric }
37590b57cec5SDimitry Andric 
37600b57cec5SDimitry Andric /// ContainsIncompleteClassType - Returns whether the given type contains an
37610b57cec5SDimitry Andric /// incomplete class type. This is true if
37620b57cec5SDimitry Andric ///
37630b57cec5SDimitry Andric ///   * The given type is an incomplete class type.
37640b57cec5SDimitry Andric ///   * The given type is a pointer type whose pointee type contains an
37650b57cec5SDimitry Andric ///     incomplete class type.
37660b57cec5SDimitry Andric ///   * The given type is a member pointer type whose class is an incomplete
37670b57cec5SDimitry Andric ///     class type.
37680b57cec5SDimitry Andric ///   * The given type is a member pointer type whoise pointee type contains an
37690b57cec5SDimitry Andric ///     incomplete class type.
37700b57cec5SDimitry Andric /// is an indirect or direct pointer to an incomplete class type.
37710b57cec5SDimitry Andric static bool ContainsIncompleteClassType(QualType Ty) {
37720b57cec5SDimitry Andric   if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
37730b57cec5SDimitry Andric     if (IsIncompleteClassType(RecordTy))
37740b57cec5SDimitry Andric       return true;
37750b57cec5SDimitry Andric   }
37760b57cec5SDimitry Andric 
37770b57cec5SDimitry Andric   if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
37780b57cec5SDimitry Andric     return ContainsIncompleteClassType(PointerTy->getPointeeType());
37790b57cec5SDimitry Andric 
37800b57cec5SDimitry Andric   if (const MemberPointerType *MemberPointerTy =
37810b57cec5SDimitry Andric       dyn_cast<MemberPointerType>(Ty)) {
37820b57cec5SDimitry Andric     // Check if the class type is incomplete.
37830b57cec5SDimitry Andric     const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
37840b57cec5SDimitry Andric     if (IsIncompleteClassType(ClassType))
37850b57cec5SDimitry Andric       return true;
37860b57cec5SDimitry Andric 
37870b57cec5SDimitry Andric     return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
37880b57cec5SDimitry Andric   }
37890b57cec5SDimitry Andric 
37900b57cec5SDimitry Andric   return false;
37910b57cec5SDimitry Andric }
37920b57cec5SDimitry Andric 
37930b57cec5SDimitry Andric // CanUseSingleInheritance - Return whether the given record decl has a "single,
37940b57cec5SDimitry Andric // public, non-virtual base at offset zero (i.e. the derived class is dynamic
37950b57cec5SDimitry Andric // iff the base is)", according to Itanium C++ ABI, 2.95p6b.
37960b57cec5SDimitry Andric static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
37970b57cec5SDimitry Andric   // Check the number of bases.
37980b57cec5SDimitry Andric   if (RD->getNumBases() != 1)
37990b57cec5SDimitry Andric     return false;
38000b57cec5SDimitry Andric 
38010b57cec5SDimitry Andric   // Get the base.
38020b57cec5SDimitry Andric   CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
38030b57cec5SDimitry Andric 
38040b57cec5SDimitry Andric   // Check that the base is not virtual.
38050b57cec5SDimitry Andric   if (Base->isVirtual())
38060b57cec5SDimitry Andric     return false;
38070b57cec5SDimitry Andric 
38080b57cec5SDimitry Andric   // Check that the base is public.
38090b57cec5SDimitry Andric   if (Base->getAccessSpecifier() != AS_public)
38100b57cec5SDimitry Andric     return false;
38110b57cec5SDimitry Andric 
38120b57cec5SDimitry Andric   // Check that the class is dynamic iff the base is.
3813a7dea167SDimitry Andric   auto *BaseDecl =
3814a7dea167SDimitry Andric       cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
38150b57cec5SDimitry Andric   if (!BaseDecl->isEmpty() &&
38160b57cec5SDimitry Andric       BaseDecl->isDynamicClass() != RD->isDynamicClass())
38170b57cec5SDimitry Andric     return false;
38180b57cec5SDimitry Andric 
38190b57cec5SDimitry Andric   return true;
38200b57cec5SDimitry Andric }
38210b57cec5SDimitry Andric 
38220b57cec5SDimitry Andric void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
38230b57cec5SDimitry Andric   // abi::__class_type_info.
38240b57cec5SDimitry Andric   static const char * const ClassTypeInfo =
38250b57cec5SDimitry Andric     "_ZTVN10__cxxabiv117__class_type_infoE";
38260b57cec5SDimitry Andric   // abi::__si_class_type_info.
38270b57cec5SDimitry Andric   static const char * const SIClassTypeInfo =
38280b57cec5SDimitry Andric     "_ZTVN10__cxxabiv120__si_class_type_infoE";
38290b57cec5SDimitry Andric   // abi::__vmi_class_type_info.
38300b57cec5SDimitry Andric   static const char * const VMIClassTypeInfo =
38310b57cec5SDimitry Andric     "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
38320b57cec5SDimitry Andric 
38330b57cec5SDimitry Andric   const char *VTableName = nullptr;
38340b57cec5SDimitry Andric 
38350b57cec5SDimitry Andric   switch (Ty->getTypeClass()) {
38360b57cec5SDimitry Andric #define TYPE(Class, Base)
38370b57cec5SDimitry Andric #define ABSTRACT_TYPE(Class, Base)
38380b57cec5SDimitry Andric #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
38390b57cec5SDimitry Andric #define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
38400b57cec5SDimitry Andric #define DEPENDENT_TYPE(Class, Base) case Type::Class:
3841a7dea167SDimitry Andric #include "clang/AST/TypeNodes.inc"
38420b57cec5SDimitry Andric     llvm_unreachable("Non-canonical and dependent types shouldn't get here");
38430b57cec5SDimitry Andric 
38440b57cec5SDimitry Andric   case Type::LValueReference:
38450b57cec5SDimitry Andric   case Type::RValueReference:
38460b57cec5SDimitry Andric     llvm_unreachable("References shouldn't get here");
38470b57cec5SDimitry Andric 
38480b57cec5SDimitry Andric   case Type::Auto:
38490b57cec5SDimitry Andric   case Type::DeducedTemplateSpecialization:
38500b57cec5SDimitry Andric     llvm_unreachable("Undeduced type shouldn't get here");
38510b57cec5SDimitry Andric 
38520b57cec5SDimitry Andric   case Type::Pipe:
38530b57cec5SDimitry Andric     llvm_unreachable("Pipe types shouldn't get here");
38540b57cec5SDimitry Andric 
38550fca6ea1SDimitry Andric   case Type::ArrayParameter:
38560fca6ea1SDimitry Andric     llvm_unreachable("Array Parameter types should not get here.");
38570fca6ea1SDimitry Andric 
38580b57cec5SDimitry Andric   case Type::Builtin:
38590eae32dcSDimitry Andric   case Type::BitInt:
38600b57cec5SDimitry Andric   // GCC treats vector and complex types as fundamental types.
38610b57cec5SDimitry Andric   case Type::Vector:
38620b57cec5SDimitry Andric   case Type::ExtVector:
38635ffd83dbSDimitry Andric   case Type::ConstantMatrix:
38640b57cec5SDimitry Andric   case Type::Complex:
38650b57cec5SDimitry Andric   case Type::Atomic:
38660b57cec5SDimitry Andric   // FIXME: GCC treats block pointers as fundamental types?!
38670b57cec5SDimitry Andric   case Type::BlockPointer:
38680b57cec5SDimitry Andric     // abi::__fundamental_type_info.
38690b57cec5SDimitry Andric     VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
38700b57cec5SDimitry Andric     break;
38710b57cec5SDimitry Andric 
38720b57cec5SDimitry Andric   case Type::ConstantArray:
38730b57cec5SDimitry Andric   case Type::IncompleteArray:
38740b57cec5SDimitry Andric   case Type::VariableArray:
38750b57cec5SDimitry Andric     // abi::__array_type_info.
38760b57cec5SDimitry Andric     VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
38770b57cec5SDimitry Andric     break;
38780b57cec5SDimitry Andric 
38790b57cec5SDimitry Andric   case Type::FunctionNoProto:
38800b57cec5SDimitry Andric   case Type::FunctionProto:
38810b57cec5SDimitry Andric     // abi::__function_type_info.
38820b57cec5SDimitry Andric     VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
38830b57cec5SDimitry Andric     break;
38840b57cec5SDimitry Andric 
38850b57cec5SDimitry Andric   case Type::Enum:
38860b57cec5SDimitry Andric     // abi::__enum_type_info.
38870b57cec5SDimitry Andric     VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
38880b57cec5SDimitry Andric     break;
38890b57cec5SDimitry Andric 
38900b57cec5SDimitry Andric   case Type::Record: {
38910b57cec5SDimitry Andric     const CXXRecordDecl *RD =
38920b57cec5SDimitry Andric       cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
38930b57cec5SDimitry Andric 
38940b57cec5SDimitry Andric     if (!RD->hasDefinition() || !RD->getNumBases()) {
38950b57cec5SDimitry Andric       VTableName = ClassTypeInfo;
38960b57cec5SDimitry Andric     } else if (CanUseSingleInheritance(RD)) {
38970b57cec5SDimitry Andric       VTableName = SIClassTypeInfo;
38980b57cec5SDimitry Andric     } else {
38990b57cec5SDimitry Andric       VTableName = VMIClassTypeInfo;
39000b57cec5SDimitry Andric     }
39010b57cec5SDimitry Andric 
39020b57cec5SDimitry Andric     break;
39030b57cec5SDimitry Andric   }
39040b57cec5SDimitry Andric 
39050b57cec5SDimitry Andric   case Type::ObjCObject:
39060b57cec5SDimitry Andric     // Ignore protocol qualifiers.
39070b57cec5SDimitry Andric     Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
39080b57cec5SDimitry Andric 
39090b57cec5SDimitry Andric     // Handle id and Class.
39100b57cec5SDimitry Andric     if (isa<BuiltinType>(Ty)) {
39110b57cec5SDimitry Andric       VTableName = ClassTypeInfo;
39120b57cec5SDimitry Andric       break;
39130b57cec5SDimitry Andric     }
39140b57cec5SDimitry Andric 
39150b57cec5SDimitry Andric     assert(isa<ObjCInterfaceType>(Ty));
3916bdd1243dSDimitry Andric     [[fallthrough]];
39170b57cec5SDimitry Andric 
39180b57cec5SDimitry Andric   case Type::ObjCInterface:
39190b57cec5SDimitry Andric     if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
39200b57cec5SDimitry Andric       VTableName = SIClassTypeInfo;
39210b57cec5SDimitry Andric     } else {
39220b57cec5SDimitry Andric       VTableName = ClassTypeInfo;
39230b57cec5SDimitry Andric     }
39240b57cec5SDimitry Andric     break;
39250b57cec5SDimitry Andric 
39260b57cec5SDimitry Andric   case Type::ObjCObjectPointer:
39270b57cec5SDimitry Andric   case Type::Pointer:
39280b57cec5SDimitry Andric     // abi::__pointer_type_info.
39290b57cec5SDimitry Andric     VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
39300b57cec5SDimitry Andric     break;
39310b57cec5SDimitry Andric 
39320b57cec5SDimitry Andric   case Type::MemberPointer:
39330b57cec5SDimitry Andric     // abi::__pointer_to_member_type_info.
39340b57cec5SDimitry Andric     VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
39350b57cec5SDimitry Andric     break;
39360b57cec5SDimitry Andric   }
39370b57cec5SDimitry Andric 
39385ffd83dbSDimitry Andric   llvm::Constant *VTable = nullptr;
39395ffd83dbSDimitry Andric 
39405ffd83dbSDimitry Andric   // Check if the alias exists. If it doesn't, then get or create the global.
39415ffd83dbSDimitry Andric   if (CGM.getItaniumVTableContext().isRelativeLayout())
39425ffd83dbSDimitry Andric     VTable = CGM.getModule().getNamedAlias(VTableName);
39435f757f3fSDimitry Andric   if (!VTable) {
39445f757f3fSDimitry Andric     llvm::Type *Ty = llvm::ArrayType::get(CGM.GlobalsInt8PtrTy, 0);
39455f757f3fSDimitry Andric     VTable = CGM.getModule().getOrInsertGlobal(VTableName, Ty);
39465f757f3fSDimitry Andric   }
39475ffd83dbSDimitry Andric 
39480b57cec5SDimitry Andric   CGM.setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
39490b57cec5SDimitry Andric 
39500b57cec5SDimitry Andric   llvm::Type *PtrDiffTy =
39510b57cec5SDimitry Andric       CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
39520b57cec5SDimitry Andric 
39530b57cec5SDimitry Andric   // The vtable address point is 2.
39545ffd83dbSDimitry Andric   if (CGM.getItaniumVTableContext().isRelativeLayout()) {
39555ffd83dbSDimitry Andric     // The vtable address point is 8 bytes after its start:
39565ffd83dbSDimitry Andric     // 4 for the offset to top + 4 for the relative offset to rtti.
39575ffd83dbSDimitry Andric     llvm::Constant *Eight = llvm::ConstantInt::get(CGM.Int32Ty, 8);
39580b57cec5SDimitry Andric     VTable =
39595ffd83dbSDimitry Andric         llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8Ty, VTable, Eight);
39605ffd83dbSDimitry Andric   } else {
39615ffd83dbSDimitry Andric     llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
396206c3fb27SDimitry Andric     VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.GlobalsInt8PtrTy,
396306c3fb27SDimitry Andric                                                           VTable, Two);
39645ffd83dbSDimitry Andric   }
39650b57cec5SDimitry Andric 
39660fca6ea1SDimitry Andric   if (auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer)
39670fca6ea1SDimitry Andric     VTable = CGM.getConstantSignedPointer(VTable, Schema, nullptr, GlobalDecl(),
39680fca6ea1SDimitry Andric                                           QualType(Ty, 0));
39690fca6ea1SDimitry Andric 
39700b57cec5SDimitry Andric   Fields.push_back(VTable);
39710b57cec5SDimitry Andric }
39720b57cec5SDimitry Andric 
39730b57cec5SDimitry Andric /// Return the linkage that the type info and type info name constants
39740b57cec5SDimitry Andric /// should have for the given type.
39750b57cec5SDimitry Andric static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
39760b57cec5SDimitry Andric                                                              QualType Ty) {
39770b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p7:
39780b57cec5SDimitry Andric   //   In addition, it and all of the intermediate abi::__pointer_type_info
39790b57cec5SDimitry Andric   //   structs in the chain down to the abi::__class_type_info for the
39800b57cec5SDimitry Andric   //   incomplete class type must be prevented from resolving to the
39810b57cec5SDimitry Andric   //   corresponding type_info structs for the complete class type, possibly
39820b57cec5SDimitry Andric   //   by making them local static objects. Finally, a dummy class RTTI is
39830b57cec5SDimitry Andric   //   generated for the incomplete type that will not resolve to the final
39840b57cec5SDimitry Andric   //   complete class RTTI (because the latter need not exist), possibly by
39850b57cec5SDimitry Andric   //   making it a local static object.
39860b57cec5SDimitry Andric   if (ContainsIncompleteClassType(Ty))
39870b57cec5SDimitry Andric     return llvm::GlobalValue::InternalLinkage;
39880b57cec5SDimitry Andric 
39890b57cec5SDimitry Andric   switch (Ty->getLinkage()) {
39905f757f3fSDimitry Andric   case Linkage::Invalid:
39915f757f3fSDimitry Andric     llvm_unreachable("Linkage hasn't been computed!");
39925f757f3fSDimitry Andric 
39935f757f3fSDimitry Andric   case Linkage::None:
39945f757f3fSDimitry Andric   case Linkage::Internal:
39955f757f3fSDimitry Andric   case Linkage::UniqueExternal:
39960b57cec5SDimitry Andric     return llvm::GlobalValue::InternalLinkage;
39970b57cec5SDimitry Andric 
39985f757f3fSDimitry Andric   case Linkage::VisibleNone:
39995f757f3fSDimitry Andric   case Linkage::Module:
40005f757f3fSDimitry Andric   case Linkage::External:
40010b57cec5SDimitry Andric     // RTTI is not enabled, which means that this type info struct is going
40020b57cec5SDimitry Andric     // to be used for exception handling. Give it linkonce_odr linkage.
40030b57cec5SDimitry Andric     if (!CGM.getLangOpts().RTTI)
40040b57cec5SDimitry Andric       return llvm::GlobalValue::LinkOnceODRLinkage;
40050b57cec5SDimitry Andric 
40060b57cec5SDimitry Andric     if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
40070b57cec5SDimitry Andric       const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
40080b57cec5SDimitry Andric       if (RD->hasAttr<WeakAttr>())
40090b57cec5SDimitry Andric         return llvm::GlobalValue::WeakODRLinkage;
40100b57cec5SDimitry Andric       if (CGM.getTriple().isWindowsItaniumEnvironment())
40110b57cec5SDimitry Andric         if (RD->hasAttr<DLLImportAttr>() &&
40120b57cec5SDimitry Andric             ShouldUseExternalRTTIDescriptor(CGM, Ty))
40130b57cec5SDimitry Andric           return llvm::GlobalValue::ExternalLinkage;
40140b57cec5SDimitry Andric       // MinGW always uses LinkOnceODRLinkage for type info.
40150b57cec5SDimitry Andric       if (RD->isDynamicClass() &&
40160b57cec5SDimitry Andric           !CGM.getContext()
40170b57cec5SDimitry Andric                .getTargetInfo()
40180b57cec5SDimitry Andric                .getTriple()
40190b57cec5SDimitry Andric                .isWindowsGNUEnvironment())
40200b57cec5SDimitry Andric         return CGM.getVTableLinkage(RD);
40210b57cec5SDimitry Andric     }
40220b57cec5SDimitry Andric 
40230b57cec5SDimitry Andric     return llvm::GlobalValue::LinkOnceODRLinkage;
40240b57cec5SDimitry Andric   }
40250b57cec5SDimitry Andric 
40260b57cec5SDimitry Andric   llvm_unreachable("Invalid linkage!");
40270b57cec5SDimitry Andric }
40280b57cec5SDimitry Andric 
40290b57cec5SDimitry Andric llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
40300b57cec5SDimitry Andric   // We want to operate on the canonical type.
40310b57cec5SDimitry Andric   Ty = Ty.getCanonicalType();
40320b57cec5SDimitry Andric 
40330b57cec5SDimitry Andric   // Check if we've already emitted an RTTI descriptor for this type.
40340b57cec5SDimitry Andric   SmallString<256> Name;
40350b57cec5SDimitry Andric   llvm::raw_svector_ostream Out(Name);
40360b57cec5SDimitry Andric   CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
40370b57cec5SDimitry Andric 
40380b57cec5SDimitry Andric   llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
40390b57cec5SDimitry Andric   if (OldGV && !OldGV->isDeclaration()) {
40400b57cec5SDimitry Andric     assert(!OldGV->hasAvailableExternallyLinkage() &&
40410b57cec5SDimitry Andric            "available_externally typeinfos not yet implemented");
40420b57cec5SDimitry Andric 
404306c3fb27SDimitry Andric     return OldGV;
40440b57cec5SDimitry Andric   }
40450b57cec5SDimitry Andric 
40460b57cec5SDimitry Andric   // Check if there is already an external RTTI descriptor for this type.
40470b57cec5SDimitry Andric   if (IsStandardLibraryRTTIDescriptor(Ty) ||
40480b57cec5SDimitry Andric       ShouldUseExternalRTTIDescriptor(CGM, Ty))
40490b57cec5SDimitry Andric     return GetAddrOfExternalRTTIDescriptor(Ty);
40500b57cec5SDimitry Andric 
40510b57cec5SDimitry Andric   // Emit the standard library with external linkage.
40520b57cec5SDimitry Andric   llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);
40530b57cec5SDimitry Andric 
40540b57cec5SDimitry Andric   // Give the type_info object and name the formal visibility of the
40550b57cec5SDimitry Andric   // type itself.
40560b57cec5SDimitry Andric   llvm::GlobalValue::VisibilityTypes llvmVisibility;
40570b57cec5SDimitry Andric   if (llvm::GlobalValue::isLocalLinkage(Linkage))
40580b57cec5SDimitry Andric     // If the linkage is local, only default visibility makes sense.
40590b57cec5SDimitry Andric     llvmVisibility = llvm::GlobalValue::DefaultVisibility;
40600b57cec5SDimitry Andric   else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) ==
40610b57cec5SDimitry Andric            ItaniumCXXABI::RUK_NonUniqueHidden)
40620b57cec5SDimitry Andric     llvmVisibility = llvm::GlobalValue::HiddenVisibility;
40630b57cec5SDimitry Andric   else
40640b57cec5SDimitry Andric     llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
40650b57cec5SDimitry Andric 
40660b57cec5SDimitry Andric   llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
40670b57cec5SDimitry Andric       llvm::GlobalValue::DefaultStorageClass;
406881ad6265SDimitry Andric   if (auto RD = Ty->getAsCXXRecordDecl()) {
406981ad6265SDimitry Andric     if ((CGM.getTriple().isWindowsItaniumEnvironment() &&
407081ad6265SDimitry Andric          RD->hasAttr<DLLExportAttr>()) ||
407181ad6265SDimitry Andric         (CGM.shouldMapVisibilityToDLLExport(RD) &&
407281ad6265SDimitry Andric          !llvm::GlobalValue::isLocalLinkage(Linkage) &&
407381ad6265SDimitry Andric          llvmVisibility == llvm::GlobalValue::DefaultVisibility))
40740b57cec5SDimitry Andric       DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
40750b57cec5SDimitry Andric   }
40760b57cec5SDimitry Andric   return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass);
40770b57cec5SDimitry Andric }
40780b57cec5SDimitry Andric 
40790b57cec5SDimitry Andric llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
40800b57cec5SDimitry Andric       QualType Ty,
40810b57cec5SDimitry Andric       llvm::GlobalVariable::LinkageTypes Linkage,
40820b57cec5SDimitry Andric       llvm::GlobalValue::VisibilityTypes Visibility,
40830b57cec5SDimitry Andric       llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
40840b57cec5SDimitry Andric   // Add the vtable pointer.
40850b57cec5SDimitry Andric   BuildVTablePointer(cast<Type>(Ty));
40860b57cec5SDimitry Andric 
40870b57cec5SDimitry Andric   // And the name.
40880b57cec5SDimitry Andric   llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
40890b57cec5SDimitry Andric   llvm::Constant *TypeNameField;
40900b57cec5SDimitry Andric 
40910b57cec5SDimitry Andric   // If we're supposed to demote the visibility, be sure to set a flag
40920b57cec5SDimitry Andric   // to use a string comparison for type_info comparisons.
40930b57cec5SDimitry Andric   ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =
40940b57cec5SDimitry Andric       CXXABI.classifyRTTIUniqueness(Ty, Linkage);
40950b57cec5SDimitry Andric   if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {
40960b57cec5SDimitry Andric     // The flag is the sign bit, which on ARM64 is defined to be clear
40970b57cec5SDimitry Andric     // for global pointers.  This is very ARM64-specific.
40980b57cec5SDimitry Andric     TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty);
40990b57cec5SDimitry Andric     llvm::Constant *flag =
41000b57cec5SDimitry Andric         llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63);
41010b57cec5SDimitry Andric     TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
41020b57cec5SDimitry Andric     TypeNameField =
410306c3fb27SDimitry Andric         llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.GlobalsInt8PtrTy);
41040b57cec5SDimitry Andric   } else {
410506c3fb27SDimitry Andric     TypeNameField = TypeName;
41060b57cec5SDimitry Andric   }
41070b57cec5SDimitry Andric   Fields.push_back(TypeNameField);
41080b57cec5SDimitry Andric 
41090b57cec5SDimitry Andric   switch (Ty->getTypeClass()) {
41100b57cec5SDimitry Andric #define TYPE(Class, Base)
41110b57cec5SDimitry Andric #define ABSTRACT_TYPE(Class, Base)
41120b57cec5SDimitry Andric #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
41130b57cec5SDimitry Andric #define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
41140b57cec5SDimitry Andric #define DEPENDENT_TYPE(Class, Base) case Type::Class:
4115a7dea167SDimitry Andric #include "clang/AST/TypeNodes.inc"
41160b57cec5SDimitry Andric     llvm_unreachable("Non-canonical and dependent types shouldn't get here");
41170b57cec5SDimitry Andric 
41180b57cec5SDimitry Andric   // GCC treats vector types as fundamental types.
41190b57cec5SDimitry Andric   case Type::Builtin:
41200b57cec5SDimitry Andric   case Type::Vector:
41210b57cec5SDimitry Andric   case Type::ExtVector:
41225ffd83dbSDimitry Andric   case Type::ConstantMatrix:
41230b57cec5SDimitry Andric   case Type::Complex:
41240b57cec5SDimitry Andric   case Type::BlockPointer:
41250b57cec5SDimitry Andric     // Itanium C++ ABI 2.9.5p4:
41260b57cec5SDimitry Andric     // abi::__fundamental_type_info adds no data members to std::type_info.
41270b57cec5SDimitry Andric     break;
41280b57cec5SDimitry Andric 
41290b57cec5SDimitry Andric   case Type::LValueReference:
41300b57cec5SDimitry Andric   case Type::RValueReference:
41310b57cec5SDimitry Andric     llvm_unreachable("References shouldn't get here");
41320b57cec5SDimitry Andric 
41330b57cec5SDimitry Andric   case Type::Auto:
41340b57cec5SDimitry Andric   case Type::DeducedTemplateSpecialization:
41350b57cec5SDimitry Andric     llvm_unreachable("Undeduced type shouldn't get here");
41360b57cec5SDimitry Andric 
41370b57cec5SDimitry Andric   case Type::Pipe:
41385ffd83dbSDimitry Andric     break;
41395ffd83dbSDimitry Andric 
41400eae32dcSDimitry Andric   case Type::BitInt:
41415ffd83dbSDimitry Andric     break;
41420b57cec5SDimitry Andric 
41430b57cec5SDimitry Andric   case Type::ConstantArray:
41440b57cec5SDimitry Andric   case Type::IncompleteArray:
41450b57cec5SDimitry Andric   case Type::VariableArray:
41460fca6ea1SDimitry Andric   case Type::ArrayParameter:
41470b57cec5SDimitry Andric     // Itanium C++ ABI 2.9.5p5:
41480b57cec5SDimitry Andric     // abi::__array_type_info adds no data members to std::type_info.
41490b57cec5SDimitry Andric     break;
41500b57cec5SDimitry Andric 
41510b57cec5SDimitry Andric   case Type::FunctionNoProto:
41520b57cec5SDimitry Andric   case Type::FunctionProto:
41530b57cec5SDimitry Andric     // Itanium C++ ABI 2.9.5p5:
41540b57cec5SDimitry Andric     // abi::__function_type_info adds no data members to std::type_info.
41550b57cec5SDimitry Andric     break;
41560b57cec5SDimitry Andric 
41570b57cec5SDimitry Andric   case Type::Enum:
41580b57cec5SDimitry Andric     // Itanium C++ ABI 2.9.5p5:
41590b57cec5SDimitry Andric     // abi::__enum_type_info adds no data members to std::type_info.
41600b57cec5SDimitry Andric     break;
41610b57cec5SDimitry Andric 
41620b57cec5SDimitry Andric   case Type::Record: {
41630b57cec5SDimitry Andric     const CXXRecordDecl *RD =
41640b57cec5SDimitry Andric       cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
41650b57cec5SDimitry Andric     if (!RD->hasDefinition() || !RD->getNumBases()) {
41660b57cec5SDimitry Andric       // We don't need to emit any fields.
41670b57cec5SDimitry Andric       break;
41680b57cec5SDimitry Andric     }
41690b57cec5SDimitry Andric 
41700b57cec5SDimitry Andric     if (CanUseSingleInheritance(RD))
41710b57cec5SDimitry Andric       BuildSIClassTypeInfo(RD);
41720b57cec5SDimitry Andric     else
41730b57cec5SDimitry Andric       BuildVMIClassTypeInfo(RD);
41740b57cec5SDimitry Andric 
41750b57cec5SDimitry Andric     break;
41760b57cec5SDimitry Andric   }
41770b57cec5SDimitry Andric 
41780b57cec5SDimitry Andric   case Type::ObjCObject:
41790b57cec5SDimitry Andric   case Type::ObjCInterface:
41800b57cec5SDimitry Andric     BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
41810b57cec5SDimitry Andric     break;
41820b57cec5SDimitry Andric 
41830b57cec5SDimitry Andric   case Type::ObjCObjectPointer:
41840b57cec5SDimitry Andric     BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
41850b57cec5SDimitry Andric     break;
41860b57cec5SDimitry Andric 
41870b57cec5SDimitry Andric   case Type::Pointer:
41880b57cec5SDimitry Andric     BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
41890b57cec5SDimitry Andric     break;
41900b57cec5SDimitry Andric 
41910b57cec5SDimitry Andric   case Type::MemberPointer:
41920b57cec5SDimitry Andric     BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
41930b57cec5SDimitry Andric     break;
41940b57cec5SDimitry Andric 
41950b57cec5SDimitry Andric   case Type::Atomic:
41960b57cec5SDimitry Andric     // No fields, at least for the moment.
41970b57cec5SDimitry Andric     break;
41980b57cec5SDimitry Andric   }
41990b57cec5SDimitry Andric 
42000b57cec5SDimitry Andric   llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
42010b57cec5SDimitry Andric 
42020b57cec5SDimitry Andric   SmallString<256> Name;
42030b57cec5SDimitry Andric   llvm::raw_svector_ostream Out(Name);
42040b57cec5SDimitry Andric   CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
42050b57cec5SDimitry Andric   llvm::Module &M = CGM.getModule();
42060b57cec5SDimitry Andric   llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
42070b57cec5SDimitry Andric   llvm::GlobalVariable *GV =
42080b57cec5SDimitry Andric       new llvm::GlobalVariable(M, Init->getType(),
42090b57cec5SDimitry Andric                                /*isConstant=*/true, Linkage, Init, Name);
42100b57cec5SDimitry Andric 
4211fe6060f1SDimitry Andric   // Export the typeinfo in the same circumstances as the vtable is exported.
4212fe6060f1SDimitry Andric   auto GVDLLStorageClass = DLLStorageClass;
42130fca6ea1SDimitry Andric   if (CGM.getTarget().hasPS4DLLImportExport() &&
42140fca6ea1SDimitry Andric       GVDLLStorageClass != llvm::GlobalVariable::DLLExportStorageClass) {
4215fe6060f1SDimitry Andric     if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
4216fe6060f1SDimitry Andric       const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
4217fe6060f1SDimitry Andric       if (RD->hasAttr<DLLExportAttr>() ||
42180fca6ea1SDimitry Andric           CXXRecordNonInlineHasAttr<DLLExportAttr>(RD))
4219fe6060f1SDimitry Andric         GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
4220fe6060f1SDimitry Andric     }
4221fe6060f1SDimitry Andric   }
4222fe6060f1SDimitry Andric 
42230b57cec5SDimitry Andric   // If there's already an old global variable, replace it with the new one.
42240b57cec5SDimitry Andric   if (OldGV) {
42250b57cec5SDimitry Andric     GV->takeName(OldGV);
42265f757f3fSDimitry Andric     OldGV->replaceAllUsesWith(GV);
42270b57cec5SDimitry Andric     OldGV->eraseFromParent();
42280b57cec5SDimitry Andric   }
42290b57cec5SDimitry Andric 
42300b57cec5SDimitry Andric   if (CGM.supportsCOMDAT() && GV->isWeakForLinker())
42310b57cec5SDimitry Andric     GV->setComdat(M.getOrInsertComdat(GV->getName()));
42320b57cec5SDimitry Andric 
4233bdd1243dSDimitry Andric   CharUnits Align = CGM.getContext().toCharUnitsFromBits(
423406c3fb27SDimitry Andric       CGM.getTarget().getPointerAlign(CGM.GetGlobalVarAddressSpace(nullptr)));
4235a7dea167SDimitry Andric   GV->setAlignment(Align.getAsAlign());
42360b57cec5SDimitry Andric 
42370b57cec5SDimitry Andric   // The Itanium ABI specifies that type_info objects must be globally
42380b57cec5SDimitry Andric   // unique, with one exception: if the type is an incomplete class
42390b57cec5SDimitry Andric   // type or a (possibly indirect) pointer to one.  That exception
42400b57cec5SDimitry Andric   // affects the general case of comparing type_info objects produced
42410b57cec5SDimitry Andric   // by the typeid operator, which is why the comparison operators on
42420b57cec5SDimitry Andric   // std::type_info generally use the type_info name pointers instead
42430b57cec5SDimitry Andric   // of the object addresses.  However, the language's built-in uses
42440b57cec5SDimitry Andric   // of RTTI generally require class types to be complete, even when
42450b57cec5SDimitry Andric   // manipulating pointers to those class types.  This allows the
42460b57cec5SDimitry Andric   // implementation of dynamic_cast to rely on address equality tests,
42470b57cec5SDimitry Andric   // which is much faster.
42480b57cec5SDimitry Andric 
42490b57cec5SDimitry Andric   // All of this is to say that it's important that both the type_info
42500b57cec5SDimitry Andric   // object and the type_info name be uniqued when weakly emitted.
42510b57cec5SDimitry Andric 
42520b57cec5SDimitry Andric   TypeName->setVisibility(Visibility);
42530b57cec5SDimitry Andric   CGM.setDSOLocal(TypeName);
42540b57cec5SDimitry Andric 
42550b57cec5SDimitry Andric   GV->setVisibility(Visibility);
42560b57cec5SDimitry Andric   CGM.setDSOLocal(GV);
42570b57cec5SDimitry Andric 
42580b57cec5SDimitry Andric   TypeName->setDLLStorageClass(DLLStorageClass);
42590fca6ea1SDimitry Andric   GV->setDLLStorageClass(GVDLLStorageClass);
42600b57cec5SDimitry Andric 
42610b57cec5SDimitry Andric   TypeName->setPartition(CGM.getCodeGenOpts().SymbolPartition);
42620b57cec5SDimitry Andric   GV->setPartition(CGM.getCodeGenOpts().SymbolPartition);
42630b57cec5SDimitry Andric 
426406c3fb27SDimitry Andric   return GV;
42650b57cec5SDimitry Andric }
42660b57cec5SDimitry Andric 
42670b57cec5SDimitry Andric /// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
42680b57cec5SDimitry Andric /// for the given Objective-C object type.
42690b57cec5SDimitry Andric void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
42700b57cec5SDimitry Andric   // Drop qualifiers.
42710b57cec5SDimitry Andric   const Type *T = OT->getBaseType().getTypePtr();
42720b57cec5SDimitry Andric   assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
42730b57cec5SDimitry Andric 
42740b57cec5SDimitry Andric   // The builtin types are abi::__class_type_infos and don't require
42750b57cec5SDimitry Andric   // extra fields.
42760b57cec5SDimitry Andric   if (isa<BuiltinType>(T)) return;
42770b57cec5SDimitry Andric 
42780b57cec5SDimitry Andric   ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
42790b57cec5SDimitry Andric   ObjCInterfaceDecl *Super = Class->getSuperClass();
42800b57cec5SDimitry Andric 
42810b57cec5SDimitry Andric   // Root classes are also __class_type_info.
42820b57cec5SDimitry Andric   if (!Super) return;
42830b57cec5SDimitry Andric 
42840b57cec5SDimitry Andric   QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
42850b57cec5SDimitry Andric 
42860b57cec5SDimitry Andric   // Everything else is single inheritance.
42870b57cec5SDimitry Andric   llvm::Constant *BaseTypeInfo =
42880b57cec5SDimitry Andric       ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(SuperTy);
42890b57cec5SDimitry Andric   Fields.push_back(BaseTypeInfo);
42900b57cec5SDimitry Andric }
42910b57cec5SDimitry Andric 
42920b57cec5SDimitry Andric /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
42930b57cec5SDimitry Andric /// inheritance, according to the Itanium C++ ABI, 2.95p6b.
42940b57cec5SDimitry Andric void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
42950b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p6b:
42960b57cec5SDimitry Andric   // It adds to abi::__class_type_info a single member pointing to the
42970b57cec5SDimitry Andric   // type_info structure for the base type,
42980b57cec5SDimitry Andric   llvm::Constant *BaseTypeInfo =
42990b57cec5SDimitry Andric     ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType());
43000b57cec5SDimitry Andric   Fields.push_back(BaseTypeInfo);
43010b57cec5SDimitry Andric }
43020b57cec5SDimitry Andric 
43030b57cec5SDimitry Andric namespace {
43040b57cec5SDimitry Andric   /// SeenBases - Contains virtual and non-virtual bases seen when traversing
43050b57cec5SDimitry Andric   /// a class hierarchy.
43060b57cec5SDimitry Andric   struct SeenBases {
43070b57cec5SDimitry Andric     llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
43080b57cec5SDimitry Andric     llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
43090b57cec5SDimitry Andric   };
43100b57cec5SDimitry Andric }
43110b57cec5SDimitry Andric 
43120b57cec5SDimitry Andric /// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
43130b57cec5SDimitry Andric /// abi::__vmi_class_type_info.
43140b57cec5SDimitry Andric ///
43150b57cec5SDimitry Andric static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
43160b57cec5SDimitry Andric                                              SeenBases &Bases) {
43170b57cec5SDimitry Andric 
43180b57cec5SDimitry Andric   unsigned Flags = 0;
43190b57cec5SDimitry Andric 
4320a7dea167SDimitry Andric   auto *BaseDecl =
4321a7dea167SDimitry Andric       cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
43220b57cec5SDimitry Andric 
43230b57cec5SDimitry Andric   if (Base->isVirtual()) {
43240b57cec5SDimitry Andric     // Mark the virtual base as seen.
43250b57cec5SDimitry Andric     if (!Bases.VirtualBases.insert(BaseDecl).second) {
43260b57cec5SDimitry Andric       // If this virtual base has been seen before, then the class is diamond
43270b57cec5SDimitry Andric       // shaped.
43280b57cec5SDimitry Andric       Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
43290b57cec5SDimitry Andric     } else {
43300b57cec5SDimitry Andric       if (Bases.NonVirtualBases.count(BaseDecl))
43310b57cec5SDimitry Andric         Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
43320b57cec5SDimitry Andric     }
43330b57cec5SDimitry Andric   } else {
43340b57cec5SDimitry Andric     // Mark the non-virtual base as seen.
43350b57cec5SDimitry Andric     if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
43360b57cec5SDimitry Andric       // If this non-virtual base has been seen before, then the class has non-
43370b57cec5SDimitry Andric       // diamond shaped repeated inheritance.
43380b57cec5SDimitry Andric       Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
43390b57cec5SDimitry Andric     } else {
43400b57cec5SDimitry Andric       if (Bases.VirtualBases.count(BaseDecl))
43410b57cec5SDimitry Andric         Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
43420b57cec5SDimitry Andric     }
43430b57cec5SDimitry Andric   }
43440b57cec5SDimitry Andric 
43450b57cec5SDimitry Andric   // Walk all bases.
43460b57cec5SDimitry Andric   for (const auto &I : BaseDecl->bases())
43470b57cec5SDimitry Andric     Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
43480b57cec5SDimitry Andric 
43490b57cec5SDimitry Andric   return Flags;
43500b57cec5SDimitry Andric }
43510b57cec5SDimitry Andric 
43520b57cec5SDimitry Andric static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
43530b57cec5SDimitry Andric   unsigned Flags = 0;
43540b57cec5SDimitry Andric   SeenBases Bases;
43550b57cec5SDimitry Andric 
43560b57cec5SDimitry Andric   // Walk all bases.
43570b57cec5SDimitry Andric   for (const auto &I : RD->bases())
43580b57cec5SDimitry Andric     Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
43590b57cec5SDimitry Andric 
43600b57cec5SDimitry Andric   return Flags;
43610b57cec5SDimitry Andric }
43620b57cec5SDimitry Andric 
43630b57cec5SDimitry Andric /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
43640b57cec5SDimitry Andric /// classes with bases that do not satisfy the abi::__si_class_type_info
43650b57cec5SDimitry Andric /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
43660b57cec5SDimitry Andric void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
43670b57cec5SDimitry Andric   llvm::Type *UnsignedIntLTy =
43680b57cec5SDimitry Andric     CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
43690b57cec5SDimitry Andric 
43700b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p6c:
43710b57cec5SDimitry Andric   //   __flags is a word with flags describing details about the class
43720b57cec5SDimitry Andric   //   structure, which may be referenced by using the __flags_masks
43730b57cec5SDimitry Andric   //   enumeration. These flags refer to both direct and indirect bases.
43740b57cec5SDimitry Andric   unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);
43750b57cec5SDimitry Andric   Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
43760b57cec5SDimitry Andric 
43770b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p6c:
43780b57cec5SDimitry Andric   //   __base_count is a word with the number of direct proper base class
43790b57cec5SDimitry Andric   //   descriptions that follow.
43800b57cec5SDimitry Andric   Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
43810b57cec5SDimitry Andric 
43820b57cec5SDimitry Andric   if (!RD->getNumBases())
43830b57cec5SDimitry Andric     return;
43840b57cec5SDimitry Andric 
43850b57cec5SDimitry Andric   // Now add the base class descriptions.
43860b57cec5SDimitry Andric 
43870b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p6c:
43880b57cec5SDimitry Andric   //   __base_info[] is an array of base class descriptions -- one for every
43890b57cec5SDimitry Andric   //   direct proper base. Each description is of the type:
43900b57cec5SDimitry Andric   //
43910b57cec5SDimitry Andric   //   struct abi::__base_class_type_info {
43920b57cec5SDimitry Andric   //   public:
43930b57cec5SDimitry Andric   //     const __class_type_info *__base_type;
43940b57cec5SDimitry Andric   //     long __offset_flags;
43950b57cec5SDimitry Andric   //
43960b57cec5SDimitry Andric   //     enum __offset_flags_masks {
43970b57cec5SDimitry Andric   //       __virtual_mask = 0x1,
43980b57cec5SDimitry Andric   //       __public_mask = 0x2,
43990b57cec5SDimitry Andric   //       __offset_shift = 8
44000b57cec5SDimitry Andric   //     };
44010b57cec5SDimitry Andric   //   };
44020b57cec5SDimitry Andric 
44030b57cec5SDimitry Andric   // If we're in mingw and 'long' isn't wide enough for a pointer, use 'long
44040b57cec5SDimitry Andric   // long' instead of 'long' for __offset_flags. libstdc++abi uses long long on
44050b57cec5SDimitry Andric   // LLP64 platforms.
44060b57cec5SDimitry Andric   // FIXME: Consider updating libc++abi to match, and extend this logic to all
44070b57cec5SDimitry Andric   // LLP64 platforms.
44080b57cec5SDimitry Andric   QualType OffsetFlagsTy = CGM.getContext().LongTy;
44090b57cec5SDimitry Andric   const TargetInfo &TI = CGM.getContext().getTargetInfo();
4410bdd1243dSDimitry Andric   if (TI.getTriple().isOSCygMing() &&
4411bdd1243dSDimitry Andric       TI.getPointerWidth(LangAS::Default) > TI.getLongWidth())
44120b57cec5SDimitry Andric     OffsetFlagsTy = CGM.getContext().LongLongTy;
44130b57cec5SDimitry Andric   llvm::Type *OffsetFlagsLTy =
44140b57cec5SDimitry Andric       CGM.getTypes().ConvertType(OffsetFlagsTy);
44150b57cec5SDimitry Andric 
44160b57cec5SDimitry Andric   for (const auto &Base : RD->bases()) {
44170b57cec5SDimitry Andric     // The __base_type member points to the RTTI for the base type.
44180b57cec5SDimitry Andric     Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));
44190b57cec5SDimitry Andric 
4420a7dea167SDimitry Andric     auto *BaseDecl =
4421a7dea167SDimitry Andric         cast<CXXRecordDecl>(Base.getType()->castAs<RecordType>()->getDecl());
44220b57cec5SDimitry Andric 
44230b57cec5SDimitry Andric     int64_t OffsetFlags = 0;
44240b57cec5SDimitry Andric 
44250b57cec5SDimitry Andric     // All but the lower 8 bits of __offset_flags are a signed offset.
44260b57cec5SDimitry Andric     // For a non-virtual base, this is the offset in the object of the base
44270b57cec5SDimitry Andric     // subobject. For a virtual base, this is the offset in the virtual table of
44280b57cec5SDimitry Andric     // the virtual base offset for the virtual base referenced (negative).
44290b57cec5SDimitry Andric     CharUnits Offset;
44300b57cec5SDimitry Andric     if (Base.isVirtual())
44310b57cec5SDimitry Andric       Offset =
44320b57cec5SDimitry Andric         CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
44330b57cec5SDimitry Andric     else {
44340b57cec5SDimitry Andric       const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
44350b57cec5SDimitry Andric       Offset = Layout.getBaseClassOffset(BaseDecl);
44360b57cec5SDimitry Andric     };
44370b57cec5SDimitry Andric 
44380b57cec5SDimitry Andric     OffsetFlags = uint64_t(Offset.getQuantity()) << 8;
44390b57cec5SDimitry Andric 
44400b57cec5SDimitry Andric     // The low-order byte of __offset_flags contains flags, as given by the
44410b57cec5SDimitry Andric     // masks from the enumeration __offset_flags_masks.
44420b57cec5SDimitry Andric     if (Base.isVirtual())
44430b57cec5SDimitry Andric       OffsetFlags |= BCTI_Virtual;
44440b57cec5SDimitry Andric     if (Base.getAccessSpecifier() == AS_public)
44450b57cec5SDimitry Andric       OffsetFlags |= BCTI_Public;
44460b57cec5SDimitry Andric 
44470b57cec5SDimitry Andric     Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags));
44480b57cec5SDimitry Andric   }
44490b57cec5SDimitry Andric }
44500b57cec5SDimitry Andric 
44510b57cec5SDimitry Andric /// Compute the flags for a __pbase_type_info, and remove the corresponding
44520b57cec5SDimitry Andric /// pieces from \p Type.
44530b57cec5SDimitry Andric static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) {
44540b57cec5SDimitry Andric   unsigned Flags = 0;
44550b57cec5SDimitry Andric 
44560b57cec5SDimitry Andric   if (Type.isConstQualified())
44570b57cec5SDimitry Andric     Flags |= ItaniumRTTIBuilder::PTI_Const;
44580b57cec5SDimitry Andric   if (Type.isVolatileQualified())
44590b57cec5SDimitry Andric     Flags |= ItaniumRTTIBuilder::PTI_Volatile;
44600b57cec5SDimitry Andric   if (Type.isRestrictQualified())
44610b57cec5SDimitry Andric     Flags |= ItaniumRTTIBuilder::PTI_Restrict;
44620b57cec5SDimitry Andric   Type = Type.getUnqualifiedType();
44630b57cec5SDimitry Andric 
44640b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p7:
44650b57cec5SDimitry Andric   //   When the abi::__pbase_type_info is for a direct or indirect pointer to an
44660b57cec5SDimitry Andric   //   incomplete class type, the incomplete target type flag is set.
44670b57cec5SDimitry Andric   if (ContainsIncompleteClassType(Type))
44680b57cec5SDimitry Andric     Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
44690b57cec5SDimitry Andric 
44700b57cec5SDimitry Andric   if (auto *Proto = Type->getAs<FunctionProtoType>()) {
44710b57cec5SDimitry Andric     if (Proto->isNothrow()) {
44720b57cec5SDimitry Andric       Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
44730b57cec5SDimitry Andric       Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None);
44740b57cec5SDimitry Andric     }
44750b57cec5SDimitry Andric   }
44760b57cec5SDimitry Andric 
44770b57cec5SDimitry Andric   return Flags;
44780b57cec5SDimitry Andric }
44790b57cec5SDimitry Andric 
44800b57cec5SDimitry Andric /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
44810b57cec5SDimitry Andric /// used for pointer types.
44820b57cec5SDimitry Andric void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
44830b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p7:
44840b57cec5SDimitry Andric   //   __flags is a flag word describing the cv-qualification and other
44850b57cec5SDimitry Andric   //   attributes of the type pointed to
44860b57cec5SDimitry Andric   unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
44870b57cec5SDimitry Andric 
44880b57cec5SDimitry Andric   llvm::Type *UnsignedIntLTy =
44890b57cec5SDimitry Andric     CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
44900b57cec5SDimitry Andric   Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
44910b57cec5SDimitry Andric 
44920b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p7:
44930b57cec5SDimitry Andric   //  __pointee is a pointer to the std::type_info derivation for the
44940b57cec5SDimitry Andric   //  unqualified type being pointed to.
44950b57cec5SDimitry Andric   llvm::Constant *PointeeTypeInfo =
44960b57cec5SDimitry Andric       ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
44970b57cec5SDimitry Andric   Fields.push_back(PointeeTypeInfo);
44980b57cec5SDimitry Andric }
44990b57cec5SDimitry Andric 
45000b57cec5SDimitry Andric /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
45010b57cec5SDimitry Andric /// struct, used for member pointer types.
45020b57cec5SDimitry Andric void
45030b57cec5SDimitry Andric ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
45040b57cec5SDimitry Andric   QualType PointeeTy = Ty->getPointeeType();
45050b57cec5SDimitry Andric 
45060b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p7:
45070b57cec5SDimitry Andric   //   __flags is a flag word describing the cv-qualification and other
45080b57cec5SDimitry Andric   //   attributes of the type pointed to.
45090b57cec5SDimitry Andric   unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
45100b57cec5SDimitry Andric 
45110b57cec5SDimitry Andric   const RecordType *ClassType = cast<RecordType>(Ty->getClass());
45120b57cec5SDimitry Andric   if (IsIncompleteClassType(ClassType))
45130b57cec5SDimitry Andric     Flags |= PTI_ContainingClassIncomplete;
45140b57cec5SDimitry Andric 
45150b57cec5SDimitry Andric   llvm::Type *UnsignedIntLTy =
45160b57cec5SDimitry Andric     CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
45170b57cec5SDimitry Andric   Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
45180b57cec5SDimitry Andric 
45190b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p7:
45200b57cec5SDimitry Andric   //   __pointee is a pointer to the std::type_info derivation for the
45210b57cec5SDimitry Andric   //   unqualified type being pointed to.
45220b57cec5SDimitry Andric   llvm::Constant *PointeeTypeInfo =
45230b57cec5SDimitry Andric       ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
45240b57cec5SDimitry Andric   Fields.push_back(PointeeTypeInfo);
45250b57cec5SDimitry Andric 
45260b57cec5SDimitry Andric   // Itanium C++ ABI 2.9.5p9:
45270b57cec5SDimitry Andric   //   __context is a pointer to an abi::__class_type_info corresponding to the
45280b57cec5SDimitry Andric   //   class type containing the member pointed to
45290b57cec5SDimitry Andric   //   (e.g., the "A" in "int A::*").
45300b57cec5SDimitry Andric   Fields.push_back(
45310b57cec5SDimitry Andric       ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0)));
45320b57cec5SDimitry Andric }
45330b57cec5SDimitry Andric 
45340b57cec5SDimitry Andric llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
45350b57cec5SDimitry Andric   return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
45360b57cec5SDimitry Andric }
45370b57cec5SDimitry Andric 
45380b57cec5SDimitry Andric void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
45390b57cec5SDimitry Andric   // Types added here must also be added to TypeInfoIsInStandardLibrary.
45400b57cec5SDimitry Andric   QualType FundamentalTypes[] = {
45410b57cec5SDimitry Andric       getContext().VoidTy,             getContext().NullPtrTy,
45420b57cec5SDimitry Andric       getContext().BoolTy,             getContext().WCharTy,
45430b57cec5SDimitry Andric       getContext().CharTy,             getContext().UnsignedCharTy,
45440b57cec5SDimitry Andric       getContext().SignedCharTy,       getContext().ShortTy,
45450b57cec5SDimitry Andric       getContext().UnsignedShortTy,    getContext().IntTy,
45460b57cec5SDimitry Andric       getContext().UnsignedIntTy,      getContext().LongTy,
45470b57cec5SDimitry Andric       getContext().UnsignedLongTy,     getContext().LongLongTy,
45480b57cec5SDimitry Andric       getContext().UnsignedLongLongTy, getContext().Int128Ty,
45490b57cec5SDimitry Andric       getContext().UnsignedInt128Ty,   getContext().HalfTy,
45500b57cec5SDimitry Andric       getContext().FloatTy,            getContext().DoubleTy,
45510b57cec5SDimitry Andric       getContext().LongDoubleTy,       getContext().Float128Ty,
45520b57cec5SDimitry Andric       getContext().Char8Ty,            getContext().Char16Ty,
45530b57cec5SDimitry Andric       getContext().Char32Ty
45540b57cec5SDimitry Andric   };
45550b57cec5SDimitry Andric   llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
455681ad6265SDimitry Andric       RD->hasAttr<DLLExportAttr>() || CGM.shouldMapVisibilityToDLLExport(RD)
45570b57cec5SDimitry Andric           ? llvm::GlobalValue::DLLExportStorageClass
45580b57cec5SDimitry Andric           : llvm::GlobalValue::DefaultStorageClass;
45590b57cec5SDimitry Andric   llvm::GlobalValue::VisibilityTypes Visibility =
45600b57cec5SDimitry Andric       CodeGenModule::GetLLVMVisibility(RD->getVisibility());
45610b57cec5SDimitry Andric   for (const QualType &FundamentalType : FundamentalTypes) {
45620b57cec5SDimitry Andric     QualType PointerType = getContext().getPointerType(FundamentalType);
45630b57cec5SDimitry Andric     QualType PointerTypeConst = getContext().getPointerType(
45640b57cec5SDimitry Andric         FundamentalType.withConst());
45650b57cec5SDimitry Andric     for (QualType Type : {FundamentalType, PointerType, PointerTypeConst})
45660b57cec5SDimitry Andric       ItaniumRTTIBuilder(*this).BuildTypeInfo(
45670b57cec5SDimitry Andric           Type, llvm::GlobalValue::ExternalLinkage,
45680b57cec5SDimitry Andric           Visibility, DLLStorageClass);
45690b57cec5SDimitry Andric   }
45700b57cec5SDimitry Andric }
45710b57cec5SDimitry Andric 
45720b57cec5SDimitry Andric /// What sort of uniqueness rules should we use for the RTTI for the
45730b57cec5SDimitry Andric /// given type?
45740b57cec5SDimitry Andric ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
45750b57cec5SDimitry Andric     QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const {
45760b57cec5SDimitry Andric   if (shouldRTTIBeUnique())
45770b57cec5SDimitry Andric     return RUK_Unique;
45780b57cec5SDimitry Andric 
45790b57cec5SDimitry Andric   // It's only necessary for linkonce_odr or weak_odr linkage.
45800b57cec5SDimitry Andric   if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
45810b57cec5SDimitry Andric       Linkage != llvm::GlobalValue::WeakODRLinkage)
45820b57cec5SDimitry Andric     return RUK_Unique;
45830b57cec5SDimitry Andric 
45840b57cec5SDimitry Andric   // It's only necessary with default visibility.
45850b57cec5SDimitry Andric   if (CanTy->getVisibility() != DefaultVisibility)
45860b57cec5SDimitry Andric     return RUK_Unique;
45870b57cec5SDimitry Andric 
45880b57cec5SDimitry Andric   // If we're not required to publish this symbol, hide it.
45890b57cec5SDimitry Andric   if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
45900b57cec5SDimitry Andric     return RUK_NonUniqueHidden;
45910b57cec5SDimitry Andric 
45920b57cec5SDimitry Andric   // If we're required to publish this symbol, as we might be under an
45930b57cec5SDimitry Andric   // explicit instantiation, leave it with default visibility but
45940b57cec5SDimitry Andric   // enable string-comparisons.
45950b57cec5SDimitry Andric   assert(Linkage == llvm::GlobalValue::WeakODRLinkage);
45960b57cec5SDimitry Andric   return RUK_NonUniqueVisible;
45970b57cec5SDimitry Andric }
45980b57cec5SDimitry Andric 
45990b57cec5SDimitry Andric // Find out how to codegen the complete destructor and constructor
46000b57cec5SDimitry Andric namespace {
46010b57cec5SDimitry Andric enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
46020b57cec5SDimitry Andric }
46030b57cec5SDimitry Andric static StructorCodegen getCodegenToUse(CodeGenModule &CGM,
46040b57cec5SDimitry Andric                                        const CXXMethodDecl *MD) {
46050b57cec5SDimitry Andric   if (!CGM.getCodeGenOpts().CXXCtorDtorAliases)
46060b57cec5SDimitry Andric     return StructorCodegen::Emit;
46070b57cec5SDimitry Andric 
46080b57cec5SDimitry Andric   // The complete and base structors are not equivalent if there are any virtual
46090b57cec5SDimitry Andric   // bases, so emit separate functions.
46100b57cec5SDimitry Andric   if (MD->getParent()->getNumVBases())
46110b57cec5SDimitry Andric     return StructorCodegen::Emit;
46120b57cec5SDimitry Andric 
46130b57cec5SDimitry Andric   GlobalDecl AliasDecl;
46140b57cec5SDimitry Andric   if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
46150b57cec5SDimitry Andric     AliasDecl = GlobalDecl(DD, Dtor_Complete);
46160b57cec5SDimitry Andric   } else {
46170b57cec5SDimitry Andric     const auto *CD = cast<CXXConstructorDecl>(MD);
46180b57cec5SDimitry Andric     AliasDecl = GlobalDecl(CD, Ctor_Complete);
46190b57cec5SDimitry Andric   }
46200b57cec5SDimitry Andric   llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl);
46210b57cec5SDimitry Andric 
46220b57cec5SDimitry Andric   if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))
46230b57cec5SDimitry Andric     return StructorCodegen::RAUW;
46240b57cec5SDimitry Andric 
46250b57cec5SDimitry Andric   // FIXME: Should we allow available_externally aliases?
46260b57cec5SDimitry Andric   if (!llvm::GlobalAlias::isValidLinkage(Linkage))
46270b57cec5SDimitry Andric     return StructorCodegen::RAUW;
46280b57cec5SDimitry Andric 
46290b57cec5SDimitry Andric   if (llvm::GlobalValue::isWeakForLinker(Linkage)) {
46300b57cec5SDimitry Andric     // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
46310b57cec5SDimitry Andric     if (CGM.getTarget().getTriple().isOSBinFormatELF() ||
46320b57cec5SDimitry Andric         CGM.getTarget().getTriple().isOSBinFormatWasm())
46330b57cec5SDimitry Andric       return StructorCodegen::COMDAT;
46340b57cec5SDimitry Andric     return StructorCodegen::Emit;
46350b57cec5SDimitry Andric   }
46360b57cec5SDimitry Andric 
46370b57cec5SDimitry Andric   return StructorCodegen::Alias;
46380b57cec5SDimitry Andric }
46390b57cec5SDimitry Andric 
46400b57cec5SDimitry Andric static void emitConstructorDestructorAlias(CodeGenModule &CGM,
46410b57cec5SDimitry Andric                                            GlobalDecl AliasDecl,
46420b57cec5SDimitry Andric                                            GlobalDecl TargetDecl) {
46430b57cec5SDimitry Andric   llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl);
46440b57cec5SDimitry Andric 
46450b57cec5SDimitry Andric   StringRef MangledName = CGM.getMangledName(AliasDecl);
46460b57cec5SDimitry Andric   llvm::GlobalValue *Entry = CGM.GetGlobalValue(MangledName);
46470b57cec5SDimitry Andric   if (Entry && !Entry->isDeclaration())
46480b57cec5SDimitry Andric     return;
46490b57cec5SDimitry Andric 
46500b57cec5SDimitry Andric   auto *Aliasee = cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(TargetDecl));
46510b57cec5SDimitry Andric 
46520b57cec5SDimitry Andric   // Create the alias with no name.
46530b57cec5SDimitry Andric   auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee);
46540b57cec5SDimitry Andric 
46550b57cec5SDimitry Andric   // Constructors and destructors are always unnamed_addr.
46560b57cec5SDimitry Andric   Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
46570b57cec5SDimitry Andric 
46580b57cec5SDimitry Andric   // Switch any previous uses to the alias.
46590b57cec5SDimitry Andric   if (Entry) {
46600b57cec5SDimitry Andric     assert(Entry->getType() == Aliasee->getType() &&
46610b57cec5SDimitry Andric            "declaration exists with different type");
46620b57cec5SDimitry Andric     Alias->takeName(Entry);
46630b57cec5SDimitry Andric     Entry->replaceAllUsesWith(Alias);
46640b57cec5SDimitry Andric     Entry->eraseFromParent();
46650b57cec5SDimitry Andric   } else {
46660b57cec5SDimitry Andric     Alias->setName(MangledName);
46670b57cec5SDimitry Andric   }
46680b57cec5SDimitry Andric 
46690b57cec5SDimitry Andric   // Finally, set up the alias with its proper name and attributes.
46700b57cec5SDimitry Andric   CGM.SetCommonAttributes(AliasDecl, Alias);
46710b57cec5SDimitry Andric }
46720b57cec5SDimitry Andric 
46730b57cec5SDimitry Andric void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {
46740b57cec5SDimitry Andric   auto *MD = cast<CXXMethodDecl>(GD.getDecl());
46750b57cec5SDimitry Andric   auto *CD = dyn_cast<CXXConstructorDecl>(MD);
46760b57cec5SDimitry Andric   const CXXDestructorDecl *DD = CD ? nullptr : cast<CXXDestructorDecl>(MD);
46770b57cec5SDimitry Andric 
46780b57cec5SDimitry Andric   StructorCodegen CGType = getCodegenToUse(CGM, MD);
46790b57cec5SDimitry Andric 
46800b57cec5SDimitry Andric   if (CD ? GD.getCtorType() == Ctor_Complete
46810b57cec5SDimitry Andric          : GD.getDtorType() == Dtor_Complete) {
46820b57cec5SDimitry Andric     GlobalDecl BaseDecl;
46830b57cec5SDimitry Andric     if (CD)
46840b57cec5SDimitry Andric       BaseDecl = GD.getWithCtorType(Ctor_Base);
46850b57cec5SDimitry Andric     else
46860b57cec5SDimitry Andric       BaseDecl = GD.getWithDtorType(Dtor_Base);
46870b57cec5SDimitry Andric 
46880b57cec5SDimitry Andric     if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {
46890b57cec5SDimitry Andric       emitConstructorDestructorAlias(CGM, GD, BaseDecl);
46900b57cec5SDimitry Andric       return;
46910b57cec5SDimitry Andric     }
46920b57cec5SDimitry Andric 
46930b57cec5SDimitry Andric     if (CGType == StructorCodegen::RAUW) {
46940b57cec5SDimitry Andric       StringRef MangledName = CGM.getMangledName(GD);
46950b57cec5SDimitry Andric       auto *Aliasee = CGM.GetAddrOfGlobal(BaseDecl);
46960b57cec5SDimitry Andric       CGM.addReplacement(MangledName, Aliasee);
46970b57cec5SDimitry Andric       return;
46980b57cec5SDimitry Andric     }
46990b57cec5SDimitry Andric   }
47000b57cec5SDimitry Andric 
47010b57cec5SDimitry Andric   // The base destructor is equivalent to the base destructor of its
47020b57cec5SDimitry Andric   // base class if there is exactly one non-virtual base class with a
47030b57cec5SDimitry Andric   // non-trivial destructor, there are no fields with a non-trivial
47040b57cec5SDimitry Andric   // destructor, and the body of the destructor is trivial.
47050b57cec5SDimitry Andric   if (DD && GD.getDtorType() == Dtor_Base &&
47060b57cec5SDimitry Andric       CGType != StructorCodegen::COMDAT &&
47070b57cec5SDimitry Andric       !CGM.TryEmitBaseDestructorAsAlias(DD))
47080b57cec5SDimitry Andric     return;
47090b57cec5SDimitry Andric 
47100b57cec5SDimitry Andric   // FIXME: The deleting destructor is equivalent to the selected operator
47110b57cec5SDimitry Andric   // delete if:
47120b57cec5SDimitry Andric   //  * either the delete is a destroying operator delete or the destructor
47130b57cec5SDimitry Andric   //    would be trivial if it weren't virtual,
47140b57cec5SDimitry Andric   //  * the conversion from the 'this' parameter to the first parameter of the
47150b57cec5SDimitry Andric   //    destructor is equivalent to a bitcast,
47160b57cec5SDimitry Andric   //  * the destructor does not have an implicit "this" return, and
47170b57cec5SDimitry Andric   //  * the operator delete has the same calling convention and IR function type
47180b57cec5SDimitry Andric   //    as the destructor.
47190b57cec5SDimitry Andric   // In such cases we should try to emit the deleting dtor as an alias to the
47200b57cec5SDimitry Andric   // selected 'operator delete'.
47210b57cec5SDimitry Andric 
47220b57cec5SDimitry Andric   llvm::Function *Fn = CGM.codegenCXXStructor(GD);
47230b57cec5SDimitry Andric 
47240b57cec5SDimitry Andric   if (CGType == StructorCodegen::COMDAT) {
47250b57cec5SDimitry Andric     SmallString<256> Buffer;
47260b57cec5SDimitry Andric     llvm::raw_svector_ostream Out(Buffer);
47270b57cec5SDimitry Andric     if (DD)
47280b57cec5SDimitry Andric       getMangleContext().mangleCXXDtorComdat(DD, Out);
47290b57cec5SDimitry Andric     else
47300b57cec5SDimitry Andric       getMangleContext().mangleCXXCtorComdat(CD, Out);
47310b57cec5SDimitry Andric     llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str());
47320b57cec5SDimitry Andric     Fn->setComdat(C);
47330b57cec5SDimitry Andric   } else {
47340b57cec5SDimitry Andric     CGM.maybeSetTrivialComdat(*MD, *Fn);
47350b57cec5SDimitry Andric   }
47360b57cec5SDimitry Andric }
47370b57cec5SDimitry Andric 
47380b57cec5SDimitry Andric static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM) {
47390b57cec5SDimitry Andric   // void *__cxa_begin_catch(void*);
47400b57cec5SDimitry Andric   llvm::FunctionType *FTy = llvm::FunctionType::get(
47410b57cec5SDimitry Andric       CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
47420b57cec5SDimitry Andric 
47430b57cec5SDimitry Andric   return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
47440b57cec5SDimitry Andric }
47450b57cec5SDimitry Andric 
47460b57cec5SDimitry Andric static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) {
47470b57cec5SDimitry Andric   // void __cxa_end_catch();
47480b57cec5SDimitry Andric   llvm::FunctionType *FTy =
47490b57cec5SDimitry Andric       llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
47500b57cec5SDimitry Andric 
47510b57cec5SDimitry Andric   return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");
47520b57cec5SDimitry Andric }
47530b57cec5SDimitry Andric 
47540b57cec5SDimitry Andric static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM) {
47550b57cec5SDimitry Andric   // void *__cxa_get_exception_ptr(void*);
47560b57cec5SDimitry Andric   llvm::FunctionType *FTy = llvm::FunctionType::get(
47570b57cec5SDimitry Andric       CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
47580b57cec5SDimitry Andric 
47590b57cec5SDimitry Andric   return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");
47600b57cec5SDimitry Andric }
47610b57cec5SDimitry Andric 
47620b57cec5SDimitry Andric namespace {
47630b57cec5SDimitry Andric   /// A cleanup to call __cxa_end_catch.  In many cases, the caught
47640b57cec5SDimitry Andric   /// exception type lets us state definitively that the thrown exception
47650b57cec5SDimitry Andric   /// type does not have a destructor.  In particular:
47660b57cec5SDimitry Andric   ///   - Catch-alls tell us nothing, so we have to conservatively
47670b57cec5SDimitry Andric   ///     assume that the thrown exception might have a destructor.
47680b57cec5SDimitry Andric   ///   - Catches by reference behave according to their base types.
47690b57cec5SDimitry Andric   ///   - Catches of non-record types will only trigger for exceptions
47700b57cec5SDimitry Andric   ///     of non-record types, which never have destructors.
47710b57cec5SDimitry Andric   ///   - Catches of record types can trigger for arbitrary subclasses
47720b57cec5SDimitry Andric   ///     of the caught type, so we have to assume the actual thrown
47730b57cec5SDimitry Andric   ///     exception type might have a throwing destructor, even if the
47740b57cec5SDimitry Andric   ///     caught type's destructor is trivial or nothrow.
47750b57cec5SDimitry Andric   struct CallEndCatch final : EHScopeStack::Cleanup {
47760b57cec5SDimitry Andric     CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
47770b57cec5SDimitry Andric     bool MightThrow;
47780b57cec5SDimitry Andric 
47790b57cec5SDimitry Andric     void Emit(CodeGenFunction &CGF, Flags flags) override {
47800b57cec5SDimitry Andric       if (!MightThrow) {
47810b57cec5SDimitry Andric         CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));
47820b57cec5SDimitry Andric         return;
47830b57cec5SDimitry Andric       }
47840b57cec5SDimitry Andric 
47850b57cec5SDimitry Andric       CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));
47860b57cec5SDimitry Andric     }
47870b57cec5SDimitry Andric   };
47880b57cec5SDimitry Andric }
47890b57cec5SDimitry Andric 
47900b57cec5SDimitry Andric /// Emits a call to __cxa_begin_catch and enters a cleanup to call
47915f757f3fSDimitry Andric /// __cxa_end_catch. If -fassume-nothrow-exception-dtor is specified, we assume
47925f757f3fSDimitry Andric /// that the exception object's dtor is nothrow, therefore the __cxa_end_catch
47935f757f3fSDimitry Andric /// call can be marked as nounwind even if EndMightThrow is true.
47940b57cec5SDimitry Andric ///
47950b57cec5SDimitry Andric /// \param EndMightThrow - true if __cxa_end_catch might throw
47960b57cec5SDimitry Andric static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
47970b57cec5SDimitry Andric                                    llvm::Value *Exn,
47980b57cec5SDimitry Andric                                    bool EndMightThrow) {
47990b57cec5SDimitry Andric   llvm::CallInst *call =
48000b57cec5SDimitry Andric     CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);
48010b57cec5SDimitry Andric 
48025f757f3fSDimitry Andric   CGF.EHStack.pushCleanup<CallEndCatch>(
48035f757f3fSDimitry Andric       NormalAndEHCleanup,
48045f757f3fSDimitry Andric       EndMightThrow && !CGF.CGM.getLangOpts().AssumeNothrowExceptionDtor);
48050b57cec5SDimitry Andric 
48060b57cec5SDimitry Andric   return call;
48070b57cec5SDimitry Andric }
48080b57cec5SDimitry Andric 
48090b57cec5SDimitry Andric /// A "special initializer" callback for initializing a catch
48100b57cec5SDimitry Andric /// parameter during catch initialization.
48110b57cec5SDimitry Andric static void InitCatchParam(CodeGenFunction &CGF,
48120b57cec5SDimitry Andric                            const VarDecl &CatchParam,
48130b57cec5SDimitry Andric                            Address ParamAddr,
48140b57cec5SDimitry Andric                            SourceLocation Loc) {
48150b57cec5SDimitry Andric   // Load the exception from where the landing pad saved it.
48160b57cec5SDimitry Andric   llvm::Value *Exn = CGF.getExceptionFromSlot();
48170b57cec5SDimitry Andric 
48180b57cec5SDimitry Andric   CanQualType CatchType =
48190b57cec5SDimitry Andric     CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
48200b57cec5SDimitry Andric   llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);
48210b57cec5SDimitry Andric 
48220b57cec5SDimitry Andric   // If we're catching by reference, we can just cast the object
48230b57cec5SDimitry Andric   // pointer to the appropriate pointer.
48240b57cec5SDimitry Andric   if (isa<ReferenceType>(CatchType)) {
48250b57cec5SDimitry Andric     QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();
48260b57cec5SDimitry Andric     bool EndCatchMightThrow = CaughtType->isRecordType();
48270b57cec5SDimitry Andric 
48280b57cec5SDimitry Andric     // __cxa_begin_catch returns the adjusted object pointer.
48290b57cec5SDimitry Andric     llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);
48300b57cec5SDimitry Andric 
48310b57cec5SDimitry Andric     // We have no way to tell the personality function that we're
48320b57cec5SDimitry Andric     // catching by reference, so if we're catching a pointer,
48330b57cec5SDimitry Andric     // __cxa_begin_catch will actually return that pointer by value.
48340b57cec5SDimitry Andric     if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
48350b57cec5SDimitry Andric       QualType PointeeType = PT->getPointeeType();
48360b57cec5SDimitry Andric 
48370b57cec5SDimitry Andric       // When catching by reference, generally we should just ignore
48380b57cec5SDimitry Andric       // this by-value pointer and use the exception object instead.
48390b57cec5SDimitry Andric       if (!PointeeType->isRecordType()) {
48400b57cec5SDimitry Andric 
48410b57cec5SDimitry Andric         // Exn points to the struct _Unwind_Exception header, which
48420b57cec5SDimitry Andric         // we have to skip past in order to reach the exception data.
48430b57cec5SDimitry Andric         unsigned HeaderSize =
48440b57cec5SDimitry Andric           CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
4845fe6060f1SDimitry Andric         AdjustedExn =
4846fe6060f1SDimitry Andric             CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, Exn, HeaderSize);
48470b57cec5SDimitry Andric 
48480b57cec5SDimitry Andric       // However, if we're catching a pointer-to-record type that won't
48490b57cec5SDimitry Andric       // work, because the personality function might have adjusted
48500b57cec5SDimitry Andric       // the pointer.  There's actually no way for us to fully satisfy
48510b57cec5SDimitry Andric       // the language/ABI contract here:  we can't use Exn because it
48520b57cec5SDimitry Andric       // might have the wrong adjustment, but we can't use the by-value
48530b57cec5SDimitry Andric       // pointer because it's off by a level of abstraction.
48540b57cec5SDimitry Andric       //
48550b57cec5SDimitry Andric       // The current solution is to dump the adjusted pointer into an
48560b57cec5SDimitry Andric       // alloca, which breaks language semantics (because changing the
48570b57cec5SDimitry Andric       // pointer doesn't change the exception) but at least works.
48580b57cec5SDimitry Andric       // The better solution would be to filter out non-exact matches
48590b57cec5SDimitry Andric       // and rethrow them, but this is tricky because the rethrow
48600b57cec5SDimitry Andric       // really needs to be catchable by other sites at this landing
48610b57cec5SDimitry Andric       // pad.  The best solution is to fix the personality function.
48620b57cec5SDimitry Andric       } else {
48630b57cec5SDimitry Andric         // Pull the pointer for the reference type off.
486481ad6265SDimitry Andric         llvm::Type *PtrTy = CGF.ConvertTypeForMem(CaughtType);
48650b57cec5SDimitry Andric 
48660b57cec5SDimitry Andric         // Create the temporary and write the adjusted pointer into it.
48670b57cec5SDimitry Andric         Address ExnPtrTmp =
48680b57cec5SDimitry Andric           CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp");
48690b57cec5SDimitry Andric         llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
48700b57cec5SDimitry Andric         CGF.Builder.CreateStore(Casted, ExnPtrTmp);
48710b57cec5SDimitry Andric 
48720b57cec5SDimitry Andric         // Bind the reference to the temporary.
48730fca6ea1SDimitry Andric         AdjustedExn = ExnPtrTmp.emitRawPointer(CGF);
48740b57cec5SDimitry Andric       }
48750b57cec5SDimitry Andric     }
48760b57cec5SDimitry Andric 
48770b57cec5SDimitry Andric     llvm::Value *ExnCast =
48780b57cec5SDimitry Andric       CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
48790b57cec5SDimitry Andric     CGF.Builder.CreateStore(ExnCast, ParamAddr);
48800b57cec5SDimitry Andric     return;
48810b57cec5SDimitry Andric   }
48820b57cec5SDimitry Andric 
48830b57cec5SDimitry Andric   // Scalars and complexes.
48840b57cec5SDimitry Andric   TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType);
48850b57cec5SDimitry Andric   if (TEK != TEK_Aggregate) {
48860b57cec5SDimitry Andric     llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);
48870b57cec5SDimitry Andric 
48880b57cec5SDimitry Andric     // If the catch type is a pointer type, __cxa_begin_catch returns
48890b57cec5SDimitry Andric     // the pointer by value.
48900b57cec5SDimitry Andric     if (CatchType->hasPointerRepresentation()) {
48910b57cec5SDimitry Andric       llvm::Value *CastExn =
48920b57cec5SDimitry Andric         CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
48930b57cec5SDimitry Andric 
48940b57cec5SDimitry Andric       switch (CatchType.getQualifiers().getObjCLifetime()) {
48950b57cec5SDimitry Andric       case Qualifiers::OCL_Strong:
48960b57cec5SDimitry Andric         CastExn = CGF.EmitARCRetainNonBlock(CastExn);
4897bdd1243dSDimitry Andric         [[fallthrough]];
48980b57cec5SDimitry Andric 
48990b57cec5SDimitry Andric       case Qualifiers::OCL_None:
49000b57cec5SDimitry Andric       case Qualifiers::OCL_ExplicitNone:
49010b57cec5SDimitry Andric       case Qualifiers::OCL_Autoreleasing:
49020b57cec5SDimitry Andric         CGF.Builder.CreateStore(CastExn, ParamAddr);
49030b57cec5SDimitry Andric         return;
49040b57cec5SDimitry Andric 
49050b57cec5SDimitry Andric       case Qualifiers::OCL_Weak:
49060b57cec5SDimitry Andric         CGF.EmitARCInitWeak(ParamAddr, CastExn);
49070b57cec5SDimitry Andric         return;
49080b57cec5SDimitry Andric       }
49090b57cec5SDimitry Andric       llvm_unreachable("bad ownership qualifier!");
49100b57cec5SDimitry Andric     }
49110b57cec5SDimitry Andric 
49120b57cec5SDimitry Andric     // Otherwise, it returns a pointer into the exception object.
49130b57cec5SDimitry Andric 
491406c3fb27SDimitry Andric     LValue srcLV = CGF.MakeNaturalAlignAddrLValue(AdjustedExn, CatchType);
49150b57cec5SDimitry Andric     LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType);
49160b57cec5SDimitry Andric     switch (TEK) {
49170b57cec5SDimitry Andric     case TEK_Complex:
49180b57cec5SDimitry Andric       CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV,
49190b57cec5SDimitry Andric                              /*init*/ true);
49200b57cec5SDimitry Andric       return;
49210b57cec5SDimitry Andric     case TEK_Scalar: {
49220b57cec5SDimitry Andric       llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc);
49230b57cec5SDimitry Andric       CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true);
49240b57cec5SDimitry Andric       return;
49250b57cec5SDimitry Andric     }
49260b57cec5SDimitry Andric     case TEK_Aggregate:
49270b57cec5SDimitry Andric       llvm_unreachable("evaluation kind filtered out!");
49280b57cec5SDimitry Andric     }
49290b57cec5SDimitry Andric     llvm_unreachable("bad evaluation kind");
49300b57cec5SDimitry Andric   }
49310b57cec5SDimitry Andric 
49320b57cec5SDimitry Andric   assert(isa<RecordType>(CatchType) && "unexpected catch type!");
49330b57cec5SDimitry Andric   auto catchRD = CatchType->getAsCXXRecordDecl();
49340b57cec5SDimitry Andric   CharUnits caughtExnAlignment = CGF.CGM.getClassPointerAlignment(catchRD);
49350b57cec5SDimitry Andric 
49365f757f3fSDimitry Andric   llvm::Type *PtrTy = CGF.UnqualPtrTy; // addrspace 0 ok
49370b57cec5SDimitry Andric 
49380b57cec5SDimitry Andric   // Check for a copy expression.  If we don't have a copy expression,
49390b57cec5SDimitry Andric   // that means a trivial copy is okay.
49400b57cec5SDimitry Andric   const Expr *copyExpr = CatchParam.getInit();
49410b57cec5SDimitry Andric   if (!copyExpr) {
49420b57cec5SDimitry Andric     llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);
49430b57cec5SDimitry Andric     Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
494481ad6265SDimitry Andric                         LLVMCatchTy, caughtExnAlignment);
49450b57cec5SDimitry Andric     LValue Dest = CGF.MakeAddrLValue(ParamAddr, CatchType);
49460b57cec5SDimitry Andric     LValue Src = CGF.MakeAddrLValue(adjustedExn, CatchType);
49470b57cec5SDimitry Andric     CGF.EmitAggregateCopy(Dest, Src, CatchType, AggValueSlot::DoesNotOverlap);
49480b57cec5SDimitry Andric     return;
49490b57cec5SDimitry Andric   }
49500b57cec5SDimitry Andric 
49510b57cec5SDimitry Andric   // We have to call __cxa_get_exception_ptr to get the adjusted
49520b57cec5SDimitry Andric   // pointer before copying.
49530b57cec5SDimitry Andric   llvm::CallInst *rawAdjustedExn =
49540b57cec5SDimitry Andric     CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
49550b57cec5SDimitry Andric 
49560b57cec5SDimitry Andric   // Cast that to the appropriate type.
49570b57cec5SDimitry Andric   Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
495881ad6265SDimitry Andric                       LLVMCatchTy, caughtExnAlignment);
49590b57cec5SDimitry Andric 
49600b57cec5SDimitry Andric   // The copy expression is defined in terms of an OpaqueValueExpr.
49610b57cec5SDimitry Andric   // Find it and map it to the adjusted expression.
49620b57cec5SDimitry Andric   CodeGenFunction::OpaqueValueMapping
49630b57cec5SDimitry Andric     opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
49640b57cec5SDimitry Andric            CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
49650b57cec5SDimitry Andric 
49660b57cec5SDimitry Andric   // Call the copy ctor in a terminate scope.
49670b57cec5SDimitry Andric   CGF.EHStack.pushTerminate();
49680b57cec5SDimitry Andric 
49690b57cec5SDimitry Andric   // Perform the copy construction.
49700b57cec5SDimitry Andric   CGF.EmitAggExpr(copyExpr,
49710b57cec5SDimitry Andric                   AggValueSlot::forAddr(ParamAddr, Qualifiers(),
49720b57cec5SDimitry Andric                                         AggValueSlot::IsNotDestructed,
49730b57cec5SDimitry Andric                                         AggValueSlot::DoesNotNeedGCBarriers,
49740b57cec5SDimitry Andric                                         AggValueSlot::IsNotAliased,
49750b57cec5SDimitry Andric                                         AggValueSlot::DoesNotOverlap));
49760b57cec5SDimitry Andric 
49770b57cec5SDimitry Andric   // Leave the terminate scope.
49780b57cec5SDimitry Andric   CGF.EHStack.popTerminate();
49790b57cec5SDimitry Andric 
49800b57cec5SDimitry Andric   // Undo the opaque value mapping.
49810b57cec5SDimitry Andric   opaque.pop();
49820b57cec5SDimitry Andric 
49830b57cec5SDimitry Andric   // Finally we can call __cxa_begin_catch.
49840b57cec5SDimitry Andric   CallBeginCatch(CGF, Exn, true);
49850b57cec5SDimitry Andric }
49860b57cec5SDimitry Andric 
49870b57cec5SDimitry Andric /// Begins a catch statement by initializing the catch variable and
49880b57cec5SDimitry Andric /// calling __cxa_begin_catch.
49890b57cec5SDimitry Andric void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,
49900b57cec5SDimitry Andric                                    const CXXCatchStmt *S) {
49910b57cec5SDimitry Andric   // We have to be very careful with the ordering of cleanups here:
49920b57cec5SDimitry Andric   //   C++ [except.throw]p4:
49930b57cec5SDimitry Andric   //     The destruction [of the exception temporary] occurs
49940b57cec5SDimitry Andric   //     immediately after the destruction of the object declared in
49950b57cec5SDimitry Andric   //     the exception-declaration in the handler.
49960b57cec5SDimitry Andric   //
49970b57cec5SDimitry Andric   // So the precise ordering is:
49980b57cec5SDimitry Andric   //   1.  Construct catch variable.
49990b57cec5SDimitry Andric   //   2.  __cxa_begin_catch
50000b57cec5SDimitry Andric   //   3.  Enter __cxa_end_catch cleanup
50010b57cec5SDimitry Andric   //   4.  Enter dtor cleanup
50020b57cec5SDimitry Andric   //
50030b57cec5SDimitry Andric   // We do this by using a slightly abnormal initialization process.
50040b57cec5SDimitry Andric   // Delegation sequence:
50050b57cec5SDimitry Andric   //   - ExitCXXTryStmt opens a RunCleanupsScope
50060b57cec5SDimitry Andric   //     - EmitAutoVarAlloca creates the variable and debug info
50070b57cec5SDimitry Andric   //       - InitCatchParam initializes the variable from the exception
50080b57cec5SDimitry Andric   //       - CallBeginCatch calls __cxa_begin_catch
50090b57cec5SDimitry Andric   //       - CallBeginCatch enters the __cxa_end_catch cleanup
50100b57cec5SDimitry Andric   //     - EmitAutoVarCleanups enters the variable destructor cleanup
50110b57cec5SDimitry Andric   //   - EmitCXXTryStmt emits the code for the catch body
50120b57cec5SDimitry Andric   //   - EmitCXXTryStmt close the RunCleanupsScope
50130b57cec5SDimitry Andric 
50140b57cec5SDimitry Andric   VarDecl *CatchParam = S->getExceptionDecl();
50150b57cec5SDimitry Andric   if (!CatchParam) {
50160b57cec5SDimitry Andric     llvm::Value *Exn = CGF.getExceptionFromSlot();
50170b57cec5SDimitry Andric     CallBeginCatch(CGF, Exn, true);
50180b57cec5SDimitry Andric     return;
50190b57cec5SDimitry Andric   }
50200b57cec5SDimitry Andric 
50210b57cec5SDimitry Andric   // Emit the local.
50220b57cec5SDimitry Andric   CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
50230b57cec5SDimitry Andric   InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc());
50240b57cec5SDimitry Andric   CGF.EmitAutoVarCleanups(var);
50250b57cec5SDimitry Andric }
50260b57cec5SDimitry Andric 
50270b57cec5SDimitry Andric /// Get or define the following function:
50280b57cec5SDimitry Andric ///   void @__clang_call_terminate(i8* %exn) nounwind noreturn
50290b57cec5SDimitry Andric /// This code is used only in C++.
50300b57cec5SDimitry Andric static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM) {
5031bdd1243dSDimitry Andric   ASTContext &C = CGM.getContext();
5032bdd1243dSDimitry Andric   const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
5033bdd1243dSDimitry Andric       C.VoidTy, {C.getPointerType(C.CharTy)});
5034bdd1243dSDimitry Andric   llvm::FunctionType *fnTy = CGM.getTypes().GetFunctionType(FI);
50350b57cec5SDimitry Andric   llvm::FunctionCallee fnRef = CGM.CreateRuntimeFunction(
50360b57cec5SDimitry Andric       fnTy, "__clang_call_terminate", llvm::AttributeList(), /*Local=*/true);
50370b57cec5SDimitry Andric   llvm::Function *fn =
50380b57cec5SDimitry Andric       cast<llvm::Function>(fnRef.getCallee()->stripPointerCasts());
50390b57cec5SDimitry Andric   if (fn->empty()) {
5040bdd1243dSDimitry Andric     CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, fn, /*IsThunk=*/false);
504106c3fb27SDimitry Andric     CGM.SetLLVMFunctionAttributesForDefinition(nullptr, fn);
50420b57cec5SDimitry Andric     fn->setDoesNotThrow();
50430b57cec5SDimitry Andric     fn->setDoesNotReturn();
50440b57cec5SDimitry Andric 
50450b57cec5SDimitry Andric     // What we really want is to massively penalize inlining without
50460b57cec5SDimitry Andric     // forbidding it completely.  The difference between that and
50470b57cec5SDimitry Andric     // 'noinline' is negligible.
50480b57cec5SDimitry Andric     fn->addFnAttr(llvm::Attribute::NoInline);
50490b57cec5SDimitry Andric 
50500b57cec5SDimitry Andric     // Allow this function to be shared across translation units, but
50510b57cec5SDimitry Andric     // we don't want it to turn into an exported symbol.
50520b57cec5SDimitry Andric     fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
50530b57cec5SDimitry Andric     fn->setVisibility(llvm::Function::HiddenVisibility);
50540b57cec5SDimitry Andric     if (CGM.supportsCOMDAT())
50550b57cec5SDimitry Andric       fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName()));
50560b57cec5SDimitry Andric 
50570b57cec5SDimitry Andric     // Set up the function.
50580b57cec5SDimitry Andric     llvm::BasicBlock *entry =
50590b57cec5SDimitry Andric         llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);
50600b57cec5SDimitry Andric     CGBuilderTy builder(CGM, entry);
50610b57cec5SDimitry Andric 
50620b57cec5SDimitry Andric     // Pull the exception pointer out of the parameter list.
50630b57cec5SDimitry Andric     llvm::Value *exn = &*fn->arg_begin();
50640b57cec5SDimitry Andric 
50650b57cec5SDimitry Andric     // Call __cxa_begin_catch(exn).
50660b57cec5SDimitry Andric     llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);
50670b57cec5SDimitry Andric     catchCall->setDoesNotThrow();
50680b57cec5SDimitry Andric     catchCall->setCallingConv(CGM.getRuntimeCC());
50690b57cec5SDimitry Andric 
50700b57cec5SDimitry Andric     // Call std::terminate().
50710b57cec5SDimitry Andric     llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn());
50720b57cec5SDimitry Andric     termCall->setDoesNotThrow();
50730b57cec5SDimitry Andric     termCall->setDoesNotReturn();
50740b57cec5SDimitry Andric     termCall->setCallingConv(CGM.getRuntimeCC());
50750b57cec5SDimitry Andric 
50760b57cec5SDimitry Andric     // std::terminate cannot return.
50770b57cec5SDimitry Andric     builder.CreateUnreachable();
50780b57cec5SDimitry Andric   }
50790b57cec5SDimitry Andric   return fnRef;
50800b57cec5SDimitry Andric }
50810b57cec5SDimitry Andric 
50820b57cec5SDimitry Andric llvm::CallInst *
50830b57cec5SDimitry Andric ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
50840b57cec5SDimitry Andric                                                    llvm::Value *Exn) {
50850b57cec5SDimitry Andric   // In C++, we want to call __cxa_begin_catch() before terminating.
50860b57cec5SDimitry Andric   if (Exn) {
50870b57cec5SDimitry Andric     assert(CGF.CGM.getLangOpts().CPlusPlus);
50880b57cec5SDimitry Andric     return CGF.EmitNounwindRuntimeCall(getClangCallTerminateFn(CGF.CGM), Exn);
50890b57cec5SDimitry Andric   }
50900b57cec5SDimitry Andric   return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn());
50910b57cec5SDimitry Andric }
50920b57cec5SDimitry Andric 
50930b57cec5SDimitry Andric std::pair<llvm::Value *, const CXXRecordDecl *>
50940b57cec5SDimitry Andric ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
50950b57cec5SDimitry Andric                              const CXXRecordDecl *RD) {
50960b57cec5SDimitry Andric   return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD};
50970b57cec5SDimitry Andric }
50980b57cec5SDimitry Andric 
50990fca6ea1SDimitry Andric llvm::Constant *
51000fca6ea1SDimitry Andric ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) {
51010fca6ea1SDimitry Andric   const CXXMethodDecl *origMD =
51020fca6ea1SDimitry Andric       cast<CXXMethodDecl>(CGM.getItaniumVTableContext()
51030fca6ea1SDimitry Andric                               .findOriginalMethod(MD->getCanonicalDecl())
51040fca6ea1SDimitry Andric                               .getDecl());
51050fca6ea1SDimitry Andric   llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD);
51060fca6ea1SDimitry Andric   QualType funcType = CGM.getContext().getMemberPointerType(
51070fca6ea1SDimitry Andric       MD->getType(), MD->getParent()->getTypeForDecl());
51080fca6ea1SDimitry Andric   return CGM.getMemberFunctionPointer(thunk, funcType);
51090fca6ea1SDimitry Andric }
51100fca6ea1SDimitry Andric 
51110b57cec5SDimitry Andric void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,
51120b57cec5SDimitry Andric                                        const CXXCatchStmt *C) {
51130b57cec5SDimitry Andric   if (CGF.getTarget().hasFeature("exception-handling"))
51140b57cec5SDimitry Andric     CGF.EHStack.pushCleanup<CatchRetScope>(
51150b57cec5SDimitry Andric         NormalCleanup, cast<llvm::CatchPadInst>(CGF.CurrentFuncletPad));
51160b57cec5SDimitry Andric   ItaniumCXXABI::emitBeginCatch(CGF, C);
51170b57cec5SDimitry Andric }
51185ffd83dbSDimitry Andric 
5119fe6060f1SDimitry Andric llvm::CallInst *
5120fe6060f1SDimitry Andric WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
5121fe6060f1SDimitry Andric                                                        llvm::Value *Exn) {
5122fe6060f1SDimitry Andric   // Itanium ABI calls __clang_call_terminate(), which __cxa_begin_catch() on
5123fe6060f1SDimitry Andric   // the violating exception to mark it handled, but it is currently hard to do
5124fe6060f1SDimitry Andric   // with wasm EH instruction structure with catch/catch_all, we just call
5125fe6060f1SDimitry Andric   // std::terminate and ignore the violating exception as in CGCXXABI.
5126fe6060f1SDimitry Andric   // TODO Consider code transformation that makes calling __clang_call_terminate
5127fe6060f1SDimitry Andric   // possible.
5128fe6060f1SDimitry Andric   return CGCXXABI::emitTerminateForUnexpectedException(CGF, Exn);
5129fe6060f1SDimitry Andric }
5130fe6060f1SDimitry Andric 
51315ffd83dbSDimitry Andric /// Register a global destructor as best as we know how.
51325ffd83dbSDimitry Andric void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
5133fe6060f1SDimitry Andric                                   llvm::FunctionCallee Dtor,
5134fe6060f1SDimitry Andric                                   llvm::Constant *Addr) {
5135fe6060f1SDimitry Andric   if (D.getTLSKind() != VarDecl::TLS_None) {
51365f757f3fSDimitry Andric     llvm::PointerType *PtrTy = CGF.UnqualPtrTy;
5137fe6060f1SDimitry Andric 
5138fe6060f1SDimitry Andric     // extern "C" int __pt_atexit_np(int flags, int(*)(int,...), ...);
5139fe6060f1SDimitry Andric     llvm::FunctionType *AtExitTy =
514006c3fb27SDimitry Andric         llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy, PtrTy}, true);
5141fe6060f1SDimitry Andric 
5142fe6060f1SDimitry Andric     // Fetch the actual function.
5143fe6060f1SDimitry Andric     llvm::FunctionCallee AtExit =
5144fe6060f1SDimitry Andric         CGM.CreateRuntimeFunction(AtExitTy, "__pt_atexit_np");
51455ffd83dbSDimitry Andric 
51465ffd83dbSDimitry Andric     // Create __dtor function for the var decl.
5147fe6060f1SDimitry Andric     llvm::Function *DtorStub = CGF.createTLSAtExitStub(D, Dtor, Addr, AtExit);
51485ffd83dbSDimitry Andric 
51495ffd83dbSDimitry Andric     // Register above __dtor with atexit().
5150fe6060f1SDimitry Andric     // First param is flags and must be 0, second param is function ptr
5151fe6060f1SDimitry Andric     llvm::Value *NV = llvm::Constant::getNullValue(CGM.IntTy);
5152fe6060f1SDimitry Andric     CGF.EmitNounwindRuntimeCall(AtExit, {NV, DtorStub});
5153fe6060f1SDimitry Andric 
5154fe6060f1SDimitry Andric     // Cannot unregister TLS __dtor so done
5155fe6060f1SDimitry Andric     return;
5156fe6060f1SDimitry Andric   }
5157fe6060f1SDimitry Andric 
5158fe6060f1SDimitry Andric   // Create __dtor function for the var decl.
51590fca6ea1SDimitry Andric   llvm::Function *DtorStub =
51600fca6ea1SDimitry Andric       cast<llvm::Function>(CGF.createAtExitStub(D, Dtor, Addr));
5161fe6060f1SDimitry Andric 
5162fe6060f1SDimitry Andric   // Register above __dtor with atexit().
5163fe6060f1SDimitry Andric   CGF.registerGlobalDtorWithAtExit(DtorStub);
51645ffd83dbSDimitry Andric 
51655ffd83dbSDimitry Andric   // Emit __finalize function to unregister __dtor and (as appropriate) call
51665ffd83dbSDimitry Andric   // __dtor.
5167fe6060f1SDimitry Andric   emitCXXStermFinalizer(D, DtorStub, Addr);
51685ffd83dbSDimitry Andric }
51695ffd83dbSDimitry Andric 
51705ffd83dbSDimitry Andric void XLCXXABI::emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
51715ffd83dbSDimitry Andric                                      llvm::Constant *addr) {
51725ffd83dbSDimitry Andric   llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
51735ffd83dbSDimitry Andric   SmallString<256> FnName;
51745ffd83dbSDimitry Andric   {
51755ffd83dbSDimitry Andric     llvm::raw_svector_ostream Out(FnName);
51765ffd83dbSDimitry Andric     getMangleContext().mangleDynamicStermFinalizer(&D, Out);
51775ffd83dbSDimitry Andric   }
51785ffd83dbSDimitry Andric 
51795ffd83dbSDimitry Andric   // Create the finalization action associated with a variable.
51805ffd83dbSDimitry Andric   const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
51815ffd83dbSDimitry Andric   llvm::Function *StermFinalizer = CGM.CreateGlobalInitOrCleanUpFunction(
51825ffd83dbSDimitry Andric       FTy, FnName.str(), FI, D.getLocation());
51835ffd83dbSDimitry Andric 
51845ffd83dbSDimitry Andric   CodeGenFunction CGF(CGM);
51855ffd83dbSDimitry Andric 
51865ffd83dbSDimitry Andric   CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, StermFinalizer, FI,
5187e8d8bef9SDimitry Andric                     FunctionArgList(), D.getLocation(),
5188e8d8bef9SDimitry Andric                     D.getInit()->getExprLoc());
51895ffd83dbSDimitry Andric 
51905ffd83dbSDimitry Andric   // The unatexit subroutine unregisters __dtor functions that were previously
51915ffd83dbSDimitry Andric   // registered by the atexit subroutine. If the referenced function is found,
51925ffd83dbSDimitry Andric   // the unatexit returns a value of 0, meaning that the cleanup is still
51935ffd83dbSDimitry Andric   // pending (and we should call the __dtor function).
51945ffd83dbSDimitry Andric   llvm::Value *V = CGF.unregisterGlobalDtorWithUnAtExit(dtorStub);
51955ffd83dbSDimitry Andric 
51965ffd83dbSDimitry Andric   llvm::Value *NeedsDestruct = CGF.Builder.CreateIsNull(V, "needs_destruct");
51975ffd83dbSDimitry Andric 
51985ffd83dbSDimitry Andric   llvm::BasicBlock *DestructCallBlock = CGF.createBasicBlock("destruct.call");
51995ffd83dbSDimitry Andric   llvm::BasicBlock *EndBlock = CGF.createBasicBlock("destruct.end");
52005ffd83dbSDimitry Andric 
52015ffd83dbSDimitry Andric   // Check if unatexit returns a value of 0. If it does, jump to
52025ffd83dbSDimitry Andric   // DestructCallBlock, otherwise jump to EndBlock directly.
52035ffd83dbSDimitry Andric   CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
52045ffd83dbSDimitry Andric 
52055ffd83dbSDimitry Andric   CGF.EmitBlock(DestructCallBlock);
52065ffd83dbSDimitry Andric 
52075ffd83dbSDimitry Andric   // Emit the call to dtorStub.
52085ffd83dbSDimitry Andric   llvm::CallInst *CI = CGF.Builder.CreateCall(dtorStub);
52095ffd83dbSDimitry Andric 
52105ffd83dbSDimitry Andric   // Make sure the call and the callee agree on calling convention.
52115ffd83dbSDimitry Andric   CI->setCallingConv(dtorStub->getCallingConv());
52125ffd83dbSDimitry Andric 
52135ffd83dbSDimitry Andric   CGF.EmitBlock(EndBlock);
52145ffd83dbSDimitry Andric 
52155ffd83dbSDimitry Andric   CGF.FinishFunction();
52165ffd83dbSDimitry Andric 
5217fe6060f1SDimitry Andric   if (auto *IPA = D.getAttr<InitPriorityAttr>()) {
5218fe6060f1SDimitry Andric     CGM.AddCXXPrioritizedStermFinalizerEntry(StermFinalizer,
5219fe6060f1SDimitry Andric                                              IPA->getPriority());
5220fe6060f1SDimitry Andric   } else if (isTemplateInstantiation(D.getTemplateSpecializationKind()) ||
5221fe6060f1SDimitry Andric              getContext().GetGVALinkageForVariable(&D) == GVA_DiscardableODR) {
5222e8d8bef9SDimitry Andric     // According to C++ [basic.start.init]p2, class template static data
5223e8d8bef9SDimitry Andric     // members (i.e., implicitly or explicitly instantiated specializations)
5224e8d8bef9SDimitry Andric     // have unordered initialization. As a consequence, we can put them into
5225e8d8bef9SDimitry Andric     // their own llvm.global_dtors entry.
5226e8d8bef9SDimitry Andric     CGM.AddCXXStermFinalizerToGlobalDtor(StermFinalizer, 65535);
5227fe6060f1SDimitry Andric   } else {
52285ffd83dbSDimitry Andric     CGM.AddCXXStermFinalizerEntry(StermFinalizer);
52295ffd83dbSDimitry Andric   }
5230fe6060f1SDimitry Andric }
5231