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

Jeremy Morse via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 8 08:27:01 PST 2025


================
@@ -0,0 +1,166 @@
+//===-- 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;
----------------
jmorse wrote:

If we re-encounter an identical DILocation while heading up the inlinedAt chain, I'd argue this is an illegal IR input because it forms a cycle. There are a fair few places in LLVM that will infinitely loop when handed such an input too, but if it's to be caught anywhere, it's in the verifier.

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


More information about the llvm-commits mailing list