xref: /openbsd/gnu/llvm/llvm/lib/IR/DebugLoc.cpp (revision d415bd75)
109467b48Spatrick //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/IR/DebugLoc.h"
1009467b48Spatrick #include "llvm/Config/llvm-config.h"
1109467b48Spatrick #include "llvm/IR/DebugInfo.h"
1209467b48Spatrick using namespace llvm;
1309467b48Spatrick 
1409467b48Spatrick //===----------------------------------------------------------------------===//
1509467b48Spatrick // DebugLoc Implementation
1609467b48Spatrick //===----------------------------------------------------------------------===//
DebugLoc(const DILocation * L)1709467b48Spatrick DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {}
DebugLoc(const MDNode * L)1809467b48Spatrick DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {}
1909467b48Spatrick 
get() const2009467b48Spatrick DILocation *DebugLoc::get() const {
2109467b48Spatrick   return cast_or_null<DILocation>(Loc.get());
2209467b48Spatrick }
2309467b48Spatrick 
getLine() const2409467b48Spatrick unsigned DebugLoc::getLine() const {
2509467b48Spatrick   assert(get() && "Expected valid DebugLoc");
2609467b48Spatrick   return get()->getLine();
2709467b48Spatrick }
2809467b48Spatrick 
getCol() const2909467b48Spatrick unsigned DebugLoc::getCol() const {
3009467b48Spatrick   assert(get() && "Expected valid DebugLoc");
3109467b48Spatrick   return get()->getColumn();
3209467b48Spatrick }
3309467b48Spatrick 
getScope() const3409467b48Spatrick MDNode *DebugLoc::getScope() const {
3509467b48Spatrick   assert(get() && "Expected valid DebugLoc");
3609467b48Spatrick   return get()->getScope();
3709467b48Spatrick }
3809467b48Spatrick 
getInlinedAt() const3909467b48Spatrick DILocation *DebugLoc::getInlinedAt() const {
4009467b48Spatrick   assert(get() && "Expected valid DebugLoc");
4109467b48Spatrick   return get()->getInlinedAt();
4209467b48Spatrick }
4309467b48Spatrick 
getInlinedAtScope() const4409467b48Spatrick MDNode *DebugLoc::getInlinedAtScope() const {
4509467b48Spatrick   return cast<DILocation>(Loc)->getInlinedAtScope();
4609467b48Spatrick }
4709467b48Spatrick 
getFnDebugLoc() const4809467b48Spatrick DebugLoc DebugLoc::getFnDebugLoc() const {
4909467b48Spatrick   // FIXME: Add a method on \a DILocation that does this work.
5009467b48Spatrick   const MDNode *Scope = getInlinedAtScope();
5109467b48Spatrick   if (auto *SP = getDISubprogram(Scope))
5273471bf0Spatrick     return DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);
5309467b48Spatrick 
5409467b48Spatrick   return DebugLoc();
5509467b48Spatrick }
5609467b48Spatrick 
isImplicitCode() const5709467b48Spatrick bool DebugLoc::isImplicitCode() const {
5809467b48Spatrick   if (DILocation *Loc = get()) {
5909467b48Spatrick     return Loc->isImplicitCode();
6009467b48Spatrick   }
6109467b48Spatrick   return true;
6209467b48Spatrick }
6309467b48Spatrick 
setImplicitCode(bool ImplicitCode)6409467b48Spatrick void DebugLoc::setImplicitCode(bool ImplicitCode) {
6509467b48Spatrick   if (DILocation *Loc = get()) {
6609467b48Spatrick     Loc->setImplicitCode(ImplicitCode);
6709467b48Spatrick   }
6809467b48Spatrick }
6909467b48Spatrick 
replaceInlinedAtSubprogram(const DebugLoc & RootLoc,DISubprogram & NewSP,LLVMContext & Ctx,DenseMap<const MDNode *,MDNode * > & Cache)70*d415bd75Srobert DebugLoc DebugLoc::replaceInlinedAtSubprogram(
71*d415bd75Srobert     const DebugLoc &RootLoc, DISubprogram &NewSP, LLVMContext &Ctx,
72*d415bd75Srobert     DenseMap<const MDNode *, MDNode *> &Cache) {
73*d415bd75Srobert   SmallVector<DILocation *> LocChain;
74*d415bd75Srobert   DILocation *CachedResult = nullptr;
75*d415bd75Srobert 
76*d415bd75Srobert   // Collect the inline chain, stopping if we find a location that has already
77*d415bd75Srobert   // been processed.
78*d415bd75Srobert   for (DILocation *Loc = RootLoc; Loc; Loc = Loc->getInlinedAt()) {
79*d415bd75Srobert     if (auto It = Cache.find(Loc); It != Cache.end()) {
80*d415bd75Srobert       CachedResult = cast<DILocation>(It->second);
81*d415bd75Srobert       break;
82*d415bd75Srobert     }
83*d415bd75Srobert     LocChain.push_back(Loc);
84*d415bd75Srobert   }
85*d415bd75Srobert 
86*d415bd75Srobert   DILocation *UpdatedLoc = CachedResult;
87*d415bd75Srobert   if (!UpdatedLoc) {
88*d415bd75Srobert     // If no cache hits, then back() is the end of the inline chain, that is,
89*d415bd75Srobert     // the DILocation whose scope ends in the Subprogram to be replaced.
90*d415bd75Srobert     DILocation *LocToUpdate = LocChain.pop_back_val();
91*d415bd75Srobert     DIScope *NewScope = DILocalScope::cloneScopeForSubprogram(
92*d415bd75Srobert         *LocToUpdate->getScope(), NewSP, Ctx, Cache);
93*d415bd75Srobert     UpdatedLoc = DILocation::get(Ctx, LocToUpdate->getLine(),
94*d415bd75Srobert                                  LocToUpdate->getColumn(), NewScope);
95*d415bd75Srobert     Cache[LocToUpdate] = UpdatedLoc;
96*d415bd75Srobert   }
97*d415bd75Srobert 
98*d415bd75Srobert   // Recreate the location chain, bottom-up, starting at the new scope (or a
99*d415bd75Srobert   // cached result).
100*d415bd75Srobert   for (const DILocation *LocToUpdate : reverse(LocChain)) {
101*d415bd75Srobert     UpdatedLoc =
102*d415bd75Srobert         DILocation::get(Ctx, LocToUpdate->getLine(), LocToUpdate->getColumn(),
103*d415bd75Srobert                         LocToUpdate->getScope(), UpdatedLoc);
104*d415bd75Srobert     Cache[LocToUpdate] = UpdatedLoc;
105*d415bd75Srobert   }
106*d415bd75Srobert 
107*d415bd75Srobert   return UpdatedLoc;
108*d415bd75Srobert }
109*d415bd75Srobert 
appendInlinedAt(const DebugLoc & DL,DILocation * InlinedAt,LLVMContext & Ctx,DenseMap<const MDNode *,MDNode * > & Cache)110097a140dSpatrick DebugLoc DebugLoc::appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt,
11109467b48Spatrick                                    LLVMContext &Ctx,
11273471bf0Spatrick                                    DenseMap<const MDNode *, MDNode *> &Cache) {
11309467b48Spatrick   SmallVector<DILocation *, 3> InlinedAtLocations;
11409467b48Spatrick   DILocation *Last = InlinedAt;
11509467b48Spatrick   DILocation *CurInlinedAt = DL;
11609467b48Spatrick 
11709467b48Spatrick   // Gather all the inlined-at nodes.
11809467b48Spatrick   while (DILocation *IA = CurInlinedAt->getInlinedAt()) {
11909467b48Spatrick     // Skip any we've already built nodes for.
12009467b48Spatrick     if (auto *Found = Cache[IA]) {
12109467b48Spatrick       Last = cast<DILocation>(Found);
12209467b48Spatrick       break;
12309467b48Spatrick     }
12409467b48Spatrick 
12509467b48Spatrick     InlinedAtLocations.push_back(IA);
12609467b48Spatrick     CurInlinedAt = IA;
12709467b48Spatrick   }
12809467b48Spatrick 
12909467b48Spatrick   // Starting from the top, rebuild the nodes to point to the new inlined-at
13009467b48Spatrick   // location (then rebuilding the rest of the chain behind it) and update the
13109467b48Spatrick   // map of already-constructed inlined-at nodes.
13209467b48Spatrick   for (const DILocation *MD : reverse(InlinedAtLocations))
13309467b48Spatrick     Cache[MD] = Last = DILocation::getDistinct(
13409467b48Spatrick         Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last);
13509467b48Spatrick 
13609467b48Spatrick   return Last;
13709467b48Spatrick }
13809467b48Spatrick 
13909467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const14009467b48Spatrick LLVM_DUMP_METHOD void DebugLoc::dump() const { print(dbgs()); }
14109467b48Spatrick #endif
14209467b48Spatrick 
print(raw_ostream & OS) const14309467b48Spatrick void DebugLoc::print(raw_ostream &OS) const {
14409467b48Spatrick   if (!Loc)
14509467b48Spatrick     return;
14609467b48Spatrick 
14709467b48Spatrick   // Print source line info.
14809467b48Spatrick   auto *Scope = cast<DIScope>(getScope());
14909467b48Spatrick   OS << Scope->getFilename();
15009467b48Spatrick   OS << ':' << getLine();
15109467b48Spatrick   if (getCol() != 0)
15209467b48Spatrick     OS << ':' << getCol();
15309467b48Spatrick 
15409467b48Spatrick   if (DebugLoc InlinedAtDL = getInlinedAt()) {
15509467b48Spatrick     OS << " @[ ";
15609467b48Spatrick     InlinedAtDL.print(OS);
15709467b48Spatrick     OS << " ]";
15809467b48Spatrick   }
15909467b48Spatrick }
160