xref: /freebsd/contrib/llvm-project/llvm/lib/IR/DebugLoc.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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