27 #include "llvm/ADT/StringExtras.h" 28 #include "llvm/ADT/StringSet.h" 29 #include "llvm/IR/Intrinsics.h" 31 using namespace clang;
32 using namespace CodeGen;
37 struct VBTableGlobals {
42 class MicrosoftCXXABI :
public CGCXXABI {
45 :
CGCXXABI(CGM), BaseClassDescriptorType(nullptr),
46 ClassHierarchyDescriptorType(nullptr),
47 CompleteObjectLocatorType(nullptr), CatchableTypeType(nullptr),
48 ThrowInfoType(nullptr) {}
50 bool HasThisReturn(
GlobalDecl GD)
const override;
51 bool hasMostDerivedReturn(
GlobalDecl GD)
const override;
57 bool isSRetParameterAfterThis()
const override {
return true; }
59 bool isThisCompleteObject(
GlobalDecl GD)
const override {
62 if (isa<CXXDestructorDecl>(GD.
getDecl())) {
71 case Dtor_Comdat: llvm_unreachable(
"emitting dtor comdat as function?");
73 llvm_unreachable(
"bad dtor kind");
82 assert(Args.size() >= 2 &&
83 "expected the arglist to have at least two args!");
92 std::vector<CharUnits> getVBPtrOffsets(
const CXXRecordDecl *RD)
override {
93 std::vector<CharUnits> VBPtrOffsets;
97 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
98 for (
const std::unique_ptr<VPtrInfo> &VBT : *VBGlobals.VBTables) {
103 if (VBT->getVBaseWithVPtr())
105 VBPtrOffsets.push_back(Offs);
107 llvm::array_pod_sort(VBPtrOffsets.begin(), VBPtrOffsets.end());
111 StringRef GetPureVirtualCallName()
override {
return "_purecall"; }
112 StringRef GetDeletedVirtualCallName()
override {
return "_purecall"; }
123 llvm::GlobalVariable *getMSCompleteObjectLocator(
const CXXRecordDecl *RD,
126 llvm::Constant *getAddrOfRTTIDescriptor(
QualType Ty)
override;
128 getAddrOfCXXCatchHandlerType(
QualType Ty,
QualType CatchHandlerType)
override;
135 bool shouldTypeidBeNullChecked(
bool IsDeref,
QualType SrcRecordTy)
override;
141 bool shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
147 llvm::BasicBlock *CastEnd)
override;
154 bool canSpeculativelyEmitVTable(
const CXXRecordDecl *RD)
const override {
217 void setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
221 llvm::GlobalValue::LinkageTypes
228 getThisArgumentTypeForMethod(
const CXXMethodDecl *MD)
override {
229 if (MD->
isVirtual() && !isa<CXXDestructorDecl>(MD)) {
231 CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
247 bool VirtualCall)
override;
265 llvm::GlobalVariable *VTable);
275 bool doStructorsInitializeVPtrs(
const CXXRecordDecl *VTableClass)
override {
276 return !VTableClass->
hasAttr<MSNoVTableAttr>();
291 llvm::GlobalVariable *getAddrOfVTable(
const CXXRecordDecl *RD,
301 DeleteOrMemberCallExpr E)
override;
306 "Only deleting destructor thunks are available in this ABI");
311 void emitVirtualInheritanceTables(
const CXXRecordDecl *RD)
override;
313 llvm::GlobalVariable *
315 llvm::GlobalVariable::LinkageTypes
Linkage);
317 llvm::GlobalVariable *
321 llvm::raw_svector_ostream Out(OutName);
322 getMangleContext().mangleCXXVirtualDisplacementMap(SrcRD, DstRD, Out);
323 StringRef MangledName = OutName.str();
325 if (
auto *VDispMap = CGM.getModule().getNamedGlobal(MangledName))
331 llvm::UndefValue::get(CGM.IntTy));
332 Map[0] = llvm::ConstantInt::get(CGM.IntTy, 0);
333 bool AnyDifferent =
false;
334 for (
const auto &I : SrcRD->
vbases()) {
335 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
341 Map[SrcVBIndex] = llvm::ConstantInt::get(CGM.IntTy, DstVBIndex * 4);
342 AnyDifferent |= SrcVBIndex != DstVBIndex;
348 llvm::ArrayType *VDispMapTy = llvm::ArrayType::get(CGM.IntTy, Map.size());
349 llvm::Constant *Init = llvm::ConstantArray::get(VDispMapTy, Map);
350 llvm::GlobalValue::LinkageTypes
Linkage =
352 ? llvm::GlobalValue::LinkOnceODRLinkage
354 auto *VDispMap =
new llvm::GlobalVariable(
355 CGM.getModule(), VDispMapTy,
true,
Linkage,
361 llvm::GlobalVariable *GV)
const;
363 void setThunkLinkage(llvm::Function *Thunk,
bool ForVTable,
366 getContext().GetGVALinkageForFunction(cast<FunctionDecl>(GD.
getDecl()));
370 else if (ReturnAdjustment)
371 Thunk->setLinkage(llvm::GlobalValue::WeakODRLinkage);
373 Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
376 bool exportThunk()
override {
return false; }
382 const ReturnAdjustment &RA)
override;
384 void EmitThreadLocalInitFuncs(
389 bool usesThreadWrapperFunction()
const override {
return false; }
394 llvm::GlobalVariable *DeclPtr,
395 bool PerformInit)
override;
397 llvm::FunctionCallee Dtor,
398 llvm::Constant *Addr)
override;
436 friend struct MSRTTIBuilder;
438 bool isImageRelative()
const {
439 return CGM.getTarget().getPointerWidth(0) == 64;
443 llvm::StructType *getTypeDescriptorType(StringRef TypeInfoString) {
445 TDTypeName += llvm::utostr(TypeInfoString.size());
446 llvm::StructType *&TypeDescriptorType =
447 TypeDescriptorTypeMap[TypeInfoString.size()];
448 if (TypeDescriptorType)
449 return TypeDescriptorType;
453 llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)};
456 return TypeDescriptorType;
460 if (!isImageRelative())
465 llvm::StructType *getBaseClassDescriptorType() {
466 if (BaseClassDescriptorType)
467 return BaseClassDescriptorType;
469 getImageRelativeType(CGM.Int8PtrTy),
475 getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()),
478 CGM.getLLVMContext(), FieldTypes,
"rtti.BaseClassDescriptor");
479 return BaseClassDescriptorType;
482 llvm::StructType *getClassHierarchyDescriptorType() {
483 if (ClassHierarchyDescriptorType)
484 return ClassHierarchyDescriptorType;
487 CGM.getLLVMContext(),
"rtti.ClassHierarchyDescriptor");
492 getImageRelativeType(
493 getBaseClassDescriptorType()->getPointerTo()->getPointerTo()),
495 ClassHierarchyDescriptorType->setBody(FieldTypes);
496 return ClassHierarchyDescriptorType;
499 llvm::StructType *getCompleteObjectLocatorType() {
500 if (CompleteObjectLocatorType)
501 return CompleteObjectLocatorType;
503 CGM.getLLVMContext(),
"rtti.CompleteObjectLocator");
508 getImageRelativeType(CGM.Int8PtrTy),
509 getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()),
510 getImageRelativeType(CompleteObjectLocatorType),
513 if (!isImageRelative())
514 FieldTypesRef = FieldTypesRef.drop_back();
515 CompleteObjectLocatorType->setBody(FieldTypesRef);
516 return CompleteObjectLocatorType;
519 llvm::GlobalVariable *getImageBase() {
520 StringRef Name =
"__ImageBase";
521 if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name))
524 auto *GV =
new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty,
532 llvm::Constant *getImageRelativeConstant(llvm::Constant *PtrVal) {
533 if (!isImageRelative())
536 if (PtrVal->isNullValue())
537 return llvm::Constant::getNullValue(CGM.IntTy);
539 llvm::Constant *ImageBaseAsInt =
540 llvm::ConstantExpr::getPtrToInt(getImageBase(), CGM.IntPtrTy);
541 llvm::Constant *PtrValAsInt =
542 llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.IntPtrTy);
543 llvm::Constant *Diff =
544 llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt,
546 return llvm::ConstantExpr::getTrunc(Diff, CGM.IntTy);
554 llvm::Constant *getZeroInt() {
555 return llvm::ConstantInt::get(CGM.IntTy, 0);
558 llvm::Constant *getAllOnesInt() {
559 return llvm::Constant::getAllOnesValue(CGM.IntTy);
580 int32_t VBTableOffset,
582 assert(VBTableOffset % 4 == 0 &&
"should be byte offset into table of i32s");
583 llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
584 *VBTOffset = llvm::ConstantInt::get(CGM.IntTy, VBTableOffset);
585 return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr);
588 std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
601 llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
602 bool IsMemberFunction,
605 unsigned VBTableIndex);
614 const VBTableGlobals &enumerateVBTables(
const CXXRecordDecl *RD);
617 llvm::Function *EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
627 return RD->
hasAttr<MSInheritanceAttr>();
634 llvm::Constant *EmitMemberFunctionPointer(
const CXXMethodDecl *MD)
override;
635 llvm::Constant *EmitMemberPointer(
const APValue &MP,
QualType MPT)
override;
641 bool Inequality)
override;
662 llvm::Constant *EmitMemberPointerConversion(
const CastExpr *E,
663 llvm::Constant *Src)
override;
665 llvm::Constant *EmitMemberPointerConversion(
678 llvm::StructType *getCatchableTypeType() {
679 if (CatchableTypeType)
680 return CatchableTypeType;
683 getImageRelativeType(CGM.Int8PtrTy),
688 getImageRelativeType(CGM.Int8PtrTy)
691 CGM.getLLVMContext(), FieldTypes,
"eh.CatchableType");
692 return CatchableTypeType;
695 llvm::StructType *getCatchableTypeArrayType(uint32_t NumEntries) {
696 llvm::StructType *&CatchableTypeArrayType =
697 CatchableTypeArrayTypeMap[NumEntries];
698 if (CatchableTypeArrayType)
699 return CatchableTypeArrayType;
702 CTATypeName += llvm::utostr(NumEntries);
704 getImageRelativeType(getCatchableTypeType()->getPointerTo());
707 llvm::ArrayType::get(CTType, NumEntries)
709 CatchableTypeArrayType =
711 return CatchableTypeArrayType;
714 llvm::StructType *getThrowInfoType() {
716 return ThrowInfoType;
719 getImageRelativeType(CGM.Int8PtrTy),
720 getImageRelativeType(CGM.Int8PtrTy),
721 getImageRelativeType(CGM.Int8PtrTy)
725 return ThrowInfoType;
731 llvm::Type *Args[] = {CGM.Int8PtrTy, getThrowInfoType()->getPointerTo()};
732 llvm::FunctionType *FTy =
733 llvm::FunctionType::get(CGM.VoidTy, Args,
false);
734 llvm::FunctionCallee Throw =
735 CGM.CreateRuntimeFunction(FTy,
"_CxxThrowException");
737 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) {
738 if (
auto *Fn = dyn_cast<llvm::Function>(Throw.getCallee()))
739 Fn->setCallingConv(llvm::CallingConv::X86_StdCall);
747 llvm::Constant *getCatchableType(
QualType T,
748 uint32_t NVOffset = 0,
749 int32_t VBPtrOffset = -1,
750 uint32_t VBIndex = 0);
752 llvm::GlobalVariable *getCatchableTypeArray(
QualType T);
754 llvm::GlobalVariable *getThrowInfo(
QualType T)
override;
756 std::pair<llvm::Value *, const CXXRecordDecl *>
761 typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
762 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy;
763 typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalValue *> VFTablesMapTy;
765 VFTablesMapTy VFTablesMap;
766 VTablesMapTy VTablesMap;
769 llvm::SmallPtrSet<const CXXRecordDecl *, 4> DeferredVFTables;
773 llvm::DenseMap<const CXXRecordDecl *, VBTableGlobals> VBTablesMap;
778 GuardInfo() : Guard(nullptr), BitIndex(0) {}
779 llvm::GlobalVariable *Guard;
785 llvm::DenseMap<const DeclContext *, GuardInfo> GuardVariableMap;
786 llvm::DenseMap<const DeclContext *, GuardInfo> ThreadLocalGuardVariableMap;
787 llvm::DenseMap<const DeclContext *, unsigned> ThreadSafeGuardNumMap;
789 llvm::DenseMap<size_t, llvm::StructType *> TypeDescriptorTypeMap;
790 llvm::StructType *BaseClassDescriptorType;
791 llvm::StructType *ClassHierarchyDescriptorType;
792 llvm::StructType *CompleteObjectLocatorType;
794 llvm::DenseMap<QualType, llvm::GlobalVariable *> CatchableTypeArrays;
796 llvm::StructType *CatchableTypeType;
797 llvm::DenseMap<uint32_t, llvm::StructType *> CatchableTypeArrayTypeMap;
798 llvm::StructType *ThrowInfoType;
805 switch (CGM.getTarget().getTriple().getArch()) {
810 case llvm::Triple::thumb:
816 case llvm::Triple::x86:
824 return RAA_DirectInMemory;
830 case llvm::Triple::x86_64:
831 case llvm::Triple::aarch64:
835 llvm_unreachable(
"invalid enum");
847 llvm::Value *MDThis = EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE);
852 void MicrosoftCXXABI::emitRethrow(
CodeGenFunction &CGF,
bool isNoReturn) {
854 llvm::ConstantPointerNull::get(CGM.Int8PtrTy),
855 llvm::ConstantPointerNull::get(getThrowInfoType()->getPointerTo())};
868 llvm::BasicBlock *CatchPadBB = CGF.
Builder.GetInsertBlock();
869 llvm::CatchPadInst *CPI =
870 cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI());
889 std::tuple<Address, llvm::Value *, const CXXRecordDecl *>
900 return std::make_tuple(Value, llvm::ConstantInt::get(CGF.
Int32Ty, 0),
909 PolymorphicBase = BaseDecl;
913 assert(PolymorphicBase &&
"polymorphic class has no apparent vfptr?");
916 GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase);
920 return std::make_tuple(
Address(Ptr, VBaseAlign), Offset, PolymorphicBase);
923 bool MicrosoftCXXABI::shouldTypeidBeNullChecked(
bool IsDeref,
927 !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
933 llvm::FunctionType *FTy =
934 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false);
941 llvm::CallBase *Call =
943 Call->setDoesNotReturn();
944 CGF.
Builder.CreateUnreachable();
951 std::tie(ThisPtr, std::ignore, std::ignore) =
952 performBaseAdjustment(CGF, ThisPtr, SrcRecordTy);
957 bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(
bool SrcIsPtr,
961 !getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
975 std::tie(This, Offset, std::ignore) =
976 performBaseAdjustment(CGF, This, SrcRecordTy);
989 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
992 ThisPtr,
Offset, SrcRTTI, DestRTTI,
1002 std::tie(Value, std::ignore, std::ignore) =
1003 performBaseAdjustment(CGF, Value, SrcRecordTy);
1009 llvm::FunctionType::get(CGF.
Int8PtrTy, ArgTypes,
false),
1019 llvm::Value *MicrosoftCXXABI::GetVirtualBaseClassOffset(
1023 int64_t VBPtrChars =
1025 llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars);
1029 CGM.getMicrosoftVTableContext().getVBTableIndex(ClassDecl, BaseClassDecl);
1031 llvm::ConstantInt::get(CGM.IntTy, VBTableChars.
getQuantity());
1034 GetVBaseOffsetFromVBPtr(CGF, This, VBPtrOffset, VBTableOffset);
1036 CGF.
Builder.CreateSExtOrBitCast(VBPtrToNewBase, CGM.PtrDiffTy);
1037 return CGF.
Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);
1040 bool MicrosoftCXXABI::HasThisReturn(
GlobalDecl GD)
const {
1041 return isa<CXXConstructorDecl>(GD.
getDecl());
1045 return isa<CXXDestructorDecl>(GD.
getDecl()) &&
1049 bool MicrosoftCXXABI::hasMostDerivedReturn(
GlobalDecl GD)
const {
1074 if (Ctor->isUserProvided())
1086 bool isAArch64 = CGM.getTarget().getTriple().isAArch64();
1088 bool isIndirectReturn =
1094 if (isIndirectReturn || !isSimple || isInstanceMethod) {
1112 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1113 assert(IsMostDerivedClass &&
1114 "ctor for a class with virtual bases must have an implicit parameter");
1116 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1118 llvm::BasicBlock *CallVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.init_vbases");
1119 llvm::BasicBlock *SkipVbaseCtorsBB = CGF.
createBasicBlock(
"ctor.skip_vbases");
1120 CGF.
Builder.CreateCondBr(IsCompleteObject,
1121 CallVbaseCtorsBB, SkipVbaseCtorsBB);
1126 EmitVBPtrStores(CGF, RD);
1130 return SkipVbaseCtorsBB;
1134 MicrosoftCXXABI::EmitDtorCompleteObjectHandler(
CodeGenFunction &CGF) {
1135 llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
1136 assert(IsMostDerivedClass &&
1137 "ctor for a class with virtual bases must have an implicit parameter");
1139 CGF.
Builder.CreateIsNotNull(IsMostDerivedClass,
"is_complete_object");
1141 llvm::BasicBlock *CallVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.dtor_vbases");
1142 llvm::BasicBlock *SkipVbaseDtorsBB = CGF.
createBasicBlock(
"Dtor.skip_vbases");
1143 CGF.
Builder.CreateCondBr(IsCompleteObject,
1144 CallVbaseDtorsBB, SkipVbaseDtorsBB);
1149 return SkipVbaseDtorsBB;
1152 void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
1172 unsigned AS = getThisAddress(CGF).getAddressSpace();
1176 const CXXRecordDecl *VBase = S.getType()->getAsCXXRecordDecl();
1177 auto I = VBaseMap.find(VBase);
1178 assert(I != VBaseMap.end());
1179 if (!I->second.hasVtorDisp())
1183 GetVirtualBaseClassOffset(CGF, getThisAddress(CGF), RD, VBase);
1184 uint64_t ConstantVBaseOffset = I->second.VBaseOffset.getQuantity();
1188 VBaseOffset, llvm::ConstantInt::get(CGM.PtrDiffTy, ConstantVBaseOffset),
1190 VtorDispValue = Builder.CreateTruncOrBitCast(VtorDispValue, CGF.
Int32Ty);
1194 CGF.
Int8Ty->getPointerTo(AS));
1195 llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(Int8This, VBaseOffset);
1197 VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4);
1199 VtorDispPtr, CGF.
Int32Ty->getPointerTo(AS),
"vtordisp.ptr");
1212 return ExpectedCallingConv == ActualCallingConv;
1226 Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage);
1227 CGM.setGVProperties(Fn, D);
1233 Address This = getThisAddress(CGF);
1238 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
1239 for (
unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
1240 const std::unique_ptr<VPtrInfo> &VBT = (*VBGlobals.VBTables)[I];
1241 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
1246 if (VBT->getVBaseWithVPtr())
1252 "vbptr." + VBT->ObjectWithVPtr->getName());
1258 MicrosoftCXXABI::buildStructorSignature(
GlobalDecl GD,
1260 AddedStructorArgs Added;
1262 if (isa<CXXDestructorDecl>(GD.
getDecl()) &&
1265 ArgTys.push_back(getContext().IntTy);
1279 ArgTys.insert(ArgTys.begin() + 1, getContext().IntTy);
1282 ArgTys.push_back(getContext().IntTy);
1290 void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
1296 GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
1299 CGM.setDLLImportDLLExport(GV, ND);
1303 llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(
1314 return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage,
1320 if (Dtor->
hasAttr<DLLExportAttr>())
1321 return llvm::GlobalValue::WeakODRLinkage;
1322 if (Dtor->
hasAttr<DLLImportAttr>())
1323 return llvm::GlobalValue::AvailableExternallyLinkage;
1324 return llvm::GlobalValue::LinkOnceODRLinkage;
1329 return llvm::GlobalValue::LinkOnceODRLinkage;
1331 llvm_unreachable(
"MS C++ ABI does not support comdat dtors");
1333 llvm_unreachable(
"invalid dtor type");
1343 MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(
GlobalDecl GD) {
1358 CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
1365 if (isa<CXXDestructorDecl>(MD))
1370 getContext().getASTRecordLayout(MD->
getParent());
1377 Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
1383 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(GD);
1406 CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
1423 GetVirtualBaseClassOffset(CGF, Result, Derived, VBase);
1428 Result =
Address(VBasePtr, VBaseAlign);
1430 if (!StaticOffset.
isZero()) {
1451 assert(isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD));
1460 if (FPT->isVariadic())
1461 Params.insert(Params.begin() + 1, IsMostDerived);
1463 Params.push_back(IsMostDerived);
1464 getStructorImplicitParamDecl(CGF) = IsMostDerived;
1470 Params.push_back(ShouldDelete);
1471 getStructorImplicitParamDecl(CGF) = ShouldDelete;
1475 void MicrosoftCXXABI::EmitInstanceFunctionProlog(
CodeGenFunction &CGF) {
1495 CharUnits Adjustment = getVirtualFunctionPrologueThisAdjustment(CGF.
CurGD);
1496 if (!Adjustment.
isZero()) {
1497 unsigned AS = cast<llvm::PointerType>(This->getType())->getAddressSpace();
1499 *thisTy = This->getType();
1502 This = CGF.
Builder.CreateConstInBoundsGEP1_32(CGF.
Int8Ty, This,
1507 setCXXABIThisValue(CGF, This);
1517 if (HasThisReturn(CGF.
CurGD))
1519 else if (hasMostDerivedReturn(CGF.
CurGD))
1524 assert(getStructorImplicitParamDecl(CGF) &&
1525 "no implicit parameter for a constructor with virtual bases?");
1526 getStructorImplicitParamValue(CGF)
1533 assert(getStructorImplicitParamDecl(CGF) &&
1534 "no implicit parameter for a deleting destructor?");
1535 getStructorImplicitParamValue(CGF)
1538 "should_call_delete");
1544 bool ForVirtualBase,
bool Delegating,
CallArgList &Args) {
1549 return AddedStructorArgs{};
1555 MostDerivedArg = getStructorImplicitParamValue(CGF);
1557 MostDerivedArg = llvm::ConstantInt::get(CGM.Int32Ty, Type ==
Ctor_Complete);
1561 Args.insert(Args.begin() + 1,
CallArg(RV, getContext().IntTy));
1562 return AddedStructorArgs::prefix(1);
1564 Args.
add(RV, getContext().IntTy);
1565 return AddedStructorArgs::suffix(1);
1571 bool Delegating,
Address This,
1584 "The deleting destructor should only be called via a virtual call");
1585 This = adjustThisArgumentForVirtualFunctionCall(CGF,
GlobalDecl(DD, Type),
1589 llvm::BasicBlock *BaseDtorEndBB =
nullptr;
1590 if (ForVirtualBase && isa<CXXConstructorDecl>(CGF.
CurCodeDecl)) {
1591 BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF);
1597 if (BaseDtorEndBB) {
1599 CGF.
Builder.CreateBr(BaseDtorEndBB);
1604 void MicrosoftCXXABI::emitVTableTypeMetadata(
const VPtrInfo &Info,
1606 llvm::GlobalVariable *VTable) {
1607 if (!CGM.getCodeGenOpts().LTOUnit)
1614 getContext().getLangOpts().RTTIData
1615 ? getContext().toCharUnitsFromBits(
1616 getContext().getTargetInfo().getPointerWidth(0))
1620 CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD);
1625 CGM.AddVTableTypeMetadata(VTable, AddressPoint,
1635 getContext().getASTRecordLayout(DerivedRD);
1641 Offset = VBI->second.VBaseOffset;
1644 CGM.AddVTableTypeMetadata(VTable, AddressPoint, DerivedRD);
1649 CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD);
1652 void MicrosoftCXXABI::emitVTableDefinitions(
CodeGenVTables &CGVT,
1657 for (
const std::unique_ptr<VPtrInfo>& Info : VFPtrs) {
1658 llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->
FullOffsetInMDC);
1659 if (VTable->hasInitializer())
1665 llvm::Constant *RTTI =
nullptr;
1668 RTTI = getMSCompleteObjectLocator(RD, *Info);
1673 Components.finishAndSetAsInitializer(VTable);
1675 emitVTableTypeMetadata(*Info, RD, VTable);
1679 bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField(
1684 llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
1687 llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass);
1688 if (!VTableAddressPoint) {
1690 !getContext().getASTRecordLayout(Base.
getBase()).hasOwnVFPtr());
1692 return VTableAddressPoint;
1698 llvm::raw_svector_ostream Out(Name);
1707 return VFTablesMap[
ID];
1710 llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
1712 llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass);
1713 assert(VFTable &&
"Couldn't find a vftable for the given base?");
1717 llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(
const CXXRecordDecl *RD,
1723 VFTableIdTy
ID(RD, VPtrOffset);
1724 VTablesMapTy::iterator I;
1726 std::tie(I, Inserted) = VTablesMap.insert(std::make_pair(ID,
nullptr));
1730 llvm::GlobalVariable *&VTable = I->second;
1735 if (DeferredVFTables.insert(RD).second) {
1738 CGM.addDeferredVTable(RD);
1743 llvm::StringSet<> ObservedMangledNames;
1744 for (
size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
1747 if (!ObservedMangledNames.insert(Name.str()).second)
1748 llvm_unreachable(
"Already saw this mangling before?");
1753 const std::unique_ptr<VPtrInfo> *VFPtrI = std::find_if(
1754 VFPtrs.begin(), VFPtrs.end(), [&](
const std::unique_ptr<VPtrInfo>& VPI) {
1755 return VPI->FullOffsetInMDC == VPtrOffset;
1757 if (VFPtrI == VFPtrs.end()) {
1758 VFTablesMap[
ID] =
nullptr;
1761 const std::unique_ptr<VPtrInfo> &VFPtr = *VFPtrI;
1773 llvm::GlobalValue::LinkageTypes VFTableLinkage =
1774 RD->
hasAttr<DLLImportAttr>() ? llvm::GlobalValue::LinkOnceODRLinkage
1775 : CGM.getVTableLinkage(RD);
1776 bool VFTableComesFromAnotherTU =
1777 llvm::GlobalValue::isAvailableExternallyLinkage(VFTableLinkage) ||
1778 llvm::GlobalValue::isExternalLinkage(VFTableLinkage);
1779 bool VTableAliasIsRequred =
1780 !VFTableComesFromAnotherTU && getContext().getLangOpts().RTTIData;
1782 if (llvm::GlobalValue *VFTable =
1783 CGM.getModule().getNamedGlobal(VFTableName)) {
1784 VFTablesMap[
ID] = VFTable;
1785 VTable = VTableAliasIsRequred
1786 ? cast<llvm::GlobalVariable>(
1787 cast<llvm::GlobalAlias>(VFTable)->getBaseObject())
1788 : cast<llvm::GlobalVariable>(VFTable);
1794 llvm::GlobalValue::LinkageTypes VTableLinkage =
1795 VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage;
1797 StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str();
1799 llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
1803 llvm::GlobalValue *VFTable;
1804 VTable =
new llvm::GlobalVariable(CGM.getModule(), VTableType,
1805 true, VTableLinkage,
1806 nullptr, VTableName);
1807 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1809 llvm::Comdat *C =
nullptr;
1810 if (!VFTableComesFromAnotherTU &&
1811 (llvm::GlobalValue::isWeakForLinker(VFTableLinkage) ||
1812 (llvm::GlobalValue::isLocalLinkage(VFTableLinkage) &&
1813 VTableAliasIsRequred)))
1814 C = CGM.getModule().getOrInsertComdat(VFTableName.str());
1819 if (VTableAliasIsRequred) {
1820 llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.Int32Ty, 0),
1821 llvm::ConstantInt::get(CGM.Int32Ty, 0),
1822 llvm::ConstantInt::get(CGM.Int32Ty, 1)};
1825 llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr(
1826 VTable->getValueType(), VTable, GEPIndices);
1827 if (llvm::GlobalValue::isWeakForLinker(VFTableLinkage)) {
1830 C->setSelectionKind(llvm::Comdat::Largest);
1834 VFTableName.str(), VTableGEP,
1836 VFTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1845 VTable->setComdat(C);
1847 if (RD->
hasAttr<DLLExportAttr>())
1848 VFTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1850 VFTablesMap[
ID] = VFTable;
1861 Ty = Ty->getPointerTo()->getPointerTo();
1863 adjustThisArgumentForVirtualFunctionCall(CGF, GD, This,
true);
1865 auto *MethodDecl = cast<CXXMethodDecl>(GD.
getDecl());
1873 auto getObjectWithVPtr = [&] {
1876 [&](
const std::unique_ptr<VPtrInfo> &Info) {
1886 getObjectWithVPtr(), VTable,
1887 ML.
Index * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8);
1889 if (CGM.getCodeGenOpts().PrepareForLTO)
1893 Builder.CreateConstInBoundsGEP1_64(VTable, ML.
Index,
"vfn");
1901 llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
1903 Address This, DeleteOrMemberCallExpr E) {
1906 assert((CE !=
nullptr) ^ (D !=
nullptr));
1907 assert(CE ==
nullptr || CE->arg_begin() == CE->arg_end());
1914 &CGM.getTypes().arrangeCXXStructorDeclaration(GD);
1919 llvm::Value *ImplicitParam = llvm::ConstantInt::get(
1925 ThisTy = CE->getObjectType();
1927 ThisTy = D->getDestroyedType();
1930 This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This,
true);
1932 ImplicitParam, Context.
IntTy, CE);
1936 const VBTableGlobals &
1937 MicrosoftCXXABI::enumerateVBTables(
const CXXRecordDecl *RD) {
1940 llvm::DenseMap<const CXXRecordDecl*, VBTableGlobals>::iterator Entry;
1942 std::tie(Entry, Added) =
1943 VBTablesMap.insert(std::make_pair(RD, VBTableGlobals()));
1944 VBTableGlobals &VBGlobals = Entry->second;
1953 llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
1954 for (VPtrInfoVector::const_iterator I = VBGlobals.VBTables->begin(),
1955 E = VBGlobals.VBTables->end();
1957 VBGlobals.Globals.push_back(getAddrOfVBTable(**I, RD, Linkage));
1964 MicrosoftCXXABI::EmitVirtualMemPtrThunk(
const CXXMethodDecl *MD,
1966 assert(!isa<CXXConstructorDecl>(MD) && !isa<CXXDestructorDecl>(MD) &&
1967 "can't form pointers to ctors or virtual dtors");
1971 llvm::raw_svector_ostream Out(ThunkName);
1972 getMangleContext().mangleVirtualMemPtrThunk(MD, ML, Out);
1975 if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
1976 return cast<llvm::Function>(GV);
1980 CGM.getTypes().arrangeUnprototypedMustTailThunk(MD);
1981 llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
1982 llvm::Function *ThunkFn =
1984 ThunkName.str(), &CGM.getModule());
1985 assert(ThunkFn->getName() == ThunkName &&
"name was uniqued!");
1988 ? llvm::GlobalValue::LinkOnceODRLinkage
1991 ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));
1993 CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn);
1994 CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn);
2000 ThunkFn->addFnAttr(
"thunk");
2013 buildThisParam(CGF, FunctionArgs);
2018 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
2023 getThisAddress(CGF), ThunkTy->getPointerTo()->getPointerTo(), MD->
getParent());
2026 CGF.
Builder.CreateConstInBoundsGEP1_64(VTable, ML.
Index,
"vfn");
2035 void MicrosoftCXXABI::emitVirtualInheritanceTables(
const CXXRecordDecl *RD) {
2036 const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
2037 for (
unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
2038 const std::unique_ptr<VPtrInfo>& VBT = (*VBGlobals.VBTables)[I];
2039 llvm::GlobalVariable *GV = VBGlobals.Globals[I];
2040 if (GV->isDeclaration())
2041 emitVBTableDefinition(*VBT, RD, GV);
2045 llvm::GlobalVariable *
2047 llvm::GlobalVariable::LinkageTypes Linkage) {
2049 llvm::raw_svector_ostream Out(OutName);
2050 getMangleContext().mangleCXXVBTable(RD, VBT.
MangledPath, Out);
2051 StringRef Name = OutName.str();
2053 llvm::ArrayType *VBTableType =
2056 assert(!CGM.getModule().getNamedGlobal(Name) &&
2057 "vbtable with this name already exists: mangling bug?");
2059 CGM.getContext().getTypeAlignInChars(CGM.getContext().IntTy);
2060 llvm::GlobalVariable *GV = CGM.CreateOrReplaceCXXRuntimeVariable(
2061 Name, VBTableType, Linkage, Alignment.getQuantity());
2062 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2064 if (RD->
hasAttr<DLLImportAttr>())
2065 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2066 else if (RD->
hasAttr<DLLExportAttr>())
2067 GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2069 if (!GV->hasExternalLinkage())
2070 emitVBTableDefinition(VBT, RD, GV);
2075 void MicrosoftCXXABI::emitVBTableDefinition(
const VPtrInfo &VBT,
2077 llvm::GlobalVariable *GV)
const {
2081 "should only emit vbtables for classes with vbtables");
2085 const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD);
2091 CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset();
2092 Offsets[0] = llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity());
2095 for (
const auto &I : ObjectWithVPtr->
vbases()) {
2096 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
2103 CompleteVBPtrOffset +=
2105 Offset -= CompleteVBPtrOffset;
2107 unsigned VBIndex = Context.getVBTableIndex(ObjectWithVPtr, VBase);
2108 assert(Offsets[VBIndex] ==
nullptr &&
"The same vbindex seen twice?");
2109 Offsets[VBIndex] = llvm::ConstantInt::get(CGM.IntTy, Offset.
getQuantity());
2112 assert(Offsets.size() ==
2113 cast<llvm::ArrayType>(cast<llvm::PointerType>(GV->getType())
2114 ->getElementType())->getNumElements());
2115 llvm::ArrayType *VBTableType =
2116 llvm::ArrayType::get(CGM.IntTy, Offsets.size());
2117 llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets);
2118 GV->setInitializer(Init);
2120 if (RD->
hasAttr<DLLImportAttr>())
2121 GV->setLinkage(llvm::GlobalVariable::AvailableExternallyLinkage);
2144 CGF.
Builder.CreateNeg(VtorDisp));
2161 V = CGF.
Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
2178 const ReturnAdjustment &RA) {
2193 V = CGF.
Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
2210 bool MicrosoftCXXABI::requiresArrayCookie(
const CXXNewExpr *expr) {
2237 assert(requiresArrayCookie(expr));
2240 CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
2256 llvm::FunctionCallee Dtor,
2257 llvm::Constant *Addr) {
2262 llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get(
2263 CGF.
IntTy, DtorStub->getType(),
false);
2266 TLRegDtorTy,
"__tlregdtor", llvm::AttributeList(),
true);
2267 if (llvm::Function *TLRegDtorFn =
2268 dyn_cast<llvm::Function>(TLRegDtor.getCallee()))
2269 TLRegDtorFn->setDoesNotThrow();
2275 llvm::FunctionCallee Dtor,
2276 llvm::Constant *Addr) {
2287 void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
2291 if (CXXThreadLocalInits.empty())
2296 ?
"/include:___dyn_tls_init@12" 2297 :
"/include:__dyn_tls_init");
2302 auto AddToXDU = [&CGM](llvm::Function *InitFunc) {
2303 llvm::GlobalVariable *InitFuncPtr =
new llvm::GlobalVariable(
2304 CGM.
getModule(), InitFunc->getType(),
true,
2306 Twine(InitFunc->getName(),
"$initializer$"));
2307 InitFuncPtr->setSection(
".CRT$XDU");
2314 std::vector<llvm::Function *> NonComdatInits;
2315 for (
size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) {
2316 llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>(
2318 llvm::Function *F = CXXThreadLocalInits[I];
2321 if (llvm::Comdat *C = GV->getComdat())
2322 AddToXDU(F)->setComdat(C);
2324 NonComdatInits.push_back(F);
2327 if (!NonComdatInits.empty()) {
2328 llvm::FunctionType *FTy =
2329 llvm::FunctionType::get(CGM.
VoidTy,
false);
2347 StringRef VarName(
"_Init_thread_epoch");
2349 if (
auto *GV = CGM.
getModule().getNamedGlobal(VarName))
2351 auto *GV =
new llvm::GlobalVariable(
2355 nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel);
2361 llvm::FunctionType *FTy =
2362 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2363 CGM.
IntTy->getPointerTo(),
false);
2365 FTy,
"_Init_thread_header",
2367 llvm::AttributeList::FunctionIndex,
2368 llvm::Attribute::NoUnwind),
2373 llvm::FunctionType *FTy =
2374 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2375 CGM.
IntTy->getPointerTo(),
false);
2377 FTy,
"_Init_thread_footer",
2379 llvm::AttributeList::FunctionIndex,
2380 llvm::Attribute::NoUnwind),
2385 llvm::FunctionType *FTy =
2386 llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.
getLLVMContext()),
2387 CGM.
IntTy->getPointerTo(),
false);
2389 FTy,
"_Init_thread_abort",
2391 llvm::AttributeList::FunctionIndex,
2392 llvm::Attribute::NoUnwind),
2400 ResetGuardBit(
Address Guard,
unsigned GuardNum)
2401 : Guard(Guard), GuardNum(GuardNum) {}
2407 llvm::LoadInst *LI = Builder.
CreateLoad(Guard);
2408 llvm::ConstantInt *Mask =
2409 llvm::ConstantInt::get(CGF.
IntTy, ~(1ULL << GuardNum));
2410 Builder.
CreateStore(Builder.CreateAnd(LI, Mask), Guard);
2426 llvm::GlobalVariable *GV,
2430 assert(GV->hasWeakLinkage() || GV->hasLinkOnceLinkage());
2432 llvm::Function *F = CGF.
CurFn;
2433 F->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
2434 F->setComdat(CGM.
getModule().getOrInsertComdat(F->getName()));
2440 bool ThreadsafeStatic = getContext().getLangOpts().ThreadsafeStatics;
2444 bool HasPerVariableGuard = ThreadsafeStatic && !ThreadlocalStatic;
2447 llvm::IntegerType *GuardTy = CGF.
Int32Ty;
2448 llvm::ConstantInt *Zero = llvm::ConstantInt::get(GuardTy, 0);
2452 GuardInfo *GI =
nullptr;
2453 if (ThreadlocalStatic)
2455 else if (!ThreadsafeStatic)
2458 llvm::GlobalVariable *GuardVar = GI ? GI->Guard :
nullptr;
2463 GuardNum = getContext().getStaticLocalNumber(&D);
2464 assert(GuardNum > 0);
2466 }
else if (HasPerVariableGuard) {
2470 GuardNum = GI->BitIndex++;
2473 if (!HasPerVariableGuard && GuardNum >= 32) {
2475 ErrorUnsupportedABI(CGF,
"more than 32 guarded initializations");
2484 llvm::raw_svector_ostream Out(GuardName);
2485 if (HasPerVariableGuard)
2486 getMangleContext().mangleThreadSafeStaticGuardVariable(&D, GuardNum,
2489 getMangleContext().mangleStaticGuardVariable(&D, Out);
2495 new llvm::GlobalVariable(CGM.
getModule(), GuardTy,
false,
2496 GV->getLinkage(), Zero, GuardName.str());
2497 GuardVar->setVisibility(GV->getVisibility());
2498 GuardVar->setDLLStorageClass(GV->getDLLStorageClass());
2500 if (GuardVar->isWeakForLinker())
2501 GuardVar->setComdat(
2502 CGM.
getModule().getOrInsertComdat(GuardVar->getName()));
2504 GuardVar->setThreadLocal(
true);
2505 if (GI && !HasPerVariableGuard)
2506 GI->Guard = GuardVar;
2511 assert(GuardVar->getLinkage() == GV->getLinkage() &&
2512 "static local from the same function had different linkage");
2514 if (!HasPerVariableGuard) {
2522 llvm::ConstantInt *Bit = llvm::ConstantInt::get(GuardTy, 1ULL << GuardNum);
2523 llvm::LoadInst *LI = Builder.
CreateLoad(GuardAddr);
2525 Builder.CreateICmpEQ(Builder.CreateAnd(LI, Bit), Zero);
2534 Builder.
CreateStore(Builder.CreateOr(LI, Bit), GuardAddr);
2538 Builder.CreateBr(EndBlock);
2556 llvm::LoadInst *FirstGuardLoad = Builder.
CreateLoad(GuardAddr);
2557 FirstGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2558 llvm::LoadInst *InitThreadEpoch =
2561 Builder.CreateICmpSGT(FirstGuardLoad, InitThreadEpoch);
2572 llvm::LoadInst *SecondGuardLoad = Builder.
CreateLoad(GuardAddr);
2573 SecondGuardLoad->setOrdering(llvm::AtomicOrdering::Unordered);
2575 Builder.CreateICmpEQ(SecondGuardLoad, getAllOnesInt());
2577 Builder.CreateCondBr(ShouldDoInit, InitBlock, EndBlock);
2586 Builder.CreateBr(EndBlock);
2603 return (!MSInheritanceAttr::hasVBTableOffsetField(Inheritance) &&
2615 fields.push_back(CGM.
IntTy);
2619 fields.push_back(CGM.
IntTy);
2620 if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
2621 fields.push_back(CGM.
IntTy);
2622 if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
2623 fields.push_back(CGM.
IntTy);
2625 if (fields.size() == 1)
2630 void MicrosoftCXXABI::
2633 assert(fields.empty());
2638 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
2640 if (RD->nullFieldOffsetIsZero())
2641 fields.push_back(getZeroInt());
2643 fields.push_back(getAllOnesInt());
2648 fields.push_back(getZeroInt());
2649 if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
2650 fields.push_back(getZeroInt());
2651 if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
2652 fields.push_back(getAllOnesInt());
2658 GetNullMemberPointerFields(MPT, fields);
2659 if (fields.size() == 1)
2661 llvm::Constant *Res = llvm::ConstantStruct::getAnon(fields);
2662 assert(Res->getType() == ConvertMemberPointerType(MPT));
2667 MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
2668 bool IsMemberFunction,
2671 unsigned VBTableIndex) {
2676 if (MSInheritanceAttr::hasOnlyOneField(IsMemberFunction, Inheritance))
2680 fields.push_back(FirstField);
2682 if (MSInheritanceAttr::hasNVOffsetField(IsMemberFunction, Inheritance))
2683 fields.push_back(llvm::ConstantInt::get(
2686 if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance)) {
2689 Offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
2694 if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
2695 fields.push_back(llvm::ConstantInt::get(CGM.
IntTy, VBTableIndex));
2697 return llvm::ConstantStruct::getAnon(fields);
2705 MSInheritanceAttr::Keyword_virtual_inheritance)
2706 offset -= getContext().getOffsetOfBaseWithVBPtr(RD);
2707 llvm::Constant *FirstField =
2709 return EmitFullMemberPointer(FirstField,
false, RD,
2713 llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(
const APValue &MP,
2718 return EmitNullMemberPointer(DstTy);
2724 if (
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
2725 C = EmitMemberFunctionPointer(MD);
2728 C = EmitMemberDataPointer(DstTy, FieldOffset);
2731 if (!MemberPointerPath.empty()) {
2732 const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext());
2736 ->castAs<MemberPointerType>();
2744 if (DerivedMember) {
2752 if (BS.getType()->getAsCXXRecordDecl()->getCanonicalDecl() ==
2754 DerivedToBasePath.push_back(&BS);
2757 assert(DerivedToBasePath.size() == MemberPointerPath.size());
2759 CastKind CK = DerivedMember ? CK_DerivedToBaseMemberPointer
2760 : CK_BaseToDerivedMemberPointer;
2761 C = EmitMemberPointerConversion(SrcTy, DstTy, CK, DerivedToBasePath.begin(),
2762 DerivedToBasePath.end(), C);
2768 MicrosoftCXXABI::EmitMemberFunctionPointer(
const CXXMethodDecl *MD) {
2769 assert(MD->
isInstance() &&
"Member function must not be static!");
2775 unsigned VBTableIndex = 0;
2776 llvm::Constant *FirstField;
2793 FirstField = EmitVirtualMemPtrThunk(MD, ML);
2797 VBTableIndex = VTableContext.getVBTableIndex(RD, ML.
VBase) * 4;
2800 if (VBTableIndex == 0 &&
2802 MSInheritanceAttr::Keyword_virtual_inheritance)
2803 NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD);
2806 FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.
VoidPtrTy);
2807 return EmitFullMemberPointer(FirstField,
true, RD,
2808 NonVirtualBaseAdjustment, VBTableIndex);
2823 llvm::ICmpInst::Predicate Eq;
2824 llvm::Instruction::BinaryOps
And, Or;
2826 Eq = llvm::ICmpInst::ICMP_NE;
2827 And = llvm::Instruction::Or;
2830 Eq = llvm::ICmpInst::ICMP_EQ;
2832 Or = llvm::Instruction::Or;
2841 return Builder.CreateICmp(Eq, L, R);
2844 llvm::Value *L0 = Builder.CreateExtractValue(L, 0,
"lhs.0");
2845 llvm::Value *R0 = Builder.CreateExtractValue(R, 0,
"rhs.0");
2846 llvm::Value *Cmp0 = Builder.CreateICmp(Eq, L0, R0,
"memptr.cmp.first");
2850 llvm::StructType *LType = cast<llvm::StructType>(L->getType());
2851 for (
unsigned I = 1, E = LType->getNumElements(); I != E; ++I) {
2852 llvm::Value *LF = Builder.CreateExtractValue(L, I);
2853 llvm::Value *RF = Builder.CreateExtractValue(R, I);
2854 llvm::Value *Cmp = Builder.CreateICmp(Eq, LF, RF,
"memptr.cmp.rest");
2856 Res = Builder.CreateBinOp(And, Res, Cmp);
2864 llvm::Value *Zero = llvm::Constant::getNullValue(L0->getType());
2865 llvm::Value *IsZero = Builder.CreateICmp(Eq, L0, Zero,
"memptr.cmp.iszero");
2866 Res = Builder.CreateBinOp(Or, Res, IsZero);
2871 return Builder.CreateBinOp(And, Res, Cmp0,
"memptr.cmp");
2882 fields.push_back(llvm::Constant::getNullValue(CGM.
VoidPtrTy));
2884 GetNullMemberPointerFields(MPT, fields);
2885 assert(!fields.empty());
2887 if (MemPtr->getType()->isStructTy())
2888 FirstField = Builder.CreateExtractValue(MemPtr, 0);
2889 llvm::Value *Res = Builder.CreateICmpNE(FirstField, fields[0],
"memptr.cmp0");
2897 for (
int I = 1, E = fields.size(); I < E; ++I) {
2898 llvm::Value *Field = Builder.CreateExtractValue(MemPtr, I);
2899 llvm::Value *Next = Builder.CreateICmpNE(Field, fields[I],
"memptr.cmp");
2900 Res = Builder.CreateOr(Res, Next,
"memptr.tobool");
2906 llvm::Constant *Val) {
2909 llvm::Constant *FirstField = Val->getType()->isStructTy() ?
2910 Val->getAggregateElement(0U) : Val;
2911 return FirstField->isNullValue();
2916 if (isZeroInitializable(MPT) && Val->isNullValue())
2922 GetNullMemberPointerFields(MPT, Fields);
2923 if (Fields.size() == 1) {
2924 assert(Val->getType()->isIntegerTy());
2925 return Val == Fields[0];
2929 for (I = 0, E = Fields.size(); I != E; ++I) {
2930 if (Val->getAggregateElement(I) != Fields[I])
2946 Builder.CreateInBoundsGEP(This.
getPointer(), VBPtrOffset,
"vbptr");
2947 if (VBPtrOut) *VBPtrOut = VBPtr;
2952 if (
auto CI = dyn_cast<llvm::ConstantInt>(VBPtrOffset)) {
2963 VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2),
2967 llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableIndex);
2980 llvm::BasicBlock *OriginalBB =
nullptr;
2981 llvm::BasicBlock *SkipAdjustBB =
nullptr;
2982 llvm::BasicBlock *VBaseAdjustBB =
nullptr;
2989 OriginalBB = Builder.GetInsertBlock();
2993 Builder.CreateICmpNE(VBTableOffset, getZeroInt(),
2995 Builder.CreateCondBr(IsVirtual, VBaseAdjustBB, SkipAdjustBB);
3007 "member pointer representation requires a " 3008 "complete class type for %0 to perform this expression");
3011 offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
3016 GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr);
3017 llvm::Value *AdjustedBase = Builder.CreateInBoundsGEP(VBPtr, VBaseOffs);
3020 if (VBaseAdjustBB) {
3021 Builder.CreateBr(SkipAdjustBB);
3023 llvm::PHINode *Phi = Builder.CreatePHI(CGM.
Int8PtrTy, 2,
"memptr.base");
3024 Phi->addIncoming(Base.
getPointer(), OriginalBB);
3025 Phi->addIncoming(AdjustedBase, VBaseAdjustBB);
3028 return AdjustedBase;
3031 llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
3045 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3047 if (MemPtr->getType()->isStructTy()) {
3050 FieldOffset = Builder.CreateExtractValue(MemPtr, I++);
3051 if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
3052 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3053 if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
3054 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3058 if (VirtualBaseAdjustmentOffset) {
3059 Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset,
3069 Addr = Builder.CreateInBoundsGEP(Addr, FieldOffset,
"memptr.offset");
3080 assert(E->
getCastKind() == CK_DerivedToBaseMemberPointer ||
3081 E->
getCastKind() == CK_BaseToDerivedMemberPointer ||
3085 if (isa<llvm::Constant>(Src))
3086 return EmitMemberPointerConversion(E, cast<llvm::Constant>(Src));
3096 bool IsReinterpret = E->
getCastKind() == CK_ReinterpretMemberPointer;
3097 if (IsReinterpret && IsFunc)
3102 if (IsReinterpret &&
3109 llvm::Value *IsNotNull = EmitMemberPointerIsNotNull(CGF, Src, SrcTy);
3110 llvm::Constant *DstNull = EmitNullMemberPointer(DstTy);
3114 if (IsReinterpret) {
3117 assert(Src->getType() == DstNull->getType());
3118 return Builder.CreateSelect(IsNotNull, Src, DstNull);
3121 llvm::BasicBlock *OriginalBB = Builder.GetInsertBlock();
3124 Builder.CreateCondBr(IsNotNull, ConvertBB, ContinueBB);
3127 llvm::Value *Dst = EmitNonNullMemberPointerConversion(
3131 Builder.CreateBr(ContinueBB);
3135 llvm::PHINode *Phi = Builder.CreatePHI(DstNull->getType(), 2,
"memptr.converted");
3136 Phi->addIncoming(DstNull, OriginalBB);
3137 Phi->addIncoming(Dst, ConvertBB);
3141 llvm::Value *MicrosoftCXXABI::EmitNonNullMemberPointerConversion(
3151 bool IsConstant = isa<llvm::Constant>(Src);
3155 llvm::Value *NonVirtualBaseAdjustment = getZeroInt();
3156 llvm::Value *VirtualBaseAdjustmentOffset = getZeroInt();
3158 if (!MSInheritanceAttr::hasOnlyOneField(IsFunc, SrcInheritance)) {
3161 FirstField = Builder.CreateExtractValue(Src, I++);
3162 if (MSInheritanceAttr::hasNVOffsetField(IsFunc, SrcInheritance))
3163 NonVirtualBaseAdjustment = Builder.CreateExtractValue(Src, I++);
3164 if (MSInheritanceAttr::hasVBPtrOffsetField(SrcInheritance))
3165 VBPtrOffset = Builder.CreateExtractValue(Src, I++);
3166 if (MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance))
3167 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(Src, I++);
3170 bool IsDerivedToBase = (CK == CK_DerivedToBaseMemberPointer);
3176 llvm::Value *&NVAdjustField = IsFunc ? NonVirtualBaseAdjustment : FirstField;
3184 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3185 if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
3186 if (int64_t SrcOffsetToFirstVBase =
3187 getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) {
3188 llvm::Value *UndoSrcAdjustment = Builder.CreateSelect(
3190 llvm::ConstantInt::get(CGM.
IntTy, SrcOffsetToFirstVBase),
3192 NVAdjustField = Builder.CreateNSWAdd(NVAdjustField, UndoSrcAdjustment);
3203 llvm::Constant *BaseClassOffset = llvm::ConstantInt::get(
3209 if (IsDerivedToBase)
3210 NVDisp = Builder.CreateNSWSub(NVAdjustField, BaseClassOffset,
"adj");
3212 NVDisp = Builder.CreateNSWAdd(NVAdjustField, BaseClassOffset,
"adj");
3214 NVAdjustField = Builder.CreateSelect(SrcVBIndexEqZero, NVDisp, getZeroInt());
3219 if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance) &&
3220 MSInheritanceAttr::hasVBTableOffsetField(SrcInheritance)) {
3221 if (llvm::GlobalVariable *VDispMap =
3222 getAddrOfVirtualDisplacementMap(SrcRD, DstRD)) {
3224 VirtualBaseAdjustmentOffset, llvm::ConstantInt::get(CGM.
IntTy, 4));
3226 llvm::Constant *Mapping = VDispMap->getInitializer();
3227 VirtualBaseAdjustmentOffset =
3228 Mapping->getAggregateElement(cast<llvm::Constant>(VBIndex));
3231 VirtualBaseAdjustmentOffset =
3237 Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
3243 if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance)) {
3244 llvm::Value *DstVBPtrOffset = llvm::ConstantInt::get(
3246 getContext().getASTRecordLayout(DstRD).getVBPtrOffset().getQuantity());
3248 Builder.CreateSelect(DstVBIndexEqZero, getZeroInt(), DstVBPtrOffset);
3254 if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
3255 if (int64_t DstOffsetToFirstVBase =
3256 getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) {
3257 llvm::Value *DoDstAdjustment = Builder.CreateSelect(
3259 llvm::ConstantInt::get(CGM.
IntTy, DstOffsetToFirstVBase),
3261 NVAdjustField = Builder.CreateNSWSub(NVAdjustField, DoDstAdjustment);
3267 if (MSInheritanceAttr::hasOnlyOneField(IsFunc, DstInheritance)) {
3270 Dst = llvm::UndefValue::get(ConvertMemberPointerType(DstTy));
3272 Dst = Builder.CreateInsertValue(Dst, FirstField, Idx++);
3273 if (MSInheritanceAttr::hasNVOffsetField(IsFunc, DstInheritance))
3274 Dst = Builder.CreateInsertValue(Dst, NonVirtualBaseAdjustment, Idx++);
3275 if (MSInheritanceAttr::hasVBPtrOffsetField(DstInheritance))
3276 Dst = Builder.CreateInsertValue(Dst, VBPtrOffset, Idx++);
3277 if (MSInheritanceAttr::hasVBTableOffsetField(DstInheritance))
3278 Dst = Builder.CreateInsertValue(Dst, VirtualBaseAdjustmentOffset, Idx++);
3284 MicrosoftCXXABI::EmitMemberPointerConversion(
const CastExpr *E,
3285 llvm::Constant *Src) {
3292 return EmitMemberPointerConversion(SrcTy, DstTy, CK, E->
path_begin(),
3296 llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
3300 assert(CK == CK_DerivedToBaseMemberPointer ||
3301 CK == CK_BaseToDerivedMemberPointer ||
3302 CK == CK_ReinterpretMemberPointer);
3305 if (MemberPointerConstantIsNull(SrcTy, Src))
3306 return EmitNullMemberPointer(DstTy);
3311 if (CK == CK_ReinterpretMemberPointer)
3315 auto *Dst = cast<llvm::Constant>(EmitNonNullMemberPointerConversion(
3316 SrcTy, DstTy, CK, PathBegin, PathEnd, Src, Builder));
3321 CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
3333 MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
3339 llvm::Value *VirtualBaseAdjustmentOffset =
nullptr;
3341 if (MemPtr->getType()->isStructTy()) {
3344 FunctionPointer = Builder.CreateExtractValue(MemPtr, I++);
3345 if (MSInheritanceAttr::hasNVOffsetField(MPT, Inheritance))
3346 NonVirtualBaseAdjustment = Builder.CreateExtractValue(MemPtr, I++);
3347 if (MSInheritanceAttr::hasVBPtrOffsetField(Inheritance))
3348 VBPtrOffset = Builder.CreateExtractValue(MemPtr, I++);
3349 if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
3350 VirtualBaseAdjustmentOffset = Builder.CreateExtractValue(MemPtr, I++);
3353 if (VirtualBaseAdjustmentOffset) {
3354 ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This,
3355 VirtualBaseAdjustmentOffset, VBPtrOffset);
3360 if (NonVirtualBaseAdjustment) {
3363 Ptr = Builder.CreateInBoundsGEP(Ptr, NonVirtualBaseAdjustment);
3364 ThisPtrForCall = Builder.
CreateBitCast(Ptr, ThisPtrForCall->getType(),
3369 Builder.
CreateBitCast(FunctionPointer, FTy->getPointerTo());
3370 CGCallee Callee(FPT, FunctionPointer);
3375 return new MicrosoftCXXABI(CGM);
3409 StringRef MangledName(
"??_7type_info@@6B@");
3410 if (
auto VTable = CGM.
getModule().getNamedGlobal(MangledName))
3415 nullptr, MangledName);
3426 struct MSRTTIClass {
3428 IsPrivateOnPath = 1 | 8,
3432 HasHierarchyDescriptor = 64
3438 MSRTTIClass *getFirstChild() {
return this + 1; }
3439 static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
3440 return Child + 1 + Child->NumBases;
3444 uint32_t Flags, NumBases, OffsetInVBase;
3450 Flags = HasHierarchyDescriptor;
3452 VirtualRoot =
nullptr;
3456 Flags |= IsPrivate | IsPrivateOnPath;
3462 if (Parent->Flags & IsPrivateOnPath)
3463 Flags |= IsPrivateOnPath;
3464 VirtualRoot = Parent->VirtualRoot;
3470 MSRTTIClass *Child = getFirstChild();
3472 NumBases += Child->initialize(
this, &Base) + 1;
3473 Child = getNextChild(Child);
3478 static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(
QualType Ty) {
3489 return llvm::GlobalValue::LinkOnceODRLinkage;
3491 llvm_unreachable(
"Invalid linkage!");
3497 struct MSRTTIBuilder {
3499 HasBranchingHierarchy = 1,
3500 HasVirtualBranchingHierarchy = 2,
3501 HasAmbiguousBases = 4
3504 MSRTTIBuilder(MicrosoftCXXABI &ABI,
const CXXRecordDecl *RD)
3510 llvm::GlobalVariable *getBaseClassDescriptor(
const MSRTTIClass &Classes);
3511 llvm::GlobalVariable *
3513 llvm::GlobalVariable *getClassHierarchyDescriptor();
3514 llvm::GlobalVariable *getCompleteObjectLocator(
const VPtrInfo &Info);
3518 llvm::LLVMContext &VMContext;
3521 llvm::GlobalVariable::LinkageTypes
Linkage;
3522 MicrosoftCXXABI &ABI;
3531 Classes.push_back(MSRTTIClass(RD));
3539 llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases;
3540 llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases;
3541 llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases;
3542 for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
3543 if ((Class->Flags & MSRTTIClass::IsVirtual) &&
3544 !VirtualBases.insert(Class->RD).second) {
3545 Class = MSRTTIClass::getNextChild(Class);
3548 if (!UniqueBases.insert(Class->RD).second)
3549 AmbiguousBases.insert(Class->RD);
3552 if (AmbiguousBases.empty())
3554 for (MSRTTIClass &Class : Classes)
3555 if (AmbiguousBases.count(Class.RD))
3556 Class.Flags |= MSRTTIClass::IsAmbiguous;
3559 llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
3562 llvm::raw_svector_ostream Out(MangledName);
3563 ABI.getMangleContext().mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
3567 if (
auto CHD =
Module.getNamedGlobal(MangledName))
3573 Classes.front().initialize(
nullptr,
nullptr);
3576 for (
auto Class : Classes) {
3577 if (Class.RD->getNumBases() > 1)
3578 Flags |= HasBranchingHierarchy;
3581 if (Class.Flags & MSRTTIClass::IsAmbiguous)
3582 Flags |= HasAmbiguousBases;
3584 if ((Flags & HasBranchingHierarchy) && RD->
getNumVBases() != 0)
3585 Flags |= HasVirtualBranchingHierarchy;
3589 llvm::ConstantInt::get(CGM.
IntTy, 0)};
3592 auto Type = ABI.getClassHierarchyDescriptorType();
3593 auto CHD =
new llvm::GlobalVariable(
Module, Type,
true, Linkage,
3596 if (CHD->isWeakForLinker())
3597 CHD->setComdat(CGM.
getModule().getOrInsertComdat(CHD->getName()));
3599 auto *Bases = getBaseClassArray(Classes);
3602 llvm::Constant *Fields[] = {
3603 llvm::ConstantInt::get(CGM.
IntTy, 0),
3604 llvm::ConstantInt::get(CGM.
IntTy, Flags),
3605 llvm::ConstantInt::get(CGM.
IntTy, Classes.size()),
3606 ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(
3607 Bases->getValueType(), Bases,
3610 CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
3614 llvm::GlobalVariable *
3618 llvm::raw_svector_ostream Out(MangledName);
3619 ABI.getMangleContext().mangleCXXRTTIBaseClassArray(RD, Out);
3627 llvm::Type *PtrType = ABI.getImageRelativeType(
3628 ABI.getBaseClassDescriptorType()->getPointerTo());
3629 auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
3631 new llvm::GlobalVariable(
Module, ArrType,
3633 nullptr, MangledName);
3634 if (BCA->isWeakForLinker())
3635 BCA->setComdat(CGM.
getModule().getOrInsertComdat(BCA->getName()));
3639 for (MSRTTIClass &Class : Classes)
3640 BaseClassArrayData.push_back(
3641 ABI.getImageRelativeConstant(getBaseClassDescriptor(Class)));
3642 BaseClassArrayData.push_back(llvm::Constant::getNullValue(PtrType));
3643 BCA->setInitializer(llvm::ConstantArray::get(ArrType, BaseClassArrayData));
3647 llvm::GlobalVariable *
3648 MSRTTIBuilder::getBaseClassDescriptor(
const MSRTTIClass &Class) {
3651 uint32_t OffsetInVBTable = 0;
3652 int32_t VBPtrOffset = -1;
3653 if (Class.VirtualRoot) {
3655 OffsetInVBTable = VTableContext.
getVBTableIndex(RD, Class.VirtualRoot) * 4;
3661 llvm::raw_svector_ostream Out(MangledName);
3662 ABI.getMangleContext().mangleCXXRTTIBaseClassDescriptor(
3663 Class.RD, Class.OffsetInVBase, VBPtrOffset, OffsetInVBTable,
3668 if (
auto BCD =
Module.getNamedGlobal(MangledName))
3672 auto Type = ABI.getBaseClassDescriptorType();
3674 new llvm::GlobalVariable(
Module, Type,
true, Linkage,
3675 nullptr, MangledName);
3676 if (BCD->isWeakForLinker())
3677 BCD->setComdat(CGM.
getModule().getOrInsertComdat(BCD->getName()));
3680 llvm::Constant *Fields[] = {
3681 ABI.getImageRelativeConstant(
3683 llvm::ConstantInt::get(CGM.
IntTy, Class.NumBases),
3684 llvm::ConstantInt::get(CGM.
IntTy, Class.OffsetInVBase),
3685 llvm::ConstantInt::get(CGM.
IntTy, VBPtrOffset),
3686 llvm::ConstantInt::get(CGM.
IntTy, OffsetInVBTable),
3687 llvm::ConstantInt::get(CGM.
IntTy, Class.Flags),
3688 ABI.getImageRelativeConstant(
3689 MSRTTIBuilder(ABI, Class.RD).getClassHierarchyDescriptor()),
3691 BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
3695 llvm::GlobalVariable *
3696 MSRTTIBuilder::getCompleteObjectLocator(
const VPtrInfo &Info) {
3699 llvm::raw_svector_ostream Out(MangledName);
3700 ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info.
MangledPath, Out);
3704 if (
auto COL =
Module.getNamedGlobal(MangledName))
3709 int VFPtrOffset = 0;
3715 ->second.hasVtorDisp())
3719 llvm::StructType *Type = ABI.getCompleteObjectLocatorType();
3720 auto COL =
new llvm::GlobalVariable(
Module, Type,
true, Linkage,
3721 nullptr, MangledName);
3724 llvm::Constant *Fields[] = {
3725 llvm::ConstantInt::get(CGM.
IntTy, ABI.isImageRelative()),
3726 llvm::ConstantInt::get(CGM.
IntTy, OffsetToTop),
3727 llvm::ConstantInt::get(CGM.
IntTy, VFPtrOffset),
3728 ABI.getImageRelativeConstant(
3730 ABI.getImageRelativeConstant(getClassHierarchyDescriptor()),
3731 ABI.getImageRelativeConstant(COL),
3734 if (!ABI.isImageRelative())
3735 FieldsRef = FieldsRef.drop_back();
3736 COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef));
3737 if (COL->isWeakForLinker())
3738 COL->setComdat(CGM.
getModule().getOrInsertComdat(COL->getName()));
3743 bool &IsConst,
bool &IsVolatile,
3744 bool &IsUnaligned) {
3754 IsUnaligned =
false;
3756 if (!PointeeType.
isNull()) {
3777 MicrosoftCXXABI::getAddrOfCXXCatchHandlerType(
QualType Type,
3782 bool IsConst, IsVolatile, IsUnaligned;
3798 return CatchTypeInfo{getAddrOfRTTIDescriptor(Type)->stripPointerCasts(),
3806 llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(
QualType Type) {
3809 llvm::raw_svector_ostream Out(MangledName);
3810 getMangleContext().mangleCXXRTTI(Type, Out);
3814 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
3815 return llvm::ConstantExpr::getBitCast(GV, CGM.
Int8PtrTy);
3823 llvm::raw_svector_ostream Out(TypeInfoString);
3824 getMangleContext().mangleCXXRTTIName(Type, Out);
3828 llvm::Constant *Fields[] = {
3830 llvm::ConstantPointerNull::get(CGM.
Int8PtrTy),
3831 llvm::ConstantDataArray::getString(CGM.
getLLVMContext(), TypeInfoString)};
3832 llvm::StructType *TypeDescriptorType =
3833 getTypeDescriptorType(TypeInfoString);
3834 auto *Var =
new llvm::GlobalVariable(
3835 CGM.
getModule(), TypeDescriptorType,
false,
3836 getLinkageForRTTI(Type),
3837 llvm::ConstantStruct::get(TypeDescriptorType, Fields),
3839 if (Var->isWeakForLinker())
3840 Var->setComdat(CGM.
getModule().getOrInsertComdat(Var->getName()));
3841 return llvm::ConstantExpr::getBitCast(Var, CGM.
Int8PtrTy);
3845 llvm::GlobalVariable *
3846 MicrosoftCXXABI::getMSCompleteObjectLocator(
const CXXRecordDecl *RD,
3848 return MSRTTIBuilder(*
this, RD).getCompleteObjectLocator(Info);
3851 void MicrosoftCXXABI::emitCXXStructor(
GlobalDecl GD) {
3852 if (
auto *ctor = dyn_cast<CXXConstructorDecl>(GD.
getDecl())) {
3854 llvm::Function *Fn =
3860 auto *dtor = cast<CXXDestructorDecl>(GD.
getDecl());
3866 dtor->getParent()->getNumVBases() == 0)
3877 if (Fn->isWeakForLinker())
3878 Fn->setComdat(CGM.
getModule().getOrInsertComdat(Fn->getName()));
3888 llvm::raw_svector_ostream Out(ThunkName);
3889 getMangleContext().mangleCXXCtor(CD, CT, Out);
3892 if (llvm::GlobalValue *GV = CGM.
getModule().getNamedValue(ThunkName))
3893 return cast<llvm::Function>(GV);
3899 QualType RecordTy = getContext().getRecordType(RD);
3901 ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.
getModule());
3902 ThunkFn->setCallingConv(static_cast<llvm::CallingConv::ID>(
3904 if (ThunkFn->isWeakForLinker())
3905 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
3916 buildThisParam(CGF, FunctionArgs);
3922 &getContext().Idents.get(
"src"),
3923 getContext().getLValueReferenceType(RecordTy,
3927 FunctionArgs.push_back(&SrcParam);
3934 &getContext().Idents.get(
"is_most_derived"),
3938 FunctionArgs.push_back(&IsMostDerived);
3946 setCXXABIThisValue(CGF, loadIncomingCXXThis(CGF));
3966 assert(PD->hasDefaultArg() &&
"ctor closure lacks default args");
3967 ArgVec.push_back(PD->getDefaultArg());
3973 CGF.
EmitCallArgs(Args, FPT, llvm::makeArrayRef(ArgVec), CD, IsCopy ? 1 : 0);
3976 AddedStructorArgs ExtraArgs =
3981 llvm::Constant *CalleePtr =
3986 Args, CD,
Ctor_Complete, ExtraArgs.Prefix, ExtraArgs.Suffix);
3998 llvm::Constant *MicrosoftCXXABI::getCatchableType(
QualType T,
4000 int32_t VBPtrOffset,
4012 uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity();
4015 llvm::raw_svector_ostream Out(MangledName);
4016 getMangleContext().mangleCXXCatchableType(T, CD, CT, Size, NVOffset,
4017 VBPtrOffset, VBIndex, Out);
4019 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4020 return getImageRelativeConstant(GV);
4024 llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(T));
4028 llvm::Constant *CopyCtor;
4035 CopyCtor = llvm::ConstantExpr::getBitCast(CopyCtor, CGM.
Int8PtrTy);
4037 CopyCtor = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4039 CopyCtor = getImageRelativeConstant(CopyCtor);
4041 bool IsScalar = !RD;
4042 bool HasVirtualBases =
false;
4043 bool IsStdBadAlloc =
false;
4048 HasVirtualBases = RD->getNumVBases() > 0;
4050 IsStdBadAlloc = II->isStr(
"bad_alloc") && RD->isInStdNamespace();
4058 if (HasVirtualBases)
4063 llvm::Constant *Fields[] = {
4064 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4066 llvm::ConstantInt::get(CGM.
IntTy, NVOffset),
4067 llvm::ConstantInt::get(CGM.
IntTy, VBPtrOffset),
4068 llvm::ConstantInt::get(CGM.
IntTy, VBIndex),
4069 llvm::ConstantInt::get(CGM.
IntTy, Size),
4072 llvm::StructType *CTType = getCatchableTypeType();
4073 auto *GV =
new llvm::GlobalVariable(
4074 CGM.
getModule(), CTType,
true, getLinkageForRTTI(T),
4075 llvm::ConstantStruct::get(CTType, Fields), MangledName);
4076 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4077 GV->setSection(
".xdata");
4078 if (GV->isWeakForLinker())
4079 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4080 return getImageRelativeConstant(GV);
4083 llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(
QualType T) {
4087 llvm::GlobalVariable *&CTA = CatchableTypeArrays[T];
4112 if (MostDerivedClass) {
4119 Classes.front().initialize(
nullptr,
nullptr);
4121 for (
const MSRTTIClass &Class : Classes) {
4124 (MSRTTIClass::IsPrivateOnPath | MSRTTIClass::IsAmbiguous))
4127 uint32_t OffsetInVBTable = 0;
4128 int32_t VBPtrOffset = -1;
4129 if (Class.VirtualRoot) {
4140 CatchableTypes.insert(getCatchableType(RTTITy, Class.OffsetInVBase,
4141 VBPtrOffset, OffsetInVBTable));
4149 CatchableTypes.insert(getCatchableType(T));
4162 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4173 CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));
4175 uint32_t NumEntries = CatchableTypes.size();
4177 getImageRelativeType(getCatchableTypeType()->getPointerTo());
4178 llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries);
4179 llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries);
4180 llvm::Constant *Fields[] = {
4181 llvm::ConstantInt::get(CGM.
IntTy, NumEntries),
4182 llvm::ConstantArray::get(
4183 AT, llvm::makeArrayRef(CatchableTypes.begin(),
4184 CatchableTypes.end()))
4188 llvm::raw_svector_ostream Out(MangledName);
4189 getMangleContext().mangleCXXCatchableTypeArray(T, NumEntries, Out);
4191 CTA =
new llvm::GlobalVariable(
4192 CGM.
getModule(), CTAType,
true, getLinkageForRTTI(T),
4193 llvm::ConstantStruct::get(CTAType, Fields), MangledName);
4194 CTA->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4195 CTA->setSection(
".xdata");
4196 if (CTA->isWeakForLinker())
4197 CTA->setComdat(CGM.
getModule().getOrInsertComdat(CTA->getName()));
4201 llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(
QualType T) {
4202 bool IsConst, IsVolatile, IsUnaligned;
4207 llvm::GlobalVariable *CTA = getCatchableTypeArray(T);
4212 uint32_t NumEntries =
4213 cast<llvm::ConstantInt>(CTA->getInitializer()->getAggregateElement(0U))
4214 ->getLimitedValue();
4218 llvm::raw_svector_ostream Out(MangledName);
4219 getMangleContext().mangleCXXThrowInfo(T, IsConst, IsVolatile, IsUnaligned,
4225 if (llvm::GlobalVariable *GV = CGM.
getModule().getNamedGlobal(MangledName))
4241 llvm::Constant *CleanupFn = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
4244 if (!DtorD->isTrivial())
4245 CleanupFn = llvm::ConstantExpr::getBitCast(
4249 llvm::Constant *ForwardCompat =
4250 getImageRelativeConstant(llvm::Constant::getNullValue(CGM.
Int8PtrTy));
4251 llvm::Constant *PointerToCatchableTypes = getImageRelativeConstant(
4252 llvm::ConstantExpr::getBitCast(CTA, CGM.
Int8PtrTy));
4253 llvm::StructType *TIType = getThrowInfoType();
4254 llvm::Constant *Fields[] = {
4255 llvm::ConstantInt::get(CGM.
IntTy, Flags),
4256 getImageRelativeConstant(CleanupFn),
4258 PointerToCatchableTypes
4260 auto *GV =
new llvm::GlobalVariable(
4261 CGM.
getModule(), TIType,
true, getLinkageForRTTI(T),
4262 llvm::ConstantStruct::get(TIType, Fields), StringRef(MangledName));
4263 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4264 GV->setSection(
".xdata");
4265 if (GV->isWeakForLinker())
4266 GV->setComdat(CGM.
getModule().getOrInsertComdat(GV->getName()));
4281 llvm::GlobalVariable *TI = getThrowInfo(ThrowType);
4291 std::pair<llvm::Value *, const CXXRecordDecl *>
4294 std::tie(This, std::ignore, RD) =
ReturnValueSlot - Contains the address where the return value of a function can be stored...
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.
struct clang::ReturnAdjustment::VirtualAdjustment::@134 Microsoft
static QualType decomposeTypeForEH(ASTContext &Context, QualType T, bool &IsConst, bool &IsVolatile, bool &IsUnaligned)
llvm::IntegerType * IntTy
int
CharUnits getIntAlign() const
void setSRetAfterThis(bool AfterThis)
External linkage, which indicates that the entity can be referred to from other translation units...
Other implicit parameter.
A (possibly-)qualified type.
static llvm::CallBase * emitRTtypeidCall(CodeGenFunction &CGF, llvm::Value *Argument)
CodeGenTypes & getTypes()
llvm::Type * ConvertTypeForMem(QualType T)
unsigned getNumBases() const
Retrieves the number of base classes of this class.
uint32_t VBPtrOffset
The offset (in bytes) of the vbptr, relative to the beginning of the derived class.
Internal linkage according to the Modules TS, but can be referred to from other translation units ind...
const Expr * getSubExpr() const
Address CreateMemTemp(QualType T, const Twine &Name="tmp", Address *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
llvm::LLVMContext & getLLVMContext()
static void detectAmbiguousBases(SmallVectorImpl< MSRTTIClass > &Classes)
Find ambiguity among base classes.
CXXDtorType getDtorType() const
The standard implementation of ConstantInitBuilder used in Clang.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
No linkage, which means that the entity is unique and can only be referred to from within its scope...
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
QualType getThisType() const
Return the type of the this pointer.
const Type * getTypeForDecl() 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.
bool isVariadic() const
Whether this function prototype is variadic.
CharUnits VFPtrOffset
This is the offset of the vfptr from the start of the last vbase, or the complete type if there are n...
const CGFunctionInfo & arrangeCXXMethodType(const CXXRecordDecl *RD, const FunctionProtoType *FTP, const CXXMethodDecl *MD)
Arrange the argument and result information for a call to an unknown C++ non-static member function o...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
bool isPOD() const
Whether this class is a POD-type (C++ [class]p4)
The base class of the type hierarchy.
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool isZero() const
isZero - Test whether the quantity equals zero.
const NestedNameSpecifier * Specifier
bool isFuncTypeConvertible(const FunctionType *FT)
isFuncTypeConvertible - Utility to check whether a function type can be converted to an LLVM type (i...
Linkage getLinkage() const
Determine the linkage of this type.
BasePath MangledPath
The bases from the inheritance path that got used to mangle the vbtable name.
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
Represents a C++ constructor within a class.
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D)
Try to emit a base destructor as an alias to its primary base-class destructor.
static llvm::FunctionCallee getInitThreadFooterFn(CodeGenModule &CGM)
Default closure variant of a ctor.
MSInheritanceAttr::Spelling getMSInheritanceModel() const
Returns the inheritance model used for this record.
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
const CXXBaseSpecifier *const * path_const_iterator
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
GlobalDecl getWithCtorType(CXXCtorType Type)
Represents a variable declaration or definition.
Address getObjectAddress(CodeGenFunction &CGF) const
Returns the address of the object within this declaration.
const CXXRecordDecl * VBase
If nonnull, holds the last vbase which contains the vfptr that the method definition is adjusted to...
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
const T * getAs() const
Member-template getAs<specific type>'.
A this pointer adjustment.
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)
DiagnosticsEngine & getDiags() const
Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")
Given a pointer to i8, adjust it by a given constant offset.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
llvm::Value * getPointer() const
A C++ throw-expression (C++ [except.throw]).
bool hasDefinition() const
Represents a parameter to a function.
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have...
unsigned getAddressSpace() const
Return the address space that this address resides in.
void add(RValue rvalue, QualType type)
const ValueDecl * getMemberPointerDecl() const
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
int32_t VBOffsetOffset
The offset (in bytes) of the vbase offset in the vbtable.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
One of these records is kept for each identifier that is lexed.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const CXXRecordDecl * NearestVBase
virtual void mangleCXXVFTable(const CXXRecordDecl *Derived, ArrayRef< const CXXRecordDecl *> BasePath, raw_ostream &Out)=0
Mangle vftable symbols.
bool ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
llvm::IntegerType * SizeTy
bool isReferenceType() const
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
__DEVICE__ int max(int __a, int __b)
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.
Describes a module or submodule.
static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM)
bool hasPrivateFields() const
bool hasProtectedFields() const
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
ArrayRef< ParmVarDecl * > parameters() const
static bool hasMicrosoftABIRestrictions(const CXXRecordDecl *RD)
ArrayRef< VTableComponent > vtable_components() const
FunctionDecl * getOperatorDelete() const
Address CreateElementBitCast(Address Addr, llvm::Type *Ty, const llvm::Twine &Name="")
Cast the element type of the given address to a different type, preserving information like the align...
CharUnits - This is an opaque type for sizes expressed in character units.
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...
AccessSpecifier getAccessSpecifier() const
Returns the access specifier for this base specifier.
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
const CXXRecordDecl * IntroducingObject
This is the class that introduced the vptr by declaring new virtual methods or virtual bases...
path_iterator path_begin()
CharUnits getAlignment() const
Return the alignment of this pointer.
llvm::PointerType * VoidPtrTy
Concrete class used by the front-end to report problems and issues.
static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM)
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
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.
QualType getExceptionObjectType(QualType T) const
const VPtrInfoVector & getVFPtrOffsets(const CXXRecordDecl *RD)
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, QualType DeleteTy, llvm::Value *NumElements=nullptr, CharUnits CookieSize=CharUnits())
static bool hasDefaultCXXMethodCC(ASTContext &Context, const CXXMethodDecl *MD)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
void ForceCleanup(std::initializer_list< llvm::Value **> ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
const VBaseOffsetsMapTy & getVBaseOffsetsMap() const
const CGFunctionInfo & arrangeCXXMethodDeclaration(const CXXMethodDecl *MD)
C++ methods have some special rules and also have implicit parameters.
GlobalDecl CurGD
CurGD - The GlobalDecl for the current function being compiled.
CharUnits getPointerAlign() const
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
GlobalDecl getWithDtorType(CXXDtorType Type)
struct clang::ThisAdjustment::VirtualAdjustment::@136 Microsoft
CallingConv getDefaultCallingConvention(bool IsVariadic, bool IsCXXMethod, bool IsBuiltin=false) const
Retrieves the default calling convention for the current target.
bool isNegative() const
isNegative - Test whether the quantity is less than zero.
CXXRecordDecl * getMostRecentNonInjectedDecl()
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
CanQualType getReturnType() const
static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Represents a prototype with parameter type info, e.g.
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...
CastKind
CastKind - The kind of operation required for a conversion.
RValue - This trivial value class is used to represent the result of an expression that is evaluated...
union clang::ReturnAdjustment::VirtualAdjustment Virtual
Module linkage, which indicates that the entity can be referred to from other translation units withi...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
llvm::Value * GetVTablePtr(Address This, llvm::Type *VTableTy, const CXXRecordDecl *VTableClass)
GetVTablePtr - Return the Value of the vtable pointer member pointed to by This.
CXXDtorType
C++ destructor types.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
This represents one expression.
bool isPositive() const
isPositive - Test whether the quantity is greater than zero.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited...
void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo, 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.
const CGFunctionInfo & arrangeNullaryFunction()
A nullary function is a freestanding function of type 'void ()'.
static llvm::FunctionCallee getInitThreadAbortFn(CodeGenModule &CGM)
const T * castAs() const
Member-template castAs<specific type>.
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
Represents a C++ destructor within a class.
VarDecl * getExceptionDecl() const
QualType getTagDeclType(const TagDecl *Decl) const
Return the unique reference to the type for the specified TagDecl (struct/union/class/enum) decl...
bool isNullPtrType() const
llvm::PointerType * getType() const
Return the type of the pointer value.
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
DeclContext * getDeclContext()
TLSKind getTLSKind() const
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
MicrosoftVTableContext & getMicrosoftVTableContext()
static bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
llvm::LLVMContext & getLLVMContext()
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
llvm::IntegerType * Int32Ty
bool hasNonTrivialDestructor() const
Determine whether this class has a non-trivial destructor (C++ [class.dtor]p3)
bool hasExtendableVFPtr() const
hasVFPtr - Does this class have a virtual function table pointer that can be extended by a derived cl...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
void GenerateCXXGlobalInitFunc(llvm::Function *Fn, ArrayRef< llvm::Function *> CXXThreadLocals, ConstantAddress Guard=ConstantAddress::invalid())
GenerateCXXGlobalInitFunc - Generates code for initializing global variables.
llvm::Value * EmitCastToVoidPtr(llvm::Value *value)
Emit a cast to void* in the appropriate address space.
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
const TargetInfo & getTarget() const
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr, bool PerformInit)
EmitCXXGlobalVarDeclInit - Create the initializer for a C++ variable with global storage.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
ASTContext & getContext() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool nullFieldOffsetIsZero() const
In the Microsoft C++ ABI, use zero for the field offset of a null data member pointer if we can guara...
The COMDAT used for dtors.
CallingConv
CallingConv - Specifies the calling convention that a function uses.
GlobalDecl - represents a global declaration.
bool isConstQualified() const
Determine whether this type is const-qualified.
The l-value was considered opaque, so the alignment was determined from a type.
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
unsigned getVBTableIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the index of VBase in the vbtable of Derived.
unsigned getEffectiveCallingConvention() const
getEffectiveCallingConvention - Return the actual calling convention to use, which may depend on the ...
Address CreateBitCast(Address Addr, llvm::Type *Ty, const llvm::Twine &Name="")
static llvm::FunctionCallee getInitThreadHeaderFn(CodeGenModule &CGM)
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
bool isMemberDataPointer() const
Returns true if the member type (i.e.
Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, const llvm::Twine &Name="")
CastKind getCastKind() const
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **callOrInvoke, SourceLocation Loc)
EmitCall - Generate a call of the given function, expecting the given result type, and using the given argument list which specifies both the LLVM arguments and the types they were derived from.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
Represents a call to a member function that may be written either with member call syntax (e...
ASTContext & getASTContext() const LLVM_READONLY
static bool IsSizeGreaterThan128(const CXXRecordDecl *RD)
const Decl * getDecl() const
Represents a single component in a vtable.
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
Represents a static or instance method of a struct/union/class.
const VTableLayout & getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset)
bool isInstanceMethod() const
QualType getAllocatedType() const
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
void createVTableInitializer(ConstantStructBuilder &builder, const VTableLayout &layout, llvm::Constant *rtti)
Add vtable components for the given vtable layout to the given global initializer.
const CXXRecordDecl * ObjectWithVPtr
This is the most derived class that has this vptr at offset zero.
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.
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after...
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
All available information about a concrete callee.
bool canPassInRegisters() const
Determine whether this class can be passed in registers.
MangleContext & getMangleContext()
Gets the mangle context.
llvm::Instruction * CurrentFuncletPad
constexpr XRayInstrMask None
CGCXXABI * CreateMicrosoftCXXABI(CodeGenModule &CGM)
Creates a Microsoft-family ABI.
static void mangleVFTableName(MicrosoftMangleContext &MangleContext, const CXXRecordDecl *RD, const VPtrInfo &VFPtr, SmallString< 256 > &Name)
bool isMemberPointerToDerivedMember() const
The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler...
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
CXXCtorType
C++ constructor types.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
void addUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.used metadata.
FunctionArgList - Type for representing both the decl and type of parameters to a function...
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
CXXRecordDecl * getMostRecentCXXRecordDecl() const
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is virtually derived from the class Base.
void ErrorUnsupported(const Stmt *S, const char *Type)
Print out an error that codegen doesn't support the specified stmt yet.
CGFunctionInfo - Class to encapsulate the information about a function definition.
This class organizes the cross-function state that is used while generating LLVM code.
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset...
llvm::GlobalValue * GetGlobalValue(StringRef Ref)
Dataflow Directional Tag Classes.
External linkage within a unique namespace.
static bool isDeletingDtor(GlobalDecl GD)
uint64_t Index
Method's index in the vftable.
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
const VPtrInfoVector & enumerateVBTables(const CXXRecordDecl *RD)
llvm::LoadInst * CreateAlignedLoad(llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
llvm::Constant * getPointer() const
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined...
A pointer to member type per C++ 8.3.3 - Pointers to members.
CharUnits NonVirtualOffset
IntroducingObject is at this offset from its containing complete object or virtual base...
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::Module & getModule() const
void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO)
CharUnits getVBaseAlignment(CharUnits DerivedAlign, const CXXRecordDecl *Derived, const CXXRecordDecl *VBase)
Returns the assumed alignment of a virtual base of a class.
ArrayRef< const CXXRecordDecl * > getMemberPointerPath() const
llvm::Function * 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...
union clang::ThisAdjustment::VirtualAdjustment Virtual
bool hasNonTrivialCopyAssignment() const
Determine whether this class has a non-trivial copy assignment operator (C++ [class.copy]p11, C++11 [class.copy]p25)
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value *> args)
Emits a call or invoke to the given noreturn runtime function.
void AppendLinkerOptions(StringRef Opts)
Appends Opts to the "llvm.linker.options" metadata value.
static llvm::GlobalVariable * getTypeInfoVTable(CodeGenModule &CGM)
StructBuilder beginStruct(llvm::StructType *structTy=nullptr)
const CXXRecordDecl * getVBaseWithVPtr() const
The vptr is stored inside the non-virtual component of this virtual base.
Implements C++ ABI-specific code generation functions.
This class organizes the cross-module state that is used while lowering AST types to LLVM types...
llvm::PointerType * Int8PtrTy
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
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.
StringRef getMangledName(GlobalDecl GD)
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false)
Create or return a runtime function declaration with the specified type and name. ...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat]...
ABIArgInfo & getReturnInfo()
Represents a base class of a C++ class.
bool isObjectType() const
Determine whether this type is an object type.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
CharUnits getIntSize() const
uint64_t getFieldOffset(const ValueDecl *FD) const
Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
llvm::IntegerType * PtrDiffTy
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
static bool isInstanceMethod(const Decl *D)
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")
bool hasUnaligned() const
Represents a C++ struct/union/class.
bool isMemberFunctionPointer() const
Returns true if the member type (i.e.
llvm::Function * CreateGlobalInitOrDestructFunction(llvm::FunctionType *ty, const Twine &name, const CGFunctionInfo &FI, SourceLocation Loc=SourceLocation(), bool TLS=false)
CXXCatchStmt - This represents a C++ catch block.
llvm::Type * ConvertType(QualType T)
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
A specialization of Address that requires the address to be an LLVM Constant.
int32_t VtordispOffset
The offset of the vtordisp (in bytes), relative to the ECX.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
No linkage according to the standard, but is visible from other translation units because of types de...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, llvm::FunctionType *FTy)
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
llvm::DenseMap< const CXXRecordDecl *, VBaseInfo > VBaseOffsetsMapTy
bool isGlobalDelete() const
Copying closure variant of a ctor.
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, CastExpr::path_const_iterator End)
CharUnits FullOffsetInMDC
Static offset from the top of the most derived class to this vfptr, including any virtual base offset...
const CGFunctionInfo & arrangeMSCtorClosure(const CXXConstructorDecl *CD, CXXCtorType CT)
Struct with all information about dynamic [sub]class needed to set vptr.
void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
llvm::Function * codegenCXXStructor(GlobalDecl GD)
MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD)
static RValue get(llvm::Value *V)
GVALinkage
A more specific kind of linkage than enum Linkage.
Holds information about the inheritance path to a virtual base or function table pointer.
bool isPointerType() const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, CharUnits Align, bool IsVolatile=false)
uint32_t VBIndex
Index of the virtual base in the vbtable.
LValue - This represents an lvalue references.
Information for lazily generating a cleanup.
This represents a decl that may have a name.
void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr, llvm::FunctionCallee Callee)
Emit a musttail call for a thunk with a potentially adjusted this pointer.
BasePath PathToIntroducingObject
This holds the base classes path from the complete type to the first base with the given vfptr offset...
const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD)
bool CurFuncIsThunk
In C++, whether we are code generating a thunk.
Notes how many arguments were added to the beginning (Prefix) and ending (Suffix) of an arg list...
RecordArgABI
Specify how one should pass an argument of a record type.
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value *> args, const Twine &name="")
Emits a call or invoke instruction to the given runtime function.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
CallArgList - Type for representing both the value and type of arguments in a call.
int32_t VBPtrOffset
The offset of the vbptr of the derived class (in bytes), relative to the ECX after vtordisp adjustmen...
void PopCleanupBlock(bool FallThroughIsBranchThrough=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
static void serializeClassHierarchy(SmallVectorImpl< MSRTTIClass > &Classes, const CXXRecordDecl *RD)
Recursively serializes a class hierarchy in pre-order depth first order.
base_class_range vbases()
static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
llvm::Value * EmitVTableTypeCheckedLoad(const CXXRecordDecl *RD, llvm::Value *VTable, uint64_t VTableByteOffset)
Emit a type checked load from the given vtable.
SourceLocation getLocation() const
QualType getPointeeType() const
bool isExternallyVisible() const
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr *> VL, ArrayRef< Expr *> PL, ArrayRef< Expr *> IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
bool isNoDestroy(const ASTContext &) const
Do we need to emit an exit-time destructor for this variable?