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 =
638 llvm::ConstantInt::getSigned(CGM.
IntTy, VBPtrOffset);
639 llvm::Value *VBTOffset = llvm::ConstantInt::get(CGM.
IntTy, VBTableOffset);
640 return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
643 std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
644 performBaseAdjustment(CodeGenFunction &CGF, Address
Value,
645 QualType SrcRecordTy);
649 llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF,
const Expr *E,
650 const CXXRecordDecl *RD, Address Base,
651 llvm::Value *VirtualBaseAdjustmentOffset,
652 llvm::Value *VBPtrOffset );
656 llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
657 bool IsMemberFunction,
658 const CXXRecordDecl *RD,
659 CharUnits NonVirtualBaseAdjustment,
660 unsigned VBTableIndex);
662 bool MemberPointerConstantIsNull(
const MemberPointerType *MPT,
666 void EmitVBPtrStores(CodeGenFunction &CGF,
const CXXRecordDecl *RD);
669 const VBTableGlobals &enumerateVBTables(
const CXXRecordDecl *RD);
672 llvm::Function *EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
673 const MethodVFTableLocation &ML);
675 llvm::Constant *EmitMemberDataPointer(
const CXXRecordDecl *RD,
679 llvm::Type *ConvertMemberPointerType(
const MemberPointerType *MPT)
override;
681 bool isZeroInitializable(
const MemberPointerType *MPT)
override;
683 bool isMemberPointerConvertible(
const MemberPointerType *MPT)
const override {
685 return RD->
hasAttr<MSInheritanceAttr>();
688 llvm::Constant *EmitNullMemberPointer(
const MemberPointerType *MPT)
override;
690 llvm::Constant *EmitMemberDataPointer(
const MemberPointerType *MPT,
691 CharUnits offset)
override;
692 llvm::Constant *EmitMemberFunctionPointer(
const CXXMethodDecl *MD)
override;
693 llvm::Constant *EmitMemberPointer(
const APValue &MP, QualType MPT)
override;
695 llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
698 const MemberPointerType *MPT,
699 bool Inequality)
override;
701 llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
703 const MemberPointerType *MPT)
override;
705 llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
const Expr *E,
706 Address Base, llvm::Value *MemPtr,
707 const MemberPointerType *MPT,
708 bool IsInBounds)
override;
710 llvm::Value *EmitNonNullMemberPointerConversion(
711 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
714 CGBuilderTy &Builder);
716 llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
718 llvm::Value *Src)
override;
720 llvm::Constant *EmitMemberPointerConversion(
const CastExpr *E,
721 llvm::Constant *Src)
override;
723 llvm::Constant *EmitMemberPointerConversion(
724 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
729 EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
const Expr *E,
730 Address This, llvm::Value *&ThisPtrForCall,
732 const MemberPointerType *MPT)
override;
734 void emitCXXStructor(GlobalDecl GD)
override;
736 llvm::StructType *getCatchableTypeType() {
737 if (CatchableTypeType)
738 return CatchableTypeType;
739 llvm::Type *FieldTypes[] = {
748 CatchableTypeType = llvm::StructType::create(
750 return CatchableTypeType;
753 llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) {
754 llvm::StructType *&CatchableTypeArrayType =
755 CatchableTypeArrayTypeMap[NumEntries];
756 if (CatchableTypeArrayType)
757 return CatchableTypeArrayType;
759 llvm::SmallString<23> CTATypeName(
"eh.CatchableTypeArray.");
760 CTATypeName += llvm::utostr(NumEntries);
761 llvm::Type *CTType = getImageRelativeType(CGM.
DefaultPtrTy);
762 llvm::Type *FieldTypes[] = {
764 llvm::ArrayType::get(CTType, NumEntries)
766 CatchableTypeArrayType =
767 llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes, CTATypeName);
768 return CatchableTypeArrayType;
771 llvm::StructType *getThrowInfoType() {
773 return ThrowInfoType;
774 llvm::Type *FieldTypes[] = {
780 ThrowInfoType = llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes,
782 return ThrowInfoType;
789 llvm::FunctionType *FTy =
790 llvm::FunctionType::get(CGM.
VoidTy, Args,
false);
791 llvm::FunctionCallee Throw =
795 if (
auto *Fn = dyn_cast<llvm::Function>(Throw.getCallee()))
796 Fn->setCallingConv(llvm::CallingConv::X86_StdCall);
801 llvm::Function *getAddrOfCXXCtorClosure(
const CXXConstructorDecl *CD,
804 llvm::Constant *getCatchableType(QualType
T,
805 uint32_t NVOffset = 0,
806 int32_t VBPtrOffset = -1,
807 uint32_t VBIndex = 0);
809 llvm::GlobalVariable *getCatchableTypeArray(QualType
T);
811 llvm::GlobalVariable *getThrowInfo(QualType
T)
override;
813 std::pair<llvm::Value *, const CXXRecordDecl *>
814 LoadVTablePtr(CodeGenFunction &CGF, Address This,
815 const CXXRecordDecl *RD)
override;
818 isPermittedToBeHomogeneousAggregate(
const CXXRecordDecl *RD)
const override;
821 typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
822 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;
823 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;
825 VFTablesMapTy VFTablesMap;
826 VTablesMapTy VTablesMap;
829 llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
833 llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap;
838 GuardInfo() =
default;
839 llvm::GlobalVariable *Guard =
nullptr;
840 unsigned BitIndex = 0;
845 llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap;
846 llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap;
847 llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap;
849 llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap;
850 llvm::StructType *BaseClassDescriptorType;
851 llvm::StructType *ClassHierarchyDescriptorType;
852 llvm::StructType *CompleteObjectLocatorType;
854 llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays;
856 llvm::StructType *CatchableTypeType;
857 llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;
858 llvm::StructType *ThrowInfoType;
864MicrosoftCXXABI::getRecordArgABI(
const CXXRecordDecl *RD)
const {
876 case llvm::Triple::thumb:
882 case llvm::Triple::x86: {
888 getContext().getTypeInfo(getContext().getCanonicalTagType(RD));
894 return RAA_DirectInMemory;
897 case llvm::Triple::x86_64:
898 case llvm::Triple::aarch64:
902 llvm_unreachable(
"invalid enum");
905void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
906 const CXXDeleteExpr *DE,
908 QualType ElementType,
909 const CXXDestructorDecl *Dtor) {
912 if (!getContext().getTargetInfo().callGlobalDeleteInDeletingDtor(
913 getContext().getLangOpts())) {
916 llvm::Value *MDThis =
917 EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,
927void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF,
bool isNoReturn) {
928 llvm::Value *Args[] = {llvm::ConstantPointerNull::get(CGM.
Int8PtrTy),
937void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
938 const CXXCatchStmt *S) {
942 llvm::BasicBlock *CatchPadBB = CGF.
Builder.GetInsertBlock();
943 llvm::CatchPadInst *CPI =
955 CPI->setArgOperand(2,
var.getObjectAddress(CGF).emitRawPointer(CGF));
963std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
964MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address
Value,
965 QualType SrcRecordTy) {
968 const ASTContext &Context = getContext();
974 return std::make_tuple(
Value, llvm::ConstantInt::get(CGF.
Int32Ty, 0),
979 const CXXRecordDecl *PolymorphicBase =
nullptr;
980 for (
auto &Base : SrcDecl->
vbases()) {
981 const CXXRecordDecl *BaseDecl =
Base.getType()->getAsCXXRecordDecl();
983 PolymorphicBase = BaseDecl;
987 assert(PolymorphicBase &&
"polymorphic class has no apparent vfptr?");
989 llvm::Value *Offset =
990 GetVirtualBaseClassOffset(CGF,
Value, SrcDecl, PolymorphicBase);
992 Value.getElementType(),
Value.emitRawPointer(CGF), Offset);
993 CharUnits VBaseAlign =
995 return std::make_tuple(Address(Ptr, CGF.
Int8Ty, VBaseAlign), Offset,
999bool MicrosoftCXXABI::shouldTypeidBeNullChecked(QualType SrcRecordTy) {
1001 return !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
1005 llvm::Value *Argument) {
1006 llvm::Type *ArgTypes[] = {CGF.
Int8PtrTy};
1007 llvm::FunctionType *FTy =
1008 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false);
1009 llvm::Value *Args[] = {Argument};
1014void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
1015 llvm::CallBase *
Call =
1017 Call->setDoesNotReturn();
1018 CGF.
Builder.CreateUnreachable();
1021llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
1022 QualType SrcRecordTy,
1024 llvm::Type *StdTypeInfoPtrTy) {
1025 std::tie(ThisPtr, std::ignore, std::ignore) =
1026 performBaseAdjustment(CGF, ThisPtr, SrcRecordTy);
1028 return CGF.
Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy);
1031bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
1032 QualType SrcRecordTy) {
1035 !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
1038llvm::Value *MicrosoftCXXABI::emitDynamicCastCall(
1039 CodeGenFunction &CGF, Address This, QualType SrcRecordTy, QualType DestTy,
1040 QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
1041 llvm::Value *SrcRTTI =
1043 llvm::Value *DestRTTI =
1046 llvm::Value *Offset;
1047 std::tie(This, Offset, std::ignore) =
1048 performBaseAdjustment(CGF, This, SrcRecordTy);
1049 llvm::Value *ThisPtr =
This.emitRawPointer(CGF);
1061 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
1063 llvm::Value *Args[] = {
1064 ThisPtr, Offset, SrcRTTI, DestRTTI,
1069llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
1071 QualType SrcRecordTy) {
1072 std::tie(
Value, std::ignore, std::ignore) =
1073 performBaseAdjustment(CGF,
Value, SrcRecordTy);
1077 llvm::Type *ArgTypes[] = {CGF.
Int8PtrTy};
1079 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
1081 llvm::Value *Args[] = {
Value.emitRawPointer(CGF)};
1085bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
1089llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset(
1090 CodeGenFunction &CGF, Address This,
const CXXRecordDecl *ClassDecl,
1091 const CXXRecordDecl *BaseClassDecl) {
1092 const ASTContext &Context = getContext();
1095 llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.
PtrDiffTy, VBPtrChars);
1097 CharUnits VBTableChars =
1100 llvm::Value *VBTableOffset =
1103 llvm::Value *VBPtrToNewBase =
1104 GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset);
1107 return CGF.
Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);
1110bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD)
const {
1120bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD)
const {
1130 uint64_t NumElts = 0;
1170 if (
auto *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
1171 if (Ctor->isUserProvided())
1173 }
else if (
auto *
Template = dyn_cast<FunctionTemplateDecl>(D)) {
1176 }
else if (
auto *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
1177 if (MethodDecl->isCopyAssignmentOperator() && MethodDecl->isDeleted())
1186bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI)
const {
1187 const CXXRecordDecl *RD = FI.
getReturnType()->getAsCXXRecordDecl();
1197 if (isIndirectReturn) {
1218MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
1219 const CXXRecordDecl *RD) {
1220 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1221 assert(IsMostDerivedClass &&
1222 "ctor for a class with virtual bases must have an implicit parameter");
1223 llvm::Value *IsCompleteObject =
1224 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1226 llvm::BasicBlock *CallVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.init_vbases");
1227 llvm::BasicBlock *SkipVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.skip_vbases");
1228 CGF.
Builder.CreateCondBr(IsCompleteObject,
1229 CallVbaseCtorsBB, SkipVbaseCtorsBB);
1234 EmitVBPtrStores(CGF, RD);
1238 return SkipVbaseCtorsBB;
1242MicrosoftCXXABI::EmitDtorCompleteObjectHandler(CodeGenFunction &CGF) {
1243 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1244 assert(IsMostDerivedClass &&
1245 "ctor for a class with virtual bases must have an implicit parameter");
1246 llvm::Value *IsCompleteObject =
1247 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1249 llvm::BasicBlock *CallVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.dtor_vbases");
1250 llvm::BasicBlock *SkipVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.skip_vbases");
1251 CGF.
Builder.CreateCondBr(IsCompleteObject,
1252 CallVbaseDtorsBB, SkipVbaseDtorsBB);
1257 return SkipVbaseDtorsBB;
1260void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
1261 CodeGenFunction &CGF,
const CXXRecordDecl *RD) {
1275 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
1278 CGBuilderTy &Builder = CGF.
Builder;
1280 llvm::Value *Int8This =
nullptr;
1282 for (
const CXXBaseSpecifier &S : RD->
vbases()) {
1283 const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl();
1284 auto I = VBaseMap.find(VBase);
1285 assert(I != VBaseMap.end());
1286 if (!I->second.hasVtorDisp())
1289 llvm::Value *VBaseOffset =
1290 GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase);
1291 uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity();
1294 llvm::Value *VtorDispValue = Builder.CreateSub(
1295 VBaseOffset, llvm::ConstantInt::get(CGM.
PtrDiffTy, ConstantVBaseOffset),
1297 VtorDispValue = Builder.CreateTruncOrBitCast(VtorDispValue, CGF.
Int32Ty);
1300 Int8This = getThisValue(CGF);
1302 llvm::Value *VtorDispPtr =
1303 Builder.CreateInBoundsGEP(CGF.
Int8Ty, Int8This, VBaseOffset);
1305 VtorDispPtr = Builder.CreateConstGEP1_32(CGF.
Int8Ty, VtorDispPtr, -4);
1307 Builder.CreateAlignedStore(VtorDispValue, VtorDispPtr,
1314 CallingConv ExpectedCallingConv = Context.getDefaultCallingConvention(
1318 return ExpectedCallingConv == ActualCallingConv;
1321void MicrosoftCXXABI::EmitCXXConstructors(
const CXXConstructorDecl *D) {
1333 Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1339void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
1340 const CXXRecordDecl *RD) {
1341 Address
This = getThisAddress(CGF);
1343 const ASTContext &Context = getContext();
1346 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
1347 for (
unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
1348 const std::unique_ptr<VPtrInfo> &VBT = (*VBGlobals.VBTables)[I];
1349 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
1350 const ASTRecordLayout &SubobjectLayout =
1352 CharUnits Offs = VBT->NonVirtualOffset;
1354 if (VBT->getVBaseWithVPtr())
1357 llvm::Value *GVPtr =
1364CGCXXABI::AddedStructorArgCounts
1365MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD,
1366 SmallVectorImpl<CanQualType> &ArgTys) {
1367 AddedStructorArgCounts Added;
1373 ArgTys.push_back(getContext().IntTy);
1376 auto *CD = dyn_cast<CXXConstructorDecl>(GD.
getDecl());
1384 const FunctionProtoType *FPT = CD->
getType()->
castAs<FunctionProtoType>();
1385 if (
Class->getNumVBases()) {
1387 ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy);
1390 ArgTys.push_back(getContext().IntTy);
1398void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
1399 const CXXDestructorDecl *Dtor,
1404 GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
1406 const NamedDecl *ND = Dtor;
1411llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(
1416 return llvm::GlobalValue::InternalLinkage;
1427 if (Dtor->
hasAttr<DLLExportAttr>())
1428 return llvm::GlobalValue::WeakODRLinkage;
1429 if (Dtor->
hasAttr<DLLImportAttr>())
1430 return llvm::GlobalValue::AvailableExternallyLinkage;
1431 return llvm::GlobalValue::LinkOnceODRLinkage;
1436 return llvm::GlobalValue::LinkOnceODRLinkage;
1438 llvm_unreachable(
"MS C++ ABI does not support unified dtors");
1444 return llvm::GlobalValue::WeakAnyLinkage;
1446 llvm_unreachable(
"MS C++ ABI does not support comdat dtors");
1448 llvm_unreachable(
"invalid dtor type");
1451void MicrosoftCXXABI::EmitCXXDestructors(
const CXXDestructorDecl *D) {
1465MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {
1468 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1483 MethodVFTableLocation ML =
1495 const ASTRecordLayout &DerivedLayout =
1496 getContext().getASTRecordLayout(MD->
getParent());
1503Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
1504 CodeGenFunction &CGF, GlobalDecl GD, Address This,
1509 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD);
1520 GlobalDecl LookupGD = GD;
1521 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
1535 MethodVFTableLocation ML =
1550 const CXXRecordDecl *Derived = MD->
getParent();
1551 const CXXRecordDecl *VBase = ML.
VBase;
1552 llvm::Value *VBaseOffset =
1553 GetVirtualBaseClassOffset(CGF,
Result, Derived, VBase);
1555 Result.getElementType(),
Result.emitRawPointer(CGF), VBaseOffset);
1556 CharUnits VBaseAlign =
1560 if (!StaticOffset.
isZero()) {
1576void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
1578 FunctionArgList &Params) {
1579 ASTContext &Context = getContext();
1586 ImplicitParamKind::Other);
1589 const FunctionProtoType *FPT = MD->
getType()->
castAs<FunctionProtoType>();
1591 Params.insert(Params.begin() + 1, IsMostDerived);
1593 Params.push_back(IsMostDerived);
1594 getStructorImplicitParamDecl(CGF) = IsMostDerived;
1599 ImplicitParamKind::Other);
1600 Params.push_back(ShouldDelete);
1601 getStructorImplicitParamDecl(CGF) = ShouldDelete;
1605void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
1622 llvm::Value *
This = loadIncomingCXXThis(CGF);
1625 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.
CurGD);
1626 if (!Adjustment.
isZero()) {
1632 setCXXABIThisValue(CGF, This);
1642 if (HasThisReturn(CGF.
CurGD) || hasMostDerivedReturn(CGF.
CurGD))
1646 assert(getStructorImplicitParamDecl(CGF) &&
1647 "no implicit parameter for a constructor with virtual bases?");
1648 getStructorImplicitParamValue(CGF)
1655 assert(getStructorImplicitParamDecl(CGF) &&
1656 "no implicit parameter for a deleting destructor?");
1657 getStructorImplicitParamValue(CGF)
1660 "should_call_delete");
1664CGCXXABI::AddedStructorArgs MicrosoftCXXABI::getImplicitConstructorArgs(
1671 return AddedStructorArgs{};
1674 const FunctionProtoType *FPT = D->
getType()->
castAs<FunctionProtoType>();
1675 llvm::Value *MostDerivedArg;
1677 MostDerivedArg = getStructorImplicitParamValue(CGF);
1682 return AddedStructorArgs::prefix({{MostDerivedArg, getContext().IntTy}});
1684 return AddedStructorArgs::suffix({{MostDerivedArg, getContext().IntTy}});
1687llvm::Value *MicrosoftCXXABI::getCXXDestructorImplicitParam(
1693void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
1694 const CXXDestructorDecl *DD,
1704 GlobalDecl GD(DD,
Type);
1708 assert(
Type != CXXDtorType::Dtor_Deleting &&
1709 "The deleting destructor should only be called via a virtual call");
1710 This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD,
Type),
1714 llvm::BasicBlock *BaseDtorEndBB =
nullptr;
1716 BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF);
1725 QualType(),
nullptr);
1726 if (BaseDtorEndBB) {
1728 CGF.
Builder.CreateBr(BaseDtorEndBB);
1733void MicrosoftCXXABI::emitVTableTypeMetadata(
const VPtrInfo &Info,
1734 const CXXRecordDecl *RD,
1735 llvm::GlobalVariable *VTable) {
1746 llvm::DenseSet<const CXXRecordDecl *> Visited;
1747 llvm::GlobalObject::VCallVisibility TypeVis =
1749 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1750 VTable->setVCallVisibilityMetadata(TypeVis);
1756 CharUnits AddressPoint =
1757 getContext().getLangOpts().RTTIData
1758 ? getContext().toCharUnitsFromBits(
1759 getContext().getTargetInfo().getPointerWidth(LangAS::Default))
1777 const ASTRecordLayout &Layout =
1778 getContext().getASTRecordLayout(DerivedRD);
1784 Offset = VBI->second.VBaseOffset;
1795void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
1796 const CXXRecordDecl *RD) {
1800 for (
const std::unique_ptr<VPtrInfo>& Info : VFPtrs) {
1801 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->
FullOffsetInMDC);
1802 if (VTable->hasInitializer())
1805 const VTableLayout &VTLayout =
1808 llvm::Constant *RTTI =
nullptr;
1810 [](
const VTableComponent &VTC) { return VTC.isRTTIKind(); }))
1811 RTTI = getMSCompleteObjectLocator(RD, *Info);
1813 ConstantInitBuilder builder(CGM);
1814 auto components = builder.beginStruct();
1816 VTable->hasLocalLinkage());
1817 components.finishAndSetAsInitializer(VTable);
1819 emitVTableTypeMetadata(*Info, RD, VTable);
1823bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField(
1824 CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) {
1828llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
1829 CodeGenFunction &CGF,
const CXXRecordDecl *VTableClass, BaseSubobject Base,
1830 const CXXRecordDecl *NearestVBase) {
1831 llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass);
1832 if (!VTableAddressPoint) {
1833 assert(
Base.getBase()->getNumVBases() &&
1834 !getContext().getASTRecordLayout(
Base.getBase()).hasOwnVFPtr());
1836 return VTableAddressPoint;
1842 llvm::raw_svector_ostream Out(Name);
1847MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base,
1848 const CXXRecordDecl *VTableClass) {
1849 (void)getAddrOfVTable(VTableClass,
Base.getBaseOffset());
1850 VFTableIdTy
ID(VTableClass,
Base.getBaseOffset());
1851 return VFTablesMap[
ID];
1854llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(
const CXXRecordDecl *RD,
1855 CharUnits VPtrOffset) {
1860 VFTableIdTy
ID(RD, VPtrOffset);
1861 auto [I, Inserted] = VTablesMap.try_emplace(ID);
1865 llvm::GlobalVariable *&VTable = I->second;
1870 if (DeferredVFTables.insert(RD).second) {
1878 llvm::StringSet<> ObservedMangledNames;
1879 for (
const auto &VFPtr : VFPtrs) {
1880 SmallString<256> Name;
1882 if (!ObservedMangledNames.insert(Name.str()).second)
1883 llvm_unreachable(
"Already saw this mangling before?");
1888 const std::unique_ptr<VPtrInfo> *VFPtrI =
1889 llvm::find_if(VFPtrs, [&](
const std::unique_ptr<VPtrInfo> &VPI) {
1890 return VPI->FullOffsetInMDC == VPtrOffset;
1892 if (VFPtrI == VFPtrs.end()) {
1893 VFTablesMap[
ID] =
nullptr;
1896 const std::unique_ptr<VPtrInfo> &VFPtr = *VFPtrI;
1898 SmallString<256> VFTableName;
1908 llvm::GlobalValue::LinkageTypes VFTableLinkage =
1909 RD->
hasAttr<DLLImportAttr>() ? llvm::GlobalValue::LinkOnceODRLinkage
1910 : CGM.getVTableLinkage(RD);
1911 bool VFTableComesFromAnotherTU =
1912 llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) ||
1913 llvm::GlobalValue::isExternalLinkage(VFTableLinkage);
1914 bool VTableAliasIsRequred =
1915 !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData;
1917 if (llvm::GlobalValue *VFTable =
1918 CGM.
getModule().getNamedGlobal(VFTableName)) {
1919 VFTablesMap[
ID] = VFTable;
1920 VTable = VTableAliasIsRequred
1923 :
cast<llvm::GlobalVariable>(VFTable);
1927 const VTableLayout &VTLayout =
1929 llvm::GlobalValue::LinkageTypes VTableLinkage =
1930 VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage;
1932 StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str();
1934 llvm::Type *VTableType = CGM.
getVTables().getVTableType(VTLayout);
1938 llvm::GlobalValue *VFTable;
1939 VTable =
new llvm::GlobalVariable(CGM.
getModule(), VTableType,
1940 true, VTableLinkage,
1941 nullptr, VTableName);
1942 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1944 llvm::Comdat *
C =
nullptr;
1945 if (!VFTableComesFromAnotherTU &&
1946 llvm::GlobalValue::isWeakForLinker(VFTableLinkage))
1947 C = CGM.
getModule().getOrInsertComdat(VFTableName.str());
1952 if (VTableAliasIsRequred) {
1953 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.
Int32Ty, 0),
1954 llvm::ConstantInt::get(CGM.
Int32Ty, 0),
1955 llvm::ConstantInt::get(CGM.
Int32Ty, 1)};
1958 llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr(
1959 VTable->getValueType(), VTable, GEPIndices);
1960 if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) {
1961 VFTableLinkage = llvm::GlobalValue::ExternalLinkage;
1963 C->setSelectionKind(llvm::Comdat::Largest);
1965 VFTable = llvm::GlobalAlias::create(CGM.
Int8PtrTy,
1967 VFTableName.str(), VTableGEP,
1969 VFTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1978 VTable->setComdat(
C);
1980 if (RD->
hasAttr<DLLExportAttr>())
1981 VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1983 VFTablesMap[
ID] = VFTable;
1987CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
1991 SourceLocation Loc) {
1992 CGBuilderTy &Builder = CGF.
Builder;
1996 adjustThisArgumentForVirtualFunctionCall(CGF, GD, This,
true);
1999 llvm::Value *VTable =
2007 auto getObjectWithVPtr = [&] {
2010 [&](
const std::unique_ptr<VPtrInfo> &Info) {
2011 return Info->FullOffsetInMDC == ML.VFPtrOffset;
2020 getObjectWithVPtr(), VTable, Ty,
2028 llvm::Value *VFuncPtr =
2029 Builder.CreateConstInBoundsGEP1_64(Ty, VTable, ML.
Index,
"vfn");
2030 VFunc = Builder.CreateAlignedLoad(Ty, VFuncPtr, CGF.
getPointerAlign());
2033 CGCallee
Callee(GD, VFunc);
2037llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
2038 CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
2039 Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke) {
2040 auto *CE = dyn_cast<const CXXMemberCallExpr *>(E);
2041 auto *D = dyn_cast<const CXXDeleteExpr *>(E);
2042 assert((CE !=
nullptr) ^ (D !=
nullptr));
2043 assert(CE ==
nullptr || CE->arg_begin() == CE->arg_end());
2049 ASTContext &Context = getContext();
2050 bool VectorDeletingDtorsEnabled =
2054 const CGFunctionInfo *FInfo =
2060 bool IsArrayDelete = D && D->isArrayForm() && VectorDeletingDtorsEnabled;
2061 bool IsGlobalDelete = D && D->isGlobalDelete() &&
2064 llvm::Value *ImplicitParam =
2065 CGF.
Builder.getInt32((IsDeleting ? 1 : 0) | (IsGlobalDelete ? 4 : 0) |
2066 (IsArrayDelete ? 2 : 0));
2070 ThisTy = CE->getObjectType();
2072 ThisTy = D->getDestroyedType();
2076 ThisTy = ATy->getElementType();
2078 This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This,
true);
2081 ImplicitParam, Context.
IntTy, CE, CallOrInvoke);
2085const VBTableGlobals &
2086MicrosoftCXXABI::enumerateVBTables(
const CXXRecordDecl *RD) {
2089 auto [Entry, Added] = VBTablesMap.try_emplace(RD);
2090 VBTableGlobals &VBGlobals = Entry->second;
2095 VBGlobals.VBTables = &Context.enumerateVBTables(RD);
2100 for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(),
2101 E = VBGlobals.VBTables->end();
2103 VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD,
Linkage));
2110MicrosoftCXXABI::EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
2111 const MethodVFTableLocation &ML) {
2113 "can't form pointers to ctors or virtual dtors");
2116 SmallString<256> ThunkName;
2117 llvm::raw_svector_ostream
Out(ThunkName);
2118 getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out);
2121 if (llvm::GlobalValue *GV = CGM.
getModule().getNamedValue(ThunkName))
2125 const CGFunctionInfo &FnInfo =
2128 llvm::Function *ThunkFn =
2129 llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage,
2131 assert(ThunkFn->getName() == ThunkName &&
"name was uniqued!");
2134 ? llvm::GlobalValue::LinkOnceODRLinkage
2135 : llvm::GlobalValue::InternalLinkage);
2137 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
2146 ThunkFn->addFnAttr(
"thunk");
2149 ThunkFn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
2152 CodeGenFunction CGF(CGM);
2153 CGF.
CurGD = GlobalDecl(MD);
2158 FunctionArgList FunctionArgs;
2159 buildThisParam(CGF, FunctionArgs);
2163 FunctionArgs, MD->
getLocation(), SourceLocation());
2166 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
2171 llvm::Value *VTable =
2174 llvm::Value *VFuncPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
2175 ThunkPtrTy, VTable, ML.
Index,
"vfn");
2184void MicrosoftCXXABI::emitVirtualInheritanceTables(
const CXXRecordDecl *RD) {
2185 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
2186 for (
unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
2187 const std::unique_ptr<VPtrInfo>& VBT = (*VBGlobals.VBTables)[I];
2188 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
2189 if (GV->isDeclaration())
2190 emitVBTableDefinition(*VBT, RD, GV);
2194llvm::GlobalVariable *
2195MicrosoftCXXABI::getAddrOfVBTable(
const VPtrInfo &VBT,
const CXXRecordDecl *RD,
2196 llvm::GlobalVariable::LinkageTypes
Linkage) {
2197 SmallString<256> OutName;
2198 llvm::raw_svector_ostream
Out(OutName);
2199 getMangleContext().mangleCXXVBTable(RD, VBT.
MangledPath, Out);
2200 StringRef Name = OutName.str();
2202 llvm::ArrayType *VBTableType =
2205 assert(!CGM.
getModule().getNamedGlobal(Name) &&
2206 "vbtable with this name already exists: mangling bug?");
2207 CharUnits Alignment =
2211 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2213 if (RD->
hasAttr<DLLImportAttr>())
2214 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2215 else if (RD->
hasAttr<DLLExportAttr>())
2216 GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2218 if (!GV->hasExternalLinkage())
2219 emitVBTableDefinition(VBT, RD, GV);
2224void MicrosoftCXXABI::emitVBTableDefinition(
const VPtrInfo &VBT,
2225 const CXXRecordDecl *RD,
2226 llvm::GlobalVariable *GV)
const {
2230 "should only emit vbtables for classes with vbtables");
2232 const ASTRecordLayout &BaseLayout =
2234 const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD);
2236 SmallVector<llvm::Constant *, 4> Offsets(1 + ObjectWithVPtr->
getNumVBases(),
2245 for (
const auto &I : ObjectWithVPtr->
vbases()) {
2246 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
2253 CompleteVBPtrOffset +=
2255 Offset -= CompleteVBPtrOffset;
2257 unsigned VBIndex = Context.getVBTableIndex(ObjectWithVPtr, VBase);
2258 assert(Offsets[VBIndex] ==
nullptr &&
"The same vbindex seen twice?");
2263 assert(Offsets.size() ==
2265 llvm::ArrayType *VBTableType =
2266 llvm::ArrayType::get(CGM.
IntTy, Offsets.size());
2267 llvm::Constant *
Init = llvm::ConstantArray::get(VBTableType, Offsets);
2268 GV->setInitializer(
Init);
2270 if (RD->
hasAttr<DLLImportAttr>())
2271 GV->setLinkage(llvm::GlobalVariable::AvailableExternallyLinkage);
2274llvm::Value *MicrosoftCXXABI::performThisAdjustment(
2275 CodeGenFunction &CGF, Address This,
2276 const CXXRecordDecl * ,
const ThunkInfo &TI) {
2277 const ThisAdjustment &TA = TI.
This;
2279 return This.emitRawPointer(CGF);
2285 V =
This.emitRawPointer(CGF);
2289 Address VtorDispPtr =
2295 CGF.
Builder.CreateNeg(VtorDisp));
2308 llvm::Value *VBaseOffset = GetVBaseOffsetFromVBPtr(
2327llvm::Value *MicrosoftCXXABI::performReturnAdjustment(
2328 CodeGenFunction &CGF, Address Ret,
2329 const CXXRecordDecl * ,
const ReturnAdjustment &RA) {
2332 return Ret.emitRawPointer(CGF);
2336 llvm::Value *
V =
Ret.emitRawPointer(CGF);
2341 llvm::Value *VBaseOffset =
2353bool MicrosoftCXXABI::requiresArrayCookie(
const CXXDeleteExpr *
expr,
2354 QualType elementType) {
2360bool MicrosoftCXXABI::requiresArrayCookie(
const CXXNewExpr *
expr) {
2363 return expr->getAllocatedType().isDestructedType();
2366CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType
type) {
2369 ASTContext &Ctx = getContext();
2374llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
2376 CharUnits cookieSize) {
2381Address MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
2383 llvm::Value *numElements,
2384 const CXXNewExpr *
expr,
2385 QualType elementType) {
2386 assert(requiresArrayCookie(
expr));
2389 CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
2392 Address cookiePtr = newPtr;
2404 llvm::FunctionCallee Dtor,
2405 llvm::Constant *
Addr) {
2410 llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get(
2411 CGF.
IntTy, DtorStub->getType(),
false);
2414 TLRegDtorTy,
"__tlregdtor", llvm::AttributeList(),
true);
2415 if (llvm::Function *TLRegDtorFn =
2416 dyn_cast<llvm::Function>(TLRegDtor.getCallee()))
2417 TLRegDtorFn->setDoesNotThrow();
2422void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
const VarDecl &D,
2423 llvm::FunctionCallee Dtor,
2424 llvm::Constant *
Addr) {
2439void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
2440 CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
2441 ArrayRef<llvm::Function *> CXXThreadLocalInits,
2442 ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
2443 if (CXXThreadLocalInits.empty())
2448 ?
"/include:___dyn_tls_init@12"
2449 :
"/include:__dyn_tls_init");
2454 auto AddToXDU = [&CGM](llvm::Function *InitFunc) {
2455 llvm::GlobalVariable *InitFuncPtr =
new llvm::GlobalVariable(
2456 CGM.
getModule(), InitFunc->getType(),
true,
2457 llvm::GlobalVariable::InternalLinkage, InitFunc,
2458 Twine(InitFunc->getName(),
"$initializer$"));
2459 InitFuncPtr->setSection(
".CRT$XDU");
2466 std::vector<llvm::Function *> NonComdatInits;
2467 for (
size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) {
2470 llvm::Function *F = CXXThreadLocalInits[I];
2473 if (llvm::Comdat *
C = GV->getComdat())
2474 AddToXDU(F)->setComdat(
C);
2476 NonComdatInits.push_back(F);
2479 if (!NonComdatInits.empty()) {
2480 llvm::FunctionType *FTy =
2481 llvm::FunctionType::get(CGM.
VoidTy,
false);
2484 SourceLocation(),
true);
2485 CodeGenFunction(CGM).GenerateCXXGlobalInitFunc(InitFunc, NonComdatInits);
2497 llvm::Constant *TlsGuardConstant =
2501 TlsGuard->setThreadLocal(
true);
2509 llvm::FunctionType *FTy =
2510 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()), {},
2513 FTy,
"__dyn_tls_on_demand_init",
2515 llvm::AttributeList::FunctionIndex,
2516 llvm::Attribute::NoUnwind),
2521 llvm::BasicBlock *DynInitBB,
2522 llvm::BasicBlock *ContinueBB) {
2523 llvm::LoadInst *TlsGuardValue =
2525 llvm::Value *CmpResult =
2527 CGF.
Builder.CreateCondBr(CmpResult, DynInitBB, ContinueBB);
2531 llvm::GlobalValue *TlsGuard,
2532 llvm::BasicBlock *ContinueBB) {
2534 llvm::Function *InitializerFunction =
2536 llvm::CallInst *CallVal = CGF.
Builder.CreateCall(InitializerFunction);
2537 CallVal->setCallingConv(InitializerFunction->getCallingConv());
2539 CGF.
Builder.CreateBr(ContinueBB);
2543 llvm::BasicBlock *DynInitBB =
2545 llvm::BasicBlock *ContinueBB =
2551 CGF.
Builder.SetInsertPoint(DynInitBB);
2553 CGF.
Builder.SetInsertPoint(ContinueBB);
2556LValue MicrosoftCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
2558 QualType LValType) {
2572 Address
Addr(
V, RealVarTy, Alignment);
2576 AlignmentSource::Decl)
2582 StringRef VarName(
"_Init_thread_epoch");
2584 if (
auto *GV = CGM.
getModule().getNamedGlobal(VarName))
2586 auto *GV =
new llvm::GlobalVariable(
2588 false, llvm::GlobalVariable::ExternalLinkage,
2590 nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel);
2596 llvm::FunctionType *FTy =
2597 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2600 FTy,
"_Init_thread_header",
2602 llvm::AttributeList::FunctionIndex,
2603 llvm::Attribute::NoUnwind),
2608 llvm::FunctionType *FTy =
2609 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2612 FTy,
"_Init_thread_footer",
2614 llvm::AttributeList::FunctionIndex,
2615 llvm::Attribute::NoUnwind),
2620 llvm::FunctionType *FTy =
2621 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2624 FTy,
"_Init_thread_abort",
2626 llvm::AttributeList::FunctionIndex,
2627 llvm::Attribute::NoUnwind),
2632struct ResetGuardBit final : EHScopeStack::Cleanup {
2635 ResetGuardBit(Address Guard,
unsigned GuardNum)
2636 : Guard(Guard), GuardNum(GuardNum) {}
2638 void Emit(CodeGenFunction &CGF, Flags flags)
override {
2641 CGBuilderTy &Builder = CGF.
Builder;
2642 llvm::LoadInst *LI = Builder.CreateLoad(Guard);
2643 llvm::ConstantInt *Mask =
2644 llvm::ConstantInt::getSigned(CGF.
IntTy, ~(1ULL << GuardNum));
2645 Builder.CreateStore(Builder.CreateAnd(LI, Mask), Guard);
2649struct CallInitThreadAbort final : EHScopeStack::Cleanup {
2651 CallInitThreadAbort(RawAddress Guard) : Guard(Guard.getPointer()) {}
2653 void Emit(CodeGenFunction &CGF, Flags flags)
override {
2660void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
const VarDecl &D,
2661 llvm::GlobalVariable *GV,
2665 assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage());
2667 llvm::Function *F = CGF.
CurFn;
2668 F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
2669 F->setComdat(CGM.
getModule().getOrInsertComdat(F->getName()));
2675 bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics;
2679 bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic;
2681 CGBuilderTy &Builder = CGF.
Builder;
2682 llvm::IntegerType *GuardTy = CGF.
Int32Ty;
2683 llvm::ConstantInt *
Zero = llvm::ConstantInt::get(GuardTy, 0);
2687 GuardInfo *GI =
nullptr;
2688 if (ThreadlocalStatic)
2690 else if (!ThreadsafeStatic)
2693 llvm::GlobalVariable *GuardVar = GI ? GI->Guard :
nullptr;
2698 GuardNum = getContext().getStaticLocalNumber(&D);
2699 assert(GuardNum > 0);
2701 }
else if (HasPerVariableGuard) {
2705 GuardNum = GI->BitIndex++;
2708 if (!HasPerVariableGuard && GuardNum >= 32) {
2710 ErrorUnsupportedABI(CGF,
"more than 32 guarded initializations");
2717 SmallString<256> GuardName;
2719 llvm::raw_svector_ostream
Out(GuardName);
2720 if (HasPerVariableGuard)
2721 getMangleContext().mangleThreadSafeStaticGuardVariable(&D, GuardNum,
2724 getMangleContext().mangleStaticGuardVariable(&D, Out);
2730 new llvm::GlobalVariable(CGM.
getModule(), GuardTy,
false,
2731 GV->getLinkage(),
Zero, GuardName.str());
2732 GuardVar->setVisibility(GV->getVisibility());
2733 GuardVar->setDLLStorageClass(GV->getDLLStorageClass());
2734 GuardVar->setAlignment(GuardAlign.
getAsAlign());
2735 if (GuardVar->isWeakForLinker())
2736 GuardVar->setComdat(
2737 CGM.
getModule().getOrInsertComdat(GuardVar->getName()));
2740 if (GI && !HasPerVariableGuard)
2741 GI->Guard = GuardVar;
2744 ConstantAddress GuardAddr(GuardVar, GuardTy, GuardAlign);
2746 assert(GuardVar->getLinkage() == GV->getLinkage() &&
2747 "static local from the same function had different linkage");
2749 if (!HasPerVariableGuard) {
2757 llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum);
2758 llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr);
2759 llvm::Value *NeedsInit =
2760 Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit),
Zero);
2764 CodeGenFunction::GuardKind::VariableGuard, &D);
2769 Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardAddr);
2773 Builder.CreateBr(EndBlock);
2791 llvm::LoadInst *FirstGuardLoad = Builder.CreateLoad(GuardAddr);
2792 FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2793 llvm::LoadInst *InitThreadEpoch =
2795 llvm::Value *IsUninitialized =
2796 Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch);
2800 CodeGenFunction::GuardKind::VariableGuard, &D);
2806 GuardAddr.getPointer());
2807 llvm::LoadInst *SecondGuardLoad = Builder.CreateLoad(GuardAddr);
2808 SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2809 llvm::Value *ShouldDoInit =
2810 Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt());
2812 Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock);
2820 GuardAddr.getPointer());
2821 Builder.CreateBr(EndBlock);
2827bool MicrosoftCXXABI::isZeroInitializable(
const MemberPointerType *MPT) {
2843MicrosoftCXXABI::ConvertMemberPointerType(
const MemberPointerType *MPT) {
2846 llvm::SmallVector<llvm::Type *, 4> fields;
2850 fields.push_back(CGM.
IntTy);
2854 fields.push_back(CGM.
IntTy);
2856 fields.push_back(CGM.
IntTy);
2858 fields.push_back(CGM.
IntTy);
2860 if (fields.size() == 1)
2865void MicrosoftCXXABI::
2866GetNullMemberPointerFields(
const MemberPointerType *MPT,
2867 llvm::SmallVectorImpl<llvm::Constant *> &fields) {
2868 assert(fields.empty());
2873 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
2876 fields.push_back(getZeroInt());
2878 fields.push_back(getAllOnesInt());
2883 fields.push_back(getZeroInt());
2885 fields.push_back(getZeroInt());
2887 fields.push_back(getAllOnesInt());
2891MicrosoftCXXABI::EmitNullMemberPointer(
const MemberPointerType *MPT) {
2892 llvm::SmallVector<llvm::Constant *, 4> fields;
2893 GetNullMemberPointerFields(MPT, fields);
2894 if (fields.size() == 1)
2896 llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields);
2897 assert(Res->getType() == ConvertMemberPointerType(MPT));
2902MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
2903 bool IsMemberFunction,
2904 const CXXRecordDecl *RD,
2905 CharUnits NonVirtualBaseAdjustment,
2906 unsigned VBTableIndex) {
2914 llvm::SmallVector<llvm::Constant *, 4> fields;
2915 fields.push_back(FirstField);
2918 fields.push_back(llvm::ConstantInt::getSigned(
2924 Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
2930 fields.push_back(llvm::ConstantInt::get(CGM.
IntTy, VBTableIndex));
2932 return llvm::ConstantStruct::getAnon(fields);
2936MicrosoftCXXABI::EmitMemberDataPointer(
const MemberPointerType *MPT,
2941llvm::Constant *MicrosoftCXXABI::EmitMemberDataPointer(
const CXXRecordDecl *RD,
2944 MSInheritanceModel::Virtual)
2945 offset -= getContext().getOffsetOfBaseWithVBPtr(RD);
2946 llvm::Constant *FirstField =
2948 return EmitFullMemberPointer(FirstField,
false, RD,
2952llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(
const APValue &MP,
2954 const MemberPointerType *DstTy = MPType->
castAs<MemberPointerType>();
2957 return EmitNullMemberPointer(DstTy);
2959 ASTContext &Ctx = getContext();
2963 if (
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
2964 C = EmitMemberFunctionPointer(MD);
2971 const FieldDecl *FD = dyn_cast<FieldDecl>(MPD);
2976 C = EmitMemberDataPointer(RD, FieldOffset);
2979 if (!MemberPointerPath.empty()) {
2981 const MemberPointerType *SrcTy =
2983 std::nullopt, SrcRD)
2984 ->
castAs<MemberPointerType>();
2987 SmallVector<const CXXBaseSpecifier *, 4> DerivedToBasePath;
2988 const CXXRecordDecl *PrevRD = SrcRD;
2989 for (
const CXXRecordDecl *PathElem : MemberPointerPath) {
2990 const CXXRecordDecl *
Base =
nullptr;
2991 const CXXRecordDecl *Derived =
nullptr;
2992 if (DerivedMember) {
2999 for (
const CXXBaseSpecifier &BS : Derived->
bases())
3000 if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() ==
3001 Base->getCanonicalDecl())
3002 DerivedToBasePath.push_back(&BS);
3005 assert(DerivedToBasePath.size() == MemberPointerPath.size());
3007 CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer
3008 : CK_BaseToDerivedMemberPointer;
3009 C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(),
3010 DerivedToBasePath.end(),
C);
3016MicrosoftCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
3017 assert(MD->
isInstance() &&
"Member function must not be static!");
3021 CodeGenTypes &Types = CGM.
getTypes();
3023 unsigned VBTableIndex = 0;
3024 llvm::Constant *FirstField;
3025 const FunctionProtoType *FPT = MD->
getType()->
castAs<FunctionProtoType>();
3040 MethodVFTableLocation ML = VTableContext.getMethodVFTableLocation(MD);
3041 FirstField = EmitVirtualMemPtrThunk(MD, ML);
3045 VBTableIndex = VTableContext.getVBTableIndex(RD, ML.
VBase) * 4;
3048 if (VBTableIndex == 0 &&
3050 MSInheritanceModel::Virtual)
3051 NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD);
3054 return EmitFullMemberPointer(FirstField,
true, RD,
3055 NonVirtualBaseAdjustment, VBTableIndex);
3062MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
3065 const MemberPointerType *MPT,
3067 CGBuilderTy &Builder = CGF.
Builder;
3070 llvm::ICmpInst::Predicate Eq;
3071 llvm::Instruction::BinaryOps
And,
Or;
3073 Eq = llvm::ICmpInst::ICMP_NE;
3074 And = llvm::Instruction::Or;
3075 Or = llvm::Instruction::And;
3077 Eq = llvm::ICmpInst::ICMP_EQ;
3078 And = llvm::Instruction::And;
3079 Or = llvm::Instruction::Or;
3088 return Builder.CreateICmp(Eq, L, R);
3091 llvm::Value *L0 = Builder.CreateExtractValue(L, 0,
"lhs.0");
3092 llvm::Value *R0 = Builder.CreateExtractValue(R, 0,
"rhs.0");
3093 llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0,
"memptr.cmp.first");
3096 llvm::Value *Res =
nullptr;
3098 for (
unsigned I = 1, E = LType->getNumElements(); I != E; ++I) {
3099 llvm::Value *LF = Builder.CreateExtractValue(L, I);
3100 llvm::Value *RF = Builder.CreateExtractValue(R, I);
3101 llvm::Value *Cmp = Builder.CreateICmp(Eq, LF, RF,
"memptr.cmp.rest");
3103 Res = Builder.CreateBinOp(
And, Res, Cmp);
3111 llvm::Value *
Zero = llvm::Constant::getNullValue(L0->getType());
3112 llvm::Value *IsZero = Builder.CreateICmp(Eq, L0,
Zero,
"memptr.cmp.iszero");
3113 Res = Builder.CreateBinOp(
Or, Res, IsZero);
3118 return Builder.CreateBinOp(
And, Res, Cmp0,
"memptr.cmp");
3122MicrosoftCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
3123 llvm::Value *MemPtr,
3124 const MemberPointerType *MPT) {
3125 CGBuilderTy &Builder = CGF.
Builder;
3126 llvm::SmallVector<llvm::Constant *, 4> fields;
3129 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
3131 GetNullMemberPointerFields(MPT, fields);
3132 assert(!fields.empty());
3133 llvm::Value *FirstField = MemPtr;
3134 if (MemPtr->getType()->isStructTy())
3135 FirstField = Builder.CreateExtractValue(MemPtr, 0);
3136 llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0],
"memptr.cmp0");
3144 for (
int I = 1, E = fields.size(); I < E; ++I) {
3145 llvm::Value *
Field = Builder.CreateExtractValue(MemPtr, I);
3146 llvm::Value *
Next = Builder.CreateICmpNE(Field, fields[I],
"memptr.cmp");
3147 Res = Builder.CreateOr(Res,
Next,
"memptr.tobool");
3152bool MicrosoftCXXABI::MemberPointerConstantIsNull(
const MemberPointerType *MPT,
3153 llvm::Constant *Val) {
3156 llvm::Constant *FirstField = Val->getType()->isStructTy() ?
3157 Val->getAggregateElement(0U) : Val;
3158 return FirstField->isNullValue();
3163 if (isZeroInitializable(MPT) && Val->isNullValue())
3168 llvm::SmallVector<llvm::Constant *, 4> Fields;
3169 GetNullMemberPointerFields(MPT, Fields);
3170 if (Fields.size() == 1) {
3171 assert(Val->getType()->isIntegerTy());
3172 return Val == Fields[0];
3176 for (I = 0, E = Fields.size(); I != E; ++I) {
3177 if (Val->getAggregateElement(I) != Fields[I])
3184MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
3186 llvm::Value *VBPtrOffset,
3187 llvm::Value *VBTableOffset,
3188 llvm::Value **VBPtrOut) {
3189 CGBuilderTy &Builder = CGF.
Builder;
3191 llvm::Value *VBPtr = Builder.CreateInBoundsGEP(
3192 CGM.
Int8Ty,
This.emitRawPointer(CGF), VBPtrOffset,
"vbptr");
3196 CharUnits VBPtrAlign;
3197 if (
auto CI = dyn_cast<llvm::ConstantInt>(VBPtrOffset)) {
3198 VBPtrAlign =
This.getAlignment().alignmentAtOffset(
3204 llvm::Value *VBTable =
3205 Builder.CreateAlignedLoad(CGM.
DefaultPtrTy, VBPtr, VBPtrAlign,
"vbtable");
3208 llvm::Value *VBTableIndex = Builder.CreateAShr(
3209 VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2),
3213 llvm::Value *VBaseOffs =
3214 Builder.CreateInBoundsGEP(CGM.
Int32Ty, VBTable, VBTableIndex);
3215 return Builder.CreateAlignedLoad(CGM.
Int32Ty, VBaseOffs,
3221llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(
3222 CodeGenFunction &CGF,
const Expr *E,
const CXXRecordDecl *RD,
3223 Address Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {
3224 CGBuilderTy &Builder = CGF.
Builder;
3226 llvm::BasicBlock *OriginalBB =
nullptr;
3227 llvm::BasicBlock *SkipAdjustBB =
nullptr;
3228 llvm::BasicBlock *VBaseAdjustBB =
nullptr;
3235 OriginalBB = Builder.GetInsertBlock();
3238 llvm::Value *IsVirtual =
3239 Builder.CreateICmpNE(VBTableOffset, getZeroInt(),
3241 Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB);
3253 "member pointer representation requires a "
3254 "complete class type for %0 to perform this expression");
3257 offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
3260 llvm::Value *VBPtr =
nullptr;
3261 llvm::Value *VBaseOffs =
3262 GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr);
3263 llvm::Value *AdjustedBase =
3264 Builder.CreateInBoundsGEP(CGM.
Int8Ty, VBPtr, VBaseOffs);
3267 if (VBaseAdjustBB) {
3268 Builder.CreateBr(SkipAdjustBB);
3270 llvm::PHINode *Phi = Builder.CreatePHI(CGM.
Int8PtrTy, 2,
"memptr.base");
3271 Phi->addIncoming(
Base.emitRawPointer(CGF), OriginalBB);
3272 Phi->addIncoming(AdjustedBase, VBaseAdjustBB);
3275 return AdjustedBase;
3278llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
3279 CodeGenFunction &CGF,
const Expr *E, Address Base, llvm::Value *MemPtr,
3280 const MemberPointerType *MPT,
bool IsInBounds) {
3282 CGBuilderTy &Builder = CGF.
Builder;
3288 llvm::Value *FieldOffset = MemPtr;
3289 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3290 llvm::Value *VBPtrOffset =
nullptr;
3291 if (MemPtr->getType()->isStructTy()) {
3294 FieldOffset = Builder.CreateExtractValue(MemPtr, I++);
3296 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3298 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3302 if (VirtualBaseAdjustmentOffset) {
3303 Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset,
3310 return Builder.CreateGEP(CGF.
Int8Ty,
Addr, FieldOffset,
"memptr.offset",
3311 IsInBounds ? llvm::GEPNoWrapFlags::inBounds()
3312 : llvm::GEPNoWrapFlags::none());
3316MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
3319 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
3320 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
3329 const MemberPointerType *SrcTy =
3331 const MemberPointerType *DstTy = E->
getType()->
castAs<MemberPointerType>();
3335 bool IsReinterpret = E->
getCastKind() == CK_ReinterpretMemberPointer;
3336 if (IsReinterpret && IsFunc)
3340 CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl();
3341 if (IsReinterpret &&
3345 CGBuilderTy &Builder = CGF.
Builder;
3348 llvm::Value *
IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy);
3349 llvm::Constant *DstNull = EmitNullMemberPointer(DstTy);
3353 if (IsReinterpret) {
3356 assert(Src->getType() == DstNull->getType());
3357 return Builder.CreateSelect(
IsNotNull, Src, DstNull);
3360 llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock();
3363 Builder.CreateCondBr(
IsNotNull, ConvertBB, ContinueBB);
3366 llvm::Value *Dst = EmitNonNullMemberPointerConversion(
3370 Builder.CreateBr(ContinueBB);
3374 llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2,
"memptr.converted");
3375 Phi->addIncoming(DstNull, OriginalBB);
3376 Phi->addIncoming(Dst, ConvertBB);
3380llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion(
3381 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
CastKind CK,
3384 CGBuilderTy &Builder) {
3393 llvm::Value *FirstField = Src;
3394 llvm::Value *NonVirtualBaseAdjustment = getZeroInt();
3395 llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt();
3396 llvm::Value *VBPtrOffset = getZeroInt();
3400 FirstField = Builder.CreateExtractValue(Src, I++);
3402 NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++);
3404 VBPtrOffset = Builder.CreateExtractValue(Src, I++);
3406 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++);
3409 bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer);
3410 const MemberPointerType *DerivedTy = IsDerivedToBase ? SrcTy : DstTy;
3415 llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;
3422 llvm::Value *SrcVBIndexEqZero =
3423 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3424 if (SrcInheritance == MSInheritanceModel::Virtual) {
3425 if (int64_t SrcOffsetToFirstVBase =
3426 getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) {
3427 llvm::Value *UndoSrcAdjustment = Builder.CreateSelect(
3429 llvm::ConstantInt::get(CGM.
IntTy, SrcOffsetToFirstVBase),
3431 NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment);
3442 llvm::Constant *BaseClassOffset = llvm::ConstantInt::get(
3447 llvm::Value *NVDisp;
3448 if (IsDerivedToBase)
3449 NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset,
"adj");
3451 NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset,
"adj");
3453 NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt());
3457 llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero;
3460 if (llvm::GlobalVariable *VDispMap =
3461 getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) {
3462 llvm::Value *VBIndex = Builder.CreateExactUDiv(
3463 VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.
IntTy, 4));
3465 llvm::Constant *Mapping = VDispMap->getInitializer();
3466 VirtualBaseAdjustmentOffset =
3469 llvm::Value *Idxs[] = {getZeroInt(), VBIndex};
3470 VirtualBaseAdjustmentOffset = Builder.CreateAlignedLoad(
3471 CGM.
IntTy, Builder.CreateInBoundsGEP(VDispMap->getValueType(),
3477 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3484 llvm::Value *DstVBPtrOffset = llvm::ConstantInt::getSigned(
3486 getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity());
3488 Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset);
3494 if (DstInheritance == MSInheritanceModel::Virtual) {
3495 if (int64_t DstOffsetToFirstVBase =
3496 getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) {
3497 llvm::Value *DoDstAdjustment = Builder.CreateSelect(
3499 llvm::ConstantInt::get(CGM.
IntTy, DstOffsetToFirstVBase),
3501 NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment);
3510 Dst = llvm::PoisonValue::get(ConvertMemberPointerType(DstTy));
3512 Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
3514 Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++);
3516 Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++);
3518 Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++);
3524MicrosoftCXXABI::EmitMemberPointerConversion(
const CastExpr *E,
3525 llvm::Constant *Src) {
3526 const MemberPointerType *SrcTy =
3528 const MemberPointerType *DstTy = E->
getType()->
castAs<MemberPointerType>();
3532 return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->
path_begin(),
3536llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
3537 const MemberPointerType *SrcTy,
const MemberPointerType *DstTy,
CastKind CK,
3540 assert(CK == CK_DerivedToBaseMemberPointer ||
3541 CK == CK_BaseToDerivedMemberPointer ||
3542 CK == CK_ReinterpretMemberPointer);
3545 if (MemberPointerConstantIsNull(SrcTy, Src))
3546 return EmitNullMemberPointer(DstTy);
3551 if (CK == CK_ReinterpretMemberPointer)
3556 SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder));
3561CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
3562 CodeGenFunction &CGF,
const Expr *E, Address This,
3563 llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
3564 const MemberPointerType *MPT) {
3566 const FunctionProtoType *FPT =
3569 CGBuilderTy &Builder = CGF.
Builder;
3575 llvm::Value *FunctionPointer = MemPtr;
3576 llvm::Value *NonVirtualBaseAdjustment =
nullptr;
3577 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3578 llvm::Value *VBPtrOffset =
nullptr;
3579 if (MemPtr->getType()->isStructTy()) {
3582 FunctionPointer = Builder.CreateExtractValue(MemPtr, I++);
3584 NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++);
3586 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3588 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3591 if (VirtualBaseAdjustmentOffset) {
3592 ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This,
3593 VirtualBaseAdjustmentOffset, VBPtrOffset);
3595 ThisPtrForCall =
This.emitRawPointer(CGF);
3598 if (NonVirtualBaseAdjustment)
3599 ThisPtrForCall = Builder.CreateInBoundsGEP(CGF.
Int8Ty, ThisPtrForCall,
3600 NonVirtualBaseAdjustment);
3602 CGCallee
Callee(FPT, FunctionPointer);
3607 return new MicrosoftCXXABI(CGM);
3641 StringRef MangledName(
"??_7type_info@@6B@");
3642 if (
auto VTable = CGM.
getModule().getNamedGlobal(MangledName))
3646 llvm::GlobalVariable::ExternalLinkage,
3647 nullptr, MangledName);
3660 IsPrivateOnPath = 1 | 8,
3664 HasHierarchyDescriptor = 64
3666 MSRTTIClass(
const CXXRecordDecl *RD) : RD(RD) {}
3668 const CXXBaseSpecifier *Specifier);
3670 MSRTTIClass *getFirstChild() {
return this + 1; }
3671 static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
3672 return Child + 1 + Child->NumBases;
3675 const CXXRecordDecl *RD, *VirtualRoot;
3676 uint32_t Flags, NumBases, OffsetInVBase;
3680uint32_t MSRTTIClass::initialize(
const MSRTTIClass *Parent,
3681 const CXXBaseSpecifier *Specifier) {
3682 Flags = HasHierarchyDescriptor;
3684 VirtualRoot =
nullptr;
3688 Flags |= IsPrivate | IsPrivateOnPath;
3694 if (Parent->Flags & IsPrivateOnPath)
3695 Flags |= IsPrivateOnPath;
3696 VirtualRoot = Parent->VirtualRoot;
3697 OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext()
3698 .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity();
3702 MSRTTIClass *Child = getFirstChild();
3703 for (
const CXXBaseSpecifier &Base : RD->bases()) {
3704 NumBases += Child->initialize(
this, &Base) + 1;
3705 Child = getNextChild(Child);
3710static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) {
3712 case Linkage::Invalid:
3713 llvm_unreachable(
"Linkage hasn't been computed!");
3716 case Linkage::Internal:
3717 case Linkage::UniqueExternal:
3718 return llvm::GlobalValue::InternalLinkage;
3720 case Linkage::VisibleNone:
3721 case Linkage::Module:
3722 case Linkage::External:
3723 return llvm::GlobalValue::LinkOnceODRLinkage;
3725 llvm_unreachable(
"Invalid linkage!");
3731struct MSRTTIBuilder {
3733 HasBranchingHierarchy = 1,
3734 HasVirtualBranchingHierarchy = 2,
3735 HasAmbiguousBases = 4
3738 MSRTTIBuilder(MicrosoftCXXABI &ABI,
const CXXRecordDecl *RD)
3739 : CGM(ABI.CGM), Context(CGM.getContext()),
3740 VMContext(CGM.getLLVMContext()),
Module(CGM.getModule()), RD(RD),
3741 Linkage(getLinkageForRTTI(CGM.getContext().getCanonicalTagType(RD))),
3744 llvm::GlobalVariable *getBaseClassDescriptor(
const MSRTTIClass &Classes);
3745 llvm::GlobalVariable *
3746 getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes);
3747 llvm::GlobalVariable *getClassHierarchyDescriptor();
3748 llvm::GlobalVariable *getCompleteObjectLocator(
const VPtrInfo &Info);
3751 ASTContext &Context;
3752 llvm::LLVMContext &VMContext;
3754 const CXXRecordDecl *RD;
3755 llvm::GlobalVariable::LinkageTypes
Linkage;
3756 MicrosoftCXXABI &ABI;
3765 Classes.push_back(MSRTTIClass(RD));
3776 for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
3777 if ((Class->Flags & MSRTTIClass::IsVirtual) &&
3778 !VirtualBases.insert(Class->RD).second) {
3779 Class = MSRTTIClass::getNextChild(Class);
3782 if (!UniqueBases.insert(Class->RD).second)
3783 AmbiguousBases.insert(Class->RD);
3786 if (AmbiguousBases.empty())
3788 for (MSRTTIClass &Class : Classes)
3789 if (AmbiguousBases.count(Class.RD))
3790 Class.Flags |= MSRTTIClass::IsAmbiguous;
3793llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
3794 SmallString<256> MangledName;
3796 llvm::raw_svector_ostream
Out(MangledName);
3797 ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
3801 if (
auto CHD =
Module.getNamedGlobal(MangledName))
3805 SmallVector<MSRTTIClass, 8> Classes;
3807 Classes.front().initialize(
nullptr,
nullptr);
3810 for (
const MSRTTIClass &
Class : Classes) {
3811 if (
Class.RD->getNumBases() > 1)
3812 Flags |= HasBranchingHierarchy;
3815 if (
Class.Flags & MSRTTIClass::IsAmbiguous)
3816 Flags |= HasAmbiguousBases;
3818 if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)
3819 Flags |= HasVirtualBranchingHierarchy;
3822 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.
IntTy, 0),
3823 llvm::ConstantInt::get(CGM.
IntTy, 0)};
3826 auto Type = ABI.getClassHierarchyDescriptorType();
3830 if (CHD->isWeakForLinker())
3831 CHD->setComdat(CGM.
getModule().getOrInsertComdat(CHD->getName()));
3833 auto *Bases = getBaseClassArray(Classes);
3836 llvm::Constant *Fields[] = {
3837 llvm::ConstantInt::get(CGM.
IntTy, 0),
3838 llvm::ConstantInt::get(CGM.
IntTy, Flags),
3839 llvm::ConstantInt::get(CGM.
IntTy, Classes.size()),
3840 ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(
3841 Bases->getValueType(), Bases,
3842 llvm::ArrayRef<llvm::Value *>(GEPIndices))),
3844 CHD->setInitializer(llvm::ConstantStruct::get(
Type, Fields));
3848llvm::GlobalVariable *
3849MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
3850 SmallString<256> MangledName;
3852 llvm::raw_svector_ostream
Out(MangledName);
3853 ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out);
3861 llvm::Type *PtrType = ABI.getImageRelativeType(CGM.
DefaultPtrTy);
3862 auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
3864 new llvm::GlobalVariable(
Module, ArrType,
3866 nullptr, MangledName);
3867 if (BCA->isWeakForLinker())
3868 BCA->setComdat(CGM.
getModule().getOrInsertComdat(BCA->getName()));
3871 SmallVector<llvm::Constant *, 8> BaseClassArrayData;
3872 for (MSRTTIClass &
Class : Classes)
3873 BaseClassArrayData.push_back(
3874 ABI.getImageRelativeConstant(getBaseClassDescriptor(
Class)));
3875 BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType));
3876 BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData));
3880llvm::GlobalVariable *
3881MSRTTIBuilder::getBaseClassDescriptor(
const MSRTTIClass &
Class) {
3886 if (
Class.VirtualRoot) {
3888 OffsetInVBTable = VTableContext.getVBTableIndex(RD,
Class.VirtualRoot) * 4;
3892 SmallString<256> MangledName;
3894 llvm::raw_svector_ostream
Out(MangledName);
3895 ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor(
3896 Class.RD,
Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable,
3901 if (
auto BCD =
Module.getNamedGlobal(MangledName))
3905 auto Type = ABI.getBaseClassDescriptorType();
3908 nullptr, MangledName);
3909 if (BCD->isWeakForLinker())
3910 BCD->setComdat(CGM.
getModule().getOrInsertComdat(BCD->getName()));
3913 llvm::Constant *Fields[] = {
3914 ABI.getImageRelativeConstant(
3916 llvm::ConstantInt::get(CGM.
IntTy,
Class.NumBases),
3917 llvm::ConstantInt::get(CGM.
IntTy,
Class.OffsetInVBase),
3918 llvm::ConstantInt::getSigned(CGM.
IntTy, VBPtrOffset),
3919 llvm::ConstantInt::get(CGM.
IntTy, OffsetInVBTable),
3920 llvm::ConstantInt::get(CGM.
IntTy,
Class.Flags),
3921 ABI.getImageRelativeConstant(
3922 MSRTTIBuilder(ABI,
Class.RD).getClassHierarchyDescriptor()),
3924 BCD->setInitializer(llvm::ConstantStruct::get(
Type, Fields));
3928llvm::GlobalVariable *
3929MSRTTIBuilder::getCompleteObjectLocator(
const VPtrInfo &Info) {
3930 SmallString<256> MangledName;
3932 llvm::raw_svector_ostream
Out(MangledName);
3933 ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info.
MangledPath, Out);
3937 if (
auto COL =
Module.getNamedGlobal(MangledName))
3942 int VFPtrOffset = 0;
3948 ->second.hasVtorDisp())
3952 llvm::StructType *
Type = ABI.getCompleteObjectLocatorType();
3954 nullptr, MangledName);
3957 llvm::Constant *Fields[] = {
3958 llvm::ConstantInt::get(CGM.
IntTy, ABI.isImageRelative()),
3959 llvm::ConstantInt::get(CGM.
IntTy, OffsetToTop),
3960 llvm::ConstantInt::get(CGM.
IntTy, VFPtrOffset),
3961 ABI.getImageRelativeConstant(
3963 ABI.getImageRelativeConstant(getClassHierarchyDescriptor()),
3964 ABI.getImageRelativeConstant(COL),
3966 llvm::ArrayRef<llvm::Constant *> FieldsRef(Fields);
3967 if (!ABI.isImageRelative())
3968 FieldsRef = FieldsRef.drop_back();
3969 COL->setInitializer(llvm::ConstantStruct::get(
Type, FieldsRef));
3970 if (COL->isWeakForLinker())
3971 COL->setComdat(CGM.
getModule().getOrInsertComdat(COL->getName()));
3976 bool &IsConst,
bool &IsVolatile,
3977 bool &IsUnaligned) {
3978 T = Context.getExceptionObjectType(
T);
3987 IsUnaligned =
false;
3988 QualType PointeeType =
T->getPointeeType();
3989 if (!PointeeType.
isNull()) {
3999 MPTy->getQualifier(),
4000 MPTy->getMostRecentCXXRecordDecl());
4004 if (
T->isPointerType())
4011MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(QualType
Type,
4012 QualType CatchHandlerType) {
4016 bool IsConst, IsVolatile, IsUnaligned;
4032 return CatchTypeInfo{getAddrOfRTTIDescriptor(
Type)->stripPointerCasts(),
4040llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType
Type) {
4041 SmallString<256> MangledName;
4043 llvm::raw_svector_ostream
Out(MangledName);
4044 getMangleContext().mangleCXXRTTI(
Type, Out);
4048 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4055 SmallString<256> TypeInfoString;
4057 llvm::raw_svector_ostream
Out(TypeInfoString);
4058 getMangleContext().mangleCXXRTTIName(
Type, Out);
4062 llvm::Constant *Fields[] = {
4064 llvm::ConstantPointerNull::get(CGM.
Int8PtrTy),
4065 llvm::ConstantDataArray::getString(CGM.
getLLVMContext(), TypeInfoString)};
4066 llvm::StructType *TypeDescriptorType =
4067 getTypeDescriptorType(TypeInfoString);
4068 auto *Var =
new llvm::GlobalVariable(
4069 CGM.
getModule(), TypeDescriptorType,
false,
4070 getLinkageForRTTI(
Type),
4071 llvm::ConstantStruct::get(TypeDescriptorType, Fields),
4073 if (Var->isWeakForLinker())
4074 Var->setComdat(CGM.
getModule().getOrInsertComdat(Var->getName()));
4079llvm::GlobalVariable *
4080MicrosoftCXXABI::getMSCompleteObjectLocator(
const CXXRecordDecl *RD,
4081 const VPtrInfo &Info) {
4082 return MSRTTIBuilder(*
this, RD).getCompleteObjectLocator(Info);
4085void MicrosoftCXXABI::emitCXXStructor(GlobalDecl GD) {
4086 if (
auto *ctor = dyn_cast<CXXConstructorDecl>(GD.
getDecl())) {
4088 llvm::Function *
Fn =
4100 dtor->getParent()->getNumVBases() == 0)
4111 !getContext().classNeedsVectorDeletingDestructor(dtor->getParent())) {
4123 if (
Fn->isWeakForLinker())
4124 Fn->setComdat(CGM.
getModule().getOrInsertComdat(
Fn->getName()));
4128MicrosoftCXXABI::getAddrOfCXXCtorClosure(
const CXXConstructorDecl *CD,
4133 SmallString<256> ThunkName;
4134 llvm::raw_svector_ostream
Out(ThunkName);
4135 getMangleContext().mangleName(GlobalDecl(CD, CT), Out);
4138 if (llvm::GlobalValue *GV = CGM.
getModule().getNamedValue(ThunkName))
4144 const CXXRecordDecl *RD = CD->
getParent();
4145 CanQualType RecordTy = getContext().getCanonicalTagType(RD);
4146 llvm::Function *ThunkFn = llvm::Function::Create(
4147 ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.
getModule());
4148 ThunkFn->setCallingConv(
static_cast<llvm::CallingConv::ID
>(
4150 if (ThunkFn->isWeakForLinker())
4151 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
4155 CodeGenFunction CGF(CGM);
4159 FunctionArgList FunctionArgs;
4162 buildThisParam(CGF, FunctionArgs);
4166 ImplicitParamDecl SrcParam(
4167 getContext(),
nullptr, SourceLocation(),
4168 &getContext().Idents.get(
"src"),
4169 getContext().getLValueReferenceType(RecordTy,
4171 ImplicitParamKind::Other);
4173 FunctionArgs.push_back(&SrcParam);
4178 ImplicitParamDecl IsMostDerived(getContext(),
nullptr,
4180 &getContext().Idents.get(
"is_most_derived"),
4181 getContext().IntTy, ImplicitParamKind::Other);
4184 FunctionArgs.push_back(&IsMostDerived);
4189 FunctionArgs, CD->
getLocation(), SourceLocation());
4192 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
4193 llvm::Value *
This = getThisValue(CGF);
4195 llvm::Value *SrcVal =
4209 SmallVector<const Stmt *, 4> ArgVec;
4210 ArrayRef<ParmVarDecl *> params = CD->
parameters().drop_front(IsCopy ? 1 : 0);
4211 for (
const ParmVarDecl *PD : params) {
4212 assert(PD->hasDefaultArg() &&
"ctor closure lacks default args");
4213 ArgVec.push_back(PD->getDefaultArg());
4216 CodeGenFunction::RunCleanupsScope Cleanups(CGF);
4218 const auto *FPT = CD->
getType()->
castAs<FunctionProtoType>();
4219 CGF.
EmitCallArgs(Args, FPT, llvm::ArrayRef(ArgVec), CD, IsCopy ? 1 : 0);
4222 AddedStructorArgCounts ExtraArgs =
4227 llvm::Constant *CalleePtr =
4232 Args, CD,
Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix);
4233 CGF.
EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args);
4235 Cleanups.ForceCleanup();
4244llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType
T,
4246 int32_t VBPtrOffset,
4251 const CXXConstructorDecl *CD =
4258 uint32_t Size = getContext().getTypeSizeInChars(
T).getQuantity();
4259 SmallString<256> MangledName;
4261 llvm::raw_svector_ostream
Out(MangledName);
4262 getMangleContext().mangleCXXCatchableType(
T, CD, CT, Size, NVOffset,
4263 VBPtrOffset, VBIndex, Out);
4265 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4266 return getImageRelativeConstant(GV);
4270 llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(
T));
4274 llvm::Constant *CopyCtor;
4281 CopyCtor = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4283 CopyCtor = getImageRelativeConstant(CopyCtor);
4285 bool IsScalar = !RD;
4286 bool HasVirtualBases =
false;
4287 bool IsStdBadAlloc =
false;
4288 QualType PointeeType =
T;
4302 if (HasVirtualBases)
4307 llvm::Constant *Fields[] = {
4308 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4310 llvm::ConstantInt::get(CGM.
IntTy, NVOffset),
4311 llvm::ConstantInt::getSigned(CGM.
IntTy, VBPtrOffset),
4312 llvm::ConstantInt::get(CGM.
IntTy, VBIndex),
4313 llvm::ConstantInt::get(CGM.
IntTy, Size),
4316 llvm::StructType *CTType = getCatchableTypeType();
4317 auto *GV =
new llvm::GlobalVariable(
4318 CGM.
getModule(), CTType,
true, getLinkageForRTTI(
T),
4319 llvm::ConstantStruct::get(CTType, Fields), MangledName);
4320 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4321 GV->setSection(
".xdata");
4322 if (GV->isWeakForLinker())
4323 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4324 return getImageRelativeConstant(GV);
4327llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType
T) {
4331 llvm::GlobalVariable *&CTA = CatchableTypeArrays[
T];
4338 llvm::SmallSetVector<llvm::Constant *, 2> CatchableTypes;
4348 const CXXRecordDecl *MostDerivedClass =
nullptr;
4356 if (MostDerivedClass) {
4357 const ASTContext &Context = getContext();
4358 const ASTRecordLayout &MostDerivedLayout =
4361 SmallVector<MSRTTIClass, 8> Classes;
4363 Classes.front().initialize(
nullptr,
nullptr);
4365 for (
const MSRTTIClass &
Class : Classes) {
4368 (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous))
4373 if (
Class.VirtualRoot) {
4384 CatchableTypes.insert(getCatchableType(RTTITy,
Class.OffsetInVBase,
4385 VBPtrOffset, OffsetInVBTable));
4393 CatchableTypes.insert(getCatchableType(
T));
4406 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4417 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4419 uint32_t NumEntries = CatchableTypes.size();
4420 llvm::Type *CTType = getImageRelativeType(CGM.
DefaultPtrTy);
4421 llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries);
4422 llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries);
4423 llvm::Constant *Fields[] = {
4424 llvm::ConstantInt::get(CGM.
IntTy, NumEntries),
4425 llvm::ConstantArray::get(
4426 AT, llvm::ArrayRef(CatchableTypes.begin(),
4427 CatchableTypes.end()))
4429 SmallString<256> MangledName;
4431 llvm::raw_svector_ostream
Out(MangledName);
4432 getMangleContext().mangleCXXCatchableTypeArray(
T, NumEntries, Out);
4434 CTA =
new llvm::GlobalVariable(
4435 CGM.
getModule(), CTAType,
true, getLinkageForRTTI(
T),
4436 llvm::ConstantStruct::get(CTAType, Fields), MangledName);
4437 CTA->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4438 CTA->setSection(
".xdata");
4439 if (CTA->isWeakForLinker())
4440 CTA->setComdat(CGM.
getModule().getOrInsertComdat(CTA->getName()));
4444llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(QualType
T) {
4445 bool IsConst, IsVolatile, IsUnaligned;
4450 llvm::GlobalVariable *CTA = getCatchableTypeArray(
T);
4457 ->getLimitedValue();
4459 SmallString<256> MangledName;
4461 llvm::raw_svector_ostream
Out(MangledName);
4462 getMangleContext().mangleCXXThrowInfo(
T, IsConst, IsVolatile, IsUnaligned,
4468 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4484 llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4487 if (!DtorD->isTrivial())
4490 llvm::Constant *ForwardCompat =
4491 getImageRelativeConstant(llvm::Constant::getNullValue(CGM.
Int8PtrTy));
4492 llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant(CTA);
4493 llvm::StructType *TIType = getThrowInfoType();
4494 llvm::Constant *Fields[] = {
4495 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4496 getImageRelativeConstant(CleanupFn),
4498 PointerToCatchableTypes
4500 auto *GV =
new llvm::GlobalVariable(
4501 CGM.
getModule(), TIType,
true, getLinkageForRTTI(
T),
4502 llvm::ConstantStruct::get(TIType, Fields), MangledName.str());
4503 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4504 GV->setSection(
".xdata");
4505 if (GV->isWeakForLinker())
4506 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4510void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF,
const CXXThrowExpr *E) {
4512 assert(SubExpr &&
"SubExpr cannot be null");
4513 QualType ThrowType = SubExpr->
getType();
4522 llvm::GlobalVariable *TI = getThrowInfo(ThrowType);
4529std::pair<llvm::Value *, const CXXRecordDecl *>
4530MicrosoftCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This,
4531 const CXXRecordDecl *RD) {
4533 std::tie(This, std::ignore, RD) = performBaseAdjustment(CGF, This,
T);
4537bool MicrosoftCXXABI::isPermittedToBeHomogeneousAggregate(
4538 const CXXRecordDecl *RD)
const {
4568 for (
const CXXBaseSpecifier &B : RD->
bases()) {
4569 if (
const CXXRecordDecl *FRD = B.getType()->getAsCXXRecordDecl()) {
4570 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...