31#include "llvm/ADT/StringExtras.h"
32#include "llvm/ADT/StringSet.h"
33#include "llvm/IR/Intrinsics.h"
36using namespace CodeGen;
41struct VBTableGlobals {
46class MicrosoftCXXABI :
public CGCXXABI {
49 :
CGCXXABI(CGM), BaseClassDescriptorType(nullptr),
50 ClassHierarchyDescriptorType(nullptr),
51 CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr),
52 ThrowInfoType(nullptr) {
55 "visibility export mapping option unimplemented in this ABI");
70 if (isa<CXXDestructorDecl>(GD.
getDecl())) {
79 case Dtor_Comdat: llvm_unreachable(
"emitting dtor comdat as function?");
81 llvm_unreachable(
"bad dtor kind");
90 assert(Args.size() >= 2 &&
91 "expected the arglist to have at least two args!");
101 std::vector<CharUnits> VBPtrOffsets;
105 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
106 for (
const std::unique_ptr<VPtrInfo> &VBT : *VBGlobals.VBTables) {
111 if (VBT->getVBaseWithVPtr())
113 VBPtrOffsets.push_back(Offs);
115 llvm::array_pod_sort(VBPtrOffsets.begin(), VBPtrOffsets.end());
131 llvm::GlobalVariable *getMSCompleteObjectLocator(
const CXXRecordDecl *RD,
152 llvm::Type *StdTypeInfoPtrTy)
override;
161 std::optional<ExactDynamicCastInfo>
164 llvm_unreachable(
"unsupported");
169 const ExactDynamicCastInfo &CastInfo,
170 llvm::BasicBlock *CastSuccess,
171 llvm::BasicBlock *CastFail)
override {
172 llvm_unreachable(
"unsupported");
178 llvm::BasicBlock *CastEnd)
override;
237 AddedStructorArgCounts
251 llvm::GlobalValue::LinkageTypes
258 auto *MD = cast<CXXMethodDecl>(GD.
getDecl());
260 if (MD->isVirtual()) {
262 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
266 return MD->getParent();
284 return MD->getParent();
290 bool VirtualCall)
override;
315 llvm::GlobalVariable *VTable);
326 return !VTableClass->
hasAttr<MSNoVTableAttr>();
347 DeleteOrMemberCallExpr
E,
348 llvm::CallBase **CallOrInvoke)
override;
353 "Only deleting destructor thunks are available in this ABI");
360 llvm::GlobalVariable *
362 llvm::GlobalVariable::LinkageTypes
Linkage);
364 llvm::GlobalVariable *
368 llvm::raw_svector_ostream Out(OutName);
370 StringRef MangledName = OutName.str();
372 if (
auto *VDispMap = CGM.
getModule().getNamedGlobal(MangledName))
378 llvm::PoisonValue::get(CGM.
IntTy));
379 Map[0] = llvm::ConstantInt::get(CGM.
IntTy, 0);
380 bool AnyDifferent =
false;
381 for (
const auto &I : SrcRD->
vbases()) {
382 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
388 Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.
IntTy, DstVBIndex * 4);
389 AnyDifferent |= SrcVBIndex != DstVBIndex;
395 llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.
IntTy, Map.size());
396 llvm::Constant *
Init = llvm::ConstantArray::get(VDispMapTy, Map);
397 llvm::GlobalValue::LinkageTypes
Linkage =
399 ? llvm::GlobalValue::LinkOnceODRLinkage
400 : llvm::GlobalValue::InternalLinkage;
401 auto *VDispMap =
new llvm::GlobalVariable(
408 llvm::GlobalVariable *GV)
const;
416 Thunk->setLinkage(llvm::GlobalValue::InternalLinkage);
418 Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage);
420 Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
440 LangOptions::MSVC2019_5) &&
448 llvm::GlobalVariable *DeclPtr,
449 bool PerformInit)
override;
451 llvm::FunctionCallee Dtor,
452 llvm::Constant *
Addr)
override;
483 llvm::Value *NumElements,
490 friend struct MSRTTIBuilder;
492 bool isImageRelative()
const {
497 llvm::StructType *getTypeDescriptorType(StringRef TypeInfoString) {
499 TDTypeName += llvm::utostr(TypeInfoString.size());
500 llvm::StructType *&TypeDescriptorType =
501 TypeDescriptorTypeMap[TypeInfoString.size()];
502 if (TypeDescriptorType)
503 return TypeDescriptorType;
504 llvm::Type *FieldTypes[] = {
507 llvm::ArrayType::get(CGM.
Int8Ty, TypeInfoString.size() + 1)};
509 llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes, TDTypeName);
510 return TypeDescriptorType;
513 llvm::Type *getImageRelativeType(llvm::Type *PtrType) {
514 if (!isImageRelative())
519 llvm::StructType *getBaseClassDescriptorType() {
520 if (BaseClassDescriptorType)
521 return BaseClassDescriptorType;
522 llvm::Type *FieldTypes[] = {
531 BaseClassDescriptorType = llvm::StructType::create(
533 return BaseClassDescriptorType;
536 llvm::StructType *getClassHierarchyDescriptorType() {
537 if (ClassHierarchyDescriptorType)
538 return ClassHierarchyDescriptorType;
542 ClassHierarchyDescriptorType =
543 llvm::StructType::create(FieldTypes,
"rtti.ClassHierarchyDescriptor");
544 return ClassHierarchyDescriptorType;
547 llvm::StructType *getCompleteObjectLocatorType() {
548 if (CompleteObjectLocatorType)
549 return CompleteObjectLocatorType;
550 llvm::Type *FieldTypes[] = {
556 getImageRelativeType(CGM.
VoidTy),
559 if (!isImageRelative())
560 FieldTypesRef = FieldTypesRef.drop_back();
561 CompleteObjectLocatorType =
562 llvm::StructType::create(FieldTypesRef,
"rtti.CompleteObjectLocator");
563 return CompleteObjectLocatorType;
566 llvm::GlobalVariable *getImageBase() {
567 StringRef Name =
"__ImageBase";
568 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(Name))
573 llvm::GlobalValue::ExternalLinkage,
579 llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) {
580 if (!isImageRelative())
583 if (PtrVal->isNullValue())
584 return llvm::Constant::getNullValue(CGM.
IntTy);
586 llvm::Constant *ImageBaseAsInt =
587 llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.
IntPtrTy);
588 llvm::Constant *PtrValAsInt =
589 llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.
IntPtrTy);
590 llvm::Constant *Diff =
591 llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt,
593 return llvm::ConstantExpr::getTrunc(Diff, CGM.
IntTy);
601 llvm::Constant *getZeroInt() {
602 return llvm::ConstantInt::get(CGM.
IntTy, 0);
605 llvm::Constant *getAllOnesInt() {
606 return llvm::Constant::getAllOnesValue(CGM.
IntTy);
620 llvm::Value *VBPtrOffset,
621 llvm::Value *VBTableOffset,
622 llvm::Value **VBPtr =
nullptr);
627 int32_t VBTableOffset,
628 llvm::Value **VBPtr =
nullptr) {
629 assert(VBTableOffset % 4 == 0 &&
"should be byte offset into table of i32s");
630 llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.
IntTy, VBPtrOffset),
631 *VBTOffset = llvm::ConstantInt::get(CGM.
IntTy, VBTableOffset);
632 return GetVBaseOffsetFromVBPtr(CGF,
Base, VBPOffset, VBTOffset, VBPtr);
635 std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
643 llvm::Value *VirtualBaseAdjustmentOffset,
644 llvm::Value *VBPtrOffset );
648 llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
649 bool IsMemberFunction,
652 unsigned VBTableIndex);
661 const VBTableGlobals &enumerateVBTables(
const CXXRecordDecl *RD);
664 llvm::Function *EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
677 return RD->
hasAttr<MSInheritanceAttr>();
691 bool Inequality)
override;
700 bool IsInBounds)
override;
702 llvm::Value *EmitNonNullMemberPointerConversion(
710 llvm::Value *Src)
override;
713 llvm::Constant *Src)
override;
728 llvm::StructType *getCatchableTypeType() {
729 if (CatchableTypeType)
730 return CatchableTypeType;
731 llvm::Type *FieldTypes[] = {
740 CatchableTypeType = llvm::StructType::create(
742 return CatchableTypeType;
745 llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) {
746 llvm::StructType *&CatchableTypeArrayType =
747 CatchableTypeArrayTypeMap[NumEntries];
748 if (CatchableTypeArrayType)
749 return CatchableTypeArrayType;
752 CTATypeName += llvm::utostr(NumEntries);
753 llvm::Type *CTType = getImageRelativeType(CGM.
UnqualPtrTy);
754 llvm::Type *FieldTypes[] = {
756 llvm::ArrayType::get(CTType, NumEntries)
758 CatchableTypeArrayType =
759 llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes, CTATypeName);
760 return CatchableTypeArrayType;
763 llvm::StructType *getThrowInfoType() {
765 return ThrowInfoType;
766 llvm::Type *FieldTypes[] = {
772 ThrowInfoType = llvm::StructType::create(CGM.
getLLVMContext(), FieldTypes,
774 return ThrowInfoType;
781 llvm::FunctionType *FTy =
782 llvm::FunctionType::get(CGM.
VoidTy, Args,
false);
783 llvm::FunctionCallee Throw =
787 if (
auto *Fn = dyn_cast<llvm::Function>(Throw.getCallee()))
788 Fn->setCallingConv(llvm::CallingConv::X86_StdCall);
796 llvm::Constant *getCatchableType(
QualType T,
797 uint32_t NVOffset = 0,
798 int32_t VBPtrOffset = -1,
799 uint32_t VBIndex = 0);
801 llvm::GlobalVariable *getCatchableTypeArray(
QualType T);
805 std::pair<llvm::Value *, const CXXRecordDecl *>
813 typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
814 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;
815 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;
817 VFTablesMapTy VFTablesMap;
818 VTablesMapTy VTablesMap;
825 llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap;
830 GuardInfo() =
default;
831 llvm::GlobalVariable *Guard =
nullptr;
832 unsigned BitIndex = 0;
837 llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap;
838 llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap;
839 llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap;
841 llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap;
842 llvm::StructType *BaseClassDescriptorType;
843 llvm::StructType *ClassHierarchyDescriptorType;
844 llvm::StructType *CompleteObjectLocatorType;
846 llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays;
848 llvm::StructType *CatchableTypeType;
849 llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;
850 llvm::StructType *ThrowInfoType;
856MicrosoftCXXABI::getRecordArgABI(
const CXXRecordDecl *RD)
const {
868 case llvm::Triple::thumb:
874 case llvm::Triple::x86: {
880 getContext().getTypeInfo(getContext().getCanonicalTagType(RD));
886 return RAA_DirectInMemory;
889 case llvm::Triple::x86_64:
890 case llvm::Triple::aarch64:
894 llvm_unreachable(
"invalid enum");
906 llvm::Value *MDThis = EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE,
912void MicrosoftCXXABI::emitRethrow(
CodeGenFunction &CGF,
bool isNoReturn) {
913 llvm::Value *Args[] = {llvm::ConstantPointerNull::get(CGM.
Int8PtrTy),
926 VarDecl *CatchParam = S->getExceptionDecl();
927 llvm::BasicBlock *CatchPadBB = CGF.
Builder.GetInsertBlock();
928 llvm::CatchPadInst *CPI =
929 cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHIIt());
940 CPI->setArgOperand(2,
var.getObjectAddress(CGF).emitRawPointer(CGF));
948std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
959 return std::make_tuple(
Value, llvm::ConstantInt::get(CGF.
Int32Ty, 0),
968 PolymorphicBase = BaseDecl;
972 assert(PolymorphicBase &&
"polymorphic class has no apparent vfptr?");
974 llvm::Value *Offset =
975 GetVirtualBaseClassOffset(CGF,
Value, SrcDecl, PolymorphicBase);
977 Value.getElementType(),
Value.emitRawPointer(CGF), Offset);
980 return std::make_tuple(
Address(Ptr, CGF.
Int8Ty, VBaseAlign), Offset,
984bool MicrosoftCXXABI::shouldTypeidBeNullChecked(
QualType SrcRecordTy) {
986 return !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
990 llvm::Value *Argument) {
991 llvm::Type *ArgTypes[] = {CGF.
Int8PtrTy};
992 llvm::FunctionType *FTy =
993 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false);
994 llvm::Value *Args[] = {Argument};
1000 llvm::CallBase *
Call =
1002 Call->setDoesNotReturn();
1003 CGF.
Builder.CreateUnreachable();
1009 llvm::Type *StdTypeInfoPtrTy) {
1010 std::tie(ThisPtr, std::ignore, std::ignore) =
1011 performBaseAdjustment(CGF, ThisPtr, SrcRecordTy);
1013 return CGF.
Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy);
1016bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
1020 !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
1023llvm::Value *MicrosoftCXXABI::emitDynamicCastCall(
1025 QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
1026 llvm::Value *SrcRTTI =
1028 llvm::Value *DestRTTI =
1031 llvm::Value *Offset;
1032 std::tie(
This, Offset, std::ignore) =
1033 performBaseAdjustment(CGF,
This, SrcRecordTy);
1034 llvm::Value *ThisPtr =
This.emitRawPointer(CGF);
1046 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
1048 llvm::Value *Args[] = {
1049 ThisPtr, Offset, SrcRTTI, DestRTTI,
1054llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(
CodeGenFunction &CGF,
1057 std::tie(
Value, std::ignore, std::ignore) =
1058 performBaseAdjustment(CGF,
Value, SrcRecordTy);
1062 llvm::Type *ArgTypes[] = {CGF.
Int8PtrTy};
1064 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
1066 llvm::Value *Args[] = {
Value.emitRawPointer(CGF)};
1074llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset(
1080 llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.
PtrDiffTy, VBPtrChars);
1085 llvm::Value *VBTableOffset =
1088 llvm::Value *VBPtrToNewBase =
1089 GetVBaseOffsetFromVBPtr(CGF,
This, VBPtrOffset, VBTableOffset);
1092 return CGF.
Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);
1095bool MicrosoftCXXABI::HasThisReturn(
GlobalDecl GD)
const {
1096 return isa<CXXConstructorDecl>(GD.
getDecl());
1100 return isa<CXXDestructorDecl>(GD.
getDecl()) &&
1104bool MicrosoftCXXABI::hasMostDerivedReturn(
GlobalDecl GD)
const {
1114 uint64_t NumElts = 0;
1117 isa<VectorType>(
Base)) {
1154 if (
auto *Ctor = dyn_cast<CXXConstructorDecl>(
D)) {
1155 if (Ctor->isUserProvided())
1157 }
else if (
auto *
Template = dyn_cast<FunctionTemplateDecl>(
D)) {
1158 if (isa<CXXConstructorDecl>(
Template->getTemplatedDecl()))
1160 }
else if (
auto *MethodDecl = dyn_cast<CXXMethodDecl>(
D)) {
1161 if (MethodDecl->isCopyAssignmentOperator() && MethodDecl->isDeleted())
1170bool MicrosoftCXXABI::classifyReturnType(
CGFunctionInfo &FI)
const {
1181 if (isIndirectReturn) {
1204 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1205 assert(IsMostDerivedClass &&
1206 "ctor for a class with virtual bases must have an implicit parameter");
1207 llvm::Value *IsCompleteObject =
1208 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1210 llvm::BasicBlock *CallVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.init_vbases");
1211 llvm::BasicBlock *SkipVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.skip_vbases");
1212 CGF.
Builder.CreateCondBr(IsCompleteObject,
1213 CallVbaseCtorsBB, SkipVbaseCtorsBB);
1218 EmitVBPtrStores(CGF, RD);
1222 return SkipVbaseCtorsBB;
1227 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1228 assert(IsMostDerivedClass &&
1229 "ctor for a class with virtual bases must have an implicit parameter");
1230 llvm::Value *IsCompleteObject =
1231 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1233 llvm::BasicBlock *CallVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.dtor_vbases");
1234 llvm::BasicBlock *SkipVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.skip_vbases");
1235 CGF.
Builder.CreateCondBr(IsCompleteObject,
1236 CallVbaseDtorsBB, SkipVbaseDtorsBB);
1241 return SkipVbaseDtorsBB;
1244void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
1264 llvm::Value *Int8This =
nullptr;
1267 const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl();
1268 auto I = VBaseMap.find(VBase);
1269 assert(I != VBaseMap.end());
1270 if (!I->second.hasVtorDisp())
1273 llvm::Value *VBaseOffset =
1274 GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase);
1275 uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity();
1278 llvm::Value *VtorDispValue = Builder.CreateSub(
1279 VBaseOffset, llvm::ConstantInt::get(CGM.
PtrDiffTy, ConstantVBaseOffset),
1281 VtorDispValue = Builder.CreateTruncOrBitCast(VtorDispValue, CGF.
Int32Ty);
1284 Int8This = getThisValue(CGF);
1286 llvm::Value *VtorDispPtr =
1287 Builder.CreateInBoundsGEP(CGF.
Int8Ty, Int8This, VBaseOffset);
1289 VtorDispPtr = Builder.CreateConstGEP1_32(CGF.
Int8Ty, VtorDispPtr, -4);
1291 Builder.CreateAlignedStore(VtorDispValue, VtorDispPtr,
1302 return ExpectedCallingConv == ActualCallingConv;
1313 if (
D->
hasAttr<DLLExportAttr>() &&
D->isDefaultConstructor() &&
1317 Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1330 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
1331 for (
unsigned I = 0,
E = VBGlobals.VBTables->size(); I !=
E; ++I) {
1332 const std::unique_ptr<VPtrInfo> &VBT = (*VBGlobals.VBTables)[I];
1333 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
1338 if (VBT->getVBaseWithVPtr())
1341 llvm::Value *GVPtr =
1349MicrosoftCXXABI::buildStructorSignature(
GlobalDecl GD,
1351 AddedStructorArgCounts Added;
1353 if (isa<CXXDestructorDecl>(GD.
getDecl()) &&
1356 ArgTys.push_back(getContext().IntTy);
1359 auto *CD = dyn_cast<CXXConstructorDecl>(GD.
getDecl());
1368 if (
Class->getNumVBases()) {
1370 ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy);
1373 ArgTys.push_back(getContext().IntTy);
1381void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
1387 GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
1394llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(
1399 return llvm::GlobalValue::InternalLinkage;
1410 if (Dtor->
hasAttr<DLLExportAttr>())
1411 return llvm::GlobalValue::WeakODRLinkage;
1412 if (Dtor->
hasAttr<DLLImportAttr>())
1413 return llvm::GlobalValue::AvailableExternallyLinkage;
1414 return llvm::GlobalValue::LinkOnceODRLinkage;
1419 return llvm::GlobalValue::LinkOnceODRLinkage;
1421 llvm_unreachable(
"MS C++ ABI does not support comdat dtors");
1423 llvm_unreachable(
"invalid dtor type");
1435 if (
D->getParent()->getNumVBases() > 0 &&
D->
hasAttr<DLLExportAttr>())
1440MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(
GlobalDecl GD) {
1462 if (isa<CXXDestructorDecl>(MD))
1467 getContext().getASTRecordLayout(MD->
getParent());
1474Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
1480 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD);
1515 Result = Result.withElementType(CGF.
Int8Ty);
1519 llvm::Value *VBaseOffset =
1520 GetVirtualBaseClassOffset(CGF, Result, Derived, VBase);
1522 Result.getElementType(), Result.emitRawPointer(CGF), VBaseOffset);
1527 if (!StaticOffset.
isZero()) {
1529 Result = Result.withElementType(CGF.
Int8Ty);
1548 assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
1553 ImplicitParamKind::Other);
1558 Params.insert(Params.begin() + 1, IsMostDerived);
1560 Params.push_back(IsMostDerived);
1561 getStructorImplicitParamDecl(CGF) = IsMostDerived;
1566 ImplicitParamKind::Other);
1567 Params.push_back(ShouldDelete);
1568 getStructorImplicitParamDecl(CGF) = ShouldDelete;
1572void MicrosoftCXXABI::EmitInstanceFunctionProlog(
CodeGenFunction &CGF) {
1589 llvm::Value *
This = loadIncomingCXXThis(CGF);
1592 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.
CurGD);
1593 if (!Adjustment.
isZero()) {
1599 setCXXABIThisValue(CGF,
This);
1609 if (HasThisReturn(CGF.
CurGD) || hasMostDerivedReturn(CGF.
CurGD))
1613 assert(getStructorImplicitParamDecl(CGF) &&
1614 "no implicit parameter for a constructor with virtual bases?");
1615 getStructorImplicitParamValue(CGF)
1622 assert(getStructorImplicitParamDecl(CGF) &&
1623 "no implicit parameter for a deleting destructor?");
1624 getStructorImplicitParamValue(CGF)
1627 "should_call_delete");
1637 if (!
D->getParent()->getNumVBases())
1638 return AddedStructorArgs{};
1642 llvm::Value *MostDerivedArg;
1644 MostDerivedArg = getStructorImplicitParamValue(CGF);
1649 return AddedStructorArgs::prefix({{MostDerivedArg, getContext().IntTy}});
1651 return AddedStructorArgs::suffix({{MostDerivedArg, getContext().IntTy}});
1654llvm::Value *MicrosoftCXXABI::getCXXDestructorImplicitParam(
1675 assert(
Type != CXXDtorType::Dtor_Deleting &&
1676 "The deleting destructor should only be called via a virtual call");
1681 llvm::BasicBlock *BaseDtorEndBB =
nullptr;
1682 if (ForVirtualBase && isa<CXXConstructorDecl>(CGF.
CurCodeDecl)) {
1683 BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF);
1693 if (BaseDtorEndBB) {
1695 CGF.
Builder.CreateBr(BaseDtorEndBB);
1700void MicrosoftCXXABI::emitVTableTypeMetadata(
const VPtrInfo &Info,
1702 llvm::GlobalVariable *VTable) {
1713 llvm::DenseSet<const CXXRecordDecl *>
Visited;
1714 llvm::GlobalObject::VCallVisibility TypeVis =
1716 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1717 VTable->setVCallVisibilityMetadata(TypeVis);
1724 getContext().getLangOpts().RTTIData
1725 ? getContext().toCharUnitsFromBits(
1726 getContext().getTargetInfo().getPointerWidth(LangAS::Default))
1745 getContext().getASTRecordLayout(DerivedRD);
1751 Offset = VBI->second.VBaseOffset;
1752 if (!Offset.isZero())
1767 for (
const std::unique_ptr<VPtrInfo>& Info : VFPtrs) {
1768 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->
FullOffsetInMDC);
1769 if (VTable->hasInitializer())
1775 llvm::Constant *RTTI =
nullptr;
1778 RTTI = getMSCompleteObjectLocator(RD, *Info);
1781 auto components = builder.beginStruct();
1783 VTable->hasLocalLinkage());
1784 components.finishAndSetAsInitializer(VTable);
1786 emitVTableTypeMetadata(*Info, RD, VTable);
1790bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField(
1795llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
1798 llvm::Constant *VTableAddressPoint = getVTableAddressPoint(
Base, VTableClass);
1799 if (!VTableAddressPoint) {
1800 assert(
Base.getBase()->getNumVBases() &&
1801 !getContext().getASTRecordLayout(
Base.getBase()).hasOwnVFPtr());
1803 return VTableAddressPoint;
1809 llvm::raw_svector_ostream Out(Name);
1816 (void)getAddrOfVTable(VTableClass,
Base.getBaseOffset());
1817 VFTableIdTy
ID(VTableClass,
Base.getBaseOffset());
1818 return VFTablesMap[
ID];
1821llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(
const CXXRecordDecl *RD,
1827 VFTableIdTy
ID(RD, VPtrOffset);
1828 auto [I, Inserted] = VTablesMap.try_emplace(ID);
1832 llvm::GlobalVariable *&VTable = I->second;
1837 if (DeferredVFTables.insert(RD).second) {
1845 llvm::StringSet<> ObservedMangledNames;
1846 for (
const auto &VFPtr : VFPtrs) {
1849 if (!ObservedMangledNames.insert(Name.str()).second)
1850 llvm_unreachable(
"Already saw this mangling before?");
1855 const std::unique_ptr<VPtrInfo> *VFPtrI =
1856 llvm::find_if(VFPtrs, [&](
const std::unique_ptr<VPtrInfo> &VPI) {
1857 return VPI->FullOffsetInMDC == VPtrOffset;
1859 if (VFPtrI == VFPtrs.end()) {
1860 VFTablesMap[
ID] =
nullptr;
1863 const std::unique_ptr<VPtrInfo> &VFPtr = *VFPtrI;
1875 llvm::GlobalValue::LinkageTypes VFTableLinkage =
1876 RD->
hasAttr<DLLImportAttr>() ? llvm::GlobalValue::LinkOnceODRLinkage
1878 bool VFTableComesFromAnotherTU =
1879 llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) ||
1880 llvm::GlobalValue::isExternalLinkage(VFTableLinkage);
1881 bool VTableAliasIsRequred =
1882 !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData;
1884 if (llvm::GlobalValue *VFTable =
1885 CGM.
getModule().getNamedGlobal(VFTableName)) {
1886 VFTablesMap[
ID] = VFTable;
1887 VTable = VTableAliasIsRequred
1888 ? cast<llvm::GlobalVariable>(
1889 cast<llvm::GlobalAlias>(VFTable)->getAliaseeObject())
1890 :
cast<
llvm::GlobalVariable>(VFTable);
1896 llvm::GlobalValue::LinkageTypes VTableLinkage =
1897 VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage;
1899 StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str();
1905 llvm::GlobalValue *VFTable;
1906 VTable =
new llvm::GlobalVariable(CGM.
getModule(), VTableType,
1907 true, VTableLinkage,
1908 nullptr, VTableName);
1909 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1911 llvm::Comdat *
C =
nullptr;
1912 if (!VFTableComesFromAnotherTU &&
1913 llvm::GlobalValue::isWeakForLinker(VFTableLinkage))
1914 C = CGM.
getModule().getOrInsertComdat(VFTableName.str());
1919 if (VTableAliasIsRequred) {
1920 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.
Int32Ty, 0),
1921 llvm::ConstantInt::get(CGM.
Int32Ty, 0),
1922 llvm::ConstantInt::get(CGM.
Int32Ty, 1)};
1925 llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr(
1926 VTable->getValueType(), VTable, GEPIndices);
1927 if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) {
1928 VFTableLinkage = llvm::GlobalValue::ExternalLinkage;
1930 C->setSelectionKind(llvm::Comdat::Largest);
1932 VFTable = llvm::GlobalAlias::create(CGM.
Int8PtrTy,
1934 VFTableName.str(), VTableGEP,
1936 VFTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1945 VTable->setComdat(
C);
1947 if (RD->
hasAttr<DLLExportAttr>())
1948 VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1950 VFTablesMap[
ID] = VFTable;
1963 adjustThisArgumentForVirtualFunctionCall(CGF, GD,
This,
true);
1965 auto *MethodDecl = cast<CXXMethodDecl>(GD.
getDecl());
1966 llvm::Value *VTable =
1974 auto getObjectWithVPtr = [&] {
1977 [&](
const std::unique_ptr<VPtrInfo> &Info) {
1978 return Info->FullOffsetInMDC == ML.VFPtrOffset;
1987 getObjectWithVPtr(), VTable, Ty,
1995 llvm::Value *VFuncPtr =
1996 Builder.CreateConstInBoundsGEP1_64(Ty, VTable, ML.
Index,
"vfn");
1997 VFunc = Builder.CreateAlignedLoad(Ty, VFuncPtr, CGF.
getPointerAlign());
2004llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
2006 Address This, DeleteOrMemberCallExpr
E, llvm::CallBase **CallOrInvoke) {
2007 auto *CE = dyn_cast<const CXXMemberCallExpr *>(
E);
2008 auto *
D = dyn_cast<const CXXDeleteExpr *>(
E);
2009 assert((CE !=
nullptr) ^ (
D !=
nullptr));
2010 assert(CE ==
nullptr || CE->arguments().empty());
2022 llvm::Value *ImplicitParam = llvm::ConstantInt::get(
2028 ThisTy = CE->getObjectType();
2030 ThisTy =
D->getDestroyedType();
2033 This = adjustThisArgumentForVirtualFunctionCall(CGF, GD,
This,
true);
2036 ImplicitParam, Context.
IntTy, CE, CallOrInvoke);
2040const VBTableGlobals &
2041MicrosoftCXXABI::enumerateVBTables(
const CXXRecordDecl *RD) {
2044 auto [Entry, Added] = VBTablesMap.try_emplace(RD);
2045 VBTableGlobals &VBGlobals = Entry->second;
2050 VBGlobals.VBTables = &Context.enumerateVBTables(RD);
2055 for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(),
2056 E = VBGlobals.VBTables->end();
2058 VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD,
Linkage));
2065MicrosoftCXXABI::EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
2067 assert(!isa<CXXConstructorDecl>(MD) && !isa<CXXDestructorDecl>(MD) &&
2068 "can't form pointers to ctors or virtual dtors");
2072 llvm::raw_svector_ostream Out(ThunkName);
2073 getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out);
2076 if (llvm::GlobalValue *GV = CGM.
getModule().getNamedValue(ThunkName))
2077 return cast<llvm::Function>(GV);
2083 llvm::Function *ThunkFn =
2084 llvm::Function::Create(ThunkTy, llvm::Function::ExternalLinkage,
2086 assert(ThunkFn->getName() == ThunkName &&
"name was uniqued!");
2089 ? llvm::GlobalValue::LinkOnceODRLinkage
2090 : llvm::GlobalValue::InternalLinkage);
2092 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
2101 ThunkFn->addFnAttr(
"thunk");
2104 ThunkFn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
2114 buildThisParam(CGF, FunctionArgs);
2121 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
2126 llvm::Value *VTable =
2129 llvm::Value *VFuncPtr = CGF.
Builder.CreateConstInBoundsGEP1_64(
2130 ThunkPtrTy, VTable, ML.
Index,
"vfn");
2139void MicrosoftCXXABI::emitVirtualInheritanceTables(
const CXXRecordDecl *RD) {
2140 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
2141 for (
unsigned I = 0,
E = VBGlobals.VBTables->size(); I !=
E; ++I) {
2142 const std::unique_ptr<VPtrInfo>& VBT = (*VBGlobals.VBTables)[I];
2143 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
2144 if (GV->isDeclaration())
2145 emitVBTableDefinition(*VBT, RD, GV);
2149llvm::GlobalVariable *
2151 llvm::GlobalVariable::LinkageTypes
Linkage) {
2153 llvm::raw_svector_ostream Out(OutName);
2154 getMangleContext().mangleCXXVBTable(RD, VBT.
MangledPath, Out);
2155 StringRef Name = OutName.str();
2157 llvm::ArrayType *VBTableType =
2160 assert(!CGM.
getModule().getNamedGlobal(Name) &&
2161 "vbtable with this name already exists: mangling bug?");
2166 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2168 if (RD->
hasAttr<DLLImportAttr>())
2169 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2170 else if (RD->
hasAttr<DLLExportAttr>())
2171 GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2173 if (!GV->hasExternalLinkage())
2174 emitVBTableDefinition(VBT, RD, GV);
2179void MicrosoftCXXABI::emitVBTableDefinition(
const VPtrInfo &VBT,
2181 llvm::GlobalVariable *GV)
const {
2185 "should only emit vbtables for classes with vbtables");
2189 const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD);
2196 Offsets[0] = llvm::ConstantInt::get(CGM.
IntTy, -VBPtrOffset.
getQuantity());
2199 for (
const auto &I : ObjectWithVPtr->
vbases()) {
2200 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
2202 assert(!Offset.isNegative());
2207 CompleteVBPtrOffset +=
2209 Offset -= CompleteVBPtrOffset;
2211 unsigned VBIndex = Context.getVBTableIndex(ObjectWithVPtr, VBase);
2212 assert(Offsets[VBIndex] ==
nullptr &&
"The same vbindex seen twice?");
2213 Offsets[VBIndex] = llvm::ConstantInt::get(CGM.
IntTy, Offset.getQuantity());
2216 assert(Offsets.size() ==
2217 cast<llvm::ArrayType>(GV->getValueType())->getNumElements());
2218 llvm::ArrayType *VBTableType =
2219 llvm::ArrayType::get(CGM.
IntTy, Offsets.size());
2220 llvm::Constant *
Init = llvm::ConstantArray::get(VBTableType, Offsets);
2221 GV->setInitializer(
Init);
2223 if (RD->
hasAttr<DLLImportAttr>())
2224 GV->setLinkage(llvm::GlobalVariable::AvailableExternallyLinkage);
2227llvm::Value *MicrosoftCXXABI::performThisAdjustment(
2232 return This.emitRawPointer(CGF);
2238 V =
This.emitRawPointer(CGF);
2248 CGF.
Builder.CreateNeg(VtorDisp));
2261 llvm::Value *VBaseOffset = GetVBaseOffsetFromVBPtr(
2280llvm::Value *MicrosoftCXXABI::performReturnAdjustment(
2285 return Ret.emitRawPointer(CGF);
2289 llvm::Value *
V =
Ret.emitRawPointer(CGF);
2294 llvm::Value *VBaseOffset =
2313bool MicrosoftCXXABI::requiresArrayCookie(
const CXXNewExpr *
expr) {
2316 return expr->getAllocatedType().isDestructedType();
2327llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(
CodeGenFunction &CGF,
2336 llvm::Value *numElements,
2339 assert(requiresArrayCookie(
expr));
2342 CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
2357 llvm::FunctionCallee Dtor,
2358 llvm::Constant *
Addr) {
2363 llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get(
2364 CGF.
IntTy, DtorStub->getType(),
false);
2367 TLRegDtorTy,
"__tlregdtor", llvm::AttributeList(),
true);
2368 if (llvm::Function *TLRegDtorFn =
2369 dyn_cast<llvm::Function>(TLRegDtor.getCallee()))
2370 TLRegDtorFn->setDoesNotThrow();
2376 llvm::FunctionCallee Dtor,
2377 llvm::Constant *
Addr) {
2392void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
2396 if (CXXThreadLocalInits.empty())
2401 ?
"/include:___dyn_tls_init@12"
2402 :
"/include:__dyn_tls_init");
2407 auto AddToXDU = [&CGM](llvm::Function *InitFunc) {
2408 llvm::GlobalVariable *InitFuncPtr =
new llvm::GlobalVariable(
2409 CGM.
getModule(), InitFunc->getType(),
true,
2410 llvm::GlobalVariable::InternalLinkage, InitFunc,
2411 Twine(InitFunc->getName(),
"$initializer$"));
2412 InitFuncPtr->setSection(
".CRT$XDU");
2419 std::vector<llvm::Function *> NonComdatInits;
2420 for (
size_t I = 0,
E = CXXThreadLocalInitVars.size(); I !=
E; ++I) {
2421 llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>(
2423 llvm::Function *F = CXXThreadLocalInits[I];
2426 if (llvm::Comdat *
C = GV->getComdat())
2427 AddToXDU(F)->setComdat(
C);
2429 NonComdatInits.push_back(F);
2432 if (!NonComdatInits.empty()) {
2433 llvm::FunctionType *FTy =
2434 llvm::FunctionType::get(CGM.
VoidTy,
false);
2450 llvm::Constant *TlsGuardConstant =
2452 llvm::GlobalValue *TlsGuard = cast<llvm::GlobalValue>(TlsGuardConstant);
2454 TlsGuard->setThreadLocal(
true);
2462 llvm::FunctionType *FTy =
2463 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()), {},
2466 FTy,
"__dyn_tls_on_demand_init",
2468 llvm::AttributeList::FunctionIndex,
2469 llvm::Attribute::NoUnwind),
2474 llvm::BasicBlock *DynInitBB,
2475 llvm::BasicBlock *ContinueBB) {
2476 llvm::LoadInst *TlsGuardValue =
2478 llvm::Value *CmpResult =
2480 CGF.
Builder.CreateCondBr(CmpResult, DynInitBB, ContinueBB);
2484 llvm::GlobalValue *TlsGuard,
2485 llvm::BasicBlock *ContinueBB) {
2487 llvm::Function *InitializerFunction =
2489 llvm::CallInst *CallVal = CGF.
Builder.CreateCall(InitializerFunction);
2490 CallVal->setCallingConv(InitializerFunction->getCallingConv());
2492 CGF.
Builder.CreateBr(ContinueBB);
2496 llvm::BasicBlock *DynInitBB =
2498 llvm::BasicBlock *ContinueBB =
2504 CGF.
Builder.SetInsertPoint(DynInitBB);
2506 CGF.
Builder.SetInsertPoint(ContinueBB);
2529 AlignmentSource::Decl)
2535 StringRef VarName(
"_Init_thread_epoch");
2537 if (
auto *GV = CGM.
getModule().getNamedGlobal(VarName))
2539 auto *GV =
new llvm::GlobalVariable(
2541 false, llvm::GlobalVariable::ExternalLinkage,
2543 nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel);
2549 llvm::FunctionType *FTy =
2550 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2553 FTy,
"_Init_thread_header",
2555 llvm::AttributeList::FunctionIndex,
2556 llvm::Attribute::NoUnwind),
2561 llvm::FunctionType *FTy =
2562 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2565 FTy,
"_Init_thread_footer",
2567 llvm::AttributeList::FunctionIndex,
2568 llvm::Attribute::NoUnwind),
2573 llvm::FunctionType *FTy =
2574 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2577 FTy,
"_Init_thread_abort",
2579 llvm::AttributeList::FunctionIndex,
2580 llvm::Attribute::NoUnwind),
2588 ResetGuardBit(
Address Guard,
unsigned GuardNum)
2589 : Guard(Guard), GuardNum(GuardNum) {}
2595 llvm::LoadInst *LI = Builder.CreateLoad(Guard);
2596 llvm::ConstantInt *Mask =
2597 llvm::ConstantInt::get(CGF.
IntTy, ~(1ULL << GuardNum));
2598 Builder.CreateStore(Builder.CreateAnd(LI, Mask), Guard);
2604 CallInitThreadAbort(
RawAddress Guard) : Guard(Guard.getPointer()) {}
2614 llvm::GlobalVariable *GV,
2617 if (!
D.isStaticLocal()) {
2618 assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage());
2620 llvm::Function *F = CGF.
CurFn;
2621 F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
2622 F->setComdat(CGM.
getModule().getOrInsertComdat(F->getName()));
2627 bool ThreadlocalStatic =
D.getTLSKind();
2628 bool ThreadsafeStatic = getContext().
getLangOpts().ThreadsafeStatics;
2632 bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic;
2635 llvm::IntegerType *GuardTy = CGF.
Int32Ty;
2636 llvm::ConstantInt *
Zero = llvm::ConstantInt::get(GuardTy, 0);
2640 GuardInfo *GI =
nullptr;
2641 if (ThreadlocalStatic)
2643 else if (!ThreadsafeStatic)
2646 llvm::GlobalVariable *GuardVar = GI ? GI->Guard :
nullptr;
2648 if (
D.isExternallyVisible()) {
2651 GuardNum = getContext().getStaticLocalNumber(&
D);
2652 assert(GuardNum > 0);
2654 }
else if (HasPerVariableGuard) {
2658 GuardNum = GI->BitIndex++;
2661 if (!HasPerVariableGuard && GuardNum >= 32) {
2662 if (
D.isExternallyVisible())
2663 ErrorUnsupportedABI(CGF,
"more than 32 guarded initializations");
2672 llvm::raw_svector_ostream Out(GuardName);
2673 if (HasPerVariableGuard)
2674 getMangleContext().mangleThreadSafeStaticGuardVariable(&
D, GuardNum,
2677 getMangleContext().mangleStaticGuardVariable(&
D, Out);
2683 new llvm::GlobalVariable(CGM.
getModule(), GuardTy,
false,
2684 GV->getLinkage(),
Zero, GuardName.str());
2685 GuardVar->setVisibility(GV->getVisibility());
2686 GuardVar->setDLLStorageClass(GV->getDLLStorageClass());
2687 GuardVar->setAlignment(GuardAlign.
getAsAlign());
2688 if (GuardVar->isWeakForLinker())
2689 GuardVar->setComdat(
2690 CGM.
getModule().getOrInsertComdat(GuardVar->getName()));
2693 if (GI && !HasPerVariableGuard)
2694 GI->Guard = GuardVar;
2699 assert(GuardVar->getLinkage() == GV->getLinkage() &&
2700 "static local from the same function had different linkage");
2702 if (!HasPerVariableGuard) {
2710 llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum);
2711 llvm::LoadInst *LI = Builder.CreateLoad(GuardAddr);
2712 llvm::Value *NeedsInit =
2713 Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit),
Zero);
2717 CodeGenFunction::GuardKind::VariableGuard, &
D);
2722 Builder.CreateStore(Builder.CreateOr(LI, Bit), GuardAddr);
2726 Builder.CreateBr(EndBlock);
2744 llvm::LoadInst *FirstGuardLoad = Builder.CreateLoad(GuardAddr);
2745 FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2746 llvm::LoadInst *InitThreadEpoch =
2748 llvm::Value *IsUninitialized =
2749 Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch);
2753 CodeGenFunction::GuardKind::VariableGuard, &
D);
2759 GuardAddr.getPointer());
2760 llvm::LoadInst *SecondGuardLoad = Builder.CreateLoad(GuardAddr);
2761 SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2762 llvm::Value *ShouldDoInit =
2763 Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt());
2765 Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock);
2773 GuardAddr.getPointer());
2774 Builder.CreateBr(EndBlock);
2803 fields.push_back(CGM.
IntTy);
2807 fields.push_back(CGM.
IntTy);
2809 fields.push_back(CGM.
IntTy);
2811 fields.push_back(CGM.
IntTy);
2813 if (fields.size() == 1)
2818void MicrosoftCXXABI::
2821 assert(fields.empty());
2826 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
2829 fields.push_back(getZeroInt());
2831 fields.push_back(getAllOnesInt());
2836 fields.push_back(getZeroInt());
2838 fields.push_back(getZeroInt());
2840 fields.push_back(getAllOnesInt());
2846 GetNullMemberPointerFields(MPT, fields);
2847 if (fields.size() == 1)
2849 llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields);
2850 assert(Res->getType() == ConvertMemberPointerType(MPT));
2855MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
2856 bool IsMemberFunction,
2859 unsigned VBTableIndex) {
2868 fields.push_back(FirstField);
2871 fields.push_back(llvm::ConstantInt::get(
2877 Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
2883 fields.push_back(llvm::ConstantInt::get(CGM.
IntTy, VBTableIndex));
2885 return llvm::ConstantStruct::getAnon(fields);
2894llvm::Constant *MicrosoftCXXABI::EmitMemberDataPointer(
const CXXRecordDecl *RD,
2897 MSInheritanceModel::Virtual)
2898 offset -= getContext().getOffsetOfBaseWithVBPtr(RD);
2899 llvm::Constant *FirstField =
2901 return EmitFullMemberPointer(FirstField,
false, RD,
2905llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(
const APValue &MP,
2910 return EmitNullMemberPointer(DstTy);
2916 if (
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
2917 C = EmitMemberFunctionPointer(MD);
2924 const FieldDecl *FD = dyn_cast<FieldDecl>(MPD);
2926 FD = cast<FieldDecl>(*cast<IndirectFieldDecl>(MPD)->chain_begin());
2929 C = EmitMemberDataPointer(RD, FieldOffset);
2932 if (!MemberPointerPath.empty()) {
2933 const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext());
2936 std::nullopt, SrcRD)
2945 if (DerivedMember) {
2953 if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() ==
2954 Base->getCanonicalDecl())
2955 DerivedToBasePath.push_back(&BS);
2958 assert(DerivedToBasePath.size() == MemberPointerPath.size());
2960 CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer
2961 : CK_BaseToDerivedMemberPointer;
2962 C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(),
2963 DerivedToBasePath.end(),
C);
2969MicrosoftCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
2970 assert(MD->
isInstance() &&
"Member function must not be static!");
2976 unsigned VBTableIndex = 0;
2977 llvm::Constant *FirstField;
2982 if (Types.isFuncTypeConvertible(FPT)) {
2984 Ty = Types.GetFunctionType(Types.arrangeCXXMethodDeclaration(MD));
2994 FirstField = EmitVirtualMemPtrThunk(MD, ML);
2998 VBTableIndex = VTableContext.getVBTableIndex(RD, ML.
VBase) * 4;
3001 if (VBTableIndex == 0 &&
3003 MSInheritanceModel::Virtual)
3004 NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD);
3007 return EmitFullMemberPointer(FirstField,
true, RD,
3008 NonVirtualBaseAdjustment, VBTableIndex);
3023 llvm::ICmpInst::Predicate
Eq;
3024 llvm::Instruction::BinaryOps
And,
Or;
3026 Eq = llvm::ICmpInst::ICMP_NE;
3027 And = llvm::Instruction::Or;
3028 Or = llvm::Instruction::And;
3030 Eq = llvm::ICmpInst::ICMP_EQ;
3031 And = llvm::Instruction::And;
3032 Or = llvm::Instruction::Or;
3041 return Builder.CreateICmp(
Eq, L, R);
3044 llvm::Value *L0 = Builder.CreateExtractValue(L, 0,
"lhs.0");
3045 llvm::Value *R0 = Builder.CreateExtractValue(R, 0,
"rhs.0");
3046 llvm::Value *Cmp0 = Builder.CreateICmp(
Eq, L0, R0,
"memptr.cmp.first");
3049 llvm::Value *Res =
nullptr;
3050 llvm::StructType *LType = cast<llvm::StructType>(L->getType());
3051 for (
unsigned I = 1,
E = LType->getNumElements(); I !=
E; ++I) {
3052 llvm::Value *LF = Builder.CreateExtractValue(L, I);
3053 llvm::Value *RF = Builder.CreateExtractValue(R, I);
3054 llvm::Value *Cmp = Builder.CreateICmp(
Eq, LF, RF,
"memptr.cmp.rest");
3056 Res = Builder.CreateBinOp(
And, Res, Cmp);
3064 llvm::Value *
Zero = llvm::Constant::getNullValue(L0->getType());
3065 llvm::Value *IsZero = Builder.CreateICmp(
Eq, L0,
Zero,
"memptr.cmp.iszero");
3066 Res = Builder.CreateBinOp(
Or, Res, IsZero);
3071 return Builder.CreateBinOp(
And, Res, Cmp0,
"memptr.cmp");
3076 llvm::Value *MemPtr,
3082 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
3084 GetNullMemberPointerFields(MPT, fields);
3085 assert(!fields.empty());
3086 llvm::Value *FirstField = MemPtr;
3087 if (MemPtr->getType()->isStructTy())
3088 FirstField = Builder.CreateExtractValue(MemPtr, 0);
3089 llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0],
"memptr.cmp0");
3097 for (
int I = 1,
E = fields.size(); I <
E; ++I) {
3098 llvm::Value *
Field = Builder.CreateExtractValue(MemPtr, I);
3099 llvm::Value *Next = Builder.CreateICmpNE(Field, fields[I],
"memptr.cmp");
3100 Res = Builder.CreateOr(Res, Next,
"memptr.tobool");
3106 llvm::Constant *Val) {
3109 llvm::Constant *FirstField = Val->getType()->isStructTy() ?
3110 Val->getAggregateElement(0
U) : Val;
3111 return FirstField->isNullValue();
3116 if (isZeroInitializable(MPT) && Val->isNullValue())
3122 GetNullMemberPointerFields(MPT, Fields);
3123 if (Fields.size() == 1) {
3124 assert(Val->getType()->isIntegerTy());
3125 return Val == Fields[0];
3129 for (I = 0,
E = Fields.size(); I !=
E; ++I) {
3130 if (Val->getAggregateElement(I) != Fields[I])
3139 llvm::Value *VBPtrOffset,
3140 llvm::Value *VBTableOffset,
3141 llvm::Value **VBPtrOut) {
3144 llvm::Value *VBPtr = Builder.CreateInBoundsGEP(
3145 CGM.
Int8Ty,
This.emitRawPointer(CGF), VBPtrOffset,
"vbptr");
3150 if (
auto CI = dyn_cast<llvm::ConstantInt>(VBPtrOffset)) {
3151 VBPtrAlign =
This.getAlignment().alignmentAtOffset(
3157 llvm::Value *VBTable =
3158 Builder.CreateAlignedLoad(CGM.
UnqualPtrTy, VBPtr, VBPtrAlign,
"vbtable");
3161 llvm::Value *VBTableIndex = Builder.CreateAShr(
3162 VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2),
3166 llvm::Value *VBaseOffs =
3167 Builder.CreateInBoundsGEP(CGM.
Int32Ty, VBTable, VBTableIndex);
3168 return Builder.CreateAlignedLoad(CGM.
Int32Ty, VBaseOffs,
3174llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(
3176 Address Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {
3179 llvm::BasicBlock *OriginalBB =
nullptr;
3180 llvm::BasicBlock *SkipAdjustBB =
nullptr;
3181 llvm::BasicBlock *VBaseAdjustBB =
nullptr;
3188 OriginalBB = Builder.GetInsertBlock();
3191 llvm::Value *IsVirtual =
3192 Builder.CreateICmpNE(VBTableOffset, getZeroInt(),
3194 Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB);
3206 "member pointer representation requires a "
3207 "complete class type for %0 to perform this expression");
3210 offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
3213 llvm::Value *VBPtr =
nullptr;
3214 llvm::Value *VBaseOffs =
3215 GetVBaseOffsetFromVBPtr(CGF,
Base, VBPtrOffset, VBTableOffset, &VBPtr);
3216 llvm::Value *AdjustedBase =
3217 Builder.CreateInBoundsGEP(CGM.
Int8Ty, VBPtr, VBaseOffs);
3220 if (VBaseAdjustBB) {
3221 Builder.CreateBr(SkipAdjustBB);
3223 llvm::PHINode *Phi = Builder.CreatePHI(CGM.
Int8PtrTy, 2,
"memptr.base");
3224 Phi->addIncoming(
Base.emitRawPointer(CGF), OriginalBB);
3225 Phi->addIncoming(AdjustedBase, VBaseAdjustBB);
3228 return AdjustedBase;
3231llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
3241 llvm::Value *FieldOffset = MemPtr;
3242 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3243 llvm::Value *VBPtrOffset =
nullptr;
3244 if (MemPtr->getType()->isStructTy()) {
3247 FieldOffset = Builder.CreateExtractValue(MemPtr, I++);
3249 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3251 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3255 if (VirtualBaseAdjustmentOffset) {
3256 Addr = AdjustVirtualBase(CGF,
E, RD,
Base, VirtualBaseAdjustmentOffset,
3263 return Builder.CreateGEP(CGF.
Int8Ty,
Addr, FieldOffset,
"memptr.offset",
3264 IsInBounds ? llvm::GEPNoWrapFlags::inBounds()
3265 : llvm::GEPNoWrapFlags::none());
3272 assert(
E->getCastKind() == CK_DerivedToBaseMemberPointer ||
3273 E->getCastKind() == CK_BaseToDerivedMemberPointer ||
3274 E->getCastKind() == CK_ReinterpretMemberPointer);
3277 if (isa<llvm::Constant>(Src))
3278 return EmitMemberPointerConversion(
E, cast<llvm::Constant>(Src));
3288 bool IsReinterpret =
E->getCastKind() == CK_ReinterpretMemberPointer;
3289 if (IsReinterpret && IsFunc)
3294 if (IsReinterpret &&
3301 llvm::Value *
IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy);
3302 llvm::Constant *DstNull = EmitNullMemberPointer(DstTy);
3306 if (IsReinterpret) {
3309 assert(Src->getType() == DstNull->getType());
3310 return Builder.CreateSelect(
IsNotNull, Src, DstNull);
3313 llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock();
3316 Builder.CreateCondBr(
IsNotNull, ConvertBB, ContinueBB);
3319 llvm::Value *Dst = EmitNonNullMemberPointerConversion(
3320 SrcTy, DstTy,
E->getCastKind(),
E->path_begin(),
E->path_end(), Src,
3323 Builder.CreateBr(ContinueBB);
3327 llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2,
"memptr.converted");
3328 Phi->addIncoming(DstNull, OriginalBB);
3329 Phi->addIncoming(Dst, ConvertBB);
3333llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion(
3343 bool IsConstant = isa<llvm::Constant>(Src);
3346 llvm::Value *FirstField = Src;
3347 llvm::Value *NonVirtualBaseAdjustment = getZeroInt();
3348 llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt();
3349 llvm::Value *VBPtrOffset = getZeroInt();
3353 FirstField = Builder.CreateExtractValue(Src, I++);
3355 NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++);
3357 VBPtrOffset = Builder.CreateExtractValue(Src, I++);
3359 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++);
3362 bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer);
3368 llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;
3375 llvm::Value *SrcVBIndexEqZero =
3376 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3377 if (SrcInheritance == MSInheritanceModel::Virtual) {
3378 if (int64_t SrcOffsetToFirstVBase =
3379 getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) {
3380 llvm::Value *UndoSrcAdjustment = Builder.CreateSelect(
3382 llvm::ConstantInt::get(CGM.
IntTy, SrcOffsetToFirstVBase),
3384 NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment);
3395 llvm::Constant *BaseClassOffset = llvm::ConstantInt::get(
3400 llvm::Value *NVDisp;
3401 if (IsDerivedToBase)
3402 NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset,
"adj");
3404 NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset,
"adj");
3406 NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt());
3410 llvm::Value *DstVBIndexEqZero = SrcVBIndexEqZero;
3413 if (llvm::GlobalVariable *VDispMap =
3414 getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) {
3415 llvm::Value *VBIndex = Builder.CreateExactUDiv(
3416 VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.
IntTy, 4));
3418 llvm::Constant *Mapping = VDispMap->getInitializer();
3419 VirtualBaseAdjustmentOffset =
3420 Mapping->getAggregateElement(cast<llvm::Constant>(VBIndex));
3422 llvm::Value *Idxs[] = {getZeroInt(), VBIndex};
3423 VirtualBaseAdjustmentOffset = Builder.CreateAlignedLoad(
3424 CGM.
IntTy, Builder.CreateInBoundsGEP(VDispMap->getValueType(),
3430 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3437 llvm::Value *DstVBPtrOffset = llvm::ConstantInt::get(
3439 getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity());
3441 Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset);
3447 if (DstInheritance == MSInheritanceModel::Virtual) {
3448 if (int64_t DstOffsetToFirstVBase =
3449 getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) {
3450 llvm::Value *DoDstAdjustment = Builder.CreateSelect(
3452 llvm::ConstantInt::get(CGM.
IntTy, DstOffsetToFirstVBase),
3454 NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment);
3463 Dst = llvm::PoisonValue::get(ConvertMemberPointerType(DstTy));
3465 Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
3467 Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++);
3469 Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++);
3471 Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++);
3477MicrosoftCXXABI::EmitMemberPointerConversion(
const CastExpr *
E,
3478 llvm::Constant *Src) {
3485 return EmitMemberPointerConversion(SrcTy, DstTy, CK,
E->path_begin(),
3486 E->path_end(), Src);
3489llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
3493 assert(CK == CK_DerivedToBaseMemberPointer ||
3494 CK == CK_BaseToDerivedMemberPointer ||
3495 CK == CK_ReinterpretMemberPointer);
3498 if (MemberPointerConstantIsNull(SrcTy, Src))
3499 return EmitNullMemberPointer(DstTy);
3504 if (CK == CK_ReinterpretMemberPointer)
3508 auto *Dst = cast<llvm::Constant>(EmitNonNullMemberPointerConversion(
3509 SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder));
3514CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
3516 llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
3528 llvm::Value *FunctionPointer = MemPtr;
3529 llvm::Value *NonVirtualBaseAdjustment =
nullptr;
3530 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3531 llvm::Value *VBPtrOffset =
nullptr;
3532 if (MemPtr->getType()->isStructTy()) {
3535 FunctionPointer = Builder.CreateExtractValue(MemPtr, I++);
3537 NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++);
3539 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3541 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3544 if (VirtualBaseAdjustmentOffset) {
3545 ThisPtrForCall = AdjustVirtualBase(CGF,
E, RD,
This,
3546 VirtualBaseAdjustmentOffset, VBPtrOffset);
3548 ThisPtrForCall =
This.emitRawPointer(CGF);
3551 if (NonVirtualBaseAdjustment)
3552 ThisPtrForCall = Builder.CreateInBoundsGEP(CGF.
Int8Ty, ThisPtrForCall,
3553 NonVirtualBaseAdjustment);
3560 return new MicrosoftCXXABI(CGM);
3594 StringRef MangledName(
"??_7type_info@@6B@");
3595 if (
auto VTable = CGM.
getModule().getNamedGlobal(MangledName))
3599 llvm::GlobalVariable::ExternalLinkage,
3600 nullptr, MangledName);
3613 IsPrivateOnPath = 1 | 8,
3617 HasHierarchyDescriptor = 64
3623 MSRTTIClass *getFirstChild() {
return this + 1; }
3624 static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
3625 return Child + 1 + Child->NumBases;
3629 uint32_t Flags, NumBases, OffsetInVBase;
3635 Flags = HasHierarchyDescriptor;
3637 VirtualRoot =
nullptr;
3641 Flags |= IsPrivate | IsPrivateOnPath;
3647 if (
Parent->Flags & IsPrivateOnPath)
3648 Flags |= IsPrivateOnPath;
3649 VirtualRoot =
Parent->VirtualRoot;
3650 OffsetInVBase =
Parent->OffsetInVBase + RD->getASTContext()
3651 .getASTRecordLayout(
Parent->RD).getBaseClassOffset(RD).getQuantity();
3655 MSRTTIClass *Child = getFirstChild();
3657 NumBases += Child->initialize(
this, &
Base) + 1;
3658 Child = getNextChild(Child);
3663static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(
QualType Ty) {
3665 case Linkage::Invalid:
3666 llvm_unreachable(
"Linkage hasn't been computed!");
3669 case Linkage::Internal:
3670 case Linkage::UniqueExternal:
3671 return llvm::GlobalValue::InternalLinkage;
3673 case Linkage::VisibleNone:
3674 case Linkage::Module:
3675 case Linkage::External:
3676 return llvm::GlobalValue::LinkOnceODRLinkage;
3678 llvm_unreachable(
"Invalid linkage!");
3684struct MSRTTIBuilder {
3686 HasBranchingHierarchy = 1,
3687 HasVirtualBranchingHierarchy = 2,
3688 HasAmbiguousBases = 4
3691 MSRTTIBuilder(MicrosoftCXXABI &ABI,
const CXXRecordDecl *RD)
3692 : CGM(ABI.CGM), Context(CGM.getContext()),
3693 VMContext(CGM.getLLVMContext()),
Module(CGM.getModule()), RD(RD),
3694 Linkage(getLinkageForRTTI(CGM.getContext().getCanonicalTagType(RD))),
3697 llvm::GlobalVariable *getBaseClassDescriptor(
const MSRTTIClass &Classes);
3698 llvm::GlobalVariable *
3700 llvm::GlobalVariable *getClassHierarchyDescriptor();
3701 llvm::GlobalVariable *getCompleteObjectLocator(
const VPtrInfo &Info);
3705 llvm::LLVMContext &VMContext;
3708 llvm::GlobalVariable::LinkageTypes
Linkage;
3709 MicrosoftCXXABI &ABI;
3718 Classes.push_back(MSRTTIClass(RD));
3729 for (MSRTTIClass *
Class = &Classes.front();
Class <= &Classes.back();) {
3730 if ((
Class->Flags & MSRTTIClass::IsVirtual) &&
3731 !VirtualBases.insert(
Class->RD).second) {
3735 if (!UniqueBases.insert(
Class->RD).second)
3736 AmbiguousBases.insert(
Class->RD);
3739 if (AmbiguousBases.empty())
3741 for (MSRTTIClass &
Class : Classes)
3742 if (AmbiguousBases.count(
Class.RD))
3743 Class.Flags |= MSRTTIClass::IsAmbiguous;
3746llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
3749 llvm::raw_svector_ostream Out(MangledName);
3750 ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
3754 if (
auto CHD =
Module.getNamedGlobal(MangledName))
3760 Classes.front().initialize(
nullptr,
nullptr);
3763 for (
const MSRTTIClass &Class : Classes) {
3764 if (
Class.RD->getNumBases() > 1)
3765 Flags |= HasBranchingHierarchy;
3768 if (
Class.Flags & MSRTTIClass::IsAmbiguous)
3769 Flags |= HasAmbiguousBases;
3771 if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)
3772 Flags |= HasVirtualBranchingHierarchy;
3775 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.
IntTy, 0),
3776 llvm::ConstantInt::get(CGM.
IntTy, 0)};
3779 auto Type = ABI.getClassHierarchyDescriptorType();
3783 if (CHD->isWeakForLinker())
3784 CHD->setComdat(CGM.
getModule().getOrInsertComdat(CHD->getName()));
3786 auto *Bases = getBaseClassArray(Classes);
3789 llvm::Constant *Fields[] = {
3790 llvm::ConstantInt::get(CGM.
IntTy, 0),
3791 llvm::ConstantInt::get(CGM.
IntTy, Flags),
3792 llvm::ConstantInt::get(CGM.
IntTy, Classes.size()),
3793 ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(
3794 Bases->getValueType(), Bases,
3797 CHD->setInitializer(llvm::ConstantStruct::get(
Type, Fields));
3801llvm::GlobalVariable *
3805 llvm::raw_svector_ostream Out(MangledName);
3806 ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out);
3814 llvm::Type *PtrType = ABI.getImageRelativeType(CGM.
UnqualPtrTy);
3815 auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
3817 new llvm::GlobalVariable(
Module, ArrType,
3819 nullptr, MangledName);
3820 if (BCA->isWeakForLinker())
3821 BCA->setComdat(CGM.
getModule().getOrInsertComdat(BCA->getName()));
3825 for (MSRTTIClass &Class : Classes)
3826 BaseClassArrayData.push_back(
3827 ABI.getImageRelativeConstant(getBaseClassDescriptor(Class)));
3828 BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType));
3829 BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData));
3833llvm::GlobalVariable *
3834MSRTTIBuilder::getBaseClassDescriptor(
const MSRTTIClass &Class) {
3839 if (
Class.VirtualRoot) {
3847 llvm::raw_svector_ostream Out(MangledName);
3848 ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor(
3849 Class.RD,
Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable,
3854 if (
auto BCD =
Module.getNamedGlobal(MangledName))
3858 auto Type = ABI.getBaseClassDescriptorType();
3861 nullptr, MangledName);
3862 if (BCD->isWeakForLinker())
3863 BCD->setComdat(CGM.
getModule().getOrInsertComdat(BCD->getName()));
3866 llvm::Constant *Fields[] = {
3867 ABI.getImageRelativeConstant(
3869 llvm::ConstantInt::get(CGM.
IntTy,
Class.NumBases),
3870 llvm::ConstantInt::get(CGM.
IntTy,
Class.OffsetInVBase),
3871 llvm::ConstantInt::get(CGM.
IntTy, VBPtrOffset),
3872 llvm::ConstantInt::get(CGM.
IntTy, OffsetInVBTable),
3873 llvm::ConstantInt::get(CGM.
IntTy,
Class.Flags),
3874 ABI.getImageRelativeConstant(
3875 MSRTTIBuilder(ABI,
Class.RD).getClassHierarchyDescriptor()),
3877 BCD->setInitializer(llvm::ConstantStruct::get(
Type, Fields));
3881llvm::GlobalVariable *
3882MSRTTIBuilder::getCompleteObjectLocator(
const VPtrInfo &Info) {
3885 llvm::raw_svector_ostream Out(MangledName);
3886 ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info.
MangledPath, Out);
3890 if (
auto COL =
Module.getNamedGlobal(MangledName))
3895 int VFPtrOffset = 0;
3901 ->second.hasVtorDisp())
3905 llvm::StructType *
Type = ABI.getCompleteObjectLocatorType();
3907 nullptr, MangledName);
3910 llvm::Constant *Fields[] = {
3911 llvm::ConstantInt::get(CGM.
IntTy, ABI.isImageRelative()),
3912 llvm::ConstantInt::get(CGM.
IntTy, OffsetToTop),
3913 llvm::ConstantInt::get(CGM.
IntTy, VFPtrOffset),
3914 ABI.getImageRelativeConstant(
3916 ABI.getImageRelativeConstant(getClassHierarchyDescriptor()),
3917 ABI.getImageRelativeConstant(COL),
3920 if (!ABI.isImageRelative())
3921 FieldsRef = FieldsRef.drop_back();
3922 COL->setInitializer(llvm::ConstantStruct::get(
Type, FieldsRef));
3923 if (COL->isWeakForLinker())
3924 COL->setComdat(CGM.
getModule().getOrInsertComdat(COL->getName()));
3929 bool &IsConst,
bool &IsVolatile,
3930 bool &IsUnaligned) {
3940 IsUnaligned =
false;
3942 if (!PointeeType.
isNull()) {
3952 MPTy->getQualifier(),
3953 MPTy->getMostRecentCXXRecordDecl());
3964MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(
QualType Type,
3969 bool IsConst, IsVolatile, IsUnaligned;
3993llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(
QualType Type) {
3996 llvm::raw_svector_ostream Out(MangledName);
3997 getMangleContext().mangleCXXRTTI(
Type, Out);
4001 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4010 llvm::raw_svector_ostream Out(TypeInfoString);
4011 getMangleContext().mangleCXXRTTIName(
Type, Out);
4015 llvm::Constant *Fields[] = {
4017 llvm::ConstantPointerNull::get(CGM.
Int8PtrTy),
4018 llvm::ConstantDataArray::getString(CGM.
getLLVMContext(), TypeInfoString)};
4019 llvm::StructType *TypeDescriptorType =
4020 getTypeDescriptorType(TypeInfoString);
4021 auto *Var =
new llvm::GlobalVariable(
4022 CGM.
getModule(), TypeDescriptorType,
false,
4023 getLinkageForRTTI(
Type),
4024 llvm::ConstantStruct::get(TypeDescriptorType, Fields),
4026 if (Var->isWeakForLinker())
4027 Var->setComdat(CGM.
getModule().getOrInsertComdat(Var->getName()));
4032llvm::GlobalVariable *
4033MicrosoftCXXABI::getMSCompleteObjectLocator(
const CXXRecordDecl *RD,
4035 return MSRTTIBuilder(*
this, RD).getCompleteObjectLocator(Info);
4038void MicrosoftCXXABI::emitCXXStructor(
GlobalDecl GD) {
4039 if (
auto *ctor = dyn_cast<CXXConstructorDecl>(GD.
getDecl())) {
4041 llvm::Function *
Fn =
4047 auto *dtor = cast<CXXDestructorDecl>(GD.
getDecl());
4053 dtor->getParent()->getNumVBases() == 0)
4064 if (
Fn->isWeakForLinker())
4065 Fn->setComdat(CGM.
getModule().getOrInsertComdat(
Fn->getName()));
4075 llvm::raw_svector_ostream Out(ThunkName);
4076 getMangleContext().mangleName(
GlobalDecl(CD, CT), Out);
4079 if (llvm::GlobalValue *GV = CGM.
getModule().getNamedValue(ThunkName))
4080 return cast<llvm::Function>(GV);
4086 CanQualType RecordTy = getContext().getCanonicalTagType(RD);
4087 llvm::Function *ThunkFn = llvm::Function::Create(
4088 ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.
getModule());
4089 ThunkFn->setCallingConv(
static_cast<llvm::CallingConv::ID
>(
4091 if (ThunkFn->isWeakForLinker())
4092 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
4103 buildThisParam(CGF, FunctionArgs);
4109 &getContext().Idents.get(
"src"),
4110 getContext().getLValueReferenceType(RecordTy,
4112 ImplicitParamKind::Other);
4114 FunctionArgs.push_back(&SrcParam);
4121 &getContext().Idents.get(
"is_most_derived"),
4122 getContext().IntTy, ImplicitParamKind::Other);
4125 FunctionArgs.push_back(&IsMostDerived);
4133 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
4134 llvm::Value *
This = getThisValue(CGF);
4136 llvm::Value *SrcVal =
4153 assert(PD->hasDefaultArg() &&
"ctor closure lacks default args");
4154 ArgVec.push_back(PD->getDefaultArg());
4163 AddedStructorArgCounts ExtraArgs =
4168 llvm::Constant *CalleePtr =
4173 Args, CD,
Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix);
4176 Cleanups.ForceCleanup();
4185llvm::Constant *MicrosoftCXXABI::getCatchableType(
QualType T,
4187 int32_t VBPtrOffset,
4199 uint32_t Size = getContext().getTypeSizeInChars(
T).getQuantity();
4202 llvm::raw_svector_ostream Out(MangledName);
4203 getMangleContext().mangleCXXCatchableType(
T, CD, CT, Size, NVOffset,
4204 VBPtrOffset, VBIndex, Out);
4206 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4207 return getImageRelativeConstant(GV);
4211 llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(
T));
4215 llvm::Constant *CopyCtor;
4222 CopyCtor = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4224 CopyCtor = getImageRelativeConstant(CopyCtor);
4226 bool IsScalar = !RD;
4227 bool HasVirtualBases =
false;
4228 bool IsStdBadAlloc =
false;
4243 if (HasVirtualBases)
4248 llvm::Constant *Fields[] = {
4249 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4251 llvm::ConstantInt::get(CGM.
IntTy, NVOffset),
4252 llvm::ConstantInt::get(CGM.
IntTy, VBPtrOffset),
4253 llvm::ConstantInt::get(CGM.
IntTy, VBIndex),
4254 llvm::ConstantInt::get(CGM.
IntTy, Size),
4257 llvm::StructType *CTType = getCatchableTypeType();
4258 auto *GV =
new llvm::GlobalVariable(
4259 CGM.
getModule(), CTType,
true, getLinkageForRTTI(
T),
4260 llvm::ConstantStruct::get(CTType, Fields), MangledName);
4261 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4262 GV->setSection(
".xdata");
4263 if (GV->isWeakForLinker())
4264 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4265 return getImageRelativeConstant(GV);
4268llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(
QualType T) {
4272 llvm::GlobalVariable *&CTA = CatchableTypeArrays[
T];
4297 if (MostDerivedClass) {
4304 Classes.front().initialize(
nullptr,
nullptr);
4306 for (
const MSRTTIClass &Class : Classes) {
4309 (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous))
4314 if (
Class.VirtualRoot) {
4325 CatchableTypes.insert(getCatchableType(RTTITy,
Class.OffsetInVBase,
4326 VBPtrOffset, OffsetInVBTable));
4334 CatchableTypes.insert(getCatchableType(
T));
4347 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4358 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4360 uint32_t NumEntries = CatchableTypes.size();
4361 llvm::Type *CTType = getImageRelativeType(CGM.
UnqualPtrTy);
4362 llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries);
4363 llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries);
4364 llvm::Constant *Fields[] = {
4365 llvm::ConstantInt::get(CGM.
IntTy, NumEntries),
4366 llvm::ConstantArray::get(
4368 CatchableTypes.end()))
4372 llvm::raw_svector_ostream Out(MangledName);
4373 getMangleContext().mangleCXXCatchableTypeArray(
T, NumEntries, Out);
4375 CTA =
new llvm::GlobalVariable(
4376 CGM.
getModule(), CTAType,
true, getLinkageForRTTI(
T),
4377 llvm::ConstantStruct::get(CTAType, Fields), MangledName);
4378 CTA->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4379 CTA->setSection(
".xdata");
4380 if (CTA->isWeakForLinker())
4381 CTA->setComdat(CGM.
getModule().getOrInsertComdat(CTA->getName()));
4385llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(
QualType T) {
4386 bool IsConst, IsVolatile, IsUnaligned;
4391 llvm::GlobalVariable *CTA = getCatchableTypeArray(
T);
4397 cast<llvm::ConstantInt>(CTA->getInitializer()->getAggregateElement(0
U))
4398 ->getLimitedValue();
4402 llvm::raw_svector_ostream Out(MangledName);
4403 getMangleContext().mangleCXXThrowInfo(
T, IsConst, IsVolatile, IsUnaligned,
4409 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4425 llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4428 if (!DtorD->isTrivial())
4431 llvm::Constant *ForwardCompat =
4432 getImageRelativeConstant(llvm::Constant::getNullValue(CGM.
Int8PtrTy));
4433 llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant(CTA);
4434 llvm::StructType *TIType = getThrowInfoType();
4435 llvm::Constant *Fields[] = {
4436 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4437 getImageRelativeConstant(CleanupFn),
4439 PointerToCatchableTypes
4441 auto *GV =
new llvm::GlobalVariable(
4442 CGM.
getModule(), TIType,
true, getLinkageForRTTI(
T),
4443 llvm::ConstantStruct::get(TIType, Fields), MangledName.str());
4444 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4445 GV->setSection(
".xdata");
4446 if (GV->isWeakForLinker())
4447 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4452 const Expr *SubExpr =
E->getSubExpr();
4453 assert(SubExpr &&
"SubExpr cannot be null");
4463 llvm::GlobalVariable *TI = getThrowInfo(ThrowType);
4470std::pair<llvm::Value *, const CXXRecordDecl *>
4474 std::tie(
This, std::ignore, RD) = performBaseAdjustment(CGF,
This,
T);
4478bool MicrosoftCXXABI::isPermittedToBeHomogeneousAggregate(
4510 if (
const CXXRecordDecl *FRD = B.getType()->getAsCXXRecordDecl()) {
4511 if (!isPermittedToBeHomogeneousAggregate(FRD))
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....
llvm::DenseSet< const void * > Visited
a trap message and trap category.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
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
CallingConv getDefaultCallingConvention(bool IsVariadic, bool IsCXXMethod) const
Retrieves the default calling convention for the current context.
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getExceptionObjectType(QualType T) const
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
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
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.
CXXCatchStmt - This represents a C++ catch block.
Represents a C++ constructor within a class.
Represents a delete expression for memory deallocation and destructor calls, e.g.
FunctionDecl * getOperatorDelete() const
bool isGlobalDelete() const
Represents a C++ destructor within a class.
Represents a 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 new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
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.
A C++ throw-expression (C++ [except.throw]).
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
const CXXBaseSpecifier *const * path_const_iterator
CharUnits - This is an opaque type for sizes expressed in character units.
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.
A scoped helper to set the current debug location to the specified location or preferred location of ...
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.
virtual bool shouldEmitExactDynamicCast(QualType DestRecordTy)=0
llvm::Value *& getStructorImplicitParamValue(CodeGenFunction &CGF)
virtual void EmitCXXConstructors(const CXXConstructorDecl *D)=0
Emit constructor variants required by this ABI.
virtual llvm::Constant * getAddrOfRTTIDescriptor(QualType Ty)=0
virtual bool hasMostDerivedReturn(GlobalDecl GD) const
virtual bool HasThisReturn(GlobalDecl GD) const
Returns true if the given constructor or destructor is one of the kinds that the ABI says returns 'th...
virtual llvm::Value * getVTableAddressPointInStructor(CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base, const CXXRecordDecl *NearestVBase)=0
Get the address point of the vtable for the given base subobject while building a constructor or a de...
virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C)=0
virtual std::vector< CharUnits > getVBPtrOffsets(const CXXRecordDecl *RD)
Gets the offsets of all the virtual base pointers in a given class.
virtual void emitRethrow(CodeGenFunction &CGF, bool isNoReturn)=0
virtual void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF, const CXXRecordDecl *RD)
Emit the code to initialize hidden members required to handle virtual inheritance,...
virtual bool isMemberPointerConvertible(const MemberPointerType *MPT) const
Return whether or not a member pointers type is convertible to an IR type.
virtual size_t getSrcArgforCopyCtor(const CXXConstructorDecl *, FunctionArgList &Args) const =0
virtual bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr)=0
Checks if ABI requires extra virtual offset for vtable field.
virtual void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, llvm::GlobalVariable *DeclPtr, bool PerformInit)=0
Emits the guarded initializer and destructor setup for the given variable, given that it couldn't be ...
virtual void EmitCXXDestructors(const CXXDestructorDecl *D)=0
Emit destructor variants required by this ABI.
virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF)=0
Emit the ABI-specific prolog for the function.
virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, CXXDtorType DT) const =0
Returns true if the given destructor type should be emitted as a linkonce delegating thunk,...
virtual CharUnits getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD)
Get the ABI-specific "this" parameter adjustment to apply in the prologue of a virtual function.
virtual void setCXXDestructorDLLStorage(llvm::GlobalValue *GV, const CXXDestructorDecl *Dtor, CXXDtorType DT) const
RecordArgABI
Specify how one should pass an argument of a record type.
virtual bool shouldTypeidBeNullChecked(QualType SrcRecordTy)=0
virtual llvm::Type * ConvertMemberPointerType(const MemberPointerType *MPT)
Find the LLVM type used to represent the given member pointer type.
virtual llvm::Value * performThisAdjustment(CodeGenFunction &CGF, Address This, const CXXRecordDecl *UnadjustedClass, const ThunkInfo &TI)=0
virtual llvm::Constant * EmitNullMemberPointer(const MemberPointerType *MPT)
Create a null member pointer of the given type.
virtual StringRef GetPureVirtualCallName()=0
Gets the pure virtual member call function.
virtual CharUnits getArrayCookieSizeImpl(QualType elementType)
Returns the extra size required in order to store the array cookie for the given type.
virtual bool isSRetParameterAfterThis() const
Returns true if the implicit 'sret' parameter comes after the implicit 'this' parameter of C++ instan...
virtual void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr)=0
Emit code to force the execution of a destructor during global teardown.
virtual std::optional< ExactDynamicCastInfo > getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy)=0
virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const =0
Determine whether it's possible to emit a vtable for RD, even though we do not know that the vtable h...
virtual StringRef GetDeletedVirtualCallName()=0
Gets the deleted virtual member call name.
virtual llvm::Value * EmitMemberPointerIsNotNull(CodeGenFunction &CGF, llvm::Value *MemPtr, const MemberPointerType *MPT)
Determine if a member pointer is non-null. Returns an i1.
virtual llvm::Value * performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const CXXRecordDecl *UnadjustedClass, const ReturnAdjustment &RA)=0
virtual LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, QualType LValType)=0
Emit a reference to a non-local thread_local variable (including triggering the initialization of all...
bool isEmittedWithConstantInitializer(const VarDecl *VD, bool InspectInitForWeakDef=false) const
Determine whether we will definitely emit this variable with a constant initializer,...
virtual llvm::Value * EmitMemberPointerComparison(CodeGenFunction &CGF, llvm::Value *L, llvm::Value *R, const MemberPointerType *MPT, bool Inequality)
Emit a comparison between two member pointers. Returns an i1.
virtual llvm::Constant * EmitMemberPointer(const APValue &MP, QualType MPT)
Create a member pointer for the given member pointer constant.
virtual llvm::Constant * getVTableAddressPoint(BaseSubobject Base, const CXXRecordDecl *VTableClass)=0
Get the address point of the vtable for the given base subobject.
virtual void addImplicitStructorParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params)=0
Insert any ABI-specific implicit parameters into the parameter list for a function.
virtual llvm::Value * readArrayCookieImpl(CodeGenFunction &IGF, Address ptr, CharUnits cookieSize)
Reads the array cookie for an allocation which is known to have one.
virtual llvm::Value * getCXXDestructorImplicitParam(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating)=0
Get the implicit (second) parameter that comes after the "this" pointer, or nullptr if there is isn't...
virtual bool requiresArrayCookie(const CXXDeleteExpr *E, QualType eltType)
virtual CatchTypeInfo getCatchAllTypeInfo()
virtual std::pair< llvm::Value *, const CXXRecordDecl * > LoadVTablePtr(CodeGenFunction &CGF, Address This, const CXXRecordDecl *RD)=0
Load a vtable from This, an object of polymorphic type RD, or from one of its virtual bases if it doe...
virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, bool ReturnAdjustment)=0
virtual Address adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD, Address This, bool VirtualCall)
Perform ABI-specific "this" argument adjustment required prior to a call of a virtual function.
bool mayNeedDestruction(const VarDecl *VD) const
virtual llvm::BasicBlock * EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, const CXXRecordDecl *RD)
virtual bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass)=0
Checks if ABI requires to initialize vptrs for given dynamic class.
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E)=0
virtual llvm::Value * GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl)=0
virtual bool isThisCompleteObject(GlobalDecl GD) const =0
Determine whether there's something special about the rules of the ABI tell us that 'this' is a compl...
virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD, Address This, llvm::Type *Ty, SourceLocation Loc)=0
Build a virtual function pointer in the ABI-specific way.
virtual bool classifyReturnType(CGFunctionInfo &FI) const =0
If the C++ ABI requires the given type be returned in a particular way, this method sets RetAI and re...
virtual void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType, const CXXDestructorDecl *Dtor)=0
virtual CatchTypeInfo getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType)=0
virtual void EmitThreadLocalInitFuncs(CodeGenModule &CGM, ArrayRef< const VarDecl * > CXXThreadLocals, ArrayRef< llvm::Function * > CXXThreadLocalInits, ArrayRef< const VarDecl * > CXXThreadLocalInitVars)=0
Emits ABI-required functions necessary to initialize thread_local variables in this translation unit.
virtual bool usesThreadWrapperFunction(const VarDecl *VD) const =0
virtual RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const =0
Returns how an argument of the given record type should be passed.
virtual llvm::Value * EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E, Address Base, llvm::Value *MemPtr, const MemberPointerType *MPT, bool IsInBounds)
Calculate an l-value from an object and a data member pointer.
virtual const CXXRecordDecl * getThisArgumentTypeForMethod(GlobalDecl GD)
Get the type of the implicit "this" parameter used by a method.
virtual void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)=0
Emit the destructor call.
virtual llvm::GlobalVariable * getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset)=0
Get the address of the vtable for the given record decl which should be used for the vptr at the give...
virtual bool EmitBadCastCall(CodeGenFunction &CGF)=0
virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, CallArgList &CallArgs)
virtual llvm::Constant * EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset)
Create a member pointer for the given field.
virtual llvm::Value * EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, Address ThisPtr, llvm::Type *StdTypeInfoPtrTy)=0
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD)=0
Emit any tables needed to implement virtual inheritance.
virtual void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD)=0
Emits the VTable definitions required for the given record type.
virtual CGCallee EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, Address This, llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, const MemberPointerType *MPT)
Load a member function from an object and a member function pointer.
virtual bool isPermittedToBeHomogeneousAggregate(const CXXRecordDecl *RD) const
Returns true if the ABI permits the argument to be a homogeneous aggregate.
virtual void emitCXXStructor(GlobalDecl GD)=0
Emit a single constructor/destructor with the given type from a C++ constructor Decl.
virtual llvm::Value * EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke)=0
Emit the ABI-specific virtual destructor call.
virtual bool exportThunk()=0
virtual void EmitBadTypeidCall(CodeGenFunction &CGF)=0
virtual llvm::Value * emitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy)=0
virtual bool isZeroInitializable(const MemberPointerType *MPT)
Return true if the given member pointer can be zero-initialized (in the C++ sense) with an LLVM zeroi...
virtual llvm::Value * EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, llvm::Value *Src)
Perform a derived-to-base, base-to-derived, or bitcast member pointer conversion.
virtual llvm::Constant * EmitMemberFunctionPointer(const CXXMethodDecl *MD)
Create a member pointer for the given method.
virtual llvm::Value * emitDynamicCastCall(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd)=0
virtual llvm::GlobalVariable * getThrowInfo(QualType T)
virtual llvm::GlobalValue::LinkageTypes getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const
virtual Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr, llvm::Value *NumElements, const CXXNewExpr *expr, QualType ElementType)
Initialize the array cookie for the given allocation.
ASTContext & getContext() const
virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, QualType SrcRecordTy)=0
virtual AddedStructorArgCounts buildStructorSignature(GlobalDecl GD, SmallVectorImpl< CanQualType > &ArgTys)=0
Build the signature of the given constructor or destructor variant by adding any required parameters.
virtual llvm::Value * emitExactDynamicCast(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, const ExactDynamicCastInfo &CastInfo, llvm::BasicBlock *CastSuccess, llvm::BasicBlock *CastFail)=0
Emit a dynamic_cast from SrcRecordTy to DestRecordTy.
MangleContext & getMangleContext()
Gets the mangle context.
virtual AddedStructorArgs getImplicitConstructorArgs(CodeGenFunction &CGF, const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating)=0
All available information about a concrete callee.
static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, llvm::FunctionType *FTy)
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
CGFunctionInfo - Class to encapsulate the information about a function definition.
bool isInstanceMethod() const
ABIArgInfo & getReturnInfo()
CanQualType getReturnType() const
unsigned getEffectiveCallingConvention() const
getEffectiveCallingConvention - Return the actual calling convention to use, which may depend on the ...
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
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 GenerateCXXGlobalInitFunc(llvm::Function *Fn, ArrayRef< llvm::Function * > CXXThreadLocals, ConstantAddress Guard=ConstantAddress::invalid())
GenerateCXXGlobalInitFunc - Generates code for initializing global variables.
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...
llvm::LLVMContext & getLLVMContext()
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
void 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.
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)
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
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.
llvm::Type * getVTableType(const VTableLayout &layout)
Returns the type of a vtable with the given layout.
A specialization of Address that requires the address to be an LLVM Constant.
The standard implementation of ConstantInitBuilder used in Clang.
Information for lazily generating a cleanup.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
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()
const LangOptions & getLangOpts() const LLVM_READONLY
Helper to get the language options from the ASTContext.
Concrete class used by the front-end to report problems and issues.
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.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
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.
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
One of these records is kept for each identifier that is lexed.
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 isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const
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)
Describes a module or submodule.
This represents a decl that may have a name.
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
Represents a parameter to a function.
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.
Encodes a location in the source.
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.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
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.
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
Represents a single component in a vtable.
ArrayRef< VTableComponent > vtable_components() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
llvm::Value * getCXXDestructorImplicitParam(CodeGenModule &CGM, llvm::BasicBlock *InsertBlock, llvm::BasicBlock::iterator InsertPoint, const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating)
@ 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 Ret(InterpState &S, CodePtr &PC)
The JSON file list parser is used to communicate input to InstallAPI.
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_DefaultClosure
Default closure variant of a ctor.
@ Ctor_CopyingClosure
Copying closure variant of a ctor.
@ Ctor_Complete
Complete object ctor.
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)
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.
@ Template
We are parsing a template declaration.
CXXDtorType
C++ destructor types.
@ Dtor_Comdat
The COMDAT used for dtors.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
CastKind
CastKind - The kind of operation required for a conversion.
const FunctionProtoType * T
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.
Diagnostic wrappers for TextAPI types for error reporting.
Similar to AddedStructorArgs, but only notes the number of additional arguments.
Additional implicit arguments to add to the beginning (Prefix) and end (Suffix) of a constructor / de...
The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler,...
Struct with all information about dynamic [sub]class needed to set vptr.
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::PointerType * UnqualPtrTy
llvm::IntegerType * PtrDiffTy
CharUnits getPointerAlign() const
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.
A this pointer adjustment.
union clang::ThisAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
The this pointer adjustment as well as an optional return adjustment for a thunk.
ThisAdjustment This
The this pointer adjustment.
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.
struct clang::ReturnAdjustment::VirtualAdjustment::@180 Microsoft
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
uint32_t VBIndex
Index of the virtual base in the vbtable.
struct clang::ThisAdjustment::VirtualAdjustment::@182 Microsoft
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
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...