aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp96
1 files changed, 20 insertions, 76 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp
index 65b3b0c5f53d..bef9a293b7ed 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGVTables.cpp
@@ -641,7 +641,7 @@ void CodeGenVTables::addRelativeComponent(ConstantArrayBuilder &builder,
llvm::Constant *target;
if (auto *func = dyn_cast<llvm::Function>(globalVal)) {
- target = getOrCreateRelativeStub(func, stubLinkage, isCompleteDtor);
+ target = llvm::DSOLocalEquivalent::get(func);
} else {
llvm::SmallString<16> rttiProxyName(globalVal->getName());
rttiProxyName.append(".rtti_proxy");
@@ -669,74 +669,6 @@ void CodeGenVTables::addRelativeComponent(ConstantArrayBuilder &builder,
/*position=*/vtableAddressPoint);
}
-llvm::Function *CodeGenVTables::getOrCreateRelativeStub(
- llvm::Function *func, llvm::GlobalValue::LinkageTypes stubLinkage,
- bool isCompleteDtor) const {
- // A complete object destructor can later be substituted in the vtable for an
- // appropriate base object destructor when optimizations are enabled. This can
- // happen for child classes that don't have their own destructor. In the case
- // where a parent virtual destructor is not guaranteed to be in the same
- // linkage unit as the child vtable, it's possible for an external reference
- // for this destructor to be substituted into the child vtable, preventing it
- // from being in rodata. If this function is a complete virtual destructor, we
- // can just force a stub to be emitted for it.
- if (func->isDSOLocal() && !isCompleteDtor)
- return func;
-
- llvm::SmallString<16> stubName(func->getName());
- stubName.append(".stub");
-
- // Instead of taking the offset between the vtable and virtual function
- // directly, we emit a dso_local stub that just contains a tail call to the
- // original virtual function and take the offset between that and the
- // vtable. We do this because there are some cases where the original
- // function that would've been inserted into the vtable is not dso_local
- // which may require some kind of dynamic relocation which prevents the
- // vtable from being readonly. On x86_64, taking the offset between the
- // function and the vtable gets lowered to the offset between the PLT entry
- // for the function and the vtable which gives us a PLT32 reloc. On AArch64,
- // right now only CALL26 and JUMP26 instructions generate PLT relocations,
- // so we manifest them with stubs that are just jumps to the original
- // function.
- auto &module = CGM.getModule();
- llvm::Function *stub = module.getFunction(stubName);
- if (stub) {
- assert(stub->isDSOLocal() &&
- "The previous definition of this stub should've been dso_local.");
- return stub;
- }
-
- stub = llvm::Function::Create(func->getFunctionType(), stubLinkage, stubName,
- module);
-
- // Propogate function attributes.
- stub->setAttributes(func->getAttributes());
-
- stub->setDSOLocal(true);
- stub->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- if (!stub->hasLocalLinkage()) {
- stub->setVisibility(llvm::GlobalValue::HiddenVisibility);
- stub->setComdat(module.getOrInsertComdat(stubName));
- }
-
- // Fill the stub with a tail call that will be optimized.
- llvm::BasicBlock *block =
- llvm::BasicBlock::Create(module.getContext(), "entry", stub);
- llvm::IRBuilder<> block_builder(block);
- llvm::SmallVector<llvm::Value *, 8> args;
- for (auto &arg : stub->args())
- args.push_back(&arg);
- llvm::CallInst *call = block_builder.CreateCall(func, args);
- call->setAttributes(func->getAttributes());
- call->setTailCall();
- if (call->getType()->isVoidTy())
- block_builder.CreateRetVoid();
- else
- block_builder.CreateRet(call);
-
- return stub;
-}
-
bool CodeGenVTables::useRelativeLayout() const {
return CGM.getTarget().getCXXABI().isItaniumFamily() &&
CGM.getItaniumVTableContext().isRelativeLayout();
@@ -1294,8 +1226,16 @@ bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
return !HasLTOVisibilityPublicStd(RD);
}
-llvm::GlobalObject::VCallVisibility
-CodeGenModule::GetVCallVisibilityLevel(const CXXRecordDecl *RD) {
+llvm::GlobalObject::VCallVisibility CodeGenModule::GetVCallVisibilityLevel(
+ const CXXRecordDecl *RD, llvm::DenseSet<const CXXRecordDecl *> &Visited) {
+ // If we have already visited this RD (which means this is a recursive call
+ // since the initial call should have an empty Visited set), return the max
+ // visibility. The recursive calls below compute the min between the result
+ // of the recursive call and the current TypeVis, so returning the max here
+ // ensures that it will have no effect on the current TypeVis.
+ if (!Visited.insert(RD).second)
+ return llvm::GlobalObject::VCallVisibilityTranslationUnit;
+
LinkageInfo LV = RD->getLinkageAndVisibility();
llvm::GlobalObject::VCallVisibility TypeVis;
if (!isExternallyVisible(LV.getLinkage()))
@@ -1307,13 +1247,15 @@ CodeGenModule::GetVCallVisibilityLevel(const CXXRecordDecl *RD) {
for (auto B : RD->bases())
if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
- TypeVis = std::min(TypeVis,
- GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl()));
+ TypeVis = std::min(
+ TypeVis,
+ GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl(), Visited));
for (auto B : RD->vbases())
if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
- TypeVis = std::min(TypeVis,
- GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl()));
+ TypeVis = std::min(
+ TypeVis,
+ GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl(), Visited));
return TypeVis;
}
@@ -1382,7 +1324,9 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD,
if (getCodeGenOpts().VirtualFunctionElimination ||
getCodeGenOpts().WholeProgramVTables) {
- llvm::GlobalObject::VCallVisibility TypeVis = GetVCallVisibilityLevel(RD);
+ llvm::DenseSet<const CXXRecordDecl *> Visited;
+ llvm::GlobalObject::VCallVisibility TypeVis =
+ GetVCallVisibilityLevel(RD, Visited);
if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
VTable->setVCallVisibilityMetadata(TypeVis);
}