23#include "llvm/IR/IRBuilder.h"
24#include "llvm/IR/IntrinsicInst.h"
25#include "llvm/IR/Intrinsics.h"
26#include "llvm/Transforms/Utils/Cloning.h"
35 : CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {}
39 return GetOrCreateLLVMFunction(Name, FnTy, GD,
true,
44 llvm::GlobalVariable *VTable =
45 CGM.getCXXABI().getAddrOfVTable(RD,
CharUnits());
50 llvm::Function *ThunkFn,
bool ForVTable,
60 ThunkFn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
61 ThunkFn->setDSOLocal(
true);
65 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
84 llvm::BasicBlock *AdjustNull =
nullptr;
85 llvm::BasicBlock *AdjustNotNull =
nullptr;
86 llvm::BasicBlock *AdjustEnd =
nullptr;
108 if (NullCheckValue) {
109 CGF.
Builder.CreateBr(AdjustEnd);
111 CGF.
Builder.CreateBr(AdjustEnd);
114 llvm::PHINode *PHI = CGF.
Builder.CreatePHI(ReturnValue->getType(), 2);
115 PHI->addIncoming(ReturnValue, AdjustNotNull);
116 PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()),
130 llvm::ValueToValueMapTy &VMap) {
132 auto *DIS = Fn->getSubprogram();
135 auto *NewDIS = llvm::MDNode::replaceWithDistinct(DIS->clone());
140 NewDIS->replaceRetainedNodes(llvm::MDTuple::get(Fn->getContext(), {}));
141 VMap.MD()[DIS].reset(NewDIS);
153 auto PrepareVariableMapping = [&VMap](llvm::DILocalVariable *DILocal) {
154 if (DILocal->isResolved())
157 if (llvm::DIType *Ty = DILocal->getType(); Ty && !Ty->isResolved())
158 VMap.MD()[Ty].reset(Ty);
163 for (
auto &BB : *Fn) {
165 for (llvm::DbgVariableRecord &DVR :
166 llvm::filterDbgVars(I.getDbgRecordRange()))
167 PrepareVariableMapping(DVR.getVariable());
169 if (
auto *DII = dyn_cast<llvm::DbgVariableIntrinsic>(&I))
170 PrepareVariableMapping(DII->getVariable());
201 llvm::Type *Ty =
CGM.getTypes().GetFunctionType(FnInfo);
202 llvm::Value *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
209 CGM.ErrorUnsupported(MD,
"return-adjusting thunk with variadic arguments");
212 assert(!BaseFn->isDeclaration() &&
"cannot clone undefined variadic method");
215 llvm::ValueToValueMapTy VMap;
220 llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
221 Fn->replaceAllUsesWith(NewFn);
223 Fn->eraseFromParent();
230 llvm::Function::arg_iterator AI = Fn->arg_begin();
231 if (
CGM.ReturnTypeUsesSRet(FnInfo))
239 llvm::BasicBlock *EntryBB = &Fn->front();
240 llvm::BasicBlock::iterator ThisStore =
241 llvm::find_if(*EntryBB, [&](llvm::Instruction &I) {
244 assert(ThisStore != EntryBB->end() &&
245 "Store of this should be in entry block?");
247 Builder.SetInsertPoint(&*ThisStore);
250 llvm::Value *AdjustedThisPtr =
CGM.getCXXABI().performThisAdjustment(
251 *
this, ThisPtr, ThisValueClass, Thunk);
252 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr,
253 ThisStore->getOperand(0)->getType());
254 ThisStore->setOperand(0, AdjustedThisPtr);
258 for (llvm::BasicBlock &BB : *Fn) {
259 llvm::Instruction *
T = BB.getTerminator();
262 T->eraseFromParent();
276 bool IsUnprototyped) {
277 assert(!
CurGD.getDecl() &&
"CurGD was already set!");
286 ResultType =
CGM.getContext().VoidTy;
287 else if (
CGM.getCXXABI().HasThisReturn(GD))
288 ResultType = ThisType;
289 else if (
CGM.getCXXABI().hasMostDerivedReturn(GD))
290 ResultType =
CGM.getContext().VoidPtrTy;
296 CGM.getCXXABI().buildThisParam(*
this, FunctionArgs);
299 if (!IsUnprototyped) {
303 CGM.getCXXABI().addImplicitStructorParams(*
this, ResultType,
315 CGM.getCXXABI().EmitInstanceFunctionProlog(*
this);
316 CXXThisValue = CXXABIThisValue;
332 bool IsUnprototyped) {
334 "Please use a new CGF for this thunk");
343 llvm::Value *AdjustedThisPtr =
345 ThisValueClass, *Thunk)
354 CGM.ErrorUnsupported(
355 MD,
"return-adjusting thunk with incomplete parameter type");
357 llvm_unreachable(
"shouldn't try to emit musttail return-adjusting "
358 "thunks for variadic functions");
360 CGM.ErrorUnsupported(
361 MD,
"non-trivial argument copy for return-adjusting thunk");
373 CGM.getCXXABI().adjustCallArgsForDestructorThunk(*
this,
CurGD, CallArgs);
376 unsigned PrefixArgs = CallArgs.size() - 1;
387 assert(CallFnInfo.getRegParm() ==
CurFnInfo->getRegParm() &&
388 CallFnInfo.isNoReturn() ==
CurFnInfo->isNoReturn() &&
389 CallFnInfo.getCallingConvention() ==
391 CallFnInfo.getX86ABIAVXLevel() ==
CurFnInfo->getX86ABIAVXLevel());
393 similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),
395 assert(CallFnInfo.arg_size() ==
CurFnInfo->arg_size());
396 for (
unsigned i = 0, e =
CurFnInfo->arg_size(); i != e; ++i)
397 assert(
similar(CallFnInfo.arg_begin()[i].info,
398 CallFnInfo.arg_begin()[i].type,
406 :
CGM.getCXXABI().hasMostDerivedReturn(
CurGD)
407 ?
CGM.getContext().VoidPtrTy
417 llvm::CallBase *CallOrInvoke;
419 CallArgs, &CallOrInvoke);
424 else if (llvm::CallInst*
Call = dyn_cast<llvm::CallInst>(CallOrInvoke))
425 Call->setTailCallKind(llvm::CallInst::TCK_Tail);
429 CGM.getCXXABI().EmitReturnFromThunk(*
this, RV, ResultType);
438 llvm::Value *AdjustedThisPtr,
439 llvm::FunctionCallee Callee) {
451 llvm::Type *ThisType = Args[ThisArgNo]->getType();
452 if (ThisType != AdjustedThisPtr->getType())
453 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
454 Args[ThisArgNo] = AdjustedThisPtr;
456 assert(ThisAI.
isInAlloca() &&
"this is passed directly or inalloca");
459 if (ThisType != AdjustedThisPtr->getType())
460 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
461 Builder.CreateStore(AdjustedThisPtr, ThisAddr);
466 llvm::CallInst *
Call =
Builder.CreateCall(Callee, Args);
467 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
471 llvm::AttributeList Attrs;
472 CGM.ConstructAttributeList(Callee.getCallee()->getName(), *
CurFnInfo, GD,
475 Call->setAttributes(Attrs);
478 if (
Call->getType()->isVoidTy())
493 bool IsUnprototyped) {
504 Ty =
CGM.getTypes().GetFunctionType(FnInfo);
506 llvm::Constant *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
510 &Thunk, IsUnprototyped);
514 bool IsUnprototyped,
bool ForVTable) {
531llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
539 SmallString<256> Name;
540 MangleContext &MCtx = CGM.getCXXABI().getMangleContext();
541 llvm::raw_svector_ostream
Out(Name);
543 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
549 if (CGM.getContext().useAbbreviatedThunkName(GD, Name.str())) {
551 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
558 llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
559 llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD);
562 bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible(
569 const CGFunctionInfo &FnInfo =
570 IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD)
571 : CGM.getTypes().arrangeGlobalDeclaration(GD);
572 llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo);
577 if (ThunkFn->getFunctionType() != ThunkFnTy) {
578 llvm::GlobalValue *OldThunkFn = ThunkFn;
580 assert(OldThunkFn->isDeclaration() &&
"Shouldn't replace non-declaration");
583 OldThunkFn->setName(StringRef());
584 ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
585 Name.str(), &CGM.getModule());
586 CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn,
false);
588 if (!OldThunkFn->use_empty()) {
589 OldThunkFn->replaceAllUsesWith(ThunkFn);
593 OldThunkFn->eraseFromParent();
596 bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions();
597 bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions;
599 if (!ThunkFn->isDeclaration()) {
600 if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) {
614 ThunkFn->addFnAttr(
"thunk");
616 CGM.SetLLVMFunctionAttributesForDefinition(GD.
getDecl(), ThunkFn);
623 bool ShouldCloneVarArgs =
false;
624 if (!IsUnprototyped && ThunkFn->isVarArg()) {
625 ShouldCloneVarArgs =
true;
627 switch (CGM.getTriple().getArch()) {
628 case llvm::Triple::x86_64:
629 case llvm::Triple::x86:
630 case llvm::Triple::aarch64:
631 ShouldCloneVarArgs =
false;
639 if (ShouldCloneVarArgs) {
640 if (UseAvailableExternallyLinkage)
643 CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI);
646 CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped);
662 VTContext->getThunkInfo(GD);
664 if (!ThunkInfoVector)
667 for (
const ThunkInfo& Thunk : *ThunkInfoVector)
668 maybeEmitThunk(GD, Thunk,
false);
672 llvm::Constant *component,
673 unsigned vtableAddressPoint,
674 bool vtableHasLocalLinkage,
675 bool isCompleteDtor)
const {
677 if (component->isNullValue())
678 return builder.
add(llvm::ConstantInt::get(CGM.
Int32Ty, 0));
695 auto stubLinkage = vtableHasLocalLinkage
696 ? llvm::GlobalValue::InternalLinkage
697 : llvm::GlobalValue::LinkOnceODRLinkage;
699 llvm::Constant *target;
700 if (
auto *func = dyn_cast<llvm::Function>(globalVal)) {
701 target = llvm::DSOLocalEquivalent::get(func);
704 rttiProxyName.append(
".rtti_proxy");
710 llvm::GlobalVariable *proxy =
module.getNamedGlobal(rttiProxyName);
712 proxy =
new llvm::GlobalVariable(module, globalVal->getType(),
714 globalVal, rttiProxyName);
715 proxy->setDSOLocal(
true);
716 proxy->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
717 if (!proxy->hasLocalLinkage()) {
718 proxy->setVisibility(llvm::GlobalValue::HiddenVisibility);
719 proxy->setComdat(module.getOrInsertComdat(rttiProxyName));
742 return CGM.getVTableComponentType();
748 builder.
add(llvm::ConstantExpr::getIntToPtr(
760 const VTableLayout &layout,
761 unsigned componentIndex,
762 llvm::Constant *rtti,
763 unsigned &nextVTableThunkIndex,
764 unsigned vtableAddressPoint,
765 bool vtableHasLocalLinkage) {
768 bool RelativeCXXABIVTables = CGM.getLangOpts().RelativeCXXABIVTables;
769 auto addOffsetConstant =
772 switch (component.getKind()) {
774 return addOffsetConstant(CGM, builder, component.getVCallOffset());
777 return addOffsetConstant(CGM, builder, component.getVBaseOffset());
780 return addOffsetConstant(CGM, builder, component.getOffsetToTop());
783 if (RelativeCXXABIVTables)
784 return addRelativeComponent(builder, rtti, vtableAddressPoint,
785 vtableHasLocalLinkage,
788 return builder.
add(rtti);
793 GlobalDecl GD = component.getGlobalDecl(
794 CGM.getContext().getTargetInfo().emitVectorDeletingDtors(
795 CGM.getContext().getLangOpts()));
799 layout.
vtable_thunks()[nextVTableThunkIndex].first == componentIndex;
801 if (CGM.getLangOpts().CUDA) {
809 CGM.getLangOpts().CUDAIsDevice
810 ? MD->
hasAttr<CUDADeviceAttr>()
811 : (MD->
hasAttr<CUDAHostAttr>() || !MD->
hasAttr<CUDADeviceAttr>());
812 if (!CanEmitMethod) {
814 nextVTableThunkIndex++;
816 llvm::ConstantExpr::getNullValue(CGM.GlobalsInt8PtrTy));
821 auto getSpecialVirtualFn = [&](StringRef
name) -> llvm::Constant * {
829 if (RelativeCXXABIVTables)
830 return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
834 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPIsTargetDevice &&
835 CGM.getTriple().isNVPTX())
836 return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
837 llvm::FunctionType *fnTy =
838 llvm::FunctionType::get(CGM.VoidTy,
false);
840 CGM.CreateRuntimeFunction(fnTy, name).getCallee());
841 if (
auto f = dyn_cast<llvm::Function>(fn))
842 f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
846 llvm::Constant *fnPtr;
852 getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName());
853 fnPtr = PureVirtualFn;
857 if (!DeletedVirtualFn)
859 getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName());
860 fnPtr = DeletedVirtualFn;
863 }
else if (IsThunk) {
864 auto &thunkInfo = layout.
vtable_thunks()[nextVTableThunkIndex].second;
866 nextVTableThunkIndex++;
867 fnPtr = maybeEmitThunk(GD, thunkInfo,
true);
868 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) {
869 assert(thunkInfo.Method &&
"Method not set");
875 llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
876 fnPtr = CGM.GetAddrOfFunction(GD, fnTy,
true);
877 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
881 if (RelativeCXXABIVTables) {
882 return addRelativeComponent(
883 builder, fnPtr, vtableAddressPoint, vtableHasLocalLinkage,
890 unsigned FnAS = fnPtr->getType()->getPointerAddressSpace();
891 unsigned GVAS = CGM.GlobalsInt8PtrTy->getPointerAddressSpace();
895 llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy);
896 if (
const auto &Schema =
897 CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
899 return builder.
add(fnPtr);
904 if (RelativeCXXABIVTables)
905 return builder.
add(llvm::ConstantExpr::getNullValue(CGM.Int32Ty));
910 llvm_unreachable(
"Unexpected vtable component kind");
916 for (
unsigned i = 0, e = layout.
getNumVTables(); i != e; ++i)
917 tys.push_back(llvm::ArrayType::get(componentType, layout.
getVTableSize(i)));
919 return llvm::StructType::get(CGM.getLLVMContext(), tys);
924 llvm::Constant *rtti,
925 bool vtableHasLocalLinkage) {
929 unsigned nextVTableThunkIndex = 0;
930 for (
unsigned vtableIndex = 0, endIndex = layout.
getNumVTables();
931 vtableIndex != endIndex; ++vtableIndex) {
932 auto vtableElem = builder.
beginArray(componentType);
935 size_t vtableEnd = vtableStart + layout.
getVTableSize(vtableIndex);
936 for (
size_t componentIndex = vtableStart; componentIndex < vtableEnd;
938 addVTableComponent(vtableElem, layout, componentIndex, rtti,
939 nextVTableThunkIndex, addressPoints[vtableIndex],
940 vtableHasLocalLinkage);
942 vtableElem.finishAndAddTo(builder);
948 llvm::GlobalVariable::LinkageTypes
Linkage,
949 VTableAddressPointsMapTy &AddressPoints) {
951 DI->completeClassData(
Base.getBase());
953 std::unique_ptr<VTableLayout> VTLayout(
955 Base.getBase(),
Base.getBaseOffset(), BaseIsVirtual, RD));
958 AddressPoints = VTLayout->getAddressPoints();
962 llvm::raw_svector_ostream Out(OutName);
964 .mangleCXXCtorVTable(RD,
Base.getBaseOffset().getQuantity(),
965 Base.getBase(), Out);
968 bool UsingRelativeLayout = CGM.getLangOpts().RelativeCXXABIVTables;
969 bool VTableAliasExists =
970 UsingRelativeLayout && CGM.getModule().getNamedAlias(Name);
971 if (VTableAliasExists) {
973 Name.append(
".local");
983 if (
Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
984 Linkage = llvm::GlobalVariable::InternalLinkage;
986 llvm::Align Align = CGM.getDataLayout().getABITypeAlign(VTType);
989 llvm::GlobalVariable *VTable =
990 CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType,
Linkage, Align);
997 if (!CGM.shouldEmitRTTI() || CGM.mayVTableBeDuplicated(VTable->getLinkage()))
998 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1000 llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
1001 CGM.getContext().getCanonicalTagType(
Base.getBase()));
1007 VTable->hasLocalLinkage());
1008 components.finishAndSetAsInitializer(VTable);
1012 assert(!VTable->isDeclaration() &&
"Shouldn't set properties on declaration");
1013 CGM.setGVProperties(VTable, RD);
1015 CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout);
1017 if (UsingRelativeLayout) {
1019 if (!VTable->isDSOLocal())
1035 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::HWAddress)) {
1036 llvm::GlobalValue::SanitizerMetadata Meta;
1037 if (GV->hasSanitizerMetadata())
1038 Meta = GV->getSanitizerMetadata();
1039 Meta.NoHWAddress =
true;
1040 GV->setSanitizerMetadata(Meta);
1051 llvm::StringRef AliasNameRef) {
1052 assert(CGM.getLangOpts().RelativeCXXABIVTables &&
1053 "Can only use this if the relative vtable ABI is used");
1054 assert(!VTable->isDSOLocal() &&
"This should be called only if the vtable is "
1055 "not guaranteed to be dso_local");
1060 if (VTable->hasAvailableExternallyLinkage())
1067 VTable->setName(AliasName +
".local");
1069 auto Linkage = VTable->getLinkage();
1070 assert(llvm::GlobalAlias::isValidLinkage(
Linkage) &&
1071 "Invalid vtable alias linkage");
1073 llvm::GlobalAlias *VTableAlias = CGM.getModule().getNamedAlias(AliasName);
1075 VTableAlias = llvm::GlobalAlias::create(VTable->getValueType(),
1076 VTable->getAddressSpace(),
Linkage,
1077 AliasName, &CGM.getModule());
1079 assert(VTableAlias->getValueType() == VTable->getValueType());
1080 assert(VTableAlias->getLinkage() ==
Linkage);
1082 VTableAlias->setVisibility(VTable->getVisibility());
1083 VTableAlias->setUnnamedAddr(VTable->getUnnamedAddr());
1086 if (!VTable->hasComdat()) {
1087 VTable->setLinkage(llvm::GlobalValue::InternalLinkage);
1097 VTable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1100 VTableAlias->setAliasee(VTable);
1112llvm::GlobalVariable::LinkageTypes
1115 return llvm::GlobalVariable::InternalLinkage;
1124 IsInNamedModule ?
nullptr : Context.getCurrentKeyFunction(RD);
1125 if (IsInNamedModule || (keyFunction && !RD->
hasAttr<DLLImportAttr>())) {
1129 if (keyFunction && keyFunction->
hasBody(def))
1132 bool IsExternalDefinition =
1146 (IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
1147 CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo ||
1149 "Shouldn't query vtable linkage without the class in module units, "
1150 "key function, optimizations, or debug info");
1151 if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
1152 return llvm::GlobalVariable::AvailableExternallyLinkage;
1154 if (keyFunction && keyFunction->
isInlined())
1155 return !Context.getLangOpts().AppleKext
1156 ? llvm::GlobalVariable::LinkOnceODRLinkage
1157 : llvm::Function::InternalLinkage;
1159 return llvm::GlobalVariable::ExternalLinkage;
1162 return !Context.getLangOpts().AppleKext ?
1163 llvm::GlobalVariable::LinkOnceODRLinkage :
1164 llvm::Function::InternalLinkage;
1167 return !Context.getLangOpts().AppleKext ?
1168 llvm::GlobalVariable::WeakODRLinkage :
1169 llvm::Function::InternalLinkage;
1172 return IsExternalDefinition
1173 ? llvm::GlobalVariable::AvailableExternallyLinkage
1174 : llvm::GlobalVariable::ExternalLinkage;
1180 if (Context.getLangOpts().AppleKext)
1181 return llvm::Function::InternalLinkage;
1183 llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage =
1184 llvm::GlobalValue::LinkOnceODRLinkage;
1185 llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage =
1186 llvm::GlobalValue::WeakODRLinkage;
1187 if (RD->
hasAttr<DLLExportAttr>()) {
1189 DiscardableODRLinkage = NonDiscardableODRLinkage;
1190 }
else if (RD->
hasAttr<DLLImportAttr>()) {
1192 DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1193 NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1200 return DiscardableODRLinkage;
1206 return DiscardableODRLinkage;
1208 ? llvm::GlobalVariable::AvailableExternallyLinkage
1209 : llvm::GlobalVariable::ExternalLinkage;
1212 return NonDiscardableODRLinkage;
1215 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
1219 llvm::GlobalValue::LinkageTypes
Linkage)
const {
1222 llvm::GlobalValue::isWeakForLinker(
Linkage);
1232 VTables.GenerateClassData(theClass);
1233 EmittedVTables.insert(theClass);
1239 DI->completeClassData(RD);
1242 CGM.getCXXABI().emitVirtualInheritanceTables(RD);
1244 CGM.getCXXABI().emitVTableDefinitions(*
this, RD);
1258 assert(RD->
isDynamicClass() &&
"Non-dynamic classes have no VTable.");
1262 if (CGM.getTarget().getCXXABI().isMicrosoft())
1284 const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
1290 return !keyFunction->
hasBody();
1309void CodeGenModule::EmitDeferredVTables() {
1313 size_t savedSize = DeferredVTables.size();
1316 for (
const CXXRecordDecl *RD : DeferredVTables) {
1319 if (EmittedVTables.count(RD) &&
1324 VTables.GenerateClassData(RD);
1325 else if (shouldOpportunisticallyEmitVTables())
1326 OpportunisticVTables.push_back(RD);
1329 assert(savedSize == DeferredVTables.size() &&
1330 "deferred extra vtables during vtable emission?");
1331 DeferredVTables.clear();
1335 if (RD->
hasAttr<LTOVisibilityPublicAttr>() || RD->
hasAttr<UuidAttr>() ||
1347 if (
auto *ND = dyn_cast<NamespaceDecl>(D))
1349 if (II->isStr(
"std") || II->isStr(
"stdext"))
1371 const CXXRecordDecl *RD, llvm::DenseSet<const CXXRecordDecl *> &Visited) {
1377 if (!Visited.insert(RD).second)
1378 return llvm::GlobalObject::VCallVisibilityTranslationUnit;
1381 llvm::GlobalObject::VCallVisibility TypeVis;
1383 TypeVis = llvm::GlobalObject::VCallVisibilityTranslationUnit;
1385 TypeVis = llvm::GlobalObject::VCallVisibilityLinkageUnit;
1387 TypeVis = llvm::GlobalObject::VCallVisibilityPublic;
1389 for (
const auto &B : RD->
bases())
1390 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1395 for (
const auto &B : RD->
vbases())
1396 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1405 llvm::GlobalVariable *VTable,
1417 struct AddressPoint {
1421 bool operator<(
const AddressPoint &RHS)
const {
1422 int D =
TypeName.compare(RHS.TypeName);
1423 return D < 0 || (D == 0 && Offset < RHS.Offset);
1426 std::vector<AddressPoint> AddressPoints;
1428 AddressPoint N{AP.first.getBase(),
1430 AP.second.AddressPointIndex,
1432 llvm::raw_string_ostream Stream(N.TypeName);
1435 AddressPoints.push_back(std::move(N));
1439 llvm::sort(AddressPoints);
1442 for (
auto AP : AddressPoints) {
1450 for (
unsigned I = 0; I != Comps.size(); ++I) {
1454 Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(),
1455 std::nullopt, AP.Base));
1456 VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD);
1462 llvm::DenseSet<const CXXRecordDecl *> Visited;
1463 llvm::GlobalObject::VCallVisibility TypeVis =
1465 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1466 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
bool mayVTableBeDuplicated(llvm::GlobalValue::LinkageTypes Linkage) const
Returns true if a vtable with the given linkage may be emitted with more than one address in the prog...
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.
virtual VTableUniquenessKind getVTableUniqueness() const
Returns whether the target's ABI guarantees that a class's vtable has a unique address program-wide.
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.
@ UniqueIfStrongLinkage
A vtable with strong linkage (e.g., a class with a key function) is unique, but a vague-linkage (weak...
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.