33#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/GlobalValue.h"
35#include "llvm/IR/Instructions.h"
36#include "llvm/IR/Intrinsics.h"
37#include "llvm/IR/Value.h"
38#include "llvm/Support/ScopedPrinter.h"
48 llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
51 llvm::SmallVector<std::pair<const VarDecl *, llvm::Function *>, 8>
55 bool UseARMMethodPtrABI;
56 bool UseARMGuardVarABI;
57 bool Use32BitVTableOffsetABI;
59 ItaniumMangleContext &getMangleContext() {
64 ItaniumCXXABI(CodeGen::CodeGenModule &CGM,
65 bool UseARMMethodPtrABI =
false,
66 bool UseARMGuardVarABI =
false) :
67 CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
68 UseARMGuardVarABI(UseARMGuardVarABI),
69 Use32BitVTableOffsetABI(
false) { }
80 bool isThisCompleteObject(GlobalDecl GD)
const override {
93 llvm_unreachable(
"emitting dtor comdat as function?");
95 llvm_unreachable(
"emitting unified dtor as function?");
97 llvm_unreachable(
"bad dtor kind");
109 llvm_unreachable(
"closure ctors in Itanium ABI?");
112 llvm_unreachable(
"emitting ctor comdat as function?");
115 llvm_unreachable(
"emitting unified ctor as function?");
117 llvm_unreachable(
"bad dtor kind");
124 bool isZeroInitializable(
const MemberPointerType *MPT)
override;
126 llvm::Type *ConvertMemberPointerType(
const MemberPointerType *MPT)
override;
129 EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
132 llvm::Value *&ThisPtrForCall,
133 llvm::Value *MemFnPtr,
134 const MemberPointerType *MPT)
override;
136 llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
const Expr *E,
137 Address Base, llvm::Value *MemPtr,
138 const MemberPointerType *MPT,
139 bool IsInBounds)
override;
141 llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
143 llvm::Value *Src)
override;
144 llvm::Constant *EmitMemberPointerConversion(
const CastExpr *E,
145 llvm::Constant *Src)
override;
147 llvm::Constant *EmitNullMemberPointer(
const MemberPointerType *MPT)
override;
149 llvm::Constant *EmitMemberFunctionPointer(
const CXXMethodDecl *MD)
override;
150 llvm::Constant *EmitMemberDataPointer(
const MemberPointerType *MPT,
151 CharUnits offset)
override;
152 llvm::Constant *EmitMemberPointer(
const APValue &MP, QualType MPT)
override;
153 llvm::Constant *BuildMemberPointer(
const CXXMethodDecl *MD,
154 CharUnits ThisAdjustment);
156 llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
157 llvm::Value *L, llvm::Value *R,
158 const MemberPointerType *MPT,
159 bool Inequality)
override;
161 llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
163 const MemberPointerType *MPT)
override;
165 void emitVirtualObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
166 Address Ptr, QualType ElementType,
167 const CXXDestructorDecl *Dtor)
override;
169 void emitRethrow(CodeGenFunction &CGF,
bool isNoReturn)
override;
170 void emitThrow(CodeGenFunction &CGF,
const CXXThrowExpr *E)
override;
172 void emitBeginCatch(CodeGenFunction &CGF,
const CXXCatchStmt *
C)
override;
175 emitTerminateForUnexpectedException(CodeGenFunction &CGF,
176 llvm::Value *Exn)
override;
178 void EmitFundamentalRTTIDescriptors(
const CXXRecordDecl *RD);
179 llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty)
override;
181 getAddrOfCXXCatchHandlerType(QualType Ty,
182 QualType CatchHandlerType)
override {
183 return CatchTypeInfo{getAddrOfRTTIDescriptor(Ty), 0};
186 bool shouldTypeidBeNullChecked(QualType SrcRecordTy)
override;
187 void EmitBadTypeidCall(CodeGenFunction &CGF)
override;
188 llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
190 llvm::Type *StdTypeInfoPtrTy)
override;
192 bool shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
193 QualType SrcRecordTy)
override;
199 bool hasUniqueVTablePointer(QualType RecordTy) {
204 if (!CGM.getCodeGenOpts().AssumeUniqueVTables ||
205 getContext().getLangOpts().AppleKext)
210 if (!CGM.shouldEmitRTTI())
215 if (!llvm::GlobalValue::isWeakForLinker(CGM.getVTableLinkage(RD)))
224 llvm::GlobalValue::DefaultVisibility)
230 bool shouldEmitExactDynamicCast(QualType DestRecordTy)
override {
231 return hasUniqueVTablePointer(DestRecordTy);
234 std::optional<ExactDynamicCastInfo>
235 getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,
236 QualType DestRecordTy)
override;
238 llvm::Value *emitDynamicCastCall(CodeGenFunction &CGF, Address
Value,
239 QualType SrcRecordTy, QualType DestTy,
240 QualType DestRecordTy,
241 llvm::BasicBlock *CastEnd)
override;
244 QualType SrcRecordTy, QualType DestTy,
245 QualType DestRecordTy,
246 const ExactDynamicCastInfo &CastInfo,
247 llvm::BasicBlock *CastSuccess,
248 llvm::BasicBlock *CastFail)
override;
251 QualType SrcRecordTy)
override;
253 bool EmitBadCastCall(CodeGenFunction &CGF)
override;
256 GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
257 const CXXRecordDecl *ClassDecl,
258 const CXXRecordDecl *BaseClassDecl)
override;
260 void EmitCXXConstructors(
const CXXConstructorDecl *D)
override;
262 AddedStructorArgCounts
263 buildStructorSignature(GlobalDecl GD,
264 SmallVectorImpl<CanQualType> &ArgTys)
override;
266 bool useThunkForDtorVariant(
const CXXDestructorDecl *Dtor,
274 void EmitCXXDestructors(
const CXXDestructorDecl *D)
override;
276 void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
277 FunctionArgList &Params)
override;
279 void EmitInstanceFunctionProlog(CodeGenFunction &CGF)
override;
281 AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
282 const CXXConstructorDecl *D,
288 const CXXDestructorDecl *DD,
293 void EmitDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *DD,
296 QualType ThisTy)
override;
298 void emitVTableDefinitions(CodeGenVTables &CGVT,
299 const CXXRecordDecl *RD)
override;
301 bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
302 CodeGenFunction::VPtr Vptr)
override;
304 bool doStructorsInitializeVPtrs(
const CXXRecordDecl *VTableClass)
override {
309 getVTableAddressPoint(BaseSubobject Base,
310 const CXXRecordDecl *VTableClass)
override;
312 llvm::Value *getVTableAddressPointInStructor(
313 CodeGenFunction &CGF,
const CXXRecordDecl *VTableClass,
314 BaseSubobject Base,
const CXXRecordDecl *NearestVBase)
override;
316 llvm::Value *getVTableAddressPointInStructorWithVTT(
317 CodeGenFunction &CGF,
const CXXRecordDecl *VTableClass,
318 BaseSubobject Base,
const CXXRecordDecl *NearestVBase);
320 llvm::GlobalVariable *getAddrOfVTable(
const CXXRecordDecl *RD,
321 CharUnits VPtrOffset)
override;
323 CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
324 Address This, llvm::Type *Ty,
325 SourceLocation Loc)
override;
328 EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
330 DeleteOrMemberCallExpr E,
331 llvm::CallBase **CallOrInvoke)
override;
333 void emitVirtualInheritanceTables(
const CXXRecordDecl *RD)
override;
335 bool canSpeculativelyEmitVTable(
const CXXRecordDecl *RD)
const override;
336 bool canSpeculativelyEmitVTableAsBaseClass(
const CXXRecordDecl *RD)
const;
338 void setThunkLinkage(llvm::Function *Thunk,
bool ForVTable, GlobalDecl GD,
339 bool ReturnAdjustment)
override {
342 if (ForVTable && !Thunk->hasLocalLinkage())
343 Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
344 CGM.setGVProperties(Thunk, GD);
347 bool exportThunk()
override {
return true; }
349 llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
350 const CXXRecordDecl *UnadjustedThisClass,
351 const ThunkInfo &TI)
override;
353 llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
354 const CXXRecordDecl *UnadjustedRetClass,
355 const ReturnAdjustment &RA)
override;
357 size_t getSrcArgforCopyCtor(
const CXXConstructorDecl *,
358 FunctionArgList &Args)
const override {
359 assert(!Args.empty() &&
"expected the arglist to not be empty!");
360 return Args.size() - 1;
363 StringRef GetPureVirtualCallName()
override {
return "__cxa_pure_virtual"; }
364 StringRef GetDeletedVirtualCallName()
override
365 {
return "__cxa_deleted_virtual"; }
367 CharUnits getArrayCookieSizeImpl(QualType elementType)
override;
368 Address InitializeArrayCookie(CodeGenFunction &CGF,
370 llvm::Value *NumElements,
371 const CXXNewExpr *
expr,
372 QualType ElementType)
override;
373 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
375 CharUnits cookieSize)
override;
377 void EmitGuardedInit(CodeGenFunction &CGF,
const VarDecl &D,
378 llvm::GlobalVariable *DeclPtr,
379 bool PerformInit)
override;
380 void registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
381 llvm::FunctionCallee dtor,
382 llvm::Constant *addr)
override;
384 llvm::Function *getOrCreateThreadLocalWrapper(
const VarDecl *VD,
386 void EmitThreadLocalInitFuncs(
388 ArrayRef<const VarDecl *> CXXThreadLocals,
389 ArrayRef<llvm::Function *> CXXThreadLocalInits,
390 ArrayRef<const VarDecl *> CXXThreadLocalInitVars)
override;
392 bool usesThreadWrapperFunction(
const VarDecl *VD)
const override {
393 return !isEmittedWithConstantInitializer(VD) ||
394 mayNeedDestruction(VD);
396 LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
const VarDecl *VD,
397 QualType LValType)
override;
399 bool NeedsVTTParameter(GlobalDecl GD)
override;
402 getOrCreateVirtualFunctionPointerThunk(
const CXXMethodDecl *MD);
409 virtual bool shouldRTTIBeUnique()
const {
return true; }
413 enum RTTIUniquenessKind {
431 classifyRTTIUniqueness(QualType CanTy,
432 llvm::GlobalValue::LinkageTypes
Linkage)
const;
433 friend class ItaniumRTTIBuilder;
435 void emitCXXStructor(GlobalDecl GD)
override;
437 std::pair<llvm::Value *, const CXXRecordDecl *>
438 LoadVTablePtr(CodeGenFunction &CGF, Address This,
439 const CXXRecordDecl *RD)
override;
443 getSignedVirtualMemberFunctionPointer(
const CXXMethodDecl *MD);
445 bool hasAnyUnusedVirtualInlineFunction(
const CXXRecordDecl *RD)
const {
446 const auto &VtableLayout =
447 CGM.getItaniumVTableContext().getVTableLayout(RD);
449 for (
const auto &VtableComponent : VtableLayout.vtable_components()) {
451 if (!VtableComponent.isUsedFunctionPointerKind())
454 const CXXMethodDecl *
Method = VtableComponent.getFunctionDecl();
455 const FunctionDecl *FD =
Method->getDefinition();
456 const bool IsInlined =
461 StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
462 auto *Entry = CGM.GetGlobalValue(Name);
468 if (!Entry || Entry->isDeclaration())
474 bool isVTableHidden(
const CXXRecordDecl *RD)
const {
475 const auto &VtableLayout =
476 CGM.getItaniumVTableContext().getVTableLayout(RD);
478 for (
const auto &VtableComponent : VtableLayout.vtable_components()) {
479 if (VtableComponent.isRTTIKind()) {
480 const CXXRecordDecl *RTTIDecl = VtableComponent.getRTTIDecl();
481 if (RTTIDecl->
getVisibility() == Visibility::HiddenVisibility)
483 }
else if (VtableComponent.isUsedFunctionPointerKind()) {
484 const CXXMethodDecl *
Method = VtableComponent.getFunctionDecl();
485 if (
Method->getVisibility() == Visibility::HiddenVisibility &&
494class ARMCXXABI :
public ItaniumCXXABI {
496 ARMCXXABI(CodeGen::CodeGenModule &CGM) :
497 ItaniumCXXABI(CGM,
true,
500 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
502 void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV,
503 QualType ResTy)
override;
505 CharUnits getArrayCookieSizeImpl(QualType elementType)
override;
506 Address InitializeArrayCookie(CodeGenFunction &CGF,
508 llvm::Value *NumElements,
509 const CXXNewExpr *
expr,
510 QualType ElementType)
override;
511 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr,
512 CharUnits cookieSize)
override;
515class AppleARM64CXXABI :
public ARMCXXABI {
517 AppleARM64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {
518 Use32BitVTableOffsetABI =
true;
522 bool shouldRTTIBeUnique()
const override {
return false; }
525class FuchsiaCXXABI final :
public ItaniumCXXABI {
527 explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM)
528 : ItaniumCXXABI(CGM) {}
531 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
534class WebAssemblyCXXABI final :
public ItaniumCXXABI {
536 explicit WebAssemblyCXXABI(CodeGen::CodeGenModule &CGM)
537 : ItaniumCXXABI(CGM,
true,
539 void emitBeginCatch(CodeGenFunction &CGF,
const CXXCatchStmt *
C)
override;
541 emitTerminateForUnexpectedException(CodeGenFunction &CGF,
542 llvm::Value *Exn)
override;
545 bool constructorsAndDestructorsReturnThis()
const override {
return true; }
546 bool canCallMismatchedFunctionType()
const override {
return false; }
549class XLCXXABI final :
public ItaniumCXXABI {
551 explicit XLCXXABI(CodeGen::CodeGenModule &CGM)
552 : ItaniumCXXABI(CGM) {}
554 void registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
555 llvm::FunctionCallee dtor,
556 llvm::Constant *addr)
override;
558 bool useSinitAndSterm()
const override {
return true; }
561 void emitCXXStermFinalizer(
const VarDecl &D, llvm::Function *dtorStub,
562 llvm::Constant *addr);
570 case TargetCXXABI::GenericARM:
571 case TargetCXXABI::iOS:
572 case TargetCXXABI::WatchOS:
573 return new ARMCXXABI(CGM);
575 case TargetCXXABI::AppleARM64:
576 return new AppleARM64CXXABI(CGM);
578 case TargetCXXABI::Fuchsia:
579 return new FuchsiaCXXABI(CGM);
584 case TargetCXXABI::GenericAArch64:
585 return new ItaniumCXXABI(CGM,
true,
588 case TargetCXXABI::GenericMIPS:
589 return new ItaniumCXXABI(CGM,
true);
591 case TargetCXXABI::WebAssembly:
592 return new WebAssemblyCXXABI(CGM);
594 case TargetCXXABI::XL:
595 return new XLCXXABI(CGM);
597 case TargetCXXABI::GenericItanium:
598 return new ItaniumCXXABI(CGM);
600 case TargetCXXABI::Microsoft:
601 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
603 llvm_unreachable(
"bad ABI kind");
609 return CGM.PtrDiffTy;
610 return llvm::StructType::get(CGM.PtrDiffTy, CGM.PtrDiffTy);
633CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
635 llvm::Value *&ThisPtrForCall,
643 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
650 llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1,
"memptr.adj");
653 llvm::Value *Adj = RawAdj;
654 if (UseARMMethodPtrABI)
655 Adj = Builder.CreateAShr(Adj, ptrdiff_1,
"memptr.adj.shifted");
660 This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(),
This, Adj);
661 ThisPtrForCall =
This;
664 llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0,
"memptr.ptr");
668 llvm::Value *IsVirtual;
669 if (UseARMMethodPtrABI)
670 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
672 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
673 IsVirtual = Builder.CreateIsNotNull(IsVirtual,
"memptr.isvirtual");
674 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
692 llvm::Value *VTableOffset = FnAsInt;
693 if (!UseARMMethodPtrABI)
694 VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
695 if (Use32BitVTableOffsetABI) {
696 VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.
Int32Ty);
697 VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
702 llvm::Constant *CheckSourceLocation;
703 llvm::Constant *CheckTypeDesc;
704 bool ShouldEmitCFICheck = CGF.
SanOpts.
has(SanitizerKind::CFIMFCall) &&
705 CGM.HasHiddenLTOVisibility(RD);
707 if (ShouldEmitCFICheck) {
708 if (
const auto *BinOp = dyn_cast<BinaryOperator>(E)) {
709 if (BinOp->isPtrMemOp() &&
712 ->hasPointeeToCFIUncheckedCalleeFunctionType())
713 ShouldEmitCFICheck =
false;
717 bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
718 CGM.HasHiddenLTOVisibility(RD);
722 bool ShouldEmitWPDInfo =
723 (CGM.getCodeGenOpts().WholeProgramVTables &&
725 !CGM.AlwaysHasLTOVisibilityPublic(RD)) ||
726 CGM.getCodeGenOpts().DevirtualizeSpeculatively;
727 llvm::Value *VirtualFn =
nullptr;
730 auto CheckOrdinal = SanitizerKind::SO_CFIMFCall;
731 auto CheckHandler = SanitizerHandler::CFICheckFail;
732 SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);
734 llvm::Value *TypeId =
nullptr;
735 llvm::Value *CheckResult =
nullptr;
737 if (ShouldEmitCFICheck || ShouldEmitVFEInfo || ShouldEmitWPDInfo) {
741 CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
745 if (ShouldEmitVFEInfo) {
746 llvm::Value *VFPAddr =
747 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
754 llvm::Value *CheckedLoad = Builder.CreateCall(
755 CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
756 {VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
757 CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
758 VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
762 if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
763 llvm::Value *VFPAddr =
764 Builder.CreateGEP(CGF.
Int8Ty, VTable, VTableOffset);
765 llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
766 ? llvm::Intrinsic::type_test
767 : llvm::Intrinsic::public_type_test;
770 Builder.CreateCall(CGM.getIntrinsic(IID), {VFPAddr, TypeId});
773 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
774 VirtualFn = CGF.
Builder.CreateCall(
775 CGM.getIntrinsic(llvm::Intrinsic::load_relative,
776 {VTableOffset->getType()}),
777 {VTable, VTableOffset});
779 llvm::Value *VFPAddr =
786 assert(VirtualFn &&
"Virtual fuction pointer not created!");
787 assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || !ShouldEmitWPDInfo ||
789 "Check result required but not created!");
791 if (ShouldEmitCFICheck) {
795 llvm::Constant *StaticData[] = {
801 if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
804 llvm::Value *AllVtables = llvm::MetadataAsValue::get(
805 CGM.getLLVMContext(),
806 llvm::MDString::get(CGM.getLLVMContext(),
"all-vtables"));
807 llvm::Value *ValidVtable = Builder.CreateCall(
808 CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
809 CGF.
EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler,
810 StaticData, {VTable, ValidVtable});
813 FnVirtual = Builder.GetInsertBlock();
822 llvm::Value *NonVirtualFn =
823 Builder.CreateIntToPtr(FnAsInt, CGF.
DefaultPtrTy,
"memptr.nonvirtualfn");
826 if (ShouldEmitCFICheck) {
829 auto CheckOrdinal = SanitizerKind::SO_CFIMFCall;
830 auto CheckHandler = SanitizerHandler::CFICheckFail;
831 SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);
833 llvm::Constant *StaticData[] = {
839 llvm::Value *Bit = Builder.getFalse();
840 for (
const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {
841 llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
844 Base->getCanonicalDecl()));
845 llvm::Value *TypeId =
848 llvm::Value *TypeTest =
849 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
850 {NonVirtualFn, TypeId});
851 Bit = Builder.CreateOr(Bit, TypeTest);
854 CGF.
EmitCheck(std::make_pair(Bit, CheckOrdinal), CheckHandler, StaticData,
855 {NonVirtualFn, llvm::UndefValue::get(CGF.
IntPtrTy)});
857 FnNonVirtual = Builder.GetInsertBlock();
863 llvm::PHINode *CalleePtr = Builder.CreatePHI(CGF.
DefaultPtrTy, 2);
864 CalleePtr->addIncoming(VirtualFn, FnVirtual);
865 CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
867 CGPointerAuthInfo PointerAuth;
869 if (
const auto &Schema =
870 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers) {
871 llvm::PHINode *DiscriminatorPHI = Builder.CreatePHI(CGF.
IntPtrTy, 2);
872 DiscriminatorPHI->addIncoming(llvm::ConstantInt::get(CGF.
IntPtrTy, 0),
874 const auto &AuthInfo =
875 CGM.getMemberFunctionPointerAuthInfo(QualType(MPT, 0));
876 assert(Schema.getKey() == AuthInfo.getKey() &&
877 "Keys for virtual and non-virtual member functions must match");
878 auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator();
879 DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual);
880 PointerAuth = CGPointerAuthInfo(
881 Schema.getKey(), Schema.getAuthenticationMode(), Schema.isIsaPointer(),
882 Schema.authenticatesNullValues(), DiscriminatorPHI);
885 CGCallee
Callee(FPT, CalleePtr, PointerAuth);
891llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
892 CodeGenFunction &CGF,
const Expr *E, Address Base, llvm::Value *MemPtr,
893 const MemberPointerType *MPT,
bool IsInBounds) {
894 assert(MemPtr->getType() == CGM.PtrDiffTy);
896 CGBuilderTy &Builder = CGF.
Builder;
899 llvm::Value *BaseAddr =
Base.emitRawPointer(CGF);
900 return Builder.CreateGEP(CGF.
Int8Ty, BaseAddr, MemPtr,
"memptr.offset",
901 IsInBounds ? llvm::GEPNoWrapFlags::inBounds()
902 : llvm::GEPNoWrapFlags::none());
909 const auto *CPA = dyn_cast<llvm::ConstantPtrAuth>(Ptr);
914 assert(CPA->getKey()->getZExtValue() == CurAuthInfo.
getKey() &&
915 CPA->getAddrDiscriminator()->isZeroValue() &&
917 "unexpected key or discriminators");
920 CPA->getPointer(), NewAuthInfo.
getKey(),
nullptr,
948ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
955 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
956 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
959 CGBuilderTy &Builder = CGF.
Builder;
960 QualType DstType = E->
getType();
963 if (
const auto &NewAuthInfo =
964 CGM.getMemberFunctionPointerAuthInfo(DstType)) {
967 const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType);
968 llvm::Value *MemFnPtr = Builder.CreateExtractValue(src, 0,
"memptr.ptr");
969 llvm::Type *OrigTy = MemFnPtr->getType();
971 llvm::BasicBlock *StartBB = Builder.GetInsertBlock();
976 assert(UseARMMethodPtrABI &&
"ARM ABI expected");
977 llvm::Value *Adj = Builder.CreateExtractValue(src, 1,
"memptr.adj");
978 llvm::Constant *Ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1);
979 llvm::Value *AndVal = Builder.CreateAnd(Adj, Ptrdiff_1);
980 llvm::Value *IsVirtualOffset =
981 Builder.CreateIsNotNull(AndVal,
"is.virtual.offset");
982 Builder.CreateCondBr(IsVirtualOffset, MergeBB, ResignBB);
985 llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
986 MemFnPtr = Builder.CreateIntToPtr(MemFnPtr, PtrTy);
990 MemFnPtr = Builder.CreatePtrToInt(MemFnPtr, OrigTy);
991 llvm::Value *ResignedVal = Builder.CreateInsertValue(src, MemFnPtr, 0);
992 ResignBB = Builder.GetInsertBlock();
995 llvm::PHINode *NewSrc = Builder.CreatePHI(src->getType(), 2);
996 NewSrc->addIncoming(src, StartBB);
997 NewSrc->addIncoming(ResignedVal, ResignBB);
1003 if (E->
getCastKind() == CK_ReinterpretMemberPointer)
return src;
1005 llvm::Constant *adj = getMemberPointerAdjustment(E);
1006 if (!adj)
return src;
1008 bool isDerivedToBase = (E->
getCastKind() == CK_DerivedToBaseMemberPointer);
1010 const MemberPointerType *destTy =
1017 if (isDerivedToBase)
1018 dst = Builder.CreateNSWSub(src, adj,
"adj");
1020 dst = Builder.CreateNSWAdd(src, adj,
"adj");
1023 llvm::Value *null = llvm::Constant::getAllOnesValue(src->getType());
1024 llvm::Value *isNull = Builder.CreateICmpEQ(src, null,
"memptr.isnull");
1025 return Builder.CreateSelect(isNull, src, dst);
1029 if (UseARMMethodPtrABI) {
1032 adj = llvm::ConstantInt::get(adj->getType(), offset);
1035 llvm::Value *srcAdj = Builder.CreateExtractValue(src, 1,
"src.adj");
1036 llvm::Value *dstAdj;
1037 if (isDerivedToBase)
1038 dstAdj = Builder.CreateNSWSub(srcAdj, adj,
"adj");
1040 dstAdj = Builder.CreateNSWAdd(srcAdj, adj,
"adj");
1042 return Builder.CreateInsertValue(src, dstAdj, 1);
1045static llvm::Constant *
1050 "member function pointers expected");
1051 if (DestType == SrcType)
1057 if (!NewAuthInfo && !CurAuthInfo)
1060 llvm::Constant *MemFnPtr = Src->getAggregateElement(0u);
1061 if (MemFnPtr->getNumOperands() == 0) {
1069 ConstPtr = llvm::ConstantExpr::getPtrToInt(ConstPtr, MemFnPtr->getType());
1070 return ConstantFoldInsertValueInstruction(Src, ConstPtr, 0);
1074ItaniumCXXABI::EmitMemberPointerConversion(
const CastExpr *E,
1075 llvm::Constant *src) {
1076 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
1077 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
1080 QualType DstType = E->
getType();
1087 if (E->
getCastKind() == CK_ReinterpretMemberPointer)
return src;
1090 llvm::Constant *adj = getMemberPointerAdjustment(E);
1091 if (!adj)
return src;
1093 bool isDerivedToBase = (E->
getCastKind() == CK_DerivedToBaseMemberPointer);
1095 const MemberPointerType *destTy =
1102 if (src->isAllOnesValue())
return src;
1104 if (isDerivedToBase)
1105 return llvm::ConstantExpr::getNSWSub(src, adj);
1107 return llvm::ConstantExpr::getNSWAdd(src, adj);
1111 if (UseARMMethodPtrABI) {
1114 adj = llvm::ConstantInt::get(adj->getType(), offset);
1117 llvm::Constant *srcAdj = src->getAggregateElement(1);
1118 llvm::Constant *dstAdj;
1119 if (isDerivedToBase)
1120 dstAdj = llvm::ConstantExpr::getNSWSub(srcAdj, adj);
1122 dstAdj = llvm::ConstantExpr::getNSWAdd(srcAdj, adj);
1124 llvm::Constant *res = ConstantFoldInsertValueInstruction(src, dstAdj, 1);
1125 assert(res !=
nullptr &&
"Folding must succeed");
1130ItaniumCXXABI::EmitNullMemberPointer(
const MemberPointerType *MPT) {
1134 return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL,
true);
1136 llvm::Constant *
Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
1137 llvm::Constant *Values[2] = {
Zero,
Zero };
1138 return llvm::ConstantStruct::getAnon(Values);
1142ItaniumCXXABI::EmitMemberDataPointer(
const MemberPointerType *MPT,
1147 return llvm::ConstantInt::get(CGM.PtrDiffTy, offset.
getQuantity());
1151ItaniumCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
1155llvm::Constant *ItaniumCXXABI::BuildMemberPointer(
const CXXMethodDecl *MD,
1156 CharUnits ThisAdjustment) {
1157 assert(MD->
isInstance() &&
"Member function must not be static!");
1159 CodeGenTypes &Types = CGM.getTypes();
1162 llvm::Constant *MemPtr[2];
1164 uint64_t Index = CGM.getItaniumVTableContext().getMethodVTableIndex(MD);
1166 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1168 VTableOffset = Index * 4;
1170 const ASTContext &Context = getContext();
1173 VTableOffset = Index * PointerWidth.
getQuantity();
1176 if (UseARMMethodPtrABI) {
1198 const auto &Schema =
1199 CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers;
1201 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(
1202 getSignedVirtualMemberFunctionPointer(MD), CGM.PtrDiffTy);
1204 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset);
1207 MemPtr[1] = llvm::ConstantInt::get(
1208 CGM.PtrDiffTy, 2 * ThisAdjustment.
getQuantity() + !Schema);
1214 MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
1215 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1219 const FunctionProtoType *FPT = MD->
getType()->
castAs<FunctionProtoType>();
1230 llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty);
1232 MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
1233 MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
1234 (UseARMMethodPtrABI ? 2 : 1) *
1238 return llvm::ConstantStruct::getAnon(MemPtr);
1241llvm::Constant *ItaniumCXXABI::EmitMemberPointer(
const APValue &MP,
1243 const MemberPointerType *MPT = MPType->
castAs<MemberPointerType>();
1246 return EmitNullMemberPointer(MPT);
1248 CharUnits ThisAdjustment = getContext().getMemberPointerPathAdjustment(MP);
1250 if (
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
1251 llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment);
1252 QualType SrcType = getContext().getMemberPointerType(
1257 CharUnits FieldOffset =
1258 getContext().toCharUnitsFromBits(getContext().
getFieldOffset(MPD));
1259 return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
1267ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
1270 const MemberPointerType *MPT,
1272 CGBuilderTy &Builder = CGF.
Builder;
1274 llvm::ICmpInst::Predicate Eq;
1275 llvm::Instruction::BinaryOps
And,
Or;
1277 Eq = llvm::ICmpInst::ICMP_NE;
1278 And = llvm::Instruction::Or;
1279 Or = llvm::Instruction::And;
1281 Eq = llvm::ICmpInst::ICMP_EQ;
1282 And = llvm::Instruction::And;
1283 Or = llvm::Instruction::Or;
1289 return Builder.CreateICmp(Eq, L, R);
1301 llvm::Value *LPtr = Builder.CreateExtractValue(L, 0,
"lhs.memptr.ptr");
1302 llvm::Value *RPtr = Builder.CreateExtractValue(R, 0,
"rhs.memptr.ptr");
1306 llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr,
"cmp.ptr");
1311 llvm::Value *
Zero = llvm::Constant::getNullValue(LPtr->getType());
1312 llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr,
Zero,
"cmp.ptr.null");
1316 llvm::Value *LAdj = Builder.CreateExtractValue(L, 1,
"lhs.memptr.adj");
1317 llvm::Value *RAdj = Builder.CreateExtractValue(R, 1,
"rhs.memptr.adj");
1318 llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj,
"cmp.adj");
1322 if (UseARMMethodPtrABI) {
1323 llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
1326 llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj,
"or.adj");
1327 llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
1328 llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1,
Zero,
1330 EqZero = Builder.CreateBinOp(
And, EqZero, OrAdjAnd1EqZero);
1334 llvm::Value *
Result = Builder.CreateBinOp(
Or, EqZero, AdjEq);
1336 Inequality ?
"memptr.ne" :
"memptr.eq");
1341ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
1342 llvm::Value *MemPtr,
1343 const MemberPointerType *MPT) {
1344 CGBuilderTy &Builder = CGF.
Builder;
1348 assert(MemPtr->getType() == CGM.PtrDiffTy);
1349 llvm::Value *NegativeOne =
1350 llvm::Constant::getAllOnesValue(MemPtr->getType());
1351 return Builder.CreateICmpNE(MemPtr, NegativeOne,
"memptr.tobool");
1355 llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0,
"memptr.ptr");
1357 llvm::Constant *
Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
1358 llvm::Value *
Result = Builder.CreateICmpNE(Ptr,
Zero,
"memptr.tobool");
1362 if (UseARMMethodPtrABI) {
1363 llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
1364 llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1,
"memptr.adj");
1365 llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One,
"memptr.virtualbit");
1366 llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit,
Zero,
1367 "memptr.isvirtual");
1374bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI)
const {
1375 const CXXRecordDecl *RD = FI.
getReturnType()->getAsCXXRecordDecl();
1381 auto Align = CGM.getContext().getTypeAlignInChars(FI.
getReturnType());
1383 Align, CGM.getDataLayout().getAllocaAddrSpace(),
1392bool ItaniumCXXABI::isZeroInitializable(
const MemberPointerType *MPT) {
1398void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
1399 const CXXDeleteExpr *DE,
1401 QualType ElementType,
1402 const CXXDestructorDecl *Dtor) {
1404 if (UseGlobalDelete) {
1413 llvm::Value *OffsetPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
1414 CGF.
IntPtrTy, VTable, -2,
"complete-offset.ptr");
1432 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,
1435 if (UseGlobalDelete)
1439void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF,
bool isNoReturn) {
1442 llvm::FunctionType *FTy =
1443 llvm::FunctionType::get(CGM.VoidTy,
false);
1445 llvm::FunctionCallee
Fn = CGM.CreateRuntimeFunction(FTy,
"__cxa_rethrow");
1456 llvm::FunctionType *FTy =
1467 llvm::FunctionType *FTy =
1468 llvm::FunctionType::get(CGM.
VoidTy, Args,
false);
1473void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF,
const CXXThrowExpr *E) {
1476 llvm::Type *SizeTy = CGF.
ConvertType(getContext().getSizeType());
1477 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
1481 AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize),
"exception");
1485 E->
getSubExpr(), Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
1488 llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
1493 llvm::Constant *Dtor =
nullptr;
1499 const ASTContext &Ctx = getContext();
1501 FunctionProtoType::ExtProtoInfo());
1503 CXXDestructorDecl *DtorD =
Record->getDestructor();
1504 Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD,
Dtor_Complete));
1505 Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
1507 if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
1509 llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };
1521 llvm::Type *PtrDiffTy =
1524 llvm::Type *Args[4] = { Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy };
1526 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args,
false);
1530 FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
1531 FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
1532 FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
1533 llvm::AttributeList Attrs = llvm::AttributeList::get(
1534 CGF.
getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
1541 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1558 unsigned NumPublicPaths = 0;
1571 if (PathElement.Base->isVirtual())
1574 if (NumPublicPaths > 1)
1578 const ASTRecordLayout &L = Context.getASTRecordLayout(PathElement.Class);
1580 PathElement.Base->getType()->getAsCXXRecordDecl());
1585 if (NumPublicPaths == 0)
1589 if (NumPublicPaths > 1)
1599 llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
1604bool ItaniumCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {
1608void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
1611 Call->setDoesNotReturn();
1612 CGF.
Builder.CreateUnreachable();
1615llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
1616 QualType SrcRecordTy,
1618 llvm::Type *StdTypeInfoPtrTy) {
1623 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1626 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
1627 {Value, llvm::ConstantInt::get(CGM.Int32Ty, -4)});
1631 CGF.
Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy,
Value, -1ULL);
1637bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
1638 QualType SrcRecordTy) {
1642llvm::Value *ItaniumCXXABI::emitDynamicCastCall(
1643 CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
1644 QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
1645 llvm::Type *PtrDiffLTy =
1648 llvm::Value *SrcRTTI =
1650 llvm::Value *DestRTTI =
1656 llvm::Value *OffsetHint = llvm::ConstantInt::get(
1662 if (CGM.getCodeGenOpts().PointerAuth.CXXVTablePointers) {
1668 llvm::Value *Vtable =
1670 CodeGenFunction::VTableAuthMode::MustTrap);
1675 llvm::Value *args[] = {
Value, SrcRTTI, DestRTTI, OffsetHint};
1681 llvm::BasicBlock *BadCastBlock =
1688 EmitBadCastCall(CGF);
1694std::optional<CGCXXABI::ExactDynamicCastInfo>
1695ItaniumCXXABI::getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,
1696 QualType DestRecordTy) {
1697 assert(shouldEmitExactDynamicCast(DestRecordTy));
1699 ASTContext &Context = getContext();
1704 CXXBasePaths Paths(
true,
true,
1710 std::optional<CharUnits> Offset;
1711 for (
const CXXBasePath &Path : Paths) {
1716 CharUnits PathOffset;
1717 for (
const CXXBasePathElement &PathElement : Path) {
1719 const CXXRecordDecl *
Base =
1720 PathElement.Base->getType()->getAsCXXRecordDecl();
1721 if (PathElement.Base->isVirtual()) {
1727 const ASTRecordLayout &L =
1734 Offset = PathOffset;
1735 else if (Offset != PathOffset) {
1737 return ExactDynamicCastInfo{
true,
1742 return std::nullopt;
1743 return ExactDynamicCastInfo{
false, *Offset};
1746llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
1747 CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
1748 QualType DestTy, QualType DestRecordTy,
1749 const ExactDynamicCastInfo &ExactCastInfo, llvm::BasicBlock *CastSuccess,
1750 llvm::BasicBlock *CastFail) {
1753 auto AuthenticateVTable = [&](Address ThisAddr,
const CXXRecordDecl *
Decl) {
1757 CodeGenFunction::VTableAuthMode::MustTrap);
1760 bool PerformPostCastAuthentication =
false;
1761 llvm::Value *VTable =
nullptr;
1762 if (ExactCastInfo.RequiresCastToPrimaryBase) {
1767 llvm::Value *PrimaryBase =
1774 PerformPostCastAuthentication = CGF.
getLangOpts().PointerAuthCalls;
1775 CGPointerAuthInfo StrippingAuthInfo(0, PointerAuthenticationMode::Strip,
1776 false,
false,
nullptr);
1779 if (PerformPostCastAuthentication)
1786 llvm::Constant *ExpectedVTable = getVTableAddressPoint(
1787 BaseSubobject(SrcDecl, ExactCastInfo.Offset), DestDecl);
1788 llvm::Value *
Success = CGF.
Builder.CreateICmpEQ(VTable, ExpectedVTable);
1791 if (!ExactCastInfo.Offset.isZero()) {
1793 llvm::Constant *OffsetConstant =
1794 llvm::ConstantInt::get(CGF.
PtrDiffTy, -Offset);
1797 PerformPostCastAuthentication = CGF.
getLangOpts().PointerAuthCalls;
1800 if (PerformPostCastAuthentication) {
1803 llvm::BasicBlock *NonNullBlock = CGF.
Builder.GetInsertBlock();
1804 llvm::BasicBlock *PostCastAuthSuccess =
1806 llvm::BasicBlock *PostCastAuthComplete =
1809 PostCastAuthComplete);
1811 Address AdjustedThisAddr =
1813 AuthenticateVTable(AdjustedThisAddr, DestDecl);
1816 llvm::PHINode *PHI = CGF.
Builder.CreatePHI(AdjustedThisPtr->getType(), 2);
1817 PHI->addIncoming(AdjustedThisPtr, PostCastAuthSuccess);
1818 llvm::Value *NullValue =
1819 llvm::Constant::getNullValue(AdjustedThisPtr->getType());
1820 PHI->addIncoming(NullValue, NonNullBlock);
1821 AdjustedThisPtr = PHI;
1824 return AdjustedThisPtr;
1827llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
1829 QualType SrcRecordTy) {
1831 llvm::Value *OffsetToTop;
1832 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1834 llvm::Value *VTable =
1839 CGF.
Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);
1843 llvm::Type *PtrDiffLTy =
1847 llvm::Value *VTable =
1852 CGF.
Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
1861bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
1864 Call->setDoesNotReturn();
1865 CGF.
Builder.CreateUnreachable();
1870ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
1872 const CXXRecordDecl *ClassDecl,
1873 const CXXRecordDecl *BaseClassDecl) {
1874 llvm::Value *VTablePtr = CGF.
GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
1875 CharUnits VBaseOffsetOffset =
1876 CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
1878 llvm::Value *VBaseOffsetPtr =
1879 CGF.
Builder.CreateConstGEP1_64(
1881 "vbase.offset.ptr");
1883 llvm::Value *VBaseOffset;
1884 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
1890 CGM.PtrDiffTy, VBaseOffsetPtr, CGF.
getPointerAlign(),
"vbase.offset");
1895void ItaniumCXXABI::EmitCXXConstructors(
const CXXConstructorDecl *D) {
1897 assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
1901 CGM.EmitGlobal(GlobalDecl(D,
Ctor_Base));
1911CGCXXABI::AddedStructorArgCounts
1912ItaniumCXXABI::buildStructorSignature(GlobalDecl GD,
1913 SmallVectorImpl<CanQualType> &ArgTys) {
1914 ASTContext &Context = getContext();
1923 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
1925 ArgTys.insert(ArgTys.begin() + 1,
1927 return AddedStructorArgCounts::prefix(1);
1929 return AddedStructorArgCounts{};
1932void ItaniumCXXABI::EmitCXXDestructors(
const CXXDestructorDecl *D) {
1935 CGM.EmitGlobal(GlobalDecl(D,
Dtor_Base));
1948void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
1950 FunctionArgList &Params) {
1955 if (NeedsVTTParameter(CGF.
CurGD)) {
1956 ASTContext &Context = getContext();
1959 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
1964 T, ImplicitParamKind::CXXVTT);
1965 Params.insert(Params.begin() + 1, VTTDecl);
1966 getStructorImplicitParamDecl(CGF) = VTTDecl;
1970void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
1977 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
1980 if (getStructorImplicitParamDecl(CGF)) {
1993 if (HasThisReturn(CGF.
CurGD))
1997CGCXXABI::AddedStructorArgs ItaniumCXXABI::getImplicitConstructorArgs(
2000 if (!NeedsVTTParameter(GlobalDecl(D,
Type)))
2001 return AddedStructorArgs{};
2008 LangAS AS = CGM.GetGlobalVarAddressSpace(
nullptr);
2009 QualType Q = getContext().getAddrSpaceQualType(getContext().VoidPtrTy, AS);
2010 QualType VTTTy = getContext().getPointerType(Q);
2011 return AddedStructorArgs::prefix({{VTT, VTTTy}});
2014llvm::Value *ItaniumCXXABI::getCXXDestructorImplicitParam(
2017 GlobalDecl GD(DD,
Type);
2021void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
2022 const CXXDestructorDecl *DD,
2026 GlobalDecl GD(DD,
Type);
2029 QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
2032 if (getContext().getLangOpts().AppleKext &&
2039 ThisTy, VTT, VTTTy,
nullptr);
2043template <
typename T>
2046 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
2059 llvm::GlobalVariable *VTable,
2061 if (VTable->getDLLStorageClass() !=
2062 llvm::GlobalVariable::DefaultStorageClass ||
2068 VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2070 VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2073void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
2074 const CXXRecordDecl *RD) {
2075 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, CharUnits());
2076 if (VTable->hasInitializer())
2079 ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
2081 llvm::GlobalVariable::LinkageTypes
Linkage = CGM.getVTableLinkage(RD);
2082 llvm::Constant *RTTI =
2083 CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getCanonicalTagType(RD));
2086 ConstantInitBuilder builder(CGM);
2087 auto components = builder.beginStruct();
2089 llvm::GlobalValue::isLocalLinkage(
Linkage));
2090 components.finishAndSetAsInitializer(VTable);
2095 if (CGM.supportsCOMDAT() && VTable->isWeakForLinker())
2096 VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName()));
2098 if (CGM.getTarget().hasPS4DLLImportExport())
2102 CGM.setGVProperties(VTable, RD);
2113 EmitFundamentalRTTIDescriptors(RD);
2121 if (!VTable->isDeclarationForLinker() ||
2122 CGM.getCodeGenOpts().WholeProgramVTables ||
2123 CGM.getCodeGenOpts().DevirtualizeSpeculatively) {
2124 CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
2128 if (VTable->isDeclarationForLinker()) {
2129 assert(CGM.getCodeGenOpts().WholeProgramVTables ||
2130 CGM.getCodeGenOpts().DevirtualizeSpeculatively);
2131 CGM.addCompilerUsedGlobal(VTable);
2137 if (!VTable->isDSOLocal())
2142 if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
2143 DI->emitVTableSymbol(VTable, RD);
2146bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
2147 CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
2150 return NeedsVTTParameter(CGF.
CurGD);
2153llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor(
2154 CodeGenFunction &CGF,
const CXXRecordDecl *VTableClass, BaseSubobject Base,
2155 const CXXRecordDecl *NearestVBase) {
2157 if ((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
2158 NeedsVTTParameter(CGF.
CurGD)) {
2159 return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base,
2162 return getVTableAddressPoint(Base, VTableClass);
2166ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
2167 const CXXRecordDecl *VTableClass) {
2168 llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());
2172 const VTableLayout &Layout =
2173 CGM.getItaniumVTableContext().getVTableLayout(VTableClass);
2174 VTableLayout::AddressPointLocation AddressPoint =
2176 llvm::Value *Indices[] = {
2177 llvm::ConstantInt::get(CGM.Int32Ty, 0),
2178 llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.
VTableIndex),
2184 unsigned ComponentSize =
2185 CGM.getDataLayout().getTypeAllocSize(CGM.getVTableComponentType());
2186 unsigned VTableSize =
2189 llvm::ConstantRange InRange(
2190 llvm::APInt(32, (
int)-Offset,
true),
2191 llvm::APInt(32, (
int)(VTableSize - Offset),
true));
2192 return llvm::ConstantExpr::getGetElementPtr(
2193 VTable->getValueType(), VTable, Indices,
true, InRange);
2196llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
2197 CodeGenFunction &CGF,
const CXXRecordDecl *VTableClass, BaseSubobject Base,
2198 const CXXRecordDecl *NearestVBase) {
2199 assert((
Base.getBase()->getNumVBases() || NearestVBase !=
nullptr) &&
2200 NeedsVTTParameter(CGF.
CurGD) &&
"This class doesn't have VTT");
2204 CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
2208 if (VirtualPointerIndex)
2210 VirtualPointerIndex);
2227llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(
const CXXRecordDecl *RD,
2228 CharUnits VPtrOffset) {
2229 assert(VPtrOffset.
isZero() &&
"Itanium ABI only supports zero vptr offsets");
2231 llvm::GlobalVariable *&VTable = VTables[RD];
2236 CGM.addDeferredVTable(RD);
2238 SmallString<256> Name;
2239 llvm::raw_svector_ostream
Out(Name);
2240 getMangleContext().mangleCXXVTable(RD, Out);
2242 const VTableLayout &VTLayout =
2243 CGM.getItaniumVTableContext().getVTableLayout(RD);
2244 llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
2249 unsigned PAlign = CGM.getVtableGlobalVarAlignment();
2251 VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
2252 Name, VTableType, llvm::GlobalValue::ExternalLinkage,
2253 getContext().toCharUnitsFromBits(PAlign).getAsAlign());
2254 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2256 if (CGM.getTarget().hasPS4DLLImportExport())
2259 CGM.setGVProperties(VTable, RD);
2263CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
2267 SourceLocation Loc) {
2268 llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy;
2270 llvm::Value *VTable = CGF.
GetVTablePtr(This, PtrTy, MethodDecl->getParent());
2272 uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
2273 llvm::Value *VFunc, *VTableSlotPtr =
nullptr;
2274 auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers;
2276 llvm::Type *ComponentTy = CGM.getVTables().getVTableComponentType();
2278 VTableIndex * CGM.getDataLayout().getTypeSizeInBits(ComponentTy) / 8;
2286 llvm::Value *VFuncLoad;
2287 if (CGM.getItaniumVTableContext().isRelativeLayout()) {
2288 VFuncLoad = CGF.
Builder.CreateCall(
2289 CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
2290 {VTable, llvm::ConstantInt::get(CGM.Int32Ty, ByteOffset)});
2292 VTableSlotPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
2293 PtrTy, VTable, VTableIndex,
"vfn");
2304 if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
2305 CGM.getCodeGenOpts().StrictVTablePointers) {
2306 if (
auto *VFuncLoadInstr = dyn_cast<llvm::Instruction>(VFuncLoad)) {
2307 VFuncLoadInstr->setMetadata(
2308 llvm::LLVMContext::MD_invariant_load,
2309 llvm::MDNode::get(CGM.getLLVMContext(),
2310 llvm::ArrayRef<llvm::Metadata *>()));
2316 CGPointerAuthInfo PointerAuth;
2318 assert(VTableSlotPtr &&
"virtual function pointer not set");
2319 GD = CGM.getItaniumVTableContext().findOriginalMethod(GD.
getCanonicalDecl());
2322 CGCallee
Callee(GD, VFunc, PointerAuth);
2326llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
2327 CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
2328 Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke) {
2329 auto *CE = dyn_cast<const CXXMemberCallExpr *>(E);
2330 auto *D = dyn_cast<const CXXDeleteExpr *>(E);
2331 assert((CE !=
nullptr) ^ (D !=
nullptr));
2332 assert(CE ==
nullptr || CE->arguments().empty());
2335 GlobalDecl GD(Dtor, DtorType);
2336 const CGFunctionInfo *FInfo =
2337 &CGM.getTypes().arrangeCXXStructorDeclaration(GD);
2343 ThisTy = CE->getObjectType();
2345 ThisTy = D->getDestroyedType();
2349 nullptr, QualType(),
nullptr, CallOrInvoke);
2353void ItaniumCXXABI::emitVirtualInheritanceTables(
const CXXRecordDecl *RD) {
2354 CodeGenVTables &VTables = CGM.getVTables();
2359bool ItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
2360 const CXXRecordDecl *RD)
const {
2363 if (CGM.getLangOpts().AppleKext)
2368 if (isVTableHidden(RD))
2371 if (CGM.getCodeGenOpts().ForceEmitVTables)
2388 if (hasAnyUnusedVirtualInlineFunction(RD))
2396 for (
const auto &B : RD->
bases()) {
2397 auto *BRD = B.getType()->getAsCXXRecordDecl();
2398 assert(BRD &&
"no class for base specifier");
2399 if (B.isVirtual() || !BRD->isDynamicClass())
2401 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2409bool ItaniumCXXABI::canSpeculativelyEmitVTable(
const CXXRecordDecl *RD)
const {
2410 if (!canSpeculativelyEmitVTableAsBaseClass(RD))
2418 for (
const auto &B : RD->
vbases()) {
2419 auto *BRD = B.getType()->getAsCXXRecordDecl();
2420 assert(BRD &&
"no class for base specifier");
2421 if (!BRD->isDynamicClass())
2423 if (!canSpeculativelyEmitVTableAsBaseClass(BRD))
2432 int64_t NonVirtualAdjustment,
2433 int64_t VirtualAdjustment,
2434 bool IsReturnAdjustment) {
2435 if (!NonVirtualAdjustment && !VirtualAdjustment)
2441 if (NonVirtualAdjustment && !IsReturnAdjustment) {
2447 llvm::Value *ResultPtr;
2448 if (VirtualAdjustment) {
2449 llvm::Value *VTablePtr =
2452 llvm::Value *Offset;
2453 llvm::Value *OffsetPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
2454 CGF.
Int8Ty, VTablePtr, VirtualAdjustment);
2461 llvm::Type *PtrDiffTy =
2470 V.emitRawPointer(CGF), Offset);
2472 ResultPtr =
V.emitRawPointer(CGF);
2477 if (NonVirtualAdjustment && IsReturnAdjustment) {
2478 ResultPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(CGF.
Int8Ty, ResultPtr,
2479 NonVirtualAdjustment);
2486ItaniumCXXABI::performThisAdjustment(CodeGenFunction &CGF, Address This,
2487 const CXXRecordDecl *UnadjustedClass,
2488 const ThunkInfo &TI) {
2495ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
2496 const CXXRecordDecl *UnadjustedClass,
2497 const ReturnAdjustment &RA) {
2503void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
2504 RValue RV, QualType ResultType) {
2506 return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
2511 return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
2516CharUnits ItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2520 CGM.getContext().getPreferredTypeAlignInChars(elementType));
2523Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
2525 llvm::Value *NumElements,
2526 const CXXNewExpr *
expr,
2527 QualType ElementType) {
2528 assert(requiresArrayCookie(
expr));
2532 ASTContext &Ctx = getContext();
2536 CharUnits CookieSize =
2538 assert(CookieSize == getArrayCookieSizeImpl(ElementType));
2541 Address CookiePtr = NewPtr;
2542 CharUnits CookieOffset = CookieSize - SizeSize;
2543 if (!CookieOffset.
isZero())
2551 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) && AS == 0 &&
2552 (
expr->getOperatorNew()->isReplaceableGlobalAllocationFunction() ||
2553 CGM.getCodeGenOpts().SanitizeAddressPoisonCustomArrayCookie)) {
2555 SI->setNoSanitizeMetadata();
2556 llvm::FunctionType *FTy =
2557 llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.
getType(),
false);
2558 llvm::FunctionCallee F =
2559 CGM.CreateRuntimeFunction(FTy,
"__asan_poison_cxx_array_cookie");
2568llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2570 CharUnits cookieSize) {
2572 Address numElementsPtr = allocPtr;
2573 CharUnits numElementsOffset = cookieSize - CGF.
getSizeSize();
2574 if (!numElementsOffset.
isZero())
2580 if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address) || AS != 0)
2587 llvm::FunctionType *FTy =
2589 llvm::FunctionCallee F =
2590 CGM.CreateRuntimeFunction(FTy,
"__asan_load_cxx_array_cookie");
2594CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2604 CGM.getContext().getTypeAlignInChars(elementType));
2607Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
2609 llvm::Value *numElements,
2610 const CXXNewExpr *
expr,
2611 QualType elementType) {
2612 assert(requiresArrayCookie(
expr));
2615 Address cookie = newPtr;
2619 llvm::Value *elementSize = llvm::ConstantInt::get(CGF.
SizeTy,
2620 getContext().getTypeSizeInChars(elementType).getQuantity());
2629 CharUnits cookieSize = ARMCXXABI::getArrayCookieSizeImpl(elementType);
2633llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2635 CharUnits cookieSize) {
2638 Address numElementsPtr
2648 llvm::PointerType *GuardPtrTy) {
2650 llvm::FunctionType *FTy =
2654 FTy,
"__cxa_guard_acquire",
2656 llvm::AttributeList::FunctionIndex,
2657 llvm::Attribute::NoUnwind));
2661 llvm::PointerType *GuardPtrTy) {
2663 llvm::FunctionType *FTy =
2664 llvm::FunctionType::get(CGM.
VoidTy, GuardPtrTy,
false);
2666 FTy,
"__cxa_guard_release",
2668 llvm::AttributeList::FunctionIndex,
2669 llvm::Attribute::NoUnwind));
2673 llvm::PointerType *GuardPtrTy) {
2675 llvm::FunctionType *FTy =
2676 llvm::FunctionType::get(CGM.
VoidTy, GuardPtrTy,
false);
2678 FTy,
"__cxa_guard_abort",
2680 llvm::AttributeList::FunctionIndex,
2681 llvm::Attribute::NoUnwind));
2685 struct CallGuardAbort final : EHScopeStack::Cleanup {
2686 llvm::GlobalVariable *Guard;
2687 CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
2689 void Emit(CodeGenFunction &CGF, Flags flags)
override {
2698void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
2700 llvm::GlobalVariable *var,
2701 bool shouldPerformInit) {
2702 CGBuilderTy &Builder = CGF.
Builder;
2706 bool NonTemplateInline =
2713 bool threadsafe = getContext().getLangOpts().ThreadsafeStatics &&
2719 bool useInt8GuardVariable = !threadsafe &&
var->hasInternalLinkage();
2721 llvm::IntegerType *guardTy;
2722 CharUnits guardAlignment;
2723 if (useInt8GuardVariable) {
2729 if (UseARMGuardVarABI) {
2738 llvm::PointerType *guardPtrTy = llvm::PointerType::get(
2744 llvm::GlobalVariable *guard = CGM.getStaticLocalDeclGuardAddress(&D);
2747 SmallString<256> guardName;
2749 llvm::raw_svector_ostream
out(guardName);
2750 getMangleContext().mangleStaticGuardVariable(&D,
out);
2756 guard =
new llvm::GlobalVariable(CGM.getModule(), guardTy,
2757 false,
var->getLinkage(),
2758 llvm::ConstantInt::get(guardTy, 0),
2760 guard->setDSOLocal(
var->isDSOLocal());
2761 guard->setVisibility(
var->getVisibility());
2762 guard->setDLLStorageClass(
var->getDLLStorageClass());
2764 guard->setThreadLocalMode(
var->getThreadLocalMode());
2765 guard->setAlignment(guardAlignment.
getAsAlign());
2770 llvm::Comdat *
C =
var->getComdat();
2772 (CGM.getTarget().getTriple().isOSBinFormatELF() ||
2773 CGM.getTarget().getTriple().isOSBinFormatWasm())) {
2774 guard->setComdat(
C);
2775 }
else if (CGM.supportsCOMDAT() && guard->isWeakForLinker()) {
2776 guard->setComdat(CGM.getModule().getOrInsertComdat(guard->getName()));
2779 CGM.setStaticLocalDeclGuardAddress(&D, guard);
2782 Address guardAddr = Address(guard, guard->getValueType(), guardAlignment);
2807 if (!threadsafe || MaxInlineWidthInBits) {
2809 llvm::LoadInst *LI =
2819 LI->setAtomic(llvm::AtomicOrdering::Acquire);
2842 (UseARMGuardVarABI && !useInt8GuardVariable)
2843 ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
2845 llvm::Value *NeedsInit = Builder.CreateIsNull(
V,
"guard.uninitialized");
2851 CodeGenFunction::GuardKind::VariableGuard, &D);
2879 Builder.CreateCondBr(Builder.CreateIsNotNull(
V,
"tobool"),
2880 InitBlock, EndBlock);
2890 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2908 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
2917 llvm::FunctionCallee dtor,
2918 llvm::Constant *addr,
bool TLS) {
2920 "unexpected call to emitGlobalDtorWithCXAAtExit");
2922 "__cxa_atexit is disabled");
2923 const char *Name =
"__cxa_atexit";
2926 Name =
T.isOSDarwin() ?
"_tlv_atexit" :
"__cxa_thread_atexit";
2934 auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0;
2935 auto AddrPtrTy = AddrAS ? llvm::PointerType::get(CGF.
getLLVMContext(), AddrAS)
2939 llvm::Constant *handle =
2942 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
2945 llvm::Type *paramTys[] = {
dtorTy, AddrPtrTy, handle->getType()};
2946 llvm::FunctionType *atexitTy =
2947 llvm::FunctionType::get(CGF.
IntTy, paramTys,
false);
2951 if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee()))
2952 fn->setDoesNotThrow();
2958 Context.getFunctionType(Context.VoidTy, {Context.VoidPtrTy}, EPI);
2967 addr = llvm::Constant::getNullValue(CGF.
Int8PtrTy);
2969 llvm::Value *args[] = {dtorCallee, addr, handle};
2977 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
2981 return GlobalInitOrCleanupFn;
2984void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {
2985 for (
const auto &I : DtorsUsingAtExit) {
2986 int Priority = I.first;
2987 std::string GlobalCleanupFnName =
2988 std::string(
"__GLOBAL_cleanup_") + llvm::to_string(Priority);
2990 llvm::Function *GlobalCleanupFn =
2993 CodeGenFunction CGF(*
this);
2994 CGF.
StartFunction(GlobalDecl(), getContext().VoidTy, GlobalCleanupFn,
2995 getTypes().arrangeNullaryFunction(), FunctionArgList(),
2996 SourceLocation(), SourceLocation());
3000 llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.
VoidTy,
false);
3004 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
3005 auto itv = Dtors.rbegin();
3006 while (itv != Dtors.rend()) {
3007 llvm::Function *Dtor = *itv;
3012 llvm::Value *NeedsDestruct =
3015 llvm::BasicBlock *DestructCallBlock =
3018 (itv + 1) != Dtors.rend() ?
"unatexit.call" :
"destruct.end");
3021 CGF.
Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
3026 llvm::CallInst *CI = CGF.
Builder.CreateCall(dtorFuncTy, Dtor);
3028 CI->setCallingConv(Dtor->getCallingConv());
3036 AddGlobalDtor(GlobalCleanupFn, Priority);
3040void CodeGenModule::registerGlobalDtorsWithAtExit() {
3041 for (
const auto &I : DtorsUsingAtExit) {
3042 int Priority = I.first;
3043 std::string GlobalInitFnName =
3044 std::string(
"__GLOBAL_init_") + llvm::to_string(Priority);
3045 llvm::Function *GlobalInitFn =
3048 CodeGenFunction CGF(*
this);
3049 CGF.
StartFunction(GlobalDecl(), getContext().VoidTy, GlobalInitFn,
3050 getTypes().arrangeNullaryFunction(), FunctionArgList(),
3051 SourceLocation(), SourceLocation());
3059 const llvm::TinyPtrVector<llvm::Function *> &Dtors = I.second;
3060 for (
auto *Dtor : Dtors) {
3063 if (getCodeGenOpts().CXAAtExit) {
3073 AddGlobalCtor(GlobalInitFn, Priority);
3076 if (getCXXABI().useSinitAndSterm())
3077 unregisterGlobalDtorsWithUnAtExit();
3081void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
3082 llvm::FunctionCallee dtor,
3083 llvm::Constant *addr) {
3088 if (CGM.getLangOpts().HLSL)
3089 return CGM.AddCXXDtorEntry(dtor, addr);
3103 if (CGM.getCodeGenOpts().CXAAtExit || D.
getTLSKind())
3108 if (CGM.getLangOpts().AppleKext) {
3110 return CGM.AddCXXDtorEntry(dtor, addr);
3118 assert(!VD->
isStaticLocal() &&
"static local VarDecls don't need wrappers!");
3128static llvm::GlobalValue::LinkageTypes
3130 llvm::GlobalValue::LinkageTypes VarLinkage =
3134 if (llvm::GlobalValue::isLocalLinkage(VarLinkage))
3139 if (!llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) &&
3140 !llvm::GlobalVariable::isWeakODRLinkage(VarLinkage))
3142 return llvm::GlobalValue::WeakODRLinkage;
3146ItaniumCXXABI::getOrCreateThreadLocalWrapper(
const VarDecl *VD,
3149 SmallString<256> WrapperName;
3151 llvm::raw_svector_ostream
Out(WrapperName);
3152 getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out);
3157 if (llvm::Value *
V = CGM.getModule().getNamedValue(WrapperName))
3160 QualType RetQT = VD->
getType();
3164 const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
3165 getContext().getPointerType(RetQT), FunctionArgList());
3167 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FI);
3168 llvm::Function *Wrapper =
3170 WrapperName.str(), &CGM.getModule());
3172 if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())
3173 Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));
3175 CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper,
false);
3178 if (!Wrapper->hasLocalLinkage())
3180 llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) ||
3181 llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) ||
3183 Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility);
3186 Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3187 Wrapper->addFnAttr(llvm::Attribute::NoUnwind);
3190 ThreadWrappers.push_back({VD, Wrapper});
3194void ItaniumCXXABI::EmitThreadLocalInitFuncs(
3195 CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
3196 ArrayRef<llvm::Function *> CXXThreadLocalInits,
3197 ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
3198 llvm::Function *InitFunc =
nullptr;
3202 llvm::SmallVector<llvm::Function *, 8> OrderedInits;
3203 llvm::SmallDenseMap<const VarDecl *, llvm::Function *> UnorderedInits;
3204 for (
unsigned I = 0; I != CXXThreadLocalInits.size(); ++I) {
3207 UnorderedInits[CXXThreadLocalInitVars[I]->getCanonicalDecl()] =
3208 CXXThreadLocalInits[I];
3210 OrderedInits.push_back(CXXThreadLocalInits[I]);
3213 if (!OrderedInits.empty()) {
3215 llvm::FunctionType *FTy =
3216 llvm::FunctionType::get(CGM.
VoidTy,
false);
3221 llvm::GlobalVariable *Guard =
new llvm::GlobalVariable(
3223 llvm::GlobalVariable::InternalLinkage,
3224 llvm::ConstantInt::get(CGM.
Int8Ty, 0),
"__tls_guard");
3225 Guard->setThreadLocal(
true);
3229 Guard->setAlignment(GuardAlign.
getAsAlign());
3231 CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(
3232 InitFunc, OrderedInits, ConstantAddress(Guard, CGM.
Int8Ty, GuardAlign));
3235 InitFunc->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3236 InitFunc->addFnAttr(llvm::Attribute::NoUnwind);
3242 for (
const VarDecl *VD : CXXThreadLocals) {
3246 getOrCreateThreadLocalWrapper(VD, GV);
3251 for (
auto VDAndWrapper : ThreadWrappers) {
3252 const VarDecl *VD = VDAndWrapper.first;
3253 llvm::GlobalVariable *Var =
3255 llvm::Function *Wrapper = VDAndWrapper.second;
3262 Wrapper->setLinkage(llvm::Function::ExternalLinkage);
3268 if (Wrapper->getLinkage() == llvm::Function::WeakODRLinkage)
3269 Wrapper->setLinkage(llvm::Function::LinkOnceODRLinkage);
3275 SmallString<256> InitFnName;
3277 llvm::raw_svector_ostream
Out(InitFnName);
3278 getMangleContext().mangleItaniumThreadLocalInit(VD, Out);
3281 llvm::FunctionType *InitFnTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
3286 llvm::GlobalValue *
Init =
nullptr;
3287 bool InitIsInitFunc =
false;
3288 bool HasConstantInitialization =
false;
3289 if (!usesThreadWrapperFunction(VD)) {
3290 HasConstantInitialization =
true;
3292 InitIsInitFunc =
true;
3293 llvm::Function *InitFuncToUse = InitFunc;
3297 Init = llvm::GlobalAlias::create(Var->getLinkage(), InitFnName.str(),
3304 Init = llvm::Function::Create(InitFnTy,
3305 llvm::GlobalVariable::ExternalWeakLinkage,
3313 Init->setVisibility(Var->getVisibility());
3315 if (!CGM.
getTriple().isOSWindows() || !
Init->hasExternalWeakLinkage())
3316 Init->setDSOLocal(Var->isDSOLocal());
3319 llvm::LLVMContext &Context = CGM.
getModule().getContext();
3327 isEmittedWithConstantInitializer(VD,
true) &&
3328 !mayNeedDestruction(VD)) {
3333 assert(
Init ==
nullptr &&
"Expected Init to be null.");
3335 llvm::Function *
Func = llvm::Function::Create(
3336 InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.
getModule());
3342 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context,
"",
Func);
3343 CGBuilderTy Builder(CGM, Entry);
3344 Builder.CreateRetVoid();
3347 llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context,
"", Wrapper);
3348 CGBuilderTy Builder(CGM, Entry);
3349 if (HasConstantInitialization) {
3351 }
else if (InitIsInitFunc) {
3353 llvm::CallInst *CallVal = Builder.CreateCall(InitFnTy,
Init);
3355 CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3356 llvm::Function *
Fn =
3358 Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
3369 Builder.CreateCall(InitFnTy,
Init);
3372 llvm::Value *Have = Builder.CreateIsNotNull(
Init);
3373 llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context,
"", Wrapper);
3374 llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context,
"", Wrapper);
3375 Builder.CreateCondBr(Have, InitBB, ExitBB);
3377 Builder.SetInsertPoint(InitBB);
3378 Builder.CreateCall(InitFnTy,
Init);
3379 Builder.CreateBr(ExitBB);
3381 Builder.SetInsertPoint(ExitBB);
3386 llvm::Value *Val = Builder.CreateThreadLocalAddress(Var);
3390 Val = Builder.CreateAlignedLoad(Var->getValueType(), Val, Align);
3392 Val = Builder.CreateAddrSpaceCast(Val, Wrapper->getReturnType());
3394 Builder.CreateRet(Val);
3398LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
3400 QualType LValType) {
3402 llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
3404 llvm::CallInst *CallVal = CGF.
Builder.CreateCall(Wrapper);
3405 CallVal->setCallingConv(Wrapper->getCallingConv());
3419bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {
3438ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(
const CXXMethodDecl *MD) {
3439 SmallString<256> MethodName;
3440 llvm::raw_svector_ostream
Out(MethodName);
3441 getMangleContext().mangleCXXName(MD, Out);
3442 MethodName +=
"_vfpthunk_";
3443 StringRef ThunkName = MethodName.str();
3444 llvm::Function *ThunkFn;
3445 if ((ThunkFn = cast_or_null<llvm::Function>(
3446 CGM.
getModule().getNamedValue(ThunkName))))
3451 llvm::GlobalValue::LinkageTypes
Linkage =
3453 : llvm::GlobalValue::InternalLinkage;
3456 if (
Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
3457 ThunkFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
3458 assert(ThunkFn->getName() == ThunkName &&
"name was uniqued!");
3464 ThunkFn->removeFnAttr(llvm::Attribute::StackProtect);
3465 ThunkFn->removeFnAttr(llvm::Attribute::StackProtectStrong);
3466 ThunkFn->removeFnAttr(llvm::Attribute::StackProtectReq);
3469 CodeGenFunction CGF(CGM);
3470 CGF.
CurGD = GlobalDecl(MD);
3474 FunctionArgList FunctionArgs;
3478 FunctionArgs, MD->
getLocation(), SourceLocation());
3479 llvm::Value *ThisVal = loadIncomingCXXThis(CGF);
3480 setCXXABIThisValue(CGF, ThisVal);
3482 CallArgList CallArgs;
3483 for (
const VarDecl *VD : FunctionArgs)
3486 const FunctionProtoType *FPT = MD->
getType()->
getAs<FunctionProtoType>();
3488 const CGFunctionInfo &CallInfo =
3491 getThisAddress(CGF), ThunkTy);
3492 llvm::CallBase *CallOrInvoke;
3493 CGF.
EmitCall(CallInfo, Callee, ReturnValueSlot(), CallArgs, &CallOrInvoke,
3494 true, SourceLocation(),
true);
3496 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
3497 if (
Call->getType()->isVoidTy())
3510class ItaniumRTTIBuilder {
3512 llvm::LLVMContext &VMContext;
3513 const ItaniumCXXABI &
CXXABI;
3516 SmallVector<llvm::Constant *, 16> Fields;
3519 llvm::GlobalVariable *
3520 GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes
Linkage);
3524 llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
3527 void BuildVTablePointer(
const Type *Ty, llvm::Constant *StorageAddress);
3531 void BuildSIClassTypeInfo(
const CXXRecordDecl *RD);
3536 void BuildVMIClassTypeInfo(
const CXXRecordDecl *RD);
3540 void BuildPointerTypeInfo(QualType PointeeTy);
3544 void BuildObjCObjectTypeInfo(
const ObjCObjectType *Ty);
3548 void BuildPointerToMemberTypeInfo(
const MemberPointerType *Ty);
3551 ItaniumRTTIBuilder(
const ItaniumCXXABI &ABI)
3552 : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()),
CXXABI(ABI) {}
3566 PTI_Incomplete = 0x8,
3570 PTI_ContainingClassIncomplete = 0x10,
3576 PTI_Noexcept = 0x40,
3582 VMI_NonDiamondRepeat = 0x1,
3585 VMI_DiamondShaped = 0x2
3599 llvm::Constant *BuildTypeInfo(QualType Ty);
3602 llvm::Constant *BuildTypeInfo(
3604 llvm::GlobalVariable::LinkageTypes
Linkage,
3605 llvm::GlobalValue::VisibilityTypes
Visibility,
3606 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
3610llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
3611 QualType Ty, llvm::GlobalVariable::LinkageTypes
Linkage) {
3612 SmallString<256> Name;
3613 llvm::raw_svector_ostream
Out(Name);
3619 llvm::Constant *
Init = llvm::ConstantDataArray::getString(VMContext,
3626 GV->setInitializer(
Init);
3632ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
3634 SmallString<256> Name;
3635 llvm::raw_svector_ostream
Out(Name);
3639 llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(Name);
3646 GV =
new llvm::GlobalVariable(
3648 true, llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
3655 GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
3682 case BuiltinType::Void:
3683 case BuiltinType::NullPtr:
3684 case BuiltinType::Bool:
3685 case BuiltinType::WChar_S:
3686 case BuiltinType::WChar_U:
3687 case BuiltinType::Char_U:
3688 case BuiltinType::Char_S:
3689 case BuiltinType::UChar:
3690 case BuiltinType::SChar:
3691 case BuiltinType::Short:
3692 case BuiltinType::UShort:
3693 case BuiltinType::Int:
3694 case BuiltinType::UInt:
3695 case BuiltinType::Long:
3696 case BuiltinType::ULong:
3697 case BuiltinType::LongLong:
3698 case BuiltinType::ULongLong:
3699 case BuiltinType::Half:
3700 case BuiltinType::Float:
3701 case BuiltinType::Double:
3702 case BuiltinType::LongDouble:
3703 case BuiltinType::Float16:
3704 case BuiltinType::Float128:
3705 case BuiltinType::Ibm128:
3706 case BuiltinType::Char8:
3707 case BuiltinType::Char16:
3708 case BuiltinType::Char32:
3709 case BuiltinType::Int128:
3710 case BuiltinType::UInt128:
3713#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
3714 case BuiltinType::Id:
3715#include "clang/Basic/OpenCLImageTypes.def"
3716#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
3717 case BuiltinType::Id:
3718#include "clang/Basic/OpenCLExtensionTypes.def"
3719 case BuiltinType::OCLSampler:
3720 case BuiltinType::OCLEvent:
3721 case BuiltinType::OCLClkEvent:
3722 case BuiltinType::OCLQueue:
3723 case BuiltinType::OCLReserveID:
3724#define SVE_TYPE(Name, Id, SingletonId) \
3725 case BuiltinType::Id:
3726#include "clang/Basic/AArch64ACLETypes.def"
3727#define PPC_VECTOR_TYPE(Name, Id, Size) \
3728 case BuiltinType::Id:
3729#include "clang/Basic/PPCTypes.def"
3730#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3731#include "clang/Basic/RISCVVTypes.def"
3732#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3733#include "clang/Basic/WebAssemblyReferenceTypes.def"
3734#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
3735#include "clang/Basic/AMDGPUTypes.def"
3736#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
3737#include "clang/Basic/HLSLIntangibleTypes.def"
3738 case BuiltinType::ShortAccum:
3739 case BuiltinType::Accum:
3740 case BuiltinType::LongAccum:
3741 case BuiltinType::UShortAccum:
3742 case BuiltinType::UAccum:
3743 case BuiltinType::ULongAccum:
3744 case BuiltinType::ShortFract:
3745 case BuiltinType::Fract:
3746 case BuiltinType::LongFract:
3747 case BuiltinType::UShortFract:
3748 case BuiltinType::UFract:
3749 case BuiltinType::ULongFract:
3750 case BuiltinType::SatShortAccum:
3751 case BuiltinType::SatAccum:
3752 case BuiltinType::SatLongAccum:
3753 case BuiltinType::SatUShortAccum:
3754 case BuiltinType::SatUAccum:
3755 case BuiltinType::SatULongAccum:
3756 case BuiltinType::SatShortFract:
3757 case BuiltinType::SatFract:
3758 case BuiltinType::SatLongFract:
3759 case BuiltinType::SatUShortFract:
3760 case BuiltinType::SatUFract:
3761 case BuiltinType::SatULongFract:
3762 case BuiltinType::BFloat16:
3765 case BuiltinType::Dependent:
3766#define BUILTIN_TYPE(Id, SingletonId)
3767#define PLACEHOLDER_TYPE(Id, SingletonId) \
3768 case BuiltinType::Id:
3769#include "clang/AST/BuiltinTypes.def"
3770 llvm_unreachable(
"asking for RRTI for a placeholder type!");
3772 case BuiltinType::ObjCId:
3773 case BuiltinType::ObjCClass:
3774 case BuiltinType::ObjCSel:
3775 llvm_unreachable(
"FIXME: Objective-C types are unsupported!");
3778 llvm_unreachable(
"Invalid BuiltinType Kind!");
3783 const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
3801 if (
const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
3806 if (
const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3822 if (!Context.getLangOpts().RTTI)
return false;
3824 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3837 bool IsDLLImport = RD->
hasAttr<DLLImportAttr>();
3847 return IsDLLImport && !CGM.
getTriple().isWindowsItaniumEnvironment()
3860 return !RecordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();
3875 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3880 if (
const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
3884 dyn_cast<MemberPointerType>(Ty)) {
3886 if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
3907 if (
Base->isVirtual())
3915 auto *BaseDecl =
Base->getType()->castAsCXXRecordDecl();
3916 if (!BaseDecl->isEmpty() &&
3923void ItaniumRTTIBuilder::BuildVTablePointer(
const Type *Ty,
3924 llvm::Constant *StorageAddress) {
3926 static const char *
const ClassTypeInfo =
3927 "_ZTVN10__cxxabiv117__class_type_infoE";
3929 static const char *
const SIClassTypeInfo =
3930 "_ZTVN10__cxxabiv120__si_class_type_infoE";
3932 static const char *
const VMIClassTypeInfo =
3933 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
3935 const char *VTableName =
nullptr;
3938#define TYPE(Class, Base)
3939#define ABSTRACT_TYPE(Class, Base)
3940#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
3941#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
3942#define DEPENDENT_TYPE(Class, Base) case Type::Class:
3943#include "clang/AST/TypeNodes.inc"
3944 llvm_unreachable(
"Non-canonical and dependent types shouldn't get here");
3946 case Type::LValueReference:
3947 case Type::RValueReference:
3948 llvm_unreachable(
"References shouldn't get here");
3951 case Type::DeducedTemplateSpecialization:
3952 llvm_unreachable(
"Undeduced type shouldn't get here");
3955 llvm_unreachable(
"Pipe types shouldn't get here");
3957 case Type::ArrayParameter:
3958 llvm_unreachable(
"Array Parameter types should not get here.");
3964 case Type::ExtVector:
3965 case Type::ConstantMatrix:
3969 case Type::BlockPointer:
3971 VTableName =
"_ZTVN10__cxxabiv123__fundamental_type_infoE";
3974 case Type::ConstantArray:
3975 case Type::IncompleteArray:
3976 case Type::VariableArray:
3978 VTableName =
"_ZTVN10__cxxabiv117__array_type_infoE";
3981 case Type::FunctionNoProto:
3982 case Type::FunctionProto:
3984 VTableName =
"_ZTVN10__cxxabiv120__function_type_infoE";
3989 VTableName =
"_ZTVN10__cxxabiv116__enum_type_infoE";
3992 case Type::Record: {
3994 ->getDefinitionOrSelf();
3997 VTableName = ClassTypeInfo;
3999 VTableName = SIClassTypeInfo;
4001 VTableName = VMIClassTypeInfo;
4007 case Type::ObjCObject:
4013 VTableName = ClassTypeInfo;
4020 case Type::ObjCInterface:
4022 VTableName = SIClassTypeInfo;
4024 VTableName = ClassTypeInfo;
4028 case Type::ObjCObjectPointer:
4031 VTableName =
"_ZTVN10__cxxabiv119__pointer_type_infoE";
4034 case Type::MemberPointer:
4036 VTableName =
"_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
4039 case Type::HLSLAttributedResource:
4040 case Type::HLSLInlineSpirv:
4041 llvm_unreachable(
"HLSL doesn't support virtual functions");
4044 llvm::Constant *VTable =
nullptr;
4048 VTable = CGM.
getModule().getNamedAlias(VTableName);
4051 VTable = CGM.
getModule().getOrInsertGlobal(VTableName, Ty);
4056 llvm::Type *PtrDiffTy =
4063 llvm::Constant *Eight = llvm::ConstantInt::get(CGM.
Int32Ty, 8);
4065 llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.
Int8Ty, VTable, Eight);
4067 llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
4068 VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.
GlobalsInt8PtrTy,
4072 if (
const auto &Schema =
4076 Schema.isAddressDiscriminated() ? StorageAddress :
nullptr,
4077 GlobalDecl(), QualType(Ty, 0));
4079 Fields.push_back(VTable);
4096 return llvm::GlobalValue::InternalLinkage;
4100 llvm_unreachable(
"Linkage hasn't been computed!");
4105 return llvm::GlobalValue::InternalLinkage;
4113 return llvm::GlobalValue::LinkOnceODRLinkage;
4115 if (
const RecordType *
Record = dyn_cast<RecordType>(Ty)) {
4119 return llvm::GlobalValue::WeakODRLinkage;
4120 if (CGM.
getTriple().isWindowsItaniumEnvironment())
4121 if (RD->
hasAttr<DLLImportAttr>() &&
4123 return llvm::GlobalValue::ExternalLinkage;
4130 return llvm::GlobalValue::LinkOnceODRLinkage;
4133 llvm_unreachable(
"Invalid linkage!");
4136llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
4141 SmallString<256> Name;
4142 llvm::raw_svector_ostream
Out(Name);
4145 llvm::GlobalVariable *OldGV = CGM.
getModule().getNamedGlobal(Name);
4146 if (OldGV && !OldGV->isDeclaration()) {
4147 assert(!OldGV->hasAvailableExternallyLinkage() &&
4148 "available_externally typeinfos not yet implemented");
4156 return GetAddrOfExternalRTTIDescriptor(Ty);
4163 llvm::GlobalValue::VisibilityTypes llvmVisibility;
4164 if (llvm::GlobalValue::isLocalLinkage(
Linkage))
4166 llvmVisibility = llvm::GlobalValue::DefaultVisibility;
4168 ItaniumCXXABI::RUK_NonUniqueHidden)
4169 llvmVisibility = llvm::GlobalValue::HiddenVisibility;
4173 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4174 llvm::GlobalValue::DefaultStorageClass;
4176 if ((CGM.
getTriple().isWindowsItaniumEnvironment() &&
4177 RD->
hasAttr<DLLExportAttr>()) ||
4179 !llvm::GlobalValue::isLocalLinkage(
Linkage) &&
4180 llvmVisibility == llvm::GlobalValue::DefaultVisibility))
4181 DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass;
4183 return BuildTypeInfo(Ty,
Linkage, llvmVisibility, DLLStorageClass);
4186llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
4188 llvm::GlobalVariable::LinkageTypes
Linkage,
4189 llvm::GlobalValue::VisibilityTypes
Visibility,
4190 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
4191 SmallString<256> Name;
4192 llvm::raw_svector_ostream
Out(Name);
4195 llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name);
4197 llvm::GlobalVariable *GV =
4206 llvm::Constant *TypeNameField;
4210 ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness =
4212 if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) {
4215 TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.
Int64Ty);
4216 llvm::Constant *flag =
4217 llvm::ConstantInt::get(CGM.
Int64Ty, ((uint64_t)1) << 63);
4218 TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag);
4224 Fields.push_back(TypeNameField);
4227#define TYPE(Class, Base)
4228#define ABSTRACT_TYPE(Class, Base)
4229#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
4230#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
4231#define DEPENDENT_TYPE(Class, Base) case Type::Class:
4232#include "clang/AST/TypeNodes.inc"
4233 llvm_unreachable(
"Non-canonical and dependent types shouldn't get here");
4238 case Type::ExtVector:
4239 case Type::ConstantMatrix:
4241 case Type::BlockPointer:
4246 case Type::LValueReference:
4247 case Type::RValueReference:
4248 llvm_unreachable(
"References shouldn't get here");
4251 case Type::DeducedTemplateSpecialization:
4252 llvm_unreachable(
"Undeduced type shouldn't get here");
4260 case Type::ConstantArray:
4261 case Type::IncompleteArray:
4262 case Type::VariableArray:
4263 case Type::ArrayParameter:
4268 case Type::FunctionNoProto:
4269 case Type::FunctionProto:
4279 case Type::Record: {
4281 ->getDefinitionOrSelf();
4288 BuildSIClassTypeInfo(RD);
4290 BuildVMIClassTypeInfo(RD);
4295 case Type::ObjCObject:
4296 case Type::ObjCInterface:
4300 case Type::ObjCObjectPointer:
4308 case Type::MemberPointer:
4316 case Type::HLSLAttributedResource:
4317 case Type::HLSLInlineSpirv:
4318 llvm_unreachable(
"HLSL doesn't support RTTI");
4321 GV->replaceInitializer(llvm::ConstantStruct::getAnon(Fields));
4324 auto GVDLLStorageClass = DLLStorageClass;
4326 GVDLLStorageClass != llvm::GlobalVariable::DLLExportStorageClass) {
4327 if (
const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
4330 if (RD->
hasAttr<DLLExportAttr>() ||
4332 GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
4338 GV->takeName(OldGV);
4339 OldGV->replaceAllUsesWith(GV);
4340 OldGV->eraseFromParent();
4344 GV->setComdat(M.getOrInsertComdat(GV->getName()));
4371 TypeName->setDLLStorageClass(DLLStorageClass);
4372 GV->setDLLStorageClass(GVDLLStorageClass);
4382void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(
const ObjCObjectType *OT) {
4384 const Type *
T = OT->getBaseType().getTypePtr();
4392 ObjCInterfaceDecl *Super =
Class->getSuperClass();
4400 llvm::Constant *BaseTypeInfo =
4401 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(SuperTy);
4402 Fields.push_back(BaseTypeInfo);
4407void ItaniumRTTIBuilder::BuildSIClassTypeInfo(
const CXXRecordDecl *RD) {
4411 llvm::Constant *BaseTypeInfo =
4413 Fields.push_back(BaseTypeInfo);
4420 llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
4421 llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
4433 auto *BaseDecl =
Base->getType()->castAsCXXRecordDecl();
4434 if (
Base->isVirtual()) {
4436 if (!Bases.VirtualBases.insert(BaseDecl).second) {
4439 Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
4441 if (Bases.NonVirtualBases.count(BaseDecl))
4442 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4446 if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
4449 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4451 if (Bases.VirtualBases.count(BaseDecl))
4452 Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
4457 for (
const auto &I : BaseDecl->bases())
4468 for (
const auto &I : RD->
bases())
4477void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(
const CXXRecordDecl *RD) {
4478 llvm::Type *UnsignedIntLTy =
4486 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4491 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->
getNumBases()));
4524 llvm::Type *OffsetFlagsLTy =
4527 for (
const auto &Base : RD->
bases()) {
4529 Fields.push_back(ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(
Base.getType()));
4531 auto *BaseDecl =
Base.getType()->castAsCXXRecordDecl();
4539 if (
Base.isVirtual())
4551 if (
Base.isVirtual())
4552 OffsetFlags |= BCTI_Virtual;
4554 OffsetFlags |= BCTI_Public;
4556 Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags));
4565 if (
Type.isConstQualified())
4566 Flags |= ItaniumRTTIBuilder::PTI_Const;
4567 if (
Type.isVolatileQualified())
4568 Flags |= ItaniumRTTIBuilder::PTI_Volatile;
4569 if (
Type.isRestrictQualified())
4570 Flags |= ItaniumRTTIBuilder::PTI_Restrict;
4577 Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
4580 if (Proto->isNothrow()) {
4581 Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
4591void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
4597 llvm::Type *UnsignedIntLTy =
4599 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4604 llvm::Constant *PointeeTypeInfo =
4605 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(PointeeTy);
4606 Fields.push_back(PointeeTypeInfo);
4612ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(
const MemberPointerType *Ty) {
4622 Flags |= PTI_ContainingClassIncomplete;
4624 llvm::Type *UnsignedIntLTy =
4626 Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
4631 llvm::Constant *PointeeTypeInfo =
4632 ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(PointeeTy);
4633 Fields.push_back(PointeeTypeInfo);
4640 Fields.push_back(ItaniumRTTIBuilder(
CXXABI).BuildTypeInfo(
T));
4643llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
4644 return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
4647void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(
const CXXRecordDecl *RD) {
4649 QualType FundamentalTypes[] = {
4650 getContext().VoidTy, getContext().NullPtrTy,
4651 getContext().BoolTy, getContext().WCharTy,
4652 getContext().CharTy, getContext().UnsignedCharTy,
4653 getContext().SignedCharTy, getContext().ShortTy,
4654 getContext().UnsignedShortTy, getContext().IntTy,
4655 getContext().UnsignedIntTy, getContext().LongTy,
4656 getContext().UnsignedLongTy, getContext().LongLongTy,
4657 getContext().UnsignedLongLongTy, getContext().Int128Ty,
4658 getContext().UnsignedInt128Ty, getContext().HalfTy,
4659 getContext().FloatTy, getContext().DoubleTy,
4660 getContext().LongDoubleTy, getContext().Float128Ty,
4661 getContext().Char8Ty, getContext().Char16Ty,
4662 getContext().Char32Ty
4664 llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
4666 ? llvm::GlobalValue::DLLExportStorageClass
4667 : llvm::GlobalValue::DefaultStorageClass;
4668 llvm::GlobalValue::VisibilityTypes
Visibility =
4670 for (
const QualType &FundamentalType : FundamentalTypes) {
4671 QualType PointerType = getContext().getPointerType(FundamentalType);
4672 QualType PointerTypeConst = getContext().getPointerType(
4673 FundamentalType.withConst());
4674 for (QualType
Type : {FundamentalType, PointerType, PointerTypeConst})
4675 ItaniumRTTIBuilder(*this).BuildTypeInfo(
4676 Type, llvm::GlobalValue::ExternalLinkage,
4683ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
4684 QualType CanTy, llvm::GlobalValue::LinkageTypes
Linkage)
const {
4685 if (shouldRTTIBeUnique())
4689 if (
Linkage != llvm::GlobalValue::LinkOnceODRLinkage &&
4690 Linkage != llvm::GlobalValue::WeakODRLinkage)
4698 if (
Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
4699 return RUK_NonUniqueHidden;
4704 assert(
Linkage == llvm::GlobalValue::WeakODRLinkage);
4705 return RUK_NonUniqueVisible;
4710enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
4715 return StructorCodegen::Emit;
4720 return StructorCodegen::Emit;
4723 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
4731 if (llvm::GlobalValue::isDiscardableIfUnused(
Linkage))
4732 return StructorCodegen::RAUW;
4735 if (!llvm::GlobalAlias::isValidLinkage(
Linkage))
4736 return StructorCodegen::RAUW;
4738 if (llvm::GlobalValue::isWeakForLinker(
Linkage)) {
4742 return StructorCodegen::COMDAT;
4743 return StructorCodegen::Emit;
4746 return StructorCodegen::Alias;
4756 if (Entry && !Entry->isDeclaration())
4762 auto *Alias = llvm::GlobalAlias::create(
Linkage,
"", Aliasee);
4765 Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4769 assert(Entry->getType() == Aliasee->getType() &&
4770 "declaration exists with different type");
4771 Alias->takeName(Entry);
4772 Entry->replaceAllUsesWith(Alias);
4773 Entry->eraseFromParent();
4775 Alias->setName(MangledName);
4782void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {
4784 auto *CD = dyn_cast<CXXConstructorDecl>(MD);
4791 GlobalDecl BaseDecl;
4797 if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {
4802 if (CGType == StructorCodegen::RAUW) {
4815 CGType != StructorCodegen::COMDAT &&
4833 if (CGType == StructorCodegen::COMDAT) {
4834 SmallString<256> Buffer;
4835 llvm::raw_svector_ostream
Out(Buffer);
4837 getMangleContext().mangleCXXDtorComdat(DD, Out);
4839 getMangleContext().mangleCXXCtorComdat(CD, Out);
4840 llvm::Comdat *
C = CGM.
getModule().getOrInsertComdat(
Out.str());
4849 llvm::FunctionType *FTy = llvm::FunctionType::get(
4857 llvm::FunctionType *FTy =
4858 llvm::FunctionType::get(CGM.
VoidTy,
false);
4865 llvm::FunctionType *FTy = llvm::FunctionType::get(
4884 struct CallEndCatch final : EHScopeStack::Cleanup {
4885 CallEndCatch(
bool MightThrow) : MightThrow(MightThrow) {}
4888 void Emit(CodeGenFunction &CGF, Flags flags)
override {
4907 bool EndMightThrow) {
4908 llvm::CallInst *call =
4911 CGF.
EHStack.pushCleanup<CallEndCatch>(
4913 EndMightThrow && !CGF.
CGM.
getLangOpts().AssumeNothrowExceptionDtor);
4938 llvm::Value *AdjustedExn =
CallBeginCatch(CGF, Exn, EndCatchMightThrow);
4943 if (
const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
4952 unsigned HeaderSize =
4955 CGF.
Builder.CreateConstGEP1_32(CGF.
Int8Ty, Exn, HeaderSize);
4978 llvm::Value *Casted = CGF.
Builder.CreateBitCast(AdjustedExn, PtrTy);
4986 llvm::Value *ExnCast =
4987 CGF.
Builder.CreateBitCast(AdjustedExn, LLVMCatchTy,
"exn.byref");
4999 if (CatchType->hasPointerRepresentation()) {
5000 llvm::Value *CastExn =
5001 CGF.
Builder.CreateBitCast(AdjustedExn, LLVMCatchTy,
"exn.casted");
5018 llvm_unreachable(
"bad ownership qualifier!");
5036 llvm_unreachable(
"evaluation kind filtered out!");
5038 llvm_unreachable(
"bad evaluation kind");
5042 auto catchRD = CatchType->getAsCXXRecordDecl();
5052 Address adjustedExn(CGF.
Builder.CreateBitCast(rawAdjustedExn, PtrTy),
5053 LLVMCatchTy, caughtExnAlignment);
5062 llvm::CallInst *rawAdjustedExn =
5066 Address adjustedExn(CGF.
Builder.CreateBitCast(rawAdjustedExn, PtrTy),
5067 LLVMCatchTy, caughtExnAlignment);
5098void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,
5099 const CXXCatchStmt *S) {
5146 C.VoidTy, {C.getPointerType(C.CharTy)});
5149 fnTy,
"__clang_call_terminate", llvm::AttributeList(),
true);
5150 llvm::Function *fn =
5155 fn->setDoesNotThrow();
5156 fn->setDoesNotReturn();
5161 fn->addFnAttr(llvm::Attribute::NoInline);
5165 fn->setLinkage(llvm::Function::LinkOnceODRLinkage);
5166 fn->setVisibility(llvm::Function::HiddenVisibility);
5168 fn->setComdat(CGM.
getModule().getOrInsertComdat(fn->getName()));
5171 llvm::BasicBlock *entry =
5176 llvm::Value *exn = &*fn->arg_begin();
5179 llvm::CallInst *catchCall = builder.CreateCall(
getBeginCatchFn(CGM), exn);
5180 catchCall->setDoesNotThrow();
5184 llvm::CallInst *termCall = builder.CreateCall(CGM.
getTerminateFn());
5185 termCall->setDoesNotThrow();
5186 termCall->setDoesNotReturn();
5190 builder.CreateUnreachable();
5196ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
5206std::pair<llvm::Value *, const CXXRecordDecl *>
5207ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
5208 const CXXRecordDecl *RD) {
5213ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(
const CXXMethodDecl *MD) {
5214 const CXXMethodDecl *origMD =
5218 llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD);
5224void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF,
5225 const CXXCatchStmt *
C) {
5227 CGF.
EHStack.pushCleanup<CatchRetScope>(
5229 ItaniumCXXABI::emitBeginCatch(CGF,
C);
5233WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
5250void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
5251 llvm::FunctionCallee Dtor,
5252 llvm::Constant *
Addr) {
5257 llvm::FunctionType *AtExitTy =
5258 llvm::FunctionType::get(CGM.
IntTy, {CGM.IntTy, PtrTy},
true);
5261 llvm::FunctionCallee
AtExit =
5269 llvm::Value *NV = llvm::Constant::getNullValue(CGM.
IntTy);
5277 llvm::Function *DtorStub =
5285 emitCXXStermFinalizer(D, DtorStub,
Addr);
5288void XLCXXABI::emitCXXStermFinalizer(
const VarDecl &D, llvm::Function *dtorStub,
5289 llvm::Constant *addr) {
5290 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
5291 SmallString<256> FnName;
5293 llvm::raw_svector_ostream
Out(FnName);
5294 getMangleContext().mangleDynamicStermFinalizer(&D, Out);
5302 CodeGenFunction CGF(CGM);
5316 llvm::BasicBlock *DestructCallBlock = CGF.
createBasicBlock(
"destruct.call");
5321 CGF.
Builder.CreateCondBr(NeedsDestruct, DestructCallBlock, EndBlock);
5326 llvm::CallInst *CI = CGF.
Builder.CreateCall(dtorStub);
5329 CI->setCallingConv(dtorStub->getCallingConv());
5335 if (
auto *IPA = D.
getAttr<InitPriorityAttr>()) {
5337 IPA->getPriority());
static void emitConstructorDestructorAlias(CIRGenModule &cgm, GlobalDecl aliasDecl, GlobalDecl targetDecl)
static CharUnits computeOffsetHint(ASTContext &astContext, const CXXRecordDecl *src, const CXXRecordDecl *dst)
static Address emitDynamicCastToVoid(CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, Address src)
static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm, QualType ty)
Return the linkage that the type info and type info name constants should have for the given type.
static mlir::Value emitExactDynamicCast(CIRGenItaniumCXXABI &abi, CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, QualType destRecordTy, cir::PointerType destCIRTy, bool isRefCast, Address src)
static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf)
static cir::FuncOp getBadCastFn(CIRGenFunction &cgf)
static StructorCodegen getCodegenToUse(CodeGenModule &CGM, const CXXMethodDecl *MD)
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 getBeginCatchFn(CodeGenModule &CGM)
static llvm::Constant * pointerAuthResignMemberFunctionPointer(llvm::Constant *Src, QualType DestType, QualType SrcType, CodeGenModule &CGM)
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 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 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 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.
a trap message and trap category.
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.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
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.
QualType getMemberPointerType(QualType T, NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
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 ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
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'.
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.
SourceLocation getBeginLoc() const LLVM_READONLY
VarDecl * getExceptionDecl() const
FunctionDecl * getOperatorDelete() const
bool isGlobalDelete() const
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 C++ struct/union/class.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_iterator bases_begin()
const CXXBaseSpecifier * base_class_const_iterator
Iterator that traverses the base classes of a class.
base_class_range vbases()
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool isDynamicClass() const
bool hasDefinition() const
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
const Expr * getSubExpr() const
static CanQual< Type > CreateUnsafe(QualType Other)
Qualifiers getQualifiers() const
Retrieve all qualifiers.
CastKind getCastKind() const
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
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, unsigned AddrSpace, 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 llvm::CallInst * emitTerminateForUnexpectedException(CodeGenFunction &CGF, llvm::Value *Exn)
MangleContext & getMangleContext()
Gets the mangle context.
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
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
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.
GlobalDecl CurGD
CurGD - The GlobalDecl for the current function being compiled.
llvm::Constant * createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr)
Create a stub function, suitable for being passed to atexit, which passes the given address to the gi...
llvm::Function * createTLSAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr, llvm::FunctionCallee &AtExit)
Create a stub function, suitable for being passed to __pt_atexit_np, which passes the given address t...
SanitizerSet SanOpts
Sanitizers enabled for this function.
void EmitARCInitWeak(Address addr, llvm::Value *value)
i8* @objc_initWeak(i8** addr, i8* value) Returns value.
llvm::Value * getExceptionFromSlot()
Returns the contents of the function's exception object and selector slots.
llvm::Type * ConvertType(QualType T)
void EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args)
Emits a call or invoke to the given noreturn runtime function.
llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")
Emits a call or invoke instruction to the given runtime function.
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
bool CurFuncIsThunk
In C++, whether we are code generating a thunk.
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.
llvm::Constant * EmitCheckSourceLocation(SourceLocation Loc)
Emit a description of a source location in a format suitable for passing to a runtime sanitizer handl...
llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)
void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc)
EmitDelegateCallArg - We are performing a delegate call; that is, the current function is delegating ...
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV, bool PerformInit)
EmitCXXGlobalVarDeclInit - Create the initializer for a C++ variable with global storage.
void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, llvm::Value *CompletePtr, QualType ElementType)
llvm::Constant * EmitCheckTypeDescriptor(QualType T)
Emit a description of a type in a format suitable for passing to a runtime sanitizer handler.
void EmitAnyExprToExn(const Expr *E, Address Addr)
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
const TargetInfo & getTarget() const
CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, const CXXRecordDecl *RD)
BuildVirtualCall - This routine makes indirect vtable call for call to virtual destructors.
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 EmitCheck(ArrayRef< std::pair< llvm::Value *, SanitizerKind::SanitizerOrdinal > > Checked, SanitizerHandler Check, ArrayRef< llvm::Constant * > StaticArgs, ArrayRef< llvm::Value * > DynamicArgs, const TrapReason *TR=nullptr)
Create a basic block that will either trap or call a handler function in the UBSan runtime with the p...
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.
CGDebugInfo * getDebugInfo()
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.
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...
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,...
CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)
Emit the concrete pointer authentication informaton for the given authentication schema.
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::Value * unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub)
Call unatexit() with function dtorStub.
llvm::Value * emitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull)
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...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
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...
llvm::Value * LoadCXXVTT()
LoadCXXVTT - Load the VTT parameter to base constructors/destructors have virtual bases.
llvm::Value * EmitARCRetainNonBlock(llvm::Value *value)
Retain the given object, with normal retain semantics.
llvm::Type * ConvertTypeForMem(QualType T)
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
llvm::Value * GetVTTParameter(GlobalDecl GD, bool ForVirtualBase, bool Delegating)
GetVTTParameter - Return the VTT parameter that should be passed to a base constructor/destructor wit...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, bool NoMerge=false, const TrapReason *TR=nullptr)
Create a basic block that will call the trap intrinsic, and emit a conditional branch to it,...
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
llvm::Value * EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy, uint64_t VTableByteOffset)
Emit a type checked load from the given vtable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::Instruction * CurrentFuncletPad
bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
llvm::LLVMContext & getLLVMContext()
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
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...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args)
llvm::Value * EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer)
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)
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 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)
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.
bool isFuncTypeConvertible(const FunctionType *FT)
isFuncTypeConvertible - Utility to check whether a function type can be converted to an LLVM type (i....
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.
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
static RValue get(llvm::Value *V)
static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
virtual unsigned getSizeOfUnwindException() const
Determines the size of struct _Unwind_Exception on this platform, in 8-bit units.
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.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
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.
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.
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
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.
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
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.
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.
Encodes a location in the source.
SourceLocation getBeginLoc() const LLVM_READONLY
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.
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...
CXXRecordDecl * castAsCXXRecordDecl() const
const T * castAs() const
Member-template castAs<specific type>.
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<specific type>'.
bool isRecordType() const
AddressPointLocation getAddressPoint(BaseSubobject Base) const
size_t getVTableSize(size_t i) const
Represents a variable declaration or definition.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isNoDestroy(const ASTContext &) const
Is destruction of this variable entirely suppressed?
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool isInline() const
Whether this variable is (C++1z) inline.
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.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
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)
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
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)
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
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.
@ Ctor_Unified
GCC-style unified dtor.
bool isa(CodeGen::Address addr)
bool isTemplateInstantiation(TemplateSpecializationKind Kind)
Determine whether this template specialization kind refers to an instantiation of an entity (as oppos...
@ Success
Annotation was successful.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
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...
@ Result
The result type of a method or function.
const FunctionProtoType * T
CXXDtorType
C++ destructor types.
@ Dtor_Comdat
The COMDAT used for dtors.
@ Dtor_Unified
GCC-style unified dtor.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
bool isDiscardableGVALinkage(GVALinkage L)
@ Type
The name was classified as a type.
LangAS
Defines the address space values used by the address space qualifier of QualType.
U cast(CodeGen::Address addr)
@ 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.
const half4 dst(half4 Src0, half4 Src1)
Represents an element in a path from a derived class to a base class.
const CXXRecordDecl * NearestVBase
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::IntegerType * PtrDiffTy
CharUnits getPointerAlign() const
llvm::PointerType * DefaultPtrTy
static const EHPersonality & get(CodeGenModule &CGM, const FunctionDecl *FD)
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.
union clang::ThisAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
ThisAdjustment This
The this pointer adjustment.
unsigned AddressPointIndex
struct clang::ReturnAdjustment::VirtualAdjustment::@103031170252120233124322035264172076254313213024 Itanium
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
struct clang::ThisAdjustment::VirtualAdjustment::@106065375072164260365214033034320247050276346205 Itanium
int64_t VCallOffsetOffset
The offset (in bytes), relative to the address point, of the virtual call offset.