1139f7f9bSDimitry Andric //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
2139f7f9bSDimitry Andric //
3139f7f9bSDimitry Andric // The LLVM Compiler Infrastructure
4139f7f9bSDimitry Andric //
5139f7f9bSDimitry Andric // This file is distributed under the University of Illinois Open Source
6139f7f9bSDimitry Andric // License. See LICENSE.TXT for details.
7139f7f9bSDimitry Andric //
8139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
9139f7f9bSDimitry Andric
1091bc56edSDimitry Andric #include "llvm/IR/DebugLoc.h"
11139f7f9bSDimitry Andric #include "LLVMContextImpl.h"
124ba319b5SDimitry Andric #include "llvm/Config/llvm-config.h"
1391bc56edSDimitry Andric #include "llvm/IR/DebugInfo.h"
14139f7f9bSDimitry Andric using namespace llvm;
15139f7f9bSDimitry Andric
16139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
17139f7f9bSDimitry Andric // DebugLoc Implementation
18139f7f9bSDimitry Andric //===----------------------------------------------------------------------===//
DebugLoc(const DILocation * L)19ff0cc061SDimitry Andric DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {}
DebugLoc(const MDNode * L)20ff0cc061SDimitry Andric DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {}
21139f7f9bSDimitry Andric
get() const22ff0cc061SDimitry Andric DILocation *DebugLoc::get() const {
23ff0cc061SDimitry Andric return cast_or_null<DILocation>(Loc.get());
24139f7f9bSDimitry Andric }
25139f7f9bSDimitry Andric
getLine() const26ff0cc061SDimitry Andric unsigned DebugLoc::getLine() const {
27ff0cc061SDimitry Andric assert(get() && "Expected valid DebugLoc");
28ff0cc061SDimitry Andric return get()->getLine();
29139f7f9bSDimitry Andric }
30139f7f9bSDimitry Andric
getCol() const31ff0cc061SDimitry Andric unsigned DebugLoc::getCol() const {
32ff0cc061SDimitry Andric assert(get() && "Expected valid DebugLoc");
33ff0cc061SDimitry Andric return get()->getColumn();
34ff0cc061SDimitry Andric }
35ff0cc061SDimitry Andric
getScope() const36ff0cc061SDimitry Andric MDNode *DebugLoc::getScope() const {
37ff0cc061SDimitry Andric assert(get() && "Expected valid DebugLoc");
38ff0cc061SDimitry Andric return get()->getScope();
39ff0cc061SDimitry Andric }
40ff0cc061SDimitry Andric
getInlinedAt() const41ff0cc061SDimitry Andric DILocation *DebugLoc::getInlinedAt() const {
42ff0cc061SDimitry Andric assert(get() && "Expected valid DebugLoc");
43ff0cc061SDimitry Andric return get()->getInlinedAt();
44ff0cc061SDimitry Andric }
45ff0cc061SDimitry Andric
getInlinedAtScope() const46ff0cc061SDimitry Andric MDNode *DebugLoc::getInlinedAtScope() const {
47ff0cc061SDimitry Andric return cast<DILocation>(Loc)->getInlinedAtScope();
48139f7f9bSDimitry Andric }
49139f7f9bSDimitry Andric
getFnDebugLoc() const5039d628a0SDimitry Andric DebugLoc DebugLoc::getFnDebugLoc() const {
51ff0cc061SDimitry Andric // FIXME: Add a method on \a DILocation that does this work.
52ff0cc061SDimitry Andric const MDNode *Scope = getInlinedAtScope();
53ff0cc061SDimitry Andric if (auto *SP = getDISubprogram(Scope))
54ff0cc061SDimitry Andric return DebugLoc::get(SP->getScopeLine(), 0, SP);
5591bc56edSDimitry Andric
5691bc56edSDimitry Andric return DebugLoc();
5791bc56edSDimitry Andric }
58139f7f9bSDimitry Andric
isImplicitCode() const59*b5893f02SDimitry Andric bool DebugLoc::isImplicitCode() const {
60*b5893f02SDimitry Andric if (DILocation *Loc = get()) {
61*b5893f02SDimitry Andric return Loc->isImplicitCode();
62*b5893f02SDimitry Andric }
63*b5893f02SDimitry Andric return true;
64*b5893f02SDimitry Andric }
65*b5893f02SDimitry Andric
setImplicitCode(bool ImplicitCode)66*b5893f02SDimitry Andric void DebugLoc::setImplicitCode(bool ImplicitCode) {
67*b5893f02SDimitry Andric if (DILocation *Loc = get()) {
68*b5893f02SDimitry Andric Loc->setImplicitCode(ImplicitCode);
69*b5893f02SDimitry Andric }
70*b5893f02SDimitry Andric }
71*b5893f02SDimitry Andric
get(unsigned Line,unsigned Col,const MDNode * Scope,const MDNode * InlinedAt,bool ImplicitCode)72ff0cc061SDimitry Andric DebugLoc DebugLoc::get(unsigned Line, unsigned Col, const MDNode *Scope,
73*b5893f02SDimitry Andric const MDNode *InlinedAt, bool ImplicitCode) {
74139f7f9bSDimitry Andric // If no scope is available, this is an unknown location.
7539d628a0SDimitry Andric if (!Scope)
7639d628a0SDimitry Andric return DebugLoc();
77139f7f9bSDimitry Andric
78ff0cc061SDimitry Andric return DILocation::get(Scope->getContext(), Line, Col,
79ff0cc061SDimitry Andric const_cast<MDNode *>(Scope),
80*b5893f02SDimitry Andric const_cast<MDNode *>(InlinedAt), ImplicitCode);
81139f7f9bSDimitry Andric }
82139f7f9bSDimitry Andric
appendInlinedAt(DebugLoc DL,DILocation * InlinedAt,LLVMContext & Ctx,DenseMap<const MDNode *,MDNode * > & Cache,bool ReplaceLast)835517e702SDimitry Andric DebugLoc DebugLoc::appendInlinedAt(DebugLoc DL, DILocation *InlinedAt,
845517e702SDimitry Andric LLVMContext &Ctx,
855517e702SDimitry Andric DenseMap<const MDNode *, MDNode *> &Cache,
865517e702SDimitry Andric bool ReplaceLast) {
875517e702SDimitry Andric SmallVector<DILocation *, 3> InlinedAtLocations;
885517e702SDimitry Andric DILocation *Last = InlinedAt;
895517e702SDimitry Andric DILocation *CurInlinedAt = DL;
905517e702SDimitry Andric
915517e702SDimitry Andric // Gather all the inlined-at nodes.
925517e702SDimitry Andric while (DILocation *IA = CurInlinedAt->getInlinedAt()) {
935517e702SDimitry Andric // Skip any we've already built nodes for.
945517e702SDimitry Andric if (auto *Found = Cache[IA]) {
955517e702SDimitry Andric Last = cast<DILocation>(Found);
965517e702SDimitry Andric break;
975517e702SDimitry Andric }
985517e702SDimitry Andric
995517e702SDimitry Andric if (ReplaceLast && !IA->getInlinedAt())
1005517e702SDimitry Andric break;
1015517e702SDimitry Andric InlinedAtLocations.push_back(IA);
1025517e702SDimitry Andric CurInlinedAt = IA;
1035517e702SDimitry Andric }
1045517e702SDimitry Andric
1055517e702SDimitry Andric // Starting from the top, rebuild the nodes to point to the new inlined-at
1065517e702SDimitry Andric // location (then rebuilding the rest of the chain behind it) and update the
1075517e702SDimitry Andric // map of already-constructed inlined-at nodes.
1085517e702SDimitry Andric for (const DILocation *MD : reverse(InlinedAtLocations))
1095517e702SDimitry Andric Cache[MD] = Last = DILocation::getDistinct(
1105517e702SDimitry Andric Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last);
1115517e702SDimitry Andric
1125517e702SDimitry Andric return Last;
1135517e702SDimitry Andric }
1145517e702SDimitry Andric
1157a7e6055SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1164ba319b5SDimitry Andric LLVM_DUMP_METHOD void DebugLoc::dump() const { print(dbgs()); }
1177a7e6055SDimitry Andric #endif
118139f7f9bSDimitry Andric
print(raw_ostream & OS) const11939d628a0SDimitry Andric void DebugLoc::print(raw_ostream &OS) const {
120ff0cc061SDimitry Andric if (!Loc)
121ff0cc061SDimitry Andric return;
122ff0cc061SDimitry Andric
12391bc56edSDimitry Andric // Print source line info.
124ff0cc061SDimitry Andric auto *Scope = cast<DIScope>(getScope());
125ff0cc061SDimitry Andric OS << Scope->getFilename();
12691bc56edSDimitry Andric OS << ':' << getLine();
12791bc56edSDimitry Andric if (getCol() != 0)
12891bc56edSDimitry Andric OS << ':' << getCol();
129ff0cc061SDimitry Andric
130ff0cc061SDimitry Andric if (DebugLoc InlinedAtDL = getInlinedAt()) {
13191bc56edSDimitry Andric OS << " @[ ";
13239d628a0SDimitry Andric InlinedAtDL.print(OS);
13391bc56edSDimitry Andric OS << " ]";
13491bc56edSDimitry Andric }
13591bc56edSDimitry Andric }
136