[llvm] [DebugInfo][NVPTX] Adding support for `inlined_at` debug directive in NVPTX backend (PR #170239)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 1 18:05:29 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-nvptx

Author: Laxman Sole (laxmansole)

<details>
<summary>Changes</summary>

This change adds support for emitting the enhanced PTX debugging directives `function_name` and `inlined_at` as part of the `.loc` directive in the NVPTX backend.

`.loc` syntax - 
>.loc file_index line_number column_position

`.loc` syntax with `inlined_at` attribute - 
>.loc file_index line_number column_position,function_name label {+ immediate }, inlined_at file_index2 line_number2 column_position2

`inlined_at` attribute specified as part of the `.loc` directive indicates PTX instructions that are generated from a function that got inlined. It specifies the source location at which the specified function is inlined. `file_index2`, `line_number2`, and `column_position2` specify the location at which the function is inlined.

The `function_name` attribute specifies an offset in the DWARF section- `.debug_str`. Offset is specified as a label expression or a label + immediate expression, where label is defined in the `.debug_str` section. DWARF section `.debug_str` contains ASCII null-terminated strings that specify the name of the function that is inlined.

These attributes were introduced in PTX ISA version 7.2 (see NVIDIA’s documentation: https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#debugging-directives-loc ).

To support these features, the PR introduces a new NVPTXDwarfDebug class derived from DwarfDebug, which implements NVPTX-specific logic for emitting these directives. The base DwarfDebug infrastructure is extended with new virtual hooks (beginFunctionHook() and recordSourceLineHook()) that enable the NVPTX backend to generate this additional debug information.

The MC layer is also updated to emit the NVPTX-specific `.loc` attributes (function_name and inlined_at). The implementation applies to PTX ISA 7.2 and later when the debug-info emission kind is either lineTableOnly or DebugDirectiveOnly. A new command-line option, `--line-info-inlined-at=<true/false>`, is added to control whether the inlined_at attribute is generated.

Note - The `NVCC` compiler already emits the `.loc` directive with `inlined_at` when compiled with `-lineinfo` option. 

---

Patch is 99.82 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170239.diff


19 Files Affected:

- (modified) llvm/include/llvm/CodeGen/AsmPrinter.h (+4) 
- (modified) llvm/include/llvm/MC/MCStreamer.h (+8) 
- (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+3-1) 
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (+18-1) 
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h (+14-7) 
- (modified) llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp (+5-2) 
- (modified) llvm/lib/MC/MCAsmStreamer.cpp (+90-33) 
- (modified) llvm/lib/Target/NVPTX/CMakeLists.txt (+1) 
- (modified) llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp (+5) 
- (modified) llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h (+3) 
- (added) llvm/lib/Target/NVPTX/NVPTXDwarfDebug.cpp (+165) 
- (added) llvm/lib/Target/NVPTX/NVPTXDwarfDebug.h (+52) 
- (added) llvm/test/DebugInfo/NVPTX/inlinedAt_1.ll (+144) 
- (added) llvm/test/DebugInfo/NVPTX/inlinedAt_2.ll (+85) 
- (added) llvm/test/DebugInfo/NVPTX/inlinedAt_3.ll (+305) 
- (added) llvm/test/DebugInfo/NVPTX/inlinedAt_4.ll (+229) 
- (added) llvm/test/DebugInfo/NVPTX/inlinedAt_5.ll (+208) 
- (added) llvm/test/DebugInfo/NVPTX/inlinedAt_6.ll (+343) 
- (added) llvm/test/DebugInfo/NVPTX/inlinedAt_7.ll (+118) 


``````````diff
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 311f7df98cf8c..d01d93750e806 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -277,6 +277,10 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
   AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer,
              char &ID = AsmPrinter::ID);
 
+  /// Create the DwarfDebug handler. Targets can override this to provide
+  /// custom debug information handling.
+  virtual DwarfDebug *createDwarfDebug();
+
 public:
   ~AsmPrinter() override;
 
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 79c715e3820a6..6fe858c3201eb 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -902,6 +902,14 @@ class LLVM_ABI MCStreamer {
                                      StringRef FileName,
                                      StringRef Comment = {});
 
+  /// This is same as emitDwarfLocDirective, except has capability to
+  /// add inlined_at information.
+  virtual void emitDwarfLocDirectiveWithInlinedAt(
+      unsigned FileNo, unsigned Line, unsigned Column, unsigned FileIA,
+      unsigned LineIA, unsigned ColumnIA, const MCSymbol *Sym, unsigned Flags,
+      unsigned Isa, unsigned Discriminator, StringRef FileName,
+      StringRef Comment = {}) {}
+
   /// This implements the '.loc_label Name' directive.
   virtual void emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name);
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 3aa245b7f3f1e..1a0a0cfd8f6ac 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -470,6 +470,8 @@ const MCSection *AsmPrinter::getCurrentSection() const {
   return OutStreamer->getCurrentSectionOnly();
 }
 
+DwarfDebug *AsmPrinter::createDwarfDebug() { return new DwarfDebug(this); }
+
 void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesAll();
   MachineFunctionPass::getAnalysisUsage(AU);
@@ -592,7 +594,7 @@ bool AsmPrinter::doInitialization(Module &M) {
       Handlers.push_back(std::make_unique<CodeViewDebug>(this));
     if (!EmitCodeView || M.getDwarfVersion()) {
       if (hasDebugInfo()) {
-        DD = new DwarfDebug(this);
+        DD = createDwarfDebug();
         Handlers.push_back(std::unique_ptr<DwarfDebug>(DD));
       }
     }
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 40bfea059c707..3fd60d70cfb68 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -2204,13 +2204,27 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
       Flags |= DWARF2_FLAG_IS_STMT;
   }
 
-  RecordSourceLine(DL, Flags);
+  // Call the hook that allows targets to customize source line recording
+  recordSourceLineHook(*MI, DL, Flags);
 
   // If we're not at line 0, remember this location.
   if (DL.getLine())
     PrevInstLoc = DL;
 }
 
+// Default implementation of target-specific hook for custom source line
+// recording
+void DwarfDebug::recordSourceLineHook(const MachineInstr &MI,
+                                      const DebugLoc &DL, unsigned Flags) {
+  SmallString<128> LocationString;
+  if (Asm->OutStreamer->isVerboseAsm()) {
+    raw_svector_ostream OS(LocationString);
+    DL.print(OS);
+  }
+  recordSourceLine(DL.getLine(), DL.getCol(), DL.getScope(), Flags,
+                   LocationString);
+}
+
 // Returns the position where we should place prologue_end, potentially nullptr,
 // which means "no good place to put prologue_end". Returns true in the second
 // return value if there are no setup instructions in this function at all,
@@ -2705,6 +2719,9 @@ void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) {
   Asm->OutStreamer->getContext().setDwarfCompileUnitID(
       getDwarfCompileUnitIDForLineTable(CU));
 
+  // Call target-specific hook for custom initialization
+  beginFunctionHook(*MF);
+
   // Record beginning of function.
   PrologEndLoc = emitInitialLocDirective(
       *MF, Asm->OutStreamer->getContext().getDwarfCompileUnitID());
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 1a1b28a6fc035..58aeb09645984 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -394,9 +394,6 @@ class DwarfDebug : public DebugHandlerBase {
   /// table for the same directory as DW_AT_comp_dir.
   StringRef CompilationDir;
 
-  /// Holder for the file specific debug information.
-  DwarfFile InfoHolder;
-
   /// Holders for the various debug information flags that we might need to
   /// have exposed. See accessor functions below for description.
 
@@ -532,10 +529,6 @@ class DwarfDebug : public DebugHandlerBase {
 
   MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &);
 
-  const SmallVectorImpl<std::unique_ptr<DwarfCompileUnit>> &getUnits() {
-    return InfoHolder.getUnits();
-  }
-
   using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
 
   void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
@@ -711,6 +704,8 @@ class DwarfDebug : public DebugHandlerBase {
   void computeKeyInstructions(const MachineFunction *MF);
 
 protected:
+  /// Holder for the file specific debug information.
+  DwarfFile InfoHolder;
   /// Gather pre-function debug information.
   void beginFunctionImpl(const MachineFunction *MF) override;
 
@@ -722,6 +717,18 @@ class DwarfDebug : public DebugHandlerBase {
 
   void skippedNonDebugFunction() override;
 
+  /// Target-specific hook for custom initialization,
+  /// default implementation is empty, only being used for NVPTX target
+  virtual void beginFunctionHook(const MachineFunction &MF) {}
+
+  /// Target-specific hook for custom source line recording
+  virtual void recordSourceLineHook(const MachineInstr &MI, const DebugLoc &DL,
+                                    unsigned Flags);
+
+  const SmallVectorImpl<std::unique_ptr<DwarfCompileUnit>> &getUnits() {
+    return InfoHolder.getUnits();
+  }
+
 public:
   //===--------------------------------------------------------------------===//
   // Main entry points.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
index d304c7efe2a75..4ccad65bdba91 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
@@ -96,9 +96,12 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
     if (ShouldCreateSymbols)
       Asm.OutStreamer->emitLabel(Entry->getValue().Symbol);
 
+    // Emit a comment with the string offset and the string itself.
+    Asm.OutStreamer->AddComment(
+        "string offset=" + Twine(Entry->getValue().Offset) + " ; " +
+        StringRef(Entry->getKeyData(), Entry->getKeyLength()));
+
     // Emit the string itself with a terminating null byte.
-    Asm.OutStreamer->AddComment("string offset=" +
-                                Twine(Entry->getValue().Offset));
     Asm.OutStreamer->emitBytes(
         StringRef(Entry->getKeyData(), Entry->getKeyLength() + 1));
   }
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 885fa55b65d50..b46ec73a4b012 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -70,6 +70,17 @@ class MCAsmStreamer final : public MCStreamer {
   void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
   void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
 
+  /// Helper to emit common .loc directive flags, isa, and discriminator
+  void emitDwarfLocDirectiveFlags(unsigned Flags, unsigned Isa,
+                                  unsigned Discriminator);
+
+  /// Helper to emit the common suffix of .loc directives (flags, comment, EOL,
+  /// parent call)
+  void emitDwarfLocDirectiveSuffix(unsigned FileNo, unsigned Line,
+                                   unsigned Column, unsigned Flags,
+                                   unsigned Isa, unsigned Discriminator,
+                                   StringRef FileName, StringRef Comment);
+
 public:
   MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
                 std::unique_ptr<MCInstPrinter> printer,
@@ -297,6 +308,14 @@ class MCAsmStreamer final : public MCStreamer {
                              StringRef Location = {}) override;
   void emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) override;
 
+  void emitDwarfLocDirectiveWithInlinedAt(unsigned FileNo, unsigned Line,
+                                          unsigned Column, unsigned FileIA,
+                                          unsigned LineIA, unsigned ColIA,
+                                          const MCSymbol *Sym, unsigned Flags,
+                                          unsigned Isa, unsigned Discriminator,
+                                          StringRef FileName,
+                                          StringRef Comment = {}) override;
+
   MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
 
   bool emitCVFileDirective(unsigned FileNo, StringRef Filename,
@@ -1675,6 +1694,57 @@ void MCAsmStreamer::emitDwarfFile0Directive(
     emitRawText(OS1.str());
 }
 
+/// Helper to emit common .loc directive flags, isa, and discriminator
+void MCAsmStreamer::emitDwarfLocDirectiveFlags(unsigned Flags, unsigned Isa,
+                                               unsigned Discriminator) {
+  if (!MAI->supportsExtendedDwarfLocDirective())
+    return;
+
+  if (Flags & DWARF2_FLAG_BASIC_BLOCK)
+    OS << " basic_block";
+  if (Flags & DWARF2_FLAG_PROLOGUE_END)
+    OS << " prologue_end";
+  if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
+    OS << " epilogue_begin";
+
+  const unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
+  if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
+    OS << " is_stmt ";
+    OS << ((Flags & DWARF2_FLAG_IS_STMT) ? "1" : "0");
+  }
+
+  if (Isa)
+    OS << " isa " << Isa;
+  if (Discriminator)
+    OS << " discriminator " << Discriminator;
+}
+
+/// Helper to emit the common suffix of .loc directives
+void MCAsmStreamer::emitDwarfLocDirectiveSuffix(unsigned FileNo, unsigned Line,
+                                                unsigned Column, unsigned Flags,
+                                                unsigned Isa,
+                                                unsigned Discriminator,
+                                                StringRef FileName,
+                                                StringRef Comment) {
+  // Emit flags, isa, and discriminator
+  emitDwarfLocDirectiveFlags(Flags, Isa, Discriminator);
+
+  // Emit verbose comment if enabled
+  if (IsVerboseAsm) {
+    OS.PadToColumn(MAI->getCommentColumn());
+    OS << MAI->getCommentString() << ' ';
+    if (Comment.empty())
+      OS << FileName << ':' << Line << ':' << Column;
+    else
+      OS << Comment;
+  }
+
+  // Emit end of line and update parent state
+  EmitEOL();
+  MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
+                                    Discriminator, FileName, Comment);
+}
+
 void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
                                           unsigned Column, unsigned Flags,
                                           unsigned Isa, unsigned Discriminator,
@@ -1691,42 +1761,29 @@ void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
     return;
   }
 
+  // Emit the basic .loc directive
   OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
-  if (MAI->supportsExtendedDwarfLocDirective()) {
-    if (Flags & DWARF2_FLAG_BASIC_BLOCK)
-      OS << " basic_block";
-    if (Flags & DWARF2_FLAG_PROLOGUE_END)
-      OS << " prologue_end";
-    if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
-      OS << " epilogue_begin";
-
-    unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
-    if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
-      OS << " is_stmt ";
-
-      if (Flags & DWARF2_FLAG_IS_STMT)
-        OS << "1";
-      else
-        OS << "0";
-    }
 
-    if (Isa)
-      OS << " isa " << Isa;
-    if (Discriminator)
-      OS << " discriminator " << Discriminator;
-  }
+  // Emit common suffix (flags, comment, EOL, parent call)
+  emitDwarfLocDirectiveSuffix(FileNo, Line, Column, Flags, Isa, Discriminator,
+                              FileName, Comment);
+}
 
-  if (IsVerboseAsm) {
-    OS.PadToColumn(MAI->getCommentColumn());
-    OS << MAI->getCommentString() << ' ';
-    if (Comment.empty())
-      OS << FileName << ':' << Line << ':' << Column;
-    else
-      OS << Comment;
-  }
-  EmitEOL();
-  this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
-                                          Discriminator, FileName, Comment);
+/// This is same as emitDwarfLocDirective, except also emits inlined function
+/// and inlined callsite information.
+void MCAsmStreamer::emitDwarfLocDirectiveWithInlinedAt(
+    unsigned FileNo, unsigned Line, unsigned Column, unsigned FileIA,
+    unsigned LineIA, unsigned ColIA, const MCSymbol *Sym, unsigned Flags,
+    unsigned Isa, unsigned Discriminator, StringRef FileName,
+    StringRef Comment) {
+  // Emit the basic .loc directive with NVPTX-specific extensions
+  OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
+  OS << ", function_name " << *Sym;
+  OS << ", inlined_at " << FileIA << " " << LineIA << " " << ColIA;
+
+  // Emit common suffix (flags, comment, EOL, parent call)
+  emitDwarfLocDirectiveSuffix(FileNo, Line, Column, Flags, Isa, Discriminator,
+                              FileName, Comment);
 }
 
 void MCAsmStreamer::emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) {
diff --git a/llvm/lib/Target/NVPTX/CMakeLists.txt b/llvm/lib/Target/NVPTX/CMakeLists.txt
index f9c24750c4836..b96a674d74e91 100644
--- a/llvm/lib/Target/NVPTX/CMakeLists.txt
+++ b/llvm/lib/Target/NVPTX/CMakeLists.txt
@@ -18,6 +18,7 @@ set(NVPTXCodeGen_sources
   NVPTXAssignValidGlobalNames.cpp
   NVPTXAtomicLower.cpp
   NVPTXCtorDtorLowering.cpp
+  NVPTXDwarfDebug.cpp
   NVPTXForwardParams.cpp
   NVPTXFrameLowering.cpp
   NVPTXGenericToNVVM.cpp
diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
index 9bbb3aad89c44..d5c9988d0eb53 100644
--- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
@@ -17,6 +17,7 @@
 #include "MCTargetDesc/NVPTXMCAsmInfo.h"
 #include "MCTargetDesc/NVPTXTargetStreamer.h"
 #include "NVPTX.h"
+#include "NVPTXDwarfDebug.h"
 #include "NVPTXMCExpr.h"
 #include "NVPTXMachineFunctionInfo.h"
 #include "NVPTXRegisterInfo.h"
@@ -676,6 +677,10 @@ void NVPTXAsmPrinter::emitStartOfAsmFile(Module &M) {
   OutStreamer->emitRawText(OS1.str());
 }
 
+DwarfDebug *NVPTXAsmPrinter::createDwarfDebug() {
+  return new NVPTXDwarfDebug(this);
+}
+
 bool NVPTXAsmPrinter::doInitialization(Module &M) {
   const NVPTXTargetMachine &NTM = static_cast<const NVPTXTargetMachine &>(TM);
   const NVPTXSubtarget &STI = *NTM.getSubtargetImpl();
diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h
index f35931868d99f..20c1bbb9e15b9 100644
--- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h
+++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h
@@ -194,6 +194,9 @@ class LLVM_LIBRARY_VISIBILITY NVPTXAsmPrinter : public AsmPrinter {
   bool doInitialization(Module &M) override;
   bool doFinalization(Module &M) override;
 
+  // Create NVPTX-specific DwarfDebug handler
+  DwarfDebug *createDwarfDebug() override;
+
 private:
   bool GlobalsEmitted;
 
diff --git a/llvm/lib/Target/NVPTX/NVPTXDwarfDebug.cpp b/llvm/lib/Target/NVPTX/NVPTXDwarfDebug.cpp
new file mode 100644
index 0000000000000..57410179a6344
--- /dev/null
+++ b/llvm/lib/Target/NVPTX/NVPTXDwarfDebug.cpp
@@ -0,0 +1,165 @@
+//===-- NVPTXDwarfDebug.cpp - NVPTX DwarfDebug Implementation ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements helper functions for NVPTX-specific debug information
+// processing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NVPTXDwarfDebug.h"
+#include "NVPTXSubtarget.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/Function.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetMachine.h"
+
+using namespace llvm;
+
+// Command line option to control inlined_at enhancement to lineinfo support.
+// Valid only when debuginfo emissionkind is DebugDirectivesOnly or
+// LineTablesOnly.
+static cl::opt<bool> LineInfoWithInlinedAt(
+    "line-info-inlined-at",
+    cl::desc("Emit line with inlined_at enhancement for NVPTX"), cl::init(true),
+    cl::Hidden);
+
+NVPTXDwarfDebug::NVPTXDwarfDebug(AsmPrinter *A) : DwarfDebug(A) {}
+
+// Collect all inlined_at locations for the current function.
+void NVPTXDwarfDebug::collectInlinedAtLocations(const MachineFunction &MF) {
+  const DISubprogram *SP = MF.getFunction().getSubprogram();
+  assert(SP && "expecting valid subprogram here");
+
+  // inlined_at support requires PTX 7.2 or later.
+  const NVPTXSubtarget &STI = MF.getSubtarget<NVPTXSubtarget>();
+  if (STI.getPTXVersion() < 72)
+    return;
+
+  if (!(SP->getUnit()->isDebugDirectivesOnly() ||
+        SP->getUnit()->getEmissionKind() == DICompileUnit::LineTablesOnly) ||
+      !LineInfoWithInlinedAt) // No enhanced lineinfo, we are done.
+    return;
+
+  for (const MachineBasicBlock &MBB : MF) {
+    for (const MachineInstr &MI : MBB) {
+      const DebugLoc &DL = MI.getDebugLoc();
+      if (!DL)
+        continue;
+      const DILocation *InlinedAt = DL.getInlinedAt();
+      while (InlinedAt) {
+        if (!InlinedAtLocs.insert(InlinedAt).second)
+          break;
+        InlinedAt = InlinedAt->getInlinedAt();
+      }
+    }
+  }
+}
+
+// NVPTX-specific source line recording with inlined_at support.
+void NVPTXDwarfDebug::recordSourceLineAndInlinedAt(const MachineInstr &MI,
+                                                   unsigned Flags) {
+  const DebugLoc &DL = MI.getDebugLoc();
+  // Maintain a work list of .loc to be emitted. If we are emitting the
+  // inlined_at directive, we might need to emit additional .loc prior
+  // to it for the location contained in the inlined_at.
+  SmallVector<const DILocation *, 8> WorkList;
+  DenseSet<const DILocation *> WorkListSet;
+  const DILocation *EmitLoc = DL.get();
+
+  const DISubprogram *SP = MI.getMF()->getFunction().getSubprogram();
+  const NVPTXSubtarget &STI = MI.getMF()->getSubtarget<NVPTXSubtarget>();
+  const bool EnhancedLineinfo =
+      LineInfoWithInlinedAt && (STI.getPTXVersion() >= 72) && SP &&
+      (SP->getUnit()->isDebugDirectivesOnly() ||
+       SP->getUnit()->getEmissionKind() == DICompileUnit::LineTablesOnly);
+
+  while (EmitLoc) {
+    // Get the scope for the current location.
+    const DIScope *Scope = EmitLoc->getScope();
+    if (!Scope)
+      break; // scope is null, we are done.
+
+    // Check if this loc is already in work list, if so, we are done.
+    if (WorkListSet.contains(EmitLoc))
+      break;
+
+    // Add this location to the work list.
+    WorkList.push_back(EmitLoc);
+    WorkListSet.insert(EmitLoc);
+
+    if (!EnhancedLineinfo) // No enhanced lineinfo, we are done.
+      break;
+
+    const DILocation *IA = EmitLoc->getInlinedAt();
+    // Check if this has inlined_at information, and if we have not yet
+    // emitted the .loc for the inlined_at location.
+    if (IA && InlinedAtLocs.contains(IA))
+      EmitLoc = IA;
+    else // We are done
+      break;
+  }
+
+  const unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID();
+  // Traverse the work list, and emit .loc.
+  while (!WorkList.empty()) {
+    const DILocation *Current = WorkList.pop_back_val();
+    const DIScope *Sco...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/170239


More information about the llvm-commits mailing list