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"
40using 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) { }
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;
138 llvm::Constant *Src)
override;
150 llvm::Value *L, llvm::Value *R,
152 bool Inequality)
override;
169 llvm::Value *Exn)
override;
171 void EmitFundamentalRTTIDescriptors(
const CXXRecordDecl *RD);
175 QualType CatchHandlerType)
override {
183 llvm::Type *StdTypeInfoPtrTy)
override;
191 llvm::BasicBlock *CastEnd)
override;
206 AddedStructorArgCounts
229 bool Delegating)
override;
235 bool Delegating)
override;
246 CodeGenFunction::VPtr Vptr)
override;
260 llvm::Value *getVTableAddressPointInStructorWithVTT(
278 DeleteOrMemberCallExpr E)
override;
283 bool canSpeculativelyEmitVTableAsBaseClass(
const CXXRecordDecl *RD)
const;
289 if (ForVTable && !Thunk->hasLocalLinkage())
290 Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
291 CGM.setGVProperties(Thunk, GD);
304 assert(!Args.empty() &&
"expected the arglist to not be empty!");
305 return Args.size() - 1;
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,
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();
417 if (RTTIDecl->
getVisibility() == Visibility::HiddenVisibility)
419 }
else if (VtableComponent.isUsedFunctionPointerKind()) {
420 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
421 if (Method->
getVisibility() == Visibility::HiddenVisibility &&
430class ARMCXXABI :
public ItaniumCXXABI {
433 ItaniumCXXABI(CGM,
true,
436 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
444 llvm::Value *NumElements,
451class AppleARM64CXXABI :
public ARMCXXABI {
454 Use32BitVTableOffsetABI =
true;
458 bool shouldRTTIBeUnique()
const override {
return false; }
461class FuchsiaCXXABI final :
public ItaniumCXXABI {
464 : ItaniumCXXABI(CGM) {}
467 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
470class WebAssemblyCXXABI final :
public ItaniumCXXABI {
473 : ItaniumCXXABI(CGM,
true,
478 llvm::Value *Exn)
override;
481 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
482 bool canCallMismatchedFunctionType()
const override {
return false; }
485class XLCXXABI final :
public ItaniumCXXABI {
488 : ItaniumCXXABI(CGM) {}
491 llvm::FunctionCallee dtor,
492 llvm::Constant *addr)
override;
494 bool useSinitAndSterm()
const override {
return true; }
497 void emitCXXStermFinalizer(
const VarDecl &D, llvm::Function *dtorStub,
498 llvm::Constant *addr);
506 case TargetCXXABI::GenericARM:
507 case TargetCXXABI::iOS:
508 case TargetCXXABI::WatchOS:
509 return new ARMCXXABI(CGM);
511 case TargetCXXABI::AppleARM64:
512 return new AppleARM64CXXABI(CGM);
514 case TargetCXXABI::Fuchsia:
515 return new FuchsiaCXXABI(CGM);
520 case TargetCXXABI::GenericAArch64:
521 return new ItaniumCXXABI(CGM,
true,
524 case TargetCXXABI::GenericMIPS:
525 return new ItaniumCXXABI(CGM,
true);
527 case TargetCXXABI::WebAssembly:
528 return new WebAssemblyCXXABI(CGM);
530 case TargetCXXABI::XL:
531 return new XLCXXABI(CGM);
533 case TargetCXXABI::GenericItanium:
535 == llvm::Triple::le32) {
539 return new ItaniumCXXABI(CGM,
true);
541 return new ItaniumCXXABI(CGM);
543 case TargetCXXABI::Microsoft:
544 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
546 llvm_unreachable(
"bad ABI kind");
552 return CGM.PtrDiffTy;
553 return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);
576CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
578 llvm::Value *&ThisPtrForCall,
587 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
588 CGM.getTypes().arrangeCXXMethodType(RD, FPT,
nullptr));
590 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
597 llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1,
"memptr.adj");
600 llvm::Value *Adj = RawAdj;
601 if (UseARMMethodPtrABI)
602 Adj = Builder.CreateAShr(Adj, ptrdiff_1,
"memptr.adj.shifted");
607 llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
608 Ptr = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), Ptr, Adj);
609 This = Builder.CreateBitCast(Ptr, This->getType(),
"this.adjusted");
610 ThisPtrForCall = This;
613 llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0,
"memptr.ptr");
617 llvm::Value *IsVirtual;
618 if (UseARMMethodPtrABI)
619 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
621 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
622 IsVirtual = Builder.CreateIsNotNull(IsVirtual,
"memptr.isvirtual");
623 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
631 llvm::Type *VTableTy = Builder.getInt8PtrTy();
641 llvm::Value *VTableOffset = FnAsInt;
642 if (!UseARMMethodPtrABI)
643 VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
644 if (Use32BitVTableOffsetABI) {
645 VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.
Int32Ty);
646 VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
651 llvm::Constant *CheckSourceLocation;
652 llvm::Constant *CheckTypeDesc;
653 bool ShouldEmitCFICheck = CGF.
SanOpts.
has(SanitizerKind::CFIMFCall) &&
654 CGM.HasHiddenLTOVisibility(RD);
655 bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
656 CGM.HasHiddenLTOVisibility(RD);
657 bool ShouldEmitWPDInfo =
658 CGM.getCodeGenOpts().WholeProgramVTables &&
660 !CGM.AlwaysHasLTOVisibilityPublic(RD);
661 llvm::Value *VirtualFn =
nullptr;
664 CodeGenFunction::SanitizerScope SanScope(&CGF);
665 llvm::Value *TypeId =
nullptr;
666 llvm::Value *CheckResult =
nullptr;
668 if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
672 CGM.CreateMetadataIdentifierForVirtualMemPtrType(
QualType(MPT, 0));
676 if (ShouldEmitVFEInfo) {
677 llvm::Value *VFPAddr =
678 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
685 llvm::Value *CheckedLoad = Builder.CreateCall(
686 CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
687 {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
688 CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
689 VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
690 VirtualFn = Builder.CreateBitCast(VirtualFn, FTy->getPointerTo(),
695 if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
696 llvm::Value *VFPAddr =
697 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
698 llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
699 ? llvm::Intrinsic::type_test
700 : llvm::Intrinsic::public_type_test;
702 CheckResult = Builder.CreateCall(
703 CGM.getIntrinsic(IID),
704 {Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId});
707 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
708 VirtualFn = CGF.
Builder.CreateCall(
709 CGM.getIntrinsic(llvm::Intrinsic::load_relative,
710 {VTableOffset->getType()}),
711 {VTable, VTableOffset});
712 VirtualFn = CGF.
Builder.CreateBitCast(VirtualFn, FTy->getPointerTo());
714 llvm::Value *VFPAddr =
716 VFPAddr = CGF.
Builder.CreateBitCast(
717 VFPAddr, FTy->getPointerTo()->getPointerTo());
723 assert(VirtualFn &&
"Virtual fuction pointer not created!");
724 assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
726 "Check result required but not created!");
728 if (ShouldEmitCFICheck) {
732 llvm::Constant *StaticData[] = {
733 llvm::ConstantInt::get(CGF.
Int8Ty, CodeGenFunction::CFITCK_VMFCall),
738 if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
739 CGF.
EmitTrapCheck(CheckResult, SanitizerHandler::CFICheckFail);
741 llvm::Value *AllVtables = llvm::MetadataAsValue::get(
742 CGM.getLLVMContext(),
743 llvm::MDString::get(CGM.getLLVMContext(),
"all-vtables"));
744 llvm::Value *ValidVtable = Builder.CreateCall(
745 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
746 CGF.
EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIMFCall),
747 SanitizerHandler::CFICheckFail, StaticData,
748 {VTable, ValidVtable});
751 FnVirtual = Builder.GetInsertBlock();
760 llvm::Value *NonVirtualFn =
761 Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(),
"memptr.nonvirtualfn");
764 if (ShouldEmitCFICheck) {
767 CodeGenFunction::SanitizerScope SanScope(&CGF);
769 llvm::Constant *StaticData[] = {
770 llvm::ConstantInt::get(CGF.
Int8Ty, CodeGenFunction::CFITCK_NVMFCall),
775 llvm::Value *Bit = Builder.getFalse();
776 llvm::Value *CastedNonVirtualFn =
777 Builder.CreateBitCast(NonVirtualFn, CGF.
Int8PtrTy);
779 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
780 getContext().getMemberPointerType(
783 llvm::Value *TypeId =
786 llvm::Value *TypeTest =
787 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
788 {CastedNonVirtualFn, TypeId});
789 Bit = Builder.CreateOr(Bit, TypeTest);
792 CGF.
EmitCheck(std::make_pair(Bit, SanitizerKind::CFIMFCall),
793 SanitizerHandler::CFICheckFail, StaticData,
794 {CastedNonVirtualFn, llvm::UndefValue::get(CGF.
IntPtrTy)});
796 FnNonVirtual = Builder.GetInsertBlock();
802 llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2);
803 CalleePtr->addIncoming(VirtualFn, FnVirtual);
804 CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
812llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
815 assert(MemPtr->getType() == CGM.PtrDiffTy);
823 llvm::Value *Addr = Builder.CreateInBoundsGEP(
824 Base.getElementType(),
Base.getPointer(), MemPtr,
"memptr.offset");
829 ->getPointerTo(
Base.getAddressSpace());
830 return Builder.CreateBitCast(Addr, PType);
860 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
861 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
865 if (E->
getCastKind() == CK_ReinterpretMemberPointer)
return src;
868 if (isa<llvm::Constant>(src))
869 return EmitMemberPointerConversion(E, cast<llvm::Constant>(src));
871 llvm::Constant *adj = getMemberPointerAdjustment(E);
872 if (!adj)
return src;
875 bool isDerivedToBase = (E->
getCastKind() == CK_DerivedToBaseMemberPointer);
885 dst = Builder.CreateNSWSub(src, adj,
"adj");
887 dst = Builder.CreateNSWAdd(src, adj,
"adj");
890 llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType());
891 llvm::Value *isNull = Builder.CreateICmpEQ(src, null,
"memptr.isnull");
892 return Builder.CreateSelect(isNull, src, dst);
896 if (UseARMMethodPtrABI) {
897 uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
899 adj = llvm::ConstantInt::get(adj->getType(), offset);
902 llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1,
"src.adj");
905 dstAdj = Builder.CreateNSWSub(srcAdj, adj,
"adj");
907 dstAdj = Builder.CreateNSWAdd(srcAdj, adj,
"adj");
909 return Builder.CreateInsertValue(src, dstAdj, 1);
913ItaniumCXXABI::EmitMemberPointerConversion(
const CastExpr *E,
914 llvm::Constant *src) {
915 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
916 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
920 if (E->
getCastKind() == CK_ReinterpretMemberPointer)
return src;
923 llvm::Constant *adj = getMemberPointerAdjustment(E);
924 if (!adj)
return src;
926 bool isDerivedToBase = (E->
getCastKind() == CK_DerivedToBaseMemberPointer);
935 if (src->isAllOnesValue())
return src;
938 return llvm::ConstantExpr::getNSWSub(src, adj);
940 return llvm::ConstantExpr::getNSWAdd(src, adj);
944 if (UseARMMethodPtrABI) {
945 uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
947 adj = llvm::ConstantInt::get(adj->getType(), offset);
950 llvm::Constant *srcAdj = src->getAggregateElement(1);
951 llvm::Constant *dstAdj;
953 dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);
955 dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);
957 llvm::Constant *res = ConstantFoldInsertValueInstruction(src, dstAdj, 1);
958 assert(res !=
nullptr &&
"Folding must succeed");
967 return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL,
true);
969 llvm::Constant *
Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
970 llvm::Constant *Values[2] = {
Zero,
Zero };
971 return llvm::ConstantStruct::getAnon(Values);
980 return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.
getQuantity());
984ItaniumCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
988llvm::Constant *ItaniumCXXABI::BuildMemberPointer(
const CXXMethodDecl *MD,
990 assert(MD->
isInstance() &&
"Member function must not be static!");
995 llvm::Constant *MemPtr[2];
997 uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
999 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1001 VTableOffset = Index * 4;
1006 VTableOffset = Index * PointerWidth.
getQuantity();
1009 if (UseARMMethodPtrABI) {
1016 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);
1017 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1024 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
1025 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1032 if (Types.isFuncTypeConvertible(FPT)) {
1034 Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
1040 llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty);
1042 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
1043 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1044 (UseARMMethodPtrABI ? 2 : 1) *
1048 return llvm::ConstantStruct::getAnon(MemPtr);
1051llvm::Constant *ItaniumCXXABI::EmitMemberPointer(
const APValue &MP,
1056 return EmitNullMemberPointer(MPT);
1064 getContext().toCharUnitsFromBits(getContext().
getFieldOffset(MPD));
1080 llvm::ICmpInst::Predicate
Eq;
1081 llvm::Instruction::BinaryOps
And, Or;
1083 Eq = llvm::ICmpInst::ICMP_NE;
1084 And = llvm::Instruction::Or;
1085 Or = llvm::Instruction::And;
1087 Eq = llvm::ICmpInst::ICMP_EQ;
1088 And = llvm::Instruction::And;
1089 Or = llvm::Instruction::Or;
1095 return Builder.CreateICmp(
Eq, L, R);
1107 llvm::Value *LPtr = Builder.CreateExtractValue(L, 0,
"lhs.memptr.ptr");
1108 llvm::Value *RPtr = Builder.CreateExtractValue(R, 0,
"rhs.memptr.ptr");
1112 llvm::Value *PtrEq = Builder.CreateICmp(
Eq, LPtr, RPtr,
"cmp.ptr");
1117 llvm::Value *
Zero = llvm::Constant::getNullValue(LPtr->getType());
1118 llvm::Value *EqZero = Builder.CreateICmp(
Eq, LPtr, Zero,
"cmp.ptr.null");
1122 llvm::Value *LAdj = Builder.CreateExtractValue(L, 1,
"lhs.memptr.adj");
1123 llvm::Value *RAdj = Builder.CreateExtractValue(R, 1,
"rhs.memptr.adj");
1124 llvm::Value *AdjEq = Builder.CreateICmp(
Eq, LAdj, RAdj,
"cmp.adj");
1128 if (UseARMMethodPtrABI) {
1129 llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
1132 llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj,
"or.adj");
1133 llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
1134 llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(
Eq, OrAdjAnd1, Zero,
1136 EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
1140 llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
1141 Result = Builder.CreateBinOp(And, PtrEq, Result,
1142 Inequality ?
"memptr.ne" :
"memptr.eq");
1148 llvm::Value *MemPtr,
1154 assert(MemPtr->getType() == CGM.PtrDiffTy);
1155 llvm::Value *NegativeOne =
1156 llvm::Constant::getAllOnesValue(MemPtr->getType());
1157 return Builder.CreateICmpNE(MemPtr, NegativeOne,
"memptr.tobool");
1161 llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0,
"memptr.ptr");
1163 llvm::Constant *
Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
1164 llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero,
"memptr.tobool");
1168 if (UseARMMethodPtrABI) {
1169 llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
1170 llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1,
"memptr.adj");
1171 llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One,
"memptr.virtualbit");
1172 llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,
1173 "memptr.isvirtual");
1174 Result = Builder.CreateOr(Result, IsVirtual);
1180bool ItaniumCXXABI::classifyReturnType(
CGFunctionInfo &FI)
const {
1187 auto Align = CGM.getContext().getTypeAlignInChars(FI.
getReturnType());
1208 if (UseGlobalDelete) {
1215 llvm::Value *VTable =
1219 llvm::Value *OffsetPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
1220 CGF.
IntPtrTy, VTable, -2,
"complete-offset.ptr");
1224 llvm::Value *CompletePtr =
1238 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE);
1240 if (UseGlobalDelete)
1244void ItaniumCXXABI::emitRethrow(
CodeGenFunction &CGF,
bool isNoReturn) {
1247 llvm::FunctionType *FTy =
1248 llvm::FunctionType::get(CGM.VoidTy,
false);
1250 llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy,
"__cxa_rethrow");
1261 llvm::FunctionType *FTy =
1272 llvm::FunctionType *FTy =
1273 llvm::FunctionType::get(CGM.
VoidTy, Args,
false);
1281 llvm::Type *SizeTy = CGF.
ConvertType(getContext().getSizeType());
1282 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
1286 AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize),
"exception");
1293 llvm::Constant *
TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
1298 llvm::Constant *Dtor =
nullptr;
1301 if (!
Record->hasTrivialDestructor()) {
1304 Dtor = llvm::ConstantExpr::getBitCast(Dtor, CGM.Int8PtrTy);
1307 if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1309 llvm::Value *args[] = { ExceptionPtr,
TypeInfo, Dtor };
1320 llvm::Type *PtrDiffTy =
1323 llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy };
1325 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args,
false);
1329 FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
1330 FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
1331 llvm::AttributeList Attrs = llvm::AttributeList::get(
1332 CGF.
getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
1339 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1356 unsigned NumPublicPaths = 0;
1369 if (PathElement.Base->isVirtual())
1372 if (NumPublicPaths > 1)
1378 PathElement.Base->getType()->getAsCXXRecordDecl());
1383 if (NumPublicPaths == 0)
1387 if (NumPublicPaths > 1)
1397 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1402bool ItaniumCXXABI::shouldTypeidBeNullChecked(
bool IsDeref,
1410 Call->setDoesNotReturn();
1411 CGF.
Builder.CreateUnreachable();
1417 llvm::Type *StdTypeInfoPtrTy) {
1420 llvm::Value *
Value =
1421 CGF.
GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo(), ClassDecl);
1423 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1427 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1428 {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
1435 CGF.
Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy,
Value, -1ULL);
1441bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
1446llvm::Value *ItaniumCXXABI::EmitDynamicCastCall(
1449 llvm::Type *PtrDiffLTy =
1453 llvm::Value *SrcRTTI =
1455 llvm::Value *DestRTTI =
1461 llvm::Value *OffsetHint = llvm::ConstantInt::get(
1469 llvm::Value *args[] = {
Value, SrcRTTI, DestRTTI, OffsetHint};
1476 llvm::BasicBlock *BadCastBlock =
1483 EmitBadCastCall(CGF);
1489llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(
CodeGenFunction &CGF,
1496 llvm::Value *OffsetToTop;
1497 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1499 llvm::Value *VTable =
1500 CGF.
GetVTablePtr(ThisAddr, CGM.Int32Ty->getPointerTo(), ClassDecl);
1504 CGF.
Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);
1508 llvm::Type *PtrDiffLTy =
1512 llvm::Value *VTable =
1513 CGF.
GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), ClassDecl);
1517 CGF.
Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
1531 Call->setDoesNotReturn();
1532 CGF.
Builder.CreateUnreachable();
1541 llvm::Value *VTablePtr = CGF.
GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
1543 CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
1545 llvm::Value *VBaseOffsetPtr =
1546 CGF.
Builder.CreateConstGEP1_64(
1548 "vbase.offset.ptr");
1550 llvm::Value *VBaseOffset;
1551 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1553 CGF.
Builder.CreateBitCast(VBaseOffsetPtr, CGF.
Int32Ty->getPointerTo());
1558 VBaseOffsetPtr = CGF.
Builder.CreateBitCast(VBaseOffsetPtr,
1559 CGM.PtrDiffTy->getPointerTo());
1561 CGM.PtrDiffTy, VBaseOffsetPtr, CGF.
getPointerAlign(),
"vbase.offset");
1568 assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
1583ItaniumCXXABI::buildStructorSignature(
GlobalDecl GD,
1593 cast<CXXMethodDecl>(GD.
getDecl())->getParent()->getNumVBases() != 0) {
1594 ArgTys.insert(ArgTys.begin() + 1,
1596 return AddedStructorArgCounts::prefix(1);
1598 return AddedStructorArgCounts{};
1621 assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
1624 if (NeedsVTTParameter(CGF.
CurGD)) {
1632 Params.insert(Params.begin() + 1, VTTDecl);
1633 getStructorImplicitParamDecl(CGF) = VTTDecl;
1644 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
1647 if (getStructorImplicitParamDecl(CGF)) {
1660 if (HasThisReturn(CGF.
CurGD))
1666 bool ForVirtualBase,
bool Delegating) {
1668 return AddedStructorArgs{};
1673 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1674 return AddedStructorArgs::prefix({{VTT, VTTTy}});
1677llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(
1679 bool ForVirtualBase,
bool Delegating) {
1687 bool Delegating,
Address This,
1692 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1695 if (getContext().getLangOpts().AppleKext &&
1707 llvm::GlobalVariable *VTable = getAddrOfVTable(RD,
CharUnits());
1708 if (VTable->hasInitializer())
1713 llvm::GlobalVariable::LinkageTypes
Linkage = CGM.getVTableLinkage(RD);
1714 llvm::Constant *RTTI =
1715 CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
1719 auto components = builder.beginStruct();
1721 llvm::GlobalValue::isLocalLinkage(
Linkage));
1722 components.finishAndSetAsInitializer(VTable);
1727 if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
1728 VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
1731 CGM.setGVProperties(VTable, RD);
1739 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
1740 cast<NamespaceDecl>(DC)->getIdentifier()->isStr(
"__cxxabiv1") &&
1742 EmitFundamentalRTTIDescriptors(RD);
1749 if (!VTable->isDeclarationForLinker() ||
1750 CGM.getCodeGenOpts().WholeProgramVTables) {
1751 CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
1755 if (VTable->isDeclarationForLinker()) {
1756 assert(CGM.getCodeGenOpts().WholeProgramVTables);
1757 CGM.addCompilerUsedGlobal(VTable);
1763 if (!VTable->isDSOLocal())
1768bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
1770 if (Vptr.NearestVBase ==
nullptr)
1772 return NeedsVTTParameter(CGF.
CurGD);
1775llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
1779 if ((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
1780 NeedsVTTParameter(CGF.
CurGD)) {
1781 return getVTableAddressPointInStructorWithVTT(CGF, VTableClass,
Base,
1784 return getVTableAddressPoint(
Base, VTableClass);
1790 llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass,
CharUnits());
1795 CGM.getItaniumVTableContext()
1796 .getVTableLayout(VTableClass)
1797 .getAddressPoint(
Base);
1798 llvm::Value *Indices[] = {
1799 llvm::ConstantInt::get(CGM.Int32Ty, 0),
1800 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.
VTableIndex),
1804 return llvm::ConstantExpr::getGetElementPtr(VTable->getValueType(), VTable,
1811template <
typename T>
1813 bool FoundNonInlineVirtualMethodWithAttr =
false;
1815 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
1816 if (!FD->isVirtualAsWritten() || FD->isInlineSpecified() ||
1817 FD->doesThisDeclarationHaveABody())
1821 FoundNonInlineVirtualMethodWithAttr =
true;
1829 return FoundNonInlineVirtualMethodWithAttr;
1832llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
1835 assert((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
1836 NeedsVTTParameter(CGF.
CurGD) &&
"This class doesn't have VTT");
1840 CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass,
Base);
1844 if (VirtualPointerIndex)
1845 VTT = CGF.
Builder.CreateConstInBoundsGEP1_64(
1846 CGF.
VoidPtrTy, VTT, VirtualPointerIndex);
1853llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
1855 return getVTableAddressPoint(
Base, VTableClass);
1858llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(
const CXXRecordDecl *RD,
1860 assert(VPtrOffset.
isZero() &&
"Itanium ABI only supports zero vptr offsets");
1862 llvm::GlobalVariable *&VTable = VTables[RD];
1867 CGM.addDeferredVTable(RD);
1870 llvm::raw_svector_ostream Out(Name);
1871 getMangleContext().mangleCXXVTable(RD, Out);
1874 CGM.getItaniumVTableContext().getVTableLayout(RD);
1875 llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
1880 unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()
1882 : CGM.getTarget().getPointerAlign(LangAS::Default);
1884 VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
1885 Name, VTableType, llvm::GlobalValue::ExternalLinkage,
1886 getContext().toCharUnitsFromBits(PAlign).getAsAlign());
1887 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1896 if (CGM.getTarget().hasPS4DLLImportExport()) {
1897 if ((!RD->
hasAttr<DLLImportAttr>()) && (!RD->
hasAttr<DLLExportAttr>())) {
1898 if (CGM.getVTables().isVTableExternal(RD)) {
1899 if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD))
1900 VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
1902 if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD))
1903 VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1907 CGM.setGVProperties(VTable, RD);
1917 llvm::Type *TyPtr = Ty->getPointerTo();
1918 auto *MethodDecl = cast<CXXMethodDecl>(GD.
getDecl());
1920 This, TyPtr->getPointerTo(), MethodDecl->getParent());
1922 uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
1926 MethodDecl->getParent(), VTable, TyPtr,
1928 CGM.getContext().getTargetInfo().getPointerWidth(LangAS::Default) /
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(),
1972llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
1974 Address This, DeleteOrMemberCallExpr E) {
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();
1999void ItaniumCXXABI::emitVirtualInheritanceTables(
const CXXRecordDecl *RD) {
2005bool 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))
2045bool 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());
2123llvm::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) {
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);
2392 guard =
new llvm::GlobalVariable(CGM.getModule(), guardTy,
2393 false, var->getLinkage(),
2394 llvm::ConstantInt::get(guardTy, 0),
2396 guard->setDSOLocal(var->isDSOLocal());
2397 guard->setVisibility(var->getVisibility());
2398 guard->setDLLStorageClass(var->getDLLStorageClass());
2400 guard->setThreadLocalMode(var->getThreadLocalMode());
2401 guard->setAlignment(guardAlignment.
getAsAlign());
2406 llvm::Comdat *
C = var->getComdat();
2408 (CGM.getTarget().getTriple().isOSBinFormatELF() ||
2409 CGM.getTarget().getTriple().isOSBinFormatWasm())) {
2410 guard->setComdat(
C);
2411 }
else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
2412 guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));
2415 CGM.setStaticLocalDeclGuardAddress(&D, guard);
2418 Address guardAddr =
Address(guard, guard->getValueType(), guardAlignment);
2443 if (!threadsafe || MaxInlineWidthInBits) {
2445 llvm::LoadInst *LI =
2446 Builder.CreateLoad(Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
2455 LI->setAtomic(llvm::AtomicOrdering::Acquire);
2478 (UseARMGuardVarABI && !useInt8GuardVariable)
2479 ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
2481 llvm::Value *NeedsInit = Builder.CreateIsNull(
V,
"guard.uninitialized");
2487 CodeGenFunction::GuardKind::VariableGuard, &D);
2515 Builder.CreateCondBr(Builder.CreateIsNotNull(
V,
"tobool"),
2516 InitBlock, EndBlock);
2526 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2527 Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
2544 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2545 Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
2553 llvm::FunctionCallee dtor,
2554 llvm::Constant *addr,
bool TLS) {
2556 "unexpected call to emitGlobalDtorWithCXAAtExit");
2558 "__cxa_atexit is disabled");
2559 const char *Name =
"__cxa_atexit";
2562 Name = T.isOSDarwin() ?
"_tlv_atexit" :
"__cxa_thread_atexit";
2569 llvm::FunctionType::get(CGF.
VoidTy, CGF.
Int8PtrTy,
false)->getPointerTo();
2572 auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0;
2573 auto AddrInt8PtrTy =
2577 llvm::Constant *handle =
2579 auto *GV = cast<llvm::GlobalValue>(handle->stripPointerCasts());
2580 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
2583 llvm::Type *paramTys[] = {
dtorTy, AddrInt8PtrTy, handle->getType()};
2584 llvm::FunctionType *atexitTy =
2585 llvm::FunctionType::get(CGF.
IntTy, paramTys,
false);
2589 if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee()))
2590 fn->setDoesNotThrow();
2597 addr = llvm::Constant::getNullValue(CGF.
Int8PtrTy);
2599 llvm::Value *args[] = {llvm::ConstantExpr::getBitCast(
2600 cast<llvm::Constant>(dtor.getCallee()),
dtorTy),
2601 llvm::ConstantExpr::getBitCast(addr, AddrInt8PtrTy),
2610 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
2614 return GlobalInitOrCleanupFn;
2617void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {
2618 for (
const auto &I : DtorsUsingAtExit) {
2620 std::string GlobalCleanupFnName =
2621 std::string(
"__GLOBAL_cleanup_") + llvm::to_string(Priority);
2623 llvm::Function *GlobalCleanupFn =
2633 llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
2634 llvm::Type *
dtorTy = dtorFuncTy->getPointerTo();
2638 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2639 auto itv = Dtors.rbegin();
2640 while (itv != Dtors.rend()) {
2641 llvm::Function *Dtor = *itv;
2646 llvm::Constant *dtor = llvm::ConstantExpr::getBitCast(Dtor,
dtorTy);
2648 llvm::Value *NeedsDestruct =
2649 CGF.
Builder.CreateIsNull(
V,
"needs_destruct");
2651 llvm::BasicBlock *DestructCallBlock =
2654 (itv + 1) != Dtors.rend() ?
"unatexit.call" :
"destruct.end");
2657 CGF.
Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
2662 llvm::CallInst *CI = CGF.
Builder.CreateCall(dtorFuncTy, dtor);
2664 CI->setCallingConv(Dtor->getCallingConv());
2672 AddGlobalDtor(GlobalCleanupFn, Priority);
2676void CodeGenModule::registerGlobalDtorsWithAtExit() {
2677 for (
const auto &I : DtorsUsingAtExit) {
2679 std::string GlobalInitFnName =
2680 std::string(
"__GLOBAL_init_") + llvm::to_string(Priority);
2681 llvm::Function *GlobalInitFn =
2695 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2696 for (
auto *Dtor : Dtors) {
2704 llvm::FunctionType::get(CGF.
VoidTy,
false)->getPointerTo();
2710 llvm::ConstantExpr::getBitCast(Dtor,
dtorTy));
2715 AddGlobalCtor(GlobalInitFn, Priority);
2719 unregisterGlobalDtorsWithUnAtExit();
2724 llvm::FunctionCallee dtor,
2725 llvm::Constant *addr) {
2733 if (CGM.getCodeGenOpts().CXAAtExit || D.
getTLSKind())
2738 if (CGM.getLangOpts().AppleKext) {
2740 return CGM.AddCXXDtorEntry(dtor, addr);
2748 assert(!VD->
isStaticLocal() &&
"static local VarDecls don't need wrappers!");
2758static llvm::GlobalValue::LinkageTypes
2760 llvm::GlobalValue::LinkageTypes VarLinkage =
2764 if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
2769 if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
2770 !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
2772 return llvm::GlobalValue::WeakODRLinkage;
2776ItaniumCXXABI::getOrCreateThreadLocalWrapper(
const VarDecl *VD,
2781 llvm::raw_svector_ostream Out(WrapperName);
2782 getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);
2787 if (llvm::Value *
V = CGM.getModule().getNamedValue(WrapperName))
2788 return cast<llvm::Function>(
V);
2794 const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
2797 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI);
2798 llvm::Function *Wrapper =
2800 WrapperName.str(), &CGM.getModule());
2802 if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())
2803 Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));
2805 CGM.SetLLVMFunctionAttributes(
GlobalDecl(), FI, Wrapper,
false);
2808 if (!Wrapper->hasLocalLinkage())
2810 llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
2811 llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
2813 Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
2816 Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2817 Wrapper->addFnAttr(llvm::Attribute::NoUnwind);
2820 ThreadWrappers.push_back({VD, Wrapper});
2824void ItaniumCXXABI::EmitThreadLocalInitFuncs(
2828 llvm::Function *InitFunc =
nullptr;
2833 llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;
2834 for (
unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {
2837 UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =
2838 CXXThreadLocalInits[I];
2840 OrderedInits.push_back(CXXThreadLocalInits[I]);
2843 if (!OrderedInits.empty()) {
2845 llvm::FunctionType *FTy =
2846 llvm::FunctionType::get(CGM.
VoidTy,
false);
2851 llvm::GlobalVariable *Guard =
new llvm::GlobalVariable(
2853 llvm::GlobalVariable::InternalLinkage,
2854 llvm::ConstantInt::get(CGM.
Int8Ty, 0),
"__tls_guard");
2855 Guard->setThreadLocal(
true);
2859 Guard->setAlignment(GuardAlign.
getAsAlign());
2865 InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2866 InitFunc->addFnAttr(llvm::Attribute::NoUnwind);
2872 for (
const VarDecl *VD : CXXThreadLocals) {
2876 getOrCreateThreadLocalWrapper(VD, GV);
2881 for (
auto VDAndWrapper : ThreadWrappers) {
2882 const VarDecl *VD = VDAndWrapper.first;
2883 llvm::GlobalVariable *Var =
2885 llvm::Function *Wrapper = VDAndWrapper.second;
2892 Wrapper->setLinkage(llvm::Function::ExternalLinkage);
2898 if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)
2899 Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);
2907 llvm::raw_svector_ostream Out(InitFnName);
2908 getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
2911 llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
2916 llvm::GlobalValue *Init =
nullptr;
2917 bool InitIsInitFunc =
false;
2918 bool HasConstantInitialization =
false;
2919 if (!usesThreadWrapperFunction(VD)) {
2920 HasConstantInitialization =
true;
2922 InitIsInitFunc =
true;
2923 llvm::Function *InitFuncToUse = InitFunc;
2927 Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),
2934 Init = llvm::Function::Create(InitFnTy,
2935 llvm::GlobalVariable::ExternalWeakLinkage,
2939 GlobalDecl(), FI, cast<llvm::Function>(Init),
false);
2943 Init->setVisibility(Var->getVisibility());
2945 if (!CGM.
getTriple().isOSWindows() || !Init->hasExternalWeakLinkage())
2946 Init->setDSOLocal(Var->isDSOLocal());
2949 llvm::LLVMContext &Context = CGM.
getModule().getContext();
2957 isEmittedWithConstantInitializer(VD,
true) &&
2958 !mayNeedDestruction(VD)) {
2963 assert(Init ==
nullptr &&
"Expected Init to be null.");
2965 llvm::Function *Func = llvm::Function::Create(
2966 InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.
getModule());
2969 cast<llvm::Function>(Func),
2972 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context,
"", Func);
2974 Builder.CreateRetVoid();
2977 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context,
"", Wrapper);
2979 if (HasConstantInitialization) {
2981 }
else if (InitIsInitFunc) {
2983 llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init);
2985 CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2986 llvm::Function *Fn =
2987 cast<llvm::Function>(cast<llvm::GlobalAlias>(Init)->getAliasee());
2988 Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2999 Builder.CreateCall(InitFnTy, Init);
3002 llvm::Value *Have = Builder.CreateIsNotNull(Init);
3003 llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context,
"", Wrapper);
3004 llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context,
"", Wrapper);
3005 Builder.CreateCondBr(Have, InitBB, ExitBB);
3007 Builder.SetInsertPoint(InitBB);
3008 Builder.CreateCall(InitFnTy, Init);
3009 Builder.CreateBr(ExitBB);
3011 Builder.SetInsertPoint(ExitBB);
3016 llvm::Value *Val = Builder.CreateThreadLocalAddress(Var);
3020 Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align);
3022 if (Val->getType() != Wrapper->getReturnType())
3023 Val = Builder.CreatePointerBitCastOrAddrSpaceCast(
3024 Val, Wrapper->getReturnType(),
"");
3026 Builder.CreateRet(Val);
3034 llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
3036 llvm::CallInst *CallVal = CGF.
Builder.CreateCall(Wrapper);
3037 CallVal->setCallingConv(Wrapper->getCallingConv());
3051bool ItaniumCXXABI::NeedsVTTParameter(
GlobalDecl GD) {
3070class ItaniumRTTIBuilder {
3072 llvm::LLVMContext &VMContext;
3073 const ItaniumCXXABI &
CXXABI;
3079 llvm::GlobalVariable *
3080 GetAddrOfTypeName(
QualType Ty, llvm::GlobalVariable::LinkageTypes
Linkage);
3084 llvm::Constant *GetAddrOfExternalRTTIDescriptor(
QualType Ty);
3087 void BuildVTablePointer(
const Type *Ty);
3100 void BuildPointerTypeInfo(
QualType PointeeTy);
3111 ItaniumRTTIBuilder(
const ItaniumCXXABI &ABI)
3112 : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()),
CXXABI(ABI) {}
3126 PTI_Incomplete = 0x8,
3130 PTI_ContainingClassIncomplete = 0x10,
3136 PTI_Noexcept = 0x40,
3142 VMI_NonDiamondRepeat = 0x1,
3145 VMI_DiamondShaped = 0x2
3159 llvm::Constant *BuildTypeInfo(
QualType Ty);
3162 llvm::Constant *BuildTypeInfo(
3164 llvm::GlobalVariable::LinkageTypes
Linkage,
3165 llvm::GlobalValue::VisibilityTypes
Visibility,
3166 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
3170llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
3173 llvm::raw_svector_ostream Out(Name);
3179 llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
3186 GV->setInitializer(Init);
3192ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(
QualType Ty) {
3195 llvm::raw_svector_ostream Out(Name);
3199 llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(Name);
3208 llvm::GlobalValue::ExternalLinkage,
nullptr,
3215 if (RD && CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD)) {
3216 GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
3222 return llvm::ConstantExpr::getBitCast(GV, CGM.
Int8PtrTy);
3243 case BuiltinType::Void:
3244 case BuiltinType::NullPtr:
3245 case BuiltinType::Bool:
3246 case BuiltinType::WChar_S:
3247 case BuiltinType::WChar_U:
3248 case BuiltinType::Char_U:
3249 case BuiltinType::Char_S:
3250 case BuiltinType::UChar:
3251 case BuiltinType::SChar:
3252 case BuiltinType::Short:
3253 case BuiltinType::UShort:
3254 case BuiltinType::Int:
3255 case BuiltinType::UInt:
3256 case BuiltinType::Long:
3257 case BuiltinType::ULong:
3258 case BuiltinType::LongLong:
3259 case BuiltinType::ULongLong:
3260 case BuiltinType::Half:
3261 case BuiltinType::Float:
3262 case BuiltinType::Double:
3263 case BuiltinType::LongDouble:
3264 case BuiltinType::Float16:
3265 case BuiltinType::Float128:
3266 case BuiltinType::Ibm128:
3267 case BuiltinType::Char8:
3268 case BuiltinType::Char16:
3269 case BuiltinType::Char32:
3270 case BuiltinType::Int128:
3271 case BuiltinType::UInt128:
3274#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
3275 case BuiltinType::Id:
3276#include "clang/Basic/OpenCLImageTypes.def"
3277#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
3278 case BuiltinType::Id:
3279#include "clang/Basic/OpenCLExtensionTypes.def"
3280 case BuiltinType::OCLSampler:
3281 case BuiltinType::OCLEvent:
3282 case BuiltinType::OCLClkEvent:
3283 case BuiltinType::OCLQueue:
3284 case BuiltinType::OCLReserveID:
3285#define SVE_TYPE(Name, Id, SingletonId) \
3286 case BuiltinType::Id:
3287#include "clang/Basic/AArch64SVEACLETypes.def"
3288#define PPC_VECTOR_TYPE(Name, Id, Size) \
3289 case BuiltinType::Id:
3290#include "clang/Basic/PPCTypes.def"
3291#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3292#include "clang/Basic/RISCVVTypes.def"
3293#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3294#include "clang/Basic/WebAssemblyReferenceTypes.def"
3295 case BuiltinType::ShortAccum:
3296 case BuiltinType::Accum:
3297 case BuiltinType::LongAccum:
3298 case BuiltinType::UShortAccum:
3299 case BuiltinType::UAccum:
3300 case BuiltinType::ULongAccum:
3301 case BuiltinType::ShortFract:
3302 case BuiltinType::Fract:
3303 case BuiltinType::LongFract:
3304 case BuiltinType::UShortFract:
3305 case BuiltinType::UFract:
3306 case BuiltinType::ULongFract:
3307 case BuiltinType::SatShortAccum:
3308 case BuiltinType::SatAccum:
3309 case BuiltinType::SatLongAccum:
3310 case BuiltinType::SatUShortAccum:
3311 case BuiltinType::SatUAccum:
3312 case BuiltinType::SatULongAccum:
3313 case BuiltinType::SatShortFract:
3314 case BuiltinType::SatFract:
3315 case BuiltinType::SatLongFract:
3316 case BuiltinType::SatUShortFract:
3317 case BuiltinType::SatUFract:
3318 case BuiltinType::SatULongFract:
3319 case BuiltinType::BFloat16:
3322 case BuiltinType::Dependent:
3323#define BUILTIN_TYPE(Id, SingletonId)
3324#define PLACEHOLDER_TYPE(Id, SingletonId) \
3325 case BuiltinType::Id:
3326#include "clang/AST/BuiltinTypes.def"
3327 llvm_unreachable(
"asking for RRTI for a placeholder type!");
3329 case BuiltinType::ObjCId:
3330 case BuiltinType::ObjCClass:
3331 case BuiltinType::ObjCSel:
3332 llvm_unreachable(
"FIXME: Objective-C types are unsupported!");
3335 llvm_unreachable(
"Invalid BuiltinType Kind!");
3340 const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
3358 if (
const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
3363 if (
const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3381 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3382 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
3393 bool IsDLLImport = RD->
hasAttr<DLLImportAttr>();
3396 if (CGM.
getTriple().isWindowsGNUEnvironment())
3403 return IsDLLImport && !CGM.
getTriple().isWindowsItaniumEnvironment()
3431 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3436 if (
const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3440 dyn_cast<MemberPointerType>(Ty)) {
3442 const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
3464 if (
Base->isVirtual())
3474 if (!BaseDecl->isEmpty() &&
3481void ItaniumRTTIBuilder::BuildVTablePointer(
const Type *Ty) {
3483 static const char *
const ClassTypeInfo =
3484 "_ZTVN10__cxxabiv117__class_type_infoE";
3486 static const char *
const SIClassTypeInfo =
3487 "_ZTVN10__cxxabiv120__si_class_type_infoE";
3489 static const char *
const VMIClassTypeInfo =
3490 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
3492 const char *VTableName =
nullptr;
3495#define TYPE(Class, Base)
3496#define ABSTRACT_TYPE(Class, Base)
3497#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3498#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3499#define DEPENDENT_TYPE(Class, Base) case Type::Class:
3500#include "clang/AST/TypeNodes.inc"
3501 llvm_unreachable(
"Non-canonical and dependent types shouldn't get here");
3503 case Type::LValueReference:
3504 case Type::RValueReference:
3505 llvm_unreachable(
"References shouldn't get here");
3508 case Type::DeducedTemplateSpecialization:
3509 llvm_unreachable(
"Undeduced type shouldn't get here");
3512 llvm_unreachable(
"Pipe types shouldn't get here");
3518 case Type::ExtVector:
3519 case Type::ConstantMatrix:
3523 case Type::BlockPointer:
3525 VTableName =
"_ZTVN10__cxxabiv123__fundamental_type_infoE";
3528 case Type::ConstantArray:
3529 case Type::IncompleteArray:
3530 case Type::VariableArray:
3532 VTableName =
"_ZTVN10__cxxabiv117__array_type_infoE";
3535 case Type::FunctionNoProto:
3536 case Type::FunctionProto:
3538 VTableName =
"_ZTVN10__cxxabiv120__function_type_infoE";
3543 VTableName =
"_ZTVN10__cxxabiv116__enum_type_infoE";
3546 case Type::Record: {
3548 cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
3551 VTableName = ClassTypeInfo;
3553 VTableName = SIClassTypeInfo;
3555 VTableName = VMIClassTypeInfo;
3561 case Type::ObjCObject:
3563 Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
3566 if (isa<BuiltinType>(Ty)) {
3567 VTableName = ClassTypeInfo;
3571 assert(isa<ObjCInterfaceType>(Ty));
3574 case Type::ObjCInterface:
3575 if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
3576 VTableName = SIClassTypeInfo;
3578 VTableName = ClassTypeInfo;
3582 case Type::ObjCObjectPointer:
3585 VTableName =
"_ZTVN10__cxxabiv119__pointer_type_infoE";
3588 case Type::MemberPointer:
3590 VTableName =
"_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
3594 llvm::Constant *VTable =
nullptr;
3598 VTable = CGM.
getModule().getNamedAlias(VTableName);
3602 CGM.
setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
3604 llvm::Type *PtrDiffTy =
3611 llvm::Constant *Eight = llvm::ConstantInt::get(CGM.
Int32Ty, 8);
3612 VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.
Int8PtrTy);
3614 llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.
Int8Ty, VTable, Eight);
3616 llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
3617 VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.
Int8PtrTy, VTable,
3620 VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.
Int8PtrTy);
3622 Fields.push_back(VTable);
3639 return llvm::GlobalValue::InternalLinkage;
3645 return llvm::GlobalValue::InternalLinkage;
3653 return llvm::GlobalValue::LinkOnceODRLinkage;
3655 if (
const RecordType *Record = dyn_cast<RecordType>(Ty)) {
3656 const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
3658 return llvm::GlobalValue::WeakODRLinkage;
3659 if (CGM.
getTriple().isWindowsItaniumEnvironment())
3660 if (RD->
hasAttr<DLLImportAttr>() &&
3662 return llvm::GlobalValue::ExternalLinkage;
3668 .isWindowsGNUEnvironment())
3672 return llvm::GlobalValue::LinkOnceODRLinkage;
3675 llvm_unreachable(
"Invalid linkage!");
3678llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
QualType Ty) {
3684 llvm::raw_svector_ostream Out(Name);
3687 llvm::GlobalVariable *OldGV = CGM.
getModule().getNamedGlobal(Name);
3688 if (OldGV && !OldGV->isDeclaration()) {
3689 assert(!OldGV->hasAvailableExternallyLinkage() &&
3690 "available_externally typeinfos not yet implemented");
3692 return llvm::ConstantExpr::getBitCast(OldGV, CGM.
Int8PtrTy);
3698 return GetAddrOfExternalRTTIDescriptor(Ty);
3705 llvm::GlobalValue::VisibilityTypes llvmVisibility;
3706 if (llvm::GlobalValue::isLocalLinkage(
Linkage))
3708 llvmVisibility = llvm::GlobalValue::DefaultVisibility;
3710 ItaniumCXXABI::RUK_NonUniqueHidden)
3711 llvmVisibility = llvm::GlobalValue::HiddenVisibility;
3715 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
3716 llvm::GlobalValue::DefaultStorageClass;
3718 if ((CGM.
getTriple().isWindowsItaniumEnvironment() &&
3719 RD->
hasAttr<DLLExportAttr>()) ||
3721 !llvm::GlobalValue::isLocalLinkage(
Linkage) &&
3722 llvmVisibility == llvm::GlobalValue::DefaultVisibility))
3723 DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
3725 return BuildTypeInfo(Ty,
Linkage, llvmVisibility, DLLStorageClass);
3728llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
3730 llvm::GlobalVariable::LinkageTypes
Linkage,
3731 llvm::GlobalValue::VisibilityTypes
Visibility,
3732 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
3734 BuildVTablePointer(cast<Type>(Ty));
3738 llvm::Constant *TypeNameField;
3742 ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =
3744 if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {
3747 TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.
Int64Ty);
3748 llvm::Constant *flag =
3749 llvm::ConstantInt::get(CGM.
Int64Ty, ((uint64_t)1) << 63);
3750 TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
3752 llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.
Int8PtrTy);
3754 TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.
Int8PtrTy);
3756 Fields.push_back(TypeNameField);
3759#define TYPE(Class, Base)
3760#define ABSTRACT_TYPE(Class, Base)
3761#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3762#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3763#define DEPENDENT_TYPE(Class, Base) case Type::Class:
3764#include "clang/AST/TypeNodes.inc"
3765 llvm_unreachable(
"Non-canonical and dependent types shouldn't get here");
3770 case Type::ExtVector:
3771 case Type::ConstantMatrix:
3773 case Type::BlockPointer:
3778 case Type::LValueReference:
3779 case Type::RValueReference:
3780 llvm_unreachable(
"References shouldn't get here");
3783 case Type::DeducedTemplateSpecialization:
3784 llvm_unreachable(
"Undeduced type shouldn't get here");
3792 case Type::ConstantArray:
3793 case Type::IncompleteArray:
3794 case Type::VariableArray:
3799 case Type::FunctionNoProto:
3800 case Type::FunctionProto:
3810 case Type::Record: {
3812 cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
3819 BuildSIClassTypeInfo(RD);
3821 BuildVMIClassTypeInfo(RD);
3826 case Type::ObjCObject:
3827 case Type::ObjCInterface:
3828 BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
3831 case Type::ObjCObjectPointer:
3832 BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
3836 BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
3839 case Type::MemberPointer:
3840 BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
3848 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
3851 llvm::raw_svector_ostream Out(Name);
3854 llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
3855 llvm::GlobalVariable *GV =
3856 new llvm::GlobalVariable(M, Init->getType(),
3860 auto GVDLLStorageClass = DLLStorageClass;
3862 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3863 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
3864 if (RD->
hasAttr<DLLExportAttr>() ||
3865 CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD)) {
3866 GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
3873 GV->takeName(OldGV);
3874 llvm::Constant *NewPtr =
3875 llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
3876 OldGV->replaceAllUsesWith(NewPtr);
3877 OldGV->eraseFromParent();
3881 GV->setComdat(M.getOrInsertComdat(GV->getName()));
3908 TypeName->setDLLStorageClass(DLLStorageClass);
3916 return llvm::ConstantExpr::getBitCast(GV, CGM.
Int8PtrTy);
3921void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(
const ObjCObjectType *OT) {
3924 assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
3928 if (isa<BuiltinType>(T))
return;
3939 llvm::Constant *BaseTypeInfo =
3940 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(SuperTy);
3941 Fields.push_back(BaseTypeInfo);
3946void ItaniumRTTIBuilder::BuildSIClassTypeInfo(
const CXXRecordDecl *RD) {
3950 llvm::Constant *BaseTypeInfo =
3952 Fields.push_back(BaseTypeInfo);
3975 if (
Base->isVirtual()) {
3977 if (!Bases.VirtualBases.insert(BaseDecl).second) {
3980 Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
3982 if (Bases.NonVirtualBases.count(BaseDecl))
3983 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
3987 if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
3990 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
3992 if (Bases.VirtualBases.count(BaseDecl))
3993 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
3998 for (
const auto &I : BaseDecl->bases())
4009 for (
const auto &I : RD->
bases())
4018void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(
const CXXRecordDecl *RD) {
4019 llvm::Type *UnsignedIntLTy =
4027 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4032 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->
getNumBases()));
4065 llvm::Type *OffsetFlagsLTy =
4070 Fields.push_back(ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(
Base.getType()));
4082 if (
Base.isVirtual())
4094 if (
Base.isVirtual())
4095 OffsetFlags |= BCTI_Virtual;
4097 OffsetFlags |= BCTI_Public;
4099 Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags));
4108 if (
Type.isConstQualified())
4109 Flags |= ItaniumRTTIBuilder::PTI_Const;
4110 if (
Type.isVolatileQualified())
4111 Flags |= ItaniumRTTIBuilder::PTI_Volatile;
4112 if (
Type.isRestrictQualified())
4113 Flags |= ItaniumRTTIBuilder::PTI_Restrict;
4120 Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
4123 if (Proto->isNothrow()) {
4124 Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
4134void ItaniumRTTIBuilder::BuildPointerTypeInfo(
QualType PointeeTy) {
4140 llvm::Type *UnsignedIntLTy =
4142 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4147 llvm::Constant *PointeeTypeInfo =
4148 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(PointeeTy);
4149 Fields.push_back(PointeeTypeInfo);
4165 Flags |= PTI_ContainingClassIncomplete;
4167 llvm::Type *UnsignedIntLTy =
4169 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4174 llvm::Constant *PointeeTypeInfo =
4175 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(PointeeTy);
4176 Fields.push_back(PointeeTypeInfo);
4183 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(
QualType(ClassType, 0)));
4186llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(
QualType Ty) {
4187 return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
4190void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(
const CXXRecordDecl *RD) {
4193 getContext().VoidTy, getContext().NullPtrTy,
4194 getContext().BoolTy, getContext().WCharTy,
4195 getContext().CharTy, getContext().UnsignedCharTy,
4196 getContext().SignedCharTy, getContext().ShortTy,
4197 getContext().UnsignedShortTy, getContext().IntTy,
4198 getContext().UnsignedIntTy, getContext().LongTy,
4199 getContext().UnsignedLongTy, getContext().LongLongTy,
4200 getContext().UnsignedLongLongTy, getContext().Int128Ty,
4201 getContext().UnsignedInt128Ty, getContext().HalfTy,
4202 getContext().FloatTy, getContext().DoubleTy,
4203 getContext().LongDoubleTy, getContext().Float128Ty,
4204 getContext().Char8Ty, getContext().Char16Ty,
4205 getContext().Char32Ty
4207 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4209 ? llvm::GlobalValue::DLLExportStorageClass
4210 : llvm::GlobalValue::DefaultStorageClass;
4211 llvm::GlobalValue::VisibilityTypes
Visibility =
4213 for (
const QualType &FundamentalType : FundamentalTypes) {
4215 QualType PointerTypeConst = getContext().getPointerType(
4216 FundamentalType.withConst());
4218 ItaniumRTTIBuilder(*this).BuildTypeInfo(
4219 Type, llvm::GlobalValue::ExternalLinkage,
4226ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
4228 if (shouldRTTIBeUnique())
4232 if (
Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
4233 Linkage != llvm::GlobalValue::WeakODRLinkage)
4241 if (
Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
4242 return RUK_NonUniqueHidden;
4247 assert(
Linkage == llvm::GlobalValue::WeakODRLinkage);
4248 return RUK_NonUniqueVisible;
4253enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
4258 return StructorCodegen::Emit;
4263 return StructorCodegen::Emit;
4266 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
4269 const auto *CD = cast<CXXConstructorDecl>(MD);
4274 if (llvm::GlobalValue::isDiscardableIfUnused(
Linkage))
4275 return StructorCodegen::RAUW;
4278 if (!llvm::GlobalAlias::isValidLinkage(
Linkage))
4279 return StructorCodegen::RAUW;
4281 if (llvm::GlobalValue::isWeakForLinker(
Linkage)) {
4285 return StructorCodegen::COMDAT;
4286 return StructorCodegen::Emit;
4289 return StructorCodegen::Alias;
4299 if (Entry && !Entry->isDeclaration())
4302 auto *Aliasee = cast<llvm::GlobalValue>(CGM.
GetAddrOfGlobal(TargetDecl));
4305 auto *Alias = llvm::GlobalAlias::create(
Linkage,
"", Aliasee);
4308 Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4312 assert(Entry->getType() == Aliasee->getType() &&
4313 "declaration exists with different type");
4314 Alias->takeName(Entry);
4315 Entry->replaceAllUsesWith(Alias);
4316 Entry->eraseFromParent();
4318 Alias->setName(MangledName);
4325void ItaniumCXXABI::emitCXXStructor(
GlobalDecl GD) {
4326 auto *MD = cast<CXXMethodDecl>(GD.
getDecl());
4327 auto *CD = dyn_cast<CXXConstructorDecl>(MD);
4340 if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {
4345 if (CGType == StructorCodegen::RAUW) {
4358 CGType != StructorCodegen::COMDAT &&
4376 if (CGType == StructorCodegen::COMDAT) {
4378 llvm::raw_svector_ostream Out(Buffer);
4380 getMangleContext().mangleCXXDtorComdat(DD, Out);
4382 getMangleContext().mangleCXXCtorComdat(CD, Out);
4383 llvm::Comdat *
C = CGM.
getModule().getOrInsertComdat(Out.str());
4392 llvm::FunctionType *FTy = llvm::FunctionType::get(
4400 llvm::FunctionType *FTy =
4401 llvm::FunctionType::get(CGM.
VoidTy,
false);
4408 llvm::FunctionType *FTy = llvm::FunctionType::get(
4428 CallEndCatch(
bool MightThrow) : MightThrow(MightThrow) {}
4448 bool EndMightThrow) {
4449 llvm::CallInst *call =
4472 if (isa<ReferenceType>(CatchType)) {
4477 llvm::Value *AdjustedExn =
CallBeginCatch(CGF, Exn, EndCatchMightThrow);
4482 if (
const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
4491 unsigned HeaderSize =
4494 CGF.
Builder.CreateConstGEP1_32(CGF.
Int8Ty, Exn, HeaderSize);
4517 llvm::Value *Casted = CGF.
Builder.CreateBitCast(AdjustedExn, PtrTy);
4525 llvm::Value *ExnCast =
4526 CGF.
Builder.CreateBitCast(AdjustedExn, LLVMCatchTy,
"exn.byref");
4538 if (CatchType->hasPointerRepresentation()) {
4539 llvm::Value *CastExn =
4540 CGF.
Builder.CreateBitCast(AdjustedExn, LLVMCatchTy,
"exn.casted");
4557 llvm_unreachable(
"bad ownership qualifier!");
4562 llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0);
4563 llvm::Value *Cast = CGF.
Builder.CreateBitCast(AdjustedExn, PtrTy);
4578 llvm_unreachable(
"evaluation kind filtered out!");
4580 llvm_unreachable(
"bad evaluation kind");
4583 assert(isa<RecordType>(CatchType) &&
"unexpected catch type!");
4584 auto catchRD = CatchType->getAsCXXRecordDecl();
4587 llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0);
4594 Address adjustedExn(CGF.
Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4595 LLVMCatchTy, caughtExnAlignment);
4604 llvm::CallInst *rawAdjustedExn =
4608 Address adjustedExn(CGF.
Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4609 LLVMCatchTy, caughtExnAlignment);
4613 CodeGenFunction::OpaqueValueMapping
4665 VarDecl *CatchParam = S->getExceptionDecl();
4674 InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc());
4684 C.VoidTy, {C.getPointerType(C.CharTy)});
4687 fnTy,
"__clang_call_terminate", llvm::AttributeList(),
true);
4688 llvm::Function *fn =
4689 cast<llvm::Function>(fnRef.getCallee()->stripPointerCasts());
4692 fn->setDoesNotThrow();
4693 fn->setDoesNotReturn();
4698 fn->addFnAttr(llvm::Attribute::NoInline);
4702 fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
4703 fn->setVisibility(llvm::Function::HiddenVisibility);
4705 fn->setComdat(CGM.
getModule().getOrInsertComdat(fn->getName()));
4708 llvm::BasicBlock *entry =
4713 llvm::Value *exn = &*fn->arg_begin();
4716 llvm::CallInst *catchCall = builder.CreateCall(
getBeginCatchFn(CGM), exn);
4717 catchCall->setDoesNotThrow();
4721 llvm::CallInst *termCall = builder.CreateCall(CGM.
getTerminateFn());
4722 termCall->setDoesNotThrow();
4723 termCall->setDoesNotReturn();
4727 builder.CreateUnreachable();
4733ItaniumCXXABI::emitTerminateForUnexpectedException(
CodeGenFunction &CGF,
4743std::pair<llvm::Value *, const CXXRecordDecl *>
4754 ItaniumCXXABI::emitBeginCatch(CGF,
C);
4758WebAssemblyCXXABI::emitTerminateForUnexpectedException(
CodeGenFunction &CGF,
4771 llvm::FunctionCallee Dtor,
4772 llvm::Constant *Addr) {
4775 llvm::FunctionType *FTy =
4776 llvm::FunctionType::get(CGM.
IntTy, CGM.
IntTy,
true);
4777 llvm::PointerType *FpTy = FTy->getPointerTo();
4780 llvm::FunctionType *AtExitTy =
4781 llvm::FunctionType::get(CGM.
IntTy, {CGM.IntTy, FpTy},
true);
4784 llvm::FunctionCallee
AtExit =
4792 llvm::Value *NV = llvm::Constant::getNullValue(CGM.
IntTy);
4807 emitCXXStermFinalizer(D, DtorStub, Addr);
4810void XLCXXABI::emitCXXStermFinalizer(
const VarDecl &D, llvm::Function *dtorStub,
4811 llvm::Constant *addr) {
4812 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
4815 llvm::raw_svector_ostream Out(FnName);
4816 getMangleContext().mangleDynamicStermFinalizer(&D, Out);
4836 llvm::Value *NeedsDestruct = CGF.
Builder.CreateIsNull(
V,
"needs_destruct");
4838 llvm::BasicBlock *DestructCallBlock = CGF.
createBasicBlock(
"destruct.call");
4843 CGF.
Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
4848 llvm::CallInst *CI = CGF.
Builder.CreateCall(dtorStub);
4851 CI->setCallingConv(dtorStub->getCallingConv());
4857 if (
auto *IPA = D.
getAttr<InitPriorityAttr>()) {
4859 IPA->getPriority());
static StructorCodegen getCodegenToUse(CodeGenModule &CGM, const CXXMethodDecl *MD)
static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF)
static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM)
Get or define the following function: void @__clang_call_terminate(i8* exn) nounwind noreturn This co...
static llvm::Value * performTypeAdjustment(CodeGenFunction &CGF, Address InitialPtr, int64_t NonVirtualAdjustment, int64_t VirtualAdjustment, bool IsReturnAdjustment)
static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type)
Compute the flags for a __pbase_type_info, and remove the corresponding pieces from Type.
static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty)
ShouldUseExternalRTTIDescriptor - Returns whether the type information for the given type exists some...
static bool IsIncompleteClassType(const RecordType *RecordTy)
IsIncompleteClassType - Returns whether the given record type is incomplete.
static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, SeenBases &Bases)
ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in abi::__vmi_class_type_info.
static llvm::FunctionCallee getBadTypeidFn(CodeGenFunction &CGF)
static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, llvm::FunctionCallee dtor, llvm::Constant *addr, bool TLS)
Register a global destructor using __cxa_atexit.
static llvm::FunctionCallee getBadCastFn(CodeGenFunction &CGF)
static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM)
static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty)
Return the linkage that the type info and type info name constants should have for the given type.
static llvm::FunctionCallee getGuardReleaseFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
static llvm::Function * createGlobalInitOrCleanupFn(CodeGen::CodeGenModule &CGM, StringRef FnName)
static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM)
static bool IsStandardLibraryRTTIDescriptor(QualType Ty)
IsStandardLibraryRTTIDescriptor - Returns whether the type information for the given type exists in t...
static llvm::Value * CallBeginCatch(CodeGenFunction &CGF, llvm::Value *Exn, bool EndMightThrow)
Emits a call to __cxa_begin_catch and enters a cleanup to call __cxa_end_catch.
static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
static CharUnits computeOffsetHint(ASTContext &Context, const CXXRecordDecl *Src, const CXXRecordDecl *Dst)
Compute the src2dst_offset hint as described in the Itanium C++ ABI [2.9.7].
static bool isThreadWrapperReplaceable(const VarDecl *VD, CodeGen::CodeGenModule &CGM)
static bool CXXRecordAllNonInlineVirtualsHaveAttr(const CXXRecordDecl *RD)
static void InitCatchParam(CodeGenFunction &CGF, const VarDecl &CatchParam, Address ParamAddr, SourceLocation Loc)
A "special initializer" callback for initializing a catch parameter during catch initialization.
static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty)
TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type info for that type is de...
static bool CanUseSingleInheritance(const CXXRecordDecl *RD)
static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM)
static llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM)
Get the appropriate linkage for the wrapper function.
static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM)
static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM, llvm::PointerType *GuardPtrTy)
static bool ContainsIncompleteClassType(QualType Ty)
ContainsIncompleteClassType - Returns whether the given type contains an incomplete class type.
static void emitConstructorDestructorAlias(CodeGenModule &CGM, GlobalDecl AliasDecl, GlobalDecl TargetDecl)
static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM)
static void dtorTy(Block *, char *Ptr, const Descriptor *)
static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD)
static const RecordType * getRecordType(QualType QT)
Checks that the passed in QualType either is of RecordType or points to RecordType.
static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D)
Determine what kind of template specialization the given declaration is.
#define CXXABI(Name, Str)
C Language Family Type Representation.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
const ValueDecl * getMemberPointerDecl() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const LangOptions & getLangOpts() const
QualType getFunctionTypeWithExceptionSpec(QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) const
Get a function type and produce the equivalent function type with the specified exception specificati...
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
CharUnits getExnObjectAlignment() const
Return the alignment (in bytes) of the thrown exception object.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
CharUnits getPreferredTypeAlignInChars(QualType T) const
Return the PreferredAlignment of a (complete) type T, in characters.
CanQualType UnsignedIntTy
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
TargetCXXABI::Kind getCXXABIKind() const
Return the C++ ABI kind that should be used.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
This class is used for builtin types like 'int'.
Implements C++ ABI-specific semantic analysis functions.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a base class of a C++ class.
QualType getType() const
Retrieves the type of the base class.
CXXCatchStmt - This represents a C++ catch block.
Represents a C++ constructor within a class.
Represents a delete expression for memory deallocation and destructor calls, e.g.
FunctionDecl * getOperatorDelete() const
bool isGlobalDelete() const
Represents a C++ destructor within a class.
Represents a call to a member function that may be written either with member call syntax (e....
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Represents a C++ struct/union/class.
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
base_class_range vbases()
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool isDynamicClass() const
bool hasDefinition() const
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
A C++ throw-expression (C++ [except.throw]).
const Expr * getSubExpr() const
Qualifiers getQualifiers() const
Retrieve all qualifiers.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
std::string SymbolPartition
The name of the partition that symbols are assigned to, specified with -fsymbol-partition (see https:...
static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
CharUnits getAlignment() const
Return the alignment of this pointer.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
unsigned getAddressSpace() const
Return the address space that this address resides in.
llvm::Value * getPointer() const
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")
Given a pointer to i8, adjust it by a given constant offset.
Address CreateElementBitCast(Address Addr, llvm::Type *Ty, const llvm::Twine &Name="")
Cast the element type of the given address to a different type, preserving information like the align...
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateGEP(Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Implements C++ ABI-specific code generation functions.
virtual llvm::Value * EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy)=0
virtual void EmitCXXConstructors(const CXXConstructorDecl *D)=0
Emit constructor variants required by this ABI.
virtual llvm::Constant * getAddrOfRTTIDescriptor(QualType Ty)=0
virtual llvm::Value * performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const ReturnAdjustment &RA)=0
virtual llvm::Value * getVTableAddressPointInStructor(CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base, const CXXRecordDecl *NearestVBase)=0
Get the address point of the vtable for the given base subobject while building a constructor or a de...
virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C)=0
virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn)=0
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &Args) const =0
virtual bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr)=0
Checks if ABI requires extra virtual offset for vtable field.
virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, llvm::GlobalVariable *DeclPtr, bool PerformInit)=0
Emits the guarded initializer and destructor setup for the given variable, given that it couldn't be ...
virtual void EmitCXXDestructors(const CXXDestructorDecl *D)=0
Emit destructor variants required by this ABI.
virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF)=0
Emit the ABI-specific prolog for the function.
virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, CXXDtorType DT) const =0
Returns true if the given destructor type should be emitted as a linkonce delegating thunk,...
virtual bool NeedsVTTParameter(GlobalDecl GD)
Return whether the given global decl needs a VTT parameter.
virtual llvm::CallInst * emitTerminateForUnexpectedException(CodeGenFunction &CGF, llvm::Value *Exn)
@ RAA_Default
Pass it using the normal C aggregate rules for the ABI, potentially introducing extra copies and pass...
@ RAA_Indirect
Pass it as a pointer to temporary memory.
virtual llvm::Type * ConvertMemberPointerType(const MemberPointerType *MPT)
Find the LLVM type used to represent the given member pointer type.
virtual llvm::Constant * EmitNullMemberPointer(const MemberPointerType *MPT)
Create a null member pointer of the given type.
virtual StringRef GetPureVirtualCallName()=0
Gets the pure virtual member call function.
virtual CharUnits getArrayCookieSizeImpl(QualType elementType)
Returns the extra size required in order to store the array cookie for the given type.
virtual void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr)=0
Emit code to force the execution of a destructor during global teardown.
virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const =0
Determine whether it's possible to emit a vtable for RD, even though we do not know that the vtable h...
virtual StringRef GetDeletedVirtualCallName()=0
Gets the deleted virtual member call name.
virtual llvm::Value * EmitMemberPointerIsNotNull(CodeGenFunction &CGF, llvm::Value *MemPtr, const MemberPointerType *MPT)
Determine if a member pointer is non-null. Returns an i1.
virtual LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, QualType LValType)=0
Emit a reference to a non-local thread_local variable (including triggering the initialization of all...
bool isEmittedWithConstantInitializer(const VarDecl *VD, bool InspectInitForWeakDef=false) const
Determine whether we will definitely emit this variable with a constant initializer,...
virtual llvm::Value * EmitMemberPointerComparison(CodeGenFunction &CGF, llvm::Value *L, llvm::Value *R, const MemberPointerType *MPT, bool Inequality)
Emit a comparison between two member pointers. Returns an i1.
virtual llvm::Constant * EmitMemberPointer(const APValue &MP, QualType MPT)
Create a member pointer for the given member pointer constant.
virtual llvm::Constant * getVTableAddressPoint(BaseSubobject Base, const CXXRecordDecl *VTableClass)=0
Get the address point of the vtable for the given base subobject.
virtual void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params)=0
Insert any ABI-specific implicit parameters into the parameter list for a function.
virtual llvm::Value * readArrayCookieImpl(CodeGenFunction &IGF, Address ptr, CharUnits cookieSize)
Reads the array cookie for an allocation which is known to have one.
virtual llvm::Value * EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, const MemberPointerType *MPT)
Calculate an l-value from an object and a data member pointer.
virtual llvm::Value * getCXXDestructorImplicitParam(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating)=0
Get the implicit (second) parameter that comes after the "this" pointer, or nullptr if there is isn't...
virtual std::pair< llvm::Value *, const CXXRecordDecl * > LoadVTablePtr(CodeGenFunction &CGF, Address This, const CXXRecordDecl *RD)=0
Load a vtable from This, an object of polymorphic type RD, or from one of its virtual bases if it doe...
virtual llvm::Constant * getVTableAddressPointForConstExpr(BaseSubobject Base, const CXXRecordDecl *VTableClass)=0
Get the address point of the vtable for the given base subobject while building a constexpr.
virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, bool ReturnAdjustment)=0
virtual llvm::Value * EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, Address This, DeleteOrMemberCallExpr E)=0
Emit the ABI-specific virtual destructor call.
bool mayNeedDestruction(const VarDecl *VD) const
virtual bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass)=0
Checks if ABI requires to initialize vptrs for given dynamic class.
virtual llvm::Value * EmitDynamicCastCall(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd)=0
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E)=0
virtual llvm::Value * GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl)=0
virtual bool isThisCompleteObject(GlobalDecl GD) const =0
Determine whether there's something special about the rules of the ABI tell us that 'this' is a compl...
virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, Address This, llvm::Type *Ty, SourceLocation Loc)=0
Build a virtual function pointer in the ABI-specific way.
virtual bool classifyReturnType(CGFunctionInfo &FI) const =0
If the C++ ABI requires the given type be returned in a particular way, this method sets RetAI and re...
virtual void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType, const CXXDestructorDecl *Dtor)=0
virtual CatchTypeInfo getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType)=0
virtual void EmitThreadLocalInitFuncs(CodeGenModule &CGM, ArrayRef< const VarDecl * > CXXThreadLocals, ArrayRef< llvm::Function * > CXXThreadLocalInits, ArrayRef< const VarDecl * > CXXThreadLocalInitVars)=0
Emits ABI-required functions necessary to initialize thread_local variables in this translation unit.
virtual bool usesThreadWrapperFunction(const VarDecl *VD) const =0
virtual RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const =0
Returns how an argument of the given record type should be passed.
virtual void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)=0
Emit the destructor call.
virtual llvm::GlobalVariable * getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset)=0
Get the address of the vtable for the given record decl which should be used for the vptr at the give...
virtual bool EmitBadCastCall(CodeGenFunction &CGF)=0
virtual llvm::Constant * EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset)
Create a member pointer for the given field.
virtual llvm::Value * EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, Address ThisPtr, llvm::Type *StdTypeInfoPtrTy)=0
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD)=0
Emit any tables needed to implement virtual inheritance.
virtual void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD)=0
Emits the VTable definitions required for the given record type.
virtual CGCallee EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, Address This, llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, const MemberPointerType *MPT)
Load a member function from an object and a member function pointer.
virtual void emitCXXStructor(GlobalDecl GD)=0
Emit a single constructor/destructor with the given type from a C++ constructor Decl.
virtual bool exportThunk()=0
virtual void EmitBadTypeidCall(CodeGenFunction &CGF)=0
virtual bool isZeroInitializable(const MemberPointerType *MPT)
Return true if the given member pointer can be zero-initialized (in the C++ sense) with an LLVM zeroi...
virtual bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy)=0
virtual llvm::Value * EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, llvm::Value *Src)
Perform a derived-to-base, base-to-derived, or bitcast member pointer conversion.
virtual llvm::Constant * EmitMemberFunctionPointer(const CXXMethodDecl *MD)
Create a member pointer for the given method.
virtual Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr, llvm::Value *NumElements, const CXXNewExpr *expr, QualType ElementType)
Initialize the array cookie for the given allocation.
virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, QualType SrcRecordTy)=0
virtual AddedStructorArgCounts buildStructorSignature(GlobalDecl GD, SmallVectorImpl< CanQualType > &ArgTys)=0
Build the signature of the given constructor or destructor variant by adding any required parameters.
virtual llvm::Value * performThisAdjustment(CodeGenFunction &CGF, Address This, const ThisAdjustment &TA)=0
MangleContext & getMangleContext()
Gets the mangle context.
virtual AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating)=0
All available information about a concrete callee.
static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, llvm::FunctionType *FTy)
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
CGFunctionInfo - Class to encapsulate the information about a function definition.
ABIArgInfo & getReturnInfo()
CanQualType getReturnType() const
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void GenerateCXXGlobalInitFunc(llvm::Function *Fn, ArrayRef< llvm::Function * > CXXThreadLocals, ConstantAddress Guard=ConstantAddress::invalid())
GenerateCXXGlobalInitFunc - Generates code for initializing global variables.
void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, llvm::Value *CompletePtr, QualType ElementType)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
GlobalDecl CurGD
CurGD - The GlobalDecl for the current function being compiled.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void PopCleanupBlock(bool FallThroughIsBranchThrough=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
SanitizerSet SanOpts
Sanitizers enabled for this function.
void EmitAnyExprToExn(const Expr *E, Address Addr)
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
llvm::Constant * EmitCheckTypeDescriptor(QualType T)
Emit a description of a type in a format suitable for passing to a runtime sanitizer handler.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID)
Create a basic block that will call the trap intrinsic, and emit a conditional branch to it,...
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
llvm::Value * EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy, uint64_t VTableByteOffset)
Emit a type checked load from the given vtable.
llvm::Value * GetVTTParameter(GlobalDecl GD, bool ForVirtualBase, bool Delegating)
GetVTTParameter - Return the VTT parameter that should be passed to a base constructor/destructor wit...
llvm::Type * ConvertTypeForMem(QualType T)