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"
39 using namespace clang;
40 using namespace CodeGen;
45 llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
52 bool UseARMMethodPtrABI;
53 bool UseARMGuardVarABI;
54 bool Use32BitVTableOffsetABI;
62 bool UseARMMethodPtrABI =
false,
63 bool UseARMGuardVarABI =
false) :
64 CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
65 UseARMGuardVarABI(UseARMGuardVarABI),
66 Use32BitVTableOffsetABI(
false) { }
77 bool isThisCompleteObject(
GlobalDecl GD)
const override {
80 if (isa<CXXDestructorDecl>(GD.
getDecl())) {
90 llvm_unreachable(
"emitting dtor comdat as function?");
92 llvm_unreachable(
"bad dtor kind");
94 if (isa<CXXConstructorDecl>(GD.
getDecl())) {
104 llvm_unreachable(
"closure ctors in Itanium ABI?");
107 llvm_unreachable(
"emitting ctor comdat as function?");
109 llvm_unreachable(
"bad dtor kind");
124 llvm::Value *&ThisPtrForCall,
125 llvm::Value *MemFnPtr,
136 llvm::Value *Src)
override;
137 llvm::Constant *EmitMemberPointerConversion(
const CastExpr *E,
138 llvm::Constant *Src)
override;
142 llvm::Constant *EmitMemberFunctionPointer(
const CXXMethodDecl *MD)
override;
145 llvm::Constant *EmitMemberPointer(
const APValue &MP,
QualType MPT)
override;
150 llvm::Value *L, llvm::Value *R,
152 bool Inequality)
override;
169 llvm::Value *Exn)
override;
171 void EmitFundamentalRTTIDescriptors(
const CXXRecordDecl *RD);
172 llvm::Constant *getAddrOfRTTIDescriptor(
QualType Ty)
override;
174 getAddrOfCXXCatchHandlerType(
QualType Ty,
175 QualType CatchHandlerType)
override {
179 bool shouldTypeidBeNullChecked(
bool IsDeref,
QualType SrcRecordTy)
override;
183 llvm::Type *StdTypeInfoPtrTy)
override;
185 bool shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
191 llvm::BasicBlock *CastEnd)
override;
206 AddedStructorArgCounts
229 bool Delegating)
override;
235 bool Delegating)
override;
248 bool doStructorsInitializeVPtrs(
const CXXRecordDecl *VTableClass)
override {
256 llvm::Value *getVTableAddressPointInStructor(
260 llvm::Value *getVTableAddressPointInStructorWithVTT(
268 llvm::GlobalVariable *getAddrOfVTable(
const CXXRecordDecl *RD,
278 DeleteOrMemberCallExpr E)
override;
280 void emitVirtualInheritanceTables(
const CXXRecordDecl *RD)
override;
282 bool canSpeculativelyEmitVTable(
const CXXRecordDecl *RD)
const override;
283 bool canSpeculativelyEmitVTableAsBaseClass(
const CXXRecordDecl *RD)
const;
285 void setThunkLinkage(llvm::Function *Thunk,
bool ForVTable,
GlobalDecl GD,
289 if (ForVTable && !Thunk->hasLocalLinkage())
290 Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
291 CGM.setGVProperties(Thunk, GD);
294 bool exportThunk()
override {
return true; }
304 assert(!Args.empty() &&
"expected the arglist to not be empty!");
305 return Args.size() - 1;
308 StringRef GetPureVirtualCallName()
override {
return "__cxa_pure_virtual"; }
309 StringRef GetDeletedVirtualCallName()
override
310 {
return "__cxa_deleted_virtual"; }
315 llvm::Value *NumElements,
323 llvm::GlobalVariable *DeclPtr,
324 bool PerformInit)
override;
326 llvm::FunctionCallee dtor,
327 llvm::Constant *addr)
override;
329 llvm::Function *getOrCreateThreadLocalWrapper(
const VarDecl *VD,
331 void EmitThreadLocalInitFuncs(
337 bool usesThreadWrapperFunction(
const VarDecl *VD)
const override {
338 return !isEmittedWithConstantInitializer(VD) ||
339 mayNeedDestruction(VD);
344 bool NeedsVTTParameter(
GlobalDecl GD)
override;
351 virtual bool shouldRTTIBeUnique()
const {
return true; }
355 enum RTTIUniquenessKind {
373 classifyRTTIUniqueness(
QualType CanTy,
374 llvm::GlobalValue::LinkageTypes
Linkage)
const;
375 friend class ItaniumRTTIBuilder;
379 std::pair<llvm::Value *, const CXXRecordDecl *>
384 bool hasAnyUnusedVirtualInlineFunction(
const CXXRecordDecl *RD)
const {
385 const auto &VtableLayout =
386 CGM.getItaniumVTableContext().getVTableLayout(RD);
388 for (
const auto &VtableComponent : VtableLayout.vtable_components()) {
390 if (!VtableComponent.isUsedFunctionPointerKind())
393 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
397 StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
398 auto *Entry = CGM.GetGlobalValue(Name);
404 if (!Entry || Entry->isDeclaration())
411 const auto &VtableLayout =
412 CGM.getItaniumVTableContext().getVTableLayout(RD);
414 for (
const auto &VtableComponent : VtableLayout.vtable_components()) {
415 if (VtableComponent.isRTTIKind()) {
416 const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();
419 }
else if (VtableComponent.isUsedFunctionPointerKind()) {
420 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
430 class ARMCXXABI :
public ItaniumCXXABI {
433 ItaniumCXXABI(CGM,
true,
436 bool HasThisReturn(
GlobalDecl GD)
const override {
437 return (isa<CXXConstructorDecl>(GD.
getDecl()) || (
438 isa<CXXDestructorDecl>(GD.
getDecl()) &&
448 llvm::Value *NumElements,
455 class AppleARM64CXXABI :
public ARMCXXABI {
458 Use32BitVTableOffsetABI =
true;
462 bool shouldRTTIBeUnique()
const override {
return false; }
465 class FuchsiaCXXABI final :
public ItaniumCXXABI {
468 : ItaniumCXXABI(CGM) {}
471 bool HasThisReturn(
GlobalDecl GD)
const override {
472 return isa<CXXConstructorDecl>(GD.
getDecl()) ||
473 (isa<CXXDestructorDecl>(GD.
getDecl()) &&
478 class WebAssemblyCXXABI final :
public ItaniumCXXABI {
481 : ItaniumCXXABI(CGM,
true,
486 llvm::Value *Exn)
override;
489 bool HasThisReturn(
GlobalDecl GD)
const override {
490 return isa<CXXConstructorDecl>(GD.
getDecl()) ||
491 (isa<CXXDestructorDecl>(GD.
getDecl()) &&
494 bool canCallMismatchedFunctionType()
const override {
return false; }
497 class XLCXXABI final :
public ItaniumCXXABI {
500 : ItaniumCXXABI(CGM) {}
503 llvm::FunctionCallee dtor,
504 llvm::Constant *addr)
override;
506 bool useSinitAndSterm()
const override {
return true; }
509 void emitCXXStermFinalizer(
const VarDecl &D, llvm::Function *dtorStub,
510 llvm::Constant *addr);
518 case TargetCXXABI::GenericARM:
519 case TargetCXXABI::iOS:
520 case TargetCXXABI::WatchOS:
521 return new ARMCXXABI(CGM);
523 case TargetCXXABI::AppleARM64:
524 return new AppleARM64CXXABI(CGM);
526 case TargetCXXABI::Fuchsia:
527 return new FuchsiaCXXABI(CGM);
532 case TargetCXXABI::GenericAArch64:
533 return new ItaniumCXXABI(CGM,
true,
536 case TargetCXXABI::GenericMIPS:
537 return new ItaniumCXXABI(CGM,
true);
539 case TargetCXXABI::WebAssembly:
540 return new WebAssemblyCXXABI(CGM);
542 case TargetCXXABI::XL:
543 return new XLCXXABI(CGM);
545 case TargetCXXABI::GenericItanium:
547 == llvm::Triple::le32) {
551 return new ItaniumCXXABI(CGM,
true);
553 return new ItaniumCXXABI(CGM);
555 case TargetCXXABI::Microsoft:
556 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
558 llvm_unreachable(
"bad ABI kind");
564 return CGM.PtrDiffTy;
565 return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);
588 CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
590 llvm::Value *&ThisPtrForCall,
599 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
600 CGM.getTypes().arrangeCXXMethodType(RD, FPT,
nullptr));
602 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
609 llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1,
"memptr.adj");
612 llvm::Value *Adj = RawAdj;
613 if (UseARMMethodPtrABI)
614 Adj = Builder.CreateAShr(Adj, ptrdiff_1,
"memptr.adj.shifted");
619 llvm::Value *Ptr = Builder.CreateBitCast(
This, Builder.getInt8PtrTy());
620 Ptr = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), Ptr, Adj);
621 This = Builder.CreateBitCast(Ptr,
This->getType(),
"this.adjusted");
622 ThisPtrForCall =
This;
625 llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0,
"memptr.ptr");
629 llvm::Value *IsVirtual;
630 if (UseARMMethodPtrABI)
631 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
633 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
634 IsVirtual = Builder.CreateIsNotNull(IsVirtual,
"memptr.isvirtual");
635 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
643 llvm::Type *VTableTy = Builder.getInt8PtrTy();
653 llvm::Value *VTableOffset = FnAsInt;
654 if (!UseARMMethodPtrABI)
655 VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
656 if (Use32BitVTableOffsetABI) {
657 VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.
Int32Ty);
658 VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
663 llvm::Constant *CheckSourceLocation;
664 llvm::Constant *CheckTypeDesc;
665 bool ShouldEmitCFICheck = CGF.
SanOpts.
has(SanitizerKind::CFIMFCall) &&
666 CGM.HasHiddenLTOVisibility(RD);
667 bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
668 CGM.HasHiddenLTOVisibility(RD);
669 bool ShouldEmitWPDInfo =
670 CGM.getCodeGenOpts().WholeProgramVTables &&
672 !CGM.HasLTOVisibilityPublicStd(RD);
673 llvm::Value *VirtualFn =
nullptr;
677 llvm::Value *TypeId =
nullptr;
678 llvm::Value *CheckResult =
nullptr;
680 if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
684 CGM.CreateMetadataIdentifierForVirtualMemPtrType(
QualType(MPT, 0));
688 if (ShouldEmitVFEInfo) {
689 llvm::Value *VFPAddr =
690 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
697 llvm::Value *CheckedLoad = Builder.CreateCall(
698 CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
699 {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
700 CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
701 VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
702 VirtualFn = Builder.CreateBitCast(VirtualFn, FTy->getPointerTo(),
707 if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
708 llvm::Value *VFPAddr =
709 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
710 CheckResult = Builder.CreateCall(
711 CGM.getIntrinsic(llvm::Intrinsic::type_test),
712 {Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId});
715 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
716 VirtualFn = CGF.
Builder.CreateCall(
717 CGM.getIntrinsic(llvm::Intrinsic::load_relative,
718 {VTableOffset->getType()}),
719 {VTable, VTableOffset});
720 VirtualFn = CGF.
Builder.CreateBitCast(VirtualFn, FTy->getPointerTo());
722 llvm::Value *VFPAddr =
724 VFPAddr = CGF.
Builder.CreateBitCast(
725 VFPAddr, FTy->getPointerTo()->getPointerTo());
731 assert(VirtualFn &&
"Virtual fuction pointer not created!");
732 assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
734 "Check result required but not created!");
736 if (ShouldEmitCFICheck) {
740 llvm::Constant *StaticData[] = {
746 if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
747 CGF.
EmitTrapCheck(CheckResult, SanitizerHandler::CFICheckFail);
749 llvm::Value *AllVtables = llvm::MetadataAsValue::get(
750 CGM.getLLVMContext(),
751 llvm::MDString::get(CGM.getLLVMContext(),
"all-vtables"));
752 llvm::Value *ValidVtable = Builder.CreateCall(
753 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
754 CGF.
EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIMFCall),
755 SanitizerHandler::CFICheckFail, StaticData,
756 {VTable, ValidVtable});
759 FnVirtual = Builder.GetInsertBlock();
768 llvm::Value *NonVirtualFn =
769 Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(),
"memptr.nonvirtualfn");
772 if (ShouldEmitCFICheck) {
777 llvm::Constant *StaticData[] = {
783 llvm::Value *Bit = Builder.getFalse();
784 llvm::Value *CastedNonVirtualFn =
785 Builder.CreateBitCast(NonVirtualFn, CGF.
Int8PtrTy);
787 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
788 getContext().getMemberPointerType(
791 llvm::Value *TypeId =
794 llvm::Value *TypeTest =
795 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
796 {CastedNonVirtualFn, TypeId});
797 Bit = Builder.CreateOr(Bit, TypeTest);
800 CGF.
EmitCheck(std::make_pair(Bit, SanitizerKind::CFIMFCall),
801 SanitizerHandler::CFICheckFail, StaticData,
802 {CastedNonVirtualFn, llvm::UndefValue::get(CGF.
IntPtrTy)});
804 FnNonVirtual = Builder.GetInsertBlock();
810 llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2);
811 CalleePtr->addIncoming(VirtualFn, FnVirtual);
812 CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
820 llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
823 assert(MemPtr->getType() == CGM.PtrDiffTy);
831 llvm::Value *Addr = Builder.CreateInBoundsGEP(
832 Base.getElementType(),
Base.getPointer(), MemPtr,
"memptr.offset");
837 ->getPointerTo(
Base.getAddressSpace());
838 return Builder.CreateBitCast(Addr, PType);
868 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
869 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
873 if (E->
getCastKind() == CK_ReinterpretMemberPointer)
return src;
876 if (isa<llvm::Constant>(src))
877 return EmitMemberPointerConversion(E, cast<llvm::Constant>(src));
879 llvm::Constant *adj = getMemberPointerAdjustment(E);
880 if (!adj)
return src;
883 bool isDerivedToBase = (E->
getCastKind() == CK_DerivedToBaseMemberPointer);
893 dst = Builder.CreateNSWSub(src, adj,
"adj");
895 dst = Builder.CreateNSWAdd(src, adj,
"adj");
898 llvm::Value *
null = llvm::Constant::getAllOnesValue(src->getType());
899 llvm::Value *isNull = Builder.CreateICmpEQ(src,
null,
"memptr.isnull");
900 return Builder.CreateSelect(isNull, src, dst);
904 if (UseARMMethodPtrABI) {
905 uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
907 adj = llvm::ConstantInt::get(adj->getType(), offset);
910 llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1,
"src.adj");
913 dstAdj = Builder.CreateNSWSub(srcAdj, adj,
"adj");
915 dstAdj = Builder.CreateNSWAdd(srcAdj, adj,
"adj");
917 return Builder.CreateInsertValue(src, dstAdj, 1);
921 ItaniumCXXABI::EmitMemberPointerConversion(
const CastExpr *E,
922 llvm::Constant *src) {
923 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
924 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
928 if (E->
getCastKind() == CK_ReinterpretMemberPointer)
return src;
931 llvm::Constant *adj = getMemberPointerAdjustment(E);
932 if (!adj)
return src;
934 bool isDerivedToBase = (E->
getCastKind() == CK_DerivedToBaseMemberPointer);
943 if (src->isAllOnesValue())
return src;
946 return llvm::ConstantExpr::getNSWSub(src, adj);
948 return llvm::ConstantExpr::getNSWAdd(src, adj);
952 if (UseARMMethodPtrABI) {
953 uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
955 adj = llvm::ConstantInt::get(adj->getType(), offset);
958 llvm::Constant *srcAdj = llvm::ConstantExpr::getExtractValue(src, 1);
959 llvm::Constant *dstAdj;
961 dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);
963 dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);
965 return llvm::ConstantExpr::getInsertValue(src, dstAdj, 1);
973 return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL,
true);
975 llvm::Constant *
Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
976 llvm::Constant *Values[2] = {
Zero,
Zero };
977 return llvm::ConstantStruct::getAnon(Values);
986 return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.
getQuantity());
990 ItaniumCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
994 llvm::Constant *ItaniumCXXABI::BuildMemberPointer(
const CXXMethodDecl *MD,
996 assert(MD->
isInstance() &&
"Member function must not be static!");
1001 llvm::Constant *MemPtr[2];
1003 uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
1004 uint64_t VTableOffset;
1005 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1007 VTableOffset = Index * 4;
1012 VTableOffset = Index * PointerWidth.
getQuantity();
1015 if (UseARMMethodPtrABI) {
1022 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);
1023 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1030 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
1031 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1038 if (Types.isFuncTypeConvertible(FPT)) {
1040 Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
1046 llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty);
1048 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
1049 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1050 (UseARMMethodPtrABI ? 2 : 1) *
1054 return llvm::ConstantStruct::getAnon(MemPtr);
1057 llvm::Constant *ItaniumCXXABI::EmitMemberPointer(
const APValue &MP,
1062 return EmitNullMemberPointer(MPT);
1070 getContext().toCharUnitsFromBits(getContext().
getFieldOffset(MPD));
1086 llvm::ICmpInst::Predicate
Eq;
1087 llvm::Instruction::BinaryOps
And, Or;
1089 Eq = llvm::ICmpInst::ICMP_NE;
1090 And = llvm::Instruction::Or;
1093 Eq = llvm::ICmpInst::ICMP_EQ;
1095 Or = llvm::Instruction::Or;
1101 return Builder.CreateICmp(Eq, L, R);
1113 llvm::Value *LPtr = Builder.CreateExtractValue(L, 0,
"lhs.memptr.ptr");
1114 llvm::Value *RPtr = Builder.CreateExtractValue(R, 0,
"rhs.memptr.ptr");
1118 llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr,
"cmp.ptr");
1123 llvm::Value *
Zero = llvm::Constant::getNullValue(LPtr->getType());
1124 llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr,
Zero,
"cmp.ptr.null");
1128 llvm::Value *LAdj = Builder.CreateExtractValue(L, 1,
"lhs.memptr.adj");
1129 llvm::Value *RAdj = Builder.CreateExtractValue(R, 1,
"rhs.memptr.adj");
1130 llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj,
"cmp.adj");
1134 if (UseARMMethodPtrABI) {
1135 llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
1138 llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj,
"or.adj");
1139 llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
1140 llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1,
Zero,
1142 EqZero = Builder.CreateBinOp(
And, EqZero, OrAdjAnd1EqZero);
1146 llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
1147 Result = Builder.CreateBinOp(
And, PtrEq, Result,
1148 Inequality ?
"memptr.ne" :
"memptr.eq");
1154 llvm::Value *MemPtr,
1160 assert(MemPtr->getType() == CGM.PtrDiffTy);
1161 llvm::Value *NegativeOne =
1162 llvm::Constant::getAllOnesValue(MemPtr->getType());
1163 return Builder.CreateICmpNE(MemPtr, NegativeOne,
"memptr.tobool");
1167 llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0,
"memptr.ptr");
1169 llvm::Constant *
Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
1170 llvm::Value *Result = Builder.CreateICmpNE(Ptr,
Zero,
"memptr.tobool");
1174 if (UseARMMethodPtrABI) {
1175 llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
1176 llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1,
"memptr.adj");
1177 llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One,
"memptr.virtualbit");
1178 llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit,
Zero,
1179 "memptr.isvirtual");
1180 Result = Builder.CreateOr(Result, IsVirtual);
1193 auto Align = CGM.getContext().getTypeAlignInChars(FI.
getReturnType());
1214 if (UseGlobalDelete) {
1221 llvm::Value *VTable =
1225 llvm::Value *OffsetPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
1226 CGF.
IntPtrTy, VTable, -2,
"complete-offset.ptr");
1230 llvm::Value *CompletePtr =
1244 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE);
1246 if (UseGlobalDelete)
1250 void ItaniumCXXABI::emitRethrow(
CodeGenFunction &CGF,
bool isNoReturn) {
1253 llvm::FunctionType *FTy =
1254 llvm::FunctionType::get(CGM.VoidTy,
false);
1256 llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy,
"__cxa_rethrow");
1267 llvm::FunctionType *FTy =
1278 llvm::FunctionType *FTy =
1279 llvm::FunctionType::get(CGM.
VoidTy, Args,
false);
1287 llvm::Type *SizeTy = CGF.
ConvertType(getContext().getSizeType());
1288 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
1292 AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize),
"exception");
1299 llvm::Constant *
TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
1304 llvm::Constant *Dtor =
nullptr;
1306 CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
1310 Dtor = llvm::ConstantExpr::getBitCast(Dtor, CGM.Int8PtrTy);
1313 if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1315 llvm::Value *args[] = { ExceptionPtr,
TypeInfo, Dtor };
1326 llvm::Type *PtrDiffTy =
1329 llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy };
1331 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args,
false);
1334 llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind,
1335 llvm::Attribute::ReadOnly };
1336 llvm::AttributeList Attrs = llvm::AttributeList::get(
1337 CGF.
getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
1344 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1361 unsigned NumPublicPaths = 0;
1374 if (PathElement.Base->isVirtual())
1377 if (NumPublicPaths > 1)
1383 PathElement.Base->getType()->getAsCXXRecordDecl());
1388 if (NumPublicPaths == 0)
1392 if (NumPublicPaths > 1)
1402 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1407 bool ItaniumCXXABI::shouldTypeidBeNullChecked(
bool IsDeref,
1415 Call->setDoesNotReturn();
1416 CGF.
Builder.CreateUnreachable();
1422 llvm::Type *StdTypeInfoPtrTy) {
1425 llvm::Value *
Value =
1426 CGF.
GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo(), ClassDecl);
1428 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1432 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1433 {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
1440 CGF.
Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy,
Value, -1ULL);
1446 bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
1451 llvm::Value *ItaniumCXXABI::EmitDynamicCastCall(
1454 llvm::Type *PtrDiffLTy =
1458 llvm::Value *SrcRTTI =
1460 llvm::Value *DestRTTI =
1466 llvm::Value *OffsetHint = llvm::ConstantInt::get(
1474 llvm::Value *args[] = {
Value, SrcRTTI, DestRTTI, OffsetHint};
1481 llvm::BasicBlock *BadCastBlock =
1485 CGF.
Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
1488 EmitBadCastCall(CGF);
1494 llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(
CodeGenFunction &CGF,
1501 llvm::Value *OffsetToTop;
1502 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1504 llvm::Value *VTable =
1505 CGF.
GetVTablePtr(ThisAddr, CGM.Int32Ty->getPointerTo(), ClassDecl);
1509 CGF.
Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2
U);
1513 llvm::Type *PtrDiffLTy =
1517 llvm::Value *VTable =
1518 CGF.
GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), ClassDecl);
1522 CGF.
Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
1536 Call->setDoesNotReturn();
1537 CGF.
Builder.CreateUnreachable();
1548 CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
1550 llvm::Value *VBaseOffsetPtr =
1551 CGF.
Builder.CreateConstGEP1_64(
1553 "vbase.offset.ptr");
1555 llvm::Value *VBaseOffset;
1556 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1558 CGF.
Builder.CreateBitCast(VBaseOffsetPtr, CGF.
Int32Ty->getPointerTo());
1563 VBaseOffsetPtr = CGF.
Builder.CreateBitCast(VBaseOffsetPtr,
1564 CGM.PtrDiffTy->getPointerTo());
1566 CGM.PtrDiffTy, VBaseOffsetPtr, CGF.
getPointerAlign(),
"vbase.offset");
1573 assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
1588 ItaniumCXXABI::buildStructorSignature(
GlobalDecl GD,
1598 cast<CXXMethodDecl>(GD.
getDecl())->getParent()->getNumVBases() != 0) {
1599 ArgTys.insert(ArgTys.begin() + 1,
1601 return AddedStructorArgCounts::prefix(1);
1603 return AddedStructorArgCounts{};
1626 assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
1629 if (NeedsVTTParameter(CGF.
CurGD)) {
1637 Params.insert(Params.begin() + 1, VTTDecl);
1638 getStructorImplicitParamDecl(CGF) = VTTDecl;
1642 void ItaniumCXXABI::EmitInstanceFunctionProlog(
CodeGenFunction &CGF) {
1649 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
1652 if (getStructorImplicitParamDecl(CGF)) {
1665 if (HasThisReturn(CGF.
CurGD))
1671 bool ForVirtualBase,
bool Delegating) {
1673 return AddedStructorArgs{};
1678 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1679 return AddedStructorArgs::prefix({{VTT, VTTTy}});
1684 bool ForVirtualBase,
bool Delegating) {
1697 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1700 if (getContext().getLangOpts().AppleKext &&
1712 llvm::GlobalVariable *VTable = getAddrOfVTable(RD,
CharUnits());
1713 if (VTable->hasInitializer())
1718 llvm::GlobalVariable::LinkageTypes
Linkage = CGM.getVTableLinkage(RD);
1719 llvm::Constant *RTTI =
1720 CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
1724 auto components = builder.beginStruct();
1726 llvm::GlobalValue::isLocalLinkage(
Linkage));
1727 components.finishAndSetAsInitializer(VTable);
1732 if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
1733 VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
1736 CGM.setGVProperties(VTable, RD);
1744 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
1745 cast<NamespaceDecl>(DC)->getIdentifier()->isStr(
"__cxxabiv1") &&
1747 EmitFundamentalRTTIDescriptors(RD);
1754 if (!VTable->isDeclarationForLinker() ||
1755 CGM.getCodeGenOpts().WholeProgramVTables) {
1756 CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
1760 if (VTable->isDeclarationForLinker()) {
1761 assert(CGM.getCodeGenOpts().WholeProgramVTables);
1762 CGM.addCompilerUsedGlobal(VTable);
1770 bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
1774 return NeedsVTTParameter(CGF.
CurGD);
1777 llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
1781 if ((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
1782 NeedsVTTParameter(CGF.
CurGD)) {
1783 return getVTableAddressPointInStructorWithVTT(CGF, VTableClass,
Base,
1786 return getVTableAddressPoint(
Base, VTableClass);
1792 llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass,
CharUnits());
1797 CGM.getItaniumVTableContext()
1798 .getVTableLayout(VTableClass)
1799 .getAddressPoint(
Base);
1800 llvm::Value *Indices[] = {
1801 llvm::ConstantInt::get(CGM.Int32Ty, 0),
1802 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.
VTableIndex),
1806 return llvm::ConstantExpr::getGetElementPtr(VTable->getValueType(), VTable,
1813 template <
typename T>
1815 bool FoundNonInlineVirtualMethodWithAttr =
false;
1817 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
1818 if (!FD->isVirtualAsWritten() || FD->isInlineSpecified() ||
1819 FD->doesThisDeclarationHaveABody())
1823 FoundNonInlineVirtualMethodWithAttr =
true;
1831 return FoundNonInlineVirtualMethodWithAttr;
1834 llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
1837 assert((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
1838 NeedsVTTParameter(CGF.
CurGD) &&
"This class doesn't have VTT");
1841 uint64_t VirtualPointerIndex =
1842 CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass,
Base);
1846 if (VirtualPointerIndex)
1847 VTT = CGF.
Builder.CreateConstInBoundsGEP1_64(
1848 CGF.
VoidPtrTy, VTT, VirtualPointerIndex);
1855 llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
1857 return getVTableAddressPoint(
Base, VTableClass);
1860 llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(
const CXXRecordDecl *RD,
1862 assert(VPtrOffset.
isZero() &&
"Itanium ABI only supports zero vptr offsets");
1864 llvm::GlobalVariable *&VTable = VTables[RD];
1869 CGM.addDeferredVTable(RD);
1872 llvm::raw_svector_ostream Out(Name);
1873 getMangleContext().mangleCXXVTable(RD, Out);
1876 CGM.getItaniumVTableContext().getVTableLayout(RD);
1877 llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
1882 unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()
1884 : CGM.getTarget().getPointerAlign(0);
1886 VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
1888 getContext().toCharUnitsFromBits(PAlign).getQuantity());
1889 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1898 if (CGM.getTarget().hasPS4DLLImportExport()) {
1899 if ((!RD->
hasAttr<DLLImportAttr>()) && (!RD->
hasAttr<DLLExportAttr>())) {
1900 if (CGM.getVTables().isVTableExternal(RD)) {
1901 if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD))
1902 VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
1904 if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD))
1905 VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1909 CGM.setGVProperties(VTable, RD);
1919 llvm::Type *TyPtr = Ty->getPointerTo();
1920 auto *MethodDecl = cast<CXXMethodDecl>(GD.
getDecl());
1922 This, TyPtr->getPointerTo(), MethodDecl->getParent());
1924 uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
1928 MethodDecl->getParent(), VTable, TyPtr,
1929 VTableIndex * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8);
1933 llvm::Value *VFuncLoad;
1934 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1935 VTable = CGF.
Builder.CreateBitCast(VTable, CGM.Int8PtrTy);
1937 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1938 {VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)});
1939 VFuncLoad = CGF.
Builder.CreateBitCast(
Load, TyPtr);
1942 CGF.
Builder.CreateBitCast(VTable, TyPtr->getPointerTo());
1943 llvm::Value *VTableSlotPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
1944 TyPtr, VTable, VTableIndex,
"vfn");
1956 if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
1957 CGM.getCodeGenOpts().StrictVTablePointers) {
1958 if (
auto *VFuncLoadInstr = dyn_cast<llvm::Instruction>(VFuncLoad)) {
1959 VFuncLoadInstr->setMetadata(
1960 llvm::LLVMContext::MD_invariant_load,
1961 llvm::MDNode::get(CGM.getLLVMContext(),
1972 llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
1977 assert((CE !=
nullptr) ^ (D !=
nullptr));
1978 assert(CE ==
nullptr || CE->arg_begin() == CE->arg_end());
1983 &CGM.getTypes().arrangeCXXStructorDeclaration(GD);
1989 ThisTy = CE->getObjectType();
1991 ThisTy = D->getDestroyedType();
1999 void ItaniumCXXABI::emitVirtualInheritanceTables(
const CXXRecordDecl *RD) {
2005 bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
2009 if (CGM.getLangOpts().AppleKext)
2014 if (isVTableHidden(RD))
2017 if (CGM.getCodeGenOpts().ForceEmitVTables)
2024 if (hasAnyUnusedVirtualInlineFunction(RD))
2032 for (
const auto &B : RD->
bases()) {
2033 auto *BRD = B.getType()->getAsCXXRecordDecl();
2034 assert(BRD &&
"no class for base specifier");
2035 if (B.isVirtual() || !BRD->isDynamicClass())
2037 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2045 bool ItaniumCXXABI::canSpeculativelyEmitVTable(
const CXXRecordDecl *RD)
const {
2046 if (!canSpeculativelyEmitVTableAsBaseClass(RD))
2051 for (
const auto &B : RD->
vbases()) {
2052 auto *BRD = B.getType()->getAsCXXRecordDecl();
2053 assert(BRD &&
"no class for base specifier");
2054 if (!BRD->isDynamicClass())
2056 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2064 int64_t NonVirtualAdjustment,
2065 int64_t VirtualAdjustment,
2066 bool IsReturnAdjustment) {
2067 if (!NonVirtualAdjustment && !VirtualAdjustment)
2073 if (NonVirtualAdjustment && !IsReturnAdjustment) {
2079 llvm::Value *ResultPtr;
2080 if (VirtualAdjustment) {
2085 llvm::Value *OffsetPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
2086 CGF.
Int8Ty, VTablePtr, VirtualAdjustment);
2090 CGF.
Builder.CreateBitCast(OffsetPtr, CGF.
Int32Ty->getPointerTo());
2095 llvm::Type *PtrDiffTy =
2099 CGF.
Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo());
2106 ResultPtr = CGF.
Builder.CreateInBoundsGEP(
2107 V.getElementType(),
V.getPointer(),
Offset);
2109 ResultPtr =
V.getPointer();
2114 if (NonVirtualAdjustment && IsReturnAdjustment) {
2115 ResultPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(CGF.
Int8Ty, ResultPtr,
2116 NonVirtualAdjustment);
2120 return CGF.
Builder.CreateBitCast(ResultPtr, InitialPtr.
getType());
2123 llvm::Value *ItaniumCXXABI::performThisAdjustment(
CodeGenFunction &CGF,
2142 return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
2147 return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
2156 CGM.getContext().getPreferredTypeAlignInChars(elementType));
2161 llvm::Value *NumElements,
2164 assert(requiresArrayCookie(
expr));
2174 assert(CookieSize == getArrayCookieSizeImpl(ElementType));
2178 CharUnits CookieOffset = CookieSize - SizeSize;
2179 if (!CookieOffset.
isZero())
2188 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
2189 (
expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||
2190 CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {
2192 CGM.getSanitizerMetadata()->disableSanitizerForInstruction(SI);
2193 llvm::FunctionType *FTy =
2194 llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.
getType(),
false);
2195 llvm::FunctionCallee F =
2196 CGM.CreateRuntimeFunction(FTy,
"__asan_poison_cxx_array_cookie");
2209 Address numElementsPtr = allocPtr;
2211 if (!numElementsOffset.
isZero())
2217 if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0)
2224 llvm::FunctionType *FTy =
2225 llvm::FunctionType::get(CGF.
SizeTy, CGF.
SizeTy->getPointerTo(0),
false);
2226 llvm::FunctionCallee F =
2227 CGM.CreateRuntimeFunction(FTy,
"__asan_load_cxx_array_cookie");
2241 CGM.getContext().getTypeAlignInChars(elementType));
2246 llvm::Value *numElements,
2249 assert(requiresArrayCookie(
expr));
2256 llvm::Value *elementSize = llvm::ConstantInt::get(CGF.
SizeTy,
2257 getContext().getTypeSizeInChars(elementType).getQuantity());
2266 CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
2285 llvm::PointerType *GuardPtrTy) {
2287 llvm::FunctionType *FTy =
2291 FTy,
"__cxa_guard_acquire",
2293 llvm::AttributeList::FunctionIndex,
2294 llvm::Attribute::NoUnwind));
2298 llvm::PointerType *GuardPtrTy) {
2300 llvm::FunctionType *FTy =
2301 llvm::FunctionType::get(CGM.
VoidTy, GuardPtrTy,
false);
2303 FTy,
"__cxa_guard_release",
2305 llvm::AttributeList::FunctionIndex,
2306 llvm::Attribute::NoUnwind));
2310 llvm::PointerType *GuardPtrTy) {
2312 llvm::FunctionType *FTy =
2313 llvm::FunctionType::get(CGM.
VoidTy, GuardPtrTy,
false);
2315 FTy,
"__cxa_guard_abort",
2317 llvm::AttributeList::FunctionIndex,
2318 llvm::Attribute::NoUnwind));
2323 llvm::GlobalVariable *Guard;
2324 CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
2337 llvm::GlobalVariable *
var,
2338 bool shouldPerformInit) {
2343 bool NonTemplateInline =
2350 bool threadsafe = getContext().getLangOpts().ThreadsafeStatics &&
2356 bool useInt8GuardVariable = !threadsafe &&
var->hasInternalLinkage();
2358 llvm::IntegerType *guardTy;
2360 if (useInt8GuardVariable) {
2366 if (UseARMGuardVarABI) {
2372 CGM.getDataLayout().getABITypeAlignment(guardTy));
2375 llvm::PointerType *guardPtrTy = guardTy->getPointerTo(
2380 llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D);
2385 llvm::raw_svector_ostream out(guardName);
2386 getMangleContext().mangleStaticGuardVariable(&D, out);
2391 guard =
new llvm::GlobalVariable(CGM.getModule(), guardTy,
2392 false,
var->getLinkage(),
2393 llvm::ConstantInt::get(guardTy, 0),
2395 guard->setDSOLocal(
var->isDSOLocal());
2396 guard->setVisibility(
var->getVisibility());
2398 guard->setThreadLocalMode(
var->getThreadLocalMode());
2399 guard->setAlignment(guardAlignment.
getAsAlign());
2404 llvm::Comdat *
C =
var->getComdat();
2406 (CGM.getTarget().getTriple().isOSBinFormatELF() ||
2407 CGM.getTarget().getTriple().isOSBinFormatWasm())) {
2408 guard->setComdat(C);
2409 }
else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
2410 guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));
2413 CGM.setStaticLocalDeclGuardAddress(&D, guard);
2416 Address guardAddr =
Address(guard, guard->getValueType(), guardAlignment);
2436 llvm::LoadInst *LI =
2437 Builder.CreateLoad(Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
2446 LI->setAtomic(llvm::AtomicOrdering::Acquire);
2469 (UseARMGuardVarABI && !useInt8GuardVariable)
2470 ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
2472 llvm::Value *NeedsInit = Builder.CreateIsNull(
V,
"guard.uninitialized");
2491 Builder.CreateCondBr(Builder.CreateIsNotNull(
V,
"tobool"),
2492 InitBlock, EndBlock);
2513 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2514 Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
2522 llvm::FunctionCallee dtor,
2523 llvm::Constant *addr,
bool TLS) {
2525 "unexpected call to emitGlobalDtorWithCXAAtExit");
2527 "__cxa_atexit is disabled");
2528 const char *Name =
"__cxa_atexit";
2531 Name = T.isOSDarwin() ?
"_tlv_atexit" :
"__cxa_thread_atexit";
2538 llvm::FunctionType::get(CGF.
VoidTy, CGF.
Int8PtrTy,
false)->getPointerTo();
2541 auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0;
2542 auto AddrInt8PtrTy =
2546 llvm::Constant *handle =
2548 auto *GV = cast<llvm::GlobalValue>(handle->stripPointerCasts());
2552 llvm::Type *paramTys[] = {
dtorTy, AddrInt8PtrTy, handle->getType()};
2553 llvm::FunctionType *atexitTy =
2554 llvm::FunctionType::get(CGF.
IntTy, paramTys,
false);
2558 if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee()))
2559 fn->setDoesNotThrow();
2566 addr = llvm::Constant::getNullValue(CGF.
Int8PtrTy);
2568 llvm::Value *args[] = {llvm::ConstantExpr::getBitCast(
2569 cast<llvm::Constant>(dtor.getCallee()),
dtorTy),
2570 llvm::ConstantExpr::getBitCast(addr, AddrInt8PtrTy),
2579 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
2583 return GlobalInitOrCleanupFn;
2586 void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {
2587 for (
const auto &I : DtorsUsingAtExit) {
2592 llvm::Function *GlobalCleanupFn =
2602 llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
2603 llvm::Type *
dtorTy = dtorFuncTy->getPointerTo();
2607 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2608 auto itv = Dtors.rbegin();
2609 while (itv != Dtors.rend()) {
2610 llvm::Function *Dtor = *itv;
2615 llvm::Constant *dtor = llvm::ConstantExpr::getBitCast(Dtor,
dtorTy);
2617 llvm::Value *NeedsDestruct =
2618 CGF.
Builder.CreateIsNull(
V,
"needs_destruct");
2620 llvm::BasicBlock *DestructCallBlock =
2623 (itv + 1) != Dtors.rend() ?
"unatexit.call" :
"destruct.end");
2626 CGF.
Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
2631 llvm::CallInst *CI = CGF.
Builder.CreateCall(dtorFuncTy, dtor);
2633 CI->setCallingConv(Dtor->getCallingConv());
2641 AddGlobalDtor(GlobalCleanupFn,
Priority);
2645 void CodeGenModule::registerGlobalDtorsWithAtExit() {
2646 for (
const auto &I : DtorsUsingAtExit) {
2650 llvm::Function *GlobalInitFn =
2664 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2665 for (
auto *Dtor : Dtors) {
2673 llvm::FunctionType::get(CGF.
VoidTy,
false)->getPointerTo();
2679 llvm::ConstantExpr::getBitCast(Dtor,
dtorTy));
2684 AddGlobalCtor(GlobalInitFn,
Priority,
nullptr);
2688 unregisterGlobalDtorsWithUnAtExit();
2693 llvm::FunctionCallee dtor,
2694 llvm::Constant *addr) {
2702 if (CGM.getCodeGenOpts().CXAAtExit || D.
getTLSKind())
2707 if (CGM.getLangOpts().AppleKext) {
2709 return CGM.AddCXXDtorEntry(dtor, addr);
2717 assert(!VD->
isStaticLocal() &&
"static local VarDecls don't need wrappers!");
2727 static llvm::GlobalValue::LinkageTypes
2729 llvm::GlobalValue::LinkageTypes VarLinkage =
2733 if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
2738 if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
2739 !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
2741 return llvm::GlobalValue::WeakODRLinkage;
2745 ItaniumCXXABI::getOrCreateThreadLocalWrapper(
const VarDecl *VD,
2750 llvm::raw_svector_ostream Out(WrapperName);
2751 getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);
2756 if (llvm::Value *
V = CGM.getModule().getNamedValue(WrapperName))
2757 return cast<llvm::Function>(
V);
2763 const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
2766 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI);
2767 llvm::Function *Wrapper =
2769 WrapperName.str(), &CGM.getModule());
2771 if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())
2772 Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));
2774 CGM.SetLLVMFunctionAttributes(
GlobalDecl(), FI, Wrapper,
false);
2777 if (!Wrapper->hasLocalLinkage())
2779 llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
2780 llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
2785 Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2786 Wrapper->addFnAttr(llvm::Attribute::NoUnwind);
2789 ThreadWrappers.push_back({VD, Wrapper});
2793 void ItaniumCXXABI::EmitThreadLocalInitFuncs(
2797 llvm::Function *InitFunc =
nullptr;
2802 llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;
2803 for (
unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {
2806 UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =
2807 CXXThreadLocalInits[I];
2809 OrderedInits.push_back(CXXThreadLocalInits[I]);
2812 if (!OrderedInits.empty()) {
2814 llvm::FunctionType *FTy =
2815 llvm::FunctionType::get(CGM.
VoidTy,
false);
2820 llvm::GlobalVariable *Guard =
new llvm::GlobalVariable(
2823 llvm::ConstantInt::get(CGM.
Int8Ty, 0),
"__tls_guard");
2824 Guard->setThreadLocal(
true);
2828 Guard->setAlignment(GuardAlign.
getAsAlign());
2834 InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2835 InitFunc->addFnAttr(llvm::Attribute::NoUnwind);
2841 for (
const VarDecl *VD : CXXThreadLocals) {
2845 getOrCreateThreadLocalWrapper(VD, GV);
2850 for (
auto VDAndWrapper : ThreadWrappers) {
2851 const VarDecl *VD = VDAndWrapper.first;
2852 llvm::GlobalVariable *Var =
2854 llvm::Function *Wrapper = VDAndWrapper.second;
2867 if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)
2868 Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);
2876 llvm::raw_svector_ostream Out(InitFnName);
2877 getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
2880 llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
2885 llvm::GlobalValue *Init =
nullptr;
2886 bool InitIsInitFunc =
false;
2887 bool HasConstantInitialization =
false;
2888 if (!usesThreadWrapperFunction(VD)) {
2889 HasConstantInitialization =
true;
2891 InitIsInitFunc =
true;
2892 llvm::Function *InitFuncToUse = InitFunc;
2903 Init = llvm::Function::Create(InitFnTy,
2904 llvm::GlobalVariable::ExternalWeakLinkage,
2908 GlobalDecl(), FI, cast<llvm::Function>(Init),
false);
2912 Init->setVisibility(Var->getVisibility());
2914 if (!CGM.
getTriple().isOSWindows() || !Init->hasExternalWeakLinkage())
2915 Init->setDSOLocal(Var->isDSOLocal());
2918 llvm::LLVMContext &Context = CGM.
getModule().getContext();
2926 isEmittedWithConstantInitializer(VD,
true) &&
2927 !mayNeedDestruction(VD)) {
2932 assert(Init ==
nullptr &&
"Expected Init to be null.");
2934 llvm::Function *Func = llvm::Function::Create(
2935 InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.
getModule());
2938 cast<llvm::Function>(Func),
2941 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context,
"", Func);
2943 Builder.CreateRetVoid();
2946 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context,
"", Wrapper);
2948 if (HasConstantInitialization) {
2950 }
else if (InitIsInitFunc) {
2952 llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init);
2954 CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2955 llvm::Function *Fn =
2956 cast<llvm::Function>(cast<llvm::GlobalAlias>(Init)->getAliasee());
2957 Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2968 Builder.CreateCall(InitFnTy, Init);
2971 llvm::Value *Have = Builder.CreateIsNotNull(Init);
2972 llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context,
"", Wrapper);
2973 llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context,
"", Wrapper);
2974 Builder.CreateCondBr(Have, InitBB, ExitBB);
2976 Builder.SetInsertPoint(InitBB);
2977 Builder.CreateCall(InitFnTy, Init);
2978 Builder.CreateBr(ExitBB);
2980 Builder.SetInsertPoint(ExitBB);
2985 llvm::Value *Val = Var;
2988 Val = Builder.CreateAlignedLoad(Var->getValueType(), Var, Align);
2990 if (Val->getType() != Wrapper->getReturnType())
2991 Val = Builder.CreatePointerBitCastOrAddrSpaceCast(
2992 Val, Wrapper->getReturnType(),
"");
2993 Builder.CreateRet(Val);
3001 llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
3003 llvm::CallInst *CallVal = CGF.
Builder.CreateCall(Wrapper);
3004 CallVal->setCallingConv(Wrapper->getCallingConv());
3018 bool ItaniumCXXABI::NeedsVTTParameter(
GlobalDecl GD) {
3037 class ItaniumRTTIBuilder {
3039 llvm::LLVMContext &VMContext;
3040 const ItaniumCXXABI &
CXXABI;
3046 llvm::GlobalVariable *
3047 GetAddrOfTypeName(
QualType Ty, llvm::GlobalVariable::LinkageTypes
Linkage);
3051 llvm::Constant *GetAddrOfExternalRTTIDescriptor(
QualType Ty);
3054 void BuildVTablePointer(
const Type *Ty);
3067 void BuildPointerTypeInfo(
QualType PointeeTy);
3078 ItaniumRTTIBuilder(
const ItaniumCXXABI &ABI)
3079 : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()),
CXXABI(ABI) {}
3093 PTI_Incomplete = 0x8,
3097 PTI_ContainingClassIncomplete = 0x10,
3103 PTI_Noexcept = 0x40,
3109 VMI_NonDiamondRepeat = 0x1,
3112 VMI_DiamondShaped = 0x2
3126 llvm::Constant *BuildTypeInfo(
QualType Ty);
3129 llvm::Constant *BuildTypeInfo(
3131 llvm::GlobalVariable::LinkageTypes
Linkage,
3132 llvm::GlobalValue::VisibilityTypes
Visibility,
3133 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
3137 llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
3140 llvm::raw_svector_ostream Out(Name);
3146 llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
3153 GV->setInitializer(Init);
3159 ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(
QualType Ty) {
3162 llvm::raw_svector_ostream Out(Name);
3166 llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(Name);
3182 if (RD && CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD)) {
3183 GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
3189 return llvm::ConstantExpr::getBitCast(GV, CGM.
Int8PtrTy);
3210 case BuiltinType::Void:
3211 case BuiltinType::NullPtr:
3212 case BuiltinType::Bool:
3213 case BuiltinType::WChar_S:
3214 case BuiltinType::WChar_U:
3215 case BuiltinType::Char_U:
3216 case BuiltinType::Char_S:
3217 case BuiltinType::UChar:
3218 case BuiltinType::SChar:
3219 case BuiltinType::Short:
3220 case BuiltinType::UShort:
3221 case BuiltinType::Int:
3222 case BuiltinType::UInt:
3223 case BuiltinType::Long:
3224 case BuiltinType::ULong:
3225 case BuiltinType::LongLong:
3226 case BuiltinType::ULongLong:
3227 case BuiltinType::Half:
3229 case BuiltinType::Double:
3230 case BuiltinType::LongDouble:
3231 case BuiltinType::Float16:
3232 case BuiltinType::Float128:
3233 case BuiltinType::Ibm128:
3234 case BuiltinType::Char8:
3235 case BuiltinType::Char16:
3236 case BuiltinType::Char32:
3237 case BuiltinType::Int128:
3238 case BuiltinType::UInt128:
3241 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
3242 case BuiltinType::Id:
3243 #include "clang/Basic/OpenCLImageTypes.def"
3244 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
3245 case BuiltinType::Id:
3246 #include "clang/Basic/OpenCLExtensionTypes.def"
3247 case BuiltinType::OCLSampler:
3248 case BuiltinType::OCLEvent:
3249 case BuiltinType::OCLClkEvent:
3250 case BuiltinType::OCLQueue:
3251 case BuiltinType::OCLReserveID:
3252 #define SVE_TYPE(Name, Id, SingletonId) \
3253 case BuiltinType::Id:
3254 #include "clang/Basic/AArch64SVEACLETypes.def"
3255 #define PPC_VECTOR_TYPE(Name, Id, Size) \
3256 case BuiltinType::Id:
3257 #include "clang/Basic/PPCTypes.def"
3258 #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3259 #include "clang/Basic/RISCVVTypes.def"
3260 case BuiltinType::ShortAccum:
3261 case BuiltinType::Accum:
3262 case BuiltinType::LongAccum:
3263 case BuiltinType::UShortAccum:
3264 case BuiltinType::UAccum:
3265 case BuiltinType::ULongAccum:
3266 case BuiltinType::ShortFract:
3267 case BuiltinType::Fract:
3268 case BuiltinType::LongFract:
3269 case BuiltinType::UShortFract:
3270 case BuiltinType::UFract:
3271 case BuiltinType::ULongFract:
3272 case BuiltinType::SatShortAccum:
3273 case BuiltinType::SatAccum:
3274 case BuiltinType::SatLongAccum:
3275 case BuiltinType::SatUShortAccum:
3276 case BuiltinType::SatUAccum:
3277 case BuiltinType::SatULongAccum:
3278 case BuiltinType::SatShortFract:
3279 case BuiltinType::SatFract:
3280 case BuiltinType::SatLongFract:
3281 case BuiltinType::SatUShortFract:
3282 case BuiltinType::SatUFract:
3283 case BuiltinType::SatULongFract:
3284 case BuiltinType::BFloat16:
3287 case BuiltinType::Dependent:
3288 #define BUILTIN_TYPE(Id, SingletonId)
3289 #define PLACEHOLDER_TYPE(Id, SingletonId) \
3290 case BuiltinType::Id:
3291 #include "clang/AST/BuiltinTypes.def"
3292 llvm_unreachable(
"asking for RRTI for a placeholder type!");
3294 case BuiltinType::ObjCId:
3295 case BuiltinType::ObjCClass:
3296 case BuiltinType::ObjCSel:
3297 llvm_unreachable(
"FIXME: Objective-C types are unsupported!");
3300 llvm_unreachable(
"Invalid BuiltinType Kind!");
3305 const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
3323 if (
const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
3328 if (
const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3346 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3347 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
3358 bool IsDLLImport = RD->
hasAttr<DLLImportAttr>();
3361 if (CGM.
getTriple().isWindowsGNUEnvironment())
3368 return IsDLLImport && !CGM.
getTriple().isWindowsItaniumEnvironment()
3396 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3401 if (
const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3405 dyn_cast<MemberPointerType>(Ty)) {
3407 const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
3429 if (
Base->isVirtual())
3439 if (!BaseDecl->isEmpty() &&
3446 void ItaniumRTTIBuilder::BuildVTablePointer(
const Type *Ty) {
3448 static const char *
const ClassTypeInfo =
3449 "_ZTVN10__cxxabiv117__class_type_infoE";
3451 static const char *
const SIClassTypeInfo =
3452 "_ZTVN10__cxxabiv120__si_class_type_infoE";
3454 static const char *
const VMIClassTypeInfo =
3455 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
3457 const char *VTableName =
nullptr;
3460 #define TYPE(Class, Base)
3461 #define ABSTRACT_TYPE(Class, Base)
3462 #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3463 #define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3464 #define DEPENDENT_TYPE(Class, Base) case Type::Class:
3465 #include "clang/AST/TypeNodes.inc"
3466 llvm_unreachable(
"Non-canonical and dependent types shouldn't get here");
3468 case Type::LValueReference:
3469 case Type::RValueReference:
3470 llvm_unreachable(
"References shouldn't get here");
3473 case Type::DeducedTemplateSpecialization:
3474 llvm_unreachable(
"Undeduced type shouldn't get here");
3477 llvm_unreachable(
"Pipe types shouldn't get here");
3483 case Type::ExtVector:
3484 case Type::ConstantMatrix:
3488 case Type::BlockPointer:
3490 VTableName =
"_ZTVN10__cxxabiv123__fundamental_type_infoE";
3493 case Type::ConstantArray:
3494 case Type::IncompleteArray:
3495 case Type::VariableArray:
3497 VTableName =
"_ZTVN10__cxxabiv117__array_type_infoE";
3500 case Type::FunctionNoProto:
3501 case Type::FunctionProto:
3503 VTableName =
"_ZTVN10__cxxabiv120__function_type_infoE";
3508 VTableName =
"_ZTVN10__cxxabiv116__enum_type_infoE";
3511 case Type::Record: {
3513 cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
3516 VTableName = ClassTypeInfo;
3518 VTableName = SIClassTypeInfo;
3520 VTableName = VMIClassTypeInfo;
3526 case Type::ObjCObject:
3528 Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
3531 if (isa<BuiltinType>(Ty)) {
3532 VTableName = ClassTypeInfo;
3536 assert(isa<ObjCInterfaceType>(Ty));
3539 case Type::ObjCInterface:
3540 if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
3541 VTableName = SIClassTypeInfo;
3543 VTableName = ClassTypeInfo;
3547 case Type::ObjCObjectPointer:
3550 VTableName =
"_ZTVN10__cxxabiv119__pointer_type_infoE";
3553 case Type::MemberPointer:
3555 VTableName =
"_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
3559 llvm::Constant *VTable =
nullptr;
3563 VTable = CGM.
getModule().getNamedAlias(VTableName);
3567 CGM.
setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
3569 llvm::Type *PtrDiffTy =
3576 llvm::Constant *Eight = llvm::ConstantInt::get(CGM.
Int32Ty, 8);
3577 VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.
Int8PtrTy);
3579 llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.
Int8Ty, VTable, Eight);
3581 llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
3582 VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.
Int8PtrTy, VTable,
3585 VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.
Int8PtrTy);
3587 Fields.push_back(VTable);
3619 return llvm::GlobalValue::LinkOnceODRLinkage;
3621 if (
const RecordType *Record = dyn_cast<RecordType>(Ty)) {
3622 const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
3624 return llvm::GlobalValue::WeakODRLinkage;
3625 if (CGM.
getTriple().isWindowsItaniumEnvironment())
3626 if (RD->
hasAttr<DLLImportAttr>() &&
3634 .isWindowsGNUEnvironment())
3638 return llvm::GlobalValue::LinkOnceODRLinkage;
3641 llvm_unreachable(
"Invalid linkage!");
3644 llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
QualType Ty) {
3650 llvm::raw_svector_ostream Out(Name);
3653 llvm::GlobalVariable *OldGV = CGM.
getModule().getNamedGlobal(Name);
3654 if (OldGV && !OldGV->isDeclaration()) {
3655 assert(!OldGV->hasAvailableExternallyLinkage() &&
3656 "available_externally typeinfos not yet implemented");
3658 return llvm::ConstantExpr::getBitCast(OldGV, CGM.
Int8PtrTy);
3664 return GetAddrOfExternalRTTIDescriptor(Ty);
3671 llvm::GlobalValue::VisibilityTypes llvmVisibility;
3672 if (llvm::GlobalValue::isLocalLinkage(
Linkage))
3676 ItaniumCXXABI::RUK_NonUniqueHidden)
3681 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
3682 llvm::GlobalValue::DefaultStorageClass;
3683 if (CGM.
getTriple().isWindowsItaniumEnvironment()) {
3685 if (RD && RD->
hasAttr<DLLExportAttr>())
3686 DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
3689 return BuildTypeInfo(Ty,
Linkage, llvmVisibility, DLLStorageClass);
3692 llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
3694 llvm::GlobalVariable::LinkageTypes
Linkage,
3695 llvm::GlobalValue::VisibilityTypes
Visibility,
3696 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
3698 BuildVTablePointer(cast<Type>(Ty));
3702 llvm::Constant *TypeNameField;
3706 ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =
3708 if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {
3711 TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.
Int64Ty);
3712 llvm::Constant *flag =
3713 llvm::ConstantInt::get(CGM.
Int64Ty, ((uint64_t)1) << 63);
3714 TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
3716 llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.
Int8PtrTy);
3718 TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.
Int8PtrTy);
3720 Fields.push_back(TypeNameField);
3723 #define TYPE(Class, Base)
3724 #define ABSTRACT_TYPE(Class, Base)
3725 #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3726 #define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3727 #define DEPENDENT_TYPE(Class, Base) case Type::Class:
3728 #include "clang/AST/TypeNodes.inc"
3729 llvm_unreachable(
"Non-canonical and dependent types shouldn't get here");
3734 case Type::ExtVector:
3735 case Type::ConstantMatrix:
3737 case Type::BlockPointer:
3742 case Type::LValueReference:
3743 case Type::RValueReference:
3744 llvm_unreachable(
"References shouldn't get here");
3747 case Type::DeducedTemplateSpecialization:
3748 llvm_unreachable(
"Undeduced type shouldn't get here");
3756 case Type::ConstantArray:
3757 case Type::IncompleteArray:
3758 case Type::VariableArray:
3763 case Type::FunctionNoProto:
3764 case Type::FunctionProto:
3774 case Type::Record: {
3776 cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
3783 BuildSIClassTypeInfo(RD);
3785 BuildVMIClassTypeInfo(RD);
3790 case Type::ObjCObject:
3791 case Type::ObjCInterface:
3792 BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
3795 case Type::ObjCObjectPointer:
3796 BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
3800 BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
3803 case Type::MemberPointer:
3804 BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
3812 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
3815 llvm::raw_svector_ostream Out(Name);
3818 llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
3819 llvm::GlobalVariable *GV =
3820 new llvm::GlobalVariable(M, Init->getType(),
3824 auto GVDLLStorageClass = DLLStorageClass;
3826 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3827 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
3828 if (RD->
hasAttr<DLLExportAttr>() ||
3829 CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD)) {
3830 GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
3837 GV->takeName(OldGV);
3838 llvm::Constant *NewPtr =
3839 llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
3840 OldGV->replaceAllUsesWith(NewPtr);
3841 OldGV->eraseFromParent();
3845 GV->setComdat(M.getOrInsertComdat(GV->getName()));
3872 TypeName->setDLLStorageClass(DLLStorageClass);
3880 return llvm::ConstantExpr::getBitCast(GV, CGM.
Int8PtrTy);
3885 void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(
const ObjCObjectType *OT) {
3888 assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
3892 if (isa<BuiltinType>(T))
return;
3903 llvm::Constant *BaseTypeInfo =
3904 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(SuperTy);
3905 Fields.push_back(BaseTypeInfo);
3910 void ItaniumRTTIBuilder::BuildSIClassTypeInfo(
const CXXRecordDecl *RD) {
3914 llvm::Constant *BaseTypeInfo =
3916 Fields.push_back(BaseTypeInfo);
3939 if (
Base->isVirtual()) {
3941 if (!Bases.VirtualBases.insert(BaseDecl).second) {
3944 Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
3946 if (Bases.NonVirtualBases.count(BaseDecl))
3947 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
3951 if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
3954 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
3956 if (Bases.VirtualBases.count(BaseDecl))
3957 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
3962 for (
const auto &I : BaseDecl->bases())
3973 for (
const auto &I : RD->
bases())
3982 void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(
const CXXRecordDecl *RD) {
3983 llvm::Type *UnsignedIntLTy =
3991 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
3996 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->
getNumBases()));
4028 llvm::Type *OffsetFlagsLTy =
4033 Fields.push_back(ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(
Base.getType()));
4038 int64_t OffsetFlags = 0;
4045 if (
Base.isVirtual())
4053 OffsetFlags = uint64_t(
Offset.getQuantity()) << 8;
4057 if (
Base.isVirtual())
4058 OffsetFlags |= BCTI_Virtual;
4060 OffsetFlags |= BCTI_Public;
4062 Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags));
4071 if (
Type.isConstQualified())
4072 Flags |= ItaniumRTTIBuilder::PTI_Const;
4073 if (
Type.isVolatileQualified())
4074 Flags |= ItaniumRTTIBuilder::PTI_Volatile;
4075 if (
Type.isRestrictQualified())
4076 Flags |= ItaniumRTTIBuilder::PTI_Restrict;
4083 Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
4086 if (Proto->isNothrow()) {
4087 Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
4097 void ItaniumRTTIBuilder::BuildPointerTypeInfo(
QualType PointeeTy) {
4103 llvm::Type *UnsignedIntLTy =
4105 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4110 llvm::Constant *PointeeTypeInfo =
4111 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(PointeeTy);
4112 Fields.push_back(PointeeTypeInfo);
4128 Flags |= PTI_ContainingClassIncomplete;
4130 llvm::Type *UnsignedIntLTy =
4132 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4137 llvm::Constant *PointeeTypeInfo =
4138 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(PointeeTy);
4139 Fields.push_back(PointeeTypeInfo);
4146 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(
QualType(ClassType, 0)));
4149 llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(
QualType Ty) {
4150 return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
4153 void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(
const CXXRecordDecl *RD) {
4156 getContext().VoidTy, getContext().NullPtrTy,
4157 getContext().BoolTy, getContext().WCharTy,
4158 getContext().CharTy, getContext().UnsignedCharTy,
4159 getContext().SignedCharTy, getContext().ShortTy,
4160 getContext().UnsignedShortTy, getContext().IntTy,
4161 getContext().UnsignedIntTy, getContext().LongTy,
4162 getContext().UnsignedLongTy, getContext().LongLongTy,
4163 getContext().UnsignedLongLongTy, getContext().Int128Ty,
4164 getContext().UnsignedInt128Ty, getContext().HalfTy,
4165 getContext().FloatTy, getContext().DoubleTy,
4166 getContext().LongDoubleTy, getContext().Float128Ty,
4167 getContext().Char8Ty, getContext().Char16Ty,
4168 getContext().Char32Ty
4170 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4172 ? llvm::GlobalValue::DLLExportStorageClass
4173 : llvm::GlobalValue::DefaultStorageClass;
4174 llvm::GlobalValue::VisibilityTypes
Visibility =
4176 for (
const QualType &FundamentalType : FundamentalTypes) {
4178 QualType PointerTypeConst = getContext().getPointerType(
4179 FundamentalType.withConst());
4181 ItaniumRTTIBuilder(*this).BuildTypeInfo(
4189 ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
4191 if (shouldRTTIBeUnique())
4195 if (
Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
4196 Linkage != llvm::GlobalValue::WeakODRLinkage)
4204 if (
Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
4205 return RUK_NonUniqueHidden;
4210 assert(
Linkage == llvm::GlobalValue::WeakODRLinkage);
4211 return RUK_NonUniqueVisible;
4216 enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
4221 return StructorCodegen::Emit;
4226 return StructorCodegen::Emit;
4229 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
4232 const auto *CD = cast<CXXConstructorDecl>(MD);
4237 if (llvm::GlobalValue::isDiscardableIfUnused(
Linkage))
4238 return StructorCodegen::RAUW;
4241 if (!llvm::GlobalAlias::isValidLinkage(
Linkage))
4242 return StructorCodegen::RAUW;
4244 if (llvm::GlobalValue::isWeakForLinker(
Linkage)) {
4248 return StructorCodegen::COMDAT;
4249 return StructorCodegen::Emit;
4252 return StructorCodegen::Alias;
4262 if (Entry && !Entry->isDeclaration())
4265 auto *Aliasee = cast<llvm::GlobalValue>(CGM.
GetAddrOfGlobal(TargetDecl));
4271 Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4275 assert(Entry->getType() == Aliasee->getType() &&
4276 "declaration exists with different type");
4277 Alias->takeName(Entry);
4278 Entry->replaceAllUsesWith(Alias);
4279 Entry->eraseFromParent();
4281 Alias->setName(MangledName);
4288 void ItaniumCXXABI::emitCXXStructor(
GlobalDecl GD) {
4289 auto *MD = cast<CXXMethodDecl>(GD.
getDecl());
4290 auto *CD = dyn_cast<CXXConstructorDecl>(MD);
4303 if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {
4308 if (CGType == StructorCodegen::RAUW) {
4321 CGType != StructorCodegen::COMDAT &&
4339 if (CGType == StructorCodegen::COMDAT) {
4341 llvm::raw_svector_ostream Out(Buffer);
4343 getMangleContext().mangleCXXDtorComdat(DD, Out);
4345 getMangleContext().mangleCXXCtorComdat(CD, Out);
4346 llvm::Comdat *
C = CGM.
getModule().getOrInsertComdat(Out.str());
4355 llvm::FunctionType *FTy = llvm::FunctionType::get(
4363 llvm::FunctionType *FTy =
4364 llvm::FunctionType::get(CGM.
VoidTy,
false);
4371 llvm::FunctionType *FTy = llvm::FunctionType::get(
4391 CallEndCatch(
bool MightThrow) : MightThrow(MightThrow) {}
4411 bool EndMightThrow) {
4412 llvm::CallInst *call =
4435 if (isa<ReferenceType>(CatchType)) {
4440 llvm::Value *AdjustedExn =
CallBeginCatch(CGF, Exn, EndCatchMightThrow);
4445 if (
const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
4454 unsigned HeaderSize =
4457 CGF.
Builder.CreateConstGEP1_32(CGF.
Int8Ty, Exn, HeaderSize);
4480 llvm::Value *Casted = CGF.
Builder.CreateBitCast(AdjustedExn, PtrTy);
4488 llvm::Value *ExnCast =
4489 CGF.
Builder.CreateBitCast(AdjustedExn, LLVMCatchTy,
"exn.byref");
4501 if (CatchType->hasPointerRepresentation()) {
4502 llvm::Value *CastExn =
4503 CGF.
Builder.CreateBitCast(AdjustedExn, LLVMCatchTy,
"exn.casted");
4520 llvm_unreachable(
"bad ownership qualifier!");
4525 llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0);
4526 llvm::Value *
Cast = CGF.
Builder.CreateBitCast(AdjustedExn, PtrTy);
4541 llvm_unreachable(
"evaluation kind filtered out!");
4543 llvm_unreachable(
"bad evaluation kind");
4546 assert(isa<RecordType>(CatchType) &&
"unexpected catch type!");
4547 auto catchRD = CatchType->getAsCXXRecordDecl();
4550 llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0);
4557 Address adjustedExn(CGF.
Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4558 LLVMCatchTy, caughtExnAlignment);
4567 llvm::CallInst *rawAdjustedExn =
4571 Address adjustedExn(CGF.
Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4572 LLVMCatchTy, caughtExnAlignment);
4628 VarDecl *CatchParam = S->getExceptionDecl();
4645 llvm::FunctionType *fnTy =
4648 fnTy,
"__clang_call_terminate", llvm::AttributeList(),
true);
4649 llvm::Function *fn =
4650 cast<llvm::Function>(fnRef.getCallee()->stripPointerCasts());
4652 fn->setDoesNotThrow();
4653 fn->setDoesNotReturn();
4658 fn->addFnAttr(llvm::Attribute::NoInline);
4662 fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
4665 fn->setComdat(CGM.
getModule().getOrInsertComdat(fn->getName()));
4668 llvm::BasicBlock *entry =
4673 llvm::Value *exn = &*fn->arg_begin();
4676 llvm::CallInst *catchCall = builder.CreateCall(
getBeginCatchFn(CGM), exn);
4677 catchCall->setDoesNotThrow();
4681 llvm::CallInst *termCall = builder.CreateCall(CGM.
getTerminateFn());
4682 termCall->setDoesNotThrow();
4683 termCall->setDoesNotReturn();
4687 builder.CreateUnreachable();
4693 ItaniumCXXABI::emitTerminateForUnexpectedException(
CodeGenFunction &CGF,
4703 std::pair<llvm::Value *, const CXXRecordDecl *>
4714 ItaniumCXXABI::emitBeginCatch(CGF, C);
4718 WebAssemblyCXXABI::emitTerminateForUnexpectedException(
CodeGenFunction &CGF,
4731 llvm::FunctionCallee Dtor,
4732 llvm::Constant *Addr) {
4735 llvm::FunctionType *FTy =
4736 llvm::FunctionType::get(CGM.
IntTy, CGM.
IntTy,
true);
4737 llvm::PointerType *FpTy = FTy->getPointerTo();
4740 llvm::FunctionType *AtExitTy =
4741 llvm::FunctionType::get(CGM.
IntTy, {CGM.IntTy, FpTy},
true);
4744 llvm::FunctionCallee
AtExit =
4752 llvm::Value *NV = llvm::Constant::getNullValue(CGM.
IntTy);
4767 emitCXXStermFinalizer(D, DtorStub, Addr);
4770 void XLCXXABI::emitCXXStermFinalizer(
const VarDecl &D, llvm::Function *dtorStub,
4771 llvm::Constant *addr) {
4772 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
4775 llvm::raw_svector_ostream Out(FnName);
4776 getMangleContext().mangleDynamicStermFinalizer(&D, Out);
4796 llvm::Value *NeedsDestruct = CGF.
Builder.CreateIsNull(
V,
"needs_destruct");
4798 llvm::BasicBlock *DestructCallBlock = CGF.
createBasicBlock(
"destruct.call");
4803 CGF.
Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
4808 llvm::CallInst *CI = CGF.
Builder.CreateCall(dtorStub);
4811 CI->setCallingConv(dtorStub->getCallingConv());
4817 if (
auto *IPA = D.
getAttr<InitPriorityAttr>()) {
4819 IPA->getPriority());