diff options
Diffstat (limited to 'llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp')
| -rw-r--r-- | llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index f0cf5581ba8..d7c75049404 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -841,17 +841,35 @@ bool DevirtIndex::tryFindVirtualCallTargets( std::vector<ValueInfo> &TargetsForSlot, const TypeIdCompatibleVtableInfo TIdInfo, uint64_t ByteOffset) { for (const TypeIdOffsetVtableInfo P : TIdInfo) { - // VTable initializer should have only one summary, or all copies must be - // linkonce/weak ODR. + // Ensure that we have at most one external linkage vtable initializer. assert(P.VTableVI.getSummaryList().size() == 1 || - llvm::all_of( + llvm::count_if( P.VTableVI.getSummaryList(), [&](const std::unique_ptr<GlobalValueSummary> &Summary) { - return GlobalValue::isLinkOnceODRLinkage(Summary->linkage()) || - GlobalValue::isWeakODRLinkage(Summary->linkage()); - })); - const auto *VS = cast<GlobalVarSummary>(P.VTableVI.getSummaryList()[0].get()); - if (!P.VTableVI.getSummaryList()[0]->isLive()) + return GlobalValue::isExternalLinkage(Summary->linkage()); + }) <= 1); + // Find the first non-available_externally linkage vtable initializer. + // We can have multiple available_externally, linkonce_odr and weak_odr + // vtable initializers, however we want to skip available_externally as they + // do not have type metadata attached, and therefore the summary will not + // contain any vtable functions. + // + // Also, handle the case of same-named local Vtables with the same path + // and therefore the same GUID. This can happen if there isn't enough + // distinguishing path when compiling the source file. In that case we + // conservatively return false early. + const GlobalVarSummary *VS = nullptr; + bool LocalFound = false; + for (auto &S : P.VTableVI.getSummaryList()) { + if (GlobalValue::isLocalLinkage(S->linkage())) { + if (LocalFound) + return false; + LocalFound = true; + } + if (!GlobalValue::isAvailableExternallyLinkage(S->linkage())) + VS = cast<GlobalVarSummary>(S.get()); + } + if (!VS->isLive()) continue; for (auto VTP : VS->vTableFuncs()) { if (VTP.VTableOffset != P.AddressPointOffset + ByteOffset) |

