31#include "llvm/ADT/StringExtras.h"
32#include "llvm/ADT/StringSet.h"
33#include "llvm/IR/Intrinsics.h"
41struct VBTableGlobals {
43 SmallVector<llvm::GlobalVariable *, 2> Globals;
46class MicrosoftCXXABI :
public CGCXXABI {
48 MicrosoftCXXABI(CodeGenModule &CGM)
49 : CGCXXABI(CGM), BaseClassDescriptorType(
nullptr),
50 ClassHierarchyDescriptorType(
nullptr),
55 "visibility export mapping option unimplemented in this ABI");
58 bool HasThisReturn(GlobalDecl GD)
const override;
59 bool hasMostDerivedReturn(GlobalDecl GD)
const override;
65 bool isSRetParameterAfterThis()
const override {
return true; }
67 bool isThisCompleteObject(GlobalDecl GD)
const override {
79 case Dtor_Comdat: llvm_unreachable(
"emitting dtor comdat as function?");
81 llvm_unreachable(
"unexpected unified dtor type");
83 llvm_unreachable(
"bad dtor kind");
90 size_t getSrcArgforCopyCtor(
const CXXConstructorDecl *CD,
91 FunctionArgList &Args)
const override {
92 assert(Args.size() >= 2 &&
93 "expected the arglist to have at least two args!");
102 std::vector<CharUnits> getVBPtrOffsets(
const CXXRecordDecl *RD)
override {
103 std::vector<CharUnits> VBPtrOffsets;
104 const ASTContext &Context = getContext();
105 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
107 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
108 for (
const std::unique_ptr<VPtrInfo> &VBT : *VBGlobals.VBTables) {
109 const ASTRecordLayout &SubobjectLayout =
110 Context.getASTRecordLayout(VBT->IntroducingObject);
111 CharUnits Offs = VBT->NonVirtualOffset;
113 if (VBT->getVBaseWithVPtr())
115 VBPtrOffsets.push_back(Offs);
117 llvm::array_pod_sort(VBPtrOffsets.begin(), VBPtrOffsets.end());
121 StringRef GetPureVirtualCallName()
override {
return "_purecall"; }
122 StringRef GetDeletedVirtualCallName()
override {
return "_purecall"; }
124 void emitVirtualObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
125 Address Ptr, QualType ElementType,
126 const CXXDestructorDecl *Dtor)
override;
128 void emitRethrow(CodeGenFunction &CGF,
bool isNoReturn)
override;
129 void emitThrow(CodeGenFunction &CGF,
const CXXThrowExpr *E)
override;
131 void emitBeginCatch(CodeGenFunction &CGF,
const CXXCatchStmt *
C)
override;
133 llvm::GlobalVariable *getMSCompleteObjectLocator(
const CXXRecordDecl *RD,
134 const VPtrInfo &Info);
136 llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty)
override;
138 getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType)
override;
141 CatchTypeInfo getCatchAllTypeInfo()
override {
144 if (getContext().getLangOpts().EHAsynch)
145 return CatchTypeInfo{
nullptr, 0};
147 return CatchTypeInfo{
nullptr, 0x40};
150 bool shouldTypeidBeNullChecked(QualType SrcRecordTy)
override;
151 void EmitBadTypeidCall(CodeGenFunction &CGF)
override;
152 llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
154 llvm::Type *StdTypeInfoPtrTy)
override;
156 bool shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
157 QualType SrcRecordTy)
override;
159 bool shouldEmitExactDynamicCast(QualType DestRecordTy)
override {
163 std::optional<ExactDynamicCastInfo>
164 getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,
165 QualType DestRecordTy)
override {
166 llvm_unreachable(
"unsupported");
169 QualType SrcRecordTy, QualType DestTy,
170 QualType DestRecordTy,
171 const ExactDynamicCastInfo &CastInfo,
172 llvm::BasicBlock *CastSuccess,
173 llvm::BasicBlock *CastFail)
override {
174 llvm_unreachable(
"unsupported");
177 llvm::Value *emitDynamicCastCall(CodeGenFunction &CGF, Address
Value,
178 QualType SrcRecordTy, QualType DestTy,
179 QualType DestRecordTy,
180 llvm::BasicBlock *CastEnd)
override;
183 QualType SrcRecordTy)
override;
185 bool EmitBadCastCall(CodeGenFunction &CGF)
override;
186 bool canSpeculativelyEmitVTable(
const CXXRecordDecl *RD)
const override {
191 GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
192 const CXXRecordDecl *ClassDecl,
193 const CXXRecordDecl *BaseClassDecl)
override;
196 EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
197 const CXXRecordDecl *RD)
override;
200 EmitDtorCompleteObjectHandler(CodeGenFunction &CGF);
202 void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF,
203 const CXXRecordDecl *RD)
override;
205 void EmitCXXConstructors(
const CXXConstructorDecl *D)
override;
239 AddedStructorArgCounts
240 buildStructorSignature(GlobalDecl GD,
241 SmallVectorImpl<CanQualType> &ArgTys)
override;
244 bool useThunkForDtorVariant(
const CXXDestructorDecl *Dtor,
249 void setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
250 const CXXDestructorDecl *Dtor,
253 llvm::GlobalValue::LinkageTypes
257 void EmitCXXDestructors(
const CXXDestructorDecl *D)
override;
259 const CXXRecordDecl *getThisArgumentTypeForMethod(GlobalDecl GD)
override {
262 if (MD->isVirtual()) {
263 GlobalDecl LookupGD = GD;
264 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
268 return MD->getParent();
272 LookupGD = GlobalDecl(
278 MethodVFTableLocation ML =
290 return MD->getParent();
294 adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD,
296 bool VirtualCall)
override;
298 void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy,
299 FunctionArgList &Params)
override;
301 void EmitInstanceFunctionProlog(CodeGenFunction &CGF)
override;
303 AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF,
304 const CXXConstructorDecl *D,
310 const CXXDestructorDecl *DD,
315 void EmitDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *DD,
318 QualType ThisTy)
override;
320 void emitVTableTypeMetadata(
const VPtrInfo &Info,
const CXXRecordDecl *RD,
321 llvm::GlobalVariable *VTable);
323 void emitVTableDefinitions(CodeGenVTables &CGVT,
324 const CXXRecordDecl *RD)
override;
326 bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
327 CodeGenFunction::VPtr Vptr)
override;
331 bool doStructorsInitializeVPtrs(
const CXXRecordDecl *VTableClass)
override {
332 return !VTableClass->
hasAttr<MSNoVTableAttr>();
336 getVTableAddressPoint(BaseSubobject Base,
337 const CXXRecordDecl *VTableClass)
override;
339 llvm::Value *getVTableAddressPointInStructor(
340 CodeGenFunction &CGF,
const CXXRecordDecl *VTableClass,
341 BaseSubobject Base,
const CXXRecordDecl *NearestVBase)
override;
343 llvm::GlobalVariable *getAddrOfVTable(
const CXXRecordDecl *RD,
344 CharUnits VPtrOffset)
override;
346 CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
347 Address This, llvm::Type *Ty,
348 SourceLocation Loc)
override;
351 EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
353 DeleteOrMemberCallExpr E,
354 llvm::CallBase **CallOrInvoke)
override;
356 void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD,
357 CallArgList &CallArgs)
override {
360 "Only vector deleting destructor thunks are available in this ABI");
365 void emitVirtualInheritanceTables(
const CXXRecordDecl *RD)
override;
367 llvm::GlobalVariable *
368 getAddrOfVBTable(
const VPtrInfo &VBT,
const CXXRecordDecl *RD,
369 llvm::GlobalVariable::LinkageTypes
Linkage);
371 llvm::GlobalVariable *
372 getAddrOfVirtualDisplacementMap(
const CXXRecordDecl *SrcRD,
373 const CXXRecordDecl *DstRD) {
374 SmallString<256> OutName;
375 llvm::raw_svector_ostream
Out(OutName);
376 getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out);
377 StringRef MangledName = OutName.str();
379 if (
auto *VDispMap = CGM.
getModule().getNamedGlobal(MangledName))
384 SmallVector<llvm::Constant *, 4> Map(NumEntries,
385 llvm::PoisonValue::get(CGM.
IntTy));
386 Map[0] = llvm::ConstantInt::get(CGM.
IntTy, 0);
387 bool AnyDifferent =
false;
388 for (
const auto &I : SrcRD->
vbases()) {
389 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
395 Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.
IntTy, DstVBIndex * 4);
396 AnyDifferent |= SrcVBIndex != DstVBIndex;
402 llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.
IntTy, Map.size());
403 llvm::Constant *
Init = llvm::ConstantArray::get(VDispMapTy, Map);
404 llvm::GlobalValue::LinkageTypes
Linkage =
406 ? llvm::GlobalValue::LinkOnceODRLinkage
407 : llvm::GlobalValue::InternalLinkage;
408 auto *VDispMap =
new llvm::GlobalVariable(
414 void emitVBTableDefinition(
const VPtrInfo &VBT,
const CXXRecordDecl *RD,
415 llvm::GlobalVariable *GV)
const;
417 void setThunkLinkage(llvm::Function *Thunk,
bool ForVTable,
418 GlobalDecl GD,
bool ReturnAdjustment)
override {
423 Thunk->setLinkage(llvm::GlobalValue::InternalLinkage);
424 else if (ReturnAdjustment)
425 Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage);
427 Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
430 bool exportThunk()
override {
return false; }
432 llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
433 const CXXRecordDecl * ,
434 const ThunkInfo &TI)
override;
436 llvm::Value *performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
437 const CXXRecordDecl * ,
438 const ReturnAdjustment &RA)
override;
440 void EmitThreadLocalInitFuncs(
441 CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
442 ArrayRef<llvm::Function *> CXXThreadLocalInits,
443 ArrayRef<const VarDecl *> CXXThreadLocalInitVars)
override;
445 bool usesThreadWrapperFunction(
const VarDecl *VD)
const override {
446 return getContext().getLangOpts().isCompatibleWithMSVC(
447 LangOptions::MSVC2019_5) &&
449 (!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD));
451 LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
const VarDecl *VD,
452 QualType LValType)
override;
454 void EmitGuardedInit(CodeGenFunction &CGF,
const VarDecl &D,
455 llvm::GlobalVariable *DeclPtr,
456 bool PerformInit)
override;
457 void registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
458 llvm::FunctionCallee Dtor,
459 llvm::Constant *
Addr)
override;
484 bool requiresArrayCookie(
const CXXDeleteExpr *
expr,
485 QualType elementType)
override;
486 bool requiresArrayCookie(
const CXXNewExpr *
expr)
override;
487 CharUnits getArrayCookieSizeImpl(QualType
type)
override;
488 Address InitializeArrayCookie(CodeGenFunction &CGF,
490 llvm::Value *NumElements,
491 const CXXNewExpr *
expr,
492 QualType ElementType)
override;
493 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
495 CharUnits cookieSize)
override;
497 friend struct MSRTTIBuilder;
499 bool isImageRelative()
const {
504 llvm::StructType *getTypeDescriptorType(StringRef TypeInfoString) {
505 llvm::SmallString<32> TDTypeName(
"rtti.TypeDescriptor");
506 TDTypeName += llvm::utostr(TypeInfoString.size());
507 llvm::StructType *&TypeDescriptorType =
508 TypeDescriptorTypeMap[TypeInfoString.size()];
509 if (TypeDescriptorType)
510 return TypeDescriptorType;
511 llvm::Type *FieldTypes[] = {
514 llvm::ArrayType::get(CGM.
Int8Ty, TypeInfoString.size() + 1)};
516 llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes, TDTypeName);
517 return TypeDescriptorType;
520 llvm::Type *getImageRelativeType(llvm::Type *PtrType) {
521 if (!isImageRelative())
526 llvm::StructType *getBaseClassDescriptorType() {
527 if (BaseClassDescriptorType)
528 return BaseClassDescriptorType;
529 llvm::Type *FieldTypes[] = {
538 BaseClassDescriptorType = llvm::StructType::create(
540 return BaseClassDescriptorType;
543 llvm::StructType *getClassHierarchyDescriptorType() {
544 if (ClassHierarchyDescriptorType)
545 return ClassHierarchyDescriptorType;
549 ClassHierarchyDescriptorType =
550 llvm::StructType::create(FieldTypes,
"rtti.ClassHierarchyDescriptor");
551 return ClassHierarchyDescriptorType;
554 llvm::StructType *getCompleteObjectLocatorType() {
555 if (CompleteObjectLocatorType)
556 return CompleteObjectLocatorType;
557 llvm::Type *FieldTypes[] = {
563 getImageRelativeType(CGM.
VoidTy),
565 llvm::ArrayRef<llvm::Type *> FieldTypesRef(FieldTypes);
566 if (!isImageRelative())
567 FieldTypesRef = FieldTypesRef.drop_back();
568 CompleteObjectLocatorType =
569 llvm::StructType::create(FieldTypesRef,
"rtti.CompleteObjectLocator");
570 return CompleteObjectLocatorType;
573 llvm::GlobalVariable *getImageBase() {
574 StringRef Name =
"__ImageBase";
575 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(Name))
580 llvm::GlobalValue::ExternalLinkage,
586 llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) {
587 if (!isImageRelative())
590 if (PtrVal->isNullValue())
591 return llvm::Constant::getNullValue(CGM.
IntTy);
593 llvm::Constant *ImageBaseAsInt =
594 llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.
IntPtrTy);
595 llvm::Constant *PtrValAsInt =
596 llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.
IntPtrTy);
597 llvm::Constant *Diff =
598 llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt,
600 return llvm::ConstantExpr::getTrunc(Diff, CGM.
IntTy);
604 MicrosoftMangleContext &getMangleContext() {
608 llvm::Constant *getZeroInt() {
609 return llvm::ConstantInt::get(CGM.
IntTy, 0);
612 llvm::Constant *getAllOnesInt() {
613 return llvm::Constant::getAllOnesValue(CGM.
IntTy);
616 CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD)
override;
619 GetNullMemberPointerFields(
const MemberPointerType *MPT,
620 llvm::SmallVectorImpl<llvm::Constant *> &fields);
625 llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
627 llvm::Value *VBPtrOffset,
628 llvm::Value *VBTableOffset,
629 llvm::Value **VBPtr =
nullptr);
631 llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
634 int32_t VBTableOffset,
635 llvm::Value **VBPtr =
nullptr) {
636 assert(VBTableOffset % 4 == 0 &&
"should be byte offset into table of i32s");
637 llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.
IntTy, VBPtrOffset),
638 *VBTOffset = llvm::ConstantInt::get(CGM.
IntTy, VBTableOffset);
639 return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
642 std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
643 performBaseAdjustment(CodeGenFunction &CGF, Address
Value,
644 QualType SrcRecordTy);
648 llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF,
const Expr *E,
649 const CXXRecordDecl *RD, Address Base,
650 llvm::Value *VirtualBaseAdjustmentOffset,
651 llvm::Value *VBPtrOffset );
655 llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
656 bool IsMemberFunction,
657 const CXXRecordDecl *RD,
658 CharUnits NonVirtualBaseAdjustment,
659 unsigned VBTableIndex);
661 bool MemberPointerConstantIsNull(
const MemberPointerType *MPT,
665 void EmitVBPtrStores(CodeGenFunction &CGF,
const CXXRecordDecl *RD);
668 const VBTableGlobals &enumerateVBTables(
const CXXRecordDecl *RD);
671 llvm::Function *EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
672 const MethodVFTableLocation &ML);
674 llvm::Constant *EmitMemberDataPointer(
const CXXRecordDecl *RD,
678 llvm::Type *ConvertMemberPointerType(
const MemberPointerType *MPT)
override;
680 bool isZeroInitializable(
const MemberPointerType *MPT)
override;
682 bool isMemberPointerConvertible(
const MemberPointerType *MPT)
const override {
684 return RD->
hasAttr<MSInheritanceAttr>();
687 llvm::Constant *EmitNullMemberPointer(
const MemberPointerType *MPT)
override;
689 llvm::Constant *EmitMemberDataPointer(
const MemberPointerType *MPT,
690 CharUnits offset)
override;
691 llvm::Constant *EmitMemberFunctionPointer(
const CXXMethodDecl *MD)
override;
692 llvm::Constant *EmitMemberPointer(
const APValue &MP, QualType MPT)
override;
694 llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
697 const MemberPointerType *MPT,
698 bool Inequality)
override;
700 llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
702 const MemberPointerType *MPT)
override;
704 llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
const Expr *E,
705 Address Base, llvm::Value *MemPtr,
706 const MemberPointerType *MPT,
707 bool IsInBounds)
override;
709 llvm::Value *EmitNonNullMemberPointerConversion(
710 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
713 CGBuilderTy &Builder);
715 llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
717 llvm::Value *Src)
override;
719 llvm::Constant *EmitMemberPointerConversion(
const CastExpr *E,
720 llvm::Constant *Src)
override;
722 llvm::Constant *EmitMemberPointerConversion(
723 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
728 EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
const Expr *E,
729 Address This, llvm::Value *&ThisPtrForCall,
731 const MemberPointerType *MPT)
override;
733 void emitCXXStructor(GlobalDecl GD)
override;
735 llvm::StructType *getCatchableTypeType() {
736 if (CatchableTypeType)
737 return CatchableTypeType;
738 llvm::Type *FieldTypes[] = {
747 CatchableTypeType = llvm::StructType::create(
749 return CatchableTypeType;
752 llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) {
753 llvm::StructType *&CatchableTypeArrayType =
754 CatchableTypeArrayTypeMap[NumEntries];
755 if (CatchableTypeArrayType)
756 return CatchableTypeArrayType;
758 llvm::SmallString<23> CTATypeName(
"eh.CatchableTypeArray.");
759 CTATypeName += llvm::utostr(NumEntries);
760 llvm::Type *CTType = getImageRelativeType(CGM.
DefaultPtrTy);
761 llvm::Type *FieldTypes[] = {
763 llvm::ArrayType::get(CTType, NumEntries)
765 CatchableTypeArrayType =
766 llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes, CTATypeName);
767 return CatchableTypeArrayType;
770 llvm::StructType *getThrowInfoType() {
772 return ThrowInfoType;
773 llvm::Type *FieldTypes[] = {
779 ThrowInfoType = llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes,
781 return ThrowInfoType;
788 llvm::FunctionType *FTy =
789 llvm::FunctionType::get(CGM.
VoidTy, Args,
false);
790 llvm::FunctionCallee Throw =
794 if (
auto *Fn = dyn_cast<llvm::Function>(Throw.getCallee()))
795 Fn->setCallingConv(llvm::CallingConv::X86_StdCall);
800 llvm::Function *getAddrOfCXXCtorClosure(
const CXXConstructorDecl *CD,
803 llvm::Constant *getCatchableType(QualType
T,
804 uint32_t NVOffset = 0,
805 int32_t VBPtrOffset = -1,
806 uint32_t VBIndex = 0);
808 llvm::GlobalVariable *getCatchableTypeArray(QualType
T);
810 llvm::GlobalVariable *getThrowInfo(QualType
T)
override;
812 std::pair<llvm::Value *, const CXXRecordDecl *>
813 LoadVTablePtr(CodeGenFunction &CGF, Address This,
814 const CXXRecordDecl *RD)
override;
817 isPermittedToBeHomogeneousAggregate(
const CXXRecordDecl *RD)
const override;
820 typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
821 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;
822 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;
824 VFTablesMapTy VFTablesMap;
825 VTablesMapTy VTablesMap;
828 llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
832 llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap;
837 GuardInfo() =
default;
838 llvm::GlobalVariable *Guard =
nullptr;
839 unsigned BitIndex = 0;
844 llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap;
845 llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap;
846 llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap;
848 llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap;
849 llvm::StructType *BaseClassDescriptorType;
850 llvm::StructType *ClassHierarchyDescriptorType;
851 llvm::StructType *CompleteObjectLocatorType;
853 llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays;
855 llvm::StructType *CatchableTypeType;
856 llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;
857 llvm::StructType *ThrowInfoType;
863MicrosoftCXXABI::getRecordArgABI(
const CXXRecordDecl *RD)
const {
875 case llvm::Triple::thumb:
881 case llvm::Triple::x86: {
887 getContext().getTypeInfo(getContext().getCanonicalTagType(RD));
893 return RAA_DirectInMemory;
896 case llvm::Triple::x86_64:
897 case llvm::Triple::aarch64:
901 llvm_unreachable(
"invalid enum");
904void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
905 const CXXDeleteExpr *DE,
907 QualType ElementType,
908 const CXXDestructorDecl *Dtor) {
911 if (!getContext().getTargetInfo().callGlobalDeleteInDeletingDtor(
912 getContext().getLangOpts())) {
915 llvm::Value *MDThis =
916 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,
926void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF,
bool isNoReturn) {
927 llvm::Value *Args[] = {llvm::ConstantPointerNull::get(CGM.
Int8PtrTy),
936void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
937 const CXXCatchStmt *S) {
941 llvm::BasicBlock *CatchPadBB = CGF.
Builder.GetInsertBlock();
942 llvm::CatchPadInst *CPI =
954 CPI->setArgOperand(2,
var.getObjectAddress(CGF).emitRawPointer(CGF));
962std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
963MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address
Value,
964 QualType SrcRecordTy) {
967 const ASTContext &Context = getContext();
973 return std::make_tuple(
Value, llvm::ConstantInt::get(CGF.
Int32Ty, 0),
978 const CXXRecordDecl *PolymorphicBase =
nullptr;
979 for (
auto &Base : SrcDecl->
vbases()) {
980 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
982 PolymorphicBase = BaseDecl;
986 assert(PolymorphicBase &&
"polymorphic class has no apparent vfptr?");
988 llvm::Value *Offset =
989 GetVirtualBaseClassOffset(CGF,
Value, SrcDecl, PolymorphicBase);
991 Value.getElementType(),
Value.emitRawPointer(CGF), Offset);
992 CharUnits VBaseAlign =
994 return std::make_tuple(Address(Ptr, CGF.
Int8Ty, VBaseAlign), Offset,
998bool MicrosoftCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {
1000 return !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
1004 llvm::Value *Argument) {
1005 llvm::Type *ArgTypes[] = {CGF.
Int8PtrTy};
1006 llvm::FunctionType *FTy =
1007 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false);
1008 llvm::Value *Args[] = {Argument};
1013void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
1014 llvm::CallBase *
Call =
1016 Call->setDoesNotReturn();
1017 CGF.
Builder.CreateUnreachable();
1020llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
1021 QualType SrcRecordTy,
1023 llvm::Type *StdTypeInfoPtrTy) {
1024 std::tie(ThisPtr, std::ignore, std::ignore) =
1025 performBaseAdjustment(CGF, ThisPtr, SrcRecordTy);
1027 return CGF.
Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy);
1030bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
1031 QualType SrcRecordTy) {
1034 !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
1037llvm::Value *MicrosoftCXXABI::emitDynamicCastCall(
1038 CodeGenFunction &CGF, Address This, QualType SrcRecordTy, QualType DestTy,
1039 QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
1040 llvm::Value *SrcRTTI =
1042 llvm::Value *DestRTTI =
1045 llvm::Value *Offset;
1046 std::tie(This, Offset, std::ignore) =
1047 performBaseAdjustment(CGF, This, SrcRecordTy);
1048 llvm::Value *ThisPtr =
This.emitRawPointer(CGF);
1060 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
1062 llvm::Value *Args[] = {
1063 ThisPtr, Offset, SrcRTTI, DestRTTI,
1068llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
1070 QualType SrcRecordTy) {
1071 std::tie(
Value, std::ignore, std::ignore) =
1072 performBaseAdjustment(CGF,
Value, SrcRecordTy);
1076 llvm::Type *ArgTypes[] = {CGF.
Int8PtrTy};
1078 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
1080 llvm::Value *Args[] = {
Value.emitRawPointer(CGF)};
1084bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
1088llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset(
1089 CodeGenFunction &CGF, Address This,
const CXXRecordDecl *ClassDecl,
1090 const CXXRecordDecl *BaseClassDecl) {
1091 const ASTContext &Context = getContext();
1094 llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.
PtrDiffTy, VBPtrChars);
1096 CharUnits VBTableChars =
1099 llvm::Value *VBTableOffset =
1102 llvm::Value *VBPtrToNewBase =
1103 GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset);
1106 return CGF.
Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);
1109bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD)
const {
1119bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD)
const {
1129 uint64_t NumElts = 0;
1169 if (
auto *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
1170 if (Ctor->isUserProvided())
1172 }
else if (
auto *
Template = dyn_cast<FunctionTemplateDecl>(D)) {
1175 }
else if (
auto *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
1176 if (MethodDecl->isCopyAssignmentOperator() && MethodDecl->isDeleted())
1185bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI)
const {
1186 const CXXRecordDecl *RD = FI.
getReturnType()->getAsCXXRecordDecl();
1196 if (isIndirectReturn) {
1217MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
1218 const CXXRecordDecl *RD) {
1219 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1220 assert(IsMostDerivedClass &&
1221 "ctor for a class with virtual bases must have an implicit parameter");
1222 llvm::Value *IsCompleteObject =
1223 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1225 llvm::BasicBlock *CallVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.init_vbases");
1226 llvm::BasicBlock *SkipVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.skip_vbases");
1227 CGF.
Builder.CreateCondBr(IsCompleteObject,
1228 CallVbaseCtorsBB, SkipVbaseCtorsBB);
1233 EmitVBPtrStores(CGF, RD);
1237 return SkipVbaseCtorsBB;
1241MicrosoftCXXABI::EmitDtorCompleteObjectHandler(CodeGenFunction &CGF) {
1242 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1243 assert(IsMostDerivedClass &&
1244 "ctor for a class with virtual bases must have an implicit parameter");
1245 llvm::Value *IsCompleteObject =
1246 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1248 llvm::BasicBlock *CallVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.dtor_vbases");
1249 llvm::BasicBlock *SkipVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.skip_vbases");
1250 CGF.
Builder.CreateCondBr(IsCompleteObject,
1251 CallVbaseDtorsBB, SkipVbaseDtorsBB);
1256 return SkipVbaseDtorsBB;
1259void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
1260 CodeGenFunction &CGF,
const CXXRecordDecl *RD) {
1274 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
1277 CGBuilderTy &Builder = CGF.
Builder;
1279 llvm::Value *Int8This =
nullptr;
1281 for (
const CXXBaseSpecifier &S : RD->
vbases()) {
1282 const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl();
1283 auto I = VBaseMap.find(VBase);
1284 assert(I != VBaseMap.end());
1285 if (!I->second.hasVtorDisp())
1288 llvm::Value *VBaseOffset =
1289 GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase);
1290 uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity();
1293 llvm::Value *VtorDispValue = Builder.CreateSub(
1294 VBaseOffset, llvm::ConstantInt::get(CGM.
PtrDiffTy, ConstantVBaseOffset),
1296 VtorDispValue = Builder.CreateTruncOrBitCast(VtorDispValue, CGF.
Int32Ty);
1299 Int8This = getThisValue(CGF);
1301 llvm::Value *VtorDispPtr =
1302 Builder.CreateInBoundsGEP(CGF.
Int8Ty, Int8This, VBaseOffset);
1304 VtorDispPtr = Builder.CreateConstGEP1_32(CGF.
Int8Ty, VtorDispPtr, -4);
1306 Builder.CreateAlignedStore(VtorDispValue, VtorDispPtr,
1313 CallingConv ExpectedCallingConv = Context.getDefaultCallingConvention(
1317 return ExpectedCallingConv == ActualCallingConv;
1320void MicrosoftCXXABI::EmitCXXConstructors(
const CXXConstructorDecl *D) {
1332 Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1338void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
1339 const CXXRecordDecl *RD) {
1340 Address
This = getThisAddress(CGF);
1342 const ASTContext &Context = getContext();
1345 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
1346 for (
unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
1347 const std::unique_ptr<VPtrInfo> &VBT = (*VBGlobals.VBTables)[I];
1348 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
1349 const ASTRecordLayout &SubobjectLayout =
1351 CharUnits Offs = VBT->NonVirtualOffset;
1353 if (VBT->getVBaseWithVPtr())
1356 llvm::Value *GVPtr =
1363CGCXXABI::AddedStructorArgCounts
1364MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD,
1365 SmallVectorImpl<CanQualType> &ArgTys) {
1366 AddedStructorArgCounts Added;
1372 ArgTys.push_back(getContext().IntTy);
1375 auto *CD = dyn_cast<CXXConstructorDecl>(GD.
getDecl());
1383 const FunctionProtoType *FPT = CD->
getType()->
castAs<FunctionProtoType>();
1384 if (
Class->getNumVBases()) {
1386 ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy);
1389 ArgTys.push_back(getContext().IntTy);
1397void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
1398 const CXXDestructorDecl *Dtor,
1403 GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
1405 const NamedDecl *ND = Dtor;
1410llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(
1415 return llvm::GlobalValue::InternalLinkage;
1426 if (Dtor->
hasAttr<DLLExportAttr>())
1427 return llvm::GlobalValue::WeakODRLinkage;
1428 if (Dtor->
hasAttr<DLLImportAttr>())
1429 return llvm::GlobalValue::AvailableExternallyLinkage;
1430 return llvm::GlobalValue::LinkOnceODRLinkage;
1435 return llvm::GlobalValue::LinkOnceODRLinkage;
1437 llvm_unreachable(
"MS C++ ABI does not support unified dtors");
1443 return llvm::GlobalValue::WeakAnyLinkage;
1445 llvm_unreachable(
"MS C++ ABI does not support comdat dtors");
1447 llvm_unreachable(
"invalid dtor type");
1450void MicrosoftCXXABI::EmitCXXDestructors(
const CXXDestructorDecl *D) {
1464MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {
1467 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1482 MethodVFTableLocation ML =
1494 const ASTRecordLayout &DerivedLayout =
1495 getContext().getASTRecordLayout(MD->
getParent());
1502Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
1503 CodeGenFunction &CGF, GlobalDecl GD, Address This,
1508 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD);
1519 GlobalDecl LookupGD = GD;
1520 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1534 MethodVFTableLocation ML =
1549 const CXXRecordDecl *Derived = MD->
getParent();
1550 const CXXRecordDecl *VBase = ML.
VBase;
1551 llvm::Value *VBaseOffset =
1552 GetVirtualBaseClassOffset(CGF,
Result, Derived, VBase);
1554 Result.getElementType(),
Result.emitRawPointer(CGF), VBaseOffset);
1555 CharUnits VBaseAlign =
1559 if (!StaticOffset.
isZero()) {
1575void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
1577 FunctionArgList &Params) {
1578 ASTContext &Context = getContext();
1585 ImplicitParamKind::Other);
1588 const FunctionProtoType *FPT = MD->
getType()->
castAs<FunctionProtoType>();
1590 Params.insert(Params.begin() + 1, IsMostDerived);
1592 Params.push_back(IsMostDerived);
1593 getStructorImplicitParamDecl(CGF) = IsMostDerived;
1598 ImplicitParamKind::Other);
1599 Params.push_back(ShouldDelete);
1600 getStructorImplicitParamDecl(CGF) = ShouldDelete;
1604void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
1621 llvm::Value *
This = loadIncomingCXXThis(CGF);
1624 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.
CurGD);
1625 if (!Adjustment.
isZero()) {
1631 setCXXABIThisValue(CGF, This);
1641 if (HasThisReturn(CGF.
CurGD) || hasMostDerivedReturn(CGF.
CurGD))
1645 assert(getStructorImplicitParamDecl(CGF) &&
1646 "no implicit parameter for a constructor with virtual bases?");
1647 getStructorImplicitParamValue(CGF)
1654 assert(getStructorImplicitParamDecl(CGF) &&
1655 "no implicit parameter for a deleting destructor?");
1656 getStructorImplicitParamValue(CGF)
1659 "should_call_delete");
1663CGCXXABI::AddedStructorArgs MicrosoftCXXABI::getImplicitConstructorArgs(
1670 return AddedStructorArgs{};
1673 const FunctionProtoType *FPT = D->
getType()->
castAs<FunctionProtoType>();
1674 llvm::Value *MostDerivedArg;
1676 MostDerivedArg = getStructorImplicitParamValue(CGF);
1681 return AddedStructorArgs::prefix({{MostDerivedArg, getContext().IntTy}});
1683 return AddedStructorArgs::suffix({{MostDerivedArg, getContext().IntTy}});
1686llvm::Value *MicrosoftCXXABI::getCXXDestructorImplicitParam(
1692void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
1693 const CXXDestructorDecl *DD,
1703 GlobalDecl GD(DD,
Type);
1707 assert(
Type != CXXDtorType::Dtor_Deleting &&
1708 "The deleting destructor should only be called via a virtual call");
1709 This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD,
Type),
1713 llvm::BasicBlock *BaseDtorEndBB =
nullptr;
1715 BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF);
1724 QualType(),
nullptr);
1725 if (BaseDtorEndBB) {
1727 CGF.
Builder.CreateBr(BaseDtorEndBB);
1732void MicrosoftCXXABI::emitVTableTypeMetadata(
const VPtrInfo &Info,
1733 const CXXRecordDecl *RD,
1734 llvm::GlobalVariable *VTable) {
1745 llvm::DenseSet<const CXXRecordDecl *> Visited;
1746 llvm::GlobalObject::VCallVisibility TypeVis =
1748 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1749 VTable->setVCallVisibilityMetadata(TypeVis);
1755 CharUnits AddressPoint =
1756 getContext().getLangOpts().RTTIData
1757 ? getContext().toCharUnitsFromBits(
1758 getContext().getTargetInfo().getPointerWidth(LangAS::Default))
1776 const ASTRecordLayout &Layout =
1777 getContext().getASTRecordLayout(DerivedRD);
1783 Offset = VBI->second.VBaseOffset;
1794void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
1795 const CXXRecordDecl *RD) {
1799 for (
const std::unique_ptr<VPtrInfo>& Info : VFPtrs) {
1800 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->
FullOffsetInMDC);
1801 if (VTable->hasInitializer())
1804 const VTableLayout &VTLayout =
1807 llvm::Constant *RTTI =
nullptr;
1809 [](
const VTableComponent &VTC) { return VTC.isRTTIKind(); }))
1810 RTTI = getMSCompleteObjectLocator(RD, *Info);
1812 ConstantInitBuilder builder(CGM);
1813 auto components = builder.beginStruct();
1815 VTable->hasLocalLinkage());
1816 components.finishAndSetAsInitializer(VTable);
1818 emitVTableTypeMetadata(*Info, RD, VTable);
1822bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField(
1823 CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
1827llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
1828 CodeGenFunction &CGF,
const CXXRecordDecl *VTableClass, BaseSubobject Base,
1829 const CXXRecordDecl *NearestVBase) {
1830 llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass);
1831 if (!VTableAddressPoint) {
1832 assert(
Base.getBase()->getNumVBases() &&
1833 !getContext().getASTRecordLayout(
Base.getBase()).hasOwnVFPtr());
1835 return VTableAddressPoint;
1841 llvm::raw_svector_ostream Out(Name);
1846MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base,
1847 const CXXRecordDecl *VTableClass) {
1848 (void)getAddrOfVTable(VTableClass,
Base.getBaseOffset());
1849 VFTableIdTy
ID(VTableClass,
Base.getBaseOffset());
1850 return VFTablesMap[
ID];
1853llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(
const CXXRecordDecl *RD,
1854 CharUnits VPtrOffset) {
1859 VFTableIdTy
ID(RD, VPtrOffset);
1860 auto [I, Inserted] = VTablesMap.try_emplace(ID);
1864 llvm::GlobalVariable *&VTable = I->second;
1869 if (DeferredVFTables.insert(RD).second) {
1877 llvm::StringSet<> ObservedMangledNames;
1878 for (
const auto &VFPtr : VFPtrs) {
1879 SmallString<256> Name;
1881 if (!ObservedMangledNames.insert(Name.str()).second)
1882 llvm_unreachable(
"Already saw this mangling before?");
1887 const std::unique_ptr<VPtrInfo> *VFPtrI =
1888 llvm::find_if(VFPtrs, [&](
const std::unique_ptr<VPtrInfo> &VPI) {
1889 return VPI->FullOffsetInMDC == VPtrOffset;
1891 if (VFPtrI == VFPtrs.end()) {
1892 VFTablesMap[
ID] =
nullptr;
1895 const std::unique_ptr<VPtrInfo> &VFPtr = *VFPtrI;
1897 SmallString<256> VFTableName;
1907 llvm::GlobalValue::LinkageTypes VFTableLinkage =
1908 RD->
hasAttr<DLLImportAttr>() ? llvm::GlobalValue::LinkOnceODRLinkage
1909 : CGM.getVTableLinkage(RD);
1910 bool VFTableComesFromAnotherTU =
1911 llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) ||
1912 llvm::GlobalValue::isExternalLinkage(VFTableLinkage);
1913 bool VTableAliasIsRequred =
1914 !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData;
1916 if (llvm::GlobalValue *VFTable =
1917 CGM.
getModule().getNamedGlobal(VFTableName)) {
1918 VFTablesMap[
ID] = VFTable;
1919 VTable = VTableAliasIsRequred
1922 :
cast<llvm::GlobalVariable>(VFTable);
1926 const VTableLayout &VTLayout =
1928 llvm::GlobalValue::LinkageTypes VTableLinkage =
1929 VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage;
1931 StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str();
1933 llvm::Type *VTableType = CGM.
getVTables().getVTableType(VTLayout);
1937 llvm::GlobalValue *VFTable;
1938 VTable =
new llvm::GlobalVariable(CGM.
getModule(), VTableType,
1939 true, VTableLinkage,
1940 nullptr, VTableName);
1941 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1943 llvm::Comdat *
C =
nullptr;
1944 if (!VFTableComesFromAnotherTU &&
1945 llvm::GlobalValue::isWeakForLinker(VFTableLinkage))
1946 C = CGM.
getModule().getOrInsertComdat(VFTableName.str());
1951 if (VTableAliasIsRequred) {
1952 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.
Int32Ty, 0),
1953 llvm::ConstantInt::get(CGM.
Int32Ty, 0),
1954 llvm::ConstantInt::get(CGM.
Int32Ty, 1)};
1957 llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr(
1958 VTable->getValueType(), VTable, GEPIndices);
1959 if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) {
1960 VFTableLinkage = llvm::GlobalValue::ExternalLinkage;
1962 C->setSelectionKind(llvm::Comdat::Largest);
1964 VFTable = llvm::GlobalAlias::create(CGM.
Int8PtrTy,
1966 VFTableName.str(), VTableGEP,
1968 VFTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1977 VTable->setComdat(
C);
1979 if (RD->
hasAttr<DLLExportAttr>())
1980 VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1982 VFTablesMap[
ID] = VFTable;
1986CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
1990 SourceLocation Loc) {
1991 CGBuilderTy &Builder = CGF.
Builder;
1995 adjustThisArgumentForVirtualFunctionCall(CGF, GD, This,
true);
1998 llvm::Value *VTable =
2006 auto getObjectWithVPtr = [&] {
2009 [&](
const std::unique_ptr<VPtrInfo> &Info) {
2010 return Info->FullOffsetInMDC == ML.VFPtrOffset;
2019 getObjectWithVPtr(), VTable, Ty,
2027 llvm::Value *VFuncPtr =
2028 Builder.CreateConstInBoundsGEP1_64(Ty, VTable, ML.
Index,
"vfn");
2029 VFunc = Builder.CreateAlignedLoad(Ty, VFuncPtr, CGF.
getPointerAlign());
2032 CGCallee
Callee(GD, VFunc);
2036llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
2037 CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
2038 Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke) {
2039 auto *CE = dyn_cast<const CXXMemberCallExpr *>(E);
2040 auto *D = dyn_cast<const CXXDeleteExpr *>(E);
2041 assert((CE !=
nullptr) ^ (D !=
nullptr));
2042 assert(CE ==
nullptr || CE->arg_begin() == CE->arg_end());
2048 ASTContext &Context = getContext();
2049 bool VectorDeletingDtorsEnabled =
2053 const CGFunctionInfo *FInfo =
2059 bool IsArrayDelete = D && D->isArrayForm() && VectorDeletingDtorsEnabled;
2060 bool IsGlobalDelete = D && D->isGlobalDelete() &&
2063 llvm::Value *ImplicitParam =
2064 CGF.
Builder.getInt32((IsDeleting ? 1 : 0) | (IsGlobalDelete ? 4 : 0) |
2065 (IsArrayDelete ? 2 : 0));
2069 ThisTy = CE->getObjectType();
2071 ThisTy = D->getDestroyedType();
2075 ThisTy = ATy->getElementType();
2077 This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This,
true);
2080 ImplicitParam, Context.
IntTy, CE, CallOrInvoke);
2084const VBTableGlobals &
2085MicrosoftCXXABI::enumerateVBTables(
const CXXRecordDecl *RD) {
2088 auto [Entry, Added] = VBTablesMap.try_emplace(RD);
2089 VBTableGlobals &VBGlobals = Entry->second;
2094 VBGlobals.VBTables = &Context.enumerateVBTables(RD);
2099 for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(),
2100 E = VBGlobals.VBTables->end();
2102 VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD,
Linkage));
2109MicrosoftCXXABI::EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
2110 const MethodVFTableLocation &ML) {
2112 "can't form pointers to ctors or virtual dtors");
2115 SmallString<256> ThunkName;
2116 llvm::raw_svector_ostream
Out(ThunkName);
2117 getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out);
2120 if (llvm::GlobalValue *GV = CGM.
getModule().getNamedValue(ThunkName))
2124 const CGFunctionInfo &FnInfo =
2127 llvm::Function *ThunkFn =
2128 llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage,
2130 assert(ThunkFn->getName() == ThunkName &&
"name was uniqued!");
2133 ? llvm::GlobalValue::LinkOnceODRLinkage
2134 : llvm::GlobalValue::InternalLinkage);
2136 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
2145 ThunkFn->addFnAttr(
"thunk");
2148 ThunkFn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
2151 CodeGenFunction CGF(CGM);
2152 CGF.
CurGD = GlobalDecl(MD);
2157 FunctionArgList FunctionArgs;
2158 buildThisParam(CGF, FunctionArgs);
2162 FunctionArgs, MD->
getLocation(), SourceLocation());
2165 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
2170 llvm::Value *VTable =
2173 llvm::Value *VFuncPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
2174 ThunkPtrTy, VTable, ML.
Index,
"vfn");
2183void MicrosoftCXXABI::emitVirtualInheritanceTables(
const CXXRecordDecl *RD) {
2184 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
2185 for (
unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
2186 const std::unique_ptr<VPtrInfo>& VBT = (*VBGlobals.VBTables)[I];
2187 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
2188 if (GV->isDeclaration())
2189 emitVBTableDefinition(*VBT, RD, GV);
2193llvm::GlobalVariable *
2194MicrosoftCXXABI::getAddrOfVBTable(
const VPtrInfo &VBT,
const CXXRecordDecl *RD,
2195 llvm::GlobalVariable::LinkageTypes
Linkage) {
2196 SmallString<256> OutName;
2197 llvm::raw_svector_ostream
Out(OutName);
2198 getMangleContext().mangleCXXVBTable(RD, VBT.
MangledPath, Out);
2199 StringRef Name = OutName.str();
2201 llvm::ArrayType *VBTableType =
2204 assert(!CGM.
getModule().getNamedGlobal(Name) &&
2205 "vbtable with this name already exists: mangling bug?");
2206 CharUnits Alignment =
2210 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2212 if (RD->
hasAttr<DLLImportAttr>())
2213 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2214 else if (RD->
hasAttr<DLLExportAttr>())
2215 GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2217 if (!GV->hasExternalLinkage())
2218 emitVBTableDefinition(VBT, RD, GV);
2223void MicrosoftCXXABI::emitVBTableDefinition(
const VPtrInfo &VBT,
2224 const CXXRecordDecl *RD,
2225 llvm::GlobalVariable *GV)
const {
2229 "should only emit vbtables for classes with vbtables");
2231 const ASTRecordLayout &BaseLayout =
2233 const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD);
2235 SmallVector<llvm::Constant *, 4> Offsets(1 + ObjectWithVPtr->
getNumVBases(),
2240 Offsets[0] = llvm::ConstantInt::get(CGM.
IntTy, -VBPtrOffset.
getQuantity());
2243 for (
const auto &I : ObjectWithVPtr->
vbases()) {
2244 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
2251 CompleteVBPtrOffset +=
2253 Offset -= CompleteVBPtrOffset;
2255 unsigned VBIndex = Context.getVBTableIndex(ObjectWithVPtr, VBase);
2256 assert(Offsets[VBIndex] ==
nullptr &&
"The same vbindex seen twice?");
2257 Offsets[VBIndex] = llvm::ConstantInt::get(CGM.
IntTy, Offset.
getQuantity());
2260 assert(Offsets.size() ==
2262 llvm::ArrayType *VBTableType =
2263 llvm::ArrayType::get(CGM.
IntTy, Offsets.size());
2264 llvm::Constant *
Init = llvm::ConstantArray::get(VBTableType, Offsets);
2265 GV->setInitializer(
Init);
2267 if (RD->
hasAttr<DLLImportAttr>())
2268 GV->setLinkage(llvm::GlobalVariable::AvailableExternallyLinkage);
2271llvm::Value *MicrosoftCXXABI::performThisAdjustment(
2272 CodeGenFunction &CGF, Address This,
2273 const CXXRecordDecl * ,
const ThunkInfo &TI) {
2274 const ThisAdjustment &TA = TI.
This;
2276 return This.emitRawPointer(CGF);
2282 V =
This.emitRawPointer(CGF);
2286 Address VtorDispPtr =
2292 CGF.
Builder.CreateNeg(VtorDisp));
2305 llvm::Value *VBaseOffset = GetVBaseOffsetFromVBPtr(
2324llvm::Value *MicrosoftCXXABI::performReturnAdjustment(
2325 CodeGenFunction &CGF, Address Ret,
2326 const CXXRecordDecl * ,
const ReturnAdjustment &RA) {
2329 return Ret.emitRawPointer(CGF);
2333 llvm::Value *
V =
Ret.emitRawPointer(CGF);
2338 llvm::Value *VBaseOffset =
2350bool MicrosoftCXXABI::requiresArrayCookie(
const CXXDeleteExpr *
expr,
2351 QualType elementType) {
2357bool MicrosoftCXXABI::requiresArrayCookie(
const CXXNewExpr *
expr) {
2360 return expr->getAllocatedType().isDestructedType();
2363CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType
type) {
2366 ASTContext &Ctx = getContext();
2371llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2373 CharUnits cookieSize) {
2378Address MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
2380 llvm::Value *numElements,
2381 const CXXNewExpr *
expr,
2382 QualType elementType) {
2383 assert(requiresArrayCookie(
expr));
2386 CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
2389 Address cookiePtr = newPtr;
2401 llvm::FunctionCallee Dtor,
2402 llvm::Constant *
Addr) {
2407 llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get(
2408 CGF.
IntTy, DtorStub->getType(),
false);
2411 TLRegDtorTy,
"__tlregdtor", llvm::AttributeList(),
true);
2412 if (llvm::Function *TLRegDtorFn =
2413 dyn_cast<llvm::Function>(TLRegDtor.getCallee()))
2414 TLRegDtorFn->setDoesNotThrow();
2419void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
2420 llvm::FunctionCallee Dtor,
2421 llvm::Constant *
Addr) {
2436void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
2437 CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
2438 ArrayRef<llvm::Function *> CXXThreadLocalInits,
2439 ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
2440 if (CXXThreadLocalInits.empty())
2445 ?
"/include:___dyn_tls_init@12"
2446 :
"/include:__dyn_tls_init");
2451 auto AddToXDU = [&CGM](llvm::Function *InitFunc) {
2452 llvm::GlobalVariable *InitFuncPtr =
new llvm::GlobalVariable(
2453 CGM.
getModule(), InitFunc->getType(),
true,
2454 llvm::GlobalVariable::InternalLinkage, InitFunc,
2455 Twine(InitFunc->getName(),
"$initializer$"));
2456 InitFuncPtr->setSection(
".CRT$XDU");
2463 std::vector<llvm::Function *> NonComdatInits;
2464 for (
size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) {
2467 llvm::Function *F = CXXThreadLocalInits[I];
2470 if (llvm::Comdat *
C = GV->getComdat())
2471 AddToXDU(F)->setComdat(
C);
2473 NonComdatInits.push_back(F);
2476 if (!NonComdatInits.empty()) {
2477 llvm::FunctionType *FTy =
2478 llvm::FunctionType::get(CGM.
VoidTy,
false);
2481 SourceLocation(),
true);
2482 CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, NonComdatInits);
2494 llvm::Constant *TlsGuardConstant =
2498 TlsGuard->setThreadLocal(
true);
2506 llvm::FunctionType *FTy =
2507 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()), {},
2510 FTy,
"__dyn_tls_on_demand_init",
2512 llvm::AttributeList::FunctionIndex,
2513 llvm::Attribute::NoUnwind),
2518 llvm::BasicBlock *DynInitBB,
2519 llvm::BasicBlock *ContinueBB) {
2520 llvm::LoadInst *TlsGuardValue =
2522 llvm::Value *CmpResult =
2524 CGF.
Builder.CreateCondBr(CmpResult, DynInitBB, ContinueBB);
2528 llvm::GlobalValue *TlsGuard,
2529 llvm::BasicBlock *ContinueBB) {
2531 llvm::Function *InitializerFunction =
2533 llvm::CallInst *CallVal = CGF.
Builder.CreateCall(InitializerFunction);
2534 CallVal->setCallingConv(InitializerFunction->getCallingConv());
2536 CGF.
Builder.CreateBr(ContinueBB);
2540 llvm::BasicBlock *DynInitBB =
2542 llvm::BasicBlock *ContinueBB =
2548 CGF.
Builder.SetInsertPoint(DynInitBB);
2550 CGF.
Builder.SetInsertPoint(ContinueBB);
2553LValue MicrosoftCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
2555 QualType LValType) {
2569 Address
Addr(
V, RealVarTy, Alignment);
2573 AlignmentSource::Decl)
2579 StringRef VarName(
"_Init_thread_epoch");
2581 if (
auto *GV = CGM.
getModule().getNamedGlobal(VarName))
2583 auto *GV =
new llvm::GlobalVariable(
2585 false, llvm::GlobalVariable::ExternalLinkage,
2587 nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel);
2593 llvm::FunctionType *FTy =
2594 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2597 FTy,
"_Init_thread_header",
2599 llvm::AttributeList::FunctionIndex,
2600 llvm::Attribute::NoUnwind),
2605 llvm::FunctionType *FTy =
2606 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2609 FTy,
"_Init_thread_footer",
2611 llvm::AttributeList::FunctionIndex,
2612 llvm::Attribute::NoUnwind),
2617 llvm::FunctionType *FTy =
2618 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2621 FTy,
"_Init_thread_abort",
2623 llvm::AttributeList::FunctionIndex,
2624 llvm::Attribute::NoUnwind),
2629struct ResetGuardBit final : EHScopeStack::Cleanup {
2632 ResetGuardBit(Address Guard,
unsigned GuardNum)
2633 : Guard(Guard), GuardNum(GuardNum) {}
2635 void Emit(CodeGenFunction &CGF, Flags flags)
override {
2638 CGBuilderTy &Builder = CGF.
Builder;
2639 llvm::LoadInst *LI = Builder.CreateLoad(Guard);
2640 llvm::ConstantInt *Mask =
2641 llvm::ConstantInt::get(CGF.
IntTy, ~(1ULL << GuardNum));
2642 Builder.CreateStore(Builder.CreateAnd(LI, Mask), Guard);
2646struct CallInitThreadAbort final : EHScopeStack::Cleanup {
2648 CallInitThreadAbort(RawAddress Guard) : Guard(Guard.getPointer()) {}
2650 void Emit(CodeGenFunction &CGF, Flags flags)
override {
2657void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
const VarDecl &D,
2658 llvm::GlobalVariable *GV,
2662 assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage());
2664 llvm::Function *F = CGF.
CurFn;
2665 F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
2666 F->setComdat(CGM.
getModule().getOrInsertComdat(F->getName()));
2672 bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics;
2676 bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic;
2678 CGBuilderTy &Builder = CGF.
Builder;
2679 llvm::IntegerType *GuardTy = CGF.
Int32Ty;
2680 llvm::ConstantInt *
Zero = llvm::ConstantInt::get(GuardTy, 0);
2684 GuardInfo *GI =
nullptr;
2685 if (ThreadlocalStatic)
2687 else if (!ThreadsafeStatic)
2690 llvm::GlobalVariable *GuardVar = GI ? GI->Guard :
nullptr;
2695 GuardNum = getContext().getStaticLocalNumber(&D);
2696 assert(GuardNum > 0);
2698 }
else if (HasPerVariableGuard) {
2702 GuardNum = GI->BitIndex++;
2705 if (!HasPerVariableGuard && GuardNum >= 32) {
2707 ErrorUnsupportedABI(CGF,
"more than 32 guarded initializations");
2714 SmallString<256> GuardName;
2716 llvm::raw_svector_ostream
Out(GuardName);
2717 if (HasPerVariableGuard)
2718 getMangleContext().mangleThreadSafeStaticGuardVariable(&D, GuardNum,
2721 getMangleContext().mangleStaticGuardVariable(&D, Out);
2727 new llvm::GlobalVariable(CGM.
getModule(), GuardTy,
false,
2728 GV->getLinkage(),
Zero, GuardName.str());
2729 GuardVar->setVisibility(GV->getVisibility());
2730 GuardVar->setDLLStorageClass(GV->getDLLStorageClass());
2731 GuardVar->setAlignment(GuardAlign.
getAsAlign());
2732 if (GuardVar->isWeakForLinker())
2733 GuardVar->setComdat(
2734 CGM.
getModule().getOrInsertComdat(GuardVar->getName()));
2737 if (GI && !HasPerVariableGuard)
2738 GI->Guard = GuardVar;
2741 ConstantAddress GuardAddr(GuardVar, GuardTy, GuardAlign);
2743 assert(GuardVar->getLinkage() == GV->getLinkage() &&
2744 "static local from the same function had different linkage");
2746 if (!HasPerVariableGuard) {
2754 llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum);
2755 llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr);
2756 llvm::Value *NeedsInit =
2757 Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit),
Zero);
2761 CodeGenFunction::GuardKind::VariableGuard, &D);
2766 Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardAddr);
2770 Builder.CreateBr(EndBlock);
2788 llvm::LoadInst *FirstGuardLoad = Builder.CreateLoad(GuardAddr);
2789 FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2790 llvm::LoadInst *InitThreadEpoch =
2792 llvm::Value *IsUninitialized =
2793 Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch);
2797 CodeGenFunction::GuardKind::VariableGuard, &D);
2803 GuardAddr.getPointer());
2804 llvm::LoadInst *SecondGuardLoad = Builder.CreateLoad(GuardAddr);
2805 SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2806 llvm::Value *ShouldDoInit =
2807 Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt());
2809 Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock);
2817 GuardAddr.getPointer());
2818 Builder.CreateBr(EndBlock);
2824bool MicrosoftCXXABI::isZeroInitializable(
const MemberPointerType *MPT) {
2840MicrosoftCXXABI::ConvertMemberPointerType(
const MemberPointerType *MPT) {
2843 llvm::SmallVector<llvm::Type *, 4> fields;
2847 fields.push_back(CGM.
IntTy);
2851 fields.push_back(CGM.
IntTy);
2853 fields.push_back(CGM.
IntTy);
2855 fields.push_back(CGM.
IntTy);
2857 if (fields.size() == 1)
2862void MicrosoftCXXABI::
2863GetNullMemberPointerFields(
const MemberPointerType *MPT,
2864 llvm::SmallVectorImpl<llvm::Constant *> &fields) {
2865 assert(fields.empty());
2870 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
2873 fields.push_back(getZeroInt());
2875 fields.push_back(getAllOnesInt());
2880 fields.push_back(getZeroInt());
2882 fields.push_back(getZeroInt());
2884 fields.push_back(getAllOnesInt());
2888MicrosoftCXXABI::EmitNullMemberPointer(
const MemberPointerType *MPT) {
2889 llvm::SmallVector<llvm::Constant *, 4> fields;
2890 GetNullMemberPointerFields(MPT, fields);
2891 if (fields.size() == 1)
2893 llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields);
2894 assert(Res->getType() == ConvertMemberPointerType(MPT));
2899MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
2900 bool IsMemberFunction,
2901 const CXXRecordDecl *RD,
2902 CharUnits NonVirtualBaseAdjustment,
2903 unsigned VBTableIndex) {
2911 llvm::SmallVector<llvm::Constant *, 4> fields;
2912 fields.push_back(FirstField);
2915 fields.push_back(llvm::ConstantInt::get(
2921 Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
2927 fields.push_back(llvm::ConstantInt::get(CGM.
IntTy, VBTableIndex));
2929 return llvm::ConstantStruct::getAnon(fields);
2933MicrosoftCXXABI::EmitMemberDataPointer(
const MemberPointerType *MPT,
2938llvm::Constant *MicrosoftCXXABI::EmitMemberDataPointer(
const CXXRecordDecl *RD,
2941 MSInheritanceModel::Virtual)
2942 offset -= getContext().getOffsetOfBaseWithVBPtr(RD);
2943 llvm::Constant *FirstField =
2945 return EmitFullMemberPointer(FirstField,
false, RD,
2949llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(
const APValue &MP,
2951 const MemberPointerType *DstTy = MPType->
castAs<MemberPointerType>();
2954 return EmitNullMemberPointer(DstTy);
2956 ASTContext &Ctx = getContext();
2960 if (
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
2961 C = EmitMemberFunctionPointer(MD);
2968 const FieldDecl *FD = dyn_cast<FieldDecl>(MPD);
2973 C = EmitMemberDataPointer(RD, FieldOffset);
2976 if (!MemberPointerPath.empty()) {
2978 const MemberPointerType *SrcTy =
2980 std::nullopt, SrcRD)
2981 ->
castAs<MemberPointerType>();
2984 SmallVector<const CXXBaseSpecifier *, 4> DerivedToBasePath;
2985 const CXXRecordDecl *PrevRD = SrcRD;
2986 for (
const CXXRecordDecl *PathElem : MemberPointerPath) {
2987 const CXXRecordDecl *
Base =
nullptr;
2988 const CXXRecordDecl *Derived =
nullptr;
2989 if (DerivedMember) {
2996 for (
const CXXBaseSpecifier &BS : Derived->
bases())
2997 if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() ==
2998 Base->getCanonicalDecl())
2999 DerivedToBasePath.push_back(&BS);
3002 assert(DerivedToBasePath.size() == MemberPointerPath.size());
3004 CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer
3005 : CK_BaseToDerivedMemberPointer;
3006 C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(),
3007 DerivedToBasePath.end(),
C);
3013MicrosoftCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
3014 assert(MD->
isInstance() &&
"Member function must not be static!");
3018 CodeGenTypes &Types = CGM.
getTypes();
3020 unsigned VBTableIndex = 0;
3021 llvm::Constant *FirstField;
3022 const FunctionProtoType *FPT = MD->
getType()->
castAs<FunctionProtoType>();
3037 MethodVFTableLocation ML = VTableContext.getMethodVFTableLocation(MD);
3038 FirstField = EmitVirtualMemPtrThunk(MD, ML);
3042 VBTableIndex = VTableContext.getVBTableIndex(RD, ML.
VBase) * 4;
3045 if (VBTableIndex == 0 &&
3047 MSInheritanceModel::Virtual)
3048 NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD);
3051 return EmitFullMemberPointer(FirstField,
true, RD,
3052 NonVirtualBaseAdjustment, VBTableIndex);
3059MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
3062 const MemberPointerType *MPT,
3064 CGBuilderTy &Builder = CGF.
Builder;
3067 llvm::ICmpInst::Predicate Eq;
3068 llvm::Instruction::BinaryOps
And,
Or;
3070 Eq = llvm::ICmpInst::ICMP_NE;
3071 And = llvm::Instruction::Or;
3072 Or = llvm::Instruction::And;
3074 Eq = llvm::ICmpInst::ICMP_EQ;
3075 And = llvm::Instruction::And;
3076 Or = llvm::Instruction::Or;
3085 return Builder.CreateICmp(Eq, L, R);
3088 llvm::Value *L0 = Builder.CreateExtractValue(L, 0,
"lhs.0");
3089 llvm::Value *R0 = Builder.CreateExtractValue(R, 0,
"rhs.0");
3090 llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0,
"memptr.cmp.first");
3093 llvm::Value *Res =
nullptr;
3095 for (
unsigned I = 1, E = LType->getNumElements(); I != E; ++I) {
3096 llvm::Value *LF = Builder.CreateExtractValue(L, I);
3097 llvm::Value *RF = Builder.CreateExtractValue(R, I);
3098 llvm::Value *Cmp = Builder.CreateICmp(Eq, LF, RF,
"memptr.cmp.rest");
3100 Res = Builder.CreateBinOp(
And, Res, Cmp);
3108 llvm::Value *
Zero = llvm::Constant::getNullValue(L0->getType());
3109 llvm::Value *IsZero = Builder.CreateICmp(Eq, L0,
Zero,
"memptr.cmp.iszero");
3110 Res = Builder.CreateBinOp(
Or, Res, IsZero);
3115 return Builder.CreateBinOp(
And, Res, Cmp0,
"memptr.cmp");
3119MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
3120 llvm::Value *MemPtr,
3121 const MemberPointerType *MPT) {
3122 CGBuilderTy &Builder = CGF.
Builder;
3123 llvm::SmallVector<llvm::Constant *, 4> fields;
3126 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
3128 GetNullMemberPointerFields(MPT, fields);
3129 assert(!fields.empty());
3130 llvm::Value *FirstField = MemPtr;
3131 if (MemPtr->getType()->isStructTy())
3132 FirstField = Builder.CreateExtractValue(MemPtr, 0);
3133 llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0],
"memptr.cmp0");
3141 for (
int I = 1, E = fields.size(); I < E; ++I) {
3142 llvm::Value *
Field = Builder.CreateExtractValue(MemPtr, I);
3143 llvm::Value *
Next = Builder.CreateICmpNE(Field, fields[I],
"memptr.cmp");
3144 Res = Builder.CreateOr(Res,
Next,
"memptr.tobool");
3149bool MicrosoftCXXABI::MemberPointerConstantIsNull(
const MemberPointerType *MPT,
3150 llvm::Constant *Val) {
3153 llvm::Constant *FirstField = Val->getType()->isStructTy() ?
3154 Val->getAggregateElement(0U) : Val;
3155 return FirstField->isNullValue();
3160 if (isZeroInitializable(MPT) && Val->isNullValue())
3165 llvm::SmallVector<llvm::Constant *, 4> Fields;
3166 GetNullMemberPointerFields(MPT, Fields);
3167 if (Fields.size() == 1) {
3168 assert(Val->getType()->isIntegerTy());
3169 return Val == Fields[0];
3173 for (I = 0, E = Fields.size(); I != E; ++I) {
3174 if (Val->getAggregateElement(I) != Fields[I])
3181MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
3183 llvm::Value *VBPtrOffset,
3184 llvm::Value *VBTableOffset,
3185 llvm::Value **VBPtrOut) {
3186 CGBuilderTy &Builder = CGF.
Builder;
3188 llvm::Value *VBPtr = Builder.CreateInBoundsGEP(
3189 CGM.
Int8Ty,
This.emitRawPointer(CGF), VBPtrOffset,
"vbptr");
3193 CharUnits VBPtrAlign;
3194 if (
auto CI = dyn_cast<llvm::ConstantInt>(VBPtrOffset)) {
3195 VBPtrAlign =
This.getAlignment().alignmentAtOffset(
3201 llvm::Value *VBTable =
3202 Builder.CreateAlignedLoad(CGM.
DefaultPtrTy, VBPtr, VBPtrAlign,
"vbtable");
3205 llvm::Value *VBTableIndex = Builder.CreateAShr(
3206 VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2),
3210 llvm::Value *VBaseOffs =
3211 Builder.CreateInBoundsGEP(CGM.
Int32Ty, VBTable, VBTableIndex);
3212 return Builder.CreateAlignedLoad(CGM.
Int32Ty, VBaseOffs,
3218llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(
3219 CodeGenFunction &CGF,
const Expr *E,
const CXXRecordDecl *RD,
3220 Address Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {
3221 CGBuilderTy &Builder = CGF.
Builder;
3223 llvm::BasicBlock *OriginalBB =
nullptr;
3224 llvm::BasicBlock *SkipAdjustBB =
nullptr;
3225 llvm::BasicBlock *VBaseAdjustBB =
nullptr;
3232 OriginalBB = Builder.GetInsertBlock();
3235 llvm::Value *IsVirtual =
3236 Builder.CreateICmpNE(VBTableOffset, getZeroInt(),
3238 Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB);
3250 "member pointer representation requires a "
3251 "complete class type for %0 to perform this expression");
3254 offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
3257 llvm::Value *VBPtr =
nullptr;
3258 llvm::Value *VBaseOffs =
3259 GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr);
3260 llvm::Value *AdjustedBase =
3261 Builder.CreateInBoundsGEP(CGM.
Int8Ty, VBPtr, VBaseOffs);
3264 if (VBaseAdjustBB) {
3265 Builder.CreateBr(SkipAdjustBB);
3267 llvm::PHINode *Phi = Builder.CreatePHI(CGM.
Int8PtrTy, 2,
"memptr.base");
3268 Phi->addIncoming(
Base.emitRawPointer(CGF), OriginalBB);
3269 Phi->addIncoming(AdjustedBase, VBaseAdjustBB);
3272 return AdjustedBase;
3275llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
3276 CodeGenFunction &CGF,
const Expr *E, Address Base, llvm::Value *MemPtr,
3277 const MemberPointerType *MPT,
bool IsInBounds) {
3279 CGBuilderTy &Builder = CGF.
Builder;
3285 llvm::Value *FieldOffset = MemPtr;
3286 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3287 llvm::Value *VBPtrOffset =
nullptr;
3288 if (MemPtr->getType()->isStructTy()) {
3291 FieldOffset = Builder.CreateExtractValue(MemPtr, I++);
3293 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3295 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3299 if (VirtualBaseAdjustmentOffset) {
3300 Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset,
3307 return Builder.CreateGEP(CGF.
Int8Ty,
Addr, FieldOffset,
"memptr.offset",
3308 IsInBounds ? llvm::GEPNoWrapFlags::inBounds()
3309 : llvm::GEPNoWrapFlags::none());
3313MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
3316 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
3317 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
3326 const MemberPointerType *SrcTy =
3328 const MemberPointerType *DstTy = E->
getType()->
castAs<MemberPointerType>();
3332 bool IsReinterpret = E->
getCastKind() == CK_ReinterpretMemberPointer;
3333 if (IsReinterpret && IsFunc)
3337 CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl();
3338 if (IsReinterpret &&
3342 CGBuilderTy &Builder = CGF.
Builder;
3345 llvm::Value *
IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy);
3346 llvm::Constant *DstNull = EmitNullMemberPointer(DstTy);
3350 if (IsReinterpret) {
3353 assert(Src->getType() == DstNull->getType());
3354 return Builder.CreateSelect(
IsNotNull, Src, DstNull);
3357 llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock();
3360 Builder.CreateCondBr(
IsNotNull, ConvertBB, ContinueBB);
3363 llvm::Value *Dst = EmitNonNullMemberPointerConversion(
3367 Builder.CreateBr(ContinueBB);
3371 llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2,
"memptr.converted");
3372 Phi->addIncoming(DstNull, OriginalBB);
3373 Phi->addIncoming(Dst, ConvertBB);
3377llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion(
3378 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
CastKind CK,
3381 CGBuilderTy &Builder) {
3390 llvm::Value *FirstField = Src;
3391 llvm::Value *NonVirtualBaseAdjustment = getZeroInt();
3392 llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt();
3393 llvm::Value *VBPtrOffset = getZeroInt();
3397 FirstField = Builder.CreateExtractValue(Src, I++);
3399 NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++);
3401 VBPtrOffset = Builder.CreateExtractValue(Src, I++);
3403 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++);
3406 bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer);
3407 const MemberPointerType *DerivedTy = IsDerivedToBase ? SrcTy : DstTy;
3412 llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;
3419 llvm::Value *SrcVBIndexEqZero =
3420 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3421 if (SrcInheritance == MSInheritanceModel::Virtual) {
3422 if (int64_t SrcOffsetToFirstVBase =
3423 getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) {
3424 llvm::Value *UndoSrcAdjustment = Builder.CreateSelect(
3426 llvm::ConstantInt::get(CGM.
IntTy, SrcOffsetToFirstVBase),
3428 NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment);
3439 llvm::Constant *BaseClassOffset = llvm::ConstantInt::get(
3444 llvm::Value *NVDisp;
3445 if (IsDerivedToBase)
3446 NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset,
"adj");
3448 NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset,
"adj");
3450 NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt());
3454 llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero;
3457 if (llvm::GlobalVariable *VDispMap =
3458 getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) {
3459 llvm::Value *VBIndex = Builder.CreateExactUDiv(
3460 VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.
IntTy, 4));
3462 llvm::Constant *Mapping = VDispMap->getInitializer();
3463 VirtualBaseAdjustmentOffset =
3466 llvm::Value *Idxs[] = {getZeroInt(), VBIndex};
3467 VirtualBaseAdjustmentOffset = Builder.CreateAlignedLoad(
3468 CGM.
IntTy, Builder.CreateInBoundsGEP(VDispMap->getValueType(),
3474 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3481 llvm::Value *DstVBPtrOffset = llvm::ConstantInt::get(
3483 getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity());
3485 Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset);
3491 if (DstInheritance == MSInheritanceModel::Virtual) {
3492 if (int64_t DstOffsetToFirstVBase =
3493 getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) {
3494 llvm::Value *DoDstAdjustment = Builder.CreateSelect(
3496 llvm::ConstantInt::get(CGM.
IntTy, DstOffsetToFirstVBase),
3498 NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment);
3507 Dst = llvm::PoisonValue::get(ConvertMemberPointerType(DstTy));
3509 Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
3511 Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++);
3513 Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++);
3515 Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++);
3521MicrosoftCXXABI::EmitMemberPointerConversion(
const CastExpr *E,
3522 llvm::Constant *Src) {
3523 const MemberPointerType *SrcTy =
3525 const MemberPointerType *DstTy = E->
getType()->
castAs<MemberPointerType>();
3529 return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->
path_begin(),
3533llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
3534 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
CastKind CK,
3537 assert(CK == CK_DerivedToBaseMemberPointer ||
3538 CK == CK_BaseToDerivedMemberPointer ||
3539 CK == CK_ReinterpretMemberPointer);
3542 if (MemberPointerConstantIsNull(SrcTy, Src))
3543 return EmitNullMemberPointer(DstTy);
3548 if (CK == CK_ReinterpretMemberPointer)
3553 SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder));
3558CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
3559 CodeGenFunction &CGF,
const Expr *E, Address This,
3560 llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
3561 const MemberPointerType *MPT) {
3563 const FunctionProtoType *FPT =
3566 CGBuilderTy &Builder = CGF.
Builder;
3572 llvm::Value *FunctionPointer = MemPtr;
3573 llvm::Value *NonVirtualBaseAdjustment =
nullptr;
3574 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3575 llvm::Value *VBPtrOffset =
nullptr;
3576 if (MemPtr->getType()->isStructTy()) {
3579 FunctionPointer = Builder.CreateExtractValue(MemPtr, I++);
3581 NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++);
3583 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3585 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3588 if (VirtualBaseAdjustmentOffset) {
3589 ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This,
3590 VirtualBaseAdjustmentOffset, VBPtrOffset);
3592 ThisPtrForCall =
This.emitRawPointer(CGF);
3595 if (NonVirtualBaseAdjustment)
3596 ThisPtrForCall = Builder.CreateInBoundsGEP(CGF.
Int8Ty, ThisPtrForCall,
3597 NonVirtualBaseAdjustment);
3599 CGCallee
Callee(FPT, FunctionPointer);
3604 return new MicrosoftCXXABI(CGM);
3638 StringRef MangledName(
"??_7type_info@@6B@");
3639 if (
auto VTable = CGM.
getModule().getNamedGlobal(MangledName))
3643 llvm::GlobalVariable::ExternalLinkage,
3644 nullptr, MangledName);
3657 IsPrivateOnPath = 1 | 8,
3661 HasHierarchyDescriptor = 64
3663 MSRTTIClass(
const CXXRecordDecl *RD) : RD(RD) {}
3665 const CXXBaseSpecifier *Specifier);
3667 MSRTTIClass *getFirstChild() {
return this + 1; }
3668 static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
3669 return Child + 1 + Child->NumBases;
3672 const CXXRecordDecl *RD, *VirtualRoot;
3673 uint32_t Flags, NumBases, OffsetInVBase;
3677uint32_t MSRTTIClass::initialize(
const MSRTTIClass *Parent,
3678 const CXXBaseSpecifier *Specifier) {
3679 Flags = HasHierarchyDescriptor;
3681 VirtualRoot =
nullptr;
3685 Flags |= IsPrivate | IsPrivateOnPath;
3691 if (Parent->Flags & IsPrivateOnPath)
3692 Flags |= IsPrivateOnPath;
3693 VirtualRoot = Parent->VirtualRoot;
3694 OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext()
3695 .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity();
3699 MSRTTIClass *Child = getFirstChild();
3700 for (
const CXXBaseSpecifier &Base : RD->bases()) {
3701 NumBases += Child->initialize(
this, &Base) + 1;
3702 Child = getNextChild(Child);
3707static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) {
3709 case Linkage::Invalid:
3710 llvm_unreachable(
"Linkage hasn't been computed!");
3713 case Linkage::Internal:
3714 case Linkage::UniqueExternal:
3715 return llvm::GlobalValue::InternalLinkage;
3717 case Linkage::VisibleNone:
3718 case Linkage::Module:
3719 case Linkage::External:
3720 return llvm::GlobalValue::LinkOnceODRLinkage;
3722 llvm_unreachable(
"Invalid linkage!");
3728struct MSRTTIBuilder {
3730 HasBranchingHierarchy = 1,
3731 HasVirtualBranchingHierarchy = 2,
3732 HasAmbiguousBases = 4
3735 MSRTTIBuilder(MicrosoftCXXABI &ABI,
const CXXRecordDecl *RD)
3736 : CGM(ABI.CGM), Context(CGM.getContext()),
3737 VMContext(CGM.getLLVMContext()),
Module(CGM.getModule()), RD(RD),
3738 Linkage(getLinkageForRTTI(CGM.getContext().getCanonicalTagType(RD))),
3741 llvm::GlobalVariable *getBaseClassDescriptor(
const MSRTTIClass &Classes);
3742 llvm::GlobalVariable *
3743 getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes);
3744 llvm::GlobalVariable *getClassHierarchyDescriptor();
3745 llvm::GlobalVariable *getCompleteObjectLocator(
const VPtrInfo &Info);
3748 ASTContext &Context;
3749 llvm::LLVMContext &VMContext;
3751 const CXXRecordDecl *RD;
3752 llvm::GlobalVariable::LinkageTypes
Linkage;
3753 MicrosoftCXXABI &ABI;
3762 Classes.push_back(MSRTTIClass(RD));
3773 for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
3774 if ((Class->Flags & MSRTTIClass::IsVirtual) &&
3775 !VirtualBases.insert(Class->RD).second) {
3776 Class = MSRTTIClass::getNextChild(Class);
3779 if (!UniqueBases.insert(Class->RD).second)
3780 AmbiguousBases.insert(Class->RD);
3783 if (AmbiguousBases.empty())
3785 for (MSRTTIClass &Class : Classes)
3786 if (AmbiguousBases.count(Class.RD))
3787 Class.Flags |= MSRTTIClass::IsAmbiguous;
3790llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
3791 SmallString<256> MangledName;
3793 llvm::raw_svector_ostream
Out(MangledName);
3794 ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
3798 if (
auto CHD =
Module.getNamedGlobal(MangledName))
3802 SmallVector<MSRTTIClass, 8> Classes;
3804 Classes.front().initialize(
nullptr,
nullptr);
3807 for (
const MSRTTIClass &
Class : Classes) {
3808 if (
Class.RD->getNumBases() > 1)
3809 Flags |= HasBranchingHierarchy;
3812 if (
Class.Flags & MSRTTIClass::IsAmbiguous)
3813 Flags |= HasAmbiguousBases;
3815 if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)
3816 Flags |= HasVirtualBranchingHierarchy;
3819 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.
IntTy, 0),
3820 llvm::ConstantInt::get(CGM.
IntTy, 0)};
3823 auto Type = ABI.getClassHierarchyDescriptorType();
3827 if (CHD->isWeakForLinker())
3828 CHD->setComdat(CGM.
getModule().getOrInsertComdat(CHD->getName()));
3830 auto *Bases = getBaseClassArray(Classes);
3833 llvm::Constant *Fields[] = {
3834 llvm::ConstantInt::get(CGM.
IntTy, 0),
3835 llvm::ConstantInt::get(CGM.
IntTy, Flags),
3836 llvm::ConstantInt::get(CGM.
IntTy, Classes.size()),
3837 ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(
3838 Bases->getValueType(), Bases,
3839 llvm::ArrayRef<llvm::Value *>(GEPIndices))),
3841 CHD->setInitializer(llvm::ConstantStruct::get(
Type, Fields));
3845llvm::GlobalVariable *
3846MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
3847 SmallString<256> MangledName;
3849 llvm::raw_svector_ostream
Out(MangledName);
3850 ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out);
3858 llvm::Type *PtrType = ABI.getImageRelativeType(CGM.
DefaultPtrTy);
3859 auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
3861 new llvm::GlobalVariable(
Module, ArrType,
3863 nullptr, MangledName);
3864 if (BCA->isWeakForLinker())
3865 BCA->setComdat(CGM.
getModule().getOrInsertComdat(BCA->getName()));
3868 SmallVector<llvm::Constant *, 8> BaseClassArrayData;
3869 for (MSRTTIClass &
Class : Classes)
3870 BaseClassArrayData.push_back(
3871 ABI.getImageRelativeConstant(getBaseClassDescriptor(
Class)));
3872 BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType));
3873 BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData));
3877llvm::GlobalVariable *
3878MSRTTIBuilder::getBaseClassDescriptor(
const MSRTTIClass &
Class) {
3883 if (
Class.VirtualRoot) {
3885 OffsetInVBTable = VTableContext.getVBTableIndex(RD,
Class.VirtualRoot) * 4;
3889 SmallString<256> MangledName;
3891 llvm::raw_svector_ostream
Out(MangledName);
3892 ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor(
3893 Class.RD,
Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable,
3898 if (
auto BCD =
Module.getNamedGlobal(MangledName))
3902 auto Type = ABI.getBaseClassDescriptorType();
3905 nullptr, MangledName);
3906 if (BCD->isWeakForLinker())
3907 BCD->setComdat(CGM.
getModule().getOrInsertComdat(BCD->getName()));
3910 llvm::Constant *Fields[] = {
3911 ABI.getImageRelativeConstant(
3913 llvm::ConstantInt::get(CGM.
IntTy,
Class.NumBases),
3914 llvm::ConstantInt::get(CGM.
IntTy,
Class.OffsetInVBase),
3915 llvm::ConstantInt::get(CGM.
IntTy, VBPtrOffset),
3916 llvm::ConstantInt::get(CGM.
IntTy, OffsetInVBTable),
3917 llvm::ConstantInt::get(CGM.
IntTy,
Class.Flags),
3918 ABI.getImageRelativeConstant(
3919 MSRTTIBuilder(ABI,
Class.RD).getClassHierarchyDescriptor()),
3921 BCD->setInitializer(llvm::ConstantStruct::get(
Type, Fields));
3925llvm::GlobalVariable *
3926MSRTTIBuilder::getCompleteObjectLocator(
const VPtrInfo &Info) {
3927 SmallString<256> MangledName;
3929 llvm::raw_svector_ostream
Out(MangledName);
3930 ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info.
MangledPath, Out);
3934 if (
auto COL =
Module.getNamedGlobal(MangledName))
3939 int VFPtrOffset = 0;
3945 ->second.hasVtorDisp())
3949 llvm::StructType *
Type = ABI.getCompleteObjectLocatorType();
3951 nullptr, MangledName);
3954 llvm::Constant *Fields[] = {
3955 llvm::ConstantInt::get(CGM.
IntTy, ABI.isImageRelative()),
3956 llvm::ConstantInt::get(CGM.
IntTy, OffsetToTop),
3957 llvm::ConstantInt::get(CGM.
IntTy, VFPtrOffset),
3958 ABI.getImageRelativeConstant(
3960 ABI.getImageRelativeConstant(getClassHierarchyDescriptor()),
3961 ABI.getImageRelativeConstant(COL),
3963 llvm::ArrayRef<llvm::Constant *> FieldsRef(Fields);
3964 if (!ABI.isImageRelative())
3965 FieldsRef = FieldsRef.drop_back();
3966 COL->setInitializer(llvm::ConstantStruct::get(
Type, FieldsRef));
3967 if (COL->isWeakForLinker())
3968 COL->setComdat(CGM.
getModule().getOrInsertComdat(COL->getName()));
3973 bool &IsConst,
bool &IsVolatile,
3974 bool &IsUnaligned) {
3975 T = Context.getExceptionObjectType(
T);
3984 IsUnaligned =
false;
3985 QualType PointeeType =
T->getPointeeType();
3986 if (!PointeeType.
isNull()) {
3996 MPTy->getQualifier(),
3997 MPTy->getMostRecentCXXRecordDecl());
4001 if (
T->isPointerType())
4008MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType
Type,
4009 QualType CatchHandlerType) {
4013 bool IsConst, IsVolatile, IsUnaligned;
4029 return CatchTypeInfo{getAddrOfRTTIDescriptor(
Type)->stripPointerCasts(),
4037llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType
Type) {
4038 SmallString<256> MangledName;
4040 llvm::raw_svector_ostream
Out(MangledName);
4041 getMangleContext().mangleCXXRTTI(
Type, Out);
4045 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4052 SmallString<256> TypeInfoString;
4054 llvm::raw_svector_ostream
Out(TypeInfoString);
4055 getMangleContext().mangleCXXRTTIName(
Type, Out);
4059 llvm::Constant *Fields[] = {
4061 llvm::ConstantPointerNull::get(CGM.
Int8PtrTy),
4062 llvm::ConstantDataArray::getString(CGM.
getLLVMContext(), TypeInfoString)};
4063 llvm::StructType *TypeDescriptorType =
4064 getTypeDescriptorType(TypeInfoString);
4065 auto *Var =
new llvm::GlobalVariable(
4066 CGM.
getModule(), TypeDescriptorType,
false,
4067 getLinkageForRTTI(
Type),
4068 llvm::ConstantStruct::get(TypeDescriptorType, Fields),
4070 if (Var->isWeakForLinker())
4071 Var->setComdat(CGM.
getModule().getOrInsertComdat(Var->getName()));
4076llvm::GlobalVariable *
4077MicrosoftCXXABI::getMSCompleteObjectLocator(
const CXXRecordDecl *RD,
4078 const VPtrInfo &Info) {
4079 return MSRTTIBuilder(*
this, RD).getCompleteObjectLocator(Info);
4082void MicrosoftCXXABI::emitCXXStructor(GlobalDecl GD) {
4083 if (
auto *ctor = dyn_cast<CXXConstructorDecl>(GD.
getDecl())) {
4085 llvm::Function *
Fn =
4097 dtor->getParent()->getNumVBases() == 0)
4108 !getContext().classNeedsVectorDeletingDestructor(dtor->getParent())) {
4120 if (
Fn->isWeakForLinker())
4121 Fn->setComdat(CGM.
getModule().getOrInsertComdat(
Fn->getName()));
4125MicrosoftCXXABI::getAddrOfCXXCtorClosure(
const CXXConstructorDecl *CD,
4130 SmallString<256> ThunkName;
4131 llvm::raw_svector_ostream
Out(ThunkName);
4132 getMangleContext().mangleName(GlobalDecl(CD, CT), Out);
4135 if (llvm::GlobalValue *GV = CGM.
getModule().getNamedValue(ThunkName))
4141 const CXXRecordDecl *RD = CD->
getParent();
4142 CanQualType RecordTy = getContext().getCanonicalTagType(RD);
4143 llvm::Function *ThunkFn = llvm::Function::Create(
4144 ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.
getModule());
4145 ThunkFn->setCallingConv(
static_cast<llvm::CallingConv::ID
>(
4147 if (ThunkFn->isWeakForLinker())
4148 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
4152 CodeGenFunction CGF(CGM);
4156 FunctionArgList FunctionArgs;
4159 buildThisParam(CGF, FunctionArgs);
4163 ImplicitParamDecl SrcParam(
4164 getContext(),
nullptr, SourceLocation(),
4165 &getContext().Idents.get(
"src"),
4166 getContext().getLValueReferenceType(RecordTy,
4168 ImplicitParamKind::Other);
4170 FunctionArgs.push_back(&SrcParam);
4175 ImplicitParamDecl IsMostDerived(getContext(),
nullptr,
4177 &getContext().Idents.get(
"is_most_derived"),
4178 getContext().IntTy, ImplicitParamKind::Other);
4181 FunctionArgs.push_back(&IsMostDerived);
4186 FunctionArgs, CD->
getLocation(), SourceLocation());
4189 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
4190 llvm::Value *
This = getThisValue(CGF);
4192 llvm::Value *SrcVal =
4206 SmallVector<const Stmt *, 4> ArgVec;
4207 ArrayRef<ParmVarDecl *> params = CD->
parameters().drop_front(IsCopy ? 1 : 0);
4208 for (
const ParmVarDecl *PD : params) {
4209 assert(PD->hasDefaultArg() &&
"ctor closure lacks default args");
4210 ArgVec.push_back(PD->getDefaultArg());
4213 CodeGenFunction::RunCleanupsScope Cleanups(CGF);
4215 const auto *FPT = CD->
getType()->
castAs<FunctionProtoType>();
4216 CGF.
EmitCallArgs(Args, FPT, llvm::ArrayRef(ArgVec), CD, IsCopy ? 1 : 0);
4219 AddedStructorArgCounts ExtraArgs =
4224 llvm::Constant *CalleePtr =
4229 Args, CD,
Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix);
4230 CGF.
EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args);
4232 Cleanups.ForceCleanup();
4241llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType
T,
4243 int32_t VBPtrOffset,
4248 const CXXConstructorDecl *CD =
4255 uint32_t Size = getContext().getTypeSizeInChars(
T).getQuantity();
4256 SmallString<256> MangledName;
4258 llvm::raw_svector_ostream
Out(MangledName);
4259 getMangleContext().mangleCXXCatchableType(
T, CD, CT, Size, NVOffset,
4260 VBPtrOffset, VBIndex, Out);
4262 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4263 return getImageRelativeConstant(GV);
4267 llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(
T));
4271 llvm::Constant *CopyCtor;
4278 CopyCtor = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4280 CopyCtor = getImageRelativeConstant(CopyCtor);
4282 bool IsScalar = !RD;
4283 bool HasVirtualBases =
false;
4284 bool IsStdBadAlloc =
false;
4285 QualType PointeeType =
T;
4299 if (HasVirtualBases)
4304 llvm::Constant *Fields[] = {
4305 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4307 llvm::ConstantInt::get(CGM.
IntTy, NVOffset),
4308 llvm::ConstantInt::get(CGM.
IntTy, VBPtrOffset),
4309 llvm::ConstantInt::get(CGM.
IntTy, VBIndex),
4310 llvm::ConstantInt::get(CGM.
IntTy, Size),
4313 llvm::StructType *CTType = getCatchableTypeType();
4314 auto *GV =
new llvm::GlobalVariable(
4315 CGM.
getModule(), CTType,
true, getLinkageForRTTI(
T),
4316 llvm::ConstantStruct::get(CTType, Fields), MangledName);
4317 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4318 GV->setSection(
".xdata");
4319 if (GV->isWeakForLinker())
4320 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4321 return getImageRelativeConstant(GV);
4324llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType
T) {
4328 llvm::GlobalVariable *&CTA = CatchableTypeArrays[
T];
4335 llvm::SmallSetVector<llvm::Constant *, 2> CatchableTypes;
4345 const CXXRecordDecl *MostDerivedClass =
nullptr;
4353 if (MostDerivedClass) {
4354 const ASTContext &Context = getContext();
4355 const ASTRecordLayout &MostDerivedLayout =
4358 SmallVector<MSRTTIClass, 8> Classes;
4360 Classes.front().initialize(
nullptr,
nullptr);
4362 for (
const MSRTTIClass &
Class : Classes) {
4365 (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous))
4370 if (
Class.VirtualRoot) {
4381 CatchableTypes.insert(getCatchableType(RTTITy,
Class.OffsetInVBase,
4382 VBPtrOffset, OffsetInVBTable));
4390 CatchableTypes.insert(getCatchableType(
T));
4403 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4414 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4416 uint32_t NumEntries = CatchableTypes.size();
4417 llvm::Type *CTType = getImageRelativeType(CGM.
DefaultPtrTy);
4418 llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries);
4419 llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries);
4420 llvm::Constant *Fields[] = {
4421 llvm::ConstantInt::get(CGM.
IntTy, NumEntries),
4422 llvm::ConstantArray::get(
4423 AT, llvm::ArrayRef(CatchableTypes.begin(),
4424 CatchableTypes.end()))
4426 SmallString<256> MangledName;
4428 llvm::raw_svector_ostream
Out(MangledName);
4429 getMangleContext().mangleCXXCatchableTypeArray(
T, NumEntries, Out);
4431 CTA =
new llvm::GlobalVariable(
4432 CGM.
getModule(), CTAType,
true, getLinkageForRTTI(
T),
4433 llvm::ConstantStruct::get(CTAType, Fields), MangledName);
4434 CTA->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4435 CTA->setSection(
".xdata");
4436 if (CTA->isWeakForLinker())
4437 CTA->setComdat(CGM.
getModule().getOrInsertComdat(CTA->getName()));
4441llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(QualType
T) {
4442 bool IsConst, IsVolatile, IsUnaligned;
4447 llvm::GlobalVariable *CTA = getCatchableTypeArray(
T);
4454 ->getLimitedValue();
4456 SmallString<256> MangledName;
4458 llvm::raw_svector_ostream
Out(MangledName);
4459 getMangleContext().mangleCXXThrowInfo(
T, IsConst, IsVolatile, IsUnaligned,
4465 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4481 llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4484 if (!DtorD->isTrivial())
4487 llvm::Constant *ForwardCompat =
4488 getImageRelativeConstant(llvm::Constant::getNullValue(CGM.
Int8PtrTy));
4489 llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant(CTA);
4490 llvm::StructType *TIType = getThrowInfoType();
4491 llvm::Constant *Fields[] = {
4492 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4493 getImageRelativeConstant(CleanupFn),
4495 PointerToCatchableTypes
4497 auto *GV =
new llvm::GlobalVariable(
4498 CGM.
getModule(), TIType,
true, getLinkageForRTTI(
T),
4499 llvm::ConstantStruct::get(TIType, Fields), MangledName.str());
4500 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4501 GV->setSection(
".xdata");
4502 if (GV->isWeakForLinker())
4503 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4507void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF,
const CXXThrowExpr *E) {
4509 assert(SubExpr &&
"SubExpr cannot be null");
4510 QualType ThrowType = SubExpr->
getType();
4519 llvm::GlobalVariable *TI = getThrowInfo(ThrowType);
4526std::pair<llvm::Value *, const CXXRecordDecl *>
4527MicrosoftCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
4528 const CXXRecordDecl *RD) {
4530 std::tie(This, std::ignore, RD) = performBaseAdjustment(CGF, This,
T);
4534bool MicrosoftCXXABI::isPermittedToBeHomogeneousAggregate(
4535 const CXXRecordDecl *RD)
const {
4565 for (
const CXXBaseSpecifier &B : RD->
bases()) {
4566 if (
const CXXRecordDecl *FRD = B.getType()->getAsCXXRecordDecl()) {
4567 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 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
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.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
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.
const FunctionProtoType * T
@ 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...