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