1 //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/DebugLoc.h"
10 #include "llvm/Config/llvm-config.h"
11 #include "llvm/IR/DebugInfo.h"
14 //===----------------------------------------------------------------------===//
15 // DebugLoc Implementation
16 //===----------------------------------------------------------------------===//
17 DebugLoc::DebugLoc(const DILocation
*L
) : Loc(const_cast<DILocation
*>(L
)) {}
18 DebugLoc::DebugLoc(const MDNode
*L
) : Loc(const_cast<MDNode
*>(L
)) {}
20 DILocation
*DebugLoc::get() const {
21 return cast_or_null
<DILocation
>(Loc
.get());
24 unsigned DebugLoc::getLine() const {
25 assert(get() && "Expected valid DebugLoc");
26 return get()->getLine();
29 unsigned DebugLoc::getCol() const {
30 assert(get() && "Expected valid DebugLoc");
31 return get()->getColumn();
34 MDNode
*DebugLoc::getScope() const {
35 assert(get() && "Expected valid DebugLoc");
36 return get()->getScope();
39 DILocation
*DebugLoc::getInlinedAt() const {
40 assert(get() && "Expected valid DebugLoc");
41 return get()->getInlinedAt();
44 MDNode
*DebugLoc::getInlinedAtScope() const {
45 return cast
<DILocation
>(Loc
)->getInlinedAtScope();
48 DebugLoc
DebugLoc::getFnDebugLoc() const {
49 // FIXME: Add a method on \a DILocation that does this work.
50 const MDNode
*Scope
= getInlinedAtScope();
51 if (auto *SP
= getDISubprogram(Scope
))
52 return DILocation::get(SP
->getContext(), SP
->getScopeLine(), 0, SP
);
57 bool DebugLoc::isImplicitCode() const {
58 if (DILocation
*Loc
= get()) {
59 return Loc
->isImplicitCode();
64 void DebugLoc::setImplicitCode(bool ImplicitCode
) {
65 if (DILocation
*Loc
= get()) {
66 Loc
->setImplicitCode(ImplicitCode
);
70 DebugLoc
DebugLoc::replaceInlinedAtSubprogram(
71 const DebugLoc
&RootLoc
, DISubprogram
&NewSP
, LLVMContext
&Ctx
,
72 DenseMap
<const MDNode
*, MDNode
*> &Cache
) {
73 SmallVector
<DILocation
*> LocChain
;
74 DILocation
*CachedResult
= nullptr;
76 // Collect the inline chain, stopping if we find a location that has already
78 for (DILocation
*Loc
= RootLoc
; Loc
; Loc
= Loc
->getInlinedAt()) {
79 if (auto It
= Cache
.find(Loc
); It
!= Cache
.end()) {
80 CachedResult
= cast
<DILocation
>(It
->second
);
83 LocChain
.push_back(Loc
);
86 DILocation
*UpdatedLoc
= CachedResult
;
88 // If no cache hits, then back() is the end of the inline chain, that is,
89 // the DILocation whose scope ends in the Subprogram to be replaced.
90 DILocation
*LocToUpdate
= LocChain
.pop_back_val();
91 DIScope
*NewScope
= DILocalScope::cloneScopeForSubprogram(
92 *LocToUpdate
->getScope(), NewSP
, Ctx
, Cache
);
93 UpdatedLoc
= DILocation::get(Ctx
, LocToUpdate
->getLine(),
94 LocToUpdate
->getColumn(), NewScope
);
95 Cache
[LocToUpdate
] = UpdatedLoc
;
98 // Recreate the location chain, bottom-up, starting at the new scope (or a
100 for (const DILocation
*LocToUpdate
: reverse(LocChain
)) {
102 DILocation::get(Ctx
, LocToUpdate
->getLine(), LocToUpdate
->getColumn(),
103 LocToUpdate
->getScope(), UpdatedLoc
);
104 Cache
[LocToUpdate
] = UpdatedLoc
;
110 DebugLoc
DebugLoc::appendInlinedAt(const DebugLoc
&DL
, DILocation
*InlinedAt
,
112 DenseMap
<const MDNode
*, MDNode
*> &Cache
) {
113 SmallVector
<DILocation
*, 3> InlinedAtLocations
;
114 DILocation
*Last
= InlinedAt
;
115 DILocation
*CurInlinedAt
= DL
;
117 // Gather all the inlined-at nodes.
118 while (DILocation
*IA
= CurInlinedAt
->getInlinedAt()) {
119 // Skip any we've already built nodes for.
120 if (auto *Found
= Cache
[IA
]) {
121 Last
= cast
<DILocation
>(Found
);
125 InlinedAtLocations
.push_back(IA
);
129 // Starting from the top, rebuild the nodes to point to the new inlined-at
130 // location (then rebuilding the rest of the chain behind it) and update the
131 // map of already-constructed inlined-at nodes.
132 for (const DILocation
*MD
: reverse(InlinedAtLocations
))
133 Cache
[MD
] = Last
= DILocation::getDistinct(
134 Ctx
, MD
->getLine(), MD
->getColumn(), MD
->getScope(), Last
);
139 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
140 LLVM_DUMP_METHOD
void DebugLoc::dump() const { print(dbgs()); }
143 void DebugLoc::print(raw_ostream
&OS
) const {
147 // Print source line info.
148 auto *Scope
= cast
<DIScope
>(getScope());
149 OS
<< Scope
->getFilename();
150 OS
<< ':' << getLine();
152 OS
<< ':' << getCol();
154 if (DebugLoc InlinedAtDL
= getInlinedAt()) {
156 InlinedAtDL
.print(OS
);