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);
143 for (
auto &BB : *Fn) {
145 for (llvm::DbgVariableRecord &DVR :
146 llvm::filterDbgVars(I.getDbgRecordRange())) {
147 auto *DILocal = DVR.getVariable();
148 if (!DILocal->isResolved())
151 if (
auto *DII = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) {
152 auto *DILocal = DII->getVariable();
153 if (!DILocal->isResolved())
186 llvm::Type *Ty =
CGM.getTypes().GetFunctionType(FnInfo);
187 llvm::Value *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
194 CGM.ErrorUnsupported(MD,
"return-adjusting thunk with variadic arguments");
197 assert(!BaseFn->isDeclaration() &&
"cannot clone undefined variadic method");
200 llvm::ValueToValueMapTy VMap;
205 llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
206 Fn->replaceAllUsesWith(NewFn);
208 Fn->eraseFromParent();
215 llvm::Function::arg_iterator AI = Fn->arg_begin();
216 if (
CGM.ReturnTypeUsesSRet(FnInfo))
224 llvm::BasicBlock *EntryBB = &Fn->front();
225 llvm::BasicBlock::iterator ThisStore =
226 llvm::find_if(*EntryBB, [&](llvm::Instruction &I) {
229 assert(ThisStore != EntryBB->end() &&
230 "Store of this should be in entry block?");
232 Builder.SetInsertPoint(&*ThisStore);
235 llvm::Value *AdjustedThisPtr =
CGM.getCXXABI().performThisAdjustment(
236 *
this, ThisPtr, ThisValueClass, Thunk);
237 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr,
238 ThisStore->getOperand(0)->getType());
239 ThisStore->setOperand(0, AdjustedThisPtr);
243 for (llvm::BasicBlock &BB : *Fn) {
244 llvm::Instruction *
T = BB.getTerminator();
247 T->eraseFromParent();
261 bool IsUnprototyped) {
262 assert(!
CurGD.getDecl() &&
"CurGD was already set!");
271 ResultType =
CGM.getContext().VoidTy;
272 else if (
CGM.getCXXABI().HasThisReturn(GD))
273 ResultType = ThisType;
274 else if (
CGM.getCXXABI().hasMostDerivedReturn(GD))
275 ResultType =
CGM.getContext().VoidPtrTy;
281 CGM.getCXXABI().buildThisParam(*
this, FunctionArgs);
284 if (!IsUnprototyped) {
288 CGM.getCXXABI().addImplicitStructorParams(*
this, ResultType,
300 CGM.getCXXABI().EmitInstanceFunctionProlog(*
this);
301 CXXThisValue = CXXABIThisValue;
317 bool IsUnprototyped) {
319 "Please use a new CGF for this thunk");
328 llvm::Value *AdjustedThisPtr =
330 ThisValueClass, *Thunk)
339 CGM.ErrorUnsupported(
340 MD,
"return-adjusting thunk with incomplete parameter type");
342 llvm_unreachable(
"shouldn't try to emit musttail return-adjusting "
343 "thunks for variadic functions");
345 CGM.ErrorUnsupported(
346 MD,
"non-trivial argument copy for return-adjusting thunk");
358 CGM.getCXXABI().adjustCallArgsForDestructorThunk(*
this,
CurGD, CallArgs);
361 unsigned PrefixArgs = CallArgs.size() - 1;
372 assert(CallFnInfo.getRegParm() ==
CurFnInfo->getRegParm() &&
373 CallFnInfo.isNoReturn() ==
CurFnInfo->isNoReturn() &&
374 CallFnInfo.getCallingConvention() ==
CurFnInfo->getCallingConvention());
376 similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),
378 assert(CallFnInfo.arg_size() ==
CurFnInfo->arg_size());
379 for (
unsigned i = 0, e =
CurFnInfo->arg_size(); i != e; ++i)
380 assert(
similar(CallFnInfo.arg_begin()[i].info,
381 CallFnInfo.arg_begin()[i].type,
389 :
CGM.getCXXABI().hasMostDerivedReturn(
CurGD)
390 ?
CGM.getContext().VoidPtrTy
400 llvm::CallBase *CallOrInvoke;
402 CallArgs, &CallOrInvoke);
407 else if (llvm::CallInst*
Call = dyn_cast<llvm::CallInst>(CallOrInvoke))
408 Call->setTailCallKind(llvm::CallInst::TCK_Tail);
412 CGM.getCXXABI().EmitReturnFromThunk(*
this, RV, ResultType);
421 llvm::Value *AdjustedThisPtr,
422 llvm::FunctionCallee Callee) {
434 llvm::Type *ThisType = Args[ThisArgNo]->getType();
435 if (ThisType != AdjustedThisPtr->getType())
436 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
437 Args[ThisArgNo] = AdjustedThisPtr;
439 assert(ThisAI.
isInAlloca() &&
"this is passed directly or inalloca");
442 if (ThisType != AdjustedThisPtr->getType())
443 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
444 Builder.CreateStore(AdjustedThisPtr, ThisAddr);
449 llvm::CallInst *
Call =
Builder.CreateCall(Callee, Args);
450 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
454 llvm::AttributeList Attrs;
455 CGM.ConstructAttributeList(Callee.getCallee()->getName(), *
CurFnInfo, GD,
458 Call->setAttributes(Attrs);
461 if (
Call->getType()->isVoidTy())
476 bool IsUnprototyped) {
487 Ty =
CGM.getTypes().GetFunctionType(FnInfo);
489 llvm::Constant *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
493 &Thunk, IsUnprototyped);
497 bool IsUnprototyped,
bool ForVTable) {
514llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
522 SmallString<256> Name;
523 MangleContext &MCtx = CGM.getCXXABI().getMangleContext();
524 llvm::raw_svector_ostream
Out(Name);
526 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
532 if (CGM.getContext().useAbbreviatedThunkName(GD, Name.str())) {
534 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
541 llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
542 llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD);
545 bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible(
552 const CGFunctionInfo &FnInfo =
553 IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD)
554 : CGM.getTypes().arrangeGlobalDeclaration(GD);
555 llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo);
560 if (ThunkFn->getFunctionType() != ThunkFnTy) {
561 llvm::GlobalValue *OldThunkFn = ThunkFn;
563 assert(OldThunkFn->isDeclaration() &&
"Shouldn't replace non-declaration");
566 OldThunkFn->setName(StringRef());
567 ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
568 Name.str(), &CGM.getModule());
569 CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn,
false);
571 if (!OldThunkFn->use_empty()) {
572 OldThunkFn->replaceAllUsesWith(ThunkFn);
576 OldThunkFn->eraseFromParent();
579 bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions();
580 bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions;
582 if (!ThunkFn->isDeclaration()) {
583 if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) {
597 ThunkFn->addFnAttr(
"thunk");
599 CGM.SetLLVMFunctionAttributesForDefinition(GD.
getDecl(), ThunkFn);
606 bool ShouldCloneVarArgs =
false;
607 if (!IsUnprototyped && ThunkFn->isVarArg()) {
608 ShouldCloneVarArgs =
true;
610 switch (CGM.getTriple().getArch()) {
611 case llvm::Triple::x86_64:
612 case llvm::Triple::x86:
613 case llvm::Triple::aarch64:
614 ShouldCloneVarArgs =
false;
622 if (ShouldCloneVarArgs) {
623 if (UseAvailableExternallyLinkage)
626 CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI);
629 CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped);
645 VTContext->getThunkInfo(GD);
647 if (!ThunkInfoVector)
650 for (
const ThunkInfo& Thunk : *ThunkInfoVector)
651 maybeEmitThunk(GD, Thunk,
false);
655 llvm::Constant *component,
656 unsigned vtableAddressPoint,
657 bool vtableHasLocalLinkage,
658 bool isCompleteDtor)
const {
660 if (component->isNullValue())
661 return builder.
add(llvm::ConstantInt::get(CGM.
Int32Ty, 0));
678 auto stubLinkage = vtableHasLocalLinkage
679 ? llvm::GlobalValue::InternalLinkage
680 : llvm::GlobalValue::LinkOnceODRLinkage;
682 llvm::Constant *target;
683 if (
auto *func = dyn_cast<llvm::Function>(globalVal)) {
684 target = llvm::DSOLocalEquivalent::get(func);
687 rttiProxyName.append(
".rtti_proxy");
693 llvm::GlobalVariable *proxy =
module.getNamedGlobal(rttiProxyName);
695 proxy =
new llvm::GlobalVariable(module, globalVal->getType(),
697 globalVal, rttiProxyName);
698 proxy->setDSOLocal(
true);
699 proxy->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
700 if (!proxy->hasLocalLinkage()) {
701 proxy->setVisibility(llvm::GlobalValue::HiddenVisibility);
702 proxy->setComdat(module.getOrInsertComdat(rttiProxyName));
734 return CGM.getVTableComponentType();
740 builder.
add(llvm::ConstantExpr::getIntToPtr(
752 const VTableLayout &layout,
753 unsigned componentIndex,
754 llvm::Constant *rtti,
755 unsigned &nextVTableThunkIndex,
756 unsigned vtableAddressPoint,
757 bool vtableHasLocalLinkage) {
760 auto addOffsetConstant =
763 switch (component.getKind()) {
765 return addOffsetConstant(CGM, builder, component.getVCallOffset());
768 return addOffsetConstant(CGM, builder, component.getVBaseOffset());
771 return addOffsetConstant(CGM, builder, component.getOffsetToTop());
775 return addRelativeComponent(builder, rtti, vtableAddressPoint,
776 vtableHasLocalLinkage,
779 return builder.
add(rtti);
784 GlobalDecl GD = component.getGlobalDecl(
785 CGM.getContext().getTargetInfo().emitVectorDeletingDtors(
786 CGM.getContext().getLangOpts()));
790 layout.
vtable_thunks()[nextVTableThunkIndex].first == componentIndex;
792 if (CGM.getLangOpts().CUDA) {
800 CGM.getLangOpts().CUDAIsDevice
801 ? MD->
hasAttr<CUDADeviceAttr>()
802 : (MD->
hasAttr<CUDAHostAttr>() || !MD->
hasAttr<CUDADeviceAttr>());
803 if (!CanEmitMethod) {
805 nextVTableThunkIndex++;
807 llvm::ConstantExpr::getNullValue(CGM.GlobalsInt8PtrTy));
812 auto getSpecialVirtualFn = [&](StringRef
name) -> llvm::Constant * {
821 return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
825 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPIsTargetDevice &&
826 CGM.getTriple().isNVPTX())
827 return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
828 llvm::FunctionType *fnTy =
829 llvm::FunctionType::get(CGM.VoidTy,
false);
831 CGM.CreateRuntimeFunction(fnTy, name).getCallee());
832 if (
auto f = dyn_cast<llvm::Function>(fn))
833 f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
837 llvm::Constant *fnPtr;
843 getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName());
844 fnPtr = PureVirtualFn;
848 if (!DeletedVirtualFn)
850 getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName());
851 fnPtr = DeletedVirtualFn;
854 }
else if (IsThunk) {
855 auto &thunkInfo = layout.
vtable_thunks()[nextVTableThunkIndex].second;
857 nextVTableThunkIndex++;
858 fnPtr = maybeEmitThunk(GD, thunkInfo,
true);
859 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) {
860 assert(thunkInfo.Method &&
"Method not set");
866 llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
867 fnPtr = CGM.GetAddrOfFunction(GD, fnTy,
true);
868 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
873 return addRelativeComponent(
874 builder, fnPtr, vtableAddressPoint, vtableHasLocalLinkage,
881 unsigned FnAS = fnPtr->getType()->getPointerAddressSpace();
882 unsigned GVAS = CGM.GlobalsInt8PtrTy->getPointerAddressSpace();
886 llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy);
887 if (
const auto &Schema =
888 CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
890 return builder.
add(fnPtr);
896 return builder.
add(llvm::ConstantExpr::getNullValue(CGM.Int32Ty));
901 llvm_unreachable(
"Unexpected vtable component kind");
907 for (
unsigned i = 0, e = layout.
getNumVTables(); i != e; ++i)
908 tys.push_back(llvm::ArrayType::get(componentType, layout.
getVTableSize(i)));
910 return llvm::StructType::get(CGM.getLLVMContext(), tys);
915 llvm::Constant *rtti,
916 bool vtableHasLocalLinkage) {
920 unsigned nextVTableThunkIndex = 0;
921 for (
unsigned vtableIndex = 0, endIndex = layout.
getNumVTables();
922 vtableIndex != endIndex; ++vtableIndex) {
923 auto vtableElem = builder.
beginArray(componentType);
926 size_t vtableEnd = vtableStart + layout.
getVTableSize(vtableIndex);
927 for (
size_t componentIndex = vtableStart; componentIndex < vtableEnd;
929 addVTableComponent(vtableElem, layout, componentIndex, rtti,
930 nextVTableThunkIndex, addressPoints[vtableIndex],
931 vtableHasLocalLinkage);
933 vtableElem.finishAndAddTo(builder);
939 llvm::GlobalVariable::LinkageTypes
Linkage,
940 VTableAddressPointsMapTy &AddressPoints) {
942 DI->completeClassData(
Base.getBase());
944 std::unique_ptr<VTableLayout> VTLayout(
946 Base.getBase(),
Base.getBaseOffset(), BaseIsVirtual, RD));
949 AddressPoints = VTLayout->getAddressPoints();
953 llvm::raw_svector_ostream Out(OutName);
955 .mangleCXXCtorVTable(RD,
Base.getBaseOffset().getQuantity(),
956 Base.getBase(), Out);
960 bool VTableAliasExists =
961 UsingRelativeLayout && CGM.getModule().getNamedAlias(Name);
962 if (VTableAliasExists) {
964 Name.append(
".local");
974 if (
Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
975 Linkage = llvm::GlobalVariable::InternalLinkage;
977 llvm::Align Align = CGM.getDataLayout().getABITypeAlign(VTType);
980 llvm::GlobalVariable *VTable =
981 CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType,
Linkage, Align);
984 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
986 llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
987 CGM.getContext().getCanonicalTagType(
Base.getBase()));
993 VTable->hasLocalLinkage());
994 components.finishAndSetAsInitializer(VTable);
998 assert(!VTable->isDeclaration() &&
"Shouldn't set properties on declaration");
999 CGM.setGVProperties(VTable, RD);
1001 CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout);
1003 if (UsingRelativeLayout) {
1005 if (!VTable->isDSOLocal())
1021 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::HWAddress)) {
1022 llvm::GlobalValue::SanitizerMetadata Meta;
1023 if (GV->hasSanitizerMetadata())
1024 Meta = GV->getSanitizerMetadata();
1025 Meta.NoHWAddress =
true;
1026 GV->setSanitizerMetadata(Meta);
1037 llvm::StringRef AliasNameRef) {
1039 "Can only use this if the relative vtable ABI is used");
1040 assert(!VTable->isDSOLocal() &&
"This should be called only if the vtable is "
1041 "not guaranteed to be dso_local");
1046 if (VTable->hasAvailableExternallyLinkage())
1053 VTable->setName(AliasName +
".local");
1055 auto Linkage = VTable->getLinkage();
1056 assert(llvm::GlobalAlias::isValidLinkage(
Linkage) &&
1057 "Invalid vtable alias linkage");
1059 llvm::GlobalAlias *VTableAlias = CGM.getModule().getNamedAlias(AliasName);
1061 VTableAlias = llvm::GlobalAlias::create(VTable->getValueType(),
1062 VTable->getAddressSpace(),
Linkage,
1063 AliasName, &CGM.getModule());
1065 assert(VTableAlias->getValueType() == VTable->getValueType());
1066 assert(VTableAlias->getLinkage() ==
Linkage);
1068 VTableAlias->setVisibility(VTable->getVisibility());
1069 VTableAlias->setUnnamedAddr(VTable->getUnnamedAddr());
1072 if (!VTable->hasComdat()) {
1073 VTable->setLinkage(llvm::GlobalValue::InternalLinkage);
1083 VTable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1086 VTableAlias->setAliasee(VTable);
1098llvm::GlobalVariable::LinkageTypes
1101 return llvm::GlobalVariable::InternalLinkage;
1110 IsInNamedModule ?
nullptr : Context.getCurrentKeyFunction(RD);
1111 if (IsInNamedModule || (keyFunction && !RD->
hasAttr<DLLImportAttr>())) {
1115 if (keyFunction && keyFunction->
hasBody(def))
1118 bool IsExternalDefinition =
1129 (IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
1130 CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) &&
1131 "Shouldn't query vtable linkage without the class in module units, "
1132 "key function, optimizations, or debug info");
1133 if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
1134 return llvm::GlobalVariable::AvailableExternallyLinkage;
1136 if (keyFunction && keyFunction->
isInlined())
1137 return !Context.getLangOpts().AppleKext
1138 ? llvm::GlobalVariable::LinkOnceODRLinkage
1139 : llvm::Function::InternalLinkage;
1141 return llvm::GlobalVariable::ExternalLinkage;
1144 return !Context.getLangOpts().AppleKext ?
1145 llvm::GlobalVariable::LinkOnceODRLinkage :
1146 llvm::Function::InternalLinkage;
1149 return !Context.getLangOpts().AppleKext ?
1150 llvm::GlobalVariable::WeakODRLinkage :
1151 llvm::Function::InternalLinkage;
1154 return IsExternalDefinition
1155 ? llvm::GlobalVariable::AvailableExternallyLinkage
1156 : llvm::GlobalVariable::ExternalLinkage;
1162 if (Context.getLangOpts().AppleKext)
1163 return llvm::Function::InternalLinkage;
1165 llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage =
1166 llvm::GlobalValue::LinkOnceODRLinkage;
1167 llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage =
1168 llvm::GlobalValue::WeakODRLinkage;
1169 if (RD->
hasAttr<DLLExportAttr>()) {
1171 DiscardableODRLinkage = NonDiscardableODRLinkage;
1172 }
else if (RD->
hasAttr<DLLImportAttr>()) {
1174 DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1175 NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1182 return DiscardableODRLinkage;
1188 return DiscardableODRLinkage;
1190 ? llvm::GlobalVariable::AvailableExternallyLinkage
1191 : llvm::GlobalVariable::ExternalLinkage;
1194 return NonDiscardableODRLinkage;
1197 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
1207 VTables.GenerateClassData(theClass);
1213 DI->completeClassData(RD);
1216 CGM.getCXXABI().emitVirtualInheritanceTables(RD);
1218 CGM.getCXXABI().emitVTableDefinitions(*
this, RD);
1232 assert(RD->
isDynamicClass() &&
"Non-dynamic classes have no VTable.");
1236 if (CGM.getTarget().getCXXABI().isMicrosoft())
1258 const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
1264 return !keyFunction->
hasBody();
1283void CodeGenModule::EmitDeferredVTables() {
1287 size_t savedSize = DeferredVTables.size();
1290 for (
const CXXRecordDecl *RD : DeferredVTables)
1292 VTables.GenerateClassData(RD);
1293 else if (shouldOpportunisticallyEmitVTables())
1294 OpportunisticVTables.push_back(RD);
1296 assert(savedSize == DeferredVTables.size() &&
1297 "deferred extra vtables during vtable emission?");
1298 DeferredVTables.clear();
1302 if (RD->
hasAttr<LTOVisibilityPublicAttr>() || RD->
hasAttr<UuidAttr>() ||
1314 if (
auto *ND = dyn_cast<NamespaceDecl>(D))
1316 if (II->isStr(
"std") || II->isStr(
"stdext"))
1338 const CXXRecordDecl *RD, llvm::DenseSet<const CXXRecordDecl *> &Visited) {
1344 if (!Visited.insert(RD).second)
1345 return llvm::GlobalObject::VCallVisibilityTranslationUnit;
1348 llvm::GlobalObject::VCallVisibility TypeVis;
1350 TypeVis = llvm::GlobalObject::VCallVisibilityTranslationUnit;
1352 TypeVis = llvm::GlobalObject::VCallVisibilityLinkageUnit;
1354 TypeVis = llvm::GlobalObject::VCallVisibilityPublic;
1356 for (
const auto &B : RD->
bases())
1357 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1362 for (
const auto &B : RD->
vbases())
1363 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1372 llvm::GlobalVariable *VTable,
1384 struct AddressPoint {
1388 bool operator<(
const AddressPoint &RHS)
const {
1389 int D =
TypeName.compare(RHS.TypeName);
1390 return D < 0 || (D == 0 && Offset < RHS.Offset);
1393 std::vector<AddressPoint> AddressPoints;
1395 AddressPoint N{AP.first.getBase(),
1397 AP.second.AddressPointIndex,
1399 llvm::raw_string_ostream Stream(N.TypeName);
1402 AddressPoints.push_back(std::move(N));
1406 llvm::sort(AddressPoints);
1409 for (
auto AP : AddressPoints) {
1417 for (
unsigned I = 0; I != Comps.size(); ++I) {
1421 Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(),
1422 std::nullopt, AP.Base));
1423 VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD);
1429 llvm::DenseSet<const CXXRecordDecl *> Visited;
1430 llvm::GlobalObject::VCallVisibility TypeVis =
1432 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1433 VTable->setVCallVisibilityMetadata(TypeVis);
static RValue PerformReturnAdjustment(CodeGenFunction &CGF, QualType ResultType, RValue RV, const ThunkInfo &Thunk)
static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk, llvm::Function *ThunkFn, bool ForVTable, GlobalDecl GD)
static bool shouldEmitVTableThunk(CodeGenModule &CGM, const CXXMethodDecl *MD, bool IsUnprototyped, bool ForVTable)
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 bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM, const CXXRecordDecl *RD)
static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &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 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 UseRelativeLayout(const CodeGenModule &CGM)
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 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)
ItaniumVTableContext & getItaniumVTableContext()
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.
bool useRelativeLayout() const
Return true if the relative vtable layout is used.
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.
bool isRelativeLayout() const
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?
bool isItaniumFamily() const
Does this ABI generally fall into the Itanium family of ABIs?
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.
const FunctionProtoType * T
@ 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.