32#include "llvm/IR/DataLayout.h"
33#include "llvm/IR/GlobalValue.h"
34#include "llvm/IR/Instructions.h"
35#include "llvm/IR/Intrinsics.h"
36#include "llvm/IR/Value.h"
37#include "llvm/Support/ScopedPrinter.h"
42using namespace CodeGen;
47 llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
54 bool UseARMMethodPtrABI;
55 bool UseARMGuardVarABI;
56 bool Use32BitVTableOffsetABI;
64 bool UseARMMethodPtrABI =
false,
65 bool UseARMGuardVarABI =
false) :
66 CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
67 UseARMGuardVarABI(UseARMGuardVarABI),
68 Use32BitVTableOffsetABI(
false) { }
82 if (isa<CXXDestructorDecl>(GD.
getDecl())) {
92 llvm_unreachable(
"emitting dtor comdat as function?");
94 llvm_unreachable(
"bad dtor kind");
96 if (isa<CXXConstructorDecl>(GD.
getDecl())) {
106 llvm_unreachable(
"closure ctors in Itanium ABI?");
109 llvm_unreachable(
"emitting ctor comdat as function?");
111 llvm_unreachable(
"bad dtor kind");
126 llvm::Value *&ThisPtrForCall,
127 llvm::Value *MemFnPtr,
138 llvm::Value *Src)
override;
140 llvm::Constant *Src)
override;
152 llvm::Value *L, llvm::Value *R,
154 bool Inequality)
override;
171 llvm::Value *Exn)
override;
173 void EmitFundamentalRTTIDescriptors(
const CXXRecordDecl *RD);
177 QualType CatchHandlerType)
override {
185 llvm::Type *StdTypeInfoPtrTy)
override;
194 bool hasUniqueVTablePointer(
QualType RecordTy) {
199 if (!CGM.getCodeGenOpts().AssumeUniqueVTables ||
200 getContext().getLangOpts().AppleKext)
205 if (!CGM.shouldEmitRTTI())
210 if (!llvm::GlobalValue::isWeakForLinker(CGM.getVTableLinkage(RD)))
219 llvm::GlobalValue::DefaultVisibility)
226 return hasUniqueVTablePointer(DestRecordTy);
232 llvm::BasicBlock *CastEnd)
override;
237 llvm::BasicBlock *CastSuccess,
238 llvm::BasicBlock *CastFail)
override;
252 AddedStructorArgCounts
275 bool Delegating)
override;
281 bool Delegating)
override;
292 CodeGenFunction::VPtr Vptr)
override;
306 llvm::Value *getVTableAddressPointInStructorWithVTT(
324 DeleteOrMemberCallExpr E)
override;
329 bool canSpeculativelyEmitVTableAsBaseClass(
const CXXRecordDecl *RD)
const;
335 if (ForVTable && !Thunk->hasLocalLinkage())
336 Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
337 CGM.setGVProperties(Thunk, GD);
350 assert(!Args.empty() &&
"expected the arglist to not be empty!");
351 return Args.size() - 1;
356 {
return "__cxa_deleted_virtual"; }
361 llvm::Value *NumElements,
369 llvm::GlobalVariable *DeclPtr,
370 bool PerformInit)
override;
372 llvm::FunctionCallee dtor,
373 llvm::Constant *addr)
override;
375 llvm::Function *getOrCreateThreadLocalWrapper(
const VarDecl *VD,
397 virtual bool shouldRTTIBeUnique()
const {
return true; }
401 enum RTTIUniquenessKind {
419 classifyRTTIUniqueness(
QualType CanTy,
420 llvm::GlobalValue::LinkageTypes
Linkage)
const;
421 friend class ItaniumRTTIBuilder;
425 std::pair<llvm::Value *, const CXXRecordDecl *>
430 bool hasAnyUnusedVirtualInlineFunction(
const CXXRecordDecl *RD)
const {
431 const auto &VtableLayout =
432 CGM.getItaniumVTableContext().getVTableLayout(RD);
434 for (
const auto &VtableComponent : VtableLayout.vtable_components()) {
436 if (!VtableComponent.isUsedFunctionPointerKind())
439 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
443 StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
444 auto *Entry = CGM.GetGlobalValue(Name);
450 if (!Entry || Entry->isDeclaration())
457 const auto &VtableLayout =
458 CGM.getItaniumVTableContext().getVTableLayout(RD);
460 for (
const auto &VtableComponent : VtableLayout.vtable_components()) {
461 if (VtableComponent.isRTTIKind()) {
462 const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();
463 if (RTTIDecl->
getVisibility() == Visibility::HiddenVisibility)
465 }
else if (VtableComponent.isUsedFunctionPointerKind()) {
466 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
467 if (Method->
getVisibility() == Visibility::HiddenVisibility &&
476class ARMCXXABI :
public ItaniumCXXABI {
479 ItaniumCXXABI(CGM,
true,
482 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
490 llvm::Value *NumElements,
497class AppleARM64CXXABI :
public ARMCXXABI {
500 Use32BitVTableOffsetABI =
true;
504 bool shouldRTTIBeUnique()
const override {
return false; }
507class FuchsiaCXXABI final :
public ItaniumCXXABI {
510 : ItaniumCXXABI(CGM) {}
513 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
516class WebAssemblyCXXABI final :
public ItaniumCXXABI {
519 : ItaniumCXXABI(CGM,
true,
524 llvm::Value *Exn)
override;
527 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
528 bool canCallMismatchedFunctionType()
const override {
return false; }
531class XLCXXABI final :
public ItaniumCXXABI {
534 : ItaniumCXXABI(CGM) {}
537 llvm::FunctionCallee dtor,
538 llvm::Constant *addr)
override;
540 bool useSinitAndSterm()
const override {
return true; }
543 void emitCXXStermFinalizer(
const VarDecl &D, llvm::Function *dtorStub,
544 llvm::Constant *addr);
552 case TargetCXXABI::GenericARM:
553 case TargetCXXABI::iOS:
554 case TargetCXXABI::WatchOS:
555 return new ARMCXXABI(CGM);
557 case TargetCXXABI::AppleARM64:
558 return new AppleARM64CXXABI(CGM);
560 case TargetCXXABI::Fuchsia:
561 return new FuchsiaCXXABI(CGM);
566 case TargetCXXABI::GenericAArch64:
567 return new ItaniumCXXABI(CGM,
true,
570 case TargetCXXABI::GenericMIPS:
571 return new ItaniumCXXABI(CGM,
true);
573 case TargetCXXABI::WebAssembly:
574 return new WebAssemblyCXXABI(CGM);
576 case TargetCXXABI::XL:
577 return new XLCXXABI(CGM);
579 case TargetCXXABI::GenericItanium:
581 == llvm::Triple::le32) {
585 return new ItaniumCXXABI(CGM,
true);
587 return new ItaniumCXXABI(CGM);
589 case TargetCXXABI::Microsoft:
590 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
592 llvm_unreachable(
"bad ABI kind");
598 return CGM.PtrDiffTy;
599 return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);
622CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
624 llvm::Value *&ThisPtrForCall,
633 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
640 llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1,
"memptr.adj");
643 llvm::Value *Adj = RawAdj;
644 if (UseARMMethodPtrABI)
645 Adj = Builder.CreateAShr(Adj, ptrdiff_1,
"memptr.adj.shifted");
650 This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj);
651 ThisPtrForCall = This;
654 llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0,
"memptr.ptr");
658 llvm::Value *IsVirtual;
659 if (UseARMMethodPtrABI)
660 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
662 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
663 IsVirtual = Builder.CreateIsNotNull(IsVirtual,
"memptr.isvirtual");
664 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
682 llvm::Value *VTableOffset = FnAsInt;
683 if (!UseARMMethodPtrABI)
684 VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
685 if (Use32BitVTableOffsetABI) {
686 VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.
Int32Ty);
687 VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
692 llvm::Constant *CheckSourceLocation;
693 llvm::Constant *CheckTypeDesc;
694 bool ShouldEmitCFICheck = CGF.
SanOpts.
has(SanitizerKind::CFIMFCall) &&
695 CGM.HasHiddenLTOVisibility(RD);
696 bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
697 CGM.HasHiddenLTOVisibility(RD);
698 bool ShouldEmitWPDInfo =
699 CGM.getCodeGenOpts().WholeProgramVTables &&
701 !CGM.AlwaysHasLTOVisibilityPublic(RD);
702 llvm::Value *VirtualFn =
nullptr;
705 CodeGenFunction::SanitizerScope SanScope(&CGF);
706 llvm::Value *TypeId =
nullptr;
707 llvm::Value *CheckResult =
nullptr;
709 if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
713 CGM.CreateMetadataIdentifierForVirtualMemPtrType(
QualType(MPT, 0));
717 if (ShouldEmitVFEInfo) {
718 llvm::Value *VFPAddr =
719 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
726 llvm::Value *CheckedLoad = Builder.CreateCall(
727 CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
728 {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
729 CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
730 VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
734 if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
735 llvm::Value *VFPAddr =
736 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
737 llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
738 ? llvm::Intrinsic::type_test
739 : llvm::Intrinsic::public_type_test;
742 Builder.CreateCall(CGM.getIntrinsic(IID), {VFPAddr, TypeId});
745 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
746 VirtualFn = CGF.
Builder.CreateCall(
747 CGM.getIntrinsic(llvm::Intrinsic::load_relative,
748 {VTableOffset->getType()}),
749 {VTable, VTableOffset});
751 llvm::Value *VFPAddr =
758 assert(VirtualFn &&
"Virtual fuction pointer not created!");
759 assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
761 "Check result required but not created!");
763 if (ShouldEmitCFICheck) {
767 llvm::Constant *StaticData[] = {
768 llvm::ConstantInt::get(CGF.
Int8Ty, CodeGenFunction::CFITCK_VMFCall),
773 if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
774 CGF.
EmitTrapCheck(CheckResult, SanitizerHandler::CFICheckFail);
776 llvm::Value *AllVtables = llvm::MetadataAsValue::get(
777 CGM.getLLVMContext(),
778 llvm::MDString::get(CGM.getLLVMContext(),
"all-vtables"));
779 llvm::Value *ValidVtable = Builder.CreateCall(
780 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
781 CGF.
EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIMFCall),
782 SanitizerHandler::CFICheckFail, StaticData,
783 {VTable, ValidVtable});
786 FnVirtual = Builder.GetInsertBlock();
795 llvm::Value *NonVirtualFn =
796 Builder.CreateIntToPtr(FnAsInt, CGF.
UnqualPtrTy,
"memptr.nonvirtualfn");
799 if (ShouldEmitCFICheck) {
802 CodeGenFunction::SanitizerScope SanScope(&CGF);
804 llvm::Constant *StaticData[] = {
805 llvm::ConstantInt::get(CGF.
Int8Ty, CodeGenFunction::CFITCK_NVMFCall),
810 llvm::Value *Bit = Builder.getFalse();
812 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
813 getContext().getMemberPointerType(
816 llvm::Value *TypeId =
819 llvm::Value *TypeTest =
820 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
821 {NonVirtualFn, TypeId});
822 Bit = Builder.CreateOr(Bit, TypeTest);
825 CGF.
EmitCheck(std::make_pair(Bit, SanitizerKind::CFIMFCall),
826 SanitizerHandler::CFICheckFail, StaticData,
827 {NonVirtualFn, llvm::UndefValue::get(CGF.
IntPtrTy)});
829 FnNonVirtual = Builder.GetInsertBlock();
835 llvm::PHINode *CalleePtr = Builder.CreatePHI(CGF.
UnqualPtrTy, 2);
836 CalleePtr->addIncoming(VirtualFn, FnVirtual);
837 CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
845llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
848 assert(MemPtr->getType() == CGM.PtrDiffTy);
853 return Builder.CreateInBoundsGEP(CGF.
Int8Ty,
Base.getPointer(), MemPtr,
884 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
885 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
889 if (E->
getCastKind() == CK_ReinterpretMemberPointer)
return src;
892 if (isa<llvm::Constant>(src))
893 return EmitMemberPointerConversion(E, cast<llvm::Constant>(src));
895 llvm::Constant *adj = getMemberPointerAdjustment(E);
896 if (!adj)
return src;
899 bool isDerivedToBase = (E->
getCastKind() == CK_DerivedToBaseMemberPointer);
909 dst = Builder.CreateNSWSub(src, adj,
"adj");
911 dst = Builder.CreateNSWAdd(src, adj,
"adj");
914 llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType());
915 llvm::Value *isNull = Builder.CreateICmpEQ(src, null,
"memptr.isnull");
916 return Builder.CreateSelect(isNull, src, dst);
920 if (UseARMMethodPtrABI) {
921 uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
923 adj = llvm::ConstantInt::get(adj->getType(), offset);
926 llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1,
"src.adj");
929 dstAdj = Builder.CreateNSWSub(srcAdj, adj,
"adj");
931 dstAdj = Builder.CreateNSWAdd(srcAdj, adj,
"adj");
933 return Builder.CreateInsertValue(src, dstAdj, 1);
937ItaniumCXXABI::EmitMemberPointerConversion(
const CastExpr *E,
938 llvm::Constant *src) {
939 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
940 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
944 if (E->
getCastKind() == CK_ReinterpretMemberPointer)
return src;
947 llvm::Constant *adj = getMemberPointerAdjustment(E);
948 if (!adj)
return src;
950 bool isDerivedToBase = (E->
getCastKind() == CK_DerivedToBaseMemberPointer);
959 if (src->isAllOnesValue())
return src;
962 return llvm::ConstantExpr::getNSWSub(src, adj);
964 return llvm::ConstantExpr::getNSWAdd(src, adj);
968 if (UseARMMethodPtrABI) {
969 uint64_t offset = cast<llvm::ConstantInt>(adj)->getZExtValue();
971 adj = llvm::ConstantInt::get(adj->getType(), offset);
974 llvm::Constant *srcAdj = src->getAggregateElement(1);
975 llvm::Constant *dstAdj;
977 dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);
979 dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);
981 llvm::Constant *res = ConstantFoldInsertValueInstruction(src, dstAdj, 1);
982 assert(res !=
nullptr &&
"Folding must succeed");
991 return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL,
true);
993 llvm::Constant *
Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
994 llvm::Constant *Values[2] = {
Zero,
Zero };
995 return llvm::ConstantStruct::getAnon(Values);
1004 return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.
getQuantity());
1008ItaniumCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
1012llvm::Constant *ItaniumCXXABI::BuildMemberPointer(
const CXXMethodDecl *MD,
1014 assert(MD->
isInstance() &&
"Member function must not be static!");
1019 llvm::Constant *MemPtr[2];
1021 uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
1023 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1025 VTableOffset = Index * 4;
1030 VTableOffset = Index * PointerWidth.
getQuantity();
1033 if (UseARMMethodPtrABI) {
1040 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);
1041 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1048 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
1049 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1056 if (Types.isFuncTypeConvertible(FPT)) {
1058 Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
1064 llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty);
1066 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
1067 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1068 (UseARMMethodPtrABI ? 2 : 1) *
1072 return llvm::ConstantStruct::getAnon(MemPtr);
1075llvm::Constant *ItaniumCXXABI::EmitMemberPointer(
const APValue &MP,
1080 return EmitNullMemberPointer(MPT);
1088 getContext().toCharUnitsFromBits(getContext().
getFieldOffset(MPD));
1104 llvm::ICmpInst::Predicate
Eq;
1105 llvm::Instruction::BinaryOps
And, Or;
1107 Eq = llvm::ICmpInst::ICMP_NE;
1108 And = llvm::Instruction::Or;
1109 Or = llvm::Instruction::And;
1111 Eq = llvm::ICmpInst::ICMP_EQ;
1112 And = llvm::Instruction::And;
1113 Or = llvm::Instruction::Or;
1119 return Builder.CreateICmp(
Eq, L, R);
1131 llvm::Value *LPtr = Builder.CreateExtractValue(L, 0,
"lhs.memptr.ptr");
1132 llvm::Value *RPtr = Builder.CreateExtractValue(R, 0,
"rhs.memptr.ptr");
1136 llvm::Value *PtrEq = Builder.CreateICmp(
Eq, LPtr, RPtr,
"cmp.ptr");
1141 llvm::Value *
Zero = llvm::Constant::getNullValue(LPtr->getType());
1142 llvm::Value *EqZero = Builder.CreateICmp(
Eq, LPtr, Zero,
"cmp.ptr.null");
1146 llvm::Value *LAdj = Builder.CreateExtractValue(L, 1,
"lhs.memptr.adj");
1147 llvm::Value *RAdj = Builder.CreateExtractValue(R, 1,
"rhs.memptr.adj");
1148 llvm::Value *AdjEq = Builder.CreateICmp(
Eq, LAdj, RAdj,
"cmp.adj");
1152 if (UseARMMethodPtrABI) {
1153 llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
1156 llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj,
"or.adj");
1157 llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
1158 llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(
Eq, OrAdjAnd1, Zero,
1160 EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
1164 llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
1165 Result = Builder.CreateBinOp(And, PtrEq, Result,
1166 Inequality ?
"memptr.ne" :
"memptr.eq");
1172 llvm::Value *MemPtr,
1178 assert(MemPtr->getType() == CGM.PtrDiffTy);
1179 llvm::Value *NegativeOne =
1180 llvm::Constant::getAllOnesValue(MemPtr->getType());
1181 return Builder.CreateICmpNE(MemPtr, NegativeOne,
"memptr.tobool");
1185 llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0,
"memptr.ptr");
1187 llvm::Constant *
Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
1188 llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero,
"memptr.tobool");
1192 if (UseARMMethodPtrABI) {
1193 llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
1194 llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1,
"memptr.adj");
1195 llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One,
"memptr.virtualbit");
1196 llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,
1197 "memptr.isvirtual");
1198 Result = Builder.CreateOr(Result, IsVirtual);
1204bool ItaniumCXXABI::classifyReturnType(
CGFunctionInfo &FI)
const {
1211 auto Align = CGM.getContext().getTypeAlignInChars(FI.
getReturnType());
1232 if (UseGlobalDelete) {
1242 llvm::Value *OffsetPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
1243 CGF.
IntPtrTy, VTable, -2,
"complete-offset.ptr");
1250 CGF.
Builder.CreateInBoundsGEP(CGF.
Int8Ty, CompletePtr, Offset);
1261 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE);
1263 if (UseGlobalDelete)
1267void ItaniumCXXABI::emitRethrow(
CodeGenFunction &CGF,
bool isNoReturn) {
1270 llvm::FunctionType *FTy =
1271 llvm::FunctionType::get(CGM.VoidTy,
false);
1273 llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy,
"__cxa_rethrow");
1284 llvm::FunctionType *FTy =
1295 llvm::FunctionType *FTy =
1296 llvm::FunctionType::get(CGM.
VoidTy, Args,
false);
1304 llvm::Type *SizeTy = CGF.
ConvertType(getContext().getSizeType());
1305 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
1309 AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize),
"exception");
1316 llvm::Constant *
TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
1321 llvm::Constant *Dtor =
nullptr;
1324 if (!
Record->hasTrivialDestructor()) {
1327 Dtor = llvm::ConstantExpr::getBitCast(Dtor, CGM.Int8PtrTy);
1330 if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1332 llvm::Value *args[] = { ExceptionPtr,
TypeInfo, Dtor };
1344 llvm::Type *PtrDiffTy =
1347 llvm::Type *Args[4] = { Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy };
1349 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args,
false);
1353 FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
1354 FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
1355 llvm::AttributeList Attrs = llvm::AttributeList::get(
1356 CGF.
getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
1363 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1380 unsigned NumPublicPaths = 0;
1393 if (PathElement.Base->isVirtual())
1396 if (NumPublicPaths > 1)
1402 PathElement.Base->getType()->getAsCXXRecordDecl());
1407 if (NumPublicPaths == 0)
1411 if (NumPublicPaths > 1)
1421 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1426bool ItaniumCXXABI::shouldTypeidBeNullChecked(
bool IsDeref,
1434 Call->setDoesNotReturn();
1435 CGF.
Builder.CreateUnreachable();
1441 llvm::Type *StdTypeInfoPtrTy) {
1447 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1450 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1451 {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
1455 CGF.
Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy,
Value, -1ULL);
1461bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
1466llvm::Value *ItaniumCXXABI::emitDynamicCastCall(
1469 llvm::Type *PtrDiffLTy =
1472 llvm::Value *SrcRTTI =
1474 llvm::Value *DestRTTI =
1480 llvm::Value *OffsetHint = llvm::ConstantInt::get(
1485 llvm::Value *Args[] = {ThisAddr.
getPointer(), SrcRTTI, DestRTTI, OffsetHint};
1486 llvm::Value *
Value =
1492 llvm::BasicBlock *BadCastBlock =
1499 EmitBadCastCall(CGF);
1505llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
1508 llvm::BasicBlock *CastFail) {
1520 std::optional<CharUnits> Offset;
1530 PathElement.Base->getType()->getAsCXXRecordDecl();
1531 if (PathElement.Base->isVirtual()) {
1544 Offset = PathOffset;
1545 else if (Offset != PathOffset) {
1550 ThisAddr =
Address(emitDynamicCastToVoid(CGF, ThisAddr, SrcRecordTy),
1561 return llvm::PoisonValue::get(CGF.
VoidPtrTy);
1570 CGM.DecorateInstructionWithTBAA(
1571 VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.
VoidPtrPtrTy));
1573 VPtr, getVTableAddressPoint(
BaseSubobject(SrcDecl, *Offset), DestDecl));
1575 if (!Offset->isZero())
1576 Result = CGF.
Builder.CreateInBoundsGEP(
1578 {llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset->getQuantity())});
1579 CGF.
Builder.CreateCondBr(Success, CastSuccess, CastFail);
1583llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(
CodeGenFunction &CGF,
1588 llvm::Value *OffsetToTop;
1589 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1591 llvm::Value *VTable =
1596 CGF.
Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);
1600 llvm::Type *PtrDiffLTy =
1604 llvm::Value *VTable =
1609 CGF.
Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
1621 Call->setDoesNotReturn();
1622 CGF.
Builder.CreateUnreachable();
1631 llvm::Value *VTablePtr = CGF.
GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
1633 CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
1635 llvm::Value *VBaseOffsetPtr =
1636 CGF.
Builder.CreateConstGEP1_64(
1638 "vbase.offset.ptr");
1640 llvm::Value *VBaseOffset;
1641 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1647 CGM.PtrDiffTy, VBaseOffsetPtr, CGF.
getPointerAlign(),
"vbase.offset");
1654 assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
1669ItaniumCXXABI::buildStructorSignature(
GlobalDecl GD,
1679 cast<CXXMethodDecl>(GD.
getDecl())->getParent()->getNumVBases() != 0) {
1680 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
1682 ArgTys.insert(ArgTys.begin() + 1,
1684 return AddedStructorArgCounts::prefix(1);
1686 return AddedStructorArgCounts{};
1709 assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
1712 if (NeedsVTTParameter(CGF.
CurGD)) {
1716 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
1722 Params.insert(Params.begin() + 1, VTTDecl);
1723 getStructorImplicitParamDecl(CGF) = VTTDecl;
1734 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
1737 if (getStructorImplicitParamDecl(CGF)) {
1750 if (HasThisReturn(CGF.
CurGD))
1756 bool ForVirtualBase,
bool Delegating) {
1758 return AddedStructorArgs{};
1765 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
1766 QualType Q = getContext().getAddrSpaceQualType(getContext().VoidPtrTy, AS);
1767 QualType VTTTy = getContext().getPointerType(Q);
1768 return AddedStructorArgs::prefix({{VTT, VTTTy}});
1771llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(
1773 bool ForVirtualBase,
bool Delegating) {
1781 bool Delegating,
Address This,
1786 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1789 if (getContext().getLangOpts().AppleKext &&
1801 llvm::GlobalVariable *VTable = getAddrOfVTable(RD,
CharUnits());
1802 if (VTable->hasInitializer())
1807 llvm::GlobalVariable::LinkageTypes
Linkage = CGM.getVTableLinkage(RD);
1808 llvm::Constant *RTTI =
1809 CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
1813 auto components = builder.beginStruct();
1815 llvm::GlobalValue::isLocalLinkage(
Linkage));
1816 components.finishAndSetAsInitializer(VTable);
1821 if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
1822 VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
1825 CGM.setGVProperties(VTable, RD);
1833 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
1834 cast<NamespaceDecl>(DC)->getIdentifier()->isStr(
"__cxxabiv1") &&
1836 EmitFundamentalRTTIDescriptors(RD);
1843 if (!VTable->isDeclarationForLinker() ||
1844 CGM.getCodeGenOpts().WholeProgramVTables) {
1845 CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
1849 if (VTable->isDeclarationForLinker()) {
1850 assert(CGM.getCodeGenOpts().WholeProgramVTables);
1851 CGM.addCompilerUsedGlobal(VTable);
1857 if (!VTable->isDSOLocal())
1862bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
1864 if (Vptr.NearestVBase ==
nullptr)
1866 return NeedsVTTParameter(CGF.
CurGD);
1869llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
1873 if ((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
1874 NeedsVTTParameter(CGF.
CurGD)) {
1875 return getVTableAddressPointInStructorWithVTT(CGF, VTableClass,
Base,
1878 return getVTableAddressPoint(
Base, VTableClass);
1884 llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass,
CharUnits());
1889 CGM.getItaniumVTableContext()
1890 .getVTableLayout(VTableClass)
1891 .getAddressPoint(
Base);
1892 llvm::Value *Indices[] = {
1893 llvm::ConstantInt::get(CGM.Int32Ty, 0),
1894 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.
VTableIndex),
1898 return llvm::ConstantExpr::getGetElementPtr(VTable->getValueType(), VTable,
1905template <
typename T>
1907 bool FoundNonInlineVirtualMethodWithAttr =
false;
1909 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
1910 if (!FD->isVirtualAsWritten() || FD->isInlineSpecified() ||
1911 FD->doesThisDeclarationHaveABody())
1915 FoundNonInlineVirtualMethodWithAttr =
true;
1923 return FoundNonInlineVirtualMethodWithAttr;
1926llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
1929 assert((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
1930 NeedsVTTParameter(CGF.
CurGD) &&
"This class doesn't have VTT");
1934 CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass,
Base);
1938 if (VirtualPointerIndex)
1940 VirtualPointerIndex);
1947llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
1949 return getVTableAddressPoint(
Base, VTableClass);
1952llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(
const CXXRecordDecl *RD,
1954 assert(VPtrOffset.
isZero() &&
"Itanium ABI only supports zero vptr offsets");
1956 llvm::GlobalVariable *&VTable = VTables[RD];
1961 CGM.addDeferredVTable(RD);
1964 llvm::raw_svector_ostream Out(Name);
1965 getMangleContext().mangleCXXVTable(RD, Out);
1968 CGM.getItaniumVTableContext().getVTableLayout(RD);
1969 llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
1974 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
1975 unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()
1977 : CGM.getTarget().getPointerAlign(AS);
1979 VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
1980 Name, VTableType, llvm::GlobalValue::ExternalLinkage,
1981 getContext().toCharUnitsFromBits(PAlign).getAsAlign());
1982 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1991 if (CGM.getTarget().hasPS4DLLImportExport()) {
1992 if ((!RD->
hasAttr<DLLImportAttr>()) && (!RD->
hasAttr<DLLExportAttr>())) {
1993 if (CGM.getVTables().isVTableExternal(RD)) {
1994 if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD))
1995 VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
1997 if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD))
1998 VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2002 CGM.setGVProperties(VTable, RD);
2012 llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy;
2013 auto *MethodDecl = cast<CXXMethodDecl>(GD.
getDecl());
2014 llvm::Value *VTable = CGF.
GetVTablePtr(This, PtrTy, MethodDecl->getParent());
2016 uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
2020 MethodDecl->getParent(), VTable, PtrTy,
2022 CGM.getContext().getTargetInfo().getPointerWidth(LangAS::Default) /
2027 llvm::Value *VFuncLoad;
2028 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
2029 VFuncLoad = CGF.
Builder.CreateCall(
2030 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
2031 {VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)});
2033 llvm::Value *VTableSlotPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
2034 PtrTy, VTable, VTableIndex,
"vfn");
2045 if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2046 CGM.getCodeGenOpts().StrictVTablePointers) {
2047 if (
auto *VFuncLoadInstr = dyn_cast<llvm::Instruction>(VFuncLoad)) {
2048 VFuncLoadInstr->setMetadata(
2049 llvm::LLVMContext::MD_invariant_load,
2050 llvm::MDNode::get(CGM.getLLVMContext(),
2061llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
2063 Address This, DeleteOrMemberCallExpr E) {
2066 assert((CE !=
nullptr) ^ (D !=
nullptr));
2067 assert(CE ==
nullptr || CE->arg_begin() == CE->arg_end());
2072 &CGM.getTypes().arrangeCXXStructorDeclaration(GD);
2078 ThisTy = CE->getObjectType();
2080 ThisTy = D->getDestroyedType();
2088void ItaniumCXXABI::emitVirtualInheritanceTables(
const CXXRecordDecl *RD) {
2094bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
2098 if (CGM.getLangOpts().AppleKext)
2103 if (isVTableHidden(RD))
2106 if (CGM.getCodeGenOpts().ForceEmitVTables)
2113 if (hasAnyUnusedVirtualInlineFunction(RD))
2121 for (
const auto &B : RD->
bases()) {
2122 auto *BRD = B.getType()->getAsCXXRecordDecl();
2123 assert(BRD &&
"no class for base specifier");
2124 if (B.isVirtual() || !BRD->isDynamicClass())
2126 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2134bool ItaniumCXXABI::canSpeculativelyEmitVTable(
const CXXRecordDecl *RD)
const {
2135 if (!canSpeculativelyEmitVTableAsBaseClass(RD))
2140 for (
const auto &B : RD->
vbases()) {
2141 auto *BRD = B.getType()->getAsCXXRecordDecl();
2142 assert(BRD &&
"no class for base specifier");
2143 if (!BRD->isDynamicClass())
2145 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2153 int64_t NonVirtualAdjustment,
2154 int64_t VirtualAdjustment,
2155 bool IsReturnAdjustment) {
2156 if (!NonVirtualAdjustment && !VirtualAdjustment)
2162 if (NonVirtualAdjustment && !IsReturnAdjustment) {
2168 llvm::Value *ResultPtr;
2169 if (VirtualAdjustment) {
2173 llvm::Value *Offset;
2174 llvm::Value *OffsetPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
2175 CGF.
Int8Ty, VTablePtr, VirtualAdjustment);
2182 llvm::Type *PtrDiffTy =
2190 ResultPtr = CGF.
Builder.CreateInBoundsGEP(
2191 V.getElementType(),
V.getPointer(), Offset);
2193 ResultPtr =
V.getPointer();
2198 if (NonVirtualAdjustment && IsReturnAdjustment) {
2199 ResultPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(CGF.
Int8Ty, ResultPtr,
2200 NonVirtualAdjustment);
2206llvm::Value *ItaniumCXXABI::performThisAdjustment(
CodeGenFunction &CGF,
2225 return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
2230 return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
2239 CGM.getContext().getPreferredTypeAlignInChars(elementType));
2244 llvm::Value *NumElements,
2247 assert(requiresArrayCookie(
expr));
2257 assert(CookieSize == getArrayCookieSizeImpl(ElementType));
2261 CharUnits CookieOffset = CookieSize - SizeSize;
2262 if (!CookieOffset.
isZero())
2270 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
2271 (
expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||
2272 CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {
2274 SI->setNoSanitizeMetadata();
2275 llvm::FunctionType *FTy =
2276 llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.
getType(),
false);
2277 llvm::FunctionCallee F =
2278 CGM.CreateRuntimeFunction(FTy,
"__asan_poison_cxx_array_cookie");
2291 Address numElementsPtr = allocPtr;
2293 if (!numElementsOffset.
isZero())
2299 if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0)
2306 llvm::FunctionType *FTy =
2308 llvm::FunctionCallee F =
2309 CGM.CreateRuntimeFunction(FTy,
"__asan_load_cxx_array_cookie");
2323 CGM.getContext().getTypeAlignInChars(elementType));
2328 llvm::Value *numElements,
2331 assert(requiresArrayCookie(
expr));
2338 llvm::Value *elementSize = llvm::ConstantInt::get(CGF.
SizeTy,
2339 getContext().getTypeSizeInChars(elementType).getQuantity());
2348 CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
2367 llvm::PointerType *GuardPtrTy) {
2369 llvm::FunctionType *FTy =
2373 FTy,
"__cxa_guard_acquire",
2375 llvm::AttributeList::FunctionIndex,
2376 llvm::Attribute::NoUnwind));
2380 llvm::PointerType *GuardPtrTy) {
2382 llvm::FunctionType *FTy =
2383 llvm::FunctionType::get(CGM.
VoidTy, GuardPtrTy,
false);
2385 FTy,
"__cxa_guard_release",
2387 llvm::AttributeList::FunctionIndex,
2388 llvm::Attribute::NoUnwind));
2392 llvm::PointerType *GuardPtrTy) {
2394 llvm::FunctionType *FTy =
2395 llvm::FunctionType::get(CGM.
VoidTy, GuardPtrTy,
false);
2397 FTy,
"__cxa_guard_abort",
2399 llvm::AttributeList::FunctionIndex,
2400 llvm::Attribute::NoUnwind));
2405 llvm::GlobalVariable *Guard;
2406 CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
2419 llvm::GlobalVariable *var,
2420 bool shouldPerformInit) {
2425 bool NonTemplateInline =
2432 bool threadsafe = getContext().getLangOpts().ThreadsafeStatics &&
2438 bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage();
2440 llvm::IntegerType *guardTy;
2442 if (useInt8GuardVariable) {
2448 if (UseARMGuardVarABI) {
2457 llvm::PointerType *guardPtrTy = llvm::PointerType::get(
2463 llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D);
2468 llvm::raw_svector_ostream out(guardName);
2469 getMangleContext().mangleStaticGuardVariable(&D, out);
2475 guard =
new llvm::GlobalVariable(CGM.getModule(), guardTy,
2476 false, var->getLinkage(),
2477 llvm::ConstantInt::get(guardTy, 0),
2479 guard->setDSOLocal(var->isDSOLocal());
2480 guard->setVisibility(var->getVisibility());
2481 guard->setDLLStorageClass(var->getDLLStorageClass());
2483 guard->setThreadLocalMode(var->getThreadLocalMode());
2484 guard->setAlignment(guardAlignment.
getAsAlign());
2489 llvm::Comdat *
C = var->getComdat();
2491 (CGM.getTarget().getTriple().isOSBinFormatELF() ||
2492 CGM.getTarget().getTriple().isOSBinFormatWasm())) {
2493 guard->setComdat(
C);
2494 }
else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
2495 guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));
2498 CGM.setStaticLocalDeclGuardAddress(&D, guard);
2501 Address guardAddr =
Address(guard, guard->getValueType(), guardAlignment);
2526 if (!threadsafe || MaxInlineWidthInBits) {
2528 llvm::LoadInst *LI =
2538 LI->setAtomic(llvm::AtomicOrdering::Acquire);
2561 (UseARMGuardVarABI && !useInt8GuardVariable)
2562 ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
2564 llvm::Value *NeedsInit = Builder.CreateIsNull(
V,
"guard.uninitialized");
2570 CodeGenFunction::GuardKind::VariableGuard, &D);
2598 Builder.CreateCondBr(Builder.CreateIsNotNull(
V,
"tobool"),
2599 InitBlock, EndBlock);
2609 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2627 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2636 llvm::FunctionCallee dtor,
2637 llvm::Constant *addr,
bool TLS) {
2639 "unexpected call to emitGlobalDtorWithCXAAtExit");
2641 "__cxa_atexit is disabled");
2642 const char *Name =
"__cxa_atexit";
2645 Name = T.isOSDarwin() ?
"_tlv_atexit" :
"__cxa_thread_atexit";
2653 auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0;
2654 auto AddrPtrTy = AddrAS ? llvm::PointerType::get(CGF.
getLLVMContext(), AddrAS)
2658 llvm::Constant *handle =
2660 auto *GV = cast<llvm::GlobalValue>(handle->stripPointerCasts());
2661 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
2664 llvm::Type *paramTys[] = {
dtorTy, AddrPtrTy, handle->getType()};
2665 llvm::FunctionType *atexitTy =
2666 llvm::FunctionType::get(CGF.
IntTy, paramTys,
false);
2670 if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee()))
2671 fn->setDoesNotThrow();
2678 addr = llvm::Constant::getNullValue(CGF.
Int8PtrTy);
2680 llvm::Value *args[] = {dtor.getCallee(), addr, handle};
2688 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
2692 return GlobalInitOrCleanupFn;
2695void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {
2696 for (
const auto &I : DtorsUsingAtExit) {
2698 std::string GlobalCleanupFnName =
2699 std::string(
"__GLOBAL_cleanup_") + llvm::to_string(Priority);
2701 llvm::Function *GlobalCleanupFn =
2711 llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
2715 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2716 auto itv = Dtors.rbegin();
2717 while (itv != Dtors.rend()) {
2718 llvm::Function *Dtor = *itv;
2723 llvm::Value *NeedsDestruct =
2724 CGF.
Builder.CreateIsNull(
V,
"needs_destruct");
2726 llvm::BasicBlock *DestructCallBlock =
2729 (itv + 1) != Dtors.rend() ?
"unatexit.call" :
"destruct.end");
2732 CGF.
Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
2737 llvm::CallInst *CI = CGF.
Builder.CreateCall(dtorFuncTy, Dtor);
2739 CI->setCallingConv(Dtor->getCallingConv());
2747 AddGlobalDtor(GlobalCleanupFn, Priority);
2751void CodeGenModule::registerGlobalDtorsWithAtExit() {
2752 for (
const auto &I : DtorsUsingAtExit) {
2754 std::string GlobalInitFnName =
2755 std::string(
"__GLOBAL_init_") + llvm::to_string(Priority);
2756 llvm::Function *GlobalInitFn =
2770 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2771 for (
auto *Dtor : Dtors) {
2784 AddGlobalCtor(GlobalInitFn, Priority);
2788 unregisterGlobalDtorsWithUnAtExit();
2793 llvm::FunctionCallee dtor,
2794 llvm::Constant *addr) {
2802 if (CGM.getCodeGenOpts().CXAAtExit || D.
getTLSKind())
2807 if (CGM.getLangOpts().AppleKext) {
2809 return CGM.AddCXXDtorEntry(dtor, addr);
2817 assert(!VD->
isStaticLocal() &&
"static local VarDecls don't need wrappers!");
2827static llvm::GlobalValue::LinkageTypes
2829 llvm::GlobalValue::LinkageTypes VarLinkage =
2833 if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
2838 if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
2839 !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
2841 return llvm::GlobalValue::WeakODRLinkage;
2845ItaniumCXXABI::getOrCreateThreadLocalWrapper(
const VarDecl *VD,
2850 llvm::raw_svector_ostream Out(WrapperName);
2851 getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);
2856 if (llvm::Value *
V = CGM.getModule().getNamedValue(WrapperName))
2857 return cast<llvm::Function>(
V);
2863 const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
2866 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI);
2867 llvm::Function *Wrapper =
2869 WrapperName.str(), &CGM.getModule());
2871 if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())
2872 Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));
2874 CGM.SetLLVMFunctionAttributes(
GlobalDecl(), FI, Wrapper,
false);
2877 if (!Wrapper->hasLocalLinkage())
2879 llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
2880 llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
2882 Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
2885 Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2886 Wrapper->addFnAttr(llvm::Attribute::NoUnwind);
2889 ThreadWrappers.push_back({VD, Wrapper});
2893void ItaniumCXXABI::EmitThreadLocalInitFuncs(
2897 llvm::Function *InitFunc =
nullptr;
2902 llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;
2903 for (
unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {
2906 UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =
2907 CXXThreadLocalInits[I];
2909 OrderedInits.push_back(CXXThreadLocalInits[I]);
2912 if (!OrderedInits.empty()) {
2914 llvm::FunctionType *FTy =
2915 llvm::FunctionType::get(CGM.
VoidTy,
false);
2920 llvm::GlobalVariable *Guard =
new llvm::GlobalVariable(
2922 llvm::GlobalVariable::InternalLinkage,
2923 llvm::ConstantInt::get(CGM.
Int8Ty, 0),
"__tls_guard");
2924 Guard->setThreadLocal(
true);
2928 Guard->setAlignment(GuardAlign.
getAsAlign());
2934 InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
2935 InitFunc->addFnAttr(llvm::Attribute::NoUnwind);
2941 for (
const VarDecl *VD : CXXThreadLocals) {
2945 getOrCreateThreadLocalWrapper(VD, GV);
2950 for (
auto VDAndWrapper : ThreadWrappers) {
2951 const VarDecl *VD = VDAndWrapper.first;
2952 llvm::GlobalVariable *Var =
2954 llvm::Function *Wrapper = VDAndWrapper.second;
2961 Wrapper->setLinkage(llvm::Function::ExternalLinkage);
2967 if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)
2968 Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);
2976 llvm::raw_svector_ostream Out(InitFnName);
2977 getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
2980 llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
2985 llvm::GlobalValue *Init =
nullptr;
2986 bool InitIsInitFunc =
false;
2987 bool HasConstantInitialization =
false;
2988 if (!usesThreadWrapperFunction(VD)) {
2989 HasConstantInitialization =
true;
2991 InitIsInitFunc =
true;
2992 llvm::Function *InitFuncToUse = InitFunc;
2996 Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),
3003 Init = llvm::Function::Create(InitFnTy,
3004 llvm::GlobalVariable::ExternalWeakLinkage,
3008 GlobalDecl(), FI, cast<llvm::Function>(Init),
false);
3012 Init->setVisibility(Var->getVisibility());
3014 if (!CGM.
getTriple().isOSWindows() || !Init->hasExternalWeakLinkage())
3015 Init->setDSOLocal(Var->isDSOLocal());
3018 llvm::LLVMContext &Context = CGM.
getModule().getContext();
3026 isEmittedWithConstantInitializer(VD,
true) &&
3027 !mayNeedDestruction(VD)) {
3032 assert(Init ==
nullptr &&
"Expected Init to be null.");
3034 llvm::Function *Func = llvm::Function::Create(
3035 InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.
getModule());
3038 cast<llvm::Function>(Func),
3041 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context,
"", Func);
3043 Builder.CreateRetVoid();
3046 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context,
"", Wrapper);
3048 if (HasConstantInitialization) {
3050 }
else if (InitIsInitFunc) {
3052 llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init);
3054 CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3055 llvm::Function *Fn =
3056 cast<llvm::Function>(cast<llvm::GlobalAlias>(Init)->getAliasee());
3057 Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3068 Builder.CreateCall(InitFnTy, Init);
3071 llvm::Value *Have = Builder.CreateIsNotNull(Init);
3072 llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context,
"", Wrapper);
3073 llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context,
"", Wrapper);
3074 Builder.CreateCondBr(Have, InitBB, ExitBB);
3076 Builder.SetInsertPoint(InitBB);
3077 Builder.CreateCall(InitFnTy, Init);
3078 Builder.CreateBr(ExitBB);
3080 Builder.SetInsertPoint(ExitBB);
3085 llvm::Value *Val = Builder.CreateThreadLocalAddress(Var);
3089 Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align);
3091 if (Val->getType() != Wrapper->getReturnType())
3092 Val = Builder.CreatePointerBitCastOrAddrSpaceCast(
3093 Val, Wrapper->getReturnType(),
"");
3095 Builder.CreateRet(Val);
3103 llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
3105 llvm::CallInst *CallVal = CGF.
Builder.CreateCall(Wrapper);
3106 CallVal->setCallingConv(Wrapper->getCallingConv());
3120bool ItaniumCXXABI::NeedsVTTParameter(
GlobalDecl GD) {
3139class ItaniumRTTIBuilder {
3141 llvm::LLVMContext &VMContext;
3142 const ItaniumCXXABI &
CXXABI;
3148 llvm::GlobalVariable *
3149 GetAddrOfTypeName(
QualType Ty, llvm::GlobalVariable::LinkageTypes
Linkage);
3153 llvm::Constant *GetAddrOfExternalRTTIDescriptor(
QualType Ty);
3156 void BuildVTablePointer(
const Type *Ty);
3169 void BuildPointerTypeInfo(
QualType PointeeTy);
3180 ItaniumRTTIBuilder(
const ItaniumCXXABI &ABI)
3181 : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()),
CXXABI(ABI) {}
3195 PTI_Incomplete = 0x8,
3199 PTI_ContainingClassIncomplete = 0x10,
3205 PTI_Noexcept = 0x40,
3211 VMI_NonDiamondRepeat = 0x1,
3214 VMI_DiamondShaped = 0x2
3228 llvm::Constant *BuildTypeInfo(
QualType Ty);
3231 llvm::Constant *BuildTypeInfo(
3233 llvm::GlobalVariable::LinkageTypes
Linkage,
3234 llvm::GlobalValue::VisibilityTypes
Visibility,
3235 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
3239llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
3242 llvm::raw_svector_ostream Out(Name);
3248 llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
3255 GV->setInitializer(Init);
3261ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(
QualType Ty) {
3264 llvm::raw_svector_ostream Out(Name);
3268 llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(Name);
3275 GV =
new llvm::GlobalVariable(
3277 true, llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
3283 if (RD && CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD)) {
3284 GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
3311 case BuiltinType::Void:
3312 case BuiltinType::NullPtr:
3313 case BuiltinType::Bool:
3314 case BuiltinType::WChar_S:
3315 case BuiltinType::WChar_U:
3316 case BuiltinType::Char_U:
3317 case BuiltinType::Char_S:
3318 case BuiltinType::UChar:
3319 case BuiltinType::SChar:
3320 case BuiltinType::Short:
3321 case BuiltinType::UShort:
3322 case BuiltinType::Int:
3323 case BuiltinType::UInt:
3324 case BuiltinType::Long:
3325 case BuiltinType::ULong:
3326 case BuiltinType::LongLong:
3327 case BuiltinType::ULongLong:
3328 case BuiltinType::Half:
3329 case BuiltinType::Float:
3330 case BuiltinType::Double:
3331 case BuiltinType::LongDouble:
3332 case BuiltinType::Float16:
3333 case BuiltinType::Float128:
3334 case BuiltinType::Ibm128:
3335 case BuiltinType::Char8:
3336 case BuiltinType::Char16:
3337 case BuiltinType::Char32:
3338 case BuiltinType::Int128:
3339 case BuiltinType::UInt128:
3342#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
3343 case BuiltinType::Id:
3344#include "clang/Basic/OpenCLImageTypes.def"
3345#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
3346 case BuiltinType::Id:
3347#include "clang/Basic/OpenCLExtensionTypes.def"
3348 case BuiltinType::OCLSampler:
3349 case BuiltinType::OCLEvent:
3350 case BuiltinType::OCLClkEvent:
3351 case BuiltinType::OCLQueue:
3352 case BuiltinType::OCLReserveID:
3353#define SVE_TYPE(Name, Id, SingletonId) \
3354 case BuiltinType::Id:
3355#include "clang/Basic/AArch64SVEACLETypes.def"
3356#define PPC_VECTOR_TYPE(Name, Id, Size) \
3357 case BuiltinType::Id:
3358#include "clang/Basic/PPCTypes.def"
3359#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3360#include "clang/Basic/RISCVVTypes.def"
3361#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3362#include "clang/Basic/WebAssemblyReferenceTypes.def"
3363 case BuiltinType::ShortAccum:
3364 case BuiltinType::Accum:
3365 case BuiltinType::LongAccum:
3366 case BuiltinType::UShortAccum:
3367 case BuiltinType::UAccum:
3368 case BuiltinType::ULongAccum:
3369 case BuiltinType::ShortFract:
3370 case BuiltinType::Fract:
3371 case BuiltinType::LongFract:
3372 case BuiltinType::UShortFract:
3373 case BuiltinType::UFract:
3374 case BuiltinType::ULongFract:
3375 case BuiltinType::SatShortAccum:
3376 case BuiltinType::SatAccum:
3377 case BuiltinType::SatLongAccum:
3378 case BuiltinType::SatUShortAccum:
3379 case BuiltinType::SatUAccum:
3380 case BuiltinType::SatULongAccum:
3381 case BuiltinType::SatShortFract:
3382 case BuiltinType::SatFract:
3383 case BuiltinType::SatLongFract:
3384 case BuiltinType::SatUShortFract:
3385 case BuiltinType::SatUFract:
3386 case BuiltinType::SatULongFract:
3387 case BuiltinType::BFloat16:
3390 case BuiltinType::Dependent:
3391#define BUILTIN_TYPE(Id, SingletonId)
3392#define PLACEHOLDER_TYPE(Id, SingletonId) \
3393 case BuiltinType::Id:
3394#include "clang/AST/BuiltinTypes.def"
3395 llvm_unreachable(
"asking for RRTI for a placeholder type!");
3397 case BuiltinType::ObjCId:
3398 case BuiltinType::ObjCClass:
3399 case BuiltinType::ObjCSel:
3400 llvm_unreachable(
"FIXME: Objective-C types are unsupported!");
3403 llvm_unreachable(
"Invalid BuiltinType Kind!");
3408 const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
3426 if (
const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
3431 if (
const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3449 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3450 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
3461 bool IsDLLImport = RD->
hasAttr<DLLImportAttr>();
3464 if (CGM.
getTriple().isWindowsGNUEnvironment())
3471 return IsDLLImport && !CGM.
getTriple().isWindowsItaniumEnvironment()
3499 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3504 if (
const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3508 dyn_cast<MemberPointerType>(Ty)) {
3510 const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
3532 if (
Base->isVirtual())
3542 if (!BaseDecl->isEmpty() &&
3549void ItaniumRTTIBuilder::BuildVTablePointer(
const Type *Ty) {
3551 static const char *
const ClassTypeInfo =
3552 "_ZTVN10__cxxabiv117__class_type_infoE";
3554 static const char *
const SIClassTypeInfo =
3555 "_ZTVN10__cxxabiv120__si_class_type_infoE";
3557 static const char *
const VMIClassTypeInfo =
3558 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
3560 const char *VTableName =
nullptr;
3563#define TYPE(Class, Base)
3564#define ABSTRACT_TYPE(Class, Base)
3565#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3566#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3567#define DEPENDENT_TYPE(Class, Base) case Type::Class:
3568#include "clang/AST/TypeNodes.inc"
3569 llvm_unreachable(
"Non-canonical and dependent types shouldn't get here");
3571 case Type::LValueReference:
3572 case Type::RValueReference:
3573 llvm_unreachable(
"References shouldn't get here");
3576 case Type::DeducedTemplateSpecialization:
3577 llvm_unreachable(
"Undeduced type shouldn't get here");
3580 llvm_unreachable(
"Pipe types shouldn't get here");
3586 case Type::ExtVector:
3587 case Type::ConstantMatrix:
3591 case Type::BlockPointer:
3593 VTableName =
"_ZTVN10__cxxabiv123__fundamental_type_infoE";
3596 case Type::ConstantArray:
3597 case Type::IncompleteArray:
3598 case Type::VariableArray:
3600 VTableName =
"_ZTVN10__cxxabiv117__array_type_infoE";
3603 case Type::FunctionNoProto:
3604 case Type::FunctionProto:
3606 VTableName =
"_ZTVN10__cxxabiv120__function_type_infoE";
3611 VTableName =
"_ZTVN10__cxxabiv116__enum_type_infoE";
3614 case Type::Record: {
3616 cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
3619 VTableName = ClassTypeInfo;
3621 VTableName = SIClassTypeInfo;
3623 VTableName = VMIClassTypeInfo;
3629 case Type::ObjCObject:
3631 Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
3634 if (isa<BuiltinType>(Ty)) {
3635 VTableName = ClassTypeInfo;
3639 assert(isa<ObjCInterfaceType>(Ty));
3642 case Type::ObjCInterface:
3643 if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
3644 VTableName = SIClassTypeInfo;
3646 VTableName = ClassTypeInfo;
3650 case Type::ObjCObjectPointer:
3653 VTableName =
"_ZTVN10__cxxabiv119__pointer_type_infoE";
3656 case Type::MemberPointer:
3658 VTableName =
"_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
3662 llvm::Constant *VTable =
nullptr;
3666 VTable = CGM.
getModule().getNamedAlias(VTableName);
3669 VTable = CGM.
getModule().getOrInsertGlobal(VTableName, Ty);
3672 CGM.
setDSOLocal(cast<llvm::GlobalValue>(VTable->stripPointerCasts()));
3674 llvm::Type *PtrDiffTy =
3681 llvm::Constant *Eight = llvm::ConstantInt::get(CGM.
Int32Ty, 8);
3683 llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.
Int8Ty, VTable, Eight);
3685 llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
3686 VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.
GlobalsInt8PtrTy,
3690 Fields.push_back(VTable);
3707 return llvm::GlobalValue::InternalLinkage;
3713 return llvm::GlobalValue::InternalLinkage;
3721 return llvm::GlobalValue::LinkOnceODRLinkage;
3723 if (
const RecordType *Record = dyn_cast<RecordType>(Ty)) {
3724 const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
3726 return llvm::GlobalValue::WeakODRLinkage;
3727 if (CGM.
getTriple().isWindowsItaniumEnvironment())
3728 if (RD->
hasAttr<DLLImportAttr>() &&
3730 return llvm::GlobalValue::ExternalLinkage;
3736 .isWindowsGNUEnvironment())
3740 return llvm::GlobalValue::LinkOnceODRLinkage;
3743 llvm_unreachable(
"Invalid linkage!");
3746llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
QualType Ty) {
3752 llvm::raw_svector_ostream Out(Name);
3755 llvm::GlobalVariable *OldGV = CGM.
getModule().getNamedGlobal(Name);
3756 if (OldGV && !OldGV->isDeclaration()) {
3757 assert(!OldGV->hasAvailableExternallyLinkage() &&
3758 "available_externally typeinfos not yet implemented");
3766 return GetAddrOfExternalRTTIDescriptor(Ty);
3773 llvm::GlobalValue::VisibilityTypes llvmVisibility;
3774 if (llvm::GlobalValue::isLocalLinkage(
Linkage))
3776 llvmVisibility = llvm::GlobalValue::DefaultVisibility;
3778 ItaniumCXXABI::RUK_NonUniqueHidden)
3779 llvmVisibility = llvm::GlobalValue::HiddenVisibility;
3783 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
3784 llvm::GlobalValue::DefaultStorageClass;
3786 if ((CGM.
getTriple().isWindowsItaniumEnvironment() &&
3787 RD->
hasAttr<DLLExportAttr>()) ||
3789 !llvm::GlobalValue::isLocalLinkage(
Linkage) &&
3790 llvmVisibility == llvm::GlobalValue::DefaultVisibility))
3791 DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
3793 return BuildTypeInfo(Ty,
Linkage, llvmVisibility, DLLStorageClass);
3796llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
3798 llvm::GlobalVariable::LinkageTypes
Linkage,
3799 llvm::GlobalValue::VisibilityTypes
Visibility,
3800 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
3802 BuildVTablePointer(cast<Type>(Ty));
3806 llvm::Constant *TypeNameField;
3810 ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =
3812 if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {
3815 TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.
Int64Ty);
3816 llvm::Constant *flag =
3817 llvm::ConstantInt::get(CGM.
Int64Ty, ((uint64_t)1) << 63);
3818 TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
3824 Fields.push_back(TypeNameField);
3827#define TYPE(Class, Base)
3828#define ABSTRACT_TYPE(Class, Base)
3829#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3830#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3831#define DEPENDENT_TYPE(Class, Base) case Type::Class:
3832#include "clang/AST/TypeNodes.inc"
3833 llvm_unreachable(
"Non-canonical and dependent types shouldn't get here");
3838 case Type::ExtVector:
3839 case Type::ConstantMatrix:
3841 case Type::BlockPointer:
3846 case Type::LValueReference:
3847 case Type::RValueReference:
3848 llvm_unreachable(
"References shouldn't get here");
3851 case Type::DeducedTemplateSpecialization:
3852 llvm_unreachable(
"Undeduced type shouldn't get here");
3860 case Type::ConstantArray:
3861 case Type::IncompleteArray:
3862 case Type::VariableArray:
3867 case Type::FunctionNoProto:
3868 case Type::FunctionProto:
3878 case Type::Record: {
3880 cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
3887 BuildSIClassTypeInfo(RD);
3889 BuildVMIClassTypeInfo(RD);
3894 case Type::ObjCObject:
3895 case Type::ObjCInterface:
3896 BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
3899 case Type::ObjCObjectPointer:
3900 BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
3904 BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
3907 case Type::MemberPointer:
3908 BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
3916 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
3919 llvm::raw_svector_ostream Out(Name);
3922 llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
3923 llvm::GlobalVariable *GV =
3924 new llvm::GlobalVariable(M, Init->getType(),
3928 auto GVDLLStorageClass = DLLStorageClass;
3930 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3931 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
3932 if (RD->
hasAttr<DLLExportAttr>() ||
3933 CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD)) {
3934 GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
3941 GV->takeName(OldGV);
3942 llvm::Constant *NewPtr =
3943 llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
3944 OldGV->replaceAllUsesWith(NewPtr);
3945 OldGV->eraseFromParent();
3949 GV->setComdat(M.getOrInsertComdat(GV->getName()));
3976 TypeName->setDLLStorageClass(DLLStorageClass);
3989void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(
const ObjCObjectType *OT) {
3992 assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
3996 if (isa<BuiltinType>(T))
return;
4007 llvm::Constant *BaseTypeInfo =
4008 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(SuperTy);
4009 Fields.push_back(BaseTypeInfo);
4014void ItaniumRTTIBuilder::BuildSIClassTypeInfo(
const CXXRecordDecl *RD) {
4018 llvm::Constant *BaseTypeInfo =
4020 Fields.push_back(BaseTypeInfo);
4043 if (
Base->isVirtual()) {
4045 if (!Bases.VirtualBases.insert(BaseDecl).second) {
4048 Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
4050 if (Bases.NonVirtualBases.count(BaseDecl))
4051 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4055 if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
4058 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4060 if (Bases.VirtualBases.count(BaseDecl))
4061 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4066 for (
const auto &I : BaseDecl->bases())
4077 for (
const auto &I : RD->
bases())
4086void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(
const CXXRecordDecl *RD) {
4087 llvm::Type *UnsignedIntLTy =
4095 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4100 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->
getNumBases()));
4133 llvm::Type *OffsetFlagsLTy =
4138 Fields.push_back(ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(
Base.getType()));
4150 if (
Base.isVirtual())
4158 OffsetFlags =
uint64_t(Offset.getQuantity()) << 8;
4162 if (
Base.isVirtual())
4163 OffsetFlags |= BCTI_Virtual;
4165 OffsetFlags |= BCTI_Public;
4167 Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags));
4176 if (
Type.isConstQualified())
4177 Flags |= ItaniumRTTIBuilder::PTI_Const;
4178 if (
Type.isVolatileQualified())
4179 Flags |= ItaniumRTTIBuilder::PTI_Volatile;
4180 if (
Type.isRestrictQualified())
4181 Flags |= ItaniumRTTIBuilder::PTI_Restrict;
4188 Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
4191 if (Proto->isNothrow()) {
4192 Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
4202void ItaniumRTTIBuilder::BuildPointerTypeInfo(
QualType PointeeTy) {
4208 llvm::Type *UnsignedIntLTy =
4210 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4215 llvm::Constant *PointeeTypeInfo =
4216 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(PointeeTy);
4217 Fields.push_back(PointeeTypeInfo);
4233 Flags |= PTI_ContainingClassIncomplete;
4235 llvm::Type *UnsignedIntLTy =
4237 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4242 llvm::Constant *PointeeTypeInfo =
4243 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(PointeeTy);
4244 Fields.push_back(PointeeTypeInfo);
4251 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(
QualType(ClassType, 0)));
4254llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(
QualType Ty) {
4255 return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
4258void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(
const CXXRecordDecl *RD) {
4261 getContext().VoidTy, getContext().NullPtrTy,
4262 getContext().BoolTy, getContext().WCharTy,
4263 getContext().CharTy, getContext().UnsignedCharTy,
4264 getContext().SignedCharTy, getContext().ShortTy,
4265 getContext().UnsignedShortTy, getContext().IntTy,
4266 getContext().UnsignedIntTy, getContext().LongTy,
4267 getContext().UnsignedLongTy, getContext().LongLongTy,
4268 getContext().UnsignedLongLongTy, getContext().Int128Ty,
4269 getContext().UnsignedInt128Ty, getContext().HalfTy,
4270 getContext().FloatTy, getContext().DoubleTy,
4271 getContext().LongDoubleTy, getContext().Float128Ty,
4272 getContext().Char8Ty, getContext().Char16Ty,
4273 getContext().Char32Ty
4275 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4277 ? llvm::GlobalValue::DLLExportStorageClass
4278 : llvm::GlobalValue::DefaultStorageClass;
4279 llvm::GlobalValue::VisibilityTypes
Visibility =
4281 for (
const QualType &FundamentalType : FundamentalTypes) {
4283 QualType PointerTypeConst = getContext().getPointerType(
4284 FundamentalType.withConst());
4286 ItaniumRTTIBuilder(*this).BuildTypeInfo(
4287 Type, llvm::GlobalValue::ExternalLinkage,
4294ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
4296 if (shouldRTTIBeUnique())
4300 if (
Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
4301 Linkage != llvm::GlobalValue::WeakODRLinkage)
4309 if (
Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
4310 return RUK_NonUniqueHidden;
4315 assert(
Linkage == llvm::GlobalValue::WeakODRLinkage);
4316 return RUK_NonUniqueVisible;
4321enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
4326 return StructorCodegen::Emit;
4331 return StructorCodegen::Emit;
4334 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
4337 const auto *CD = cast<CXXConstructorDecl>(MD);
4342 if (llvm::GlobalValue::isDiscardableIfUnused(
Linkage))
4343 return StructorCodegen::RAUW;
4346 if (!llvm::GlobalAlias::isValidLinkage(
Linkage))
4347 return StructorCodegen::RAUW;
4349 if (llvm::GlobalValue::isWeakForLinker(
Linkage)) {
4353 return StructorCodegen::COMDAT;
4354 return StructorCodegen::Emit;
4357 return StructorCodegen::Alias;
4367 if (Entry && !Entry->isDeclaration())
4370 auto *Aliasee = cast<llvm::GlobalValue>(CGM.
GetAddrOfGlobal(TargetDecl));
4373 auto *Alias = llvm::GlobalAlias::create(
Linkage,
"", Aliasee);
4376 Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4380 assert(Entry->getType() == Aliasee->getType() &&
4381 "declaration exists with different type");
4382 Alias->takeName(Entry);
4383 Entry->replaceAllUsesWith(Alias);
4384 Entry->eraseFromParent();
4386 Alias->setName(MangledName);
4393void ItaniumCXXABI::emitCXXStructor(
GlobalDecl GD) {
4394 auto *MD = cast<CXXMethodDecl>(GD.
getDecl());
4395 auto *CD = dyn_cast<CXXConstructorDecl>(MD);
4408 if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {
4413 if (CGType == StructorCodegen::RAUW) {
4426 CGType != StructorCodegen::COMDAT &&
4444 if (CGType == StructorCodegen::COMDAT) {
4446 llvm::raw_svector_ostream Out(Buffer);
4448 getMangleContext().mangleCXXDtorComdat(DD, Out);
4450 getMangleContext().mangleCXXCtorComdat(CD, Out);
4451 llvm::Comdat *
C = CGM.
getModule().getOrInsertComdat(Out.str());
4460 llvm::FunctionType *FTy = llvm::FunctionType::get(
4468 llvm::FunctionType *FTy =
4469 llvm::FunctionType::get(CGM.
VoidTy,
false);
4476 llvm::FunctionType *FTy = llvm::FunctionType::get(
4496 CallEndCatch(
bool MightThrow) : MightThrow(MightThrow) {}
4516 bool EndMightThrow) {
4517 llvm::CallInst *call =
4540 if (isa<ReferenceType>(CatchType)) {
4545 llvm::Value *AdjustedExn =
CallBeginCatch(CGF, Exn, EndCatchMightThrow);
4550 if (
const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
4559 unsigned HeaderSize =
4562 CGF.
Builder.CreateConstGEP1_32(CGF.
Int8Ty, Exn, HeaderSize);
4585 llvm::Value *Casted = CGF.
Builder.CreateBitCast(AdjustedExn, PtrTy);
4593 llvm::Value *ExnCast =
4594 CGF.
Builder.CreateBitCast(AdjustedExn, LLVMCatchTy,
"exn.byref");
4606 if (CatchType->hasPointerRepresentation()) {
4607 llvm::Value *CastExn =
4608 CGF.
Builder.CreateBitCast(AdjustedExn, LLVMCatchTy,
"exn.casted");
4625 llvm_unreachable(
"bad ownership qualifier!");
4643 llvm_unreachable(
"evaluation kind filtered out!");
4645 llvm_unreachable(
"bad evaluation kind");
4648 assert(isa<RecordType>(CatchType) &&
"unexpected catch type!");
4649 auto catchRD = CatchType->getAsCXXRecordDecl();
4659 Address adjustedExn(CGF.
Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4660 LLVMCatchTy, caughtExnAlignment);
4669 llvm::CallInst *rawAdjustedExn =
4673 Address adjustedExn(CGF.
Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4674 LLVMCatchTy, caughtExnAlignment);
4678 CodeGenFunction::OpaqueValueMapping
4730 VarDecl *CatchParam = S->getExceptionDecl();
4739 InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc());
4749 C.VoidTy, {C.getPointerType(C.CharTy)});
4752 fnTy,
"__clang_call_terminate", llvm::AttributeList(),
true);
4753 llvm::Function *fn =
4754 cast<llvm::Function>(fnRef.getCallee()->stripPointerCasts());
4758 fn->setDoesNotThrow();
4759 fn->setDoesNotReturn();
4764 fn->addFnAttr(llvm::Attribute::NoInline);
4768 fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
4769 fn->setVisibility(llvm::Function::HiddenVisibility);
4771 fn->setComdat(CGM.
getModule().getOrInsertComdat(fn->getName()));
4774 llvm::BasicBlock *entry =
4779 llvm::Value *exn = &*fn->arg_begin();
4782 llvm::CallInst *catchCall = builder.CreateCall(
getBeginCatchFn(CGM), exn);
4783 catchCall->setDoesNotThrow();
4787 llvm::CallInst *termCall = builder.CreateCall(CGM.
getTerminateFn());
4788 termCall->setDoesNotThrow();
4789 termCall->setDoesNotReturn();
4793 builder.CreateUnreachable();
4799ItaniumCXXABI::emitTerminateForUnexpectedException(
CodeGenFunction &CGF,
4809std::pair<llvm::Value *, const CXXRecordDecl *>
4820 ItaniumCXXABI::emitBeginCatch(CGF,
C);
4824WebAssemblyCXXABI::emitTerminateForUnexpectedException(
CodeGenFunction &CGF,
4837 llvm::FunctionCallee Dtor,
4838 llvm::Constant *Addr) {
4843 llvm::FunctionType *AtExitTy =
4844 llvm::FunctionType::get(CGM.
IntTy, {CGM.IntTy, PtrTy},
true);
4847 llvm::FunctionCallee
AtExit =
4855 llvm::Value *NV = llvm::Constant::getNullValue(CGM.
IntTy);
4870 emitCXXStermFinalizer(D, DtorStub, Addr);
4873void XLCXXABI::emitCXXStermFinalizer(
const VarDecl &D, llvm::Function *dtorStub,
4874 llvm::Constant *addr) {
4875 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
4878 llvm::raw_svector_ostream Out(FnName);
4879 getMangleContext().mangleDynamicStermFinalizer(&D, Out);
4899 llvm::Value *NeedsDestruct = CGF.
Builder.CreateIsNull(
V,
"needs_destruct");
4901 llvm::BasicBlock *DestructCallBlock = CGF.
createBasicBlock(
"destruct.call");
4906 CGF.
Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
4911 llvm::CallInst *CI = CGF.
Builder.CreateCall(dtorStub);
4914 CI->setCallingConv(dtorStub->getCallingConv());
4920 if (
auto *IPA = D.
getAttr<InitPriorityAttr>()) {
4922 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 *, std::byte *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.
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
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.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - 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
static CanQual< Type > CreateUnsafe(QualType Other)
Builds a canonical type from a QualType.
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.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
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.
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 bool shouldEmitExactDynamicCast(QualType DestRecordTy)=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 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 llvm::Value * emitExactDynamicCast(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastSuccess, llvm::BasicBlock *CastFail)=0
Emit a dynamic_cast from SrcRecordTy to DestRecordTy.
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 llvm::Value * emitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy)=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 llvm::Value * emitDynamicCastCall(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd)=0
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())