summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/DebugLoc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/DebugLoc.cpp')
-rw-r--r--llvm/lib/IR/DebugLoc.cpp81
1 files changed, 81 insertions, 0 deletions
diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp
index 0485fece7c4..b7e3f0c6779 100644
--- a/llvm/lib/IR/DebugLoc.cpp
+++ b/llvm/lib/IR/DebugLoc.cpp
@@ -99,6 +99,87 @@ DebugLoc DebugLoc::appendInlinedAt(DebugLoc DL, DILocation *InlinedAt,
return Last;
}
+/// Reparent \c Scope from \c OrigSP to \c NewSP.
+static DIScope *reparentScope(LLVMContext &Ctx, DIScope *Scope,
+ DISubprogram *OrigSP, DISubprogram *NewSP,
+ DenseMap<const MDNode *, MDNode *> &Cache) {
+ SmallVector<DIScope *, 3> ScopeChain;
+ DIScope *Last = NewSP;
+ DIScope *CurScope = Scope;
+ do {
+ if (auto *SP = dyn_cast<DISubprogram>(CurScope)) {
+ // Don't rewrite this scope chain if it doesn't lead to the replaced SP.
+ if (SP != OrigSP)
+ return Scope;
+ Cache.insert({OrigSP, NewSP});
+ break;
+ }
+ if (auto *Found = Cache[CurScope]) {
+ Last = cast<DIScope>(Found);
+ break;
+ }
+ ScopeChain.push_back(CurScope);
+ } while ((CurScope = CurScope->getScope().resolve()));
+
+ // Starting from the top, rebuild the nodes to point to the new inlined-at
+ // location (then rebuilding the rest of the chain behind it) and update the
+ // map of already-constructed inlined-at nodes.
+ for (const DIScope *MD : reverse(ScopeChain)) {
+ if (auto *LB = dyn_cast<DILexicalBlock>(MD))
+ Cache[MD] = Last = DILexicalBlock::getDistinct(
+ Ctx, Last, LB->getFile(), LB->getLine(), LB->getColumn());
+ else if (auto *LB = dyn_cast<DILexicalBlockFile>(MD))
+ Cache[MD] = Last = DILexicalBlockFile::getDistinct(
+ Ctx, Last, LB->getFile(), LB->getDiscriminator());
+ else
+ llvm_unreachable("illegal parent scope");
+ }
+ return Last;
+}
+
+void DebugLoc::reparentDebugInfo(Instruction &I, DISubprogram *OrigSP,
+ DISubprogram *NewSP,
+ DenseMap<const MDNode *, MDNode *> &Cache) {
+ auto DL = I.getDebugLoc();
+ if (!OrigSP || !NewSP || OrigSP == NewSP || !DL)
+ return;
+
+ // Reparent the debug location.
+ auto &Ctx = I.getContext();
+ DILocation *InlinedAt = DL->getInlinedAt();
+ if (InlinedAt) {
+ while (auto *IA = InlinedAt->getInlinedAt())
+ InlinedAt = IA;
+ auto NewScope =
+ reparentScope(Ctx, InlinedAt->getScope(), OrigSP, NewSP, Cache);
+ InlinedAt =
+ DebugLoc::get(InlinedAt->getLine(), InlinedAt->getColumn(), NewScope);
+ }
+ I.setDebugLoc(
+ DebugLoc::get(DL.getLine(), DL.getCol(),
+ reparentScope(Ctx, DL->getScope(), OrigSP, NewSP, Cache),
+ DebugLoc::appendInlinedAt(DL, InlinedAt, Ctx, Cache,
+ ReplaceLastInlinedAt)));
+
+ // Fix up debug variables to point to NewSP.
+ auto reparentVar = [&](DILocalVariable *Var) {
+ return DILocalVariable::get(
+ Ctx,
+ cast<DILocalScope>(
+ reparentScope(Ctx, Var->getScope(), OrigSP, NewSP, Cache)),
+ Var->getName(), Var->getFile(), Var->getLine(), Var->getType(),
+ Var->getArg(), Var->getFlags(), Var->getAlignInBits());
+ };
+ if (auto *DbgValue = dyn_cast<DbgValueInst>(&I)) {
+ auto *Var = DbgValue->getVariable();
+ I.setOperand(2, MetadataAsValue::get(Ctx, reparentVar(Var)));
+ } else if (auto *DbgDeclare = dyn_cast<DbgDeclareInst>(&I)) {
+ auto *Var = DbgDeclare->getVariable();
+ I.setOperand(1, MetadataAsValue::get(Ctx, reparentVar(Var)));
+ }
+}
+
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void DebugLoc::dump() const {
if (!Loc)
OpenPOWER on IntegriCloud