23#include "llvm/IR/IntrinsicInst.h"
24#include "llvm/Transforms/Utils/Cloning.h"
33 : CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {}
37 return GetOrCreateLLVMFunction(Name, FnTy, GD,
true,
42 llvm::Function *ThunkFn,
bool ForVTable,
52 ThunkFn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
53 ThunkFn->setDSOLocal(
true);
57 ThunkFn->setComdat(CGM.
getModule().getOrInsertComdat(ThunkFn->getName()));
76 llvm::BasicBlock *AdjustNull =
nullptr;
77 llvm::BasicBlock *AdjustNotNull =
nullptr;
78 llvm::BasicBlock *AdjustEnd =
nullptr;
100 if (NullCheckValue) {
101 CGF.
Builder.CreateBr(AdjustEnd);
103 CGF.
Builder.CreateBr(AdjustEnd);
106 llvm::PHINode *PHI = CGF.
Builder.CreatePHI(ReturnValue->getType(), 2);
107 PHI->addIncoming(ReturnValue, AdjustNotNull);
108 PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()),
122 llvm::ValueToValueMapTy &VMap) {
124 auto *DIS = Fn->getSubprogram();
127 auto *NewDIS = llvm::MDNode::replaceWithDistinct(DIS->clone());
132 NewDIS->replaceRetainedNodes(llvm::MDTuple::get(Fn->getContext(), {}));
133 VMap.MD()[DIS].reset(NewDIS);
137 for (
auto &BB : *Fn) {
139 for (llvm::DbgVariableRecord &DVR :
140 llvm::filterDbgVars(I.getDbgRecordRange())) {
141 auto *DILocal = DVR.getVariable();
142 if (!DILocal->isResolved())
145 if (
auto *DII = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) {
146 auto *DILocal = DII->getVariable();
147 if (!DILocal->isResolved())
180 llvm::Type *Ty =
CGM.getTypes().GetFunctionType(FnInfo);
181 llvm::Value *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
188 CGM.ErrorUnsupported(MD,
"return-adjusting thunk with variadic arguments");
191 assert(!BaseFn->isDeclaration() &&
"cannot clone undefined variadic method");
194 llvm::ValueToValueMapTy VMap;
199 llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
200 Fn->replaceAllUsesWith(NewFn);
202 Fn->eraseFromParent();
209 llvm::Function::arg_iterator AI = Fn->arg_begin();
210 if (
CGM.ReturnTypeUsesSRet(FnInfo))
218 llvm::BasicBlock *EntryBB = &Fn->front();
219 llvm::BasicBlock::iterator ThisStore =
220 llvm::find_if(*EntryBB, [&](llvm::Instruction &I) {
223 assert(ThisStore != EntryBB->end() &&
224 "Store of this should be in entry block?");
226 Builder.SetInsertPoint(&*ThisStore);
229 llvm::Value *AdjustedThisPtr =
CGM.getCXXABI().performThisAdjustment(
230 *
this, ThisPtr, ThisValueClass, Thunk);
231 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr,
232 ThisStore->getOperand(0)->getType());
233 ThisStore->setOperand(0, AdjustedThisPtr);
237 for (llvm::BasicBlock &BB : *Fn) {
238 llvm::Instruction *
T = BB.getTerminator();
241 T->eraseFromParent();
255 bool IsUnprototyped) {
256 assert(!
CurGD.getDecl() &&
"CurGD was already set!");
265 ResultType =
CGM.getContext().VoidTy;
266 else if (
CGM.getCXXABI().HasThisReturn(GD))
267 ResultType = ThisType;
268 else if (
CGM.getCXXABI().hasMostDerivedReturn(GD))
269 ResultType =
CGM.getContext().VoidPtrTy;
275 CGM.getCXXABI().buildThisParam(*
this, FunctionArgs);
278 if (!IsUnprototyped) {
282 CGM.getCXXABI().addImplicitStructorParams(*
this, ResultType,
294 CGM.getCXXABI().EmitInstanceFunctionProlog(*
this);
295 CXXThisValue = CXXABIThisValue;
311 bool IsUnprototyped) {
313 "Please use a new CGF for this thunk");
322 llvm::Value *AdjustedThisPtr =
324 ThisValueClass, *Thunk)
333 CGM.ErrorUnsupported(
334 MD,
"return-adjusting thunk with incomplete parameter type");
336 llvm_unreachable(
"shouldn't try to emit musttail return-adjusting "
337 "thunks for variadic functions");
339 CGM.ErrorUnsupported(
340 MD,
"non-trivial argument copy for return-adjusting thunk");
352 CGM.getCXXABI().adjustCallArgsForDestructorThunk(*
this,
CurGD, CallArgs);
355 unsigned PrefixArgs = CallArgs.size() - 1;
366 assert(CallFnInfo.getRegParm() ==
CurFnInfo->getRegParm() &&
367 CallFnInfo.isNoReturn() ==
CurFnInfo->isNoReturn() &&
368 CallFnInfo.getCallingConvention() ==
CurFnInfo->getCallingConvention());
370 similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(),
372 assert(CallFnInfo.arg_size() ==
CurFnInfo->arg_size());
373 for (
unsigned i = 0, e =
CurFnInfo->arg_size(); i != e; ++i)
374 assert(
similar(CallFnInfo.arg_begin()[i].info,
375 CallFnInfo.arg_begin()[i].type,
383 :
CGM.getCXXABI().hasMostDerivedReturn(
CurGD)
384 ?
CGM.getContext().VoidPtrTy
394 llvm::CallBase *CallOrInvoke;
396 CallArgs, &CallOrInvoke);
401 else if (llvm::CallInst*
Call = dyn_cast<llvm::CallInst>(CallOrInvoke))
402 Call->setTailCallKind(llvm::CallInst::TCK_Tail);
406 CGM.getCXXABI().EmitReturnFromThunk(*
this, RV, ResultType);
415 llvm::Value *AdjustedThisPtr,
416 llvm::FunctionCallee Callee) {
428 llvm::Type *ThisType = Args[ThisArgNo]->getType();
429 if (ThisType != AdjustedThisPtr->getType())
430 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
431 Args[ThisArgNo] = AdjustedThisPtr;
433 assert(ThisAI.
isInAlloca() &&
"this is passed directly or inalloca");
436 if (ThisType != AdjustedThisPtr->getType())
437 AdjustedThisPtr =
Builder.CreateBitCast(AdjustedThisPtr, ThisType);
438 Builder.CreateStore(AdjustedThisPtr, ThisAddr);
443 llvm::CallInst *
Call =
Builder.CreateCall(Callee, Args);
444 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
448 llvm::AttributeList Attrs;
449 CGM.ConstructAttributeList(Callee.getCallee()->getName(), *
CurFnInfo, GD,
452 Call->setAttributes(Attrs);
455 if (
Call->getType()->isVoidTy())
470 bool IsUnprototyped) {
481 Ty =
CGM.getTypes().GetFunctionType(FnInfo);
483 llvm::Constant *Callee =
CGM.GetAddrOfFunction(GD, Ty,
true);
487 &Thunk, IsUnprototyped);
491 bool IsUnprototyped,
bool ForVTable) {
508llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
516 SmallString<256> Name;
517 MangleContext &MCtx = CGM.getCXXABI().getMangleContext();
518 llvm::raw_svector_ostream
Out(Name);
520 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
526 if (CGM.getContext().useAbbreviatedThunkName(GD, Name.str())) {
528 if (
const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD))
535 llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
536 llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD);
539 bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible(
546 const CGFunctionInfo &FnInfo =
547 IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD)
548 : CGM.getTypes().arrangeGlobalDeclaration(GD);
549 llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo);
554 if (ThunkFn->getFunctionType() != ThunkFnTy) {
555 llvm::GlobalValue *OldThunkFn = ThunkFn;
557 assert(OldThunkFn->isDeclaration() &&
"Shouldn't replace non-declaration");
560 OldThunkFn->setName(StringRef());
561 ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
562 Name.str(), &CGM.getModule());
563 CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn,
false);
565 if (!OldThunkFn->use_empty()) {
566 OldThunkFn->replaceAllUsesWith(ThunkFn);
570 OldThunkFn->eraseFromParent();
573 bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions();
574 bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions;
576 if (!ThunkFn->isDeclaration()) {
577 if (!ABIHasKeyFunctions || UseAvailableExternallyLinkage) {
591 ThunkFn->addFnAttr(
"thunk");
593 CGM.SetLLVMFunctionAttributesForDefinition(GD.
getDecl(), ThunkFn);
600 bool ShouldCloneVarArgs =
false;
601 if (!IsUnprototyped && ThunkFn->isVarArg()) {
602 ShouldCloneVarArgs =
true;
604 switch (CGM.getTriple().getArch()) {
605 case llvm::Triple::x86_64:
606 case llvm::Triple::x86:
607 case llvm::Triple::aarch64:
608 ShouldCloneVarArgs =
false;
616 if (ShouldCloneVarArgs) {
617 if (UseAvailableExternallyLinkage)
620 CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI);
623 CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped);
639 VTContext->getThunkInfo(GD);
641 if (!ThunkInfoVector)
644 for (
const ThunkInfo& Thunk : *ThunkInfoVector)
645 maybeEmitThunk(GD, Thunk,
false);
649 llvm::Constant *component,
650 unsigned vtableAddressPoint,
651 bool vtableHasLocalLinkage,
652 bool isCompleteDtor)
const {
654 if (component->isNullValue())
655 return builder.
add(llvm::ConstantInt::get(CGM.
Int32Ty, 0));
672 auto stubLinkage = vtableHasLocalLinkage
673 ? llvm::GlobalValue::InternalLinkage
674 : llvm::GlobalValue::LinkOnceODRLinkage;
676 llvm::Constant *target;
677 if (
auto *func = dyn_cast<llvm::Function>(globalVal)) {
678 target = llvm::DSOLocalEquivalent::get(func);
681 rttiProxyName.append(
".rtti_proxy");
687 llvm::GlobalVariable *proxy =
module.getNamedGlobal(rttiProxyName);
689 proxy =
new llvm::GlobalVariable(module, globalVal->getType(),
691 globalVal, rttiProxyName);
692 proxy->setDSOLocal(
true);
693 proxy->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
694 if (!proxy->hasLocalLinkage()) {
695 proxy->setVisibility(llvm::GlobalValue::HiddenVisibility);
696 proxy->setComdat(module.getOrInsertComdat(rttiProxyName));
728 return CGM.getVTableComponentType();
734 builder.
add(llvm::ConstantExpr::getIntToPtr(
746 const VTableLayout &layout,
747 unsigned componentIndex,
748 llvm::Constant *rtti,
749 unsigned &nextVTableThunkIndex,
750 unsigned vtableAddressPoint,
751 bool vtableHasLocalLinkage) {
754 auto addOffsetConstant =
757 switch (component.getKind()) {
759 return addOffsetConstant(CGM, builder, component.getVCallOffset());
762 return addOffsetConstant(CGM, builder, component.getVBaseOffset());
765 return addOffsetConstant(CGM, builder, component.getOffsetToTop());
769 return addRelativeComponent(builder, rtti, vtableAddressPoint,
770 vtableHasLocalLinkage,
773 return builder.
add(rtti);
778 GlobalDecl GD = component.getGlobalDecl();
782 layout.
vtable_thunks()[nextVTableThunkIndex].first == componentIndex;
784 if (CGM.getLangOpts().CUDA) {
792 CGM.getLangOpts().CUDAIsDevice
793 ? MD->
hasAttr<CUDADeviceAttr>()
794 : (MD->
hasAttr<CUDAHostAttr>() || !MD->
hasAttr<CUDADeviceAttr>());
795 if (!CanEmitMethod) {
797 nextVTableThunkIndex++;
799 llvm::ConstantExpr::getNullValue(CGM.GlobalsInt8PtrTy));
804 auto getSpecialVirtualFn = [&](StringRef
name) -> llvm::Constant * {
813 return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
817 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPIsTargetDevice &&
818 CGM.getTriple().isNVPTX())
819 return llvm::ConstantPointerNull::get(CGM.GlobalsInt8PtrTy);
820 llvm::FunctionType *fnTy =
821 llvm::FunctionType::get(CGM.VoidTy,
false);
823 CGM.CreateRuntimeFunction(fnTy, name).getCallee());
824 if (
auto f = dyn_cast<llvm::Function>(fn))
825 f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
829 llvm::Constant *fnPtr;
835 getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName());
836 fnPtr = PureVirtualFn;
840 if (!DeletedVirtualFn)
842 getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName());
843 fnPtr = DeletedVirtualFn;
846 }
else if (IsThunk) {
847 auto &thunkInfo = layout.
vtable_thunks()[nextVTableThunkIndex].second;
849 nextVTableThunkIndex++;
850 fnPtr = maybeEmitThunk(GD, thunkInfo,
true);
851 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) {
852 assert(thunkInfo.Method &&
"Method not set");
858 llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
859 fnPtr = CGM.GetAddrOfFunction(GD, fnTy,
true);
860 if (CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
865 return addRelativeComponent(
866 builder, fnPtr, vtableAddressPoint, vtableHasLocalLinkage,
873 unsigned FnAS = fnPtr->getType()->getPointerAddressSpace();
874 unsigned GVAS = CGM.GlobalsInt8PtrTy->getPointerAddressSpace();
878 llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy);
879 if (
const auto &Schema =
880 CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers)
882 return builder.
add(fnPtr);
888 return builder.
add(llvm::ConstantExpr::getNullValue(CGM.Int32Ty));
893 llvm_unreachable(
"Unexpected vtable component kind");
899 for (
unsigned i = 0, e = layout.
getNumVTables(); i != e; ++i)
900 tys.push_back(llvm::ArrayType::get(componentType, layout.
getVTableSize(i)));
902 return llvm::StructType::get(CGM.getLLVMContext(), tys);
907 llvm::Constant *rtti,
908 bool vtableHasLocalLinkage) {
912 unsigned nextVTableThunkIndex = 0;
913 for (
unsigned vtableIndex = 0, endIndex = layout.
getNumVTables();
914 vtableIndex != endIndex; ++vtableIndex) {
915 auto vtableElem = builder.
beginArray(componentType);
918 size_t vtableEnd = vtableStart + layout.
getVTableSize(vtableIndex);
919 for (
size_t componentIndex = vtableStart; componentIndex < vtableEnd;
921 addVTableComponent(vtableElem, layout, componentIndex, rtti,
922 nextVTableThunkIndex, addressPoints[vtableIndex],
923 vtableHasLocalLinkage);
925 vtableElem.finishAndAddTo(builder);
931 llvm::GlobalVariable::LinkageTypes
Linkage,
932 VTableAddressPointsMapTy &AddressPoints) {
934 DI->completeClassData(
Base.getBase());
936 std::unique_ptr<VTableLayout> VTLayout(
938 Base.getBase(),
Base.getBaseOffset(), BaseIsVirtual, RD));
941 AddressPoints = VTLayout->getAddressPoints();
945 llvm::raw_svector_ostream Out(OutName);
947 .mangleCXXCtorVTable(RD,
Base.getBaseOffset().getQuantity(),
948 Base.getBase(), Out);
952 bool VTableAliasExists =
953 UsingRelativeLayout && CGM.getModule().getNamedAlias(Name);
954 if (VTableAliasExists) {
956 Name.append(
".local");
966 if (
Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
967 Linkage = llvm::GlobalVariable::InternalLinkage;
969 llvm::Align Align = CGM.getDataLayout().getABITypeAlign(VTType);
972 llvm::GlobalVariable *VTable =
973 CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType,
Linkage, Align);
976 VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
978 llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor(
979 CGM.getContext().getCanonicalTagType(
Base.getBase()));
985 VTable->hasLocalLinkage());
986 components.finishAndSetAsInitializer(VTable);
990 assert(!VTable->isDeclaration() &&
"Shouldn't set properties on declaration");
991 CGM.setGVProperties(VTable, RD);
993 CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout);
995 if (UsingRelativeLayout) {
997 if (!VTable->isDSOLocal())
1013 if (CGM.getLangOpts().Sanitize.has(SanitizerKind::HWAddress)) {
1014 llvm::GlobalValue::SanitizerMetadata Meta;
1015 if (GV->hasSanitizerMetadata())
1016 Meta = GV->getSanitizerMetadata();
1017 Meta.NoHWAddress =
true;
1018 GV->setSanitizerMetadata(Meta);
1029 llvm::StringRef AliasNameRef) {
1031 "Can only use this if the relative vtable ABI is used");
1032 assert(!VTable->isDSOLocal() &&
"This should be called only if the vtable is "
1033 "not guaranteed to be dso_local");
1038 if (VTable->hasAvailableExternallyLinkage())
1045 VTable->setName(AliasName +
".local");
1047 auto Linkage = VTable->getLinkage();
1048 assert(llvm::GlobalAlias::isValidLinkage(
Linkage) &&
1049 "Invalid vtable alias linkage");
1051 llvm::GlobalAlias *VTableAlias = CGM.getModule().getNamedAlias(AliasName);
1053 VTableAlias = llvm::GlobalAlias::create(VTable->getValueType(),
1054 VTable->getAddressSpace(),
Linkage,
1055 AliasName, &CGM.getModule());
1057 assert(VTableAlias->getValueType() == VTable->getValueType());
1058 assert(VTableAlias->getLinkage() ==
Linkage);
1060 VTableAlias->setVisibility(VTable->getVisibility());
1061 VTableAlias->setUnnamedAddr(VTable->getUnnamedAddr());
1064 if (!VTable->hasComdat()) {
1065 VTable->setLinkage(llvm::GlobalValue::InternalLinkage);
1075 VTable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1078 VTableAlias->setAliasee(VTable);
1090llvm::GlobalVariable::LinkageTypes
1093 return llvm::GlobalVariable::InternalLinkage;
1102 IsInNamedModule ?
nullptr : Context.getCurrentKeyFunction(RD);
1103 if (IsInNamedModule || (keyFunction && !RD->
hasAttr<DLLImportAttr>())) {
1107 if (keyFunction && keyFunction->
hasBody(def))
1110 bool IsExternalDefinition =
1121 (IsInNamedModule || def || CodeGenOpts.OptimizationLevel > 0 ||
1122 CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) &&
1123 "Shouldn't query vtable linkage without the class in module units, "
1124 "key function, optimizations, or debug info");
1125 if (IsExternalDefinition && CodeGenOpts.OptimizationLevel > 0)
1126 return llvm::GlobalVariable::AvailableExternallyLinkage;
1128 if (keyFunction && keyFunction->
isInlined())
1129 return !Context.getLangOpts().AppleKext
1130 ? llvm::GlobalVariable::LinkOnceODRLinkage
1131 : llvm::Function::InternalLinkage;
1133 return llvm::GlobalVariable::ExternalLinkage;
1136 return !Context.getLangOpts().AppleKext ?
1137 llvm::GlobalVariable::LinkOnceODRLinkage :
1138 llvm::Function::InternalLinkage;
1141 return !Context.getLangOpts().AppleKext ?
1142 llvm::GlobalVariable::WeakODRLinkage :
1143 llvm::Function::InternalLinkage;
1146 return IsExternalDefinition
1147 ? llvm::GlobalVariable::AvailableExternallyLinkage
1148 : llvm::GlobalVariable::ExternalLinkage;
1154 if (Context.getLangOpts().AppleKext)
1155 return llvm::Function::InternalLinkage;
1157 llvm::GlobalVariable::LinkageTypes DiscardableODRLinkage =
1158 llvm::GlobalValue::LinkOnceODRLinkage;
1159 llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage =
1160 llvm::GlobalValue::WeakODRLinkage;
1161 if (RD->
hasAttr<DLLExportAttr>()) {
1163 DiscardableODRLinkage = NonDiscardableODRLinkage;
1164 }
else if (RD->
hasAttr<DLLImportAttr>()) {
1166 DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1167 NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
1174 return DiscardableODRLinkage;
1180 return DiscardableODRLinkage;
1182 ? llvm::GlobalVariable::AvailableExternallyLinkage
1183 : llvm::GlobalVariable::ExternalLinkage;
1186 return NonDiscardableODRLinkage;
1189 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
1199 VTables.GenerateClassData(theClass);
1205 DI->completeClassData(RD);
1208 CGM.getCXXABI().emitVirtualInheritanceTables(RD);
1210 CGM.getCXXABI().emitVTableDefinitions(*
this, RD);
1224 assert(RD->
isDynamicClass() &&
"Non-dynamic classes have no VTable.");
1228 if (CGM.getTarget().getCXXABI().isMicrosoft())
1250 const CXXMethodDecl *keyFunction = CGM.getContext().getCurrentKeyFunction(RD);
1256 return !keyFunction->
hasBody();
1275void CodeGenModule::EmitDeferredVTables() {
1279 size_t savedSize = DeferredVTables.size();
1282 for (
const CXXRecordDecl *RD : DeferredVTables)
1284 VTables.GenerateClassData(RD);
1285 else if (shouldOpportunisticallyEmitVTables())
1286 OpportunisticVTables.push_back(RD);
1288 assert(savedSize == DeferredVTables.size() &&
1289 "deferred extra vtables during vtable emission?");
1290 DeferredVTables.clear();
1294 if (RD->
hasAttr<LTOVisibilityPublicAttr>() || RD->
hasAttr<UuidAttr>() ||
1306 if (
auto *ND = dyn_cast<NamespaceDecl>(D))
1308 if (II->isStr(
"std") || II->isStr(
"stdext"))
1330 const CXXRecordDecl *RD, llvm::DenseSet<const CXXRecordDecl *> &Visited) {
1336 if (!Visited.insert(RD).second)
1337 return llvm::GlobalObject::VCallVisibilityTranslationUnit;
1340 llvm::GlobalObject::VCallVisibility TypeVis;
1342 TypeVis = llvm::GlobalObject::VCallVisibilityTranslationUnit;
1344 TypeVis = llvm::GlobalObject::VCallVisibilityLinkageUnit;
1346 TypeVis = llvm::GlobalObject::VCallVisibilityPublic;
1348 for (
const auto &B : RD->
bases())
1349 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1354 for (
const auto &B : RD->
vbases())
1355 if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
1364 llvm::GlobalVariable *VTable,
1376 struct AddressPoint {
1380 bool operator<(
const AddressPoint &RHS)
const {
1381 int D =
TypeName.compare(RHS.TypeName);
1382 return D < 0 || (D == 0 && Offset < RHS.Offset);
1385 std::vector<AddressPoint> AddressPoints;
1387 AddressPoint N{AP.first.getBase(),
1389 AP.second.AddressPointIndex,
1391 llvm::raw_string_ostream Stream(N.TypeName);
1394 AddressPoints.push_back(std::move(N));
1398 llvm::sort(AddressPoints);
1401 for (
auto AP : AddressPoints) {
1409 for (
unsigned I = 0; I != Comps.size(); ++I) {
1413 Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(),
1414 std::nullopt, AP.Base));
1415 VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD);
1421 llvm::DenseSet<const CXXRecordDecl *> Visited;
1422 llvm::GlobalObject::VCallVisibility TypeVis =
1424 if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
1425 VTable->setVCallVisibilityMetadata(TypeVis);
static RValue PerformReturnAdjustment(CodeGenFunction &CGF, QualType ResultType, RValue RV, const ThunkInfo &Thunk)
static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk, llvm::Function *ThunkFn, bool ForVTable, GlobalDecl GD)
static bool shouldEmitVTableThunk(CodeGenModule &CGM, const CXXMethodDecl *MD, bool IsUnprototyped, bool ForVTable)
static void resolveTopLevelMetadata(llvm::Function *Fn, llvm::ValueToValueMapTy &VMap)
This function clones a function's DISubprogram node and enters it into a value map with the intent th...
static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM, const CXXRecordDecl *RD)
static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM, const CXXRecordDecl *RD)
Given that we're currently at the end of the translation unit, and we've emitted a reference to the v...
static void AddRelativeLayoutOffset(const CodeGenModule &CGM, ConstantArrayBuilder &builder, CharUnits offset)
static void AddPointerLayoutOffset(const CodeGenModule &CGM, ConstantArrayBuilder &builder, CharUnits offset)
static bool similar(const ABIArgInfo &infoL, CanQualType typeL, const ABIArgInfo &infoR, CanQualType typeR)
static bool UseRelativeLayout(const CodeGenModule &CGM)
static Decl::Kind getKind(const Decl *D)
static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr)
CanQualType getCanonicalTagType(const TagDecl *TD) const
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getThisType() const
Return the type of the this pointer.
QualType getFunctionObjectParameterType() const
Represents a C++ struct/union/class.
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
base_class_range vbases()
bool isDynamicClass() const
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
bool isSRetAfterThis() const
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const =0
Determine whether it's possible to emit a vtable for RD, even though we do not know that the vtable h...
virtual llvm::Value * performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const CXXRecordDecl *UnadjustedClass, const ReturnAdjustment &RA)=0
virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, bool ReturnAdjustment)=0
virtual bool exportThunk()=0
MangleContext & getMangleContext()
Gets the mangle context.
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
CGFunctionInfo - Class to encapsulate the information about a function definition.
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
GlobalDecl CurGD
CurGD - The GlobalDecl for the current function being compiled.
void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr, llvm::FunctionCallee Callee)
Emit a musttail call for a thunk with a potentially adjusted this pointer.
Address LoadCXXThisAddress()
bool CurFuncIsThunk
In C++, whether we are code generating a thunk.
void EmitDelegateCallArg(CallArgList &args, const VarDecl *param, SourceLocation loc)
EmitDelegateCallArg - We are performing a delegate call; that is, the current function is delegating ...
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
Address makeNaturalAddressForPointer(llvm::Value *Ptr, QualType T, CharUnits Alignment=CharUnits::Zero(), bool ForPointeeType=false, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
Construct an address with the natural alignment of T.
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
void EmitCallAndReturnForThunk(llvm::FunctionCallee Callee, const ThunkInfo *Thunk, bool IsUnprototyped)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
llvm::Function * GenerateVarArgsThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, GlobalDecl GD, const ThunkInfo &Thunk)
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
bool AutoreleaseResult
In ARC, whether we should autorelease the return value.
llvm::Type * ConvertTypeForMem(QualType T)
void generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, GlobalDecl GD, const ThunkInfo &Thunk, bool IsUnprototyped)
Generate a thunk for the given method.
void StartThunk(llvm::Function *Fn, GlobalDecl GD, const CGFunctionInfo &FnInfo, bool IsUnprototyped)
static bool hasAggregateEvaluationKind(QualType T)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::Value * LoadCXXThis()
LoadCXXThis - Load the value of 'this'.
const CGFunctionInfo * CurFnInfo
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::LLVMContext & getLLVMContext()
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const
Set visibility, dllimport/dllexport and dso_local.
void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD)
Create and attach type metadata for the given vtable.
llvm::GlobalObject::VCallVisibility GetVCallVisibilityLevel(const CXXRecordDecl *RD, llvm::DenseSet< const CXXRecordDecl * > &Visited)
Returns the vcall visibility of the given type.
llvm::Module & getModule() const
CodeGenVTables & getVTables()
CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const
Return the store size, in character units, of the given LLVM type.
const TargetInfo & getTarget() const
void EmitVTableTypeMetadata(const CXXRecordDecl *RD, llvm::GlobalVariable *VTable, const VTableLayout &VTLayout)
Emit type metadata for the given vtable using the given layout.
bool HasHiddenLTOVisibility(const CXXRecordDecl *RD)
Returns whether the given record has hidden LTO visibility and therefore may participate in (single-m...
CGCXXABI & getCXXABI() const
CharUnits getClassPointerAlignment(const CXXRecordDecl *CD)
Returns the assumed alignment of an opaque pointer to the given class.
const llvm::Triple & getTriple() const
bool AlwaysHasLTOVisibilityPublic(const CXXRecordDecl *RD)
Returns whether the given record has public LTO visibility (regardless of -lto-whole-program-visibili...
void EmitVTable(CXXRecordDecl *Class)
This is a callback from Sema to tell us that a particular vtable is required to be emitted in this tr...
void setFunctionLinkage(GlobalDecl GD, llvm::Function *F)
ItaniumVTableContext & getItaniumVTableContext()
ASTContext & getContext() const
llvm::Type * getVTableComponentType() const
bool supportsCOMDAT() const
const CodeGenOptions & getCodeGenOpts() const
llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD)
Return the appropriate linkage for the vtable, VTT, and type information of the given class.
llvm::Metadata * CreateMetadataIdentifierForVirtualMemPtrType(QualType T)
Create a metadata identifier that is intended to be used to check virtual calls via a member function...
llvm::Constant * GetAddrOfThunk(StringRef Name, llvm::Type *FnTy, GlobalDecl GD)
Get the address of the thunk for the given global decl.
void createVTableInitializer(ConstantStructBuilder &builder, const VTableLayout &layout, llvm::Constant *rtti, bool vtableHasLocalLinkage)
Add vtable components for the given vtable layout to the given global initializer.
void GenerateClassData(const CXXRecordDecl *RD)
GenerateClassData - Generate all the class data required to be generated upon definition of a KeyFunc...
void GenerateRelativeVTableAlias(llvm::GlobalVariable *VTable, llvm::StringRef AliasNameRef)
Generate a public facing alias for the vtable and make the vtable either hidden or private.
ItaniumVTableContext & getItaniumVTableContext()
CodeGenVTables(CodeGenModule &CGM)
llvm::GlobalVariable * GenerateConstructionVTable(const CXXRecordDecl *RD, const BaseSubobject &Base, bool BaseIsVirtual, llvm::GlobalVariable::LinkageTypes Linkage, VTableAddressPointsMapTy &AddressPoints)
GenerateConstructionVTable - Generate a construction vtable for the given base subobject.
llvm::Type * getVTableType(const VTableLayout &layout)
Returns the type of a vtable with the given layout.
bool useRelativeLayout() const
Return true if the relative vtable layout is used.
llvm::Type * getVTableComponentType() const
Return the type used as components for a vtable.
bool isVTableExternal(const CXXRecordDecl *RD)
At this point in the translation unit, does it appear that can we rely on the vtable being defined el...
void RemoveHwasanMetadata(llvm::GlobalValue *GV) const
Specify a global should not be instrumented with hwasan.
void EmitThunks(GlobalDecl GD)
EmitThunks - Emit the associated thunks for the given global decl.
void addRelativeOffsetToPosition(llvm::IntegerType *type, llvm::Constant *target, size_t position)
Same as addRelativeOffset(), but instead relative to an element in this aggregate,...
void add(llvm::Constant *value)
Add a new value to this initializer.
void addNullPointer(llvm::PointerType *ptrTy)
Add a null pointer of a specific type.
void addSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, GlobalDecl CalleeDecl, QualType CalleeType)
Add a signed pointer using the given pointer authentication schema.
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
A helper class of ConstantInitBuilder, used for building constant array initializers.
StructBuilder beginStruct(llvm::StructType *structTy=nullptr)
The standard implementation of ConstantInitBuilder used in Clang.
A helper class of ConstantInitBuilder, used for building constant struct initializers.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
bool isInNamedModule() const
Whether this declaration comes from a named module.
SourceLocation getLocation() const
bool shouldEmitInExternalSource() const
Whether the definition of the declaration should be emitted in external sources.
Represents a function declaration or definition.
param_iterator param_end()
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
ArrayRef< ParmVarDecl * > parameters() const
param_iterator param_begin()
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine what kind of template instantiation this function represents.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Represents a prototype with parameter type info, e.g.
QualType getReturnType() const
GlobalDecl - represents a global declaration.
GlobalDecl getWithDecl(const Decl *D)
CXXDtorType getDtorType() const
const Decl * getDecl() const
One of these records is kept for each identifier that is lexed.
bool isRelativeLayout() const
GlobalDecl findOriginalMethod(GlobalDecl GD)
Return the method that added the v-table slot that will be used to call the given method.
Visibility getVisibility() const
Linkage getLinkage() const
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, const ThunkInfo &Thunk, bool ElideOverrideInfo, raw_ostream &)=0
virtual void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, bool ElideOverrideInfo, raw_ostream &)=0
virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
Generates a unique string for an externally visible type for use with TBAA or type uniquing.
LinkageInfo getLinkageAndVisibility() const
Determines the linkage and visibility of this entity.
bool isExternallyVisible() const
Represents a parameter to a function.
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Encodes a location in the source.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
bool isItaniumFamily() const
Does this ABI generally fall into the Itanium family of ABIs?
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
@ CK_DeletingDtorPointer
A pointer to the deleting destructor.
@ CK_UnusedFunctionPointer
An entry that is never used.
@ CK_CompleteDtorPointer
A pointer to the complete destructor.
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
const AddressPointsIndexMapTy & getAddressPointIndices() const
size_t getVTableOffset(size_t i) const
ArrayRef< VTableComponent > vtable_components() const
size_t getNumVTables() const
ArrayRef< VTableThunkTy > vtable_thunks() const
const AddressPointsMapTy & getAddressPoints() const
size_t getVTableSize(size_t i) const
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
const FunctionProtoType * T
@ Dtor_Base
Base object dtor.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
@ TSK_ExplicitSpecialization
This template specialization was declared or defined by an explicit specialization (C++ [temp....
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
@ TSK_Undeclared
This template specialization was formed from a template-id but has not yet been declared,...
CallingConv
CallingConv - Specifies the calling convention that a function uses.
U cast(CodeGen::Address addr)
bool isExternallyVisible(Linkage L)
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
llvm::PointerType * GlobalsInt8PtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * PtrDiffTy
The this pointer adjustment as well as an optional return adjustment for a thunk.
ReturnAdjustment Return
The return adjustment.