10b57cec5SDimitry Andric //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 100b57cec5SDimitry Andric #include "LLVMContextImpl.h" 110b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 120b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h" 130b57cec5SDimitry Andric using namespace llvm; 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric // DebugLoc Implementation 170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 180b57cec5SDimitry Andric DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {} 190b57cec5SDimitry Andric DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {} 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric DILocation *DebugLoc::get() const { 220b57cec5SDimitry Andric return cast_or_null<DILocation>(Loc.get()); 230b57cec5SDimitry Andric } 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric unsigned DebugLoc::getLine() const { 260b57cec5SDimitry Andric assert(get() && "Expected valid DebugLoc"); 270b57cec5SDimitry Andric return get()->getLine(); 280b57cec5SDimitry Andric } 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric unsigned DebugLoc::getCol() const { 310b57cec5SDimitry Andric assert(get() && "Expected valid DebugLoc"); 320b57cec5SDimitry Andric return get()->getColumn(); 330b57cec5SDimitry Andric } 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric MDNode *DebugLoc::getScope() const { 360b57cec5SDimitry Andric assert(get() && "Expected valid DebugLoc"); 370b57cec5SDimitry Andric return get()->getScope(); 380b57cec5SDimitry Andric } 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric DILocation *DebugLoc::getInlinedAt() const { 410b57cec5SDimitry Andric assert(get() && "Expected valid DebugLoc"); 420b57cec5SDimitry Andric return get()->getInlinedAt(); 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric MDNode *DebugLoc::getInlinedAtScope() const { 460b57cec5SDimitry Andric return cast<DILocation>(Loc)->getInlinedAtScope(); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric DebugLoc DebugLoc::getFnDebugLoc() const { 500b57cec5SDimitry Andric // FIXME: Add a method on \a DILocation that does this work. 510b57cec5SDimitry Andric const MDNode *Scope = getInlinedAtScope(); 520b57cec5SDimitry Andric if (auto *SP = getDISubprogram(Scope)) 53*e8d8bef9SDimitry Andric return DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP); 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric return DebugLoc(); 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric bool DebugLoc::isImplicitCode() const { 590b57cec5SDimitry Andric if (DILocation *Loc = get()) { 600b57cec5SDimitry Andric return Loc->isImplicitCode(); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric return true; 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric void DebugLoc::setImplicitCode(bool ImplicitCode) { 660b57cec5SDimitry Andric if (DILocation *Loc = get()) { 670b57cec5SDimitry Andric Loc->setImplicitCode(ImplicitCode); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 715ffd83dbSDimitry Andric DebugLoc DebugLoc::appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt, 720b57cec5SDimitry Andric LLVMContext &Ctx, 73*e8d8bef9SDimitry Andric DenseMap<const MDNode *, MDNode *> &Cache) { 740b57cec5SDimitry Andric SmallVector<DILocation *, 3> InlinedAtLocations; 750b57cec5SDimitry Andric DILocation *Last = InlinedAt; 760b57cec5SDimitry Andric DILocation *CurInlinedAt = DL; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // Gather all the inlined-at nodes. 790b57cec5SDimitry Andric while (DILocation *IA = CurInlinedAt->getInlinedAt()) { 800b57cec5SDimitry Andric // Skip any we've already built nodes for. 810b57cec5SDimitry Andric if (auto *Found = Cache[IA]) { 820b57cec5SDimitry Andric Last = cast<DILocation>(Found); 830b57cec5SDimitry Andric break; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric InlinedAtLocations.push_back(IA); 870b57cec5SDimitry Andric CurInlinedAt = IA; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric // Starting from the top, rebuild the nodes to point to the new inlined-at 910b57cec5SDimitry Andric // location (then rebuilding the rest of the chain behind it) and update the 920b57cec5SDimitry Andric // map of already-constructed inlined-at nodes. 930b57cec5SDimitry Andric for (const DILocation *MD : reverse(InlinedAtLocations)) 940b57cec5SDimitry Andric Cache[MD] = Last = DILocation::getDistinct( 950b57cec5SDimitry Andric Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last); 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric return Last; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1010b57cec5SDimitry Andric LLVM_DUMP_METHOD void DebugLoc::dump() const { print(dbgs()); } 1020b57cec5SDimitry Andric #endif 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric void DebugLoc::print(raw_ostream &OS) const { 1050b57cec5SDimitry Andric if (!Loc) 1060b57cec5SDimitry Andric return; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric // Print source line info. 1090b57cec5SDimitry Andric auto *Scope = cast<DIScope>(getScope()); 1100b57cec5SDimitry Andric OS << Scope->getFilename(); 1110b57cec5SDimitry Andric OS << ':' << getLine(); 1120b57cec5SDimitry Andric if (getCol() != 0) 1130b57cec5SDimitry Andric OS << ':' << getCol(); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric if (DebugLoc InlinedAtDL = getInlinedAt()) { 1160b57cec5SDimitry Andric OS << " @[ "; 1170b57cec5SDimitry Andric InlinedAtDL.print(OS); 1180b57cec5SDimitry Andric OS << " ]"; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric } 121