32#include "llvm/ADT/StringExtras.h"
33#include "llvm/ADT/StringSet.h"
34#include "llvm/IR/Intrinsics.h"
42struct VBTableGlobals {
44 SmallVector<llvm::GlobalVariable *, 2> Globals;
47class MicrosoftCXXABI :
public CGCXXABI {
49 MicrosoftCXXABI(CodeGenModule &CGM)
50 : CGCXXABI(CGM), BaseClassDescriptorType(
nullptr),
51 ClassHierarchyDescriptorType(
nullptr),
56 "visibility export mapping option unimplemented in this ABI");
59 bool HasThisReturn(GlobalDecl GD)
const override;
60 bool hasMostDerivedReturn(GlobalDecl GD)
const override;
66 bool isSRetParameterAfterThis()
const override {
return true; }
68 bool isThisCompleteObject(GlobalDecl GD)
const override {
80 case Dtor_Comdat: llvm_unreachable(
"emitting dtor comdat as function?");
82 llvm_unreachable(
"unexpected unified dtor type");
84 llvm_unreachable(
"bad dtor kind");
91 size_t getSrcArgforCopyCtor(
const CXXConstructorDecl *CD,
92 FunctionArgList &Args)
const override {
93 assert(Args.size() >= 2 &&
94 "expected the arglist to have at least two args!");
103 std::vector<CharUnits> getVBPtrOffsets(
const CXXRecordDecl *RD)
override {
104 std::vector<CharUnits> VBPtrOffsets;
105 const ASTContext &Context = getContext();
106 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
108 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
109 for (
const std::unique_ptr<VPtrInfo> &VBT : *VBGlobals.VBTables) {
110 const ASTRecordLayout &SubobjectLayout =
111 Context.getASTRecordLayout(VBT->IntroducingObject);
112 CharUnits Offs = VBT->NonVirtualOffset;
114 if (VBT->getVBaseWithVPtr())
116 VBPtrOffsets.push_back(Offs);
118 llvm::array_pod_sort(VBPtrOffsets.begin(), VBPtrOffsets.end());
122 StringRef GetPureVirtualCallName()
override {
return "_purecall"; }
123 StringRef GetDeletedVirtualCallName()
override {
return "_purecall"; }
125 void emitVirtualObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
126 Address Ptr, QualType ElementType,
127 const CXXDestructorDecl *Dtor)
override;
129 void emitRethrow(CodeGenFunction &CGF,
bool isNoReturn)
override;
130 void emitThrow(CodeGenFunction &CGF,
const CXXThrowExpr *E)
override;
132 void emitBeginCatch(CodeGenFunction &CGF,
const CXXCatchStmt *
C)
override;
134 llvm::GlobalVariable *getMSCompleteObjectLocator(
const CXXRecordDecl *RD,
135 const VPtrInfo &Info);
137 llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty)
override;
139 getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType)
override;
142 CatchTypeInfo getCatchAllTypeInfo()
override {
145 if (getContext().getLangOpts().EHAsynch)
146 return CatchTypeInfo{
nullptr, 0};
148 return CatchTypeInfo{
nullptr, 0x40};
151 bool shouldTypeidBeNullChecked(QualType SrcRecordTy)
override;
152 void EmitBadTypeidCall(CodeGenFunction &CGF)
override;
153 llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
155 llvm::Type *StdTypeInfoPtrTy)
override;
157 bool shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
158 QualType SrcRecordTy)
override;
160 bool shouldEmitExactDynamicCast(QualType DestRecordTy)
override {
164 std::optional<ExactDynamicCastInfo>
165 getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,
166 QualType DestRecordTy)
override {
167 llvm_unreachable(
"unsupported");
170 QualType SrcRecordTy, QualType DestTy,
171 QualType DestRecordTy,
172 const ExactDynamicCastInfo &CastInfo,
173 llvm::BasicBlock *CastSuccess,
174 llvm::BasicBlock *CastFail)
override {
175 llvm_unreachable(
"unsupported");
178 llvm::Value *emitDynamicCastCall(CodeGenFunction &CGF, Address
Value,
179 QualType SrcRecordTy, QualType DestTy,
180 QualType DestRecordTy,
181 llvm::BasicBlock *CastEnd)
override;
184 QualType SrcRecordTy)
override;
186 bool EmitBadCastCall(CodeGenFunction &CGF)
override;
187 bool canSpeculativelyEmitVTable(
const CXXRecordDecl *RD)
const override {
192 GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
193 const CXXRecordDecl *ClassDecl,
194 const CXXRecordDecl *BaseClassDecl)
override;
197 EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
198 const CXXRecordDecl *RD)
override;
201 EmitDtorCompleteObjectHandler(CodeGenFunction &CGF);
203 void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF,
204 const CXXRecordDecl *RD)
override;
206 void EmitCXXConstructors(
const CXXConstructorDecl *D)
override;
240 AddedStructorArgCounts
241 buildStructorSignature(GlobalDecl GD,
242 SmallVectorImpl<CanQualType> &ArgTys)
override;
245 bool useThunkForDtorVariant(
const CXXDestructorDecl *Dtor,
250 void setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
251 const CXXDestructorDecl *Dtor,
254 llvm::GlobalValue::LinkageTypes
258 void EmitCXXDestructors(
const CXXDestructorDecl *D)
override;
260 const CXXRecordDecl *getThisArgumentTypeForMethod(GlobalDecl GD)
override {
263 if (MD->isVirtual()) {
264 GlobalDecl LookupGD = GD;
265 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
269 return MD->getParent();
273 LookupGD = GlobalDecl(
279 MethodVFTableLocation ML =
291 return MD->getParent();
295 adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD,
297 bool VirtualCall)
override;
299 void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
300 FunctionArgList &Params)
override;
302 void EmitInstanceFunctionProlog(CodeGenFunction &CGF)
override;
304 AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
305 const CXXConstructorDecl *D,
311 const CXXDestructorDecl *DD,
316 void EmitDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *DD,
319 QualType ThisTy)
override;
321 void emitVTableTypeMetadata(
const VPtrInfo &Info,
const CXXRecordDecl *RD,
322 llvm::GlobalVariable *VTable);
324 void emitVTableDefinitions(CodeGenVTables &CGVT,
325 const CXXRecordDecl *RD)
override;
327 bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
328 CodeGenFunction::VPtr Vptr)
override;
332 bool doStructorsInitializeVPtrs(
const CXXRecordDecl *VTableClass)
override {
333 return !VTableClass->
hasAttr<MSNoVTableAttr>();
337 getVTableAddressPoint(BaseSubobject Base,
338 const CXXRecordDecl *VTableClass)
override;
340 llvm::Value *getVTableAddressPointInStructor(
341 CodeGenFunction &CGF,
const CXXRecordDecl *VTableClass,
342 BaseSubobject Base,
const CXXRecordDecl *NearestVBase)
override;
344 llvm::GlobalVariable *getAddrOfVTable(
const CXXRecordDecl *RD,
345 CharUnits VPtrOffset)
override;
347 CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
348 Address This, llvm::Type *Ty,
349 SourceLocation Loc)
override;
352 EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
354 DeleteOrMemberCallExpr E,
355 llvm::CallBase **CallOrInvoke)
override;
357 void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD,
358 CallArgList &CallArgs)
override {
361 "Only vector deleting destructor thunks are available in this ABI");
366 void emitVirtualInheritanceTables(
const CXXRecordDecl *RD)
override;
368 llvm::GlobalVariable *
369 getAddrOfVBTable(
const VPtrInfo &VBT,
const CXXRecordDecl *RD,
370 llvm::GlobalVariable::LinkageTypes
Linkage);
372 llvm::GlobalVariable *
373 getAddrOfVirtualDisplacementMap(
const CXXRecordDecl *SrcRD,
374 const CXXRecordDecl *DstRD) {
375 SmallString<256> OutName;
376 llvm::raw_svector_ostream
Out(OutName);
377 getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out);
378 StringRef MangledName = OutName.str();
380 if (
auto *VDispMap = CGM.
getModule().getNamedGlobal(MangledName))
385 SmallVector<llvm::Constant *, 4> Map(NumEntries,
386 llvm::PoisonValue::get(CGM.
IntTy));
387 Map[0] = llvm::ConstantInt::get(CGM.
IntTy, 0);
388 bool AnyDifferent =
false;
389 for (
const auto &I : SrcRD->
vbases()) {
390 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
396 Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.
IntTy, DstVBIndex * 4);
397 AnyDifferent |= SrcVBIndex != DstVBIndex;
403 llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.
IntTy, Map.size());
404 llvm::Constant *
Init = llvm::ConstantArray::get(VDispMapTy, Map);
405 llvm::GlobalValue::LinkageTypes
Linkage =
407 ? llvm::GlobalValue::LinkOnceODRLinkage
408 : llvm::GlobalValue::InternalLinkage;
409 auto *VDispMap =
new llvm::GlobalVariable(
415 void emitVBTableDefinition(
const VPtrInfo &VBT,
const CXXRecordDecl *RD,
416 llvm::GlobalVariable *GV)
const;
418 void setThunkLinkage(llvm::Function *Thunk,
bool ForVTable,
419 GlobalDecl GD,
bool ReturnAdjustment)
override {
424 Thunk->setLinkage(llvm::GlobalValue::InternalLinkage);
425 else if (ReturnAdjustment)
426 Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage);
428 Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
431 bool exportThunk()
override {
return false; }
433 llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
434 const CXXRecordDecl * ,
435 const ThunkInfo &TI)
override;
438 const CXXRecordDecl * ,
439 const ReturnAdjustment &RA)
override;
441 void EmitThreadLocalInitFuncs(
442 CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
443 ArrayRef<llvm::Function *> CXXThreadLocalInits,
444 ArrayRef<const VarDecl *> CXXThreadLocalInitVars)
override;
446 bool usesThreadWrapperFunction(
const VarDecl *VD)
const override {
447 return getContext().getLangOpts().isCompatibleWithMSVC(
448 LangOptions::MSVC2019_5) &&
450 (!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD));
452 LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
const VarDecl *VD,
453 QualType LValType)
override;
455 void EmitGuardedInit(CodeGenFunction &CGF,
const VarDecl &D,
456 llvm::GlobalVariable *DeclPtr,
457 bool PerformInit)
override;
458 void registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
459 llvm::FunctionCallee Dtor,
460 llvm::Constant *
Addr)
override;
485 bool requiresArrayCookie(
const CXXDeleteExpr *
expr,
486 QualType elementType)
override;
487 bool requiresArrayCookie(
const CXXNewExpr *
expr)
override;
488 CharUnits getArrayCookieSizeImpl(QualType
type)
override;
489 Address InitializeArrayCookie(CodeGenFunction &CGF,
491 llvm::Value *NumElements,
492 const CXXNewExpr *
expr,
493 QualType ElementType)
override;
494 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
496 CharUnits cookieSize)
override;
498 friend struct MSRTTIBuilder;
500 bool isImageRelative()
const {
505 llvm::StructType *getTypeDescriptorType(StringRef TypeInfoString) {
506 llvm::SmallString<32> TDTypeName(
"rtti.TypeDescriptor");
507 TDTypeName += llvm::utostr(TypeInfoString.size());
508 llvm::StructType *&TypeDescriptorType =
509 TypeDescriptorTypeMap[TypeInfoString.size()];
510 if (TypeDescriptorType)
511 return TypeDescriptorType;
512 llvm::Type *FieldTypes[] = {
515 llvm::ArrayType::get(CGM.
Int8Ty, TypeInfoString.size() + 1)};
517 llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes, TDTypeName);
518 return TypeDescriptorType;
521 llvm::Type *getImageRelativeType(llvm::Type *PtrType) {
522 if (!isImageRelative())
527 llvm::StructType *getBaseClassDescriptorType() {
528 if (BaseClassDescriptorType)
529 return BaseClassDescriptorType;
530 llvm::Type *FieldTypes[] = {
539 BaseClassDescriptorType = llvm::StructType::create(
541 return BaseClassDescriptorType;
544 llvm::StructType *getClassHierarchyDescriptorType() {
545 if (ClassHierarchyDescriptorType)
546 return ClassHierarchyDescriptorType;
550 ClassHierarchyDescriptorType =
551 llvm::StructType::create(FieldTypes,
"rtti.ClassHierarchyDescriptor");
552 return ClassHierarchyDescriptorType;
555 llvm::StructType *getCompleteObjectLocatorType() {
556 if (CompleteObjectLocatorType)
557 return CompleteObjectLocatorType;
558 llvm::Type *FieldTypes[] = {
564 getImageRelativeType(CGM.
VoidTy),
566 llvm::ArrayRef<llvm::Type *> FieldTypesRef(FieldTypes);
567 if (!isImageRelative())
568 FieldTypesRef = FieldTypesRef.drop_back();
569 CompleteObjectLocatorType =
570 llvm::StructType::create(FieldTypesRef,
"rtti.CompleteObjectLocator");
571 return CompleteObjectLocatorType;
574 llvm::GlobalVariable *getImageBase() {
575 StringRef Name =
"__ImageBase";
576 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(Name))
581 llvm::GlobalValue::ExternalLinkage,
587 llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) {
588 if (!isImageRelative())
591 if (PtrVal->isNullValue())
592 return llvm::Constant::getNullValue(CGM.
IntTy);
594 llvm::Constant *ImageBaseAsInt =
595 llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.
IntPtrTy);
596 llvm::Constant *PtrValAsInt =
597 llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.
IntPtrTy);
598 llvm::Constant *Diff =
599 llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt,
601 return llvm::ConstantExpr::getTrunc(Diff, CGM.
IntTy);
605 MicrosoftMangleContext &getMangleContext() {
609 llvm::Constant *getZeroInt() {
610 return llvm::ConstantInt::get(CGM.
IntTy, 0);
613 llvm::Constant *getAllOnesInt() {
614 return llvm::Constant::getAllOnesValue(CGM.
IntTy);
617 CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD)
override;
620 GetNullMemberPointerFields(
const MemberPointerType *MPT,
621 llvm::SmallVectorImpl<llvm::Constant *> &fields);
626 llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
628 llvm::Value *VBPtrOffset,
629 llvm::Value *VBTableOffset,
630 llvm::Value **VBPtr =
nullptr);
632 llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
635 int32_t VBTableOffset,
636 llvm::Value **VBPtr =
nullptr) {
637 assert(VBTableOffset % 4 == 0 &&
"should be byte offset into table of i32s");
638 llvm::Value *VBPOffset =
639 llvm::ConstantInt::getSigned(CGM.
IntTy, VBPtrOffset);
640 llvm::Value *VBTOffset = llvm::ConstantInt::get(CGM.
IntTy, VBTableOffset);
641 return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
644 std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
645 performBaseAdjustment(CodeGenFunction &CGF, Address
Value,
646 QualType SrcRecordTy);
650 llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF,
const Expr *E,
651 const CXXRecordDecl *RD, Address Base,
652 llvm::Value *VirtualBaseAdjustmentOffset,
653 llvm::Value *VBPtrOffset );
657 llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
658 bool IsMemberFunction,
659 const CXXRecordDecl *RD,
660 CharUnits NonVirtualBaseAdjustment,
661 unsigned VBTableIndex);
663 bool MemberPointerConstantIsNull(
const MemberPointerType *MPT,
667 void EmitVBPtrStores(CodeGenFunction &CGF,
const CXXRecordDecl *RD);
670 const VBTableGlobals &enumerateVBTables(
const CXXRecordDecl *RD);
673 llvm::Function *EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
674 const MethodVFTableLocation &ML);
676 llvm::Constant *EmitMemberDataPointer(
const CXXRecordDecl *RD,
680 llvm::Type *ConvertMemberPointerType(
const MemberPointerType *MPT)
override;
682 bool isZeroInitializable(
const MemberPointerType *MPT)
override;
684 bool isMemberPointerConvertible(
const MemberPointerType *MPT)
const override {
686 return RD->
hasAttr<MSInheritanceAttr>();
689 llvm::Constant *EmitNullMemberPointer(
const MemberPointerType *MPT)
override;
691 llvm::Constant *EmitMemberDataPointer(
const MemberPointerType *MPT,
692 CharUnits offset)
override;
693 llvm::Constant *EmitMemberFunctionPointer(
const CXXMethodDecl *MD)
override;
694 llvm::Constant *EmitMemberPointer(
const APValue &MP, QualType MPT)
override;
696 llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
699 const MemberPointerType *MPT,
700 bool Inequality)
override;
702 llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
704 const MemberPointerType *MPT)
override;
706 llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
const Expr *E,
707 Address Base, llvm::Value *MemPtr,
708 const MemberPointerType *MPT,
709 bool IsInBounds)
override;
711 llvm::Value *EmitNonNullMemberPointerConversion(
712 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
715 CGBuilderTy &Builder);
717 llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
719 llvm::Value *Src)
override;
721 llvm::Constant *EmitMemberPointerConversion(
const CastExpr *E,
722 llvm::Constant *Src)
override;
724 llvm::Constant *EmitMemberPointerConversion(
725 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
730 EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
const Expr *E,
731 Address This, llvm::Value *&ThisPtrForCall,
733 const MemberPointerType *MPT)
override;
735 void emitCXXStructor(GlobalDecl GD)
override;
737 llvm::StructType *getCatchableTypeType() {
738 if (CatchableTypeType)
739 return CatchableTypeType;
740 llvm::Type *FieldTypes[] = {
749 CatchableTypeType = llvm::StructType::create(
751 return CatchableTypeType;
754 llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) {
755 llvm::StructType *&CatchableTypeArrayType =
756 CatchableTypeArrayTypeMap[NumEntries];
757 if (CatchableTypeArrayType)
758 return CatchableTypeArrayType;
760 llvm::SmallString<23> CTATypeName(
"eh.CatchableTypeArray.");
761 CTATypeName += llvm::utostr(NumEntries);
762 llvm::Type *CTType = getImageRelativeType(CGM.
DefaultPtrTy);
763 llvm::Type *FieldTypes[] = {
765 llvm::ArrayType::get(CTType, NumEntries)
767 CatchableTypeArrayType =
768 llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes, CTATypeName);
769 return CatchableTypeArrayType;
772 llvm::StructType *getThrowInfoType() {
774 return ThrowInfoType;
775 llvm::Type *FieldTypes[] = {
781 ThrowInfoType = llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes,
783 return ThrowInfoType;
790 llvm::FunctionType *FTy =
791 llvm::FunctionType::get(CGM.
VoidTy, Args,
false);
792 llvm::FunctionCallee Throw =
796 if (
auto *Fn = dyn_cast<llvm::Function>(Throw.getCallee()))
797 Fn->setCallingConv(llvm::CallingConv::X86_StdCall);
802 llvm::Function *getAddrOfCXXCtorClosure(
const CXXConstructorDecl *CD,
805 llvm::Constant *getCatchableType(QualType T,
806 uint32_t NVOffset = 0,
807 int32_t VBPtrOffset = -1,
808 uint32_t VBIndex = 0);
810 llvm::GlobalVariable *getCatchableTypeArray(QualType T);
812 llvm::GlobalVariable *getThrowInfo(QualType T)
override;
814 std::pair<llvm::Value *, const CXXRecordDecl *>
815 LoadVTablePtr(CodeGenFunction &CGF, Address This,
816 const CXXRecordDecl *RD)
override;
819 isPermittedToBeHomogeneousAggregate(
const CXXRecordDecl *RD)
const override;
822 typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
823 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;
824 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;
826 VFTablesMapTy VFTablesMap;
827 VTablesMapTy VTablesMap;
830 llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
834 llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap;
839 GuardInfo() =
default;
840 llvm::GlobalVariable *Guard =
nullptr;
841 unsigned BitIndex = 0;
846 llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap;
847 llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap;
848 llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap;
850 llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap;
851 llvm::StructType *BaseClassDescriptorType;
852 llvm::StructType *ClassHierarchyDescriptorType;
853 llvm::StructType *CompleteObjectLocatorType;
855 llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays;
857 llvm::StructType *CatchableTypeType;
858 llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;
859 llvm::StructType *ThrowInfoType;
865MicrosoftCXXABI::getRecordArgABI(
const CXXRecordDecl *RD)
const {
877 case llvm::Triple::thumb:
883 case llvm::Triple::x86: {
889 getContext().getTypeInfo(getContext().getCanonicalTagType(RD));
895 return RAA_DirectInMemory;
898 case llvm::Triple::x86_64:
899 case llvm::Triple::aarch64:
903 llvm_unreachable(
"invalid enum");
906void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
907 const CXXDeleteExpr *DE,
909 QualType ElementType,
910 const CXXDestructorDecl *Dtor) {
913 if (!getContext().getTargetInfo().callGlobalDeleteInDeletingDtor(
914 getContext().getLangOpts())) {
917 llvm::Value *MDThis =
918 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,
928void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF,
bool isNoReturn) {
929 llvm::Value *Args[] = {llvm::ConstantPointerNull::get(CGM.
Int8PtrTy),
938void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
939 const CXXCatchStmt *S) {
943 llvm::BasicBlock *CatchPadBB = CGF.
Builder.GetInsertBlock();
944 llvm::CatchPadInst *CPI =
956 CPI->setArgOperand(2,
var.getObjectAddress(CGF).emitRawPointer(CGF));
964std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
965MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address
Value,
966 QualType SrcRecordTy) {
969 const ASTContext &Context = getContext();
975 return std::make_tuple(
Value, llvm::ConstantInt::get(CGF.
Int32Ty, 0),
980 const CXXRecordDecl *PolymorphicBase =
nullptr;
981 for (
auto &Base : SrcDecl->
vbases()) {
982 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
984 PolymorphicBase = BaseDecl;
988 assert(PolymorphicBase &&
"polymorphic class has no apparent vfptr?");
990 llvm::Value *Offset =
991 GetVirtualBaseClassOffset(CGF,
Value, SrcDecl, PolymorphicBase);
993 Value.getElementType(),
Value.emitRawPointer(CGF), Offset);
994 CharUnits VBaseAlign =
996 return std::make_tuple(Address(Ptr, CGF.
Int8Ty, VBaseAlign), Offset,
1000bool MicrosoftCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {
1002 return !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
1006 llvm::Value *Argument) {
1007 llvm::Type *ArgTypes[] = {CGF.
Int8PtrTy};
1008 llvm::FunctionType *FTy =
1009 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false);
1010 llvm::Value *Args[] = {Argument};
1015void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
1016 llvm::CallBase *
Call =
1018 Call->setDoesNotReturn();
1019 CGF.
Builder.CreateUnreachable();
1022llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
1023 QualType SrcRecordTy,
1025 llvm::Type *StdTypeInfoPtrTy) {
1026 std::tie(ThisPtr, std::ignore, std::ignore) =
1027 performBaseAdjustment(CGF, ThisPtr, SrcRecordTy);
1029 return CGF.
Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy);
1032bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
1033 QualType SrcRecordTy) {
1036 !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
1039llvm::Value *MicrosoftCXXABI::emitDynamicCastCall(
1040 CodeGenFunction &CGF, Address This, QualType SrcRecordTy, QualType DestTy,
1041 QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
1042 llvm::Value *SrcRTTI =
1044 llvm::Value *DestRTTI =
1047 llvm::Value *Offset;
1048 std::tie(This, Offset, std::ignore) =
1049 performBaseAdjustment(CGF, This, SrcRecordTy);
1050 llvm::Value *ThisPtr =
This.emitRawPointer(CGF);
1062 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
1064 llvm::Value *Args[] = {
1065 ThisPtr, Offset, SrcRTTI, DestRTTI,
1070llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
1072 QualType SrcRecordTy) {
1073 std::tie(
Value, std::ignore, std::ignore) =
1074 performBaseAdjustment(CGF,
Value, SrcRecordTy);
1078 llvm::Type *ArgTypes[] = {CGF.
Int8PtrTy};
1080 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
1082 llvm::Value *Args[] = {
Value.emitRawPointer(CGF)};
1086bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
1090llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset(
1091 CodeGenFunction &CGF, Address This,
const CXXRecordDecl *ClassDecl,
1092 const CXXRecordDecl *BaseClassDecl) {
1093 const ASTContext &Context = getContext();
1096 llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.
PtrDiffTy, VBPtrChars);
1098 CharUnits VBTableChars =
1101 llvm::Value *VBTableOffset =
1104 llvm::Value *VBPtrToNewBase =
1105 GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset);
1108 return CGF.
Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);
1111bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD)
const {
1121bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD)
const {
1131 uint64_t NumElts = 0;
1171 if (
auto *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
1172 if (Ctor->isUserProvided())
1174 }
else if (
auto *
Template = dyn_cast<FunctionTemplateDecl>(D)) {
1177 }
else if (
auto *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
1178 if (MethodDecl->isCopyAssignmentOperator() && MethodDecl->isDeleted())
1187bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI)
const {
1188 const CXXRecordDecl *RD = FI.
getReturnType()->getAsCXXRecordDecl();
1198 if (isIndirectReturn) {
1219MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
1220 const CXXRecordDecl *RD) {
1221 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1222 assert(IsMostDerivedClass &&
1223 "ctor for a class with virtual bases must have an implicit parameter");
1224 llvm::Value *IsCompleteObject =
1225 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1227 llvm::BasicBlock *CallVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.init_vbases");
1228 llvm::BasicBlock *SkipVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.skip_vbases");
1229 CGF.
Builder.CreateCondBr(IsCompleteObject,
1230 CallVbaseCtorsBB, SkipVbaseCtorsBB);
1235 EmitVBPtrStores(CGF, RD);
1239 return SkipVbaseCtorsBB;
1243MicrosoftCXXABI::EmitDtorCompleteObjectHandler(CodeGenFunction &CGF) {
1244 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1245 assert(IsMostDerivedClass &&
1246 "ctor for a class with virtual bases must have an implicit parameter");
1247 llvm::Value *IsCompleteObject =
1248 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1250 llvm::BasicBlock *CallVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.dtor_vbases");
1251 llvm::BasicBlock *SkipVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.skip_vbases");
1252 CGF.
Builder.CreateCondBr(IsCompleteObject,
1253 CallVbaseDtorsBB, SkipVbaseDtorsBB);
1258 return SkipVbaseDtorsBB;
1261void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
1262 CodeGenFunction &CGF,
const CXXRecordDecl *RD) {
1276 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
1279 CGBuilderTy &Builder = CGF.
Builder;
1281 llvm::Value *Int8This =
nullptr;
1283 for (
const CXXBaseSpecifier &S : RD->
vbases()) {
1284 const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl();
1285 auto I = VBaseMap.find(VBase);
1286 assert(I != VBaseMap.end());
1287 if (!I->second.hasVtorDisp())
1290 llvm::Value *VBaseOffset =
1291 GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase);
1292 uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity();
1295 llvm::Value *VtorDispValue = Builder.CreateSub(
1296 VBaseOffset, llvm::ConstantInt::get(CGM.
PtrDiffTy, ConstantVBaseOffset),
1298 VtorDispValue = Builder.CreateTruncOrBitCast(VtorDispValue, CGF.
Int32Ty);
1301 Int8This = getThisValue(CGF);
1303 llvm::Value *VtorDispPtr =
1304 Builder.CreateInBoundsGEP(CGF.
Int8Ty, Int8This, VBaseOffset);
1306 VtorDispPtr = Builder.CreateConstGEP1_32(CGF.
Int8Ty, VtorDispPtr, -4);
1308 Builder.CreateAlignedStore(VtorDispValue, VtorDispPtr,
1315 CallingConv ExpectedCallingConv = Context.getDefaultCallingConvention(
1319 return ExpectedCallingConv == ActualCallingConv;
1322void MicrosoftCXXABI::EmitCXXConstructors(
const CXXConstructorDecl *D) {
1334 Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1340void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
1341 const CXXRecordDecl *RD) {
1342 Address
This = getThisAddress(CGF);
1344 const ASTContext &Context = getContext();
1347 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
1348 for (
unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
1349 const std::unique_ptr<VPtrInfo> &VBT = (*VBGlobals.VBTables)[I];
1350 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
1351 const ASTRecordLayout &SubobjectLayout =
1353 CharUnits Offs = VBT->NonVirtualOffset;
1355 if (VBT->getVBaseWithVPtr())
1358 llvm::Value *GVPtr =
1365CGCXXABI::AddedStructorArgCounts
1366MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD,
1367 SmallVectorImpl<CanQualType> &ArgTys) {
1368 AddedStructorArgCounts Added;
1374 ArgTys.push_back(getContext().IntTy);
1377 auto *CD = dyn_cast<CXXConstructorDecl>(GD.
getDecl());
1385 const FunctionProtoType *FPT = CD->
getType()->
castAs<FunctionProtoType>();
1386 if (
Class->getNumVBases()) {
1388 ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy);
1391 ArgTys.push_back(getContext().IntTy);
1399void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
1400 const CXXDestructorDecl *Dtor,
1405 GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
1407 const NamedDecl *ND = Dtor;
1412llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(
1417 return llvm::GlobalValue::InternalLinkage;
1428 if (Dtor->
hasAttr<DLLExportAttr>())
1429 return llvm::GlobalValue::WeakODRLinkage;
1430 if (Dtor->
hasAttr<DLLImportAttr>())
1431 return llvm::GlobalValue::AvailableExternallyLinkage;
1432 return llvm::GlobalValue::LinkOnceODRLinkage;
1437 return llvm::GlobalValue::LinkOnceODRLinkage;
1439 llvm_unreachable(
"MS C++ ABI does not support unified dtors");
1445 return llvm::GlobalValue::WeakAnyLinkage;
1447 llvm_unreachable(
"MS C++ ABI does not support comdat dtors");
1449 llvm_unreachable(
"invalid dtor type");
1452void MicrosoftCXXABI::EmitCXXDestructors(
const CXXDestructorDecl *D) {
1466MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {
1469 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1484 MethodVFTableLocation ML =
1496 const ASTRecordLayout &DerivedLayout =
1497 getContext().getASTRecordLayout(MD->
getParent());
1504Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
1505 CodeGenFunction &CGF, GlobalDecl GD, Address This,
1510 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD);
1521 GlobalDecl LookupGD = GD;
1522 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1536 MethodVFTableLocation ML =
1551 const CXXRecordDecl *Derived = MD->
getParent();
1552 const CXXRecordDecl *VBase = ML.
VBase;
1553 llvm::Value *VBaseOffset =
1554 GetVirtualBaseClassOffset(CGF,
Result, Derived, VBase);
1556 Result.getElementType(),
Result.emitRawPointer(CGF), VBaseOffset);
1557 CharUnits VBaseAlign =
1561 if (!StaticOffset.
isZero()) {
1577void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
1579 FunctionArgList &Params) {
1580 ASTContext &Context = getContext();
1587 ImplicitParamKind::Other);
1590 const FunctionProtoType *FPT = MD->
getType()->
castAs<FunctionProtoType>();
1592 Params.insert(Params.begin() + 1, IsMostDerived);
1594 Params.push_back(IsMostDerived);
1595 getStructorImplicitParamDecl(CGF) = IsMostDerived;
1600 ImplicitParamKind::Other);
1601 Params.push_back(ShouldDelete);
1602 getStructorImplicitParamDecl(CGF) = ShouldDelete;
1606void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
1623 llvm::Value *
This = loadIncomingCXXThis(CGF);
1626 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.
CurGD);
1627 if (!Adjustment.
isZero()) {
1633 setCXXABIThisValue(CGF, This);
1643 if (HasThisReturn(CGF.
CurGD) || hasMostDerivedReturn(CGF.
CurGD))
1647 assert(getStructorImplicitParamDecl(CGF) &&
1648 "no implicit parameter for a constructor with virtual bases?");
1649 getStructorImplicitParamValue(CGF)
1656 assert(getStructorImplicitParamDecl(CGF) &&
1657 "no implicit parameter for a deleting destructor?");
1658 getStructorImplicitParamValue(CGF)
1661 "should_call_delete");
1665CGCXXABI::AddedStructorArgs MicrosoftCXXABI::getImplicitConstructorArgs(
1672 return AddedStructorArgs{};
1675 const FunctionProtoType *FPT = D->
getType()->
castAs<FunctionProtoType>();
1676 llvm::Value *MostDerivedArg;
1678 MostDerivedArg = getStructorImplicitParamValue(CGF);
1683 return AddedStructorArgs::prefix({{MostDerivedArg, getContext().IntTy}});
1685 return AddedStructorArgs::suffix({{MostDerivedArg, getContext().IntTy}});
1688llvm::Value *MicrosoftCXXABI::getCXXDestructorImplicitParam(
1694void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
1695 const CXXDestructorDecl *DD,
1705 GlobalDecl GD(DD,
Type);
1709 assert(
Type != CXXDtorType::Dtor_Deleting &&
1710 "The deleting destructor should only be called via a virtual call");
1711 This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD,
Type),
1715 llvm::BasicBlock *BaseDtorEndBB =
nullptr;
1717 BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF);
1726 QualType(),
nullptr);
1727 if (BaseDtorEndBB) {
1729 CGF.
Builder.CreateBr(BaseDtorEndBB);
1734void MicrosoftCXXABI::emitVTableTypeMetadata(
const VPtrInfo &Info,
1735 const CXXRecordDecl *RD,
1736 llvm::GlobalVariable *VTable) {
1747 llvm::DenseSet<const CXXRecordDecl *> Visited;
1748 llvm::GlobalObject::VCallVisibility TypeVis =
1750 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1751 VTable->setVCallVisibilityMetadata(TypeVis);
1757 CharUnits AddressPoint =
1758 getContext().getLangOpts().RTTIData
1759 ? getContext().toCharUnitsFromBits(
1760 getContext().getTargetInfo().getPointerWidth(LangAS::Default))
1778 const ASTRecordLayout &Layout =
1779 getContext().getASTRecordLayout(DerivedRD);
1785 Offset = VBI->second.VBaseOffset;
1796void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
1797 const CXXRecordDecl *RD) {
1801 for (
const std::unique_ptr<VPtrInfo>& Info : VFPtrs) {
1802 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->
FullOffsetInMDC);
1803 if (VTable->hasInitializer())
1806 const VTableLayout &VTLayout =
1809 llvm::Constant *RTTI =
nullptr;
1811 [](
const VTableComponent &VTC) { return VTC.isRTTIKind(); }))
1812 RTTI = getMSCompleteObjectLocator(RD, *Info);
1814 ConstantInitBuilder builder(CGM);
1815 auto components = builder.beginStruct();
1817 VTable->hasLocalLinkage());
1818 components.finishAndSetAsInitializer(VTable);
1820 emitVTableTypeMetadata(*Info, RD, VTable);
1824bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField(
1825 CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
1829llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
1830 CodeGenFunction &CGF,
const CXXRecordDecl *VTableClass, BaseSubobject Base,
1831 const CXXRecordDecl *NearestVBase) {
1832 llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass);
1833 if (!VTableAddressPoint) {
1834 assert(
Base.getBase()->getNumVBases() &&
1835 !getContext().getASTRecordLayout(
Base.getBase()).hasOwnVFPtr());
1837 return VTableAddressPoint;
1843 llvm::raw_svector_ostream Out(Name);
1848MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base,
1849 const CXXRecordDecl *VTableClass) {
1850 (void)getAddrOfVTable(VTableClass,
Base.getBaseOffset());
1851 VFTableIdTy
ID(VTableClass,
Base.getBaseOffset());
1852 return VFTablesMap[
ID];
1855llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(
const CXXRecordDecl *RD,
1856 CharUnits VPtrOffset) {
1861 VFTableIdTy
ID(RD, VPtrOffset);
1862 auto [I, Inserted] = VTablesMap.try_emplace(ID);
1866 llvm::GlobalVariable *&VTable = I->second;
1871 if (DeferredVFTables.insert(RD).second) {
1879 llvm::StringSet<> ObservedMangledNames;
1880 for (
const auto &VFPtr : VFPtrs) {
1881 SmallString<256> Name;
1883 if (!ObservedMangledNames.insert(Name.str()).second)
1884 llvm_unreachable(
"Already saw this mangling before?");
1889 const std::unique_ptr<VPtrInfo> *VFPtrI =
1890 llvm::find_if(VFPtrs, [&](
const std::unique_ptr<VPtrInfo> &VPI) {
1891 return VPI->FullOffsetInMDC == VPtrOffset;
1893 if (VFPtrI == VFPtrs.end()) {
1894 VFTablesMap[
ID] =
nullptr;
1897 const std::unique_ptr<VPtrInfo> &VFPtr = *VFPtrI;
1899 SmallString<256> VFTableName;
1909 llvm::GlobalValue::LinkageTypes VFTableLinkage =
1910 RD->
hasAttr<DLLImportAttr>() ? llvm::GlobalValue::LinkOnceODRLinkage
1911 : CGM.getVTableLinkage(RD);
1912 bool VFTableComesFromAnotherTU =
1913 llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) ||
1914 llvm::GlobalValue::isExternalLinkage(VFTableLinkage);
1915 bool VTableAliasIsRequred =
1916 !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData;
1918 if (llvm::GlobalValue *VFTable =
1919 CGM.
getModule().getNamedGlobal(VFTableName)) {
1920 VFTablesMap[
ID] = VFTable;
1921 VTable = VTableAliasIsRequred
1924 :
cast<llvm::GlobalVariable>(VFTable);
1928 const VTableLayout &VTLayout =
1930 llvm::GlobalValue::LinkageTypes VTableLinkage =
1931 VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage;
1933 StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str();
1935 llvm::Type *VTableType = CGM.
getVTables().getVTableType(VTLayout);
1939 llvm::GlobalValue *VFTable;
1940 VTable =
new llvm::GlobalVariable(CGM.
getModule(), VTableType,
1941 true, VTableLinkage,
1942 nullptr, VTableName);
1943 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1945 llvm::Comdat *
C =
nullptr;
1946 if (!VFTableComesFromAnotherTU &&
1947 llvm::GlobalValue::isWeakForLinker(VFTableLinkage))
1948 C = CGM.
getModule().getOrInsertComdat(VFTableName.str());
1953 if (VTableAliasIsRequred) {
1954 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.
Int32Ty, 0),
1955 llvm::ConstantInt::get(CGM.
Int32Ty, 0),
1956 llvm::ConstantInt::get(CGM.
Int32Ty, 1)};
1959 llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr(
1960 VTable->getValueType(), VTable, GEPIndices);
1961 if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) {
1962 VFTableLinkage = llvm::GlobalValue::ExternalLinkage;
1964 C->setSelectionKind(llvm::Comdat::Largest);
1966 VFTable = llvm::GlobalAlias::create(CGM.
Int8PtrTy,
1968 VFTableName.str(), VTableGEP,
1970 VFTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1979 VTable->setComdat(
C);
1981 if (RD->
hasAttr<DLLExportAttr>())
1982 VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1984 VFTablesMap[
ID] = VFTable;
1988CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
1992 SourceLocation Loc) {
1993 CGBuilderTy &Builder = CGF.
Builder;
1997 adjustThisArgumentForVirtualFunctionCall(CGF, GD, This,
true);
2000 llvm::Value *VTable =
2008 auto getObjectWithVPtr = [&] {
2011 [&](
const std::unique_ptr<VPtrInfo> &Info) {
2012 return Info->FullOffsetInMDC == ML.VFPtrOffset;
2021 getObjectWithVPtr(), VTable, Ty,
2029 llvm::Value *VFuncPtr =
2030 Builder.CreateConstInBoundsGEP1_64(Ty, VTable, ML.
Index,
"vfn");
2031 VFunc = Builder.CreateAlignedLoad(Ty, VFuncPtr, CGF.
getPointerAlign());
2034 CGCallee
Callee(GD, VFunc);
2038llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
2039 CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
2040 Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke) {
2041 auto *CE = dyn_cast<const CXXMemberCallExpr *>(E);
2042 auto *D = dyn_cast<const CXXDeleteExpr *>(E);
2043 assert((CE !=
nullptr) ^ (D !=
nullptr));
2044 assert(CE ==
nullptr || CE->arg_begin() == CE->arg_end());
2050 ASTContext &Context = getContext();
2051 bool VectorDeletingDtorsEnabled =
2055 const CGFunctionInfo *FInfo =
2061 bool IsArrayDelete = D && D->isArrayForm() && VectorDeletingDtorsEnabled;
2062 bool IsGlobalDelete = D && D->isGlobalDelete() &&
2065 llvm::Value *ImplicitParam =
2066 CGF.
Builder.getInt32((IsDeleting ? 1 : 0) | (IsGlobalDelete ? 4 : 0) |
2067 (IsArrayDelete ? 2 : 0));
2071 ThisTy = CE->getObjectType();
2073 ThisTy = D->getDestroyedType();
2077 ThisTy = ATy->getElementType();
2079 This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This,
true);
2082 ImplicitParam, Context.
IntTy, CE, CallOrInvoke);
2086const VBTableGlobals &
2087MicrosoftCXXABI::enumerateVBTables(
const CXXRecordDecl *RD) {
2090 auto [Entry, Added] = VBTablesMap.try_emplace(RD);
2091 VBTableGlobals &VBGlobals = Entry->second;
2096 VBGlobals.VBTables = &Context.enumerateVBTables(RD);
2101 for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(),
2102 E = VBGlobals.VBTables->end();
2104 VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD,
Linkage));
2111MicrosoftCXXABI::EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
2112 const MethodVFTableLocation &ML) {
2114 "can't form pointers to ctors or virtual dtors");
2117 SmallString<256> ThunkName;
2118 llvm::raw_svector_ostream
Out(ThunkName);
2119 getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out);
2122 if (llvm::GlobalValue *GV = CGM.
getModule().getNamedValue(ThunkName))
2126 const CGFunctionInfo &FnInfo =
2129 llvm::Function *ThunkFn =
2130 llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage,
2132 assert(ThunkFn->getName() == ThunkName &&
"name was uniqued!");
2135 ? llvm::GlobalValue::LinkOnceODRLinkage
2136 : llvm::GlobalValue::InternalLinkage);
2138 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
2147 ThunkFn->addFnAttr(
"thunk");
2150 ThunkFn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
2153 CodeGenFunction CGF(CGM);
2154 CGF.
CurGD = GlobalDecl(MD);
2159 FunctionArgList FunctionArgs;
2160 buildThisParam(CGF, FunctionArgs);
2164 FunctionArgs, MD->
getLocation(), SourceLocation());
2167 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
2172 llvm::Value *VTable =
2175 llvm::Value *VFuncPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
2176 ThunkPtrTy, VTable, ML.
Index,
"vfn");
2185void MicrosoftCXXABI::emitVirtualInheritanceTables(
const CXXRecordDecl *RD) {
2186 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
2187 for (
unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
2188 const std::unique_ptr<VPtrInfo>& VBT = (*VBGlobals.VBTables)[I];
2189 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
2190 if (GV->isDeclaration())
2191 emitVBTableDefinition(*VBT, RD, GV);
2195llvm::GlobalVariable *
2196MicrosoftCXXABI::getAddrOfVBTable(
const VPtrInfo &VBT,
const CXXRecordDecl *RD,
2197 llvm::GlobalVariable::LinkageTypes
Linkage) {
2198 SmallString<256> OutName;
2199 llvm::raw_svector_ostream
Out(OutName);
2200 getMangleContext().mangleCXXVBTable(RD, VBT.
MangledPath, Out);
2201 StringRef Name = OutName.str();
2203 llvm::ArrayType *VBTableType =
2206 assert(!CGM.
getModule().getNamedGlobal(Name) &&
2207 "vbtable with this name already exists: mangling bug?");
2208 CharUnits Alignment =
2212 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2214 if (RD->
hasAttr<DLLImportAttr>())
2215 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2216 else if (RD->
hasAttr<DLLExportAttr>())
2217 GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2219 if (!GV->hasExternalLinkage())
2220 emitVBTableDefinition(VBT, RD, GV);
2225void MicrosoftCXXABI::emitVBTableDefinition(
const VPtrInfo &VBT,
2226 const CXXRecordDecl *RD,
2227 llvm::GlobalVariable *GV)
const {
2231 "should only emit vbtables for classes with vbtables");
2233 const ASTRecordLayout &BaseLayout =
2235 const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD);
2237 SmallVector<llvm::Constant *, 4> Offsets(1 + ObjectWithVPtr->
getNumVBases(),
2246 for (
const auto &I : ObjectWithVPtr->
vbases()) {
2247 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
2254 CompleteVBPtrOffset +=
2256 Offset -= CompleteVBPtrOffset;
2258 unsigned VBIndex = Context.getVBTableIndex(ObjectWithVPtr, VBase);
2259 assert(Offsets[VBIndex] ==
nullptr &&
"The same vbindex seen twice?");
2264 assert(Offsets.size() ==
2266 llvm::ArrayType *VBTableType =
2267 llvm::ArrayType::get(CGM.
IntTy, Offsets.size());
2268 llvm::Constant *
Init = llvm::ConstantArray::get(VBTableType, Offsets);
2269 GV->setInitializer(
Init);
2271 if (RD->
hasAttr<DLLImportAttr>())
2272 GV->setLinkage(llvm::GlobalVariable::AvailableExternallyLinkage);
2275llvm::Value *MicrosoftCXXABI::performThisAdjustment(
2276 CodeGenFunction &CGF, Address This,
2277 const CXXRecordDecl * ,
const ThunkInfo &TI) {
2278 const ThisAdjustment &TA = TI.
This;
2280 return This.emitRawPointer(CGF);
2286 V =
This.emitRawPointer(CGF);
2290 Address VtorDispPtr =
2296 CGF.
Builder.CreateNeg(VtorDisp));
2309 llvm::Value *VBaseOffset = GetVBaseOffsetFromVBPtr(
2328llvm::Value *MicrosoftCXXABI::performReturnAdjustment(
2329 CodeGenFunction &CGF, Address Ret,
2330 const CXXRecordDecl * ,
const ReturnAdjustment &RA) {
2333 return Ret.emitRawPointer(CGF);
2337 llvm::Value *
V =
Ret.emitRawPointer(CGF);
2342 llvm::Value *VBaseOffset =
2354bool MicrosoftCXXABI::requiresArrayCookie(
const CXXDeleteExpr *
expr,
2355 QualType elementType) {
2361bool MicrosoftCXXABI::requiresArrayCookie(
const CXXNewExpr *
expr) {
2364 return expr->getAllocatedType().isDestructedType();
2367CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType
type) {
2370 ASTContext &Ctx = getContext();
2375llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2377 CharUnits cookieSize) {
2382Address MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
2384 llvm::Value *numElements,
2385 const CXXNewExpr *
expr,
2386 QualType elementType) {
2387 assert(requiresArrayCookie(
expr));
2390 CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
2393 Address cookiePtr = newPtr;
2405 llvm::FunctionCallee Dtor,
2406 llvm::Constant *
Addr) {
2411 llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get(
2412 CGF.
IntTy, DtorStub->getType(),
false);
2415 TLRegDtorTy,
"__tlregdtor", llvm::AttributeList(),
true);
2416 if (llvm::Function *TLRegDtorFn =
2417 dyn_cast<llvm::Function>(TLRegDtor.getCallee()))
2418 TLRegDtorFn->setDoesNotThrow();
2423void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
2424 llvm::FunctionCallee Dtor,
2425 llvm::Constant *
Addr) {
2440void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
2441 CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
2442 ArrayRef<llvm::Function *> CXXThreadLocalInits,
2443 ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
2444 if (CXXThreadLocalInits.empty())
2449 ?
"/include:___dyn_tls_init@12"
2450 :
"/include:__dyn_tls_init");
2455 auto AddToXDU = [&CGM](llvm::Function *InitFunc) {
2456 llvm::GlobalVariable *InitFuncPtr =
new llvm::GlobalVariable(
2457 CGM.
getModule(), InitFunc->getType(),
true,
2458 llvm::GlobalVariable::InternalLinkage, InitFunc,
2459 Twine(InitFunc->getName(),
"$initializer$"));
2460 InitFuncPtr->setSection(
".CRT$XDU");
2467 std::vector<llvm::Function *> NonComdatInits;
2468 for (
size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) {
2471 llvm::Function *F = CXXThreadLocalInits[I];
2474 if (llvm::Comdat *
C = GV->getComdat())
2475 AddToXDU(F)->setComdat(
C);
2477 NonComdatInits.push_back(F);
2480 if (!NonComdatInits.empty()) {
2481 llvm::FunctionType *FTy =
2482 llvm::FunctionType::get(CGM.
VoidTy,
false);
2485 SourceLocation(),
true);
2486 CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, NonComdatInits);
2498 llvm::Constant *TlsGuardConstant =
2502 TlsGuard->setThreadLocal(
true);
2510 llvm::FunctionType *FTy =
2511 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()), {},
2514 FTy,
"__dyn_tls_on_demand_init",
2516 llvm::AttributeList::FunctionIndex,
2517 llvm::Attribute::NoUnwind),
2522 llvm::BasicBlock *DynInitBB,
2523 llvm::BasicBlock *ContinueBB) {
2524 llvm::LoadInst *TlsGuardValue =
2526 llvm::Value *CmpResult =
2528 CGF.
Builder.CreateCondBr(CmpResult, DynInitBB, ContinueBB);
2532 llvm::GlobalValue *TlsGuard,
2533 llvm::BasicBlock *ContinueBB) {
2535 llvm::Function *InitializerFunction =
2537 llvm::CallInst *CallVal = CGF.
Builder.CreateCall(InitializerFunction);
2538 CallVal->setCallingConv(InitializerFunction->getCallingConv());
2540 CGF.
Builder.CreateBr(ContinueBB);
2544 llvm::BasicBlock *DynInitBB =
2546 llvm::BasicBlock *ContinueBB =
2552 CGF.
Builder.SetInsertPoint(DynInitBB);
2554 CGF.
Builder.SetInsertPoint(ContinueBB);
2557LValue MicrosoftCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
2559 QualType LValType) {
2573 Address
Addr(
V, RealVarTy, Alignment);
2577 AlignmentSource::Decl)
2583 StringRef VarName(
"_Init_thread_epoch");
2585 if (
auto *GV = CGM.
getModule().getNamedGlobal(VarName))
2587 auto *GV =
new llvm::GlobalVariable(
2589 false, llvm::GlobalVariable::ExternalLinkage,
2591 nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel);
2597 llvm::FunctionType *FTy =
2598 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2601 FTy,
"_Init_thread_header",
2603 llvm::AttributeList::FunctionIndex,
2604 llvm::Attribute::NoUnwind),
2609 llvm::FunctionType *FTy =
2610 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2613 FTy,
"_Init_thread_footer",
2615 llvm::AttributeList::FunctionIndex,
2616 llvm::Attribute::NoUnwind),
2621 llvm::FunctionType *FTy =
2622 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2625 FTy,
"_Init_thread_abort",
2627 llvm::AttributeList::FunctionIndex,
2628 llvm::Attribute::NoUnwind),
2633struct ResetGuardBit final : EHScopeStack::Cleanup {
2636 ResetGuardBit(Address Guard,
unsigned GuardNum)
2637 : Guard(Guard), GuardNum(GuardNum) {}
2639 void Emit(CodeGenFunction &CGF, Flags flags)
override {
2642 CGBuilderTy &Builder = CGF.
Builder;
2643 llvm::LoadInst *LI = Builder.CreateLoad(Guard);
2644 llvm::ConstantInt *Mask =
2645 llvm::ConstantInt::getSigned(CGF.
IntTy, ~(1ULL << GuardNum));
2646 Builder.CreateStore(Builder.CreateAnd(LI, Mask), Guard);
2650struct CallInitThreadAbort final : EHScopeStack::Cleanup {
2652 CallInitThreadAbort(RawAddress Guard) : Guard(Guard.getPointer()) {}
2654 void Emit(CodeGenFunction &CGF, Flags flags)
override {
2661void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
const VarDecl &D,
2662 llvm::GlobalVariable *GV,
2666 assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage());
2668 llvm::Function *F = CGF.
CurFn;
2669 F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
2670 F->setComdat(CGM.
getModule().getOrInsertComdat(F->getName()));
2676 bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics;
2680 bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic;
2682 CGBuilderTy &Builder = CGF.
Builder;
2683 llvm::IntegerType *GuardTy = CGF.
Int32Ty;
2684 llvm::ConstantInt *
Zero = llvm::ConstantInt::get(GuardTy, 0);
2688 GuardInfo *GI =
nullptr;
2689 if (ThreadlocalStatic)
2691 else if (!ThreadsafeStatic)
2694 llvm::GlobalVariable *GuardVar = GI ? GI->Guard :
nullptr;
2699 GuardNum = getContext().getStaticLocalNumber(&D);
2700 assert(GuardNum > 0);
2702 }
else if (HasPerVariableGuard) {
2706 GuardNum = GI->BitIndex++;
2709 if (!HasPerVariableGuard && GuardNum >= 32) {
2711 ErrorUnsupportedABI(CGF,
"more than 32 guarded initializations");
2718 SmallString<256> GuardName;
2720 llvm::raw_svector_ostream
Out(GuardName);
2721 if (HasPerVariableGuard)
2722 getMangleContext().mangleThreadSafeStaticGuardVariable(&D, GuardNum,
2725 getMangleContext().mangleStaticGuardVariable(&D, Out);
2731 new llvm::GlobalVariable(CGM.
getModule(), GuardTy,
false,
2732 GV->getLinkage(),
Zero, GuardName.str());
2733 GuardVar->setVisibility(GV->getVisibility());
2734 GuardVar->setDLLStorageClass(GV->getDLLStorageClass());
2735 GuardVar->setAlignment(GuardAlign.
getAsAlign());
2736 if (GuardVar->isWeakForLinker())
2737 GuardVar->setComdat(
2738 CGM.
getModule().getOrInsertComdat(GuardVar->getName()));
2741 if (GI && !HasPerVariableGuard)
2742 GI->Guard = GuardVar;
2745 ConstantAddress GuardAddr(GuardVar, GuardTy, GuardAlign);
2747 assert(GuardVar->getLinkage() == GV->getLinkage() &&
2748 "static local from the same function had different linkage");
2750 if (!HasPerVariableGuard) {
2758 llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum);
2759 llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr);
2760 llvm::Value *NeedsInit =
2761 Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit),
Zero);
2765 CodeGenFunction::GuardKind::VariableGuard, &D);
2770 Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardAddr);
2774 Builder.CreateBr(EndBlock);
2792 llvm::LoadInst *FirstGuardLoad = Builder.CreateLoad(GuardAddr);
2793 FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2794 llvm::LoadInst *InitThreadEpoch =
2796 llvm::Value *IsUninitialized =
2797 Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch);
2801 CodeGenFunction::GuardKind::VariableGuard, &D);
2807 GuardAddr.getPointer());
2808 llvm::LoadInst *SecondGuardLoad = Builder.CreateLoad(GuardAddr);
2809 SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2810 llvm::Value *ShouldDoInit =
2811 Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt());
2813 Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock);
2821 GuardAddr.getPointer());
2822 Builder.CreateBr(EndBlock);
2828bool MicrosoftCXXABI::isZeroInitializable(
const MemberPointerType *MPT) {
2844MicrosoftCXXABI::ConvertMemberPointerType(
const MemberPointerType *MPT) {
2847 llvm::SmallVector<llvm::Type *, 4> fields;
2851 fields.push_back(CGM.
IntTy);
2855 fields.push_back(CGM.
IntTy);
2857 fields.push_back(CGM.
IntTy);
2859 fields.push_back(CGM.
IntTy);
2861 if (fields.size() == 1)
2866void MicrosoftCXXABI::
2867GetNullMemberPointerFields(
const MemberPointerType *MPT,
2868 llvm::SmallVectorImpl<llvm::Constant *> &fields) {
2869 assert(fields.empty());
2874 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
2877 fields.push_back(getZeroInt());
2879 fields.push_back(getAllOnesInt());
2884 fields.push_back(getZeroInt());
2886 fields.push_back(getZeroInt());
2888 fields.push_back(getAllOnesInt());
2892MicrosoftCXXABI::EmitNullMemberPointer(
const MemberPointerType *MPT) {
2893 llvm::SmallVector<llvm::Constant *, 4> fields;
2894 GetNullMemberPointerFields(MPT, fields);
2895 if (fields.size() == 1)
2897 llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields);
2898 assert(Res->getType() == ConvertMemberPointerType(MPT));
2903MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
2904 bool IsMemberFunction,
2905 const CXXRecordDecl *RD,
2906 CharUnits NonVirtualBaseAdjustment,
2907 unsigned VBTableIndex) {
2915 llvm::SmallVector<llvm::Constant *, 4> fields;
2916 fields.push_back(FirstField);
2919 fields.push_back(llvm::ConstantInt::getSigned(
2925 Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
2931 fields.push_back(llvm::ConstantInt::get(CGM.
IntTy, VBTableIndex));
2933 return llvm::ConstantStruct::getAnon(fields);
2937MicrosoftCXXABI::EmitMemberDataPointer(
const MemberPointerType *MPT,
2942llvm::Constant *MicrosoftCXXABI::EmitMemberDataPointer(
const CXXRecordDecl *RD,
2945 MSInheritanceModel::Virtual)
2946 offset -= getContext().getOffsetOfBaseWithVBPtr(RD);
2947 llvm::Constant *FirstField =
2949 return EmitFullMemberPointer(FirstField,
false, RD,
2953llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(
const APValue &MP,
2955 const MemberPointerType *DstTy = MPType->
castAs<MemberPointerType>();
2958 return EmitNullMemberPointer(DstTy);
2960 ASTContext &Ctx = getContext();
2964 if (
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
2965 C = EmitMemberFunctionPointer(MD);
2973 const FieldDecl *FD = dyn_cast<FieldDecl>(MPD);
2978 C = EmitMemberDataPointer(RD, FieldOffset);
2981 if (!MemberPointerPath.empty()) {
2983 const MemberPointerType *SrcTy =
2985 std::nullopt, SrcRD)
2986 ->
castAs<MemberPointerType>();
2989 SmallVector<const CXXBaseSpecifier *, 4> DerivedToBasePath;
2990 const CXXRecordDecl *PrevRD = SrcRD;
2991 for (
const CXXRecordDecl *PathElem : MemberPointerPath) {
2992 const CXXRecordDecl *
Base =
nullptr;
2993 const CXXRecordDecl *Derived =
nullptr;
2994 if (DerivedMember) {
3001 for (
const CXXBaseSpecifier &BS : Derived->
bases())
3002 if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() ==
3003 Base->getCanonicalDecl())
3004 DerivedToBasePath.push_back(&BS);
3007 assert(DerivedToBasePath.size() == MemberPointerPath.size());
3009 CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer
3010 : CK_BaseToDerivedMemberPointer;
3011 C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(),
3012 DerivedToBasePath.end(),
C);
3018MicrosoftCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
3019 assert(MD->
isInstance() &&
"Member function must not be static!");
3023 CodeGenTypes &Types = CGM.
getTypes();
3025 unsigned VBTableIndex = 0;
3026 llvm::Constant *FirstField;
3027 const FunctionProtoType *FPT = MD->
getType()->
castAs<FunctionProtoType>();
3042 MethodVFTableLocation ML = VTableContext.getMethodVFTableLocation(MD);
3043 FirstField = EmitVirtualMemPtrThunk(MD, ML);
3047 VBTableIndex = VTableContext.getVBTableIndex(RD, ML.
VBase) * 4;
3050 if (VBTableIndex == 0 &&
3052 MSInheritanceModel::Virtual)
3053 NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD);
3056 return EmitFullMemberPointer(FirstField,
true, RD,
3057 NonVirtualBaseAdjustment, VBTableIndex);
3064MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
3067 const MemberPointerType *MPT,
3069 CGBuilderTy &Builder = CGF.
Builder;
3072 llvm::ICmpInst::Predicate Eq;
3073 llvm::Instruction::BinaryOps
And,
Or;
3075 Eq = llvm::ICmpInst::ICMP_NE;
3076 And = llvm::Instruction::Or;
3077 Or = llvm::Instruction::And;
3079 Eq = llvm::ICmpInst::ICMP_EQ;
3080 And = llvm::Instruction::And;
3081 Or = llvm::Instruction::Or;
3090 return Builder.CreateICmp(Eq, L, R);
3093 llvm::Value *L0 = Builder.CreateExtractValue(L, 0,
"lhs.0");
3094 llvm::Value *R0 = Builder.CreateExtractValue(R, 0,
"rhs.0");
3095 llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0,
"memptr.cmp.first");
3098 llvm::Value *Res =
nullptr;
3100 for (
unsigned I = 1, E = LType->getNumElements(); I != E; ++I) {
3101 llvm::Value *LF = Builder.CreateExtractValue(L, I);
3102 llvm::Value *RF = Builder.CreateExtractValue(R, I);
3103 llvm::Value *
Cmp = Builder.CreateICmp(Eq, LF, RF,
"memptr.cmp.rest");
3105 Res = Builder.CreateBinOp(
And, Res,
Cmp);
3113 llvm::Value *
Zero = llvm::Constant::getNullValue(L0->getType());
3114 llvm::Value *IsZero = Builder.CreateICmp(Eq, L0,
Zero,
"memptr.cmp.iszero");
3115 Res = Builder.CreateBinOp(
Or, Res, IsZero);
3120 return Builder.CreateBinOp(
And, Res, Cmp0,
"memptr.cmp");
3124MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
3125 llvm::Value *MemPtr,
3126 const MemberPointerType *MPT) {
3127 CGBuilderTy &Builder = CGF.
Builder;
3128 llvm::SmallVector<llvm::Constant *, 4> fields;
3131 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
3133 GetNullMemberPointerFields(MPT, fields);
3134 assert(!fields.empty());
3135 llvm::Value *FirstField = MemPtr;
3136 if (MemPtr->getType()->isStructTy())
3137 FirstField = Builder.CreateExtractValue(MemPtr, 0);
3138 llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0],
"memptr.cmp0");
3146 for (
int I = 1, E = fields.size(); I < E; ++I) {
3147 llvm::Value *
Field = Builder.CreateExtractValue(MemPtr, I);
3148 llvm::Value *
Next = Builder.CreateICmpNE(Field, fields[I],
"memptr.cmp");
3149 Res = Builder.CreateOr(Res,
Next,
"memptr.tobool");
3154bool MicrosoftCXXABI::MemberPointerConstantIsNull(
const MemberPointerType *MPT,
3155 llvm::Constant *Val) {
3158 llvm::Constant *FirstField = Val->getType()->isStructTy() ?
3159 Val->getAggregateElement(0U) : Val;
3160 return FirstField->isNullValue();
3165 if (isZeroInitializable(MPT) && Val->isNullValue())
3170 llvm::SmallVector<llvm::Constant *, 4> Fields;
3171 GetNullMemberPointerFields(MPT, Fields);
3172 if (Fields.size() == 1) {
3173 assert(Val->getType()->isIntegerTy());
3174 return Val == Fields[0];
3178 for (I = 0, E = Fields.size(); I != E; ++I) {
3179 if (Val->getAggregateElement(I) != Fields[I])
3186MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
3188 llvm::Value *VBPtrOffset,
3189 llvm::Value *VBTableOffset,
3190 llvm::Value **VBPtrOut) {
3191 CGBuilderTy &Builder = CGF.
Builder;
3193 llvm::Value *VBPtr = Builder.CreateInBoundsGEP(
3194 CGM.
Int8Ty,
This.emitRawPointer(CGF), VBPtrOffset,
"vbptr");
3198 CharUnits VBPtrAlign;
3199 if (
auto CI = dyn_cast<llvm::ConstantInt>(VBPtrOffset)) {
3200 VBPtrAlign =
This.getAlignment().alignmentAtOffset(
3206 llvm::Value *VBTable =
3207 Builder.CreateAlignedLoad(CGM.
DefaultPtrTy, VBPtr, VBPtrAlign,
"vbtable");
3210 llvm::Value *VBTableIndex = Builder.CreateAShr(
3211 VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2),
3215 llvm::Value *VBaseOffs =
3216 Builder.CreateInBoundsGEP(CGM.
Int32Ty, VBTable, VBTableIndex);
3217 return Builder.CreateAlignedLoad(CGM.
Int32Ty, VBaseOffs,
3223llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(
3224 CodeGenFunction &CGF,
const Expr *E,
const CXXRecordDecl *RD,
3225 Address Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {
3226 CGBuilderTy &Builder = CGF.
Builder;
3228 llvm::BasicBlock *OriginalBB =
nullptr;
3229 llvm::BasicBlock *SkipAdjustBB =
nullptr;
3230 llvm::BasicBlock *VBaseAdjustBB =
nullptr;
3237 OriginalBB = Builder.GetInsertBlock();
3240 llvm::Value *IsVirtual =
3241 Builder.CreateICmpNE(VBTableOffset, getZeroInt(),
3243 Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB);
3256 offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
3259 llvm::Value *VBPtr =
nullptr;
3260 llvm::Value *VBaseOffs =
3261 GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr);
3262 llvm::Value *AdjustedBase =
3263 Builder.CreateInBoundsGEP(CGM.
Int8Ty, VBPtr, VBaseOffs);
3266 if (VBaseAdjustBB) {
3267 Builder.CreateBr(SkipAdjustBB);
3269 llvm::PHINode *Phi = Builder.CreatePHI(CGM.
Int8PtrTy, 2,
"memptr.base");
3270 Phi->addIncoming(
Base.emitRawPointer(CGF), OriginalBB);
3271 Phi->addIncoming(AdjustedBase, VBaseAdjustBB);
3274 return AdjustedBase;
3277llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
3278 CodeGenFunction &CGF,
const Expr *E, Address Base, llvm::Value *MemPtr,
3279 const MemberPointerType *MPT,
bool IsInBounds) {
3281 CGBuilderTy &Builder = CGF.
Builder;
3287 llvm::Value *FieldOffset = MemPtr;
3288 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3289 llvm::Value *VBPtrOffset =
nullptr;
3290 if (MemPtr->getType()->isStructTy()) {
3293 FieldOffset = Builder.CreateExtractValue(MemPtr, I++);
3295 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3297 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3301 if (VirtualBaseAdjustmentOffset) {
3302 Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset,
3309 return Builder.CreateGEP(CGF.
Int8Ty,
Addr, FieldOffset,
"memptr.offset",
3310 IsInBounds ? llvm::GEPNoWrapFlags::inBounds()
3311 : llvm::GEPNoWrapFlags::none());
3315MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
3318 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
3319 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
3328 const MemberPointerType *SrcTy =
3330 const MemberPointerType *DstTy = E->
getType()->
castAs<MemberPointerType>();
3334 bool IsReinterpret = E->
getCastKind() == CK_ReinterpretMemberPointer;
3335 if (IsReinterpret && IsFunc)
3339 CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl();
3340 if (IsReinterpret &&
3344 CGBuilderTy &Builder = CGF.
Builder;
3347 llvm::Value *
IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy);
3348 llvm::Constant *DstNull = EmitNullMemberPointer(DstTy);
3352 if (IsReinterpret) {
3355 assert(Src->getType() == DstNull->getType());
3356 return Builder.CreateSelect(
IsNotNull, Src, DstNull);
3359 llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock();
3362 Builder.CreateCondBr(
IsNotNull, ConvertBB, ContinueBB);
3365 llvm::Value *Dst = EmitNonNullMemberPointerConversion(
3369 Builder.CreateBr(ContinueBB);
3373 llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2,
"memptr.converted");
3374 Phi->addIncoming(DstNull, OriginalBB);
3375 Phi->addIncoming(Dst, ConvertBB);
3379llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion(
3380 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
CastKind CK,
3383 CGBuilderTy &Builder) {
3392 llvm::Value *FirstField = Src;
3393 llvm::Value *NonVirtualBaseAdjustment = getZeroInt();
3394 llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt();
3395 llvm::Value *VBPtrOffset = getZeroInt();
3399 FirstField = Builder.CreateExtractValue(Src, I++);
3401 NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++);
3403 VBPtrOffset = Builder.CreateExtractValue(Src, I++);
3405 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++);
3408 bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer);
3409 const MemberPointerType *DerivedTy = IsDerivedToBase ? SrcTy : DstTy;
3414 llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;
3421 llvm::Value *SrcVBIndexEqZero =
3422 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3423 if (SrcInheritance == MSInheritanceModel::Virtual) {
3424 if (int64_t SrcOffsetToFirstVBase =
3425 getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) {
3426 llvm::Value *UndoSrcAdjustment = Builder.CreateSelect(
3428 llvm::ConstantInt::get(CGM.
IntTy, SrcOffsetToFirstVBase),
3430 NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment);
3441 llvm::Constant *BaseClassOffset = llvm::ConstantInt::get(
3446 llvm::Value *NVDisp;
3447 if (IsDerivedToBase)
3448 NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset,
"adj");
3450 NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset,
"adj");
3452 NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt());
3456 llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero;
3459 if (llvm::GlobalVariable *VDispMap =
3460 getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) {
3461 llvm::Value *VBIndex = Builder.CreateExactUDiv(
3462 VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.
IntTy, 4));
3464 llvm::Constant *Mapping = VDispMap->getInitializer();
3465 VirtualBaseAdjustmentOffset =
3468 llvm::Value *Idxs[] = {getZeroInt(), VBIndex};
3469 VirtualBaseAdjustmentOffset = Builder.CreateAlignedLoad(
3470 CGM.
IntTy, Builder.CreateInBoundsGEP(VDispMap->getValueType(),
3476 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3483 llvm::Value *DstVBPtrOffset = llvm::ConstantInt::getSigned(
3485 getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity());
3487 Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset);
3493 if (DstInheritance == MSInheritanceModel::Virtual) {
3494 if (int64_t DstOffsetToFirstVBase =
3495 getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) {
3496 llvm::Value *DoDstAdjustment = Builder.CreateSelect(
3498 llvm::ConstantInt::get(CGM.
IntTy, DstOffsetToFirstVBase),
3500 NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment);
3509 Dst = llvm::PoisonValue::get(ConvertMemberPointerType(DstTy));
3511 Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
3513 Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++);
3515 Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++);
3517 Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++);
3523MicrosoftCXXABI::EmitMemberPointerConversion(
const CastExpr *E,
3524 llvm::Constant *Src) {
3525 const MemberPointerType *SrcTy =
3527 const MemberPointerType *DstTy = E->
getType()->
castAs<MemberPointerType>();
3531 return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->
path_begin(),
3535llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
3536 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
CastKind CK,
3539 assert(CK == CK_DerivedToBaseMemberPointer ||
3540 CK == CK_BaseToDerivedMemberPointer ||
3541 CK == CK_ReinterpretMemberPointer);
3544 if (MemberPointerConstantIsNull(SrcTy, Src))
3545 return EmitNullMemberPointer(DstTy);
3550 if (CK == CK_ReinterpretMemberPointer)
3555 SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder));
3560CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
3561 CodeGenFunction &CGF,
const Expr *E, Address This,
3562 llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
3563 const MemberPointerType *MPT) {
3565 const FunctionProtoType *FPT =
3568 CGBuilderTy &Builder = CGF.
Builder;
3574 llvm::Value *FunctionPointer = MemPtr;
3575 llvm::Value *NonVirtualBaseAdjustment =
nullptr;
3576 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3577 llvm::Value *VBPtrOffset =
nullptr;
3578 if (MemPtr->getType()->isStructTy()) {
3581 FunctionPointer = Builder.CreateExtractValue(MemPtr, I++);
3583 NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++);
3585 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3587 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3590 if (VirtualBaseAdjustmentOffset) {
3591 ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This,
3592 VirtualBaseAdjustmentOffset, VBPtrOffset);
3594 ThisPtrForCall =
This.emitRawPointer(CGF);
3597 if (NonVirtualBaseAdjustment)
3598 ThisPtrForCall = Builder.CreateInBoundsGEP(CGF.
Int8Ty, ThisPtrForCall,
3599 NonVirtualBaseAdjustment);
3601 CGCallee
Callee(FPT, FunctionPointer);
3606 return new MicrosoftCXXABI(CGM);
3640 StringRef MangledName(
"??_7type_info@@6B@");
3641 if (
auto VTable = CGM.
getModule().getNamedGlobal(MangledName))
3645 llvm::GlobalVariable::ExternalLinkage,
3646 nullptr, MangledName);
3659 IsPrivateOnPath = 1 | 8,
3663 HasHierarchyDescriptor = 64
3665 MSRTTIClass(
const CXXRecordDecl *RD) : RD(RD) {}
3667 const CXXBaseSpecifier *Specifier);
3669 MSRTTIClass *getFirstChild() {
return this + 1; }
3670 static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
3671 return Child + 1 + Child->NumBases;
3674 const CXXRecordDecl *RD, *VirtualRoot;
3675 uint32_t Flags, NumBases, OffsetInVBase;
3679uint32_t MSRTTIClass::initialize(
const MSRTTIClass *Parent,
3680 const CXXBaseSpecifier *Specifier) {
3681 Flags = HasHierarchyDescriptor;
3683 VirtualRoot =
nullptr;
3687 Flags |= IsPrivate | IsPrivateOnPath;
3693 if (Parent->Flags & IsPrivateOnPath)
3694 Flags |= IsPrivateOnPath;
3695 VirtualRoot = Parent->VirtualRoot;
3696 OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext()
3697 .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity();
3701 MSRTTIClass *Child = getFirstChild();
3702 for (
const CXXBaseSpecifier &Base : RD->bases()) {
3703 NumBases += Child->initialize(
this, &Base) + 1;
3704 Child = getNextChild(Child);
3709static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) {
3711 case Linkage::Invalid:
3712 llvm_unreachable(
"Linkage hasn't been computed!");
3715 case Linkage::Internal:
3716 case Linkage::UniqueExternal:
3717 return llvm::GlobalValue::InternalLinkage;
3719 case Linkage::VisibleNone:
3720 case Linkage::Module:
3721 case Linkage::External:
3722 return llvm::GlobalValue::LinkOnceODRLinkage;
3724 llvm_unreachable(
"Invalid linkage!");
3730struct MSRTTIBuilder {
3732 HasBranchingHierarchy = 1,
3733 HasVirtualBranchingHierarchy = 2,
3734 HasAmbiguousBases = 4
3737 MSRTTIBuilder(MicrosoftCXXABI &ABI,
const CXXRecordDecl *RD)
3738 : CGM(ABI.CGM), Context(CGM.getContext()),
3739 VMContext(CGM.getLLVMContext()),
Module(CGM.getModule()), RD(RD),
3740 Linkage(getLinkageForRTTI(CGM.getContext().getCanonicalTagType(RD))),
3743 llvm::GlobalVariable *getBaseClassDescriptor(
const MSRTTIClass &Classes);
3744 llvm::GlobalVariable *
3745 getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes);
3746 llvm::GlobalVariable *getClassHierarchyDescriptor();
3747 llvm::GlobalVariable *getCompleteObjectLocator(
const VPtrInfo &Info);
3750 ASTContext &Context;
3751 llvm::LLVMContext &VMContext;
3753 const CXXRecordDecl *RD;
3754 llvm::GlobalVariable::LinkageTypes
Linkage;
3755 MicrosoftCXXABI &ABI;
3764 Classes.push_back(MSRTTIClass(RD));
3775 for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
3776 if ((Class->Flags & MSRTTIClass::IsVirtual) &&
3777 !VirtualBases.insert(Class->RD).second) {
3778 Class = MSRTTIClass::getNextChild(Class);
3781 if (!UniqueBases.insert(Class->RD).second)
3782 AmbiguousBases.insert(Class->RD);
3785 if (AmbiguousBases.empty())
3787 for (MSRTTIClass &Class : Classes)
3788 if (AmbiguousBases.count(Class.RD))
3789 Class.Flags |= MSRTTIClass::IsAmbiguous;
3792llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
3793 SmallString<256> MangledName;
3795 llvm::raw_svector_ostream
Out(MangledName);
3796 ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
3800 if (
auto CHD =
Module.getNamedGlobal(MangledName))
3804 SmallVector<MSRTTIClass, 8> Classes;
3806 Classes.front().initialize(
nullptr,
nullptr);
3809 for (
const MSRTTIClass &
Class : Classes) {
3810 if (
Class.RD->getNumBases() > 1)
3811 Flags |= HasBranchingHierarchy;
3814 if (
Class.Flags & MSRTTIClass::IsAmbiguous)
3815 Flags |= HasAmbiguousBases;
3817 if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)
3818 Flags |= HasVirtualBranchingHierarchy;
3821 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.
IntTy, 0),
3822 llvm::ConstantInt::get(CGM.
IntTy, 0)};
3825 auto Type = ABI.getClassHierarchyDescriptorType();
3829 if (CHD->isWeakForLinker())
3830 CHD->setComdat(CGM.
getModule().getOrInsertComdat(CHD->getName()));
3832 auto *Bases = getBaseClassArray(Classes);
3835 llvm::Constant *Fields[] = {
3836 llvm::ConstantInt::get(CGM.
IntTy, 0),
3837 llvm::ConstantInt::get(CGM.
IntTy, Flags),
3838 llvm::ConstantInt::get(CGM.
IntTy, Classes.size()),
3839 ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(
3840 Bases->getValueType(), Bases,
3841 llvm::ArrayRef<llvm::Value *>(GEPIndices))),
3843 CHD->setInitializer(llvm::ConstantStruct::get(
Type, Fields));
3847llvm::GlobalVariable *
3848MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
3849 SmallString<256> MangledName;
3851 llvm::raw_svector_ostream
Out(MangledName);
3852 ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out);
3860 llvm::Type *PtrType = ABI.getImageRelativeType(CGM.
DefaultPtrTy);
3861 auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
3863 new llvm::GlobalVariable(
Module, ArrType,
3865 nullptr, MangledName);
3866 if (BCA->isWeakForLinker())
3867 BCA->setComdat(CGM.
getModule().getOrInsertComdat(BCA->getName()));
3870 SmallVector<llvm::Constant *, 8> BaseClassArrayData;
3871 for (MSRTTIClass &
Class : Classes)
3872 BaseClassArrayData.push_back(
3873 ABI.getImageRelativeConstant(getBaseClassDescriptor(
Class)));
3874 BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType));
3875 BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData));
3879llvm::GlobalVariable *
3880MSRTTIBuilder::getBaseClassDescriptor(
const MSRTTIClass &
Class) {
3885 if (
Class.VirtualRoot) {
3887 OffsetInVBTable = VTableContext.getVBTableIndex(RD,
Class.VirtualRoot) * 4;
3891 SmallString<256> MangledName;
3893 llvm::raw_svector_ostream
Out(MangledName);
3894 ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor(
3895 Class.RD,
Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable,
3900 if (
auto BCD =
Module.getNamedGlobal(MangledName))
3904 auto Type = ABI.getBaseClassDescriptorType();
3907 nullptr, MangledName);
3908 if (BCD->isWeakForLinker())
3909 BCD->setComdat(CGM.
getModule().getOrInsertComdat(BCD->getName()));
3912 llvm::Constant *Fields[] = {
3913 ABI.getImageRelativeConstant(
3915 llvm::ConstantInt::get(CGM.
IntTy,
Class.NumBases),
3916 llvm::ConstantInt::get(CGM.
IntTy,
Class.OffsetInVBase),
3917 llvm::ConstantInt::getSigned(CGM.
IntTy, VBPtrOffset),
3918 llvm::ConstantInt::get(CGM.
IntTy, OffsetInVBTable),
3919 llvm::ConstantInt::get(CGM.
IntTy,
Class.Flags),
3920 ABI.getImageRelativeConstant(
3921 MSRTTIBuilder(ABI,
Class.RD).getClassHierarchyDescriptor()),
3923 BCD->setInitializer(llvm::ConstantStruct::get(
Type, Fields));
3927llvm::GlobalVariable *
3928MSRTTIBuilder::getCompleteObjectLocator(
const VPtrInfo &Info) {
3929 SmallString<256> MangledName;
3931 llvm::raw_svector_ostream
Out(MangledName);
3932 ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info.
MangledPath, Out);
3936 if (
auto COL =
Module.getNamedGlobal(MangledName))
3941 int VFPtrOffset = 0;
3947 ->second.hasVtorDisp())
3951 llvm::StructType *
Type = ABI.getCompleteObjectLocatorType();
3953 nullptr, MangledName);
3956 llvm::Constant *Fields[] = {
3957 llvm::ConstantInt::get(CGM.
IntTy, ABI.isImageRelative()),
3958 llvm::ConstantInt::get(CGM.
IntTy, OffsetToTop),
3959 llvm::ConstantInt::get(CGM.
IntTy, VFPtrOffset),
3960 ABI.getImageRelativeConstant(
3962 ABI.getImageRelativeConstant(getClassHierarchyDescriptor()),
3963 ABI.getImageRelativeConstant(COL),
3965 llvm::ArrayRef<llvm::Constant *> FieldsRef(Fields);
3966 if (!ABI.isImageRelative())
3967 FieldsRef = FieldsRef.drop_back();
3968 COL->setInitializer(llvm::ConstantStruct::get(
Type, FieldsRef));
3969 if (COL->isWeakForLinker())
3970 COL->setComdat(CGM.
getModule().getOrInsertComdat(COL->getName()));
3975 bool &IsConst,
bool &IsVolatile,
3976 bool &IsUnaligned) {
3977 T = Context.getExceptionObjectType(T);
3986 IsUnaligned =
false;
3988 if (!PointeeType.
isNull()) {
3998 MPTy->getQualifier(),
3999 MPTy->getMostRecentCXXRecordDecl());
4003 if (T->isPointerType())
4010MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType
Type,
4011 QualType CatchHandlerType) {
4015 bool IsConst, IsVolatile, IsUnaligned;
4031 return CatchTypeInfo{getAddrOfRTTIDescriptor(
Type)->stripPointerCasts(),
4039llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType
Type) {
4040 SmallString<256> MangledName;
4042 llvm::raw_svector_ostream
Out(MangledName);
4043 getMangleContext().mangleCXXRTTI(
Type, Out);
4047 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4054 SmallString<256> TypeInfoString;
4056 llvm::raw_svector_ostream
Out(TypeInfoString);
4057 getMangleContext().mangleCXXRTTIName(
Type, Out);
4061 llvm::Constant *Fields[] = {
4063 llvm::ConstantPointerNull::get(CGM.
Int8PtrTy),
4064 llvm::ConstantDataArray::getString(CGM.
getLLVMContext(), TypeInfoString)};
4065 llvm::StructType *TypeDescriptorType =
4066 getTypeDescriptorType(TypeInfoString);
4067 auto *Var =
new llvm::GlobalVariable(
4068 CGM.
getModule(), TypeDescriptorType,
false,
4069 getLinkageForRTTI(
Type),
4070 llvm::ConstantStruct::get(TypeDescriptorType, Fields),
4072 if (Var->isWeakForLinker())
4073 Var->setComdat(CGM.
getModule().getOrInsertComdat(Var->getName()));
4078llvm::GlobalVariable *
4079MicrosoftCXXABI::getMSCompleteObjectLocator(
const CXXRecordDecl *RD,
4080 const VPtrInfo &Info) {
4081 return MSRTTIBuilder(*
this, RD).getCompleteObjectLocator(Info);
4084void MicrosoftCXXABI::emitCXXStructor(GlobalDecl GD) {
4085 if (
auto *ctor = dyn_cast<CXXConstructorDecl>(GD.
getDecl())) {
4087 llvm::Function *
Fn =
4099 dtor->getParent()->getNumVBases() == 0)
4110 !getContext().classNeedsVectorDeletingDestructor(dtor->getParent())) {
4122 if (
Fn->isWeakForLinker())
4123 Fn->setComdat(CGM.
getModule().getOrInsertComdat(
Fn->getName()));
4127MicrosoftCXXABI::getAddrOfCXXCtorClosure(
const CXXConstructorDecl *CD,
4132 SmallString<256> ThunkName;
4133 llvm::raw_svector_ostream
Out(ThunkName);
4134 getMangleContext().mangleName(GlobalDecl(CD, CT), Out);
4137 if (llvm::GlobalValue *GV = CGM.
getModule().getNamedValue(ThunkName))
4143 const CXXRecordDecl *RD = CD->
getParent();
4144 CanQualType RecordTy = getContext().getCanonicalTagType(RD);
4145 llvm::Function *ThunkFn = llvm::Function::Create(
4146 ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.
getModule());
4147 ThunkFn->setCallingConv(
static_cast<llvm::CallingConv::ID
>(
4149 if (ThunkFn->isWeakForLinker())
4150 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
4154 CodeGenFunction CGF(CGM);
4158 FunctionArgList FunctionArgs;
4161 buildThisParam(CGF, FunctionArgs);
4165 ImplicitParamDecl SrcParam(
4166 getContext(),
nullptr, SourceLocation(),
4167 &getContext().Idents.get(
"src"),
4168 getContext().getLValueReferenceType(RecordTy,
4170 ImplicitParamKind::Other);
4172 FunctionArgs.push_back(&SrcParam);
4177 ImplicitParamDecl IsMostDerived(getContext(),
nullptr,
4179 &getContext().Idents.get(
"is_most_derived"),
4180 getContext().IntTy, ImplicitParamKind::Other);
4183 FunctionArgs.push_back(&IsMostDerived);
4188 FunctionArgs, CD->
getLocation(), SourceLocation());
4191 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
4192 llvm::Value *
This = getThisValue(CGF);
4194 llvm::Value *SrcVal =
4208 SmallVector<const Stmt *, 4> ArgVec;
4209 ArrayRef<ParmVarDecl *> params = CD->
parameters().drop_front(IsCopy ? 1 : 0);
4210 for (
const ParmVarDecl *PD : params) {
4211 assert(PD->hasDefaultArg() &&
"ctor closure lacks default args");
4212 ArgVec.push_back(PD->getDefaultArg());
4215 CodeGenFunction::RunCleanupsScope Cleanups(CGF);
4217 const auto *FPT = CD->
getType()->
castAs<FunctionProtoType>();
4218 CGF.
EmitCallArgs(Args, FPT, llvm::ArrayRef(ArgVec), CD, IsCopy ? 1 : 0);
4221 AddedStructorArgCounts ExtraArgs =
4226 llvm::Constant *CalleePtr =
4231 Args, CD,
Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix);
4232 CGF.
EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args);
4234 Cleanups.ForceCleanup();
4243llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T,
4245 int32_t VBPtrOffset,
4250 const CXXConstructorDecl *CD =
4257 uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity();
4258 SmallString<256> MangledName;
4260 llvm::raw_svector_ostream
Out(MangledName);
4261 getMangleContext().mangleCXXCatchableType(T, CD, CT, Size, NVOffset,
4262 VBPtrOffset, VBIndex, Out);
4264 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4265 return getImageRelativeConstant(GV);
4269 llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(T));
4273 llvm::Constant *CopyCtor;
4280 CopyCtor = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4282 CopyCtor = getImageRelativeConstant(CopyCtor);
4284 bool IsScalar = !RD;
4285 bool HasVirtualBases =
false;
4286 bool IsStdBadAlloc =
false;
4287 QualType PointeeType = T;
4301 if (HasVirtualBases)
4306 llvm::Constant *Fields[] = {
4307 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4309 llvm::ConstantInt::get(CGM.
IntTy, NVOffset),
4310 llvm::ConstantInt::getSigned(CGM.
IntTy, VBPtrOffset),
4311 llvm::ConstantInt::get(CGM.
IntTy, VBIndex),
4312 llvm::ConstantInt::get(CGM.
IntTy, Size),
4315 llvm::StructType *CTType = getCatchableTypeType();
4316 auto *GV =
new llvm::GlobalVariable(
4317 CGM.
getModule(), CTType,
true, getLinkageForRTTI(T),
4318 llvm::ConstantStruct::get(CTType, Fields), MangledName);
4319 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4320 GV->setSection(
".xdata");
4321 if (GV->isWeakForLinker())
4322 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4323 return getImageRelativeConstant(GV);
4326llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) {
4330 llvm::GlobalVariable *&CTA = CatchableTypeArrays[T];
4337 llvm::SmallSetVector<llvm::Constant *, 2> CatchableTypes;
4347 const CXXRecordDecl *MostDerivedClass =
nullptr;
4355 if (MostDerivedClass) {
4356 const ASTContext &Context = getContext();
4357 const ASTRecordLayout &MostDerivedLayout =
4360 SmallVector<MSRTTIClass, 8> Classes;
4362 Classes.front().initialize(
nullptr,
nullptr);
4364 for (
const MSRTTIClass &
Class : Classes) {
4367 (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous))
4372 if (
Class.VirtualRoot) {
4383 CatchableTypes.insert(getCatchableType(RTTITy,
Class.OffsetInVBase,
4384 VBPtrOffset, OffsetInVBTable));
4392 CatchableTypes.insert(getCatchableType(T));
4405 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4416 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4418 uint32_t NumEntries = CatchableTypes.size();
4419 llvm::Type *CTType = getImageRelativeType(CGM.
DefaultPtrTy);
4420 llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries);
4421 llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries);
4422 llvm::Constant *Fields[] = {
4423 llvm::ConstantInt::get(CGM.
IntTy, NumEntries),
4424 llvm::ConstantArray::get(
4425 AT, llvm::ArrayRef(CatchableTypes.begin(),
4426 CatchableTypes.end()))
4428 SmallString<256> MangledName;
4430 llvm::raw_svector_ostream
Out(MangledName);
4431 getMangleContext().mangleCXXCatchableTypeArray(T, NumEntries, Out);
4433 CTA =
new llvm::GlobalVariable(
4434 CGM.
getModule(), CTAType,
true, getLinkageForRTTI(T),
4435 llvm::ConstantStruct::get(CTAType, Fields), MangledName);
4436 CTA->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4437 CTA->setSection(
".xdata");
4438 if (CTA->isWeakForLinker())
4439 CTA->setComdat(CGM.
getModule().getOrInsertComdat(CTA->getName()));
4443llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(QualType T) {
4444 bool IsConst, IsVolatile, IsUnaligned;
4449 llvm::GlobalVariable *CTA = getCatchableTypeArray(T);
4456 ->getLimitedValue();
4458 SmallString<256> MangledName;
4460 llvm::raw_svector_ostream
Out(MangledName);
4461 getMangleContext().mangleCXXThrowInfo(T, IsConst, IsVolatile, IsUnaligned,
4467 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4483 llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4486 if (!DtorD->isTrivial())
4489 llvm::Constant *ForwardCompat =
4490 getImageRelativeConstant(llvm::Constant::getNullValue(CGM.
Int8PtrTy));
4491 llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant(CTA);
4492 llvm::StructType *TIType = getThrowInfoType();
4493 llvm::Constant *Fields[] = {
4494 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4495 getImageRelativeConstant(CleanupFn),
4497 PointerToCatchableTypes
4499 auto *GV =
new llvm::GlobalVariable(
4500 CGM.
getModule(), TIType,
true, getLinkageForRTTI(T),
4501 llvm::ConstantStruct::get(TIType, Fields), MangledName.str());
4502 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4503 GV->setSection(
".xdata");
4504 if (GV->isWeakForLinker())
4505 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4509void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF,
const CXXThrowExpr *E) {
4511 assert(SubExpr &&
"SubExpr cannot be null");
4512 QualType ThrowType = SubExpr->
getType();
4521 llvm::GlobalVariable *TI = getThrowInfo(ThrowType);
4528std::pair<llvm::Value *, const CXXRecordDecl *>
4529MicrosoftCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
4530 const CXXRecordDecl *RD) {
4532 std::tie(This, std::ignore, RD) = performBaseAdjustment(CGF, This, T);
4536bool MicrosoftCXXABI::isPermittedToBeHomogeneousAggregate(
4537 const CXXRecordDecl *RD)
const {
4567 for (
const CXXBaseSpecifier &B : RD->
bases()) {
4568 if (
const CXXRecordDecl *FRD = B.getType()->getAsCXXRecordDecl()) {
4569 if (!isPermittedToBeHomogeneousAggregate(FRD))
static Address emitDynamicCastToVoid(CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, Address src)
static mlir::Value emitExactDynamicCast(CIRGenItaniumCXXABI &abi, CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, QualType destRecordTy, cir::PointerType destCIRTy, bool isRefCast, Address src)
static RValue performReturnAdjustment(CIRGenFunction &cgf, QualType resultType, RValue rv, const ThunkInfo &thunk)
static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM)
static void emitTlsGuardCheck(CodeGenFunction &CGF, llvm::GlobalValue *TlsGuard, llvm::BasicBlock *DynInitBB, llvm::BasicBlock *ContinueBB)
static llvm::GlobalVariable * getTypeInfoVTable(CodeGenModule &CGM)
static bool hasDefaultCXXMethodCC(ASTContext &Context, const CXXMethodDecl *MD)
static bool isTrivialForMSVC(const CXXRecordDecl *RD, QualType Ty, CodeGenModule &CGM)
static llvm::FunctionCallee getInitThreadAbortFn(CodeGenModule &CGM)
static llvm::FunctionCallee getInitThreadHeaderFn(CodeGenModule &CGM)
static llvm::GlobalValue * getTlsGuardVar(CodeGenModule &CGM)
static QualType decomposeTypeForEH(ASTContext &Context, QualType T, bool &IsConst, bool &IsVolatile, bool &IsUnaligned)
static llvm::CallBase * emitRTtypeidCall(CodeGenFunction &CGF, llvm::Value *Argument)
static llvm::FunctionCallee getDynTlsOnDemandInitFn(CodeGenModule &CGM)
static void emitDynamicTlsInitializationCall(CodeGenFunction &CGF, llvm::GlobalValue *TlsGuard, llvm::BasicBlock *ContinueBB)
static void detectAmbiguousBases(SmallVectorImpl< MSRTTIClass > &Classes)
Find ambiguity among base classes.
static void emitDynamicTlsInitialization(CodeGenFunction &CGF)
static void serializeClassHierarchy(SmallVectorImpl< MSRTTIClass > &Classes, const CXXRecordDecl *RD)
Recursively serializes a class hierarchy in pre-order depth first order.
static llvm::FunctionCallee getInitThreadFooterFn(CodeGenModule &CGM)
static bool isDeletingDtor(GlobalDecl GD)
static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr)
static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM)
static void mangleVFTableName(MicrosoftMangleContext &MangleContext, const CXXRecordDecl *RD, const VPtrInfo &VFPtr, SmallString< 256 > &Name)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
bool isMemberPointerToDerivedMember() const
const ValueDecl * getMemberPointerDecl() const
ArrayRef< const CXXRecordDecl * > getMemberPointerPath() 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.
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
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.
const LangOptions & getLangOpts() const
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
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 CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD)
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
void recordMemberDataPointerEvaluation(const ValueDecl *VD)
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
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.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
bool hasExtendableVFPtr() const
hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...
Represents a base class of a C++ class.
VarDecl * getExceptionDecl() const
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
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.
QualType getThisType() const
Return the type of the this pointer.
Represents a C++ struct/union/class.
bool hasNonTrivialCopyAssignment() const
Determine whether this class has a non-trivial copy assignment operator (C++ [class....
CXXRecordDecl * getMostRecentDecl()
bool hasPrivateFields() const
bool hasProtectedFields() const
bool hasNonTrivialDestructor() const
Determine whether this class has a non-trivial destructor (C++ [class.dtor]p3)
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_range vbases()
MSInheritanceModel getMSInheritanceModel() const
Returns the inheritance model used for this record.
bool nullFieldOffsetIsZero() const
In the Microsoft C++ ABI, use zero for the field offset of a null data member pointer if we can guara...
bool hasDefinition() const
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
bool hasNonTrivialDefaultConstructor() const
Determine whether this class has a non-trivial default constructor (C++11 [class.ctor]p5).
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is virtually derived from the class Base.
bool needsImplicitCopyAssignment() const
Determine whether this class needs an implicit copy assignment operator to be lazily declared.
bool hasSimpleCopyAssignment() const
true if we know for sure that this class has a single, accessible, unambiguous copy assignment operat...
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
const Expr * getSubExpr() const
path_iterator path_begin()
CastKind getCastKind() const
const CXXBaseSpecifier *const * path_const_iterator
CharUnits - This is an opaque type for sizes expressed in character units.
bool isNegative() const
isNegative - Test whether the quantity is less than zero.
bool isPositive() const
isPositive - Test whether the quantity is greater than zero.
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.
bool hasProfileIRInstr() const
Check if IR level profile instrumentation is on.
static ABIArgInfo getIndirect(CharUnits Alignment, unsigned AddrSpace, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
void setSRetAfterThis(bool AfterThis)
bool isHomogeneousAggregate(QualType Ty, const Type *&Base, uint64_t &Members) const
isHomogeneousAggregate - Return true if a type is an ELFv2 homogeneous aggregate.
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...
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")
Given a pointer to i8, adjust it by a given constant offset.
Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, const llvm::Twine &Name="")
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")
Implements C++ ABI-specific code generation functions.
RecordArgABI
Specify how one should pass an argument of a record type.
MangleContext & getMangleContext()
Gets the mangle context.
static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, llvm::FunctionType *FTy)
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
bool isInstanceMethod() const
ABIArgInfo & getReturnInfo()
CanQualType getReturnType() const
unsigned getEffectiveCallingConvention() const
getEffectiveCallingConvention - Return the actual calling convention to use, which may depend on the ...
void add(RValue rvalue, QualType type)
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.
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
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...
void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr, llvm::FunctionCallee Callee)
Emit a musttail call for a thunk with a potentially adjusted this pointer.
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.
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::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
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)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV, bool PerformInit)
EmitCXXGlobalVarDeclInit - Create the initializer for a C++ variable with global storage.
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 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.
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,...
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::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, QualType DeleteTy, llvm::Value *NumElements=nullptr, CharUnits CookieSize=CharUnits())
CodeGenTypes & getTypes() const
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitCallArgs(CallArgList &Args, PrototypeWrapper Prototype, llvm::iterator_range< CallExpr::const_arg_iterator > ArgRange, AbstractCallee AC=AbstractCallee(), unsigned ParamsToSkip=0, EvaluationOrder Order=EvaluationOrder::Default)
EmitCallArgs - Emit call arguments for a function.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
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...
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const
Set visibility, dllimport/dllexport and dso_local.
void AddCXXDtorEntry(llvm::FunctionCallee DtorFn, llvm::Constant *Object)
Add a destructor and object to add to the C++ global destructor function.
void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD)
Create and attach type metadata for the given vtable.
void setDSOLocal(llvm::GlobalValue *GV) const
llvm::GlobalObject::VCallVisibility GetVCallVisibilityLevel(const CXXRecordDecl *RD, llvm::DenseSet< const CXXRecordDecl * > &Visited)
Returns the vcall visibility of the given type.
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()
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the given function.
const ABIInfo & getABIInfo()
DiagnosticsEngine & getDiags() const
llvm::Constant * getAddrOfCXXStructor(GlobalDecl GD, const CGFunctionInfo *FnInfo=nullptr, llvm::FunctionType *FnType=nullptr, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the constructor/destructor of the given type.
llvm::GlobalValue::LinkageTypes getLLVMLinkageForDeclarator(const DeclaratorDecl *D, GVALinkage Linkage)
Returns LLVM linkage for a declarator.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
void EmitGlobal(GlobalDecl D)
Emit code for a single global function or var decl.
void addUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.used metadata.
void AppendLinkerOptions(StringRef Opts)
Appends Opts to the "llvm.linker.options" metadata value.
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D)
Try to emit a base destructor as an alias to its primary base-class destructor.
const llvm::DataLayout & getDataLayout() const
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, CastExpr::path_const_iterator End)
CharUnits getVBaseAlignment(CharUnits DerivedAlign, const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the assumed alignment of a virtual base of a class.
void EmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target)
Emit a definition as a global alias for another definition, unconditionally.
llvm::Function * codegenCXXStructor(GlobalDecl GD)
llvm::Constant * CreateRuntimeVariable(llvm::Type *Ty, StringRef Name)
Create a new runtime global variable with the specified type and name.
void setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const
Set the TLS mode for the given LLVM GlobalValue for the thread-local variable declaration D.
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.
MicrosoftVTableContext & getMicrosoftVTableContext()
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
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::LLVMContext & getLLVMContext()
llvm::GlobalValue * GetGlobalValue(StringRef Ref)
void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO)
void setDLLImportDLLExport(llvm::GlobalValue *GV, GlobalDecl D) const
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 addDeferredVTable(const CXXRecordDecl *RD)
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)
const CGFunctionInfo & arrangeCXXMethodDeclaration(const CXXMethodDecl *MD)
C++ methods have some special rules and also have implicit parameters.
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....
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD)
Arrange a thunk that takes 'this' as the first parameter followed by varargs.
const CGFunctionInfo & arrangeCXXConstructorCall(const CallArgList &Args, const CXXConstructorDecl *D, CXXCtorType CtorKind, unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, bool PassProtoArgs=true)
Arrange a call to a C++ method, passing the given arguments.
const CGFunctionInfo & arrangeCXXStructorDeclaration(GlobalDecl GD)
const CGFunctionInfo & arrangeMSCtorClosure(const CXXConstructorDecl *CD, CXXCtorType CT)
const CGFunctionInfo & arrangeNullaryFunction()
A nullary function is a freestanding function of type 'void ()'.
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.
A specialization of Address that requires the address to be an LLVM Constant.
static RValue get(llvm::Value *V)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
ArrayRef< ParmVarDecl * > parameters() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Represents a prototype with parameter type info, e.g.
bool isVariadic() const
Whether this function prototype is variadic.
GlobalDecl - represents a global declaration.
GlobalDecl getWithCtorType(CXXCtorType Type)
GlobalDecl getWithDtorType(CXXDtorType Type)
CXXDtorType getDtorType() const
const Decl * getDecl() const
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 isExplicitDefaultVisibilityExportMapping() const
bool isAllDefaultVisibilityExportMapping() const
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
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.
unsigned getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the index of VBase in the vbtable of Derived.
MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD)
const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)
const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
bool isExternallyVisible() const
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool isConstQualified() const
Determine whether this type is const-qualified.
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
bool hasUnaligned() const
bool canPassInRegisters() const
Determine whether this class can be passed in registers.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
virtual bool emitVectorDeletingDtors(const LangOptions &) const
Controls whether to emit MSVC vector deleting destructors.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
virtual bool callGlobalDeleteInDeletingDtor(const LangOptions &) const
Controls whether global operator delete is called by the deleting destructor or at the point where de...
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...
bool isPointerType() 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.
bool isObjectType() const
Determine whether this type is an object type.
Linkage getLinkage() const
Determine the linkage of this type.
bool isNullPtrType() const
ArrayRef< VTableComponent > vtable_components() const
Represents a variable declaration or definition.
TLSKind getTLSKind() const
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.
llvm::Value * getCXXDestructorImplicitParam(CodeGenModule &CGM, llvm::BasicBlock *InsertBlock, llvm::BasicBlock::iterator InsertPoint, const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating)
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
@ 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 * CreateMicrosoftCXXABI(CodeGenModule &CGM)
Creates a Microsoft-family ABI.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
constexpr Variable var(Literal L)
Returns the variable of L.
bool This(InterpState &S, CodePtr OpPC)
bool Ret(InterpState &S, CodePtr &PC)
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.
bool isa(CodeGen::Address addr)
GVALinkage
A more specific kind of linkage than enum Linkage.
void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
bool inheritanceModelHasNVOffsetField(bool IsMemberFunction, MSInheritanceModel Inheritance)
bool inheritanceModelHasOnlyOneField(bool IsMemberFunction, MSInheritanceModel Inheritance)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool inheritanceModelHasVBPtrOffsetField(MSInheritanceModel Inheritance)
bool inheritanceModelHasVBTableOffsetField(MSInheritanceModel Inheritance)
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
@ 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.
@ Template
We are parsing a template declaration.
SmallVector< std::unique_ptr< VPtrInfo >, 2 > VPtrInfoVector
CXXDtorType
C++ destructor types.
@ Dtor_VectorDeleting
Vector deleting dtor.
@ 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.
@ Type
The name was classified as a type.
CastKind
CastKind - The kind of operation required for a conversion.
MSInheritanceModel
Assigned inheritance model for a class in the MS C++ ABI.
CallingConv
CallingConv - Specifies the calling convention that a function uses.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
@ Implicit
An implicit conversion.
const CXXRecordDecl * NearestVBase
llvm::PointerType * VoidPtrTy
llvm::PointerType * Int8PtrPtrTy
CharUnits getIntAlign() const
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
CharUnits getIntSize() const
llvm::IntegerType * SizeTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
llvm::PointerType * Int8PtrTy
llvm::IntegerType * PtrDiffTy
CharUnits getPointerAlign() const
llvm::PointerType * DefaultPtrTy
const CXXRecordDecl * VBase
If nonnull, holds the last vbase which contains the vfptr that the method definition is adjusted to.
CharUnits VFPtrOffset
This is the offset of the vfptr from the start of the last vbase, or the complete type if there are n...
uint64_t Index
Method's index in the vftable.
union clang::ReturnAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
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.
Holds information about the inheritance path to a virtual base or function table pointer.
CharUnits NonVirtualOffset
IntroducingObject is at this offset from its containing complete object or virtual base.
CharUnits FullOffsetInMDC
Static offset from the top of the most derived class to this vfptr, including any virtual base offset...
const CXXRecordDecl * getVBaseWithVPtr() const
The vptr is stored inside the non-virtual component of this virtual base.
const CXXRecordDecl * IntroducingObject
This is the class that introduced the vptr by declaring new virtual methods or virtual bases.
BasePath MangledPath
The bases from the inheritance path that got used to mangle the vbtable name.
BasePath PathToIntroducingObject
This holds the base classes path from the complete type to the first base with the given vfptr offset...
const CXXRecordDecl * ObjectWithVPtr
This is the most derived class that has this vptr at offset zero.
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
struct clang::ReturnAdjustment::VirtualAdjustment::@167242364125115315334113104006210160165266060257 Microsoft
uint32_t VBIndex
Index of the virtual base in the vbtable.
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
struct clang::ThisAdjustment::VirtualAdjustment::@312251255113040203233347230177110330127151157305 Microsoft
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
int32_t VBPtrOffset
The offset of the vbptr of the derived class (in bytes), relative to the ECX after vtordisp adjustmen...