1 //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/IR/DebugLoc.h" 11 #include "llvm/IR/IntrinsicInst.h" 12 #include "LLVMContextImpl.h" 13 #include "llvm/IR/DebugInfo.h" 14 using namespace llvm; 15 16 //===----------------------------------------------------------------------===// 17 // DebugLoc Implementation 18 //===----------------------------------------------------------------------===// 19 DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {} 20 DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {} 21 22 DILocation *DebugLoc::get() const { 23 return cast_or_null<DILocation>(Loc.get()); 24 } 25 26 unsigned DebugLoc::getLine() const { 27 assert(get() && "Expected valid DebugLoc"); 28 return get()->getLine(); 29 } 30 31 unsigned DebugLoc::getCol() const { 32 assert(get() && "Expected valid DebugLoc"); 33 return get()->getColumn(); 34 } 35 36 MDNode *DebugLoc::getScope() const { 37 assert(get() && "Expected valid DebugLoc"); 38 return get()->getScope(); 39 } 40 41 DILocation *DebugLoc::getInlinedAt() const { 42 assert(get() && "Expected valid DebugLoc"); 43 return get()->getInlinedAt(); 44 } 45 46 MDNode *DebugLoc::getInlinedAtScope() const { 47 return cast<DILocation>(Loc)->getInlinedAtScope(); 48 } 49 50 DebugLoc DebugLoc::getFnDebugLoc() const { 51 // FIXME: Add a method on \a DILocation that does this work. 52 const MDNode *Scope = getInlinedAtScope(); 53 if (auto *SP = getDISubprogram(Scope)) 54 return DebugLoc::get(SP->getScopeLine(), 0, SP); 55 56 return DebugLoc(); 57 } 58 59 DebugLoc DebugLoc::get(unsigned Line, unsigned Col, const MDNode *Scope, 60 const MDNode *InlinedAt) { 61 // If no scope is available, this is an unknown location. 62 if (!Scope) 63 return DebugLoc(); 64 65 return DILocation::get(Scope->getContext(), Line, Col, 66 const_cast<MDNode *>(Scope), 67 const_cast<MDNode *>(InlinedAt)); 68 } 69 70 DebugLoc DebugLoc::appendInlinedAt(DebugLoc DL, DILocation *InlinedAt, 71 LLVMContext &Ctx, 72 DenseMap<const MDNode *, MDNode *> &Cache, 73 bool ReplaceLast) { 74 SmallVector<DILocation *, 3> InlinedAtLocations; 75 DILocation *Last = InlinedAt; 76 DILocation *CurInlinedAt = DL; 77 78 // Gather all the inlined-at nodes. 79 while (DILocation *IA = CurInlinedAt->getInlinedAt()) { 80 // Skip any we've already built nodes for. 81 if (auto *Found = Cache[IA]) { 82 Last = cast<DILocation>(Found); 83 break; 84 } 85 86 if (ReplaceLast && !IA->getInlinedAt()) 87 break; 88 InlinedAtLocations.push_back(IA); 89 CurInlinedAt = IA; 90 } 91 92 // Starting from the top, rebuild the nodes to point to the new inlined-at 93 // location (then rebuilding the rest of the chain behind it) and update the 94 // map of already-constructed inlined-at nodes. 95 for (const DILocation *MD : reverse(InlinedAtLocations)) 96 Cache[MD] = Last = DILocation::getDistinct( 97 Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last); 98 99 return Last; 100 } 101 102 /// Reparent \c Scope from \c OrigSP to \c NewSP. 103 static DIScope *reparentScope(LLVMContext &Ctx, DIScope *Scope, 104 DISubprogram *OrigSP, DISubprogram *NewSP, 105 DenseMap<const MDNode *, MDNode *> &Cache) { 106 SmallVector<DIScope *, 3> ScopeChain; 107 DIScope *Last = NewSP; 108 DIScope *CurScope = Scope; 109 do { 110 if (auto *SP = dyn_cast<DISubprogram>(CurScope)) { 111 // Don't rewrite this scope chain if it doesn't lead to the replaced SP. 112 if (SP != OrigSP) 113 return Scope; 114 Cache.insert({OrigSP, NewSP}); 115 break; 116 } 117 if (auto *Found = Cache[CurScope]) { 118 Last = cast<DIScope>(Found); 119 break; 120 } 121 ScopeChain.push_back(CurScope); 122 } while ((CurScope = CurScope->getScope().resolve())); 123 124 // Starting from the top, rebuild the nodes to point to the new inlined-at 125 // location (then rebuilding the rest of the chain behind it) and update the 126 // map of already-constructed inlined-at nodes. 127 for (const DIScope *MD : reverse(ScopeChain)) { 128 if (auto *LB = dyn_cast<DILexicalBlock>(MD)) 129 Cache[MD] = Last = DILexicalBlock::getDistinct( 130 Ctx, Last, LB->getFile(), LB->getLine(), LB->getColumn()); 131 else if (auto *LB = dyn_cast<DILexicalBlockFile>(MD)) 132 Cache[MD] = Last = DILexicalBlockFile::getDistinct( 133 Ctx, Last, LB->getFile(), LB->getDiscriminator()); 134 else 135 llvm_unreachable("illegal parent scope"); 136 } 137 return Last; 138 } 139 140 void DebugLoc::reparentDebugInfo(Instruction &I, DISubprogram *OrigSP, 141 DISubprogram *NewSP, 142 DenseMap<const MDNode *, MDNode *> &Cache) { 143 auto DL = I.getDebugLoc(); 144 if (!OrigSP || !NewSP || OrigSP == NewSP || !DL) 145 return; 146 147 // Reparent the debug location. 148 auto &Ctx = I.getContext(); 149 DILocation *InlinedAt = DL->getInlinedAt(); 150 if (InlinedAt) { 151 while (auto *IA = InlinedAt->getInlinedAt()) 152 InlinedAt = IA; 153 auto NewScope = 154 reparentScope(Ctx, InlinedAt->getScope(), OrigSP, NewSP, Cache); 155 InlinedAt = 156 DebugLoc::get(InlinedAt->getLine(), InlinedAt->getColumn(), NewScope); 157 } 158 I.setDebugLoc( 159 DebugLoc::get(DL.getLine(), DL.getCol(), 160 reparentScope(Ctx, DL->getScope(), OrigSP, NewSP, Cache), 161 DebugLoc::appendInlinedAt(DL, InlinedAt, Ctx, Cache, 162 ReplaceLastInlinedAt))); 163 164 // Fix up debug variables to point to NewSP. 165 auto reparentVar = [&](DILocalVariable *Var) { 166 return DILocalVariable::getDistinct( 167 Ctx, 168 cast<DILocalScope>( 169 reparentScope(Ctx, Var->getScope(), OrigSP, NewSP, Cache)), 170 Var->getName(), Var->getFile(), Var->getLine(), Var->getType(), 171 Var->getArg(), Var->getFlags(), Var->getAlignInBits()); 172 }; 173 if (auto *DbgValue = dyn_cast<DbgValueInst>(&I)) { 174 auto *Var = DbgValue->getVariable(); 175 I.setOperand(2, MetadataAsValue::get(Ctx, reparentVar(Var))); 176 } else if (auto *DbgDeclare = dyn_cast<DbgDeclareInst>(&I)) { 177 auto *Var = DbgDeclare->getVariable(); 178 I.setOperand(1, MetadataAsValue::get(Ctx, reparentVar(Var))); 179 } 180 } 181 182 183 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 184 LLVM_DUMP_METHOD void DebugLoc::dump() const { 185 if (!Loc) 186 return; 187 188 dbgs() << getLine(); 189 if (getCol() != 0) 190 dbgs() << ',' << getCol(); 191 if (DebugLoc InlinedAtDL = DebugLoc(getInlinedAt())) { 192 dbgs() << " @ "; 193 InlinedAtDL.dump(); 194 } else 195 dbgs() << "\n"; 196 } 197 #endif 198 199 void DebugLoc::print(raw_ostream &OS) const { 200 if (!Loc) 201 return; 202 203 // Print source line info. 204 auto *Scope = cast<DIScope>(getScope()); 205 OS << Scope->getFilename(); 206 OS << ':' << getLine(); 207 if (getCol() != 0) 208 OS << ':' << getCol(); 209 210 if (DebugLoc InlinedAtDL = getInlinedAt()) { 211 OS << " @[ "; 212 InlinedAtDL.print(OS); 213 OS << " ]"; 214 } 215 } 216