23#include "llvm/IR/IntrinsicInst.h"
24#include "llvm/Transforms/Utils/Cloning.h"
33 : CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {}
37 return GetOrCreateLLVMFunction(Name, FnTy, GD,
true,
42 llvm::GlobalVariable *VTable =
43 CGM.getCXXABI().getAddrOfVTable(RD,
CharUnits());
48 llvm::Function *ThunkFn,
bool ForVTable,
58 ThunkFn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
59 ThunkFn->setDSOLocal(
true);
63 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
82 llvm::BasicBlock *AdjustNull =
nullptr;
83 llvm::BasicBlock *AdjustNotNull =
nullptr;
84 llvm::BasicBlock *AdjustEnd =
nullptr;
106 if (NullCheckValue) {
107 CGF.
Builder.CreateBr(AdjustEnd);
109 CGF.
Builder.CreateBr(AdjustEnd);
112 llvm::PHINode *PHI = CGF.
Builder.CreatePHI(ReturnValue->getType(), 2);
113 PHI->addIncoming(ReturnValue, AdjustNotNull);
114 PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()),
128 llvm::ValueToValueMapTy &VMap) {
130 auto *DIS = Fn->getSubprogram();
133 auto *NewDIS = llvm::MDNode::replaceWithDistinct(DIS->clone());
138 NewDIS->replaceRetainedNodes(llvm::MDTuple::get(Fn->getContext(), {}));
139 VMap.MD()[DIS].reset(NewDIS);
151 auto PrepareVariableMapping = [&VMap](llvm::DILocalVariable *DILocal) {
152 if (DILocal->isResolved())
155 if (llvm::DIType *Ty = DILocal->getType(); Ty && !Ty->isResolved())
156 VMap.MD()[Ty].reset(Ty);
161 for (
auto &BB : *Fn) {
163 for (llvm::DbgVariableRecord &DVR :
164 llvm::filterDbgVars(I.getDbgRecordRange()))
165 PrepareVariableMapping(DVR.getVariable());
167 if (
auto *DII = dyn_cast<llvm::DbgVariableIntrinsic>(&I))
168 PrepareVariableMapping(DII->getVariable());
199 llvm::Type *Ty =
CGM.getTypes().GetFunctionType(FnInfo);
200 llvm::Value *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
207 CGM.ErrorUnsupported(MD,
"return-adjusting thunk with variadic arguments");
210 assert(!BaseFn->isDeclaration() &&
"cannot clone undefined variadic method");
213 llvm::ValueToValueMapTy VMap;
218 llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
219 Fn->replaceAllUsesWith(NewFn);
221 Fn->eraseFromParent();
228 llvm::Function::arg_iterator AI = Fn->arg_begin();
229 if (
CGM.ReturnTypeUsesSRet(FnInfo))
237 llvm::BasicBlock *EntryBB = &Fn->front();
238 llvm::BasicBlock::iterator ThisStore =
239 llvm::find_if(*EntryBB, [&](llvm::Instruction &I) {
242 assert(ThisStore != EntryBB->end() &&
243 "Store of this should be in entry block?");
245 Builder.SetInsertPoint(&*ThisStore);
248 llvm::Value *AdjustedThisPtr =
CGM.getCXXABI().performThisAdjustment(
249 *
this, ThisPtr, ThisValueClass, Thunk);
250 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr,
251 ThisStore->getOperand(0)->getType());
252 ThisStore->setOperand(0, AdjustedThisPtr);
256 for (llvm::BasicBlock &BB : *Fn) {
257 llvm::Instruction *T = BB.getTerminator();
260 T->eraseFromParent();
274 bool IsUnprototyped) {
275 assert(!
CurGD.getDecl() &&
"CurGD was already set!");
284 ResultType =
CGM.getContext().VoidTy;
285 else if (
CGM.getCXXABI().HasThisReturn(GD))
286 ResultType = ThisType;
287 else if (
CGM.getCXXABI().hasMostDerivedReturn(GD))
288 ResultType =
CGM.getContext().VoidPtrTy;
294 CGM.getCXXABI().buildThisParam(*
this, FunctionArgs);
297 if (!IsUnprototyped) {
301 CGM.getCXXABI().addImplicitStructorParams(*
this, ResultType,
313 CGM.getCXXABI().EmitInstanceFunctionProlog(*
this);
314 CXXThisValue = CXXABIThisValue;
330 bool IsUnprototyped) {
332 "Please use a new CGF for this thunk");
341 llvm::Value *AdjustedThisPtr =
343 ThisValueClass, *Thunk)
352 CGM.ErrorUnsupported(
353 MD,
"return-adjusting thunk with incomplete parameter type");
355 llvm_unreachable(
"shouldn't try to emit musttail return-adjusting "
356 "thunks for variadic functions");
358 CGM.ErrorUnsupported(
359 MD,
"non-trivial argument copy for return-adjusting thunk");
371 CGM.getCXXABI().adjustCallArgsForDestructorThunk(*
this,
CurGD, CallArgs);
374 unsigned PrefixArgs = CallArgs.size() - 1;
385 assert(CallFnInfo.getRegParm() ==
CurFnInfo->getRegParm() &&
386 CallFnInfo.isNoReturn() ==
CurFnInfo->isNoReturn() &&
387 CallFnInfo.getCallingConvention() ==
CurFnInfo->getCallingConvention());
389 similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),
391 assert(CallFnInfo.arg_size() ==
CurFnInfo->arg_size());
392 for (
unsigned i = 0, e =
CurFnInfo->arg_size(); i != e; ++i)
393 assert(
similar(CallFnInfo.arg_begin()[i].info,
394 CallFnInfo.arg_begin()[i].type,
402 :
CGM.getCXXABI().hasMostDerivedReturn(
CurGD)
403 ?
CGM.getContext().VoidPtrTy
413 llvm::CallBase *CallOrInvoke;
415 CallArgs, &CallOrInvoke);
420 else if (llvm::CallInst*
Call = dyn_cast<llvm::CallInst>(CallOrInvoke))
421 Call->setTailCallKind(llvm::CallInst::TCK_Tail);
425 CGM.getCXXABI().EmitReturnFromThunk(*
this, RV, ResultType);
434 llvm::Value *AdjustedThisPtr,
435 llvm::FunctionCallee Callee) {
447 llvm::Type *ThisType = Args[ThisArgNo]->getType();
448 if (ThisType != AdjustedThisPtr->getType())
449 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
450 Args[ThisArgNo] = AdjustedThisPtr;
452 assert(ThisAI.
isInAlloca() &&
"this is passed directly or inalloca");
455 if (ThisType != AdjustedThisPtr->getType())
456 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
457 Builder.CreateStore(AdjustedThisPtr, ThisAddr);
462 llvm::CallInst *
Call =
Builder.CreateCall(Callee, Args);
463 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
467 llvm::AttributeList Attrs;
468 CGM.ConstructAttributeList(Callee.getCallee()->getName(), *
CurFnInfo, GD,
471 Call->setAttributes(Attrs);
474 if (
Call->getType()->isVoidTy())
489 bool IsUnprototyped) {
500 Ty =
CGM.getTypes().GetFunctionType(FnInfo);
502 llvm::Constant *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
506 &Thunk, IsUnprototyped);
510 bool IsUnprototyped,
bool ForVTable) {
527llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
535 SmallString<256> Name;
536 MangleContext &MCtx = CGM.getCXXABI().getMangleContext();
537 llvm::raw_svector_ostream
Out(Name);
539 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
545 if (CGM.getContext().useAbbreviatedThunkName(GD, Name.str())) {
547 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
554 llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
555 llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD);
558 bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible(
565 const CGFunctionInfo &FnInfo =
566 IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD)
567 : CGM.getTypes().arrangeGlobalDeclaration(GD);
568 llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo);
573 if (ThunkFn->getFunctionType() != ThunkFnTy) {
574 llvm::GlobalValue *OldThunkFn = ThunkFn;
576 assert(OldThunkFn->isDeclaration() &&
"Shouldn't replace non-declaration");
579 OldThunkFn->setName(StringRef());
580 ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
581 Name.str(), &CGM.getModule());
582 CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn,
false);
584 if (!OldThunkFn->use_empty()) {
585 OldThunkFn->replaceAllUsesWith(ThunkFn);
589 OldThunkFn->eraseFromParent();
592 bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions();
593 bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions;
595 if (!ThunkFn->isDeclaration()) {
596 if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) {
610 ThunkFn->addFnAttr(
"thunk");
612 CGM.SetLLVMFunctionAttributesForDefinition(GD.
getDecl(), ThunkFn);
619 bool ShouldCloneVarArgs =
false;
620 if (!IsUnprototyped && ThunkFn->isVarArg()) {
621 ShouldCloneVarArgs =
true;
623 switch (CGM.getTriple().getArch()) {
624 case llvm::Triple::x86_64:
625 case llvm::Triple::x86:
626 case llvm::Triple::aarch64:
627 ShouldCloneVarArgs =
false;
635 if (ShouldCloneVarArgs) {
636 if (UseAvailableExternallyLinkage)
639 CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI);
642 CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped);
658 VTContext->getThunkInfo(GD);
660 if (!ThunkInfoVector)
663 for (
const ThunkInfo& Thunk : *ThunkInfoVector)
664 maybeEmitThunk(GD, Thunk,
false);
668 llvm::Constant *component,
669 unsigned vtableAddressPoint,
670 bool vtableHasLocalLinkage,
671 bool isCompleteDtor)
const {
673 if (component->isNullValue())
674 return builder.
add(llvm::ConstantInt::get(CGM.
Int32Ty, 0));
691 auto stubLinkage = vtableHasLocalLinkage
692 ? llvm::GlobalValue::InternalLinkage
693 : llvm::GlobalValue::LinkOnceODRLinkage;
695 llvm::Constant *target;
696 if (
auto *func = dyn_cast<llvm::Function>(globalVal)) {
697 target = llvm::DSOLocalEquivalent::get(func);
700 rttiProxyName.append(
".rtti_proxy");
706 llvm::GlobalVariable *proxy =
module.getNamedGlobal(rttiProxyName);
708 proxy =
new llvm::GlobalVariable(module, globalVal->getType(),
710 globalVal, rttiProxyName);
711 proxy->setDSOLocal(
true);
712 proxy->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
713 if (!proxy->hasLocalLinkage()) {
714 proxy->setVisibility(llvm::GlobalValue::HiddenVisibility);
715 proxy->setComdat(module.getOrInsertComdat(rttiProxyName));
738 return CGM.getVTableComponentType();
744 builder.
add(llvm::ConstantExpr::getIntToPtr(
756 const VTableLayout &layout,
757 unsigned componentIndex,
758 llvm::Constant *rtti,
759 unsigned &nextVTableThunkIndex,
760 unsigned vtableAddressPoint,
761 bool vtableHasLocalLinkage) {
764 bool RelativeCXXABIVTables = CGM.getLangOpts().RelativeCXXABIVTables;
765 auto addOffsetConstant =
768 switch (component.getKind()) {
770 return addOffsetConstant(CGM, builder, component.getVCallOffset());
773 return addOffsetConstant(CGM, builder, component.getVBaseOffset());
776 return addOffsetConstant(CGM, builder, component.getOffsetToTop());
779 if (RelativeCXXABIVTables)
780 return addRelativeComponent(builder, rtti, vtableAddressPoint,
781 vtableHasLocalLinkage,
784 return builder.
add(rtti);
789 GlobalDecl GD = component.getGlobalDecl(
790 CGM.getContext().getTargetInfo().emitVectorDeletingDtors(
791 CGM.getContext().getLangOpts()));
795 layout.
vtable_thunks()[nextVTableThunkIndex].first == componentIndex;
797 if (CGM.getLangOpts().CUDA) {
805 CGM.getLangOpts().CUDAIsDevice
806 ? MD->
hasAttr<CUDADeviceAttr>()
807 : (MD->
hasAttr<CUDAHostAttr>() || !MD->
hasAttr<CUDADeviceAttr>());
808 if (!CanEmitMethod) {
810 nextVTableThunkIndex++;
812 llvm::ConstantExpr::getNullValue(CGM.GlobalsInt8PtrTy));
817 auto getSpecialVirtualFn = [&](StringRef
name) -> llvm::Constant * {
825 if (RelativeCXXABIVTables)
826 return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
830 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPIsTargetDevice &&
831 CGM.getTriple().isNVPTX())
832 return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
833 llvm::FunctionType *fnTy =
834 llvm::FunctionType::get(CGM.VoidTy,
false);
836 CGM.CreateRuntimeFunction(fnTy, name).getCallee());
837 if (
auto f = dyn_cast<llvm::Function>(fn))
838 f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
842 llvm::Constant *fnPtr;
848 getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName());
849 fnPtr = PureVirtualFn;
853 if (!DeletedVirtualFn)
855 getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName());
856 fnPtr = DeletedVirtualFn;
859 }
else if (IsThunk) {
860 auto &thunkInfo = layout.
vtable_thunks()[nextVTableThunkIndex].second;
862 nextVTableThunkIndex++;
863 fnPtr = maybeEmitThunk(GD, thunkInfo,
true);
864 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) {
865 assert(thunkInfo.Method &&
"Method not set");
871 llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
872 fnPtr = CGM.GetAddrOfFunction(GD, fnTy,
true);
873 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
877 if (RelativeCXXABIVTables) {
878 return addRelativeComponent(
879 builder, fnPtr, vtableAddressPoint, vtableHasLocalLinkage,
886 unsigned FnAS = fnPtr->getType()->getPointerAddressSpace();
887 unsigned GVAS = CGM.GlobalsInt8PtrTy->getPointerAddressSpace();
891 llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy);
892 if (
const auto &Schema =
893 CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
895 return builder.
add(fnPtr);
900 if (RelativeCXXABIVTables)
901 return builder.
add(llvm::ConstantExpr::getNullValue(CGM.Int32Ty));
906 llvm_unreachable(
"Unexpected vtable component kind");
912 for (
unsigned i = 0, e = layout.
getNumVTables(); i != e; ++i)
913 tys.push_back(llvm::ArrayType::get(componentType, layout.
getVTableSize(i)));
915 return llvm::StructType::get(CGM.getLLVMContext(), tys);
920 llvm::Constant *rtti,
921 bool vtableHasLocalLinkage) {
925 unsigned nextVTableThunkIndex = 0;
926 for (
unsigned vtableIndex = 0, endIndex = layout.
getNumVTables();
927 vtableIndex != endIndex; ++vtableIndex) {
928 auto vtableElem = builder.
beginArray(componentType);
931 size_t vtableEnd = vtableStart + layout.
getVTableSize(vtableIndex);
932 for (
size_t componentIndex = vtableStart; componentIndex < vtableEnd;
934 addVTableComponent(vtableElem, layout, componentIndex, rtti,
935 nextVTableThunkIndex, addressPoints[vtableIndex],
936 vtableHasLocalLinkage);
938 vtableElem.finishAndAddTo(builder);
944 llvm::GlobalVariable::LinkageTypes
Linkage,
945 VTableAddressPointsMapTy &AddressPoints) {
947 DI->completeClassData(
Base.getBase());
949 std::unique_ptr<VTableLayout> VTLayout(
951 Base.getBase(),
Base.getBaseOffset(), BaseIsVirtual, RD));
954 AddressPoints = VTLayout->getAddressPoints();
958 llvm::raw_svector_ostream Out(OutName);
960 .mangleCXXCtorVTable(RD,
Base.getBaseOffset().getQuantity(),
961 Base.getBase(), Out);
964 bool UsingRelativeLayout = CGM.getLangOpts().RelativeCXXABIVTables;
965 bool VTableAliasExists =
966 UsingRelativeLayout && CGM.getModule().getNamedAlias(Name);
967 if (VTableAliasExists) {
969 Name.append(
".local");
979 if (
Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
980 Linkage = llvm::GlobalVariable::InternalLinkage;
982 llvm::Align Align = CGM.getDataLayout().getABITypeAlign(VTType);
985 llvm::GlobalVariable *VTable =
986 CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType,
Linkage, Align);
989 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
991 llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
992 CGM.getContext().getCanonicalTagType(
Base.getBase()));
998 VTable->hasLocalLinkage());
999 components.finishAndSetAsInitializer(VTable);
1003 assert(!VTable->isDeclaration() &&
"Shouldn't set properties on declaration");
1004 CGM.setGVProperties(VTable, RD);
1006 CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout);
1008 if (UsingRelativeLayout) {
1010 if (!VTable->isDSOLocal())
1026 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::HWAddress)) {
1027 llvm::GlobalValue::SanitizerMetadata Meta;
1028 if (GV->hasSanitizerMetadata())
1029 Meta = GV->getSanitizerMetadata();
1030 Meta.NoHWAddress =
true;
1031 GV->setSanitizerMetadata(Meta);
1042 llvm::StringRef AliasNameRef) {
1043 assert(CGM.getLangOpts().RelativeCXXABIVTables &&
1044 "Can only use this if the relative vtable ABI is used");
1045 assert(!VTable->isDSOLocal() &&
"This should be called only if the vtable is "
1046 "not guaranteed to be dso_local");
1051 if (VTable->hasAvailableExternallyLinkage())
1058 VTable->setName(AliasName +
".local");
1060 auto Linkage = VTable->getLinkage();
1061 assert(llvm::GlobalAlias::isValidLinkage(
Linkage) &&
1062 "Invalid vtable alias linkage");
1064 llvm::GlobalAlias *VTableAlias = CGM.getModule().getNamedAlias(AliasName);
1066 VTableAlias = llvm::GlobalAlias::create(VTable->getValueType(),
1067 VTable->getAddressSpace(),
Linkage,
1068 AliasName, &CGM.getModule());
1070 assert(VTableAlias->getValueType() == VTable->getValueType());
1071 assert(VTableAlias->getLinkage() ==
Linkage);
1073 VTableAlias->setVisibility(VTable->getVisibility());
1074 VTableAlias->setUnnamedAddr(VTable->getUnnamedAddr());
1077 if (!VTable->hasComdat()) {
1078 VTable->setLinkage(llvm::GlobalValue::InternalLinkage);
1088 VTable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1091 VTableAlias->setAliasee(VTable);
1103llvm::GlobalVariable::LinkageTypes
1106 return llvm::GlobalVariable::InternalLinkage;
1115 IsInNamedModule ?
nullptr : Context.getCurrentKeyFunction(RD);
1116 if (IsInNamedModule || (keyFunction && !RD->
hasAttr<DLLImportAttr>())) {
1120 if (keyFunction && keyFunction->
hasBody(def))
1123 bool IsExternalDefinition =
1134 (IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
1135 CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) &&
1136 "Shouldn't query vtable linkage without the class in module units, "
1137 "key function, optimizations, or debug info");
1138 if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
1139 return llvm::GlobalVariable::AvailableExternallyLinkage;
1141 if (keyFunction && keyFunction->
isInlined())
1142 return !Context.getLangOpts().AppleKext
1143 ? llvm::GlobalVariable::LinkOnceODRLinkage
1144 : llvm::Function::InternalLinkage;
1146 return llvm::GlobalVariable::ExternalLinkage;
1149 return !Context.getLangOpts().AppleKext ?
1150 llvm::GlobalVariable::LinkOnceODRLinkage :
1151 llvm::Function::InternalLinkage;
1154 return !Context.getLangOpts().AppleKext ?
1155 llvm::GlobalVariable::WeakODRLinkage :
1156 llvm::Function::InternalLinkage;
1159 return IsExternalDefinition
1160 ? llvm::GlobalVariable::AvailableExternallyLinkage
1161 : llvm::GlobalVariable::ExternalLinkage;
1167 if (Context.getLangOpts().AppleKext)
1168 return llvm::Function::InternalLinkage;
1170 llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage =
1171 llvm::GlobalValue::LinkOnceODRLinkage;
1172 llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage =
1173 llvm::GlobalValue::WeakODRLinkage;
1174 if (RD->
hasAttr<DLLExportAttr>()) {
1176 DiscardableODRLinkage = NonDiscardableODRLinkage;
1177 }
else if (RD->
hasAttr<DLLImportAttr>()) {
1179 DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1180 NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1187 return DiscardableODRLinkage;
1193 return DiscardableODRLinkage;
1195 ? llvm::GlobalVariable::AvailableExternallyLinkage
1196 : llvm::GlobalVariable::ExternalLinkage;
1199 return NonDiscardableODRLinkage;
1202 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
1212 VTables.GenerateClassData(theClass);
1218 DI->completeClassData(RD);
1221 CGM.getCXXABI().emitVirtualInheritanceTables(RD);
1223 CGM.getCXXABI().emitVTableDefinitions(*
this, RD);
1237 assert(RD->
isDynamicClass() &&
"Non-dynamic classes have no VTable.");
1241 if (CGM.getTarget().getCXXABI().isMicrosoft())
1263 const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
1269 return !keyFunction->
hasBody();
1288void CodeGenModule::EmitDeferredVTables() {
1292 size_t savedSize = DeferredVTables.size();
1295 for (
const CXXRecordDecl *RD : DeferredVTables)
1297 VTables.GenerateClassData(RD);
1298 else if (shouldOpportunisticallyEmitVTables())
1299 OpportunisticVTables.push_back(RD);
1301 assert(savedSize == DeferredVTables.size() &&
1302 "deferred extra vtables during vtable emission?");
1303 DeferredVTables.clear();
1307 if (RD->
hasAttr<LTOVisibilityPublicAttr>() || RD->
hasAttr<UuidAttr>() ||
1319 if (
auto *ND = dyn_cast<NamespaceDecl>(D))
1321 if (II->isStr(
"std") || II->isStr(
"stdext"))
1343 const CXXRecordDecl *RD, llvm::DenseSet<const CXXRecordDecl *> &Visited) {
1349 if (!Visited.insert(RD).second)
1350 return llvm::GlobalObject::VCallVisibilityTranslationUnit;
1353 llvm::GlobalObject::VCallVisibility TypeVis;
1355 TypeVis = llvm::GlobalObject::VCallVisibilityTranslationUnit;
1357 TypeVis = llvm::GlobalObject::VCallVisibilityLinkageUnit;
1359 TypeVis = llvm::GlobalObject::VCallVisibilityPublic;
1361 for (
const auto &B : RD->
bases())
1362 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1367 for (
const auto &B : RD->
vbases())
1368 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1377 llvm::GlobalVariable *VTable,
1389 struct AddressPoint {
1393 bool operator<(
const AddressPoint &RHS)
const {
1394 int D =
TypeName.compare(RHS.TypeName);
1395 return D < 0 || (D == 0 && Offset < RHS.Offset);
1398 std::vector<AddressPoint> AddressPoints;
1400 AddressPoint N{AP.first.getBase(),
1402 AP.second.AddressPointIndex,
1404 llvm::raw_string_ostream Stream(N.TypeName);
1407 AddressPoints.push_back(std::move(N));
1411 llvm::sort(AddressPoints);
1414 for (
auto AP : AddressPoints) {
1422 for (
unsigned I = 0; I != Comps.size(); ++I) {
1426 Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(),
1427 std::nullopt, AP.Base));
1428 VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD);
1434 llvm::DenseSet<const CXXRecordDecl *> Visited;
1435 llvm::GlobalObject::VCallVisibility TypeVis =
1437 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1438 VTable->setVCallVisibilityMetadata(TypeVis);
static RValue PerformReturnAdjustment(CodeGenFunction &CGF, QualType ResultType, RValue RV, const ThunkInfo &Thunk)
static void resolveTopLevelMetadata(llvm::Function *Fn, llvm::ValueToValueMapTy &VMap)
This function clones a function's DISubprogram node and enters it into a value map with the intent th...
static void AddRelativeLayoutOffset(const CodeGenModule &CGM, ConstantArrayBuilder &builder, CharUnits offset)
static void AddPointerLayoutOffset(const CodeGenModule &CGM, ConstantArrayBuilder &builder, CharUnits offset)
static bool similar(const ABIArgInfo &infoL, CanQualType typeL, const ABIArgInfo &infoR, CanQualType typeR)
static bool shouldEmitAvailableExternallyVTable(const CIRGenModule &cgm, const CXXRecordDecl *rd)
static bool shouldEmitVTableAtEndOfTranslationUnit(CIRGenModule &cgm, const CXXRecordDecl *rd)
Given that we're currently at the end of the translation unit, and we've emitted a reference to the v...
static void setThunkProperties(CIRGenModule &cgm, const ThunkInfo &thunk, cir::FuncOp thunkFn, bool forVTable, GlobalDecl gd)
static bool shouldEmitVTableThunk(CIRGenModule &cgm, const CXXMethodDecl *md, bool isUnprototyped, bool forVTable)
static Decl::Kind getKind(const Decl *D)
static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr)
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getThisType() const
Return the type of the this pointer.
QualType getFunctionObjectParameterType() const
Represents a C++ struct/union/class.
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
base_class_range vbases()
bool isDynamicClass() const
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
bool isSRetAfterThis() const
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const =0
Determine whether it's possible to emit a vtable for RD, even though we do not know that the vtable h...
virtual llvm::Value * performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const CXXRecordDecl *UnadjustedClass, const ReturnAdjustment &RA)=0
virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, bool ReturnAdjustment)=0
virtual bool exportThunk()=0
MangleContext & getMangleContext()
Gets the mangle context.
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
CGFunctionInfo - Class to encapsulate the information about a function definition.
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
GlobalDecl CurGD
CurGD - The GlobalDecl for the current function being compiled.
void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr, llvm::FunctionCallee Callee)
Emit a musttail call for a thunk with a potentially adjusted this pointer.
Address LoadCXXThisAddress()
bool CurFuncIsThunk
In C++, whether we are code generating a thunk.
void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc)
EmitDelegateCallArg - We are performing a delegate call; that is, the current function is delegating ...
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
Address makeNaturalAddressForPointer(llvm::Value *Ptr, QualType T, CharUnits Alignment=CharUnits::Zero(), bool ForPointeeType=false, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
Construct an address with the natural alignment of T.
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
void EmitCallAndReturnForThunk(llvm::FunctionCallee Callee, const ThunkInfo *Thunk, bool IsUnprototyped)
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.
llvm::Function * GenerateVarArgsThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, GlobalDecl GD, const ThunkInfo &Thunk)
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
bool AutoreleaseResult
In ARC, whether we should autorelease the return value.
llvm::Type * ConvertTypeForMem(QualType T)
void generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, GlobalDecl GD, const ThunkInfo &Thunk, bool IsUnprototyped)
Generate a thunk for the given method.
void StartThunk(llvm::Function *Fn, GlobalDecl GD, const CGFunctionInfo &FnInfo, bool IsUnprototyped)
static bool hasAggregateEvaluationKind(QualType T)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::Value * LoadCXXThis()
LoadCXXThis - Load the value of 'this'.
const CGFunctionInfo * CurFnInfo
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::LLVMContext & getLLVMContext()
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const
Set visibility, dllimport/dllexport and dso_local.
void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD)
Create and attach type metadata for the given vtable.
llvm::GlobalObject::VCallVisibility GetVCallVisibilityLevel(const CXXRecordDecl *RD, llvm::DenseSet< const CXXRecordDecl * > &Visited)
Returns the vcall visibility of the given type.
llvm::Module & getModule() const
CodeGenVTables & getVTables()
CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const
Return the store size, in character units, of the given LLVM type.
const LangOptions & getLangOpts() const
const TargetInfo & getTarget() const
void EmitVTableTypeMetadata(const CXXRecordDecl *RD, llvm::GlobalVariable *VTable, const VTableLayout &VTLayout)
Emit type metadata for the given vtable using the given layout.
bool HasHiddenLTOVisibility(const CXXRecordDecl *RD)
Returns whether the given record has hidden LTO visibility and therefore may participate in (single-m...
CGCXXABI & getCXXABI() const
CharUnits getClassPointerAlignment(const CXXRecordDecl *CD)
Returns the assumed alignment of an opaque pointer to the given class.
const llvm::Triple & getTriple() const
bool AlwaysHasLTOVisibilityPublic(const CXXRecordDecl *RD)
Returns whether the given record has public LTO visibility (regardless of -lto-whole-program-visibili...
void EmitVTable(CXXRecordDecl *Class)
This is a callback from Sema to tell us that a particular vtable is required to be emitted in this tr...
void setFunctionLinkage(GlobalDecl GD, llvm::Function *F)
ASTContext & getContext() const
llvm::Type * getVTableComponentType() const
bool supportsCOMDAT() const
const CodeGenOptions & getCodeGenOpts() const
llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD)
Return the appropriate linkage for the vtable, VTT, and type information of the given class.
llvm::Metadata * CreateMetadataIdentifierForVirtualMemPtrType(QualType T)
Create a metadata identifier that is intended to be used to check virtual calls via a member function...
llvm::Constant * GetAddrOfThunk(StringRef Name, llvm::Type *FnTy, GlobalDecl GD)
Get the address of the thunk for the given global decl.
llvm::GlobalVariable * GetAddrOfVTable(const CXXRecordDecl *RD)
GetAddrOfVTable - Get the address of the VTable for the given record decl.
void createVTableInitializer(ConstantStructBuilder &builder, const VTableLayout &layout, llvm::Constant *rtti, bool vtableHasLocalLinkage)
Add vtable components for the given vtable layout to the given global initializer.
void GenerateClassData(const CXXRecordDecl *RD)
GenerateClassData - Generate all the class data required to be generated upon definition of a KeyFunc...
void GenerateRelativeVTableAlias(llvm::GlobalVariable *VTable, llvm::StringRef AliasNameRef)
Generate a public facing alias for the vtable and make the vtable either hidden or private.
ItaniumVTableContext & getItaniumVTableContext()
CodeGenVTables(CodeGenModule &CGM)
llvm::GlobalVariable * GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base, bool BaseIsVirtual, llvm::GlobalVariable::LinkageTypes Linkage, VTableAddressPointsMapTy &AddressPoints)
GenerateConstructionVTable - Generate a construction vtable for the given base subobject.
llvm::Type * getVTableType(const VTableLayout &layout)
Returns the type of a vtable with the given layout.
llvm::Type * getVTableComponentType() const
Return the type used as components for a vtable.
bool isVTableExternal(const CXXRecordDecl *RD)
At this point in the translation unit, does it appear that can we rely on the vtable being defined el...
void RemoveHwasanMetadata(llvm::GlobalValue *GV) const
Specify a global should not be instrumented with hwasan.
void EmitThunks(GlobalDecl GD)
EmitThunks - Emit the associated thunks for the given global decl.
void addRelativeOffsetToPosition(llvm::IntegerType *type, llvm::Constant *target, size_t position)
Same as addRelativeOffset(), but instead relative to an element in this aggregate,...
void add(llvm::Constant *value)
Add a new value to this initializer.
void addNullPointer(llvm::PointerType *ptrTy)
Add a null pointer of a specific type.
void addSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, GlobalDecl CalleeDecl, QualType CalleeType)
Add a signed pointer using the given pointer authentication schema.
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
A helper class of ConstantInitBuilder, used for building constant array initializers.
StructBuilder beginStruct(llvm::StructType *structTy=nullptr)
The standard implementation of ConstantInitBuilder used in Clang.
A helper class of ConstantInitBuilder, used for building constant struct initializers.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
bool isInNamedModule() const
Whether this declaration comes from a named module.
SourceLocation getLocation() const
bool shouldEmitInExternalSource() const
Whether the definition of the declaration should be emitted in external sources.
Represents a function declaration or definition.
param_iterator param_end()
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
ArrayRef< ParmVarDecl * > parameters() const
param_iterator param_begin()
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine what kind of template instantiation this function represents.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Represents a prototype with parameter type info, e.g.
QualType getReturnType() const
GlobalDecl - represents a global declaration.
GlobalDecl getWithDecl(const Decl *D)
CXXDtorType getDtorType() const
const Decl * getDecl() const
One of these records is kept for each identifier that is lexed.
GlobalDecl findOriginalMethod(GlobalDecl GD)
Return the method that added the v-table slot that will be used to call the given method.
Visibility getVisibility() const
Linkage getLinkage() const
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, const ThunkInfo &Thunk, bool ElideOverrideInfo, raw_ostream &)=0
virtual void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, bool ElideOverrideInfo, raw_ostream &)=0
virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
Generates a unique string for an externally visible type for use with TBAA or type uniquing.
LinkageInfo getLinkageAndVisibility() const
Determines the linkage and visibility of this entity.
bool isExternallyVisible() const
Represents a parameter to a function.
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Encodes a location in the source.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
@ CK_DeletingDtorPointer
A pointer to the deleting destructor.
@ CK_UnusedFunctionPointer
An entry that is never used.
@ CK_CompleteDtorPointer
A pointer to the complete destructor.
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
const AddressPointsIndexMapTy & getAddressPointIndices() const
size_t getVTableOffset(size_t i) const
ArrayRef< VTableComponent > vtable_components() const
size_t getNumVTables() const
ArrayRef< VTableThunkTy > vtable_thunks() const
const AddressPointsMapTy & getAddressPoints() const
size_t getVTableSize(size_t i) const
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
@ Dtor_Base
Base object dtor.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
@ TSK_ExplicitSpecialization
This template specialization was declared or defined by an explicit specialization (C++ [temp....
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
@ TSK_Undeclared
This template specialization was formed from a template-id but has not yet been declared,...
CallingConv
CallingConv - Specifies the calling convention that a function uses.
U cast(CodeGen::Address addr)
bool isExternallyVisible(Linkage L)
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
llvm::PointerType * GlobalsInt8PtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * PtrDiffTy
The this pointer adjustment as well as an optional return adjustment for a thunk.
ReturnAdjustment Return
The return adjustment.