diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-12-18 01:05:33 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-12-18 01:05:33 +0000 |
commit | fda0cee7c6d4e4f874f7ae955b1f4cb4aa31416f (patch) | |
tree | 5e5746022a3cad3f51e54b7d2ef51956894e0dc2 /llvm/lib/Linker/LinkModules.cpp | |
parent | 9fb36654265a8dfa1eb8e5e5054311c5396386aa (diff) | |
download | bcm5719-llvm-fda0cee7c6d4e4f874f7ae955b1f4cb4aa31416f.tar.gz bcm5719-llvm-fda0cee7c6d4e4f874f7ae955b1f4cb4aa31416f.zip |
Reapply "Linker: Drop superseded subprograms"
This reverts commit r224416, reapplying r224389. The buildbots hadn't
recovered after my revert, waiting until David reverted a couple of his
commits. It looks like it was just bad timing (where we were both
modifying code related to the same assertion). Trying again...
Here's the original text:
When a function gets replaced by `ModuleLinker`, drop superseded
subprograms. This ensures that the "first" subprogram pointing at a
function is the same one that `!dbg` references point at.
This is a stop-gap fix for PR21910. Notably, this fixes Release+Asserts
bootstraps that are currently asserting out in
`LexicalScopes::initialize()` due to the explicit instantiations in
`lib/IR/Dominators.cpp` eventually getting replaced by -argpromotion.
llvm-svn: 224487
Diffstat (limited to 'llvm/lib/Linker/LinkModules.cpp')
-rw-r--r-- | llvm/lib/Linker/LinkModules.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp index 0e144157af4..7f3e5b3bd2a 100644 --- a/llvm/lib/Linker/LinkModules.cpp +++ b/llvm/lib/Linker/LinkModules.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" @@ -416,6 +417,9 @@ class ModuleLinker { // Vector of GlobalValues to lazily link in. std::vector<GlobalValue *> LazilyLinkGlobalValues; + /// Functions that have replaced other functions. + SmallPtrSet<const Function *, 16> OverridingFunctions; + Linker::DiagnosticHandlerFunction DiagnosticHandler; public: @@ -494,6 +498,7 @@ private: bool linkGlobalValueBody(GlobalValue &Src); void linkNamedMDNodes(); + void stripReplacedSubprograms(); }; } @@ -1078,6 +1083,10 @@ bool ModuleLinker::linkGlobalValueProto(GlobalValue *SGV) { } NewGV = copyGlobalValueProto(TypeMap, *DstM, SGV); + + if (DGV && isa<Function>(DGV)) + if (auto *NewF = dyn_cast<Function>(NewGV)) + OverridingFunctions.insert(NewF); } NewGV->setUnnamedAddr(HasUnnamedAddr); @@ -1244,6 +1253,48 @@ void ModuleLinker::linkNamedMDNodes() { } } +/// Drop DISubprograms that have been superseded. +/// +/// FIXME: this creates an asymmetric result: we strip losing subprograms from +/// DstM, but leave losing subprograms in SrcM. Instead we should also strip +/// losers from SrcM, but this requires extra plumbing in MapValue. +void ModuleLinker::stripReplacedSubprograms() { + // Avoid quadratic runtime by returning early when there's nothing to do. + if (OverridingFunctions.empty()) + return; + + // Move the functions now, so the set gets cleared even on early returns. + auto Functions = std::move(OverridingFunctions); + OverridingFunctions.clear(); + + // Drop subprograms whose functions have been overridden by the new compile + // unit. + NamedMDNode *CompileUnits = DstM->getNamedMetadata("llvm.dbg.cu"); + if (!CompileUnits) + return; + for (unsigned I = 0, E = CompileUnits->getNumOperands(); I != E; ++I) { + DICompileUnit CU(CompileUnits->getOperand(I)); + assert(CU && "Expected valid compile unit"); + + DITypedArray<DISubprogram> SPs(CU.getSubprograms()); + assert(SPs && "Expected valid subprogram array"); + + SmallVector<Metadata *, 16> NewSPs; + NewSPs.reserve(SPs.getNumElements()); + for (unsigned S = 0, SE = SPs.getNumElements(); S != SE; ++S) { + DISubprogram SP = SPs.getElement(S); + if (SP && SP.getFunction() && Functions.count(SP.getFunction())) + continue; + + NewSPs.push_back(SP); + } + + // Redirect operand to the overriding subprogram. + if (NewSPs.size() != SPs.getNumElements()) + CU.replaceSubprograms(DIArray(MDNode::get(DstM->getContext(), NewSPs))); + } +} + /// Merge the linker flags in Src into the Dest module. bool ModuleLinker::linkModuleFlagsMetadata() { // If the source module has no module flags, we are done. @@ -1509,6 +1560,9 @@ bool ModuleLinker::run() { linkGlobalValueBody(Src); } + // Strip replaced subprograms before linking together compile units. + stripReplacedSubprograms(); + // Remap all of the named MDNodes in Src into the DstM module. We do this // after linking GlobalValues so that MDNodes that reference GlobalValues // are properly remapped. |