23#include "llvm/IR/IRBuilder.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());
196 llvm::Type *Ty =
CGM.getTypes().GetFunctionType(FnInfo);
197 llvm::Value *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
204 CGM.ErrorUnsupported(MD,
"return-adjusting thunk with variadic arguments");
207 assert(!BaseFn->isDeclaration() &&
"cannot clone undefined variadic method");
210 llvm::ValueToValueMapTy VMap;
215 llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
216 Fn->replaceAllUsesWith(NewFn);
218 Fn->eraseFromParent();
225 llvm::Function::arg_iterator AI = Fn->arg_begin();
226 if (
CGM.ReturnTypeUsesSRet(FnInfo))
236 CGM.getClassPointerAlignment(ThisValueClass));
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);
247 llvm::Value *AdjustedThisPtr =
CGM.getCXXABI().performThisAdjustment(
248 *
this, ThisPtr, ThisValueClass, Thunk);
249 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr,
250 ThisStore->getOperand(0)->getType());
251 ThisStore->setOperand(0, AdjustedThisPtr);
255 for (llvm::BasicBlock &BB : *Fn) {
256 llvm::Instruction *
T = BB.getTerminator();
259 T->eraseFromParent();
273 bool IsUnprototyped) {
274 assert(!
CurGD.getDecl() &&
"CurGD was already set!");
283 ResultType =
CGM.getContext().VoidTy;
284 else if (
CGM.getCXXABI().HasThisReturn(GD))
285 ResultType = ThisType;
286 else if (
CGM.getCXXABI().hasMostDerivedReturn(GD))
287 ResultType =
CGM.getContext().VoidPtrTy;
293 CGM.getCXXABI().buildThisParam(*
this, FunctionArgs);
296 if (!IsUnprototyped) {
300 CGM.getCXXABI().addImplicitStructorParams(*
this, ResultType,
312 CGM.getCXXABI().EmitInstanceFunctionProlog(*
this);
313 CXXThisValue = CXXABIThisValue;
329 bool IsUnprototyped) {
331 "Please use a new CGF for this thunk");
335 llvm::Value *AdjustedThisPtr;
341 CGM.getClassPointerAlignment(ThisValueClass),
false,
343 AdjustedThisPtr =
CGM.getCXXABI().performThisAdjustment(
344 *
this, ThisPtr, ThisValueClass, *Thunk);
355 CGM.ErrorUnsupported(
356 MD,
"return-adjusting thunk with incomplete parameter type");
358 llvm_unreachable(
"shouldn't try to emit musttail return-adjusting "
359 "thunks for variadic functions");
361 CGM.ErrorUnsupported(
362 MD,
"non-trivial argument copy for return-adjusting thunk");
374 CGM.getCXXABI().adjustCallArgsForDestructorThunk(*
this,
CurGD, CallArgs);
377 unsigned PrefixArgs = CallArgs.size() - 1;
388 assert(CallFnInfo.getRegParm() ==
CurFnInfo->getRegParm() &&
389 CallFnInfo.isNoReturn() ==
CurFnInfo->isNoReturn() &&
390 CallFnInfo.getCallingConvention() ==
392 CallFnInfo.getX86ABIAVXLevel() ==
CurFnInfo->getX86ABIAVXLevel());
394 similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),
396 assert(CallFnInfo.arg_size() ==
CurFnInfo->arg_size());
397 for (
unsigned i = 0, e =
CurFnInfo->arg_size(); i != e; ++i)
398 assert(
similar(CallFnInfo.arg_begin()[i].info,
399 CallFnInfo.arg_begin()[i].type,
407 :
CGM.getCXXABI().hasMostDerivedReturn(
CurGD)
408 ?
CGM.getContext().VoidPtrTy
418 llvm::CallBase *CallOrInvoke;
420 CallArgs, &CallOrInvoke);
425 else if (llvm::CallInst*
Call = dyn_cast<llvm::CallInst>(CallOrInvoke))
426 Call->setTailCallKind(llvm::CallInst::TCK_Tail);
430 CGM.getCXXABI().EmitReturnFromThunk(*
this, RV, ResultType);
439 llvm::Value *AdjustedThisPtr,
440 llvm::FunctionCallee Callee) {
452 llvm::Type *ThisType = Args[ThisArgNo]->getType();
453 if (ThisType != AdjustedThisPtr->getType())
454 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
455 Args[ThisArgNo] = AdjustedThisPtr;
457 assert(ThisAI.
isInAlloca() &&
"this is passed directly or inalloca");
460 if (ThisType != AdjustedThisPtr->getType())
461 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
462 Builder.CreateStore(AdjustedThisPtr, ThisAddr);
467 llvm::CallInst *
Call =
Builder.CreateCall(Callee, Args);
468 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
472 llvm::AttributeList Attrs;
473 CGM.ConstructAttributeList(Callee.getCallee()->getName(), *
CurFnInfo, GD,
476 Call->setAttributes(Attrs);
479 if (
Call->getType()->isVoidTy())
494 bool IsUnprototyped) {
505 Ty =
CGM.getTypes().GetFunctionType(FnInfo);
507 llvm::Constant *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
511 &Thunk, IsUnprototyped);
515 bool IsUnprototyped,
bool ForVTable) {
532llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
540 SmallString<256> Name;
541 MangleContext &MCtx = CGM.getCXXABI().getMangleContext();
542 llvm::raw_svector_ostream
Out(Name);
544 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
550 if (CGM.getContext().useAbbreviatedThunkName(GD, Name.str())) {
552 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
559 llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
560 llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD);
563 bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible(
570 const CGFunctionInfo &FnInfo =
571 IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD)
572 : CGM.getTypes().arrangeGlobalDeclaration(GD);
573 llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo);
578 if (ThunkFn->getFunctionType() != ThunkFnTy) {
579 llvm::GlobalValue *OldThunkFn = ThunkFn;
581 assert(OldThunkFn->isDeclaration() &&
"Shouldn't replace non-declaration");
584 OldThunkFn->setName(StringRef());
585 ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
586 Name.str(), &CGM.getModule());
587 CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn,
false);
589 if (!OldThunkFn->use_empty()) {
590 OldThunkFn->replaceAllUsesWith(ThunkFn);
594 OldThunkFn->eraseFromParent();
597 bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions();
598 bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions;
600 if (!ThunkFn->isDeclaration()) {
601 if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) {
615 ThunkFn->addFnAttr(
"thunk");
617 CGM.SetLLVMFunctionAttributesForDefinition(GD.
getDecl(), ThunkFn);
624 bool ShouldCloneVarArgs =
false;
625 if (!IsUnprototyped && ThunkFn->isVarArg()) {
626 ShouldCloneVarArgs =
true;
628 switch (CGM.getTriple().getArch()) {
629 case llvm::Triple::x86_64:
630 case llvm::Triple::x86:
631 case llvm::Triple::aarch64:
632 ShouldCloneVarArgs =
false;
640 if (ShouldCloneVarArgs) {
641 if (UseAvailableExternallyLinkage)
644 CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI);
647 CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped);
663 VTContext->getThunkInfo(GD);
665 if (!ThunkInfoVector)
668 for (
const ThunkInfo& Thunk : *ThunkInfoVector)
669 maybeEmitThunk(GD, Thunk,
false);
673 llvm::Constant *component,
674 unsigned vtableAddressPoint,
675 bool vtableHasLocalLinkage,
676 bool isCompleteDtor)
const {
678 if (component->isNullValue())
679 return builder.
add(llvm::ConstantInt::get(CGM.
Int32Ty, 0));
696 auto stubLinkage = vtableHasLocalLinkage
697 ? llvm::GlobalValue::InternalLinkage
698 : llvm::GlobalValue::LinkOnceODRLinkage;
700 llvm::Constant *target;
701 if (
auto *func = dyn_cast<llvm::Function>(globalVal)) {
702 target = llvm::DSOLocalEquivalent::get(func);
705 rttiProxyName.append(
".rtti_proxy");
711 llvm::GlobalVariable *proxy =
module.getNamedGlobal(rttiProxyName);
713 proxy =
new llvm::GlobalVariable(module, globalVal->getType(),
715 globalVal, rttiProxyName);
716 proxy->setDSOLocal(
true);
717 proxy->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
718 if (!proxy->hasLocalLinkage()) {
719 proxy->setVisibility(llvm::GlobalValue::HiddenVisibility);
720 proxy->setComdat(module.getOrInsertComdat(rttiProxyName));
743 return CGM.getVTableComponentType();
749 builder.
add(llvm::ConstantExpr::getIntToPtr(
761 const VTableLayout &layout,
762 unsigned componentIndex,
763 llvm::Constant *rtti,
764 unsigned &nextVTableThunkIndex,
765 unsigned vtableAddressPoint,
766 bool vtableHasLocalLinkage) {
769 bool RelativeCXXABIVTables = CGM.getLangOpts().RelativeCXXABIVTables;
770 auto addOffsetConstant =
773 switch (component.getKind()) {
775 return addOffsetConstant(CGM, builder, component.getVCallOffset());
778 return addOffsetConstant(CGM, builder, component.getVBaseOffset());
781 return addOffsetConstant(CGM, builder, component.getOffsetToTop());
784 if (RelativeCXXABIVTables)
785 return addRelativeComponent(builder, rtti, vtableAddressPoint,
786 vtableHasLocalLinkage,
789 return builder.
add(rtti);
794 GlobalDecl GD = component.getGlobalDecl(
795 CGM.getContext().getTargetInfo().emitVectorDeletingDtors(
796 CGM.getContext().getLangOpts()));
800 layout.
vtable_thunks()[nextVTableThunkIndex].first == componentIndex;
802 if (CGM.getLangOpts().CUDA) {
810 CGM.getLangOpts().CUDAIsDevice
811 ? MD->
hasAttr<CUDADeviceAttr>()
812 : (MD->
hasAttr<CUDAHostAttr>() || !MD->
hasAttr<CUDADeviceAttr>());
813 if (!CanEmitMethod) {
815 nextVTableThunkIndex++;
817 llvm::ConstantExpr::getNullValue(CGM.GlobalsInt8PtrTy));
822 auto getSpecialVirtualFn = [&](StringRef
name) -> llvm::Constant * {
823 llvm::FunctionType *fnTy =
824 llvm::FunctionType::get(CGM.VoidTy,
false);
826 CGM.CreateRuntimeFunction(fnTy, name).getCallee());
827 F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
836 if (CGM.getLangOpts().isTargetDevice()) {
837 F->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
838 CodeGenFunction CGF(CGM);
839 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
840 CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI,
842 CGF.EmitTrapCallAndMakeUnreachable();
843 CGF.FinishFunction();
849 llvm::Constant *fnPtr;
855 getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName());
856 fnPtr = PureVirtualFn;
860 if (!DeletedVirtualFn)
862 getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName());
863 fnPtr = DeletedVirtualFn;
866 }
else if (IsThunk) {
867 auto &thunkInfo = layout.
vtable_thunks()[nextVTableThunkIndex].second;
869 nextVTableThunkIndex++;
870 fnPtr = maybeEmitThunk(GD, thunkInfo,
true);
871 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) {
872 assert(thunkInfo.Method &&
"Method not set");
878 llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
879 fnPtr = CGM.GetAddrOfFunction(GD, fnTy,
true);
880 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
884 if (RelativeCXXABIVTables) {
885 return addRelativeComponent(
886 builder, fnPtr, vtableAddressPoint, vtableHasLocalLinkage,
893 unsigned FnAS = fnPtr->getType()->getPointerAddressSpace();
894 unsigned GVAS = CGM.GlobalsInt8PtrTy->getPointerAddressSpace();
898 llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy);
899 if (
const auto &Schema =
900 CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
902 return builder.
add(fnPtr);
907 if (RelativeCXXABIVTables)
908 return builder.
add(llvm::ConstantExpr::getNullValue(CGM.Int32Ty));
913 llvm_unreachable(
"Unexpected vtable component kind");
919 for (
unsigned i = 0, e = layout.
getNumVTables(); i != e; ++i)
920 tys.push_back(llvm::ArrayType::get(componentType, layout.
getVTableSize(i)));
922 return llvm::StructType::get(CGM.getLLVMContext(), tys);
927 llvm::Constant *rtti,
928 bool vtableHasLocalLinkage) {
932 unsigned nextVTableThunkIndex = 0;
933 for (
unsigned vtableIndex = 0, endIndex = layout.
getNumVTables();
934 vtableIndex != endIndex; ++vtableIndex) {
935 auto vtableElem = builder.
beginArray(componentType);
938 size_t vtableEnd = vtableStart + layout.
getVTableSize(vtableIndex);
939 for (
size_t componentIndex = vtableStart; componentIndex < vtableEnd;
941 addVTableComponent(vtableElem, layout, componentIndex, rtti,
942 nextVTableThunkIndex, addressPoints[vtableIndex],
943 vtableHasLocalLinkage);
945 vtableElem.finishAndAddTo(builder);
951 llvm::GlobalVariable::LinkageTypes
Linkage,
952 VTableAddressPointsMapTy &AddressPoints) {
954 DI->completeClassData(
Base.getBase());
956 std::unique_ptr<VTableLayout> VTLayout(
958 Base.getBase(),
Base.getBaseOffset(), BaseIsVirtual, RD));
961 AddressPoints = VTLayout->getAddressPoints();
965 llvm::raw_svector_ostream Out(OutName);
967 .mangleCXXCtorVTable(RD,
Base.getBaseOffset().getQuantity(),
968 Base.getBase(), Out);
971 bool UsingRelativeLayout = CGM.getLangOpts().RelativeCXXABIVTables;
972 bool VTableAliasExists =
973 UsingRelativeLayout && CGM.getModule().getNamedAlias(Name);
974 if (VTableAliasExists) {
976 Name.append(
".local");
986 if (
Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
987 Linkage = llvm::GlobalVariable::InternalLinkage;
989 llvm::Align Align = CGM.getDataLayout().getABITypeAlign(VTType);
992 llvm::GlobalVariable *VTable =
993 CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType,
Linkage, Align);
1000 if (!CGM.shouldEmitRTTI() || CGM.mayVTableBeDuplicated(VTable->getLinkage()))
1001 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1003 llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
1004 CGM.getContext().getCanonicalTagType(
Base.getBase()));
1010 VTable->hasLocalLinkage());
1011 components.finishAndSetAsInitializer(VTable);
1015 assert(!VTable->isDeclaration() &&
"Shouldn't set properties on declaration");
1016 CGM.setGVProperties(VTable, RD);
1018 CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout);
1020 if (UsingRelativeLayout) {
1022 if (!VTable->isDSOLocal())
1038 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::HWAddress)) {
1039 llvm::GlobalValue::SanitizerMetadata Meta;
1040 if (GV->hasSanitizerMetadata())
1041 Meta = GV->getSanitizerMetadata();
1042 Meta.NoHWAddress =
true;
1043 GV->setSanitizerMetadata(Meta);
1054 llvm::StringRef AliasNameRef) {
1055 assert(CGM.getLangOpts().RelativeCXXABIVTables &&
1056 "Can only use this if the relative vtable ABI is used");
1057 assert(!VTable->isDSOLocal() &&
"This should be called only if the vtable is "
1058 "not guaranteed to be dso_local");
1063 if (VTable->hasAvailableExternallyLinkage())
1070 VTable->setName(AliasName +
".local");
1072 auto Linkage = VTable->getLinkage();
1073 assert(llvm::GlobalAlias::isValidLinkage(
Linkage) &&
1074 "Invalid vtable alias linkage");
1076 llvm::GlobalAlias *VTableAlias = CGM.getModule().getNamedAlias(AliasName);
1078 VTableAlias = llvm::GlobalAlias::create(VTable->getValueType(),
1079 VTable->getAddressSpace(),
Linkage,
1080 AliasName, &CGM.getModule());
1082 assert(VTableAlias->getValueType() == VTable->getValueType());
1083 assert(VTableAlias->getLinkage() ==
Linkage);
1085 VTableAlias->setVisibility(VTable->getVisibility());
1086 VTableAlias->setUnnamedAddr(VTable->getUnnamedAddr());
1089 if (!VTable->hasComdat()) {
1090 VTable->setLinkage(llvm::GlobalValue::InternalLinkage);
1100 VTable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1103 VTableAlias->setAliasee(VTable);
1115llvm::GlobalVariable::LinkageTypes
1118 return llvm::GlobalVariable::InternalLinkage;
1127 IsInNamedModule ?
nullptr : Context.getCurrentKeyFunction(RD);
1128 if (IsInNamedModule || (keyFunction && !RD->
hasAttr<DLLImportAttr>())) {
1132 if (keyFunction && keyFunction->
hasBody(def))
1135 bool IsExternalDefinition =
1149 (IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
1150 CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo ||
1152 "Shouldn't query vtable linkage without the class in module units, "
1153 "key function, optimizations, or debug info");
1154 if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
1155 return llvm::GlobalVariable::AvailableExternallyLinkage;
1157 if (keyFunction && keyFunction->
isInlined())
1158 return !Context.getLangOpts().AppleKext
1159 ? llvm::GlobalVariable::LinkOnceODRLinkage
1160 : llvm::Function::InternalLinkage;
1162 return llvm::GlobalVariable::ExternalLinkage;
1165 return !Context.getLangOpts().AppleKext ?
1166 llvm::GlobalVariable::LinkOnceODRLinkage :
1167 llvm::Function::InternalLinkage;
1170 return !Context.getLangOpts().AppleKext ?
1171 llvm::GlobalVariable::WeakODRLinkage :
1172 llvm::Function::InternalLinkage;
1175 return IsExternalDefinition
1176 ? llvm::GlobalVariable::AvailableExternallyLinkage
1177 : llvm::GlobalVariable::ExternalLinkage;
1183 if (Context.getLangOpts().AppleKext)
1184 return llvm::Function::InternalLinkage;
1186 llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage =
1187 llvm::GlobalValue::LinkOnceODRLinkage;
1188 llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage =
1189 llvm::GlobalValue::WeakODRLinkage;
1190 if (RD->
hasAttr<DLLExportAttr>()) {
1192 DiscardableODRLinkage = NonDiscardableODRLinkage;
1193 }
else if (RD->
hasAttr<DLLImportAttr>()) {
1195 DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1196 NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1203 return DiscardableODRLinkage;
1209 return DiscardableODRLinkage;
1211 ? llvm::GlobalVariable::AvailableExternallyLinkage
1212 : llvm::GlobalVariable::ExternalLinkage;
1215 return NonDiscardableODRLinkage;
1218 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
1222 llvm::GlobalValue::LinkageTypes
Linkage)
const {
1225 llvm::GlobalValue::isWeakForLinker(
Linkage);
1235 VTables.GenerateClassData(theClass);
1236 EmittedVTables.insert(theClass);
1242 DI->completeClassData(RD);
1245 CGM.getCXXABI().emitVirtualInheritanceTables(RD);
1247 CGM.getCXXABI().emitVTableDefinitions(*
this, RD);
1261 assert(RD->
isDynamicClass() &&
"Non-dynamic classes have no VTable.");
1265 if (CGM.getTarget().getCXXABI().isMicrosoft())
1287 const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
1293 return !keyFunction->
hasBody();
1312void CodeGenModule::EmitDeferredVTables() {
1316 size_t savedSize = DeferredVTables.size();
1319 for (
const CXXRecordDecl *RD : DeferredVTables) {
1322 if (EmittedVTables.count(RD) &&
1327 VTables.GenerateClassData(RD);
1328 else if (shouldOpportunisticallyEmitVTables())
1329 OpportunisticVTables.push_back(RD);
1332 assert(savedSize == DeferredVTables.size() &&
1333 "deferred extra vtables during vtable emission?");
1334 DeferredVTables.clear();
1338 if (RD->
hasAttr<LTOVisibilityPublicAttr>() || RD->
hasAttr<UuidAttr>() ||
1350 if (
auto *ND = dyn_cast<NamespaceDecl>(D))
1352 if (II->isStr(
"std") || II->isStr(
"stdext"))
1374 const CXXRecordDecl *RD, llvm::DenseSet<const CXXRecordDecl *> &Visited) {
1380 if (!Visited.insert(RD).second)
1381 return llvm::GlobalObject::VCallVisibilityTranslationUnit;
1384 llvm::GlobalObject::VCallVisibility TypeVis;
1386 TypeVis = llvm::GlobalObject::VCallVisibilityTranslationUnit;
1388 TypeVis = llvm::GlobalObject::VCallVisibilityLinkageUnit;
1390 TypeVis = llvm::GlobalObject::VCallVisibilityPublic;
1392 for (
const auto &B : RD->
bases())
1393 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1398 for (
const auto &B : RD->
vbases())
1399 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1408 llvm::GlobalVariable *VTable,
1420 struct AddressPoint {
1424 bool operator<(
const AddressPoint &RHS)
const {
1425 int D =
TypeName.compare(RHS.TypeName);
1426 return D < 0 || (D == 0 && Offset < RHS.Offset);
1429 std::vector<AddressPoint> AddressPoints;
1431 AddressPoint N{AP.first.getBase(),
1433 AP.second.AddressPointIndex,
1435 llvm::raw_string_ostream Stream(N.TypeName);
1438 AddressPoints.push_back(std::move(N));
1442 llvm::sort(AddressPoints);
1445 for (
auto AP : AddressPoints) {
1453 for (
unsigned I = 0; I != Comps.size(); ++I) {
1457 Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(),
1458 std::nullopt, AP.Base));
1459 VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD);
1465 llvm::DenseSet<const CXXRecordDecl *> Visited;
1466 llvm::GlobalObject::VCallVisibility TypeVis =
1468 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1469 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.
QualType getThisType() const
Return the type of the this pointer.
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.
This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
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.
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
Top level wrappers for InstallAPI frontend operations.
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.