1ef860a24SChandler Carruth //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
2ef860a24SChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ef860a24SChandler Carruth //
7ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
8ef860a24SChandler Carruth 
992051407SChandler Carruth #include "llvm/IR/DebugLoc.h"
10432a3883SNico Weber #include "llvm/Config/llvm-config.h"
119a4c9e59SChandler Carruth #include "llvm/IR/DebugInfo.h"
12ef860a24SChandler Carruth using namespace llvm;
13ef860a24SChandler Carruth 
14ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
15ef860a24SChandler Carruth // DebugLoc Implementation
16ef860a24SChandler Carruth //===----------------------------------------------------------------------===//
DebugLoc(const DILocation * L)17a9308c49SDuncan P. N. Exon Smith DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {}
DebugLoc(const MDNode * L)185c8f1dc2SDuncan P. N. Exon Smith DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {}
19ef860a24SChandler Carruth 
get() const20a9308c49SDuncan P. N. Exon Smith DILocation *DebugLoc::get() const {
21a9308c49SDuncan P. N. Exon Smith   return cast_or_null<DILocation>(Loc.get());
22ef860a24SChandler Carruth }
23ef860a24SChandler Carruth 
getLine() const2486b0db42SDuncan P. N. Exon Smith unsigned DebugLoc::getLine() const {
2586b0db42SDuncan P. N. Exon Smith   assert(get() && "Expected valid DebugLoc");
2686b0db42SDuncan P. N. Exon Smith   return get()->getLine();
27ef860a24SChandler Carruth }
28ef860a24SChandler Carruth 
getCol() const2986b0db42SDuncan P. N. Exon Smith unsigned DebugLoc::getCol() const {
3086b0db42SDuncan P. N. Exon Smith   assert(get() && "Expected valid DebugLoc");
3186b0db42SDuncan P. N. Exon Smith   return get()->getColumn();
3286b0db42SDuncan P. N. Exon Smith }
3386b0db42SDuncan P. N. Exon Smith 
getScope() const3486b0db42SDuncan P. N. Exon Smith MDNode *DebugLoc::getScope() const {
3586b0db42SDuncan P. N. Exon Smith   assert(get() && "Expected valid DebugLoc");
3686b0db42SDuncan P. N. Exon Smith   return get()->getScope();
3786b0db42SDuncan P. N. Exon Smith }
3886b0db42SDuncan P. N. Exon Smith 
getInlinedAt() const39a9308c49SDuncan P. N. Exon Smith DILocation *DebugLoc::getInlinedAt() const {
4086b0db42SDuncan P. N. Exon Smith   assert(get() && "Expected valid DebugLoc");
4186b0db42SDuncan P. N. Exon Smith   return get()->getInlinedAt();
4286b0db42SDuncan P. N. Exon Smith }
4386b0db42SDuncan P. N. Exon Smith 
getInlinedAtScope() const4486b0db42SDuncan P. N. Exon Smith MDNode *DebugLoc::getInlinedAtScope() const {
45a9308c49SDuncan P. N. Exon Smith   return cast<DILocation>(Loc)->getInlinedAtScope();
46ef860a24SChandler Carruth }
47ef860a24SChandler Carruth 
getFnDebugLoc() const485bf8fef5SDuncan P. N. Exon Smith DebugLoc DebugLoc::getFnDebugLoc() const {
49a9308c49SDuncan P. N. Exon Smith   // FIXME: Add a method on \a DILocation that does this work.
5086b0db42SDuncan P. N. Exon Smith   const MDNode *Scope = getInlinedAtScope();
512fbe1354SDuncan P. N. Exon Smith   if (auto *SP = getDISubprogram(Scope))
52b5ad32efSFangrui Song     return DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);
53f166f6c8STimur Iskhodzhanov 
54f166f6c8STimur Iskhodzhanov   return DebugLoc();
55f166f6c8STimur Iskhodzhanov }
56ef860a24SChandler Carruth 
isImplicitCode() const57eb7f6020SCalixte Denizet bool DebugLoc::isImplicitCode() const {
58eb7f6020SCalixte Denizet   if (DILocation *Loc = get()) {
59eb7f6020SCalixte Denizet     return Loc->isImplicitCode();
60eb7f6020SCalixte Denizet   }
61eb7f6020SCalixte Denizet   return true;
62eb7f6020SCalixte Denizet }
63eb7f6020SCalixte Denizet 
setImplicitCode(bool ImplicitCode)64eb7f6020SCalixte Denizet void DebugLoc::setImplicitCode(bool ImplicitCode) {
65eb7f6020SCalixte Denizet   if (DILocation *Loc = get()) {
66eb7f6020SCalixte Denizet     Loc->setImplicitCode(ImplicitCode);
67eb7f6020SCalixte Denizet   }
68eb7f6020SCalixte Denizet }
69eb7f6020SCalixte Denizet 
appendInlinedAt(const DebugLoc & DL,DILocation * InlinedAt,LLVMContext & Ctx,DenseMap<const MDNode *,MDNode * > & Cache)700ae989a1SSimon Pilgrim DebugLoc DebugLoc::appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt,
71c10d0e5cSAdrian Prantl                                    LLVMContext &Ctx,
72*d466e10aSFangrui Song                                    DenseMap<const MDNode *, MDNode *> &Cache) {
73c10d0e5cSAdrian Prantl   SmallVector<DILocation *, 3> InlinedAtLocations;
74c10d0e5cSAdrian Prantl   DILocation *Last = InlinedAt;
75c10d0e5cSAdrian Prantl   DILocation *CurInlinedAt = DL;
76c10d0e5cSAdrian Prantl 
77c10d0e5cSAdrian Prantl   // Gather all the inlined-at nodes.
78c10d0e5cSAdrian Prantl   while (DILocation *IA = CurInlinedAt->getInlinedAt()) {
79c10d0e5cSAdrian Prantl     // Skip any we've already built nodes for.
80c10d0e5cSAdrian Prantl     if (auto *Found = Cache[IA]) {
81c10d0e5cSAdrian Prantl       Last = cast<DILocation>(Found);
82c10d0e5cSAdrian Prantl       break;
83c10d0e5cSAdrian Prantl     }
84c10d0e5cSAdrian Prantl 
85c10d0e5cSAdrian Prantl     InlinedAtLocations.push_back(IA);
86c10d0e5cSAdrian Prantl     CurInlinedAt = IA;
87c10d0e5cSAdrian Prantl   }
88c10d0e5cSAdrian Prantl 
89c10d0e5cSAdrian Prantl   // Starting from the top, rebuild the nodes to point to the new inlined-at
90c10d0e5cSAdrian Prantl   // location (then rebuilding the rest of the chain behind it) and update the
91c10d0e5cSAdrian Prantl   // map of already-constructed inlined-at nodes.
92c10d0e5cSAdrian Prantl   for (const DILocation *MD : reverse(InlinedAtLocations))
93c10d0e5cSAdrian Prantl     Cache[MD] = Last = DILocation::getDistinct(
94c10d0e5cSAdrian Prantl         Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last);
95c10d0e5cSAdrian Prantl 
96c10d0e5cSAdrian Prantl   return Last;
97c10d0e5cSAdrian Prantl }
98c10d0e5cSAdrian Prantl 
99615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const100673f4b57SSean Silva LLVM_DUMP_METHOD void DebugLoc::dump() const { print(dbgs()); }
1018c209aa8SMatthias Braun #endif
102ef860a24SChandler Carruth 
print(raw_ostream & OS) const1035bf8fef5SDuncan P. N. Exon Smith void DebugLoc::print(raw_ostream &OS) const {
10486b0db42SDuncan P. N. Exon Smith   if (!Loc)
10586b0db42SDuncan P. N. Exon Smith     return;
10686b0db42SDuncan P. N. Exon Smith 
107da925c0dSZinovy Nis   // Print source line info.
108a9308c49SDuncan P. N. Exon Smith   auto *Scope = cast<DIScope>(getScope());
109b273d06bSDuncan P. N. Exon Smith   OS << Scope->getFilename();
110da925c0dSZinovy Nis   OS << ':' << getLine();
111da925c0dSZinovy Nis   if (getCol() != 0)
112da925c0dSZinovy Nis     OS << ':' << getCol();
11386b0db42SDuncan P. N. Exon Smith 
11486b0db42SDuncan P. N. Exon Smith   if (DebugLoc InlinedAtDL = getInlinedAt()) {
115da925c0dSZinovy Nis     OS << " @[ ";
1165bf8fef5SDuncan P. N. Exon Smith     InlinedAtDL.print(OS);
117da925c0dSZinovy Nis     OS << " ]";
118da925c0dSZinovy Nis   }
119da925c0dSZinovy Nis }
120