32#include "llvm/IR/DataLayout.h"
33#include "llvm/IR/GlobalValue.h"
34#include "llvm/IR/Instructions.h"
35#include "llvm/IR/Intrinsics.h"
36#include "llvm/IR/Value.h"
37#include "llvm/Support/ScopedPrinter.h"
42using namespace CodeGen;
47 llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
54 bool UseARMMethodPtrABI;
55 bool UseARMGuardVarABI;
56 bool Use32BitVTableOffsetABI;
64 bool UseARMMethodPtrABI =
false,
65 bool UseARMGuardVarABI =
false) :
66 CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
67 UseARMGuardVarABI(UseARMGuardVarABI),
68 Use32BitVTableOffsetABI(
false) { }
82 if (isa<CXXDestructorDecl>(GD.
getDecl())) {
92 llvm_unreachable(
"emitting dtor comdat as function?");
94 llvm_unreachable(
"bad dtor kind");
96 if (isa<CXXConstructorDecl>(GD.
getDecl())) {
106 llvm_unreachable(
"closure ctors in Itanium ABI?");
109 llvm_unreachable(
"emitting ctor comdat as function?");
111 llvm_unreachable(
"bad dtor kind");
126 llvm::Value *&ThisPtrForCall,
127 llvm::Value *MemFnPtr,
138 llvm::Value *Src)
override;
140 llvm::Constant *Src)
override;
152 llvm::Value *L, llvm::Value *R,
154 bool Inequality)
override;
171 llvm::Value *Exn)
override;
173 void EmitFundamentalRTTIDescriptors(
const CXXRecordDecl *RD);
177 QualType CatchHandlerType)
override {
185 llvm::Type *StdTypeInfoPtrTy)
override;
194 bool hasUniqueVTablePointer(
QualType RecordTy) {
199 if (!CGM.getCodeGenOpts().AssumeUniqueVTables ||
200 getContext().getLangOpts().AppleKext)
205 if (!CGM.shouldEmitRTTI())
210 if (!llvm::GlobalValue::isWeakForLinker(CGM.getVTableLinkage(RD)))
219 llvm::GlobalValue::DefaultVisibility)
226 return hasUniqueVTablePointer(DestRecordTy);
232 llvm::BasicBlock *CastEnd)
override;
237 llvm::BasicBlock *CastSuccess,
238 llvm::BasicBlock *CastFail)
override;
252 AddedStructorArgCounts
292 CodeGenFunction::VPtr Vptr)
override;
306 llvm::Value *getVTableAddressPointInStructorWithVTT(
320 DeleteOrMemberCallExpr
E,
321 llvm::CallBase **CallOrInvoke)
override;
326 bool canSpeculativelyEmitVTableAsBaseClass(
const CXXRecordDecl *RD)
const;
332 if (ForVTable && !Thunk->hasLocalLinkage())
333 Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
334 CGM.setGVProperties(Thunk, GD);
349 assert(!Args.empty() &&
"expected the arglist to not be empty!");
350 return Args.size() - 1;
355 {
return "__cxa_deleted_virtual"; }
360 llvm::Value *NumElements,
368 llvm::GlobalVariable *DeclPtr,
369 bool PerformInit)
override;
371 llvm::FunctionCallee dtor,
372 llvm::Constant *addr)
override;
374 llvm::Function *getOrCreateThreadLocalWrapper(
const VarDecl *VD,
392 getOrCreateVirtualFunctionPointerThunk(
const CXXMethodDecl *MD);
399 virtual bool shouldRTTIBeUnique()
const {
return true; }
403 enum RTTIUniquenessKind {
421 classifyRTTIUniqueness(
QualType CanTy,
422 llvm::GlobalValue::LinkageTypes
Linkage)
const;
423 friend class ItaniumRTTIBuilder;
427 std::pair<llvm::Value *, const CXXRecordDecl *>
433 getSignedVirtualMemberFunctionPointer(
const CXXMethodDecl *MD);
435 bool hasAnyUnusedVirtualInlineFunction(
const CXXRecordDecl *RD)
const {
436 const auto &VtableLayout =
437 CGM.getItaniumVTableContext().getVTableLayout(RD);
439 for (
const auto &VtableComponent : VtableLayout.vtable_components()) {
441 if (!VtableComponent.isUsedFunctionPointerKind())
444 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
446 const bool IsInlined =
451 StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
452 auto *Entry = CGM.GetGlobalValue(Name);
458 if (!Entry || Entry->isDeclaration())
465 const auto &VtableLayout =
466 CGM.getItaniumVTableContext().getVTableLayout(RD);
468 for (
const auto &VtableComponent : VtableLayout.vtable_components()) {
469 if (VtableComponent.isRTTIKind()) {
470 const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();
471 if (RTTIDecl->
getVisibility() == Visibility::HiddenVisibility)
473 }
else if (VtableComponent.isUsedFunctionPointerKind()) {
474 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
475 if (Method->
getVisibility() == Visibility::HiddenVisibility &&
484class ARMCXXABI :
public ItaniumCXXABI {
487 ItaniumCXXABI(CGM,
true,
490 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
498 llvm::Value *NumElements,
505class AppleARM64CXXABI :
public ARMCXXABI {
508 Use32BitVTableOffsetABI =
true;
512 bool shouldRTTIBeUnique()
const override {
return false; }
515class FuchsiaCXXABI final :
public ItaniumCXXABI {
518 : ItaniumCXXABI(CGM) {}
521 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
524class WebAssemblyCXXABI final :
public ItaniumCXXABI {
527 : ItaniumCXXABI(CGM,
true,
532 llvm::Value *Exn)
override;
535 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
536 bool canCallMismatchedFunctionType()
const override {
return false; }
539class XLCXXABI final :
public ItaniumCXXABI {
542 : ItaniumCXXABI(CGM) {}
545 llvm::FunctionCallee dtor,
546 llvm::Constant *addr)
override;
548 bool useSinitAndSterm()
const override {
return true; }
551 void emitCXXStermFinalizer(
const VarDecl &
D, llvm::Function *dtorStub,
552 llvm::Constant *addr);
560 case TargetCXXABI::GenericARM:
561 case TargetCXXABI::iOS:
562 case TargetCXXABI::WatchOS:
563 return new ARMCXXABI(CGM);
565 case TargetCXXABI::AppleARM64:
566 return new AppleARM64CXXABI(CGM);
568 case TargetCXXABI::Fuchsia:
569 return new FuchsiaCXXABI(CGM);
574 case TargetCXXABI::GenericAArch64:
575 return new ItaniumCXXABI(CGM,
true,
578 case TargetCXXABI::GenericMIPS:
579 return new ItaniumCXXABI(CGM,
true);
581 case TargetCXXABI::WebAssembly:
582 return new WebAssemblyCXXABI(CGM);
584 case TargetCXXABI::XL:
585 return new XLCXXABI(CGM);
587 case TargetCXXABI::GenericItanium:
588 return new ItaniumCXXABI(CGM);
590 case TargetCXXABI::Microsoft:
591 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
593 llvm_unreachable(
"bad ABI kind");
599 return CGM.PtrDiffTy;
600 return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);
623CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
625 llvm::Value *&ThisPtrForCall,
634 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
641 llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1,
"memptr.adj");
644 llvm::Value *Adj = RawAdj;
645 if (UseARMMethodPtrABI)
646 Adj = Builder.CreateAShr(Adj, ptrdiff_1,
"memptr.adj.shifted");
651 This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj);
652 ThisPtrForCall = This;
655 llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0,
"memptr.ptr");
659 llvm::Value *IsVirtual;
660 if (UseARMMethodPtrABI)
661 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
663 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
664 IsVirtual = Builder.CreateIsNotNull(IsVirtual,
"memptr.isvirtual");
665 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
683 llvm::Value *VTableOffset = FnAsInt;
684 if (!UseARMMethodPtrABI)
685 VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
686 if (Use32BitVTableOffsetABI) {
687 VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.
Int32Ty);
688 VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
693 llvm::Constant *CheckSourceLocation;
694 llvm::Constant *CheckTypeDesc;
695 bool ShouldEmitCFICheck = CGF.
SanOpts.
has(SanitizerKind::CFIMFCall) &&
696 CGM.HasHiddenLTOVisibility(RD);
697 bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
698 CGM.HasHiddenLTOVisibility(RD);
699 bool ShouldEmitWPDInfo =
700 CGM.getCodeGenOpts().WholeProgramVTables &&
702 !CGM.AlwaysHasLTOVisibilityPublic(RD);
703 llvm::Value *VirtualFn =
nullptr;
706 CodeGenFunction::SanitizerScope SanScope(&CGF);
707 llvm::Value *TypeId =
nullptr;
708 llvm::Value *CheckResult =
nullptr;
710 if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
714 CGM.CreateMetadataIdentifierForVirtualMemPtrType(
QualType(MPT, 0));
718 if (ShouldEmitVFEInfo) {
719 llvm::Value *VFPAddr =
720 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
727 llvm::Value *CheckedLoad = Builder.CreateCall(
728 CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
729 {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
730 CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
731 VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
735 if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
736 llvm::Value *VFPAddr =
737 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
738 llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
739 ? llvm::Intrinsic::type_test
740 : llvm::Intrinsic::public_type_test;
743 Builder.CreateCall(CGM.getIntrinsic(IID), {VFPAddr, TypeId});
746 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
747 VirtualFn = CGF.
Builder.CreateCall(
748 CGM.getIntrinsic(llvm::Intrinsic::load_relative,
749 {VTableOffset->getType()}),
750 {VTable, VTableOffset});
752 llvm::Value *VFPAddr =
759 assert(VirtualFn &&
"Virtual fuction pointer not created!");
760 assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
762 "Check result required but not created!");
764 if (ShouldEmitCFICheck) {
768 llvm::Constant *StaticData[] = {
769 llvm::ConstantInt::get(CGF.
Int8Ty, CodeGenFunction::CFITCK_VMFCall),
774 if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
775 CGF.
EmitTrapCheck(CheckResult, SanitizerHandler::CFICheckFail);
777 llvm::Value *AllVtables = llvm::MetadataAsValue::get(
778 CGM.getLLVMContext(),
779 llvm::MDString::get(CGM.getLLVMContext(),
"all-vtables"));
780 llvm::Value *ValidVtable = Builder.CreateCall(
781 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
782 CGF.
EmitCheck(std::make_pair(CheckResult, SanitizerKind::SO_CFIMFCall),
783 SanitizerHandler::CFICheckFail, StaticData,
784 {VTable, ValidVtable});
787 FnVirtual = Builder.GetInsertBlock();
796 llvm::Value *NonVirtualFn =
797 Builder.CreateIntToPtr(FnAsInt, CGF.
UnqualPtrTy,
"memptr.nonvirtualfn");
800 if (ShouldEmitCFICheck) {
803 CodeGenFunction::SanitizerScope SanScope(&CGF);
805 llvm::Constant *StaticData[] = {
806 llvm::ConstantInt::get(CGF.
Int8Ty, CodeGenFunction::CFITCK_NVMFCall),
811 llvm::Value *Bit = Builder.getFalse();
813 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
814 getContext().getMemberPointerType(
817 llvm::Value *TypeId =
820 llvm::Value *TypeTest =
821 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
822 {NonVirtualFn, TypeId});
823 Bit = Builder.CreateOr(Bit, TypeTest);
826 CGF.
EmitCheck(std::make_pair(Bit, SanitizerKind::SO_CFIMFCall),
827 SanitizerHandler::CFICheckFail, StaticData,
828 {NonVirtualFn, llvm::UndefValue::get(CGF.
IntPtrTy)});
830 FnNonVirtual = Builder.GetInsertBlock();
836 llvm::PHINode *CalleePtr = Builder.CreatePHI(CGF.
UnqualPtrTy, 2);
837 CalleePtr->addIncoming(VirtualFn, FnVirtual);
838 CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
842 if (
const auto &Schema =
843 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers) {
844 llvm::PHINode *DiscriminatorPHI = Builder.CreatePHI(CGF.
IntPtrTy, 2);
845 DiscriminatorPHI->addIncoming(llvm::ConstantInt::get(CGF.
IntPtrTy, 0),
847 const auto &AuthInfo =
848 CGM.getMemberFunctionPointerAuthInfo(
QualType(MPT, 0));
849 assert(Schema.getKey() == AuthInfo.getKey() &&
850 "Keys for virtual and non-virtual member functions must match");
851 auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator();
852 DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual);
854 Schema.getKey(), Schema.getAuthenticationMode(), Schema.isIsaPointer(),
855 Schema.authenticatesNullValues(), DiscriminatorPHI);
864llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
867 assert(MemPtr->getType() == CGM.PtrDiffTy);
872 return Builder.CreateInBoundsGEP(CGF.
Int8Ty,
Base.emitRawPointer(CGF), MemPtr,
880 const auto *CPA = dyn_cast<llvm::ConstantPtrAuth>(Ptr);
885 assert(CPA->getKey()->getZExtValue() == CurAuthInfo.
getKey() &&
886 CPA->getAddrDiscriminator()->isZeroValue() &&
888 "unexpected key or discriminators");
891 CPA->getPointer(), NewAuthInfo.
getKey(),
nullptr,
923 if (isa<llvm::Constant>(src))
924 return EmitMemberPointerConversion(
E, cast<llvm::Constant>(src));
926 assert(
E->getCastKind() == CK_DerivedToBaseMemberPointer ||
927 E->getCastKind() == CK_BaseToDerivedMemberPointer ||
928 E->getCastKind() == CK_ReinterpretMemberPointer);
934 if (
const auto &NewAuthInfo =
935 CGM.getMemberFunctionPointerAuthInfo(DstType)) {
938 const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType);
939 llvm::Value *MemFnPtr = Builder.CreateExtractValue(src, 0,
"memptr.ptr");
940 llvm::Type *OrigTy = MemFnPtr->getType();
942 llvm::BasicBlock *StartBB = Builder.GetInsertBlock();
947 assert(UseARMMethodPtrABI &&
"ARM ABI expected");
948 llvm::Value *Adj = Builder.CreateExtractValue(src, 1,
"memptr.adj");
949 llvm::Constant *Ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
950 llvm::Value *AndVal = Builder.CreateAnd(Adj, Ptrdiff_1);
951 llvm::Value *IsVirtualOffset =
952 Builder.CreateIsNotNull(AndVal,
"is.virtual.offset");
953 Builder.CreateCondBr(IsVirtualOffset, MergeBB, ResignBB);
956 llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGM.Int8Ty);
957 MemFnPtr = Builder.CreateIntToPtr(MemFnPtr, PtrTy);
960 isa<llvm::Constant>(src));
961 MemFnPtr = Builder.CreatePtrToInt(MemFnPtr, OrigTy);
962 llvm::Value *ResignedVal = Builder.CreateInsertValue(src, MemFnPtr, 0);
963 ResignBB = Builder.GetInsertBlock();
966 llvm::PHINode *NewSrc = Builder.CreatePHI(src->getType(), 2);
967 NewSrc->addIncoming(src, StartBB);
968 NewSrc->addIncoming(ResignedVal, ResignBB);
974 if (
E->getCastKind() == CK_ReinterpretMemberPointer)
return src;
976 llvm::Constant *adj = getMemberPointerAdjustment(
E);
977 if (!adj)
return src;
979 bool isDerivedToBase = (
E->getCastKind() == CK_DerivedToBaseMemberPointer);
989 dst = Builder.CreateNSWSub(src, adj,
"adj");
991 dst = Builder.CreateNSWAdd(src, adj,
"adj");
994 llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType());
995 llvm::Value *isNull = Builder.CreateICmpEQ(src, null,
"memptr.isnull");
996 return Builder.CreateSelect(isNull, src, dst);
1000 if (UseARMMethodPtrABI) {
1001 uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
1003 adj = llvm::ConstantInt::get(adj->getType(), offset);
1006 llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1,
"src.adj");
1007 llvm::Value *dstAdj;
1008 if (isDerivedToBase)
1009 dstAdj = Builder.CreateNSWSub(srcAdj, adj,
"adj");
1011 dstAdj = Builder.CreateNSWAdd(srcAdj, adj,
"adj");
1013 return Builder.CreateInsertValue(src, dstAdj, 1);
1016static llvm::Constant *
1021 "member function pointers expected");
1022 if (DestType == SrcType)
1028 if (!NewAuthInfo && !CurAuthInfo)
1031 llvm::Constant *MemFnPtr = Src->getAggregateElement(0u);
1032 if (MemFnPtr->getNumOperands() == 0) {
1034 assert(isa<llvm::ConstantInt>(MemFnPtr) &&
"constant int expected");
1039 cast<llvm::User>(MemFnPtr)->getOperand(0), CurAuthInfo, NewAuthInfo, CGM);
1040 ConstPtr = llvm::ConstantExpr::getPtrToInt(ConstPtr, MemFnPtr->getType());
1041 return ConstantFoldInsertValueInstruction(Src, ConstPtr, 0);
1045ItaniumCXXABI::EmitMemberPointerConversion(
const CastExpr *
E,
1046 llvm::Constant *src) {
1047 assert(
E->getCastKind() == CK_DerivedToBaseMemberPointer ||
1048 E->getCastKind() == CK_BaseToDerivedMemberPointer ||
1049 E->getCastKind() == CK_ReinterpretMemberPointer);
1055 src, DstType,
E->getSubExpr()->
getType(), CGM);
1058 if (
E->getCastKind() == CK_ReinterpretMemberPointer)
return src;
1061 llvm::Constant *adj = getMemberPointerAdjustment(
E);
1062 if (!adj)
return src;
1064 bool isDerivedToBase = (
E->getCastKind() == CK_DerivedToBaseMemberPointer);
1073 if (src->isAllOnesValue())
return src;
1075 if (isDerivedToBase)
1076 return llvm::ConstantExpr::getNSWSub(src, adj);
1078 return llvm::ConstantExpr::getNSWAdd(src, adj);
1082 if (UseARMMethodPtrABI) {
1083 uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
1085 adj = llvm::ConstantInt::get(adj->getType(), offset);
1088 llvm::Constant *srcAdj = src->getAggregateElement(1);
1089 llvm::Constant *dstAdj;
1090 if (isDerivedToBase)
1091 dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);
1093 dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);
1095 llvm::Constant *res = ConstantFoldInsertValueInstruction(src, dstAdj, 1);
1096 assert(res !=
nullptr &&
"Folding must succeed");
1105 return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL,
true);
1107 llvm::Constant *
Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
1108 llvm::Constant *Values[2] = {
Zero,
Zero };
1109 return llvm::ConstantStruct::getAnon(Values);
1118 return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.
getQuantity());
1122ItaniumCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
1126llvm::Constant *ItaniumCXXABI::BuildMemberPointer(
const CXXMethodDecl *MD,
1128 assert(MD->
isInstance() &&
"Member function must not be static!");
1133 llvm::Constant *MemPtr[2];
1135 uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
1137 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1139 VTableOffset = Index * 4;
1144 VTableOffset = Index * PointerWidth.
getQuantity();
1147 if (UseARMMethodPtrABI) {
1169 const auto &Schema =
1170 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers;
1172 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(
1173 getSignedVirtualMemberFunctionPointer(MD), CGM.PtrDiffTy);
1175 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);
1178 MemPtr[1] = llvm::ConstantInt::get(
1185 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
1186 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1193 if (Types.isFuncTypeConvertible(FPT)) {
1195 Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
1201 llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty);
1203 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
1204 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1205 (UseARMMethodPtrABI ? 2 : 1) *
1209 return llvm::ConstantStruct::getAnon(MemPtr);
1212llvm::Constant *ItaniumCXXABI::EmitMemberPointer(
const APValue &MP,
1217 return EmitNullMemberPointer(MPT);
1221 if (
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
1223 QualType SrcType = getContext().getMemberPointerType(
1229 getContext().toCharUnitsFromBits(getContext().
getFieldOffset(MPD));
1245 llvm::ICmpInst::Predicate
Eq;
1246 llvm::Instruction::BinaryOps
And,
Or;
1248 Eq = llvm::ICmpInst::ICMP_NE;
1249 And = llvm::Instruction::Or;
1250 Or = llvm::Instruction::And;
1252 Eq = llvm::ICmpInst::ICMP_EQ;
1253 And = llvm::Instruction::And;
1254 Or = llvm::Instruction::Or;
1260 return Builder.CreateICmp(
Eq, L, R);
1272 llvm::Value *LPtr = Builder.CreateExtractValue(L, 0,
"lhs.memptr.ptr");
1273 llvm::Value *RPtr = Builder.CreateExtractValue(R, 0,
"rhs.memptr.ptr");
1277 llvm::Value *PtrEq = Builder.CreateICmp(
Eq, LPtr, RPtr,
"cmp.ptr");
1282 llvm::Value *
Zero = llvm::Constant::getNullValue(LPtr->getType());
1283 llvm::Value *EqZero = Builder.CreateICmp(
Eq, LPtr, Zero,
"cmp.ptr.null");
1287 llvm::Value *LAdj = Builder.CreateExtractValue(L, 1,
"lhs.memptr.adj");
1288 llvm::Value *RAdj = Builder.CreateExtractValue(R, 1,
"rhs.memptr.adj");
1289 llvm::Value *AdjEq = Builder.CreateICmp(
Eq, LAdj, RAdj,
"cmp.adj");
1293 if (UseARMMethodPtrABI) {
1294 llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
1297 llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj,
"or.adj");
1298 llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
1299 llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(
Eq, OrAdjAnd1, Zero,
1301 EqZero = Builder.CreateBinOp(
And, EqZero, OrAdjAnd1EqZero);
1305 llvm::Value *Result = Builder.CreateBinOp(
Or, EqZero, AdjEq);
1306 Result = Builder.CreateBinOp(
And, PtrEq, Result,
1307 Inequality ?
"memptr.ne" :
"memptr.eq");
1313 llvm::Value *MemPtr,
1319 assert(MemPtr->getType() == CGM.PtrDiffTy);
1320 llvm::Value *NegativeOne =
1321 llvm::Constant::getAllOnesValue(MemPtr->getType());
1322 return Builder.CreateICmpNE(MemPtr, NegativeOne,
"memptr.tobool");
1326 llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0,
"memptr.ptr");
1328 llvm::Constant *
Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
1329 llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero,
"memptr.tobool");
1333 if (UseARMMethodPtrABI) {
1334 llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
1335 llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1,
"memptr.adj");
1336 llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One,
"memptr.virtualbit");
1337 llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,
1338 "memptr.isvirtual");
1339 Result = Builder.CreateOr(Result, IsVirtual);
1345bool ItaniumCXXABI::classifyReturnType(
CGFunctionInfo &FI)
const {
1352 auto Align = CGM.getContext().getTypeAlignInChars(FI.
getReturnType());
1373 if (UseGlobalDelete) {
1383 llvm::Value *OffsetPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
1384 CGF.
IntPtrTy, VTable, -2,
"complete-offset.ptr");
1402 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,
1405 if (UseGlobalDelete)
1409void ItaniumCXXABI::emitRethrow(
CodeGenFunction &CGF,
bool isNoReturn) {
1412 llvm::FunctionType *FTy =
1413 llvm::FunctionType::get(CGM.VoidTy,
false);
1415 llvm::FunctionCallee
Fn = CGM.CreateRuntimeFunction(FTy,
"__cxa_rethrow");
1426 llvm::FunctionType *FTy =
1437 llvm::FunctionType *FTy =
1438 llvm::FunctionType::get(CGM.
VoidTy, Args,
false);
1446 llvm::Type *SizeTy = CGF.
ConvertType(getContext().getSizeType());
1447 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
1451 AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize),
"exception");
1455 E->getSubExpr(),
Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
1458 llvm::Constant *
TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
1463 llvm::Constant *Dtor =
nullptr;
1466 if (!
Record->hasTrivialDestructor()) {
1476 Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
1479 if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1481 llvm::Value *args[] = { ExceptionPtr,
TypeInfo, Dtor };
1493 llvm::Type *PtrDiffTy =
1496 llvm::Type *Args[4] = { Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy };
1498 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args,
false);
1502 FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
1503 FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
1504 FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
1505 llvm::AttributeList Attrs = llvm::AttributeList::get(
1506 CGF.
getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
1513 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1530 unsigned NumPublicPaths = 0;
1543 if (PathElement.Base->isVirtual())
1546 if (NumPublicPaths > 1)
1552 PathElement.Base->getType()->getAsCXXRecordDecl());
1557 if (NumPublicPaths == 0)
1561 if (NumPublicPaths > 1)
1571 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1576bool ItaniumCXXABI::shouldTypeidBeNullChecked(
QualType SrcRecordTy) {
1583 Call->setDoesNotReturn();
1584 CGF.
Builder.CreateUnreachable();
1590 llvm::Type *StdTypeInfoPtrTy) {
1596 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1599 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1600 {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
1604 CGF.
Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy,
Value, -1ULL);
1610bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
1615llvm::Value *ItaniumCXXABI::emitDynamicCastCall(
1618 llvm::Type *PtrDiffLTy =
1621 llvm::Value *SrcRTTI =
1623 llvm::Value *DestRTTI =
1629 llvm::Value *OffsetHint = llvm::ConstantInt::get(
1635 if (CGM.getCodeGenOpts().PointerAuth.CXXVTablePointers) {
1641 llvm::Value *Vtable =
1643 CodeGenFunction::VTableAuthMode::MustTrap);
1648 llvm::Value *args[] = {
Value, SrcRTTI, DestRTTI, OffsetHint};
1654 llvm::BasicBlock *BadCastBlock =
1661 EmitBadCastCall(CGF);
1667llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
1670 llvm::BasicBlock *CastFail) {
1682 std::optional<CharUnits> Offset;
1692 PathElement.Base->getType()->getAsCXXRecordDecl();
1693 if (PathElement.Base->isVirtual()) {
1706 Offset = PathOffset;
1707 else if (Offset != PathOffset) {
1712 ThisAddr =
Address(emitDynamicCastToVoid(CGF, ThisAddr, SrcRecordTy),
1723 return llvm::PoisonValue::get(CGF.
VoidPtrTy);
1732 CGM.DecorateInstructionWithTBAA(
1733 VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.
VoidPtrPtrTy));
1735 VPtr, getVTableAddressPoint(
BaseSubobject(SrcDecl, *Offset), DestDecl));
1737 if (!Offset->isZero())
1740 {llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset->getQuantity())});
1745llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(
CodeGenFunction &CGF,
1750 llvm::Value *OffsetToTop;
1751 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1753 llvm::Value *VTable =
1758 CGF.
Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);
1762 llvm::Type *PtrDiffLTy =
1766 llvm::Value *VTable =
1771 CGF.
Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
1783 Call->setDoesNotReturn();
1784 CGF.
Builder.CreateUnreachable();
1793 llvm::Value *VTablePtr = CGF.
GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
1795 CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
1797 llvm::Value *VBaseOffsetPtr =
1798 CGF.
Builder.CreateConstGEP1_64(
1800 "vbase.offset.ptr");
1802 llvm::Value *VBaseOffset;
1803 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1809 CGM.PtrDiffTy, VBaseOffsetPtr, CGF.
getPointerAlign(),
"vbase.offset");
1816 assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
1824 if (!
D->getParent()->isAbstract()) {
1831ItaniumCXXABI::buildStructorSignature(
GlobalDecl GD,
1841 cast<CXXMethodDecl>(GD.
getDecl())->getParent()->getNumVBases() != 0) {
1842 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
1844 ArgTys.insert(ArgTys.begin() + 1,
1846 return AddedStructorArgCounts::prefix(1);
1848 return AddedStructorArgCounts{};
1871 assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
1874 if (NeedsVTTParameter(CGF.
CurGD)) {
1878 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
1883 T, ImplicitParamKind::CXXVTT);
1884 Params.insert(Params.begin() + 1, VTTDecl);
1885 getStructorImplicitParamDecl(CGF) = VTTDecl;
1896 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
1899 if (getStructorImplicitParamDecl(CGF)) {
1912 if (HasThisReturn(CGF.
CurGD))
1920 return AddedStructorArgs{};
1927 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
1928 QualType Q = getContext().getAddrSpaceQualType(getContext().VoidPtrTy, AS);
1929 QualType VTTTy = getContext().getPointerType(Q);
1930 return AddedStructorArgs::prefix({{VTT, VTTTy}});
1933llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(
1948 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1951 if (getContext().getLangOpts().AppleKext &&
1958 ThisTy, VTT, VTTTy,
nullptr);
1962template <
typename T>
1965 if (
const auto *FD = dyn_cast<FunctionDecl>(
D)) {
1978 llvm::GlobalVariable *VTable,
1980 if (VTable->getDLLStorageClass() !=
1981 llvm::GlobalVariable::DefaultStorageClass ||
1986 if (CXXRecordNonInlineHasAttr<DLLImportAttr>(RD))
1987 VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
1988 }
else if (CXXRecordNonInlineHasAttr<DLLExportAttr>(RD))
1989 VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1994 llvm::GlobalVariable *VTable = getAddrOfVTable(RD,
CharUnits());
1995 if (VTable->hasInitializer())
2000 llvm::GlobalVariable::LinkageTypes
Linkage = CGM.getVTableLinkage(RD);
2001 llvm::Constant *RTTI =
2002 CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
2006 auto components = builder.beginStruct();
2008 llvm::GlobalValue::isLocalLinkage(
Linkage));
2009 components.finishAndSetAsInitializer(VTable);
2014 if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
2015 VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
2017 if (CGM.getTarget().hasPS4DLLImportExport())
2021 CGM.setGVProperties(VTable, RD);
2029 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
2030 cast<NamespaceDecl>(DC)->getIdentifier()->isStr(
"__cxxabiv1") &&
2032 EmitFundamentalRTTIDescriptors(RD);
2039 if (!VTable->isDeclarationForLinker() ||
2040 CGM.getCodeGenOpts().WholeProgramVTables) {
2041 CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
2045 if (VTable->isDeclarationForLinker()) {
2046 assert(CGM.getCodeGenOpts().WholeProgramVTables);
2047 CGM.addCompilerUsedGlobal(VTable);
2053 if (!VTable->isDSOLocal())
2058bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
2060 if (Vptr.NearestVBase ==
nullptr)
2062 return NeedsVTTParameter(CGF.
CurGD);
2065llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
2069 if ((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
2070 NeedsVTTParameter(CGF.
CurGD)) {
2071 return getVTableAddressPointInStructorWithVTT(CGF, VTableClass,
Base,
2074 return getVTableAddressPoint(
Base, VTableClass);
2080 llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass,
CharUnits());
2085 CGM.getItaniumVTableContext().getVTableLayout(VTableClass);
2088 llvm::Value *Indices[] = {
2089 llvm::ConstantInt::get(CGM.Int32Ty, 0),
2090 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.
VTableIndex),
2096 unsigned ComponentSize =
2097 CGM.getDataLayout().getTypeAllocSize(CGM.getVTableComponentType());
2098 unsigned VTableSize =
2102 llvm::APInt(32, (
int)-Offset,
true),
2103 llvm::APInt(32, (
int)(VTableSize - Offset),
true));
2104 return llvm::ConstantExpr::getGetElementPtr(
2105 VTable->getValueType(), VTable, Indices,
true, InRange);
2108llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
2111 assert((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
2112 NeedsVTTParameter(CGF.
CurGD) &&
"This class doesn't have VTT");
2116 CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass,
Base);