LLVM  16.0.0git
DebugLoc.cpp
Go to the documentation of this file.
1 //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/IR/DebugLoc.h"
10 #include "llvm/Config/llvm-config.h"
11 #include "llvm/IR/DebugInfo.h"
12 using namespace llvm;
13 
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)) {}
19 
21  return cast_or_null<DILocation>(Loc.get());
22 }
23 
24 unsigned DebugLoc::getLine() const {
25  assert(get() && "Expected valid DebugLoc");
26  return get()->getLine();
27 }
28 
29 unsigned DebugLoc::getCol() const {
30  assert(get() && "Expected valid DebugLoc");
31  return get()->getColumn();
32 }
33 
35  assert(get() && "Expected valid DebugLoc");
36  return get()->getScope();
37 }
38 
40  assert(get() && "Expected valid DebugLoc");
41  return get()->getInlinedAt();
42 }
43 
45  return cast<DILocation>(Loc)->getInlinedAtScope();
46 }
47 
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);
53 
54  return DebugLoc();
55 }
56 
58  if (DILocation *Loc = get()) {
59  return Loc->isImplicitCode();
60  }
61  return true;
62 }
63 
64 void DebugLoc::setImplicitCode(bool ImplicitCode) {
65  if (DILocation *Loc = get()) {
66  Loc->setImplicitCode(ImplicitCode);
67  }
68 }
69 
70 /// Traverses the scope chain rooted at RootScope until it hits a Subprogram,
71 /// recreating the chain with "NewSP" instead.
72 static DIScope *
74  LLVMContext &Ctx,
76  SmallVector<DIScope *> ScopeChain;
77  DIScope *CachedResult = nullptr;
78 
79  for (DIScope *Scope = &RootScope; !isa<DISubprogram>(Scope);
80  Scope = Scope->getScope()) {
81  if (auto It = Cache.find(Scope); It != Cache.end()) {
82  CachedResult = cast<DIScope>(It->second);
83  break;
84  }
85  ScopeChain.push_back(Scope);
86  }
87 
88  // Recreate the scope chain, bottom-up, starting at the new subprogram (or a
89  // cached result).
90  DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
91  for (DIScope *ScopeToUpdate : reverse(ScopeChain)) {
92  TempMDNode ClonedScope = ScopeToUpdate->clone();
93  cast<DILexicalBlockBase>(*ClonedScope).replaceScope(UpdatedScope);
94  UpdatedScope =
95  cast<DIScope>(MDNode::replaceWithUniqued(std::move(ClonedScope)));
96  Cache[ScopeToUpdate] = UpdatedScope;
97  }
98  return UpdatedScope;
99 }
100 
102  const DebugLoc &RootLoc, DISubprogram &NewSP, LLVMContext &Ctx,
104  SmallVector<DILocation *> LocChain;
105  DILocation *CachedResult = nullptr;
106 
107  // Collect the inline chain, stopping if we find a location that has already
108  // been processed.
109  for (DILocation *Loc = RootLoc; Loc; Loc = Loc->getInlinedAt()) {
110  if (auto It = Cache.find(Loc); It != Cache.end()) {
111  CachedResult = cast<DILocation>(It->second);
112  break;
113  }
114  LocChain.push_back(Loc);
115  }
116 
117  DILocation *UpdatedLoc = CachedResult;
118  if (!UpdatedLoc) {
119  // If no cache hits, then back() is the end of the inline chain, that is,
120  // the DILocation whose scope ends in the Subprogram to be replaced.
121  DILocation *LocToUpdate = LocChain.pop_back_val();
122  DIScope *NewScope =
123  cloneScopeForSubprogram(*LocToUpdate->getScope(), NewSP, Ctx, Cache);
124  UpdatedLoc = DILocation::get(Ctx, LocToUpdate->getLine(),
125  LocToUpdate->getColumn(), NewScope);
126  Cache[LocToUpdate] = UpdatedLoc;
127  }
128 
129  // Recreate the location chain, bottom-up, starting at the new scope (or a
130  // cached result).
131  for (const DILocation *LocToUpdate : reverse(LocChain)) {
132  UpdatedLoc =
133  DILocation::get(Ctx, LocToUpdate->getLine(), LocToUpdate->getColumn(),
134  LocToUpdate->getScope(), UpdatedLoc);
135  Cache[LocToUpdate] = UpdatedLoc;
136  }
137 
138  return UpdatedLoc;
139 }
140 
142  LLVMContext &Ctx,
144  SmallVector<DILocation *, 3> InlinedAtLocations;
145  DILocation *Last = InlinedAt;
146  DILocation *CurInlinedAt = DL;
147 
148  // Gather all the inlined-at nodes.
149  while (DILocation *IA = CurInlinedAt->getInlinedAt()) {
150  // Skip any we've already built nodes for.
151  if (auto *Found = Cache[IA]) {
152  Last = cast<DILocation>(Found);
153  break;
154  }
155 
156  InlinedAtLocations.push_back(IA);
157  CurInlinedAt = IA;
158  }
159 
160  // Starting from the top, rebuild the nodes to point to the new inlined-at
161  // location (then rebuilding the rest of the chain behind it) and update the
162  // map of already-constructed inlined-at nodes.
163  for (const DILocation *MD : reverse(InlinedAtLocations))
164  Cache[MD] = Last = DILocation::getDistinct(
165  Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last);
166 
167  return Last;
168 }
169 
170 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
172 #endif
173 
174 void DebugLoc::print(raw_ostream &OS) const {
175  if (!Loc)
176  return;
177 
178  // Print source line info.
179  auto *Scope = cast<DIScope>(getScope());
180  OS << Scope->getFilename();
181  OS << ':' << getLine();
182  if (getCol() != 0)
183  OS << ':' << getCol();
184 
185  if (DebugLoc InlinedAtDL = getInlinedAt()) {
186  OS << " @[ ";
187  InlinedAtDL.print(OS);
188  OS << " ]";
189  }
190 }
cloneScopeForSubprogram
static DIScope * cloneScopeForSubprogram(DILocalScope &RootScope, DISubprogram &NewSP, LLVMContext &Ctx, DenseMap< const MDNode *, MDNode * > &Cache)
Traverses the scope chain rooted at RootScope until it hits a Subprogram, recreating the chain with "...
Definition: DebugLoc.cpp:73
LLVM_DUMP_METHOD
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:492
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::PseudoProbeReservedId::Last
@ Last
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::DebugLoc::replaceInlinedAtSubprogram
static DebugLoc replaceInlinedAtSubprogram(const DebugLoc &DL, DISubprogram &NewSP, LLVMContext &Ctx, DenseMap< const MDNode *, MDNode * > &Cache)
Rebuild the entire inline-at chain by replacing the subprogram at the end of the chain with NewSP.
Definition: DebugLoc.cpp:101
llvm::DILocation
Debug location.
Definition: DebugInfoMetadata.h:1600
llvm::getDISubprogram
DISubprogram * getDISubprogram(const MDNode *Scope)
Find subprogram that is enclosing this scope.
Definition: DebugInfo.cpp:139
llvm::DebugLoc::getInlinedAt
DILocation * getInlinedAt() const
Definition: DebugLoc.cpp:39
llvm::DebugLoc::DebugLoc
DebugLoc()=default
llvm::MDNode::get
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1400
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::TypedTrackingMDRef::get
T * get() const
Definition: TrackingMDRef.h:126
llvm::DebugLoc::getCol
unsigned getCol() const
Definition: DebugLoc.cpp:29
llvm::DebugLoc::getFnDebugLoc
DebugLoc getFnDebugLoc() const
Find the debug info location for the start of the function.
Definition: DebugLoc.cpp:48
llvm::DebugLoc::dump
void dump() const
Definition: DebugLoc.cpp:171
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::AArch64PACKey::IA
@ IA
Definition: AArch64BaseInfo.h:819
DebugLoc.h
llvm::DebugLoc::appendInlinedAt
static DebugLoc appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt, LLVMContext &Ctx, DenseMap< const MDNode *, MDNode * > &Cache)
Rebuild the entire inlined-at chain for this instruction so that the top of the chain now is inlined-...
Definition: DebugLoc.cpp:141
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::MDNode::replaceWithUniqued
static std::enable_if_t< std::is_base_of< MDNode, T >::value, T * > replaceWithUniqued(std::unique_ptr< T, TempMDNodeDeleter > N)
Replace a temporary node with a uniqued one.
Definition: Metadata.h:1168
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
llvm::DenseMap
Definition: DenseMap.h:714
DebugInfo.h
llvm::DebugLoc::get
DILocation * get() const
Get the underlying DILocation.
Definition: DebugLoc.cpp:20
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::find
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MDNode
Metadata node.
Definition: Metadata.h:944
llvm::DebugLoc::setImplicitCode
void setImplicitCode(bool ImplicitCode)
Definition: DebugLoc.cpp:64
llvm::DebugLoc::isImplicitCode
bool isImplicitCode() const
Check if the DebugLoc corresponds to an implicit code.
Definition: DebugLoc.cpp:57
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::MDNode::getDistinct
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1408
llvm::DIScope
Base class for scope-like contexts.
Definition: DebugInfoMetadata.h:509
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::end
iterator end()
Definition: DenseMap.h:84
llvm::DebugLoc::print
void print(raw_ostream &OS) const
prints source location /path/to/file.exe:line:col @[inlined at]
Definition: DebugLoc.cpp:174
llvm::DebugLoc::getLine
unsigned getLine() const
Definition: DebugLoc.cpp:24
llvm::SmallVectorImpl::pop_back_val
T pop_back_val()
Definition: SmallVector.h:677
llvm::DISubprogram
Subprogram description.
Definition: DebugInfoMetadata.h:1846
llvm::reverse
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:485
llvm::MDNode::clone
TempMDNode clone() const
Create a (temporary) clone of this.
Definition: Metadata.cpp:559
llvm::DILocalScope
A scope for locals.
Definition: DebugInfoMetadata.h:1570
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::DebugLoc::getInlinedAtScope
MDNode * getInlinedAtScope() const
Get the fully inlined-at scope for a DebugLoc.
Definition: DebugLoc.cpp:44
llvm::DebugLoc::getScope
MDNode * getScope() const
Definition: DebugLoc.cpp:34