clang: lib/CodeGen/ItaniumCXXABI.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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"
38
39#include
40
41using namespace clang;
42using namespace CodeGen;
43
44namespace {
46
47 llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
48
49
51 ThreadWrappers;
52
53protected:
54 bool UseARMMethodPtrABI;
55 bool UseARMGuardVarABI;
56 bool Use32BitVTableOffsetABI;
57
60 }
61
62public:
64 bool UseARMMethodPtrABI = false,
65 bool UseARMGuardVarABI = false) :
66 CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
67 UseARMGuardVarABI(UseARMGuardVarABI),
68 Use32BitVTableOffsetABI(false) { }
69
71
73
77 }
78
80
81
82 if (isa(GD.getDecl())) {
86 return true;
87
89 return false;
90
92 llvm_unreachable("emitting dtor comdat as function?");
93 }
94 llvm_unreachable("bad dtor kind");
95 }
96 if (isa(GD.getDecl())) {
99 return true;
100
102 return false;
103
106 llvm_unreachable("closure ctors in Itanium ABI?");
107
109 llvm_unreachable("emitting ctor comdat as function?");
110 }
111 llvm_unreachable("bad dtor kind");
112 }
113
114
115 return false;
116 }
117
119
121
126 llvm::Value *&ThisPtrForCall,
127 llvm::Value *MemFnPtr,
129
130 llvm::Value *
133 llvm::Value *MemPtr,
135
138 llvm::Value *Src) override;
140 llvm::Constant *Src) override;
141
143
148 llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD,
150
152 llvm::Value *L, llvm::Value *R,
154 bool Inequality) override;
155
157 llvm::Value *Addr,
159
163
166
168
169 llvm::CallInst *
171 llvm::Value *Exn) override;
172
173 void EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD);
177 QualType CatchHandlerType) override {
179 }
180
185 llvm::Type *StdTypeInfoPtrTy) override;
186
188 QualType SrcRecordTy) override;
189
190
191
192
193
194 bool hasUniqueVTablePointer(QualType RecordTy) {
196
197
198
199 if (!CGM.getCodeGenOpts().AssumeUniqueVTables ||
200 getContext().getLangOpts().AppleKext)
201 return false;
202
203
204
205 if (!CGM.shouldEmitRTTI())
206 return false;
207
208
209
210 if (!llvm::GlobalValue::isWeakForLinker(CGM.getVTableLinkage(RD)))
211 return true;
212
213
214
215
216
217
218 if (CGM.GetLLVMVisibility(RD->getVisibility()) !=
219 llvm::GlobalValue::DefaultVisibility)
220 return false;
221
222 return true;
223 }
224
226 return hasUniqueVTablePointer(DestRecordTy);
227 }
228
232 llvm::BasicBlock *CastEnd) override;
233
237 llvm::BasicBlock *CastSuccess,
238 llvm::BasicBlock *CastFail) override;
239
241 QualType SrcRecordTy) override;
242
244
245 llvm::Value *
249
251
252 AddedStructorArgCounts
255
258
259
260
261 return false;
262 }
263
265
268
270
274 bool ForVirtualBase,
276
280 bool ForVirtualBase,
282
287
290
292 CodeGenFunction::VPtr Vptr) override;
293
295 return true;
296 }
297
298 llvm::Constant *
301
305
306 llvm::Value *getVTableAddressPointInStructorWithVTT(
309
312
314 Address This, llvm::Type *Ty,
316
317 llvm::Value *
320 DeleteOrMemberCallExpr E,
321 llvm::CallBase **CallOrInvoke) override;
322
324
326 bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const;
327
330
331
332 if (ForVTable && !Thunk->hasLocalLinkage())
333 Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
334 CGM.setGVProperties(Thunk, GD);
335 }
336
337 bool exportThunk() override { return true; }
338
342
346
349 assert(!Args.empty() && "expected the arglist to not be empty!");
350 return Args.size() - 1;
351 }
352
355 { return "__cxa_deleted_virtual"; }
356
360 llvm::Value *NumElements,
362 QualType ElementType) override;
366
368 llvm::GlobalVariable *DeclPtr,
369 bool PerformInit) override;
371 llvm::FunctionCallee dtor,
372 llvm::Constant *addr) override;
373
374 llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD,
375 llvm::Value *Val);
381
385 }
388
390
391 llvm::Constant *
392 getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD);
393
394
395
396protected:
397
398
399 virtual bool shouldRTTIBeUnique() const { return true; }
400
401public:
402
403 enum RTTIUniquenessKind {
404
405
406 RUK_Unique,
407
408
409
410 RUK_NonUniqueHidden,
411
412
413
414
415 RUK_NonUniqueVisible
416 };
417
418
419
420 RTTIUniquenessKind
421 classifyRTTIUniqueness(QualType CanTy,
422 llvm::GlobalValue::LinkageTypes Linkage) const;
423 friend class ItaniumRTTIBuilder;
424
426
427 std::pair<llvm::Value *, const CXXRecordDecl *>
430
431 private:
432 llvm::Constant *
433 getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD);
434
435 bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
436 const auto &VtableLayout =
437 CGM.getItaniumVTableContext().getVTableLayout(RD);
438
439 for (const auto &VtableComponent : VtableLayout.vtable_components()) {
440
441 if (!VtableComponent.isUsedFunctionPointerKind())
442 continue;
443
444 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
446 const bool IsInlined =
448 if (!IsInlined)
449 continue;
450
451 StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
452 auto *Entry = CGM.GetGlobalValue(Name);
453
454
455
456
457
458 if (!Entry || Entry->isDeclaration())
459 return true;
460 }
461 return false;
462 }
463
464 bool isVTableHidden(const CXXRecordDecl *RD) const {
465 const auto &VtableLayout =
466 CGM.getItaniumVTableContext().getVTableLayout(RD);
467
468 for (const auto &VtableComponent : VtableLayout.vtable_components()) {
469 if (VtableComponent.isRTTIKind()) {
470 const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();
471 if (RTTIDecl->getVisibility() == Visibility::HiddenVisibility)
472 return true;
473 } else if (VtableComponent.isUsedFunctionPointerKind()) {
474 const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
475 if (Method->getVisibility() == Visibility::HiddenVisibility &&
477 return true;
478 }
479 }
480 return false;
481 }
482};
483
484class ARMCXXABI : public ItaniumCXXABI {
485public:
487 ItaniumCXXABI(CGM, true,
488 true) {}
489
490 bool constructorsAndDestructorsReturnThis() const override { return true; }
491
494
498 llvm::Value *NumElements,
500 QualType ElementType) override;
503};
504
505class AppleARM64CXXABI : public ARMCXXABI {
506public:
508 Use32BitVTableOffsetABI = true;
509 }
510
511
512 bool shouldRTTIBeUnique() const override { return false; }
513};
514
515class FuchsiaCXXABI final : public ItaniumCXXABI {
516public:
518 : ItaniumCXXABI(CGM) {}
519
520private:
521 bool constructorsAndDestructorsReturnThis() const override { return true; }
522};
523
524class WebAssemblyCXXABI final : public ItaniumCXXABI {
525public:
527 : ItaniumCXXABI(CGM, true,
528 true) {}
530 llvm::CallInst *
531 emitTerminateForUnexpectedException(CodeGenFunction &CGF,
532 llvm::Value *Exn) override;
533
534private:
535 bool constructorsAndDestructorsReturnThis() const override { return true; }
536 bool canCallMismatchedFunctionType() const override { return false; }
537};
538
539class XLCXXABI final : public ItaniumCXXABI {
540public:
542 : ItaniumCXXABI(CGM) {}
543
545 llvm::FunctionCallee dtor,
546 llvm::Constant *addr) override;
547
548 bool useSinitAndSterm() const override { return true; }
549
550private:
551 void emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
552 llvm::Constant *addr);
553};
554}
555
558
559
560 case TargetCXXABI::GenericARM:
561 case TargetCXXABI::iOS:
562 case TargetCXXABI::WatchOS:
563 return new ARMCXXABI(CGM);
564
565 case TargetCXXABI::AppleARM64:
566 return new AppleARM64CXXABI(CGM);
567
568 case TargetCXXABI::Fuchsia:
569 return new FuchsiaCXXABI(CGM);
570
571
572
573
574 case TargetCXXABI::GenericAArch64:
575 return new ItaniumCXXABI(CGM, true,
576 true);
577
578 case TargetCXXABI::GenericMIPS:
579 return new ItaniumCXXABI(CGM, true);
580
581 case TargetCXXABI::WebAssembly:
582 return new WebAssemblyCXXABI(CGM);
583
584 case TargetCXXABI::XL:
585 return new XLCXXABI(CGM);
586
587 case TargetCXXABI::GenericItanium:
588 return new ItaniumCXXABI(CGM);
589
590 case TargetCXXABI::Microsoft:
591 llvm_unreachable("Microsoft ABI is not Itanium-based");
592 }
593 llvm_unreachable("bad ABI kind");
594}
595
596llvm::Type *
597ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
599 return CGM.PtrDiffTy;
600 return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);
601}
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
625 llvm::Value *&ThisPtrForCall,
628
631 auto *RD =
633
634 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
635
636 llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual");
637 llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");
638 llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");
639
640
641 llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj");
642
643
644 llvm::Value *Adj = RawAdj;
645 if (UseARMMethodPtrABI)
646 Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
647
648
649
651 This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj);
652 ThisPtrForCall = This;
653
654
655 llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");
656
657
658
659 llvm::Value *IsVirtual;
660 if (UseARMMethodPtrABI)
661 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
662 else
663 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
664 IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual");
665 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
666
667
668
669
671
672
679
680
681
682
683 llvm::Value *VTableOffset = FnAsInt;
684 if (!UseARMMethodPtrABI)
685 VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
686 if (Use32BitVTableOffsetABI) {
687 VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty);
688 VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
689 }
690
691
692
693 llvm::Constant *CheckSourceLocation;
694 llvm::Constant *CheckTypeDesc;
695 bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) &&
696 CGM.HasHiddenLTOVisibility(RD);
697 bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
698 CGM.HasHiddenLTOVisibility(RD);
699 bool ShouldEmitWPDInfo =
700 CGM.getCodeGenOpts().WholeProgramVTables &&
701
702 !CGM.AlwaysHasLTOVisibilityPublic(RD);
703 llvm::Value *VirtualFn = nullptr;
704
705 {
706 CodeGenFunction::SanitizerScope SanScope(&CGF);
707 llvm::Value *TypeId = nullptr;
708 llvm::Value *CheckResult = nullptr;
709
710 if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
711
712
713 llvm::Metadata *MD =
714 CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
715 TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
716 }
717
718 if (ShouldEmitVFEInfo) {
719 llvm::Value *VFPAddr =
720 Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
721
722
723
724
725
726
727 llvm::Value *CheckedLoad = Builder.CreateCall(
728 CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
729 {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
730 CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
731 VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
732 } else {
733
734
735 if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
736 llvm::Value *VFPAddr =
737 Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
738 llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
739 ? llvm::Intrinsic::type_test
740 : llvm::Intrinsic::public_type_test;
741
742 CheckResult =
743 Builder.CreateCall(CGM.getIntrinsic(IID), {VFPAddr, TypeId});
744 }
745
746 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
747 VirtualFn = CGF.Builder.CreateCall(
748 CGM.getIntrinsic(llvm::Intrinsic::load_relative,
749 {VTableOffset->getType()}),
750 {VTable, VTableOffset});
751 } else {
752 llvm::Value *VFPAddr =
756 "memptr.virtualfn");
757 }
758 }
759 assert(VirtualFn && "Virtual fuction pointer not created!");
760 assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
761 CheckResult) &&
762 "Check result required but not created!");
763
764 if (ShouldEmitCFICheck) {
765
768 llvm::Constant *StaticData[] = {
769 llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall),
770 CheckSourceLocation,
771 CheckTypeDesc,
772 };
773
774 if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
775 CGF.EmitTrapCheck(CheckResult, SanitizerHandler::CFICheckFail);
776 } else {
777 llvm::Value *AllVtables = llvm::MetadataAsValue::get(
778 CGM.getLLVMContext(),
779 llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
780 llvm::Value *ValidVtable = Builder.CreateCall(
781 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
782 CGF.EmitCheck(std::make_pair(CheckResult, SanitizerKind::SO_CFIMFCall),
783 SanitizerHandler::CFICheckFail, StaticData,
784 {VTable, ValidVtable});
785 }
786
787 FnVirtual = Builder.GetInsertBlock();
788 }
789 }
790
792
793
794
796 llvm::Value *NonVirtualFn =
797 Builder.CreateIntToPtr(FnAsInt, CGF.UnqualPtrTy, "memptr.nonvirtualfn");
798
799
800 if (ShouldEmitCFICheck) {
803 CodeGenFunction::SanitizerScope SanScope(&CGF);
804
805 llvm::Constant *StaticData[] = {
806 llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_NVMFCall),
807 CheckSourceLocation,
808 CheckTypeDesc,
809 };
810
811 llvm::Value *Bit = Builder.getFalse();
813 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
814 getContext().getMemberPointerType(
817 llvm::Value *TypeId =
818 llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
819
820 llvm::Value *TypeTest =
821 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
822 {NonVirtualFn, TypeId});
823 Bit = Builder.CreateOr(Bit, TypeTest);
824 }
825
826 CGF.EmitCheck(std::make_pair(Bit, SanitizerKind::SO_CFIMFCall),
827 SanitizerHandler::CFICheckFail, StaticData,
828 {NonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)});
829
830 FnNonVirtual = Builder.GetInsertBlock();
831 }
832 }
833
834
836 llvm::PHINode *CalleePtr = Builder.CreatePHI(CGF.UnqualPtrTy, 2);
837 CalleePtr->addIncoming(VirtualFn, FnVirtual);
838 CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
839
841
842 if (const auto &Schema =
843 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers) {
844 llvm::PHINode *DiscriminatorPHI = Builder.CreatePHI(CGF.IntPtrTy, 2);
845 DiscriminatorPHI->addIncoming(llvm::ConstantInt::get(CGF.IntPtrTy, 0),
846 FnVirtual);
847 const auto &AuthInfo =
848 CGM.getMemberFunctionPointerAuthInfo(QualType(MPT, 0));
849 assert(Schema.getKey() == AuthInfo.getKey() &&
850 "Keys for virtual and non-virtual member functions must match");
851 auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator();
852 DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual);
854 Schema.getKey(), Schema.getAuthenticationMode(), Schema.isIsaPointer(),
855 Schema.authenticatesNullValues(), DiscriminatorPHI);
856 }
857
860}
861
862
863
864llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
867 assert(MemPtr->getType() == CGM.PtrDiffTy);
868
870
871
872 return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.emitRawPointer(CGF), MemPtr,
873 "memptr.offset");
874}
875
876
880 const auto *CPA = dyn_castllvm::ConstantPtrAuth(Ptr);
881
882 if (!CPA)
883 return nullptr;
884
885 assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() &&
886 CPA->getAddrDiscriminator()->isZeroValue() &&
888 "unexpected key or discriminators");
889
891 CPA->getPointer(), NewAuthInfo.getKey(), nullptr,
893}
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918llvm::Value *
919ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
921 llvm::Value *src) {
922
923 if (isallvm::Constant(src))
924 return EmitMemberPointerConversion(E, castllvm::Constant(src));
925
926 assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
927 E->getCastKind() == CK_BaseToDerivedMemberPointer ||
928 E->getCastKind() == CK_ReinterpretMemberPointer);
929
932
934 if (const auto &NewAuthInfo =
935 CGM.getMemberFunctionPointerAuthInfo(DstType)) {
938 const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType);
939 llvm::Value *MemFnPtr = Builder.CreateExtractValue(src, 0, "memptr.ptr");
940 llvm::Type *OrigTy = MemFnPtr->getType();
941
942 llvm::BasicBlock *StartBB = Builder.GetInsertBlock();
945
946
947 assert(UseARMMethodPtrABI && "ARM ABI expected");
948 llvm::Value *Adj = Builder.CreateExtractValue(src, 1, "memptr.adj");
949 llvm::Constant *Ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
950 llvm::Value *AndVal = Builder.CreateAnd(Adj, Ptrdiff_1);
951 llvm::Value *IsVirtualOffset =
952 Builder.CreateIsNotNull(AndVal, "is.virtual.offset");
953 Builder.CreateCondBr(IsVirtualOffset, MergeBB, ResignBB);
954
956 llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGM.Int8Ty);
957 MemFnPtr = Builder.CreateIntToPtr(MemFnPtr, PtrTy);
958 MemFnPtr =
960 isallvm::Constant(src));
961 MemFnPtr = Builder.CreatePtrToInt(MemFnPtr, OrigTy);
962 llvm::Value *ResignedVal = Builder.CreateInsertValue(src, MemFnPtr, 0);
963 ResignBB = Builder.GetInsertBlock();
964
966 llvm::PHINode *NewSrc = Builder.CreatePHI(src->getType(), 2);
967 NewSrc->addIncoming(src, StartBB);
968 NewSrc->addIncoming(ResignedVal, ResignBB);
969 src = NewSrc;
970 }
971 }
972
973
974 if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
975
976 llvm::Constant *adj = getMemberPointerAdjustment(E);
977 if (!adj) return src;
978
979 bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
980
983
984
985
987 llvm::Value *dst;
988 if (isDerivedToBase)
989 dst = Builder.CreateNSWSub(src, adj, "adj");
990 else
991 dst = Builder.CreateNSWAdd(src, adj, "adj");
992
993
994 llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType());
995 llvm::Value *isNull = Builder.CreateICmpEQ(src, null, "memptr.isnull");
996 return Builder.CreateSelect(isNull, src, dst);
997 }
998
999
1000 if (UseARMMethodPtrABI) {
1001 uint64_t offset = castllvm::ConstantInt(adj)->getZExtValue();
1002 offset <<= 1;
1003 adj = llvm::ConstantInt::get(adj->getType(), offset);
1004 }
1005
1006 llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1, "src.adj");
1007 llvm::Value *dstAdj;
1008 if (isDerivedToBase)
1009 dstAdj = Builder.CreateNSWSub(srcAdj, adj, "adj");
1010 else
1011 dstAdj = Builder.CreateNSWAdd(srcAdj, adj, "adj");
1012
1013 return Builder.CreateInsertValue(src, dstAdj, 1);
1014}
1015
1016static llvm::Constant *
1021 "member function pointers expected");
1022 if (DestType == SrcType)
1023 return Src;
1024
1027
1028 if (!NewAuthInfo && !CurAuthInfo)
1029 return Src;
1030
1031 llvm::Constant *MemFnPtr = Src->getAggregateElement(0u);
1032 if (MemFnPtr->getNumOperands() == 0) {
1033
1034 assert(isallvm::ConstantInt(MemFnPtr) && "constant int expected");
1035 return Src;
1036 }
1037
1039 castllvm::User(MemFnPtr)->getOperand(0), CurAuthInfo, NewAuthInfo, CGM);
1040 ConstPtr = llvm::ConstantExpr::getPtrToInt(ConstPtr, MemFnPtr->getType());
1041 return ConstantFoldInsertValueInstruction(Src, ConstPtr, 0);
1042}
1043
1044llvm::Constant *
1045ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,
1046 llvm::Constant *src) {
1047 assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
1048 E->getCastKind() == CK_BaseToDerivedMemberPointer ||
1049 E->getCastKind() == CK_ReinterpretMemberPointer);
1050
1052
1055 src, DstType, E->getSubExpr()->getType(), CGM);
1056
1057
1058 if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
1059
1060
1061 llvm::Constant *adj = getMemberPointerAdjustment(E);
1062 if (!adj) return src;
1063
1064 bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
1065
1068
1069
1070
1072
1073 if (src->isAllOnesValue()) return src;
1074
1075 if (isDerivedToBase)
1076 return llvm::ConstantExpr::getNSWSub(src, adj);
1077 else
1078 return llvm::ConstantExpr::getNSWAdd(src, adj);
1079 }
1080
1081
1082 if (UseARMMethodPtrABI) {
1083 uint64_t offset = castllvm::ConstantInt(adj)->getZExtValue();
1084 offset <<= 1;
1085 adj = llvm::ConstantInt::get(adj->getType(), offset);
1086 }
1087
1088 llvm::Constant *srcAdj = src->getAggregateElement(1);
1089 llvm::Constant *dstAdj;
1090 if (isDerivedToBase)
1091 dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);
1092 else
1093 dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);
1094
1095 llvm::Constant *res = ConstantFoldInsertValueInstruction(src, dstAdj, 1);
1096 assert(res != nullptr && "Folding must succeed");
1097 return res;
1098}
1099
1100llvm::Constant *
1101ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
1102
1103
1105 return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, true);
1106
1107 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
1108 llvm::Constant *Values[2] = { Zero, Zero };
1109 return llvm::ConstantStruct::getAnon(Values);
1110}
1111
1112llvm::Constant *
1113ItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
1115
1116
1117
1118 return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity());
1119}
1120
1121llvm::Constant *
1122ItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
1124}
1125
1126llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
1128 assert(MD->isInstance() && "Member function must not be static!");
1129
1131
1132
1133 llvm::Constant *MemPtr[2];
1135 uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
1137 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1138
1139 VTableOffset = Index * 4;
1140 } else {
1141 const ASTContext &Context = getContext();
1144 VTableOffset = Index * PointerWidth.getQuantity();
1145 }
1146
1147 if (UseARMMethodPtrABI) {
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169 const auto &Schema =
1170 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers;
1171 if (Schema)
1172 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(
1173 getSignedVirtualMemberFunctionPointer(MD), CGM.PtrDiffTy);
1174 else
1175 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);
1176
1177
1178 MemPtr[1] = llvm::ConstantInt::get(
1179 CGM.PtrDiffTy, 2 * ThisAdjustment.getQuantity() + !Schema);
1180 } else {
1181
1182
1183
1184
1185 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
1186 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1188 }
1189 } else {
1191 llvm::Type *Ty;
1192
1193 if (Types.isFuncTypeConvertible(FPT)) {
1194
1195 Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
1196 } else {
1197
1198
1199 Ty = CGM.PtrDiffTy;
1200 }
1201 llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty);
1202
1203 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
1204 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1205 (UseARMMethodPtrABI ? 2 : 1) *
1207 }
1208
1209 return llvm::ConstantStruct::getAnon(MemPtr);
1210}
1211
1212llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
1216 if (!MPD)
1217 return EmitNullMemberPointer(MPT);
1218
1220
1221 if (const CXXMethodDecl *MD = dyn_cast(MPD)) {
1222 llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment);
1223 QualType SrcType = getContext().getMemberPointerType(
1226 }
1227
1229 getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
1230 return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
1231}
1232
1233
1234
1235
1236
1237llvm::Value *
1238ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
1239 llvm::Value *L,
1240 llvm::Value *R,
1242 bool Inequality) {
1244
1245 llvm::ICmpInst::Predicate Eq;
1246 llvm::Instruction::BinaryOps And, Or;
1247 if (Inequality) {
1248 Eq = llvm::ICmpInst::ICMP_NE;
1249 And = llvm::Instruction::Or;
1250 Or = llvm::Instruction::And;
1251 } else {
1252 Eq = llvm::ICmpInst::ICMP_EQ;
1253 And = llvm::Instruction::And;
1254 Or = llvm::Instruction::Or;
1255 }
1256
1257
1258
1260 return Builder.CreateICmp(Eq, L, R);
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr");
1273 llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr");
1274
1275
1276
1277 llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr");
1278
1279
1280
1281
1282 llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType());
1283 llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null");
1284
1285
1286
1287 llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj");
1288 llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj");
1289 llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj");
1290
1291
1292
1293 if (UseARMMethodPtrABI) {
1294 llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
1295
1296
1297 llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");
1298 llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
1299 llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,
1300 "cmp.or.adj");
1301 EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
1302 }
1303
1304
1305 llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
1306 Result = Builder.CreateBinOp(And, PtrEq, Result,
1307 Inequality ? "memptr.ne" : "memptr.eq");
1308 return Result;
1309}
1310
1311llvm::Value *
1312ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
1313 llvm::Value *MemPtr,
1316
1317
1319 assert(MemPtr->getType() == CGM.PtrDiffTy);
1320 llvm::Value *NegativeOne =
1321 llvm::Constant::getAllOnesValue(MemPtr->getType());
1322 return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");
1323 }
1324
1325
1326 llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr");
1327
1328 llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
1329 llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool");
1330
1331
1332
1333 if (UseARMMethodPtrABI) {
1334 llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
1335 llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
1336 llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
1337 llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,
1338 "memptr.isvirtual");
1339 Result = Builder.CreateOr(Result, IsVirtual);
1340 }
1341
1342 return Result;
1343}
1344
1345bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
1347 if (!RD)
1348 return false;
1349
1350
1352 auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
1354 return true;
1355 }
1356 return false;
1357}
1358
1359
1360
1361bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
1363}
1364
1365
1366
1367void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
1373 if (UseGlobalDelete) {
1374
1375
1376
1377
1378 auto *ClassDecl =
1381
1382
1383 llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
1384 CGF.IntPtrTy, VTable, -2, "complete-offset.ptr");
1387
1388
1390 CompletePtr =
1392
1393
1394
1396 ElementType);
1397 }
1398
1399
1400
1402 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,
1403 nullptr);
1404
1405 if (UseGlobalDelete)
1407}
1408
1409void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
1410
1411
1412 llvm::FunctionType *FTy =
1413 llvm::FunctionType::get(CGM.VoidTy, false);
1414
1415 llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
1416
1417 if (isNoReturn)
1419 else
1421}
1422
1424
1425
1426 llvm::FunctionType *FTy =
1427 llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, false);
1428
1430}
1431
1433
1434
1435
1437 llvm::FunctionType *FTy =
1438 llvm::FunctionType::get(CGM.VoidTy, Args, false);
1439
1441}
1442
1445
1446 llvm::Type *SizeTy = CGF.ConvertType(getContext().getSizeType());
1447 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
1448
1451 AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception");
1452
1455 E->getSubExpr(), Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
1456
1457
1458 llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
1459 true);
1460
1461
1462
1463 llvm::Constant *Dtor = nullptr;
1466 if (->hasTrivialDestructor()) {
1467
1468
1469
1470 const ASTContext &Ctx = getContext();
1473
1476 Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
1477 }
1478 }
1479 if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1480
1481 llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };
1483}
1484
1486
1487
1488
1489
1490
1491 llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
1493 llvm::Type *PtrDiffTy =
1495
1496 llvm::Type *Args[4] = { Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy };
1497
1498 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
1499
1500
1502 FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
1503 FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
1504 FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
1505 llvm::AttributeList Attrs = llvm::AttributeList::get(
1506 CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
1507
1509}
1510
1512
1513 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
1515}
1516
1517
1518
1522 CXXBasePaths Paths(true, true,
1523 false);
1524
1525
1526
1529
1530 unsigned NumPublicPaths = 0;
1532
1533
1535 if (Path.Access != AS_public)
1536 continue;
1537
1538 ++NumPublicPaths;
1539
1541
1542
1543 if (PathElement.Base->isVirtual())
1545
1546 if (NumPublicPaths > 1)
1547 continue;
1548
1549
1552 PathElement.Base->getType()->getAsCXXRecordDecl());
1553 }
1554 }
1555
1556
1557 if (NumPublicPaths == 0)
1559
1560
1561 if (NumPublicPaths > 1)
1563
1564
1565
1566 return Offset;
1567}
1568
1570
1571 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
1572
1574}
1575
1576bool ItaniumCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {
1577 return true;
1578}
1579
1580void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
1583 Call->setDoesNotReturn();
1584 CGF.Builder.CreateUnreachable();
1585}
1586
1587llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
1590 llvm::Type *StdTypeInfoPtrTy) {
1591 auto *ClassDecl =
1593 llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,
1594 ClassDecl);
1595
1596 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1597
1599 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1600 {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
1601 } else {
1602
1604 CGF.Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy, Value, -1ULL);
1605 }
1608}
1609
1610bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
1612 return SrcIsPtr;
1613}
1614
1615llvm::Value *ItaniumCXXABI::emitDynamicCastCall(
1617 QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
1618 llvm::Type *PtrDiffLTy =
1620
1621 llvm::Value *SrcRTTI =
1623 llvm::Value *DestRTTI =
1625
1626
1629 llvm::Value *OffsetHint = llvm::ConstantInt::get(
1630 PtrDiffLTy,
1632
1633
1635 if (CGM.getCodeGenOpts().PointerAuth.CXXVTablePointers) {
1636
1637
1638
1639
1640
1641 llvm::Value *Vtable =
1642 CGF.GetVTablePtr(ThisAddr, CGM.Int8PtrTy, SrcDecl,
1643 CodeGenFunction::VTableAuthMode::MustTrap);
1644 assert(Vtable);
1645 (void)Vtable;
1646 }
1647
1648 llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint};
1650
1651
1652
1654 llvm::BasicBlock *BadCastBlock =
1656
1658 CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
1659
1661 EmitBadCastCall(CGF);
1662 }
1663
1665}
1666
1667llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
1669 QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastSuccess,
1670 llvm::BasicBlock *CastFail) {
1672
1673
1676 CXXBasePaths Paths(true, true,
1677 false);
1679
1680
1681
1682 std::optional Offset;
1684
1686 continue;
1687
1690
1692 PathElement.Base->getType()->getAsCXXRecordDecl();
1693 if (PathElement.Base->isVirtual()) {
1694
1695
1698 } else {
1702 }
1703 }
1704
1705 if (!Offset)
1706 Offset = PathOffset;
1707 else if (Offset != PathOffset) {
1708
1709
1710
1711
1712 ThisAddr = Address(emitDynamicCastToVoid(CGF, ThisAddr, SrcRecordTy),
1714 SrcDecl = DestDecl;
1716 break;
1717 }
1718 }
1719
1720 if (!Offset) {
1721
1723 return llvm::PoisonValue::get(CGF.VoidPtrTy);
1724 }
1725
1726
1727
1728
1729
1732 CGM.DecorateInstructionWithTBAA(
1733 VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.VoidPtrPtrTy));
1735 VPtr, getVTableAddressPoint(BaseSubobject(SrcDecl, *Offset), DestDecl));
1737 if (!Offset->isZero())
1740 {llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset->getQuantity())});
1741 CGF.Builder.CreateCondBr(Success, CastSuccess, CastFail);
1742 return Result;
1743}
1744
1745llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
1748 auto *ClassDecl =
1750 llvm::Value *OffsetToTop;
1751 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1752
1753 llvm::Value *VTable =
1755
1756
1757 OffsetToTop =
1758 CGF.Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);
1761 } else {
1762 llvm::Type *PtrDiffLTy =
1764
1765
1766 llvm::Value *VTable =
1768
1769
1770 OffsetToTop =
1771 CGF.Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
1773 PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top");
1774 }
1775
1777 OffsetToTop);
1778}
1779
1780bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
1783 Call->setDoesNotReturn();
1784 CGF.Builder.CreateUnreachable();
1785 return true;
1786}
1787
1788llvm::Value *
1789ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
1793 llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
1795 CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
1796 BaseClassDecl);
1797 llvm::Value *VBaseOffsetPtr =
1798 CGF.Builder.CreateConstGEP1_64(
1800 "vbase.offset.ptr");
1801
1802 llvm::Value *VBaseOffset;
1803 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1806 "vbase.offset");
1807 } else {
1809 CGM.PtrDiffTy, VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");
1810 }
1811 return VBaseOffset;
1812}
1813
1815
1816 assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
1817
1818
1819
1821
1822
1823
1824 if (->getParent()->isAbstract()) {
1825
1827 }
1828}
1829
1831ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
1834
1835
1836
1837
1838
1841 cast(GD.getDecl())->getParent()->getNumVBases() != 0) {
1842 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
1844 ArgTys.insert(ArgTys.begin() + 1,
1846 return AddedStructorArgCounts::prefix(1);
1847 }
1848 return AddedStructorArgCounts{};
1849}
1850
1852
1853
1855
1856
1857
1859
1860
1861
1862
1863 if (D->isVirtual())
1865}
1866
1867void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
1871 assert(isa(MD) || isa(MD));
1872
1873
1874 if (NeedsVTTParameter(CGF.CurGD)) {
1876
1877
1878 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
1883 T, ImplicitParamKind::CXXVTT);
1884 Params.insert(Params.begin() + 1, VTTDecl);
1885 getStructorImplicitParamDecl(CGF) = VTTDecl;
1886 }
1887}
1888
1889void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
1890
1892 return;
1893
1894
1895
1896 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
1897
1898
1899 if (getStructorImplicitParamDecl(CGF)) {
1901 CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)), "vtt");
1902 }
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912 if (HasThisReturn(CGF.CurGD))
1914}
1915
1918 bool ForVirtualBase, bool Delegating) {
1920 return AddedStructorArgs{};
1921
1922
1923
1924
1925 llvm::Value *VTT =
1927 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
1928 QualType Q = getContext().getAddrSpaceQualType(getContext().VoidPtrTy, AS);
1929 QualType VTTTy = getContext().getPointerType(Q);
1930 return AddedStructorArgs::prefix({{VTT, VTTTy}});
1931}
1932
1933llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(
1935 bool ForVirtualBase, bool Delegating) {
1938}
1939
1940void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
1946 llvm::Value *VTT =
1948 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
1949
1951 if (getContext().getLangOpts().AppleKext &&
1954 else
1956
1958 ThisTy, VTT, VTTTy, nullptr);
1959}
1960
1961
1962template
1965 if (const auto *FD = dyn_cast(D)) {
1968 continue;
1970 return true;
1971 }
1972 }
1973
1974 return false;
1975}
1976
1978 llvm::GlobalVariable *VTable,
1980 if (VTable->getDLLStorageClass() !=
1981 llvm::GlobalVariable::DefaultStorageClass ||
1982 RD->hasAttr() || RD->hasAttr())
1983 return;
1984
1986 if (CXXRecordNonInlineHasAttr(RD))
1987 VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
1988 } else if (CXXRecordNonInlineHasAttr(RD))
1989 VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1990}
1991
1992void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
1994 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits());
1995 if (VTable->hasInitializer())
1996 return;
1997
2000 llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
2001 llvm::Constant *RTTI =
2002 CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
2003
2004
2006 auto components = builder.beginStruct();
2008 llvm::GlobalValue::isLocalLinkage(Linkage));
2009 components.finishAndSetAsInitializer(VTable);
2010
2011
2012 VTable->setLinkage(Linkage);
2013
2014 if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
2015 VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
2016
2017 if (CGM.getTarget().hasPS4DLLImportExport())
2019
2020
2021 CGM.setGVProperties(VTable, RD);
2022
2023
2024
2025
2029 isa(DC) && cast(DC)->getIdentifier() &&
2030 cast(DC)->getIdentifier()->isStr("__cxxabiv1") &&
2032 EmitFundamentalRTTIDescriptors(RD);
2033
2034
2035
2036
2037
2038
2039 if (!VTable->isDeclarationForLinker() ||
2040 CGM.getCodeGenOpts().WholeProgramVTables) {
2041 CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
2042
2043
2044
2045 if (VTable->isDeclarationForLinker()) {
2046 assert(CGM.getCodeGenOpts().WholeProgramVTables);
2047 CGM.addCompilerUsedGlobal(VTable);
2048 }
2049 }
2050
2053 if (!VTable->isDSOLocal())
2055 }
2056}
2057
2058bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
2060 if (Vptr.NearestVBase == nullptr)
2061 return false;
2062 return NeedsVTTParameter(CGF.CurGD);
2063}
2064
2065llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
2068
2069 if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
2070 NeedsVTTParameter(CGF.CurGD)) {
2071 return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base,
2072 NearestVBase);
2073 }
2074 return getVTableAddressPoint(Base, VTableClass);
2075}
2076
2077llvm::Constant *
2080 llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());
2081
2082
2083
2085 CGM.getItaniumVTableContext().getVTableLayout(VTableClass);
2088 llvm::Value *Indices[] = {
2089 llvm::ConstantInt::get(CGM.Int32Ty, 0),
2090 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
2091 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
2092 };
2093
2094
2095
2096 unsigned ComponentSize =
2097 CGM.getDataLayout().getTypeAllocSize(CGM.getVTableComponentType());
2098 unsigned VTableSize =
2100 unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
2101 llvm::ConstantRange InRange(
2102 llvm::APInt(32, (int)-Offset, true),
2103 llvm::APInt(32, (int)(VTableSize - Offset), true));
2104 return llvm::ConstantExpr::getGetElementPtr(
2105 VTable->getValueType(), VTable, Indices, true, InRange);
2106}
2107
2108llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
2111 assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
2112 NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT");
2113
2114
2115 uint64_t VirtualPointerIndex =
2116 CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
2117
2118
2119 llvm::Value *VTT = CGF.LoadCXXVTT();
2120 if (VirtualPointerIndex)
2122 VirtualPointerIndex);
2123
2124
2125 llvm::Value *AP =
2128
2134 }
2135
2136 return AP;
2137}
2138
2139llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
2141 assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
2142
2143 llvm::GlobalVariable *&VTable = VTables[RD];
2144 if (VTable)
2145 return VTable;
2146
2147
2148 CGM.addDeferredVTable(RD);
2149
2151 llvm::raw_svector_ostream Out(Name);
2152 getMangleContext().mangleCXXVTable(RD, Out);
2153
2155 CGM.getItaniumVTableContext().getVTableLayout(RD);
2156 llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
2157
2158
2159
2160
2161 LangAS AS = CGM.GetGlobalVarAddressSpace(nullptr);
2162 unsigned PAlign = CGM.getItaniumVTableContext().isRelativeLayout()
2163 ? 32
2164 : CGM.getTarget().getPointerAlign(AS);
2165
2166 VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
2167 Name, VTableType, llvm::GlobalValue::ExternalLinkage,
2168 getContext().toCharUnitsFromBits(PAlign).getAsAlign());
2169 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2170
2171 if (CGM.getTarget().hasPS4DLLImportExport())
2173
2174 CGM.setGVProperties(VTable, RD);
2175 return VTable;
2176}
2177
2181 llvm::Type *Ty,
2183 llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy;
2184 auto *MethodDecl = cast(GD.getDecl());
2185 llvm::Value *VTable = CGF.GetVTablePtr(This, PtrTy, MethodDecl->getParent());
2186
2187 uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
2188 llvm::Value *VFunc, *VTableSlotPtr = nullptr;
2189 auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers;
2192 MethodDecl->getParent(), VTable, PtrTy,
2193 VTableIndex *
2194 CGM.getContext().getTargetInfo().getPointerWidth(LangAS::Default) /
2195 8);
2196 } else {
2198
2199 llvm::Value *VFuncLoad;
2200 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
2201 VFuncLoad = CGF.Builder.CreateCall(
2202 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
2203 {VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)});
2204 } else {
2205 VTableSlotPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
2206 PtrTy, VTable, VTableIndex, "vfn");
2209 }
2210
2211
2212
2213
2214
2215
2216
2217 if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2218 CGM.getCodeGenOpts().StrictVTablePointers) {
2219 if (auto *VFuncLoadInstr = dyn_castllvm::Instruction(VFuncLoad)) {
2220 VFuncLoadInstr->setMetadata(
2221 llvm::LLVMContext::MD_invariant_load,
2222 llvm::MDNode::get(CGM.getLLVMContext(),
2224 }
2225 }
2226 VFunc = VFuncLoad;
2227 }
2228
2230 if (Schema) {
2231 assert(VTableSlotPtr && "virtual function pointer not set");
2232 GD = CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl());
2234 }
2237}
2238
2239llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
2241 Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke) {
2244 assert((CE != nullptr) ^ (D != nullptr));
2245 assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
2247
2250 &CGM.getTypes().arrangeCXXStructorDeclaration(GD);
2253
2255 if (CE) {
2256 ThisTy = CE->getObjectType();
2257 } else {
2258 ThisTy = D->getDestroyedType();
2259 }
2260
2262 nullptr, QualType(), nullptr, CallOrInvoke);
2263 return nullptr;
2264}
2265
2266void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
2268 llvm::GlobalVariable *VTT = VTables.GetAddrOfVTT(RD);
2270}
2271
2272bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
2274
2275
2276 if (CGM.getLangOpts().AppleKext)
2277 return false;
2278
2279
2280
2281 if (isVTableHidden(RD))
2282 return false;
2283
2284 if (CGM.getCodeGenOpts().ForceEmitVTables)
2285 return true;
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301 if (hasAnyUnusedVirtualInlineFunction(RD))
2302 return false;
2303
2304
2305
2306
2307
2309 for (const auto &B : RD->bases()) {
2310 auto *BRD = B.getType()->getAsCXXRecordDecl();
2311 assert(BRD && "no class for base specifier");
2312 if (B.isVirtual() || !BRD->isDynamicClass())
2313 continue;
2314 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2315 return false;
2316 }
2317 }
2318
2319 return true;
2320}
2321
2322bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
2323 if (!canSpeculativelyEmitVTableAsBaseClass(RD))
2324 return false;
2325
2327 return false;
2328
2329
2330
2331 for (const auto &B : RD->vbases()) {
2332 auto *BRD = B.getType()->getAsCXXRecordDecl();
2333 assert(BRD && "no class for base specifier");
2334 if (!BRD->isDynamicClass())
2335 continue;
2336 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2337 return false;
2338 }
2339
2340 return true;
2341}
2345 int64_t NonVirtualAdjustment,
2346 int64_t VirtualAdjustment,
2347 bool IsReturnAdjustment) {
2348 if (!NonVirtualAdjustment && !VirtualAdjustment)
2350
2352
2353
2354 if (NonVirtualAdjustment && !IsReturnAdjustment) {
2357 }
2358
2359
2360 llvm::Value *ResultPtr;
2361 if (VirtualAdjustment) {
2362 llvm::Value *VTablePtr =
2364
2365 llvm::Value *Offset;
2366 llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
2367 CGF.Int8Ty, VTablePtr, VirtualAdjustment);
2369
2370 Offset =
2373 } else {
2374 llvm::Type *PtrDiffTy =
2376
2377
2380 }
2381
2383 V.emitRawPointer(CGF), Offset);
2384 } else {
2385 ResultPtr = V.emitRawPointer(CGF);
2386 }
2387
2388
2389
2390 if (NonVirtualAdjustment && IsReturnAdjustment) {
2391 ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.Int8Ty, ResultPtr,
2392 NonVirtualAdjustment);
2393 }
2394
2395 return ResultPtr;
2396}
2397
2398llvm::Value *
2404 false);
2405}
2406
2407llvm::Value *
2413 true);
2414}
2415
2416void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
2418 if (!isa(CGF.CurGD.getDecl()))
2419 return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
2420
2421
2424 return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
2425}
2426
2427
2428
2429CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2430
2431
2433 CGM.getContext().getPreferredTypeAlignInChars(elementType));
2434}
2435
2438 llvm::Value *NumElements,
2441 assert(requiresArrayCookie(expr));
2442
2444
2447
2448
2451 assert(CookieSize == getArrayCookieSizeImpl(ElementType));
2452
2453
2454 Address CookiePtr = NewPtr;
2455 CharUnits CookieOffset = CookieSize - SizeSize;
2456 if (!CookieOffset.isZero())
2458
2459
2461 llvm::Instruction *SI = CGF.Builder.CreateStore(NumElements, NumElementsPtr);
2462
2463
2464 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
2465 (expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||
2466 CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {
2467
2468 SI->setNoSanitizeMetadata();
2469 llvm::FunctionType *FTy =
2470 llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false);
2471 llvm::FunctionCallee F =
2472 CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie");
2474 }
2475
2476
2477
2479}
2480
2481llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2484
2485 Address numElementsPtr = allocPtr;
2487 if (!numElementsOffset.isZero())
2488 numElementsPtr =
2490
2493 if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0)
2495
2496
2497
2498
2499
2500 llvm::FunctionType *FTy =
2502 llvm::FunctionCallee F =
2503 CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie");
2505}
2506
2507CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2508
2509
2510
2511
2512
2513
2514
2515
2517 CGM.getContext().getTypeAlignInChars(elementType));
2518}
2519
2522 llvm::Value *numElements,
2525 assert(requiresArrayCookie(expr));
2526
2527
2528 Address cookie = newPtr;
2529
2530
2532 llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,
2533 getContext().getTypeSizeInChars(elementType).getQuantity());
2535
2536
2539
2540
2541
2542 CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
2544}
2545
2546llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2549
2550
2553
2556}
2557
2558
2559
2561 llvm::PointerType *GuardPtrTy) {
2562
2563 llvm::FunctionType *FTy =
2565 GuardPtrTy, false);
2567 FTy, "__cxa_guard_acquire",
2569 llvm::AttributeList::FunctionIndex,
2570 llvm::Attribute::NoUnwind));
2571}
2572
2574 llvm::PointerType *GuardPtrTy) {
2575
2576 llvm::FunctionType *FTy =
2577 llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, false);
2579 FTy, "__cxa_guard_release",
2581 llvm::AttributeList::FunctionIndex,
2582 llvm::Attribute::NoUnwind));
2583}
2584
2586 llvm::PointerType *GuardPtrTy) {
2587
2588 llvm::FunctionType *FTy =
2589 llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, false);
2591 FTy, "__cxa_guard_abort",
2593 llvm::AttributeList::FunctionIndex,
2594 llvm::Attribute::NoUnwind));
2595}
2596
2597namespace {
2599 llvm::GlobalVariable *Guard;
2600 CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
2601
2604 Guard);
2605 }
2606 };
2607}
2608
2609
2610
2611void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
2613 llvm::GlobalVariable *var,
2614 bool shouldPerformInit) {
2616
2617
2618
2619 bool NonTemplateInline =
2620 D.isInline() &&
2622
2623
2624
2625
2626 bool threadsafe = getContext().getLangOpts().ThreadsafeStatics &&
2627 (D.isLocalVarDecl() || NonTemplateInline) &&
2628 .getTLSKind();
2629
2630
2631
2632 bool useInt8GuardVariable = !threadsafe && var->hasInternalLinkage();
2633
2634 llvm::IntegerType *guardTy;
2636 if (useInt8GuardVariable) {
2637 guardTy = CGF.Int8Ty;
2639 } else {
2640
2641
2642 if (UseARMGuardVarABI) {
2643 guardTy = CGF.SizeTy;
2645 } else {
2647 guardAlignment =
2649 }
2650 }
2651 llvm::PointerType *guardPtrTy = llvm::PointerType::get(
2654
2655
2656
2657 llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D);
2658 if (!guard) {
2659
2661 {
2662 llvm::raw_svector_ostream out(guardName);
2663 getMangleContext().mangleStaticGuardVariable(&D, out);
2664 }
2665
2666
2667
2668
2669 guard = new llvm::GlobalVariable(CGM.getModule(), guardTy,
2670 false, var->getLinkage(),
2671 llvm::ConstantInt::get(guardTy, 0),
2672 guardName.str());
2673 guard->setDSOLocal(var->isDSOLocal());
2674 guard->setVisibility(var->getVisibility());
2675 guard->setDLLStorageClass(var->getDLLStorageClass());
2676
2677 guard->setThreadLocalMode(var->getThreadLocalMode());
2678 guard->setAlignment(guardAlignment.getAsAlign());
2679
2680
2681
2682
2683 llvm::Comdat *C = var->getComdat();
2684 if (.isLocalVarDecl() && C &&
2685 (CGM.getTarget().getTriple().isOSBinFormatELF() ||
2686 CGM.getTarget().getTriple().isOSBinFormatWasm())) {
2687 guard->setComdat(C);
2688 } else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
2689 guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));
2690 }
2691
2692 CGM.setStaticLocalDeclGuardAddress(&D, guard);
2693 }
2694
2695 Address guardAddr = Address(guard, guard->getValueType(), guardAlignment);
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2719 llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end");
2720 if (!threadsafe || MaxInlineWidthInBits) {
2721
2722 llvm::LoadInst *LI =
2723 Builder.CreateLoad(guardAddr.withElementType(CGM.Int8Ty));
2724
2725
2726
2727
2728
2729
2730
2731 if (threadsafe)
2732 LI->setAtomic(llvm::AtomicOrdering::Acquire);
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754 llvm::Value *V =
2755 (UseARMGuardVarABI && !useInt8GuardVariable)
2756 ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
2757 : LI;
2758 llvm::Value *NeedsInit = Builder.CreateIsNull(V, "guard.uninitialized");
2759
2760 llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check");
2761
2762
2764 CodeGenFunction::GuardKind::VariableGuard, &D);
2765
2767 }
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785 if (threadsafe) {
2786
2787 llvm::Value *V
2789
2791
2792 Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
2793 InitBlock, EndBlock);
2794
2795
2797
2799 } else if (.isLocalVarDecl()) {
2800
2801
2802
2803 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2805 }
2806
2807
2809
2810 if (threadsafe) {
2811
2813
2814
2817 } else if (D.isLocalVarDecl()) {
2818
2819
2820
2821 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2823 }
2824
2826}
2827
2828
2830 llvm::FunctionCallee dtor,
2831 llvm::Constant *addr, bool TLS) {
2833 "unexpected call to emitGlobalDtorWithCXAAtExit");
2835 "__cxa_atexit is disabled");
2836 const char *Name = "__cxa_atexit";
2837 if (TLS) {
2839 Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit";
2840 }
2841
2842
2843
2845
2846
2847 auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0;
2848 auto AddrPtrTy = AddrAS ? llvm::PointerType::get(CGF.getLLVMContext(), AddrAS)
2850
2851
2852 llvm::Constant *handle =
2854 auto *GV = castllvm::GlobalValue(handle->stripPointerCasts());
2855 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
2856
2857
2858 llvm::Type *paramTys[] = {dtorTy, AddrPtrTy, handle->getType()};
2859 llvm::FunctionType *atexitTy =
2860 llvm::FunctionType::get(CGF.IntTy, paramTys, false);
2861
2862
2864 if (llvm::Function *fn = dyn_castllvm::Function(atexit.getCallee()))
2865 fn->setDoesNotThrow();
2866
2869 false, false));
2872 llvm::Constant *dtorCallee = castllvm::Constant(dtor.getCallee());
2874
2875 if (!addr)
2876
2877
2878
2879
2880 addr = llvm::Constant::getNullValue(CGF.Int8PtrTy);
2881
2882 llvm::Value *args[] = {dtorCallee, addr, handle};
2884}
2885
2887 StringRef FnName) {
2888
2889
2890 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
2893
2894 return GlobalInitOrCleanupFn;
2895}
2896
2897void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {
2898 for (const auto &I : DtorsUsingAtExit) {
2900 std::string GlobalCleanupFnName =
2901 std::string("__GLOBAL_cleanup_") + llvm::to_string(Priority);
2902
2903 llvm::Function *GlobalCleanupFn =
2905
2911
2912
2913 llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.VoidTy, false);
2914
2915
2916
2917 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2918 auto itv = Dtors.rbegin();
2919 while (itv != Dtors.rend()) {
2920 llvm::Function *Dtor = *itv;
2921
2922
2923
2925 llvm::Value *NeedsDestruct =
2927
2928 llvm::BasicBlock *DestructCallBlock =
2931 (itv + 1) != Dtors.rend() ? "unatexit.call" : "destruct.end");
2932
2933
2934 CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
2935
2936 CGF.EmitBlock(DestructCallBlock);
2937
2938
2939 llvm::CallInst *CI = CGF.Builder.CreateCall(dtorFuncTy, Dtor);
2940
2941 CI->setCallingConv(Dtor->getCallingConv());
2942
2944
2945 itv++;
2946 }
2947
2950 }
2951}
2952
2953void CodeGenModule::registerGlobalDtorsWithAtExit() {
2954 for (const auto &I : DtorsUsingAtExit) {
2956 std::string GlobalInitFnName =
2957 std::string("__GLOBAL_init_") + llvm::to_string(Priority);
2958 llvm::Function *GlobalInitFn =
2960
2966
2967
2968
2969
2970
2971
2972 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
2973 for (auto *Dtor : Dtors) {
2974
2975
2978 } else {
2979
2980
2982 }
2983 }
2984
2987 }
2988
2989 if (getCXXABI().useSinitAndSterm())
2990 unregisterGlobalDtorsWithUnAtExit();
2991}
2992
2993
2995 llvm::FunctionCallee dtor,
2996 llvm::Constant *addr) {
2997 if (D.isNoDestroy(CGM.getContext()))
2998 return;
2999
3000
3001 if (CGM.getLangOpts().HLSL)
3002 return CGM.AddCXXDtorEntry(dtor, addr);
3003
3004
3005
3006
3007
3008
3009 if (!CGM.getLangOpts().hasAtExit() && .isStaticLocal())
3011
3012
3013
3014
3015
3016 if (CGM.getCodeGenOpts().CXAAtExit || D.getTLSKind())
3018
3019
3020
3021 if (CGM.getLangOpts().AppleKext) {
3022
3023 return CGM.AddCXXDtorEntry(dtor, addr);
3024 }
3025
3027}
3028
3031 assert(!VD->isStaticLocal() && "static local VarDecls don't need wrappers!");
3032
3033
3036}
3037
3038
3039
3040
3041static llvm::GlobalValue::LinkageTypes
3043 llvm::GlobalValue::LinkageTypes VarLinkage =
3045
3046
3047 if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
3048 return VarLinkage;
3049
3050
3052 if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
3053 !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
3054 return VarLinkage;
3055 return llvm::GlobalValue::WeakODRLinkage;
3056}
3057
3058llvm::Function *
3059ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
3060 llvm::Value *Val) {
3061
3063 {
3064 llvm::raw_svector_ostream Out(WrapperName);
3065 getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);
3066 }
3067
3068
3069
3070 if (llvm::Value *V = CGM.getModule().getNamedValue(WrapperName))
3071 return castllvm::Function(V);
3072
3076
3077 const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
3079
3080 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI);
3081 llvm::Function *Wrapper =
3083 WrapperName.str(), &CGM.getModule());
3084
3085 if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())
3086 Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));
3087
3088 CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper, false);
3089
3090
3091 if (!Wrapper->hasLocalLinkage())
3093 llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
3094 llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
3096 Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
3097
3099 Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3100 Wrapper->addFnAttr(llvm::Attribute::NoUnwind);
3101 }
3102
3103 ThreadWrappers.push_back({VD, Wrapper});
3104 return Wrapper;
3105}
3106
3107void ItaniumCXXABI::EmitThreadLocalInitFuncs(
3111 llvm::Function *InitFunc = nullptr;
3112
3113
3114
3116 llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;
3117 for (unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {
3120 UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =
3121 CXXThreadLocalInits[I];
3122 else
3123 OrderedInits.push_back(CXXThreadLocalInits[I]);
3124 }
3125
3126 if (!OrderedInits.empty()) {
3127
3128 llvm::FunctionType *FTy =
3129 llvm::FunctionType::get(CGM.VoidTy, false);
3133 true);
3134 llvm::GlobalVariable *Guard = new llvm::GlobalVariable(
3136 llvm::GlobalVariable::InternalLinkage,
3137 llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard");
3138 Guard->setThreadLocal(true);
3140
3142 Guard->setAlignment(GuardAlign.getAsAlign());
3143
3146
3148 InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3149 InitFunc->addFnAttr(llvm::Attribute::NoUnwind);
3150 }
3151 }
3152
3153
3154
3155 for (const VarDecl *VD : CXXThreadLocals) {
3159 getOrCreateThreadLocalWrapper(VD, GV);
3160 }
3161 }
3162
3163
3164 for (auto VDAndWrapper : ThreadWrappers) {
3165 const VarDecl *VD = VDAndWrapper.first;
3166 llvm::GlobalVariable *Var =
3168 llvm::Function *Wrapper = VDAndWrapper.second;
3169
3170
3171
3172
3175 Wrapper->setLinkage(llvm::Function::ExternalLinkage);
3176 continue;
3177 }
3178
3179
3180
3181 if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)
3182 Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);
3183 }
3184
3186
3187
3189 {
3190 llvm::raw_svector_ostream Out(InitFnName);
3191 getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
3192 }
3193
3194 llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.VoidTy, false);
3195
3196
3197
3198
3199 llvm::GlobalValue *Init = nullptr;
3200 bool InitIsInitFunc = false;
3201 bool HasConstantInitialization = false;
3202 if (!usesThreadWrapperFunction(VD)) {
3203 HasConstantInitialization = true;
3205 InitIsInitFunc = true;
3206 llvm::Function *InitFuncToUse = InitFunc;
3208 InitFuncToUse = UnorderedInits.lookup(VD->getCanonicalDecl());
3209 if (InitFuncToUse)
3210 Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),
3211 InitFuncToUse);
3212 } else {
3213
3214
3215
3216
3217 Init = llvm::Function::Create(InitFnTy,
3218 llvm::GlobalVariable::ExternalWeakLinkage,
3219 InitFnName.str(), &CGM.getModule());
3222 GlobalDecl(), FI, castllvm::Function(Init), false);
3223 }
3224
3226 Init->setVisibility(Var->getVisibility());
3227
3228 if (!CGM.getTriple().isOSWindows() || ->hasExternalWeakLinkage())
3229 Init->setDSOLocal(Var->isDSOLocal());
3230 }
3231
3232 llvm::LLVMContext &Context = CGM.getModule().getContext();
3233
3234
3235
3236
3237
3238
3240 isEmittedWithConstantInitializer(VD, true) &&
3241 !mayNeedDestruction(VD)) {
3242
3243
3244
3245
3246 assert(Init == nullptr && "Expected Init to be null.");
3247
3248 llvm::Function *Func = llvm::Function::Create(
3249 InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.getModule());
3252 castllvm::Function(Func),
3253 false);
3254
3255 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Func);
3257 Builder.CreateRetVoid();
3258 }
3259
3260 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);
3262 if (HasConstantInitialization) {
3263
3264 } else if (InitIsInitFunc) {
3266 llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy, Init);
3268 CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3269 llvm::Function *Fn =
3270 castllvm::Function(castllvm::GlobalAlias(Init)->getAliasee());
3271 Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3272 }
3273 }
3274 } else if (CGM.getTriple().isOSAIX()) {
3275
3276
3277
3278
3279
3280
3281
3282 Builder.CreateCall(InitFnTy, Init);
3283 } else {
3284
3285 llvm::Value *Have = Builder.CreateIsNotNull(Init);
3286 llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context, "", Wrapper);
3287 llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context, "", Wrapper);
3288 Builder.CreateCondBr(Have, InitBB, ExitBB);
3289
3290 Builder.SetInsertPoint(InitBB);
3291 Builder.CreateCall(InitFnTy, Init);
3292 Builder.CreateBr(ExitBB);
3293
3294 Builder.SetInsertPoint(ExitBB);
3295 }
3296
3297
3298
3299 llvm::Value *Val = Builder.CreateThreadLocalAddress(Var);
3300
3303 Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align);
3304 }
3305 Val = Builder.CreateAddrSpaceCast(Val, Wrapper->getReturnType());
3306
3307 Builder.CreateRet(Val);
3308 }
3309}
3310
3315 llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
3316
3317 llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper);
3318 CallVal->setCallingConv(Wrapper->getCallingConv());
3319
3323 else
3326
3327 return LV;
3328}
3329
3330
3331
3332bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {
3334
3335
3337 return false;
3338
3339
3341 return true;
3342
3343
3345 return true;
3346
3347 return false;
3348}
3349
3350llvm::Constant *
3351ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) {
3353 llvm::raw_svector_ostream Out(MethodName);
3354 getMangleContext().mangleCXXName(MD, Out);
3355 MethodName += "_vfpthunk_";
3356 StringRef ThunkName = MethodName.str();
3357 llvm::Function *ThunkFn;
3358 if ((ThunkFn = cast_or_nullllvm::Function(
3359 CGM.getModule().getNamedValue(ThunkName))))
3360 return ThunkFn;
3361
3364 llvm::GlobalValue::LinkageTypes Linkage =
3366 : llvm::GlobalValue::InternalLinkage;
3367 ThunkFn =
3368 llvm::Function::Create(ThunkTy, Linkage, ThunkName, &CGM.getModule());
3369 if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
3370 ThunkFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
3371 assert(ThunkFn->getName() == ThunkName && "name was uniqued!");
3372
3375
3376
3377 ThunkFn->removeFnAttr(llvm::Attribute::StackProtect);
3378 ThunkFn->removeFnAttr(llvm::Attribute::StackProtectStrong);
3379 ThunkFn->removeFnAttr(llvm::Attribute::StackProtectReq);
3380
3381
3385
3386
3389
3392 llvm::Value *ThisVal = loadIncomingCXXThis(CGF);
3393 setCXXABIThisValue(CGF, ThisVal);
3394
3396 for (const VarDecl *VD : FunctionArgs)
3398
3404 getThisAddress(CGF), ThunkTy);
3405 llvm::CallBase *CallOrInvoke;
3408 auto *Call = castllvm::CallInst(CallOrInvoke);
3409 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
3410 if (Call->getType()->isVoidTy())
3411 CGF.Builder.CreateRetVoid();
3412 else
3414
3415
3416
3419 return ThunkFn;
3420}
3421
3422namespace {
3423class ItaniumRTTIBuilder {
3425 llvm::LLVMContext &VMContext;
3426 const ItaniumCXXABI &CXXABI;
3427
3428
3430
3431
3432 llvm::GlobalVariable *
3433 GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
3434
3435
3436
3437 llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
3438
3439
3440 void BuildVTablePointer(const Type *Ty, llvm::Constant *StorageAddress);
3441
3442
3443
3444 void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
3445
3446
3447
3448
3449 void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
3450
3451
3452
3453 void BuildPointerTypeInfo(QualType PointeeTy);
3454
3455
3456
3457 void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
3458
3459
3460
3462
3463public:
3464 ItaniumRTTIBuilder(const ItaniumCXXABI &ABI)
3465 : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {}
3466
3467
3468 enum {
3469
3470 PTI_Const = 0x1,
3471
3472
3473 PTI_Volatile = 0x2,
3474
3475
3476 PTI_Restrict = 0x4,
3477
3478
3479 PTI_Incomplete = 0x8,
3480
3481
3482
3483 PTI_ContainingClassIncomplete = 0x10,
3484
3485
3486
3487
3488
3489 PTI_Noexcept = 0x40,
3490 };
3491
3492
3493 enum {
3494
3495 VMI_NonDiamondRepeat = 0x1,
3496
3497
3498 VMI_DiamondShaped = 0x2
3499 };
3500
3501
3502 enum {
3503
3504 BCTI_Virtual = 0x1,
3505
3506
3507 BCTI_Public = 0x2
3508 };
3509
3510
3511
3512 llvm::Constant *BuildTypeInfo(QualType Ty);
3513
3514
3515 llvm::Constant *BuildTypeInfo(
3517 llvm::GlobalVariable::LinkageTypes Linkage,
3518 llvm::GlobalValue::VisibilityTypes Visibility,
3519 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
3520};
3521}
3522
3523llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
3524 QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {
3526 llvm::raw_svector_ostream Out(Name);
3528
3529
3530
3531
3532 llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
3533 Name.substr(4));
3535
3538
3539 GV->setInitializer(Init);
3540
3541 return GV;
3542}
3543
3544llvm::Constant *
3545ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
3546
3548 llvm::raw_svector_ostream Out(Name);
3550
3551
3552 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
3553
3554 if (!GV) {
3555
3556
3557
3558
3559 GV = new llvm::GlobalVariable(
3561 true, llvm::GlobalValue::ExternalLinkage, nullptr, Name);
3564
3565
3567 if (RD && CXXRecordNonInlineHasAttr(RD)) {
3568 GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
3570 }
3571 }
3572 }
3573
3574 return GV;
3575}
3576
3577
3578
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594 switch (Ty->getKind()) {
3595 case BuiltinType::Void:
3596 case BuiltinType::NullPtr:
3597 case BuiltinType::Bool:
3598 case BuiltinType::WChar_S:
3599 case BuiltinType::WChar_U:
3600 case BuiltinType::Char_U:
3601 case BuiltinType::Char_S:
3602 case BuiltinType::UChar:
3603 case BuiltinType::SChar:
3604 case BuiltinType::Short:
3605 case BuiltinType::UShort:
3606 case BuiltinType::Int:
3607 case BuiltinType::UInt:
3608 case BuiltinType::Long:
3609 case BuiltinType::ULong:
3610 case BuiltinType::LongLong:
3611 case BuiltinType::ULongLong:
3612 case BuiltinType::Half:
3613 case BuiltinType::Float:
3614 case BuiltinType::Double:
3615 case BuiltinType::LongDouble:
3616 case BuiltinType::Float16:
3617 case BuiltinType::Float128:
3618 case BuiltinType::Ibm128:
3619 case BuiltinType::Char8:
3620 case BuiltinType::Char16:
3621 case BuiltinType::Char32:
3622 case BuiltinType::Int128:
3623 case BuiltinType::UInt128:
3624 return true;
3625
3626#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
3627 case BuiltinType::Id:
3628#include "clang/Basic/OpenCLImageTypes.def"
3629#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
3630 case BuiltinType::Id:
3631#include "clang/Basic/OpenCLExtensionTypes.def"
3632 case BuiltinType::OCLSampler:
3633 case BuiltinType::OCLEvent:
3634 case BuiltinType::OCLClkEvent:
3635 case BuiltinType::OCLQueue:
3636 case BuiltinType::OCLReserveID:
3637#define SVE_TYPE(Name, Id, SingletonId) \
3638 case BuiltinType::Id:
3639#include "clang/Basic/AArch64SVEACLETypes.def"
3640#define PPC_VECTOR_TYPE(Name, Id, Size) \
3641 case BuiltinType::Id:
3642#include "clang/Basic/PPCTypes.def"
3643#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3644#include "clang/Basic/RISCVVTypes.def"
3645#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3646#include "clang/Basic/WebAssemblyReferenceTypes.def"
3647#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
3648#include "clang/Basic/AMDGPUTypes.def"
3649#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3650#include "clang/Basic/HLSLIntangibleTypes.def"
3651 case BuiltinType::ShortAccum:
3652 case BuiltinType::Accum:
3653 case BuiltinType::LongAccum:
3654 case BuiltinType::UShortAccum:
3655 case BuiltinType::UAccum:
3656 case BuiltinType::ULongAccum:
3657 case BuiltinType::ShortFract:
3658 case BuiltinType::Fract:
3659 case BuiltinType::LongFract:
3660 case BuiltinType::UShortFract:
3661 case BuiltinType::UFract:
3662 case BuiltinType::ULongFract:
3663 case BuiltinType::SatShortAccum:
3664 case BuiltinType::SatAccum:
3665 case BuiltinType::SatLongAccum:
3666 case BuiltinType::SatUShortAccum:
3667 case BuiltinType::SatUAccum:
3668 case BuiltinType::SatULongAccum:
3669 case BuiltinType::SatShortFract:
3670 case BuiltinType::SatFract:
3671 case BuiltinType::SatLongFract:
3672 case BuiltinType::SatUShortFract:
3673 case BuiltinType::SatUFract:
3674 case BuiltinType::SatULongFract:
3675 case BuiltinType::BFloat16:
3676 return false;
3677
3678 case BuiltinType::Dependent:
3679#define BUILTIN_TYPE(Id, SingletonId)
3680#define PLACEHOLDER_TYPE(Id, SingletonId) \
3681 case BuiltinType::Id:
3682#include "clang/AST/BuiltinTypes.def"
3683 llvm_unreachable("asking for RRTI for a placeholder type!");
3684
3685 case BuiltinType::ObjCId:
3686 case BuiltinType::ObjCClass:
3687 case BuiltinType::ObjCSel:
3688 llvm_unreachable("FIXME: Objective-C types are unsupported!");
3689 }
3690
3691 llvm_unreachable("Invalid BuiltinType Kind!");
3692}
3693
3696 const BuiltinType *BuiltinTy = dyn_cast(PointeeTy);
3697 if (!BuiltinTy)
3698 return false;
3699
3700
3703
3704 if (!Quals.empty())
3705 return false;
3706
3708}
3709
3710
3711
3713
3714 if (const BuiltinType *BuiltinTy = dyn_cast(Ty))
3716
3717
3718
3719 if (const PointerType *PointerTy = dyn_cast(Ty))
3721
3722 return false;
3723}
3724
3725
3726
3727
3728
3732
3733
3734
3735 if (!Context.getLangOpts().RTTI) return false;
3736
3737 if (const RecordType *RecordTy = dyn_cast(Ty)) {
3738 const CXXRecordDecl *RD = cast(RecordTy->getDecl());
3740 return false;
3741
3743 return false;
3744
3745
3746
3747
3748
3749 bool IsDLLImport = RD->hasAttr();
3750
3751
3752 if (CGM.getTriple().isWindowsGNUEnvironment())
3753 return false;
3754
3757 return true;
3758
3759 return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment()
3761 : true;
3762 }
3763 if (IsDLLImport)
3764 return true;
3765 }
3766
3767 return false;
3768}
3769
3770
3773}
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3787 if (const RecordType *RecordTy = dyn_cast(Ty)) {
3789 return true;
3790 }
3791
3792 if (const PointerType *PointerTy = dyn_cast(Ty))
3794
3796 dyn_cast(Ty)) {
3797
3798 const RecordType *ClassType = cast(MemberPointerTy->getClass());
3800 return true;
3801
3803 }
3804
3805 return false;
3806}
3807
3808
3809
3810
3812
3814 return false;
3815
3816
3818
3819
3820 if (Base->isVirtual())
3821 return false;
3822
3823
3825 return false;
3826
3827
3828 auto *BaseDecl =
3830 if (!BaseDecl->isEmpty() &&
3832 return false;
3833
3834 return true;
3835}
3836
3837void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
3838 llvm::Constant *StorageAddress) {
3839
3840 static const char * const ClassTypeInfo =
3841 "_ZTVN10__cxxabiv117__class_type_infoE";
3842
3843 static const char * const SIClassTypeInfo =
3844 "_ZTVN10__cxxabiv120__si_class_type_infoE";
3845
3846 static const char * const VMIClassTypeInfo =
3847 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
3848
3849 const char *VTableName = nullptr;
3850
3852#define TYPE(Class, Base)
3853#define ABSTRACT_TYPE(Class, Base)
3854#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3855#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3856#define DEPENDENT_TYPE(Class, Base) case Type::Class:
3857#include "clang/AST/TypeNodes.inc"
3858 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
3859
3860 case Type::LValueReference:
3861 case Type::RValueReference:
3862 llvm_unreachable("References shouldn't get here");
3863
3864 case Type::Auto:
3865 case Type::DeducedTemplateSpecialization:
3866 llvm_unreachable("Undeduced type shouldn't get here");
3867
3868 case Type::Pipe:
3869 llvm_unreachable("Pipe types shouldn't get here");
3870
3871 case Type::ArrayParameter:
3872 llvm_unreachable("Array Parameter types should not get here.");
3873
3874 case Type::Builtin:
3875 case Type::BitInt:
3876
3877 case Type::Vector:
3878 case Type::ExtVector:
3879 case Type::ConstantMatrix:
3880 case Type::Complex:
3881 case Type::Atomic:
3882
3883 case Type::BlockPointer:
3884
3885 VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
3886 break;
3887
3888 case Type::ConstantArray:
3889 case Type::IncompleteArray:
3890 case Type::VariableArray:
3891
3892 VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
3893 break;
3894
3895 case Type::FunctionNoProto:
3896 case Type::FunctionProto:
3897
3898 VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
3899 break;
3900
3901 case Type::Enum:
3902
3903 VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
3904 break;
3905
3906 case Type::Record: {
3908 cast(cast(Ty)->getDecl());
3909
3911 VTableName = ClassTypeInfo;
3913 VTableName = SIClassTypeInfo;
3914 } else {
3915 VTableName = VMIClassTypeInfo;
3916 }
3917
3918 break;
3919 }
3920
3921 case Type::ObjCObject:
3922
3923 Ty = cast(Ty)->getBaseType().getTypePtr();
3924
3925
3926 if (isa(Ty)) {
3927 VTableName = ClassTypeInfo;
3928 break;
3929 }
3930
3931 assert(isa(Ty));
3932 [[fallthrough]];
3933
3934 case Type::ObjCInterface:
3935 if (cast(Ty)->getDecl()->getSuperClass()) {
3936 VTableName = SIClassTypeInfo;
3937 } else {
3938 VTableName = ClassTypeInfo;
3939 }
3940 break;
3941
3942 case Type::ObjCObjectPointer:
3943 case Type::Pointer:
3944
3945 VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
3946 break;
3947
3948 case Type::MemberPointer:
3949
3950 VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
3951 break;
3952
3953 case Type::HLSLAttributedResource:
3954 llvm_unreachable("HLSL doesn't support virtual functions");
3955 }
3956
3957 llvm::Constant *VTable = nullptr;
3958
3959
3961 VTable = CGM.getModule().getNamedAlias(VTableName);
3962 if (!VTable) {
3963 llvm::Type *Ty = llvm::ArrayType::get(CGM.GlobalsInt8PtrTy, 0);
3964 VTable = CGM.getModule().getOrInsertGlobal(VTableName, Ty);
3965 }
3966
3967 CGM.setDSOLocal(castllvm::GlobalValue(VTable->stripPointerCasts()));
3968
3969 llvm::Type *PtrDiffTy =
3971
3972
3974
3975
3976 llvm::Constant *Eight = llvm::ConstantInt::get(CGM.Int32Ty, 8);
3977 VTable =
3978 llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.Int8Ty, VTable, Eight);
3979 } else {
3980 llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
3981 VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.GlobalsInt8PtrTy,
3982 VTable, Two);
3983 }
3984
3985 if (const auto &Schema =
3988 VTable, Schema,
3989 Schema.isAddressDiscriminated() ? StorageAddress : nullptr,
3991
3992 Fields.push_back(VTable);
3993}
3994
3995
3996
3999
4000
4001
4002
4003
4004
4005
4006
4007
4009 return llvm::GlobalValue::InternalLinkage;
4010
4013 llvm_unreachable("Linkage hasn't been computed!");
4014
4018 return llvm::GlobalValue::InternalLinkage;
4019
4023
4024
4026 return llvm::GlobalValue::LinkOnceODRLinkage;
4027
4030 if (RD->hasAttr())
4031 return llvm::GlobalValue::WeakODRLinkage;
4032 if (CGM.getTriple().isWindowsItaniumEnvironment())
4033 if (RD->hasAttr() &&
4035 return llvm::GlobalValue::ExternalLinkage;
4036
4041 .isWindowsGNUEnvironment())
4043 }
4044
4045 return llvm::GlobalValue::LinkOnceODRLinkage;
4046 }
4047
4048 llvm_unreachable("Invalid linkage!");
4049}
4050
4051llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
4052
4054
4055
4057 llvm::raw_svector_ostream Out(Name);
4059
4060 llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
4061 if (OldGV && !OldGV->isDeclaration()) {
4062 assert(!OldGV->hasAvailableExternallyLinkage() &&
4063 "available_externally typeinfos not yet implemented");
4064
4065 return OldGV;
4066 }
4067
4068
4071 return GetAddrOfExternalRTTIDescriptor(Ty);
4072
4073
4075
4076
4077
4078 llvm::GlobalValue::VisibilityTypes llvmVisibility;
4079 if (llvm::GlobalValue::isLocalLinkage(Linkage))
4080
4081 llvmVisibility = llvm::GlobalValue::DefaultVisibility;
4082 else if (CXXABI.classifyRTTIUniqueness(Ty, Linkage) ==
4083 ItaniumCXXABI::RUK_NonUniqueHidden)
4084 llvmVisibility = llvm::GlobalValue::HiddenVisibility;
4085 else
4087
4088 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4089 llvm::GlobalValue::DefaultStorageClass;
4091 if ((CGM.getTriple().isWindowsItaniumEnvironment() &&
4092 RD->hasAttr()) ||
4094 !llvm::GlobalValue::isLocalLinkage(Linkage) &&
4095 llvmVisibility == llvm::GlobalValue::DefaultVisibility))
4096 DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
4097 }
4098 return BuildTypeInfo(Ty, Linkage, llvmVisibility, DLLStorageClass);
4099}
4100
4101llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
4103 llvm::GlobalVariable::LinkageTypes Linkage,
4104 llvm::GlobalValue::VisibilityTypes Visibility,
4105 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
4107 llvm::raw_svector_ostream Out(Name);
4109 llvm::Module &M = CGM.getModule();
4110 llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
4111
4112 llvm::GlobalVariable *GV =
4113 new llvm::GlobalVariable(M, CGM.Int8Ty, true, Linkage,
4114 nullptr, Name);
4115
4116
4117 BuildVTablePointer(cast(Ty), GV);
4118
4119
4120 llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
4121 llvm::Constant *TypeNameField;
4122
4123
4124
4125 ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =
4127 if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {
4128
4129
4130 TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty);
4131 llvm::Constant *flag =
4132 llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63);
4133 TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
4134 TypeNameField =
4135 llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.GlobalsInt8PtrTy);
4136 } else {
4138 }
4139 Fields.push_back(TypeNameField);
4140
4142#define TYPE(Class, Base)
4143#define ABSTRACT_TYPE(Class, Base)
4144#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
4145#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
4146#define DEPENDENT_TYPE(Class, Base) case Type::Class:
4147#include "clang/AST/TypeNodes.inc"
4148 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
4149
4150
4151 case Type::Builtin:
4152 case Type::Vector:
4153 case Type::ExtVector:
4154 case Type::ConstantMatrix:
4155 case Type::Complex:
4156 case Type::BlockPointer:
4157
4158
4159 break;
4160
4161 case Type::LValueReference:
4162 case Type::RValueReference:
4163 llvm_unreachable("References shouldn't get here");
4164
4165 case Type::Auto:
4166 case Type::DeducedTemplateSpecialization:
4167 llvm_unreachable("Undeduced type shouldn't get here");
4168
4169 case Type::Pipe:
4170 break;
4171
4172 case Type::BitInt:
4173 break;
4174
4175 case Type::ConstantArray:
4176 case Type::IncompleteArray:
4177 case Type::VariableArray:
4178 case Type::ArrayParameter:
4179
4180
4181 break;
4182
4183 case Type::FunctionNoProto:
4184 case Type::FunctionProto:
4185
4186
4187 break;
4188
4189 case Type::Enum:
4190
4191
4192 break;
4193
4194 case Type::Record: {
4196 cast(cast(Ty)->getDecl());
4198
4199 break;
4200 }
4201
4203 BuildSIClassTypeInfo(RD);
4204 else
4205 BuildVMIClassTypeInfo(RD);
4206
4207 break;
4208 }
4209
4210 case Type::ObjCObject:
4211 case Type::ObjCInterface:
4212 BuildObjCObjectTypeInfo(cast(Ty));
4213 break;
4214
4215 case Type::ObjCObjectPointer:
4216 BuildPointerTypeInfo(cast(Ty)->getPointeeType());
4217 break;
4218
4219 case Type::Pointer:
4220 BuildPointerTypeInfo(cast(Ty)->getPointeeType());
4221 break;
4222
4223 case Type::MemberPointer:
4224 BuildPointerToMemberTypeInfo(cast(Ty));
4225 break;
4226
4227 case Type::Atomic:
4228
4229 break;
4230
4231 case Type::HLSLAttributedResource:
4232 llvm_unreachable("HLSL doesn't support RTTI");
4233 }
4234
4235 GV->replaceInitializer(llvm::ConstantStruct::getAnon(Fields));
4236
4237
4238 auto GVDLLStorageClass = DLLStorageClass;
4240 GVDLLStorageClass != llvm::GlobalVariable::DLLExportStorageClass) {
4241 if (const RecordType *RecordTy = dyn_cast(Ty)) {
4242 const CXXRecordDecl *RD = cast(RecordTy->getDecl());
4243 if (RD->hasAttr() ||
4244 CXXRecordNonInlineHasAttr(RD))
4245 GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
4246 }
4247 }
4248
4249
4250 if (OldGV) {
4251 GV->takeName(OldGV);
4252 OldGV->replaceAllUsesWith(GV);
4253 OldGV->eraseFromParent();
4254 }
4255
4257 GV->setComdat(M.getOrInsertComdat(GV->getName()));
4258
4261 GV->setAlignment(Align.getAsAlign());
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4280
4283
4284 TypeName->setDLLStorageClass(DLLStorageClass);
4285 GV->setDLLStorageClass(GVDLLStorageClass);
4286
4289
4290 return GV;
4291}
4292
4293
4294
4295void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
4296
4298 assert(isa(T) || isa(T));
4299
4300
4301
4302 if (isa(T)) return;
4303
4306
4307
4308 if (!Super) return;
4309
4311
4312
4313 llvm::Constant *BaseTypeInfo =
4314 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(SuperTy);
4315 Fields.push_back(BaseTypeInfo);
4316}
4317
4318
4319
4320void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
4321
4322
4323
4324 llvm::Constant *BaseTypeInfo =
4326 Fields.push_back(BaseTypeInfo);
4327}
4328
4329namespace {
4330
4331
4332 struct SeenBases {
4335 };
4336}
4337
4338
4339
4340
4342 SeenBases &Bases) {
4343
4344 unsigned Flags = 0;
4345
4346 auto *BaseDecl =
4348
4349 if (Base->isVirtual()) {
4350
4351 if (!Bases.VirtualBases.insert(BaseDecl).second) {
4352
4353
4354 Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
4355 } else {
4356 if (Bases.NonVirtualBases.count(BaseDecl))
4357 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4358 }
4359 } else {
4360
4361 if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
4362
4363
4364 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4365 } else {
4366 if (Bases.VirtualBases.count(BaseDecl))
4367 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4368 }
4369 }
4370
4371
4372 for (const auto &I : BaseDecl->bases())
4374
4375 return Flags;
4376}
4377
4379 unsigned Flags = 0;
4380 SeenBases Bases;
4381
4382
4383 for (const auto &I : RD->bases())
4385
4386 return Flags;
4387}
4388
4389
4390
4391
4392void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
4393 llvm::Type *UnsignedIntLTy =
4395
4396
4397
4398
4399
4401 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4402
4403
4404
4405
4406 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
4407
4409 return;
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4436 if (TI.getTriple().isOSCygMing() &&
4439 llvm::Type *OffsetFlagsLTy =
4441
4442 for (const auto &Base : RD->bases()) {
4443
4444 Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));
4445
4446 auto *BaseDecl =
4448
4449 int64_t OffsetFlags = 0;
4450
4451
4452
4453
4454
4456 if (Base.isVirtual())
4457 Offset =
4459 else {
4462 };
4463
4464 OffsetFlags = uint64_t(Offset.getQuantity()) << 8;
4465
4466
4467
4468 if (Base.isVirtual())
4469 OffsetFlags |= BCTI_Virtual;
4471 OffsetFlags |= BCTI_Public;
4472
4473 Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags));
4474 }
4475}
4476
4477
4478
4480 unsigned Flags = 0;
4481
4482 if (Type.isConstQualified())
4483 Flags |= ItaniumRTTIBuilder::PTI_Const;
4484 if (Type.isVolatileQualified())
4485 Flags |= ItaniumRTTIBuilder::PTI_Volatile;
4486 if (Type.isRestrictQualified())
4487 Flags |= ItaniumRTTIBuilder::PTI_Restrict;
4488 Type = Type.getUnqualifiedType();
4489
4490
4491
4492
4494 Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
4495
4497 if (Proto->isNothrow()) {
4498 Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
4500 }
4501 }
4502
4503 return Flags;
4504}
4505
4506
4507
4508void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
4509
4510
4511
4513
4514 llvm::Type *UnsignedIntLTy =
4516 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4517
4518
4519
4520
4521 llvm::Constant *PointeeTypeInfo =
4522 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
4523 Fields.push_back(PointeeTypeInfo);
4524}
4525
4526
4527
4528void
4529ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
4531
4532
4533
4534
4536
4539 Flags |= PTI_ContainingClassIncomplete;
4540
4541 llvm::Type *UnsignedIntLTy =
4543 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4544
4545
4546
4547
4548 llvm::Constant *PointeeTypeInfo =
4549 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
4550 Fields.push_back(PointeeTypeInfo);
4551
4552
4553
4554
4555
4556 Fields.push_back(
4557 ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0)));
4558}
4559
4560llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
4561 return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
4562}
4563
4564void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
4565
4566 QualType FundamentalTypes[] = {
4567 getContext().VoidTy, getContext().NullPtrTy,
4568 getContext().BoolTy, getContext().WCharTy,
4569 getContext().CharTy, getContext().UnsignedCharTy,
4570 getContext().SignedCharTy, getContext().ShortTy,
4571 getContext().UnsignedShortTy, getContext().IntTy,
4572 getContext().UnsignedIntTy, getContext().LongTy,
4573 getContext().UnsignedLongTy, getContext().LongLongTy,
4574 getContext().UnsignedLongLongTy, getContext().Int128Ty,
4575 getContext().UnsignedInt128Ty, getContext().HalfTy,
4576 getContext().FloatTy, getContext().DoubleTy,
4577 getContext().LongDoubleTy, getContext().Float128Ty,
4578 getContext().Char8Ty, getContext().Char16Ty,
4579 getContext().Char32Ty
4580 };
4581 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4583 ? llvm::GlobalValue::DLLExportStorageClass
4584 : llvm::GlobalValue::DefaultStorageClass;
4585 llvm::GlobalValue::VisibilityTypes Visibility =
4587 for (const QualType &FundamentalType : FundamentalTypes) {
4589 QualType PointerTypeConst = getContext().getPointerType(
4590 FundamentalType.withConst());
4592 ItaniumRTTIBuilder(*this).BuildTypeInfo(
4593 Type, llvm::GlobalValue::ExternalLinkage,
4595 }
4596}
4597
4598
4599
4600ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
4601 QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const {
4602 if (shouldRTTIBeUnique())
4603 return RUK_Unique;
4604
4605
4606 if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
4607 Linkage != llvm::GlobalValue::WeakODRLinkage)
4608 return RUK_Unique;
4609
4610
4612 return RUK_Unique;
4613
4614
4615 if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
4616 return RUK_NonUniqueHidden;
4617
4618
4619
4620
4621 assert(Linkage == llvm::GlobalValue::WeakODRLinkage);
4622 return RUK_NonUniqueVisible;
4623}
4624
4625
4626namespace {
4627enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
4628}
4632 return StructorCodegen::Emit;
4633
4634
4635
4637 return StructorCodegen::Emit;
4638
4640 if (const auto *DD = dyn_cast(MD)) {
4642 } else {
4643 const auto *CD = cast(MD);
4645 }
4647
4648 if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))
4649 return StructorCodegen::RAUW;
4650
4651
4652 if (!llvm::GlobalAlias::isValidLinkage(Linkage))
4653 return StructorCodegen::RAUW;
4654
4655 if (llvm::GlobalValue::isWeakForLinker(Linkage)) {
4656
4659 return StructorCodegen::COMDAT;
4660 return StructorCodegen::Emit;
4661 }
4662
4663 return StructorCodegen::Alias;
4664}
4665
4670
4672 llvm::GlobalValue *Entry = CGM.GetGlobalValue(MangledName);
4673 if (Entry && !Entry->isDeclaration())
4674 return;
4675
4676 auto *Aliasee = castllvm::GlobalValue(CGM.GetAddrOfGlobal(TargetDecl));
4677
4678
4679 auto *Alias = llvm::GlobalAlias::create(Linkage, "", Aliasee);
4680
4681
4682 Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4683
4684
4685 if (Entry) {
4686 assert(Entry->getType() == Aliasee->getType() &&
4687 "declaration exists with different type");
4688 Alias->takeName(Entry);
4689 Entry->replaceAllUsesWith(Alias);
4690 Entry->eraseFromParent();
4691 } else {
4692 Alias->setName(MangledName);
4693 }
4694
4695
4697}
4698
4699void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {
4700 auto *MD = cast(GD.getDecl());
4701 auto *CD = dyn_cast(MD);
4702 const CXXDestructorDecl *DD = CD ? nullptr : cast(MD);
4703
4705
4709 if (CD)
4711 else
4713
4714 if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {
4716 return;
4717 }
4718
4719 if (CGType == StructorCodegen::RAUW) {
4723 return;
4724 }
4725 }
4726
4727
4728
4729
4730
4732 CGType != StructorCodegen::COMDAT &&
4734 return;
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4749
4750 if (CGType == StructorCodegen::COMDAT) {
4752 llvm::raw_svector_ostream Out(Buffer);
4753 if (DD)
4754 getMangleContext().mangleCXXDtorComdat(DD, Out);
4755 else
4756 getMangleContext().mangleCXXCtorComdat(CD, Out);
4757 llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str());
4759 } else {
4761 }
4762}
4763
4765
4766 llvm::FunctionType *FTy = llvm::FunctionType::get(
4768
4770}
4771
4773
4774 llvm::FunctionType *FTy =
4775 llvm::FunctionType::get(CGM.VoidTy, false);
4776
4778}
4779
4781
4782 llvm::FunctionType *FTy = llvm::FunctionType::get(
4784
4786}
4787
4788namespace {
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4802 CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
4803 bool MightThrow;
4804
4806 if (!MightThrow) {
4808 return;
4809 }
4810
4812 }
4813 };
4814}
4815
4816
4817
4818
4819
4820
4821
4823 llvm::Value *Exn,
4824 bool EndMightThrow) {
4825 llvm::CallInst *call =
4827
4828 CGF.EHStack.pushCleanup(
4830 EndMightThrow && !CGF.CGM.getLangOpts().AssumeNothrowExceptionDtor);
4831
4832 return call;
4833}
4834
4835
4836
4838 const VarDecl &CatchParam,
4841
4843
4847
4848
4849
4850 if (isa(CatchType)) {
4852 bool EndCatchMightThrow = CaughtType->isRecordType();
4853
4854
4855 llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);
4856
4857
4858
4859
4860 if (const PointerType *PT = dyn_cast(CaughtType)) {
4862
4863
4864
4866
4867
4868
4869 unsigned HeaderSize =
4871 AdjustedExn =
4872 CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, Exn, HeaderSize);
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888 } else {
4889
4891
4892
4895 llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
4897
4898
4900 }
4901 }
4902
4903 llvm::Value *ExnCast =
4904 CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
4906 return;
4907 }
4908
4909
4912 llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);
4913
4914
4915
4916 if (CatchType->hasPointerRepresentation()) {
4917 llvm::Value *CastExn =
4918 CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
4919
4923 [[fallthrough]];
4924
4929 return;
4930
4933 return;
4934 }
4935 llvm_unreachable("bad ownership qualifier!");
4936 }
4937
4938
4939
4942 switch (TEK) {
4945 true);
4946 return;
4950 return;
4951 }
4953 llvm_unreachable("evaluation kind filtered out!");
4954 }
4955 llvm_unreachable("bad evaluation kind");
4956 }
4957
4958 assert(isa(CatchType) && "unexpected catch type!");
4959 auto catchRD = CatchType->getAsCXXRecordDecl();
4961
4962 llvm::Type *PtrTy = CGF.UnqualPtrTy;
4963
4964
4965
4966 const Expr *copyExpr = CatchParam.getInit();
4967 if (!copyExpr) {
4968 llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);
4969 Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4970 LLVMCatchTy, caughtExnAlignment);
4974 return;
4975 }
4976
4977
4978
4979 llvm::CallInst *rawAdjustedExn =
4981
4982
4983 Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
4984 LLVMCatchTy, caughtExnAlignment);
4985
4986
4987
4988 CodeGenFunction::OpaqueValueMapping
4991
4992
4994
4995
5002
5003
5005
5006
5007 opaque.pop();
5008
5009
5011}
5012
5013
5014
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040 VarDecl *CatchParam = S->getExceptionDecl();
5041 if (!CatchParam) {
5044 return;
5045 }
5046
5047
5049 InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getBeginLoc());
5051}
5052
5053
5054
5055
5059 C.VoidTy, {C.getPointerType(C.CharTy)});
5062 fnTy, "__clang_call_terminate", llvm::AttributeList(), true);
5063 llvm::Function *fn =
5064 castllvm::Function(fnRef.getCallee()->stripPointerCasts());
5065 if (fn->empty()) {
5068 fn->setDoesNotThrow();
5069 fn->setDoesNotReturn();
5070
5071
5072
5073
5074 fn->addFnAttr(llvm::Attribute::NoInline);
5075
5076
5077
5078 fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
5079 fn->setVisibility(llvm::Function::HiddenVisibility);
5081 fn->setComdat(CGM.getModule().getOrInsertComdat(fn->getName()));
5082
5083
5084 llvm::BasicBlock *entry =
5085 llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn);
5087
5088
5089 llvm::Value *exn = &*fn->arg_begin();
5090
5091
5092 llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);
5093 catchCall->setDoesNotThrow();
5094 catchCall->setCallingConv(CGM.getRuntimeCC());
5095
5096
5097 llvm::CallInst *termCall = builder.CreateCall(CGM.getTerminateFn());
5098 termCall->setDoesNotThrow();
5099 termCall->setDoesNotReturn();
5100 termCall->setCallingConv(CGM.getRuntimeCC());
5101
5102
5103 builder.CreateUnreachable();
5104 }
5105 return fnRef;
5106}
5107
5108llvm::CallInst *
5109ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
5110 llvm::Value *Exn) {
5111
5112 if (Exn) {
5115 }
5117}
5118
5119std::pair<llvm::Value *, const CXXRecordDecl *>
5123}
5124
5125llvm::Constant *
5126ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) {
5131 llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD);
5135}
5136
5137void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,
5142 ItaniumCXXABI::emitBeginCatch(CGF, C);
5143}
5144
5145llvm::CallInst *
5146WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
5147 llvm::Value *Exn) {
5148
5149
5150
5151
5152
5153
5155}
5156
5157
5159 llvm::FunctionCallee Dtor,
5160 llvm::Constant *Addr) {
5162 llvm::PointerType *PtrTy = CGF.UnqualPtrTy;
5163
5164
5165 llvm::FunctionType *AtExitTy =
5166 llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy, PtrTy}, true);
5167
5168
5169 llvm::FunctionCallee AtExit =
5171
5172
5174
5175
5176
5177 llvm::Value *NV = llvm::Constant::getNullValue(CGM.IntTy);
5179
5180
5181 return;
5182 }
5183
5184
5185 llvm::Function *DtorStub =
5187
5188
5190
5191
5192
5193 emitCXXStermFinalizer(D, DtorStub, Addr);
5194}
5195
5196void XLCXXABI::emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
5197 llvm::Constant *addr) {
5198 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
5200 {
5201 llvm::raw_svector_ostream Out(FnName);
5202 getMangleContext().mangleDynamicStermFinalizer(&D, Out);
5203 }
5204
5205
5209
5211
5214 D.getInit()->getExprLoc());
5215
5216
5217
5218
5219
5221
5223
5224 llvm::BasicBlock *DestructCallBlock = CGF.createBasicBlock("destruct.call");
5225 llvm::BasicBlock *EndBlock = CGF.createBasicBlock("destruct.end");
5226
5227
5228
5229 CGF.Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
5230
5231 CGF.EmitBlock(DestructCallBlock);
5232
5233
5234 llvm::CallInst *CI = CGF.Builder.CreateCall(dtorStub);
5235
5236
5237 CI->setCallingConv(dtorStub->getCallingConv());
5238
5240
5242
5243 if (auto *IPA = D.getAttr()) {
5245 IPA->getPriority());
5248
5249
5250
5251
5253 } else {
5255 }
5256}
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 bool CXXRecordNonInlineHasAttr(const CXXRecordDecl *RD)
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::Constant * pointerAuthResignMemberFunctionPointer(llvm::Constant *Src, QualType DestType, QualType SrcType, 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::Value * performTypeAdjustment(CodeGenFunction &CGF, Address InitialPtr, const CXXRecordDecl *UnadjustedClass, int64_t NonVirtualAdjustment, int64_t VirtualAdjustment, bool IsReturnAdjustment)
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 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 void setVTableSelectiveDLLImportExport(CodeGenModule &CGM, llvm::GlobalVariable *VTable, const CXXRecordDecl *RD)
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 llvm::Constant * pointerAuthResignConstant(llvm::Value *Ptr, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, CodeGenModule &CGM)
static void emitConstructorDestructorAlias(CodeGenModule &CGM, GlobalDecl AliasDecl, GlobalDecl TargetDecl)
static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM)
static void dtorTy(Block *, std::byte *Ptr, const Descriptor *)
llvm::MachO::Record Record
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.
static QualType getPointeeType(const MemRegion *R)
#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.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
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 ...
CallingConv getDefaultCallingConvention(bool IsVariadic, bool IsCXXMethod, bool IsBuiltin=false) const
Retrieves the default calling convention for the current target.
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
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
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 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]).
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...
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.
PointerAuthOptions PointerAuth
Configuration for pointer-signing.
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)
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
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::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::Value * CreateIsNull(Address Addr, const Twine &Name="")
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
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 CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const 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 * 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 bool shouldTypeidBeNullChecked(QualType SrcRecordTy)=0
virtual llvm::Type * ConvertMemberPointerType(const MemberPointerType *MPT)
Find the LLVM type used to represent the given member pointer type.
virtual llvm::Value * performThisAdjustment(CodeGenFunction &CGF, Address This, const CXXRecordDecl *UnadjustedClass, const ThunkInfo &TI)=0
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 llvm::Value * performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const CXXRecordDecl *UnadjustedClass, const ReturnAdjustment &RA)=0
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 void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, bool ReturnAdjustment)=0
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 llvm::Value * EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke)=0
Emit the ABI-specific virtual destructor call.
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 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.
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
llvm::Value * getDiscriminator() const
CallArgList - Type for representing both the value and type of arguments in a call.
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.
llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
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.
llvm::Value * GetVTablePtr(Address This, llvm::Type *VTableTy, const CXXRecordDecl *VTableClass, VTableAuthMode AuthMode=VTableAuthMode::Authenticate)
GetVTablePtr - Return the Value of the vtable pointer member pointed to by This.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
SanitizerSet SanOpts
Sanitizers enabled for this function.
llvm::Constant * createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr)
void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge=false)
Create a basic block that will call the trap intrinsic, and emit a conditional branch to it,...
bool CurFuncIsThunk
In C++, whether we are code generating a thunk.
void EmitAnyExprToExn(const Expr *E, Address Addr)
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)
llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)
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.
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)
llvm::Function * createTLSAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr, llvm::FunctionCallee &AtExit)
void registerGlobalDtorWithLLVM(const VarDecl &D, llvm::FunctionCallee fn, llvm::Constant *addr)
Registers the dtor using 'llvm.global_dtors' for platforms that do not support an 'atexit()' function...
const TargetInfo & getTarget() const
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV, bool PerformInit)
EmitCXXGlobalVarDeclInit - Create the initializer for a C++ variable with global storage.
llvm::Value * emitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull)
bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
void EmitCheck(ArrayRef< std::pair< llvm::Value *, SanitizerKind::SanitizerOrdinal > > Checked, SanitizerHandler Check, ArrayRef< llvm::Constant * > StaticArgs, ArrayRef< llvm::Value * > DynamicArgs)
Create a basic block that will either trap or call a handler function in the UBSan runtime with the p...
CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, const CXXRecordDecl *RD)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc)
EmitDelegateCallArg - We are performing a delegate call; that is, the current function is delegating ...
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)
Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...
void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::FunctionCallee fn, llvm::Constant *addr)
Call atexit() with a function that passes the given argument to the given function.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
llvm::Value * unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub)
Call unatexit() with function dtorStub.
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
llvm::Value * LoadCXXVTT()
LoadCXXVTT - Load the VTT parameter to base constructors/destructors have virtual bases.
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
void EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable, SourceLocation Loc)
If whole-program virtual table optimization is enabled, emit an assumption that VTable is a member of...
llvm::Type * ConvertType(QualType T)
void EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args)
CodeGenTypes & getTypes() const
void EmitARCInitWeak(Address addr, llvm::Value *value)
llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")
QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args)
llvm::Value * EmitARCRetainNonBlock(llvm::Value *value)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::Instruction * CurrentFuncletPad
llvm::LLVMContext & getLLVMContext()
llvm::Value * getExceptionFromSlot()
Returns the contents of the function's exception object and selector slots.
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
void EmitCXXGuardedInitBranch(llvm::Value *NeedsInit, llvm::BasicBlock *InitBlock, llvm::BasicBlock *NoInitBlock, GuardKind Kind, const VarDecl *D)
Emit a branch to select whether or not to perform guarded initialization.
This class organizes the cross-function state that is used while generating LLVM code.
void AddCXXPrioritizedStermFinalizerEntry(llvm::Function *StermFinalizer, int Priority)
void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const
Set visibility, dllimport/dllexport and dso_local.
void AddCXXStermFinalizerToGlobalDtor(llvm::Function *StermFinalizer, int Priority)
Add an sterm finalizer to its own llvm.global_dtors entry.
llvm::GlobalVariable::ThreadLocalMode GetDefaultLLVMTLSModel() const
Get LLVM TLS mode from CodeGenOptions.
void setDSOLocal(llvm::GlobalValue *GV) const
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
CodeGenVTables & getVTables()
void AddCXXStermFinalizerEntry(llvm::FunctionCallee DtorFn)
Add an sterm finalizer to the C++ global cleanup function.
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
llvm::Constant * getFunctionPointer(GlobalDecl GD, llvm::Type *Ty=nullptr)
Return the ABI-correct function pointer value for a reference to the given function.
CGPointerAuthInfo getMemberFunctionPointerAuthInfo(QualType FT)
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
bool shouldMapVisibilityToDLLExport(const NamedDecl *D) const
const TargetInfo & getTarget() const
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D)
Try to emit a base destructor as an alias to its primary base-class destructor.
llvm::GlobalValue::LinkageTypes getLLVMLinkageVarDefinition(const VarDecl *VD)
Returns LLVM linkage for a declarator.
const llvm::DataLayout & getDataLayout() const
CGCXXABI & getCXXABI() const
static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V)
llvm::Constant * getMemberFunctionPointer(const FunctionDecl *FD, llvm::Type *Ty=nullptr)
llvm::Function * codegenCXXStructor(GlobalDecl GD)
CharUnits getClassPointerAlignment(const CXXRecordDecl *CD)
Returns the assumed alignment of an opaque pointer to the given class.
const llvm::Triple & getTriple() const
llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD)
void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535, bool IsDtorAttrFunc=false)
AddGlobalDtor - Add a function to the list that will be called when the module is unloaded.
llvm::Constant * CreateRuntimeVariable(llvm::Type *Ty, StringRef Name)
Create a new runtime global variable with the specified type and name.
CharUnits getDynamicOffsetAlignment(CharUnits ActualAlign, const CXXRecordDecl *Class, CharUnits ExpectedTargetAlign)
Given a class pointer with an actual known alignment, and the expected alignment of an object at a dy...
llvm::Constant * GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition=NotForDefinition)
ItaniumVTableContext & getItaniumVTableContext()
ASTContext & getContext() const
llvm::Constant * GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty=nullptr, ForDefinition_t IsForDefinition=NotForDefinition)
Return the llvm::Constant for the address of the given global variable.
bool supportsCOMDAT() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
void SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV)
Set attributes which are common to any form of a global definition (alias, Objective-C method,...
llvm::GlobalVariable * CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage, llvm::Align Alignment)
Will return a global variable of the given type.
llvm::FunctionCallee getTerminateFn()
Get the declaration of std::terminate for the platform.
llvm::LLVMContext & getLLVMContext()
llvm::GlobalValue * GetGlobalValue(StringRef Ref)
void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO)
LangAS GetGlobalVarAddressSpace(const VarDecl *D)
Return the AST address space of the underlying global variable for D, as determined by its declaratio...
llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD)
Return the appropriate linkage for the vtable, VTT, and type information of the given class.
void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F, bool IsThunk)
Set the LLVM function attributes (sext, zext, etc).
void addReplacement(StringRef Name, llvm::Constant *C)
llvm::Constant * getConstantSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, llvm::Constant *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
Sign a constant pointer using the given scheme, producing a constant with the same IR type.
void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535, unsigned LexOrder=~0U, llvm::Constant *AssociatedData=nullptr)
AddGlobalCtor - Add a function to the list that will be called before main() runs.
void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F)
Set the LLVM function attributes which only apply to a function definition.
llvm::Function * CreateGlobalInitOrCleanUpFunction(llvm::FunctionType *ty, const Twine &name, const CGFunctionInfo &FI, SourceLocation Loc=SourceLocation(), bool TLS=false, llvm::GlobalVariable::LinkageTypes Linkage=llvm::GlobalVariable::InternalLinkage)
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeCXXMethodDeclaration(const CXXMethodDecl *MD)
C++ methods have some special rules and also have implicit parameters.
const CodeGenOptions & getCodeGenOpts() const
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGFunctionInfo & arrangeCXXMethodCall(const CallArgList &args, const FunctionProtoType *type, RequiredArgs required, unsigned numPrefixArgs)
Arrange a call to a C++ method, passing the given arguments.
const CGFunctionInfo & arrangeNullaryFunction()
A nullary function is a freestanding function of type 'void ()'.
llvm::GlobalVariable * GetAddrOfVTT(const CXXRecordDecl *RD)
GetAddrOfVTT - Get the address of the VTT for the given record decl.
void createVTableInitializer(ConstantStructBuilder &builder, const VTableLayout &layout, llvm::Constant *rtti, bool vtableHasLocalLinkage)
Add vtable components for the given vtable layout to the given global initializer.
void GenerateRelativeVTableAlias(llvm::GlobalVariable *VTable, llvm::StringRef AliasNameRef)
Generate a public facing alias for the vtable and make the vtable either hidden or private.
bool isVTableExternal(const CXXRecordDecl *RD)
At this point in the translation unit, does it appear that can we rely on the vtable being defined el...
void RemoveHwasanMetadata(llvm::GlobalValue *GV) const
Specify a global should not be instrumented with hwasan.
void EmitVTTDefinition(llvm::GlobalVariable *VTT, llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl *RD)
EmitVTTDefinition - Emit the definition of the given vtable.
A specialization of Address that requires the address to be an LLVM Constant.
The standard implementation of ConstantInitBuilder used in Clang.
Information for lazily generating a cleanup.
void popTerminate()
Pops a terminate handler off the stack.
void pushTerminate()
Push a terminate handler on the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
A class for recording the number of arguments that a function signature requires.
static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
virtual unsigned getSizeOfUnwindException() const
Determines the size of struct _Unwind_Exception on this platform, in 8-bit units.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTranslationUnit() const
decl_range noload_decls() const
noload_decls_begin/end - Iterate over the declarations stored in this context that are currently load...
SourceLocation getLocation() const
DeclContext * getDeclContext()
bool shouldEmitInExternalSource() const
Whether the definition of the declaration should be emitted in external sources.
This represents one expression.
Represents a function declaration or definition.
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
FunctionDecl * getDefinition()
Get the definition for this declaration.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Represents a prototype with parameter type info, e.g.
GlobalDecl - represents a global declaration.
GlobalDecl getWithCtorType(CXXCtorType Type)
CXXCtorType getCtorType() const
GlobalDecl getCanonicalDecl() const
GlobalDecl getWithDtorType(CXXDtorType Type)
CXXDtorType getDtorType() const
const Decl * getDecl() const
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
bool isRelativeLayout() const
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
Return the offset in chars (relative to the vtable address point) where the offset of the virtual bas...
GlobalDecl findOriginalMethod(GlobalDecl GD)
Return the method that added the v-table slot that will be used to call the given method.
virtual void mangleCXXRTTI(QualType T, raw_ostream &)=0
virtual void mangleCXXRTTIName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
A pointer to member type per C++ 8.3.3 - Pointers to members.
QualType getPointeeType() const
bool isMemberFunctionPointer() const
Returns true if the member type (i.e.
bool isMemberDataPointer() const
Returns true if the member type (i.e.
const Type * getClass() const
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Visibility getVisibility() const
Determines the visibility of this entity.
bool isExternallyVisible() const
Represents an ObjC class declaration.
Represents a class type in Objective C.
QualType getBaseType() const
Gets the base type of this object type.
static const OpaqueValueExpr * findInCopyConstruct(const Expr *expr)
Given an expression which invokes a copy constructor — i.e.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
The collection of all-type qualifiers we support.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
ObjCLifetime getObjCLifetime() const
bool canPassInRegisters() const
Determine whether this class can be passed in registers.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
Encodes a location in the source.
SourceLocation getBeginLoc() const LLVM_READONLY
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Exposes information about the current target.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
unsigned getMaxAtomicInlineWidth() const
Return the maximum width lock-free atomic operation which can be inlined given the supported features...
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
virtual bool hasPS4DLLImportExport() const
uint64_t getPointerAlign(LangAS AddrSpace) const
unsigned getLongWidth() const
getLongWidth/Align - Return the size of 'signed long' and 'unsigned long' for this target,...
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
const Type * getTypeForDecl() const
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const T * castAs() const
Member-template castAs.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Visibility getVisibility() const
Determine the visibility of this type.
bool isMemberFunctionPointerType() const
Linkage getLinkage() const
Determine the linkage of this type.
TypeClass getTypeClass() const
const T * getAs() const
Member-template getAs'.
bool isRecordType() const
AddressPointLocation getAddressPoint(BaseSubobject Base) const
size_t getVTableSize(size_t i) const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
@ TLS_Dynamic
TLS with a dynamic initializer.
@ TLS_None
Not a TLS variable.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
TemplateSpecializationKind getTemplateSpecializationKind() const
If this variable is an instantiation of a variable template or a static data member of a class templa...
llvm::Value * getCXXDestructorImplicitParam(CodeGenModule &CGM, llvm::BasicBlock *InsertBlock, llvm::BasicBlock::iterator InsertPoint, const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating)
TypeEvaluationKind
The kind of evaluation to perform on values of a particular type.
@ NormalCleanup
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
@ EHCleanup
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
CGCXXABI * CreateItaniumCXXABI(CodeGenModule &CGM)
Creates an Itanium-family ABI.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
constexpr Variable var(Literal L)
Returns the variable of L.
bool This(InterpState &S, CodePtr OpPC)
bool Zero(InterpState &S, CodePtr OpPC)
bool InRange(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_DefaultClosure
Default closure variant of a ctor.
@ Ctor_CopyingClosure
Copying closure variant of a ctor.
@ Ctor_Complete
Complete object ctor.
@ Ctor_Comdat
The COMDAT used for ctors.
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
@ VisibleNone
No linkage according to the standard, but is visible from other translation units because of types de...
@ None
No linkage, which means that the entity is unique and can only be referred to from within its scope.
@ UniqueExternal
External linkage within a unique namespace.
@ Internal
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
@ External
External linkage, which indicates that the entity can be referred to from other translation units.
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
CXXDtorType
C++ destructor types.
@ Dtor_Comdat
The COMDAT used for dtors.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
bool isDiscardableGVALinkage(GVALinkage L)
LangAS
Defines the address space values used by the address space qualifier of QualType.
const FunctionProtoType * T
@ Success
Template argument deduction was successful.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
@ EST_None
no exception specification
Visibility
Describes the different kinds of visibility that a declaration may have.
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
@ DefaultVisibility
Objects with "default" visibility are seen by the dynamic linker and act like normal objects.
Represents an element in a path from a derived class to a base class.
Similar to AddedStructorArgs, but only notes the number of additional arguments.
Additional implicit arguments to add to the beginning (Prefix) and end (Suffix) of a constructor / de...
The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler,...
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::PointerType * GlobalsVoidPtrTy
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * CharTy
char
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::PointerType * GlobalsInt8PtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
CharUnits getSizeSize() const
CharUnits getSizeAlign() const
llvm::PointerType * Int8PtrTy
llvm::PointerType * UnqualPtrTy
CharUnits getPointerAlign() const
Extra information about a function prototype.
PointerAuthSchema CXXVTTVTablePointers
The ABI for C++ virtual table pointers as installed in a VTT.
PointerAuthSchema CXXTypeInfoVTablePointer
TypeInfo has external ABI requirements and is emitted without actually having parsed the libcxx defin...
union clang::ReturnAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.
A this pointer adjustment.
union clang::ThisAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
The this pointer adjustment as well as an optional return adjustment for a thunk.
ThisAdjustment This
The this pointer adjustment.
unsigned AddressPointIndex
struct clang::ReturnAdjustment::VirtualAdjustment::@192 Itanium
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
int64_t VCallOffsetOffset
The offset (in bytes), relative to the address point, of the virtual call offset.
struct clang::ThisAdjustment::VirtualAdjustment::@194 Itanium