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))
234 llvm::BasicBlock *EntryBB = &Fn->front();
235 llvm::BasicBlock::iterator ThisStore =
236 llvm::find_if(*EntryBB, [&](llvm::Instruction &I) {
239 assert(ThisStore != EntryBB->end() &&
240 "Store of this should be in entry block?");
242 Builder.SetInsertPoint(&*ThisStore);
245 llvm::Value *AdjustedThisPtr =
CGM.getCXXABI().performThisAdjustment(
246 *
this, ThisPtr, ThisValueClass, Thunk);
247 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr,
248 ThisStore->getOperand(0)->getType());
249 ThisStore->setOperand(0, AdjustedThisPtr);
253 for (llvm::BasicBlock &BB : *Fn) {
254 llvm::Instruction *
T = BB.getTerminator();
257 T->eraseFromParent();
271 bool IsUnprototyped) {
272 assert(!
CurGD.getDecl() &&
"CurGD was already set!");
281 ResultType =
CGM.getContext().VoidTy;
282 else if (
CGM.getCXXABI().HasThisReturn(GD))
283 ResultType = ThisType;
284 else if (
CGM.getCXXABI().hasMostDerivedReturn(GD))
285 ResultType =
CGM.getContext().VoidPtrTy;
291 CGM.getCXXABI().buildThisParam(*
this, FunctionArgs);
294 if (!IsUnprototyped) {
298 CGM.getCXXABI().addImplicitStructorParams(*
this, ResultType,
310 CGM.getCXXABI().EmitInstanceFunctionProlog(*
this);
311 CXXThisValue = CXXABIThisValue;
327 bool IsUnprototyped) {
329 "Please use a new CGF for this thunk");
338 llvm::Value *AdjustedThisPtr =
340 ThisValueClass, *Thunk)
349 CGM.ErrorUnsupported(
350 MD,
"return-adjusting thunk with incomplete parameter type");
352 llvm_unreachable(
"shouldn't try to emit musttail return-adjusting "
353 "thunks for variadic functions");
355 CGM.ErrorUnsupported(
356 MD,
"non-trivial argument copy for return-adjusting thunk");
368 CGM.getCXXABI().adjustCallArgsForDestructorThunk(*
this,
CurGD, CallArgs);
371 unsigned PrefixArgs = CallArgs.size() - 1;
382 assert(CallFnInfo.getRegParm() ==
CurFnInfo->getRegParm() &&
383 CallFnInfo.isNoReturn() ==
CurFnInfo->isNoReturn() &&
384 CallFnInfo.getCallingConvention() ==
386 CallFnInfo.getX86ABIAVXLevel() ==
CurFnInfo->getX86ABIAVXLevel());
388 similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),
390 assert(CallFnInfo.arg_size() ==
CurFnInfo->arg_size());
391 for (
unsigned i = 0, e =
CurFnInfo->arg_size(); i != e; ++i)
392 assert(
similar(CallFnInfo.arg_begin()[i].info,
393 CallFnInfo.arg_begin()[i].type,
401 :
CGM.getCXXABI().hasMostDerivedReturn(
CurGD)
402 ?
CGM.getContext().VoidPtrTy
412 llvm::CallBase *CallOrInvoke;
414 CallArgs, &CallOrInvoke);
419 else if (llvm::CallInst*
Call = dyn_cast<llvm::CallInst>(CallOrInvoke))
420 Call->setTailCallKind(llvm::CallInst::TCK_Tail);
424 CGM.getCXXABI().EmitReturnFromThunk(*
this, RV, ResultType);
433 llvm::Value *AdjustedThisPtr,
434 llvm::FunctionCallee Callee) {
446 llvm::Type *ThisType = Args[ThisArgNo]->getType();
447 if (ThisType != AdjustedThisPtr->getType())
448 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
449 Args[ThisArgNo] = AdjustedThisPtr;
451 assert(ThisAI.
isInAlloca() &&
"this is passed directly or inalloca");
454 if (ThisType != AdjustedThisPtr->getType())
455 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
456 Builder.CreateStore(AdjustedThisPtr, ThisAddr);
461 llvm::CallInst *
Call =
Builder.CreateCall(Callee, Args);
462 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
466 llvm::AttributeList Attrs;
467 CGM.ConstructAttributeList(Callee.getCallee()->getName(), *
CurFnInfo, GD,
470 Call->setAttributes(Attrs);
473 if (
Call->getType()->isVoidTy())
488 bool IsUnprototyped) {
499 Ty =
CGM.getTypes().GetFunctionType(FnInfo);
501 llvm::Constant *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
505 &Thunk, IsUnprototyped);
509 bool IsUnprototyped,
bool ForVTable) {
526llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
534 SmallString<256> Name;
535 MangleContext &MCtx = CGM.getCXXABI().getMangleContext();
536 llvm::raw_svector_ostream
Out(Name);
538 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
544 if (CGM.getContext().useAbbreviatedThunkName(GD, Name.str())) {
546 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
553 llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
554 llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD);
557 bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible(
564 const CGFunctionInfo &FnInfo =
565 IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD)
566 : CGM.getTypes().arrangeGlobalDeclaration(GD);
567 llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo);
572 if (ThunkFn->getFunctionType() != ThunkFnTy) {
573 llvm::GlobalValue *OldThunkFn = ThunkFn;
575 assert(OldThunkFn->isDeclaration() &&
"Shouldn't replace non-declaration");
578 OldThunkFn->setName(StringRef());
579 ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
580 Name.str(), &CGM.getModule());
581 CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn,
false);
583 if (!OldThunkFn->use_empty()) {
584 OldThunkFn->replaceAllUsesWith(ThunkFn);
588 OldThunkFn->eraseFromParent();
591 bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions();
592 bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions;
594 if (!ThunkFn->isDeclaration()) {
595 if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) {
609 ThunkFn->addFnAttr(
"thunk");
611 CGM.SetLLVMFunctionAttributesForDefinition(GD.
getDecl(), ThunkFn);
618 bool ShouldCloneVarArgs =
false;
619 if (!IsUnprototyped && ThunkFn->isVarArg()) {
620 ShouldCloneVarArgs =
true;
622 switch (CGM.getTriple().getArch()) {
623 case llvm::Triple::x86_64:
624 case llvm::Triple::x86:
625 case llvm::Triple::aarch64:
626 ShouldCloneVarArgs =
false;
634 if (ShouldCloneVarArgs) {
635 if (UseAvailableExternallyLinkage)
638 CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI);
641 CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped);
657 VTContext->getThunkInfo(GD);
659 if (!ThunkInfoVector)
662 for (
const ThunkInfo& Thunk : *ThunkInfoVector)
663 maybeEmitThunk(GD, Thunk,
false);
667 llvm::Constant *component,
668 unsigned vtableAddressPoint,
669 bool vtableHasLocalLinkage,
670 bool isCompleteDtor)
const {
672 if (component->isNullValue())
673 return builder.
add(llvm::ConstantInt::get(CGM.
Int32Ty, 0));
690 auto stubLinkage = vtableHasLocalLinkage
691 ? llvm::GlobalValue::InternalLinkage
692 : llvm::GlobalValue::LinkOnceODRLinkage;
694 llvm::Constant *target;
695 if (
auto *func = dyn_cast<llvm::Function>(globalVal)) {
696 target = llvm::DSOLocalEquivalent::get(func);
699 rttiProxyName.append(
".rtti_proxy");
705 llvm::GlobalVariable *proxy =
module.getNamedGlobal(rttiProxyName);
707 proxy =
new llvm::GlobalVariable(module, globalVal->getType(),
709 globalVal, rttiProxyName);
710 proxy->setDSOLocal(
true);
711 proxy->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
712 if (!proxy->hasLocalLinkage()) {
713 proxy->setVisibility(llvm::GlobalValue::HiddenVisibility);
714 proxy->setComdat(module.getOrInsertComdat(rttiProxyName));
737 return CGM.getVTableComponentType();
743 builder.
add(llvm::ConstantExpr::getIntToPtr(
755 const VTableLayout &layout,
756 unsigned componentIndex,
757 llvm::Constant *rtti,
758 unsigned &nextVTableThunkIndex,
759 unsigned vtableAddressPoint,
760 bool vtableHasLocalLinkage) {
763 bool RelativeCXXABIVTables = CGM.getLangOpts().RelativeCXXABIVTables;
764 auto addOffsetConstant =
767 switch (component.getKind()) {
769 return addOffsetConstant(CGM, builder, component.getVCallOffset());
772 return addOffsetConstant(CGM, builder, component.getVBaseOffset());
775 return addOffsetConstant(CGM, builder, component.getOffsetToTop());
778 if (RelativeCXXABIVTables)
779 return addRelativeComponent(builder, rtti, vtableAddressPoint,
780 vtableHasLocalLinkage,
783 return builder.
add(rtti);
788 GlobalDecl GD = component.getGlobalDecl(
789 CGM.getContext().getTargetInfo().emitVectorDeletingDtors(
790 CGM.getContext().getLangOpts()));
794 layout.
vtable_thunks()[nextVTableThunkIndex].first == componentIndex;
796 if (CGM.getLangOpts().CUDA) {
804 CGM.getLangOpts().CUDAIsDevice
805 ? MD->
hasAttr<CUDADeviceAttr>()
806 : (MD->
hasAttr<CUDAHostAttr>() || !MD->
hasAttr<CUDADeviceAttr>());
807 if (!CanEmitMethod) {
809 nextVTableThunkIndex++;
811 llvm::ConstantExpr::getNullValue(CGM.GlobalsInt8PtrTy));
816 auto getSpecialVirtualFn = [&](StringRef
name) -> llvm::Constant * {
817 llvm::FunctionType *fnTy =
818 llvm::FunctionType::get(CGM.VoidTy,
false);
820 CGM.CreateRuntimeFunction(fnTy, name).getCallee());
821 F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
830 if (CGM.getLangOpts().isTargetDevice()) {
831 F->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
832 CodeGenFunction CGF(CGM);
833 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
834 CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI,
836 CGF.EmitTrapCallAndMakeUnreachable();
837 CGF.FinishFunction();
843 llvm::Constant *fnPtr;
849 getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName());
850 fnPtr = PureVirtualFn;
854 if (!DeletedVirtualFn)
856 getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName());
857 fnPtr = DeletedVirtualFn;
860 }
else if (IsThunk) {
861 auto &thunkInfo = layout.
vtable_thunks()[nextVTableThunkIndex].second;
863 nextVTableThunkIndex++;
864 fnPtr = maybeEmitThunk(GD, thunkInfo,
true);
865 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) {
866 assert(thunkInfo.Method &&
"Method not set");
872 llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
873 fnPtr = CGM.GetAddrOfFunction(GD, fnTy,
true);
874 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
878 if (RelativeCXXABIVTables) {
879 return addRelativeComponent(
880 builder, fnPtr, vtableAddressPoint, vtableHasLocalLinkage,
887 unsigned FnAS = fnPtr->getType()->getPointerAddressSpace();
888 unsigned GVAS = CGM.GlobalsInt8PtrTy->getPointerAddressSpace();
892 llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy);
893 if (
const auto &Schema =
894 CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
896 return builder.
add(fnPtr);
901 if (RelativeCXXABIVTables)
902 return builder.
add(llvm::ConstantExpr::getNullValue(CGM.Int32Ty));
907 llvm_unreachable(
"Unexpected vtable component kind");
913 for (
unsigned i = 0, e = layout.
getNumVTables(); i != e; ++i)
914 tys.push_back(llvm::ArrayType::get(componentType, layout.
getVTableSize(i)));
916 return llvm::StructType::get(CGM.getLLVMContext(), tys);
921 llvm::Constant *rtti,
922 bool vtableHasLocalLinkage) {
926 unsigned nextVTableThunkIndex = 0;
927 for (
unsigned vtableIndex = 0, endIndex = layout.
getNumVTables();
928 vtableIndex != endIndex; ++vtableIndex) {
929 auto vtableElem = builder.
beginArray(componentType);
932 size_t vtableEnd = vtableStart + layout.
getVTableSize(vtableIndex);
933 for (
size_t componentIndex = vtableStart; componentIndex < vtableEnd;
935 addVTableComponent(vtableElem, layout, componentIndex, rtti,
936 nextVTableThunkIndex, addressPoints[vtableIndex],
937 vtableHasLocalLinkage);
939 vtableElem.finishAndAddTo(builder);
945 llvm::GlobalVariable::LinkageTypes
Linkage,
946 VTableAddressPointsMapTy &AddressPoints) {
948 DI->completeClassData(
Base.getBase());
950 std::unique_ptr<VTableLayout> VTLayout(
952 Base.getBase(),
Base.getBaseOffset(), BaseIsVirtual, RD));
955 AddressPoints = VTLayout->getAddressPoints();
959 llvm::raw_svector_ostream Out(OutName);
961 .mangleCXXCtorVTable(RD,
Base.getBaseOffset().getQuantity(),
962 Base.getBase(), Out);
965 bool UsingRelativeLayout = CGM.getLangOpts().RelativeCXXABIVTables;
966 bool VTableAliasExists =
967 UsingRelativeLayout && CGM.getModule().getNamedAlias(Name);
968 if (VTableAliasExists) {
970 Name.append(
".local");
980 if (
Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
981 Linkage = llvm::GlobalVariable::InternalLinkage;
983 llvm::Align Align = CGM.getDataLayout().getABITypeAlign(VTType);
986 llvm::GlobalVariable *VTable =
987 CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType,
Linkage, Align);
994 if (!CGM.shouldEmitRTTI() || CGM.mayVTableBeDuplicated(VTable->getLinkage()))
995 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
997 llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
998 CGM.getContext().getCanonicalTagType(
Base.getBase()));
1004 VTable->hasLocalLinkage());
1005 components.finishAndSetAsInitializer(VTable);
1009 assert(!VTable->isDeclaration() &&
"Shouldn't set properties on declaration");
1010 CGM.setGVProperties(VTable, RD);
1012 CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout);
1014 if (UsingRelativeLayout) {
1016 if (!VTable->isDSOLocal())
1032 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::HWAddress)) {
1033 llvm::GlobalValue::SanitizerMetadata Meta;
1034 if (GV->hasSanitizerMetadata())
1035 Meta = GV->getSanitizerMetadata();
1036 Meta.NoHWAddress =
true;
1037 GV->setSanitizerMetadata(Meta);
1048 llvm::StringRef AliasNameRef) {
1049 assert(CGM.getLangOpts().RelativeCXXABIVTables &&
1050 "Can only use this if the relative vtable ABI is used");
1051 assert(!VTable->isDSOLocal() &&
"This should be called only if the vtable is "
1052 "not guaranteed to be dso_local");
1057 if (VTable->hasAvailableExternallyLinkage())
1064 VTable->setName(AliasName +
".local");
1066 auto Linkage = VTable->getLinkage();
1067 assert(llvm::GlobalAlias::isValidLinkage(
Linkage) &&
1068 "Invalid vtable alias linkage");
1070 llvm::GlobalAlias *VTableAlias = CGM.getModule().getNamedAlias(AliasName);
1072 VTableAlias = llvm::GlobalAlias::create(VTable->getValueType(),
1073 VTable->getAddressSpace(),
Linkage,
1074 AliasName, &CGM.getModule());
1076 assert(VTableAlias->getValueType() == VTable->getValueType());
1077 assert(VTableAlias->getLinkage() ==
Linkage);
1079 VTableAlias->setVisibility(VTable->getVisibility());
1080 VTableAlias->setUnnamedAddr(VTable->getUnnamedAddr());
1083 if (!VTable->hasComdat()) {
1084 VTable->setLinkage(llvm::GlobalValue::InternalLinkage);
1094 VTable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1097 VTableAlias->setAliasee(VTable);
1109llvm::GlobalVariable::LinkageTypes
1112 return llvm::GlobalVariable::InternalLinkage;
1121 IsInNamedModule ?
nullptr : Context.getCurrentKeyFunction(RD);
1122 if (IsInNamedModule || (keyFunction && !RD->
hasAttr<DLLImportAttr>())) {
1126 if (keyFunction && keyFunction->
hasBody(def))
1129 bool IsExternalDefinition =
1143 (IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
1144 CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo ||
1146 "Shouldn't query vtable linkage without the class in module units, "
1147 "key function, optimizations, or debug info");
1148 if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
1149 return llvm::GlobalVariable::AvailableExternallyLinkage;
1151 if (keyFunction && keyFunction->
isInlined())
1152 return !Context.getLangOpts().AppleKext
1153 ? llvm::GlobalVariable::LinkOnceODRLinkage
1154 : llvm::Function::InternalLinkage;
1156 return llvm::GlobalVariable::ExternalLinkage;
1159 return !Context.getLangOpts().AppleKext ?
1160 llvm::GlobalVariable::LinkOnceODRLinkage :
1161 llvm::Function::InternalLinkage;
1164 return !Context.getLangOpts().AppleKext ?
1165 llvm::GlobalVariable::WeakODRLinkage :
1166 llvm::Function::InternalLinkage;
1169 return IsExternalDefinition
1170 ? llvm::GlobalVariable::AvailableExternallyLinkage
1171 : llvm::GlobalVariable::ExternalLinkage;
1177 if (Context.getLangOpts().AppleKext)
1178 return llvm::Function::InternalLinkage;
1180 llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage =
1181 llvm::GlobalValue::LinkOnceODRLinkage;
1182 llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage =
1183 llvm::GlobalValue::WeakODRLinkage;
1184 if (RD->
hasAttr<DLLExportAttr>()) {
1186 DiscardableODRLinkage = NonDiscardableODRLinkage;
1187 }
else if (RD->
hasAttr<DLLImportAttr>()) {
1189 DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1190 NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1197 return DiscardableODRLinkage;
1203 return DiscardableODRLinkage;
1205 ? llvm::GlobalVariable::AvailableExternallyLinkage
1206 : llvm::GlobalVariable::ExternalLinkage;
1209 return NonDiscardableODRLinkage;
1212 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
1216 llvm::GlobalValue::LinkageTypes
Linkage)
const {
1219 llvm::GlobalValue::isWeakForLinker(
Linkage);
1229 VTables.GenerateClassData(theClass);
1230 EmittedVTables.insert(theClass);
1236 DI->completeClassData(RD);
1239 CGM.getCXXABI().emitVirtualInheritanceTables(RD);
1241 CGM.getCXXABI().emitVTableDefinitions(*
this, RD);
1255 assert(RD->
isDynamicClass() &&
"Non-dynamic classes have no VTable.");
1259 if (CGM.getTarget().getCXXABI().isMicrosoft())
1281 const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
1287 return !keyFunction->
hasBody();
1306void CodeGenModule::EmitDeferredVTables() {
1310 size_t savedSize = DeferredVTables.size();
1313 for (
const CXXRecordDecl *RD : DeferredVTables) {
1316 if (EmittedVTables.count(RD) &&
1321 VTables.GenerateClassData(RD);
1322 else if (shouldOpportunisticallyEmitVTables())
1323 OpportunisticVTables.push_back(RD);
1326 assert(savedSize == DeferredVTables.size() &&
1327 "deferred extra vtables during vtable emission?");
1328 DeferredVTables.clear();
1332 if (RD->
hasAttr<LTOVisibilityPublicAttr>() || RD->
hasAttr<UuidAttr>() ||
1344 if (
auto *ND = dyn_cast<NamespaceDecl>(D))
1346 if (II->isStr(
"std") || II->isStr(
"stdext"))
1368 const CXXRecordDecl *RD, llvm::DenseSet<const CXXRecordDecl *> &Visited) {
1374 if (!Visited.insert(RD).second)
1375 return llvm::GlobalObject::VCallVisibilityTranslationUnit;
1378 llvm::GlobalObject::VCallVisibility TypeVis;
1380 TypeVis = llvm::GlobalObject::VCallVisibilityTranslationUnit;
1382 TypeVis = llvm::GlobalObject::VCallVisibilityLinkageUnit;
1384 TypeVis = llvm::GlobalObject::VCallVisibilityPublic;
1386 for (
const auto &B : RD->
bases())
1387 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1392 for (
const auto &B : RD->
vbases())
1393 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1402 llvm::GlobalVariable *VTable,
1414 struct AddressPoint {
1418 bool operator<(
const AddressPoint &RHS)
const {
1419 int D =
TypeName.compare(RHS.TypeName);
1420 return D < 0 || (D == 0 && Offset < RHS.Offset);
1423 std::vector<AddressPoint> AddressPoints;
1425 AddressPoint N{AP.first.getBase(),
1427 AP.second.AddressPointIndex,
1429 llvm::raw_string_ostream Stream(N.TypeName);
1432 AddressPoints.push_back(std::move(N));
1436 llvm::sort(AddressPoints);
1439 for (
auto AP : AddressPoints) {
1447 for (
unsigned I = 0; I != Comps.size(); ++I) {
1451 Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(),
1452 std::nullopt, AP.Base));
1453 VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD);
1459 llvm::DenseSet<const CXXRecordDecl *> Visited;
1460 llvm::GlobalObject::VCallVisibility TypeVis =
1462 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1463 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.
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.
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
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.