[llvm] [CodeView] Generate debug info for artificial subprograms (PR #196327)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 7 07:32:23 PDT 2026


https://github.com/serge-sans-paille created https://github.com/llvm/llvm-project/pull/196327

Based on https://clang.llvm.org/docs/AttributeReference.html#artificial, Artificial subprograms are not required to have a non-zero line number location, so don't ignore them.

Fix #195768

>From 5a32d0ea4f109ea13451159eef3000974701d78e Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Thu, 7 May 2026 16:14:23 +0200
Subject: [PATCH] [CodeView] Generate debug info for artificial subprograms

Based on https://clang.llvm.org/docs/AttributeReference.html#artificial,
Artificial subprograms are not required to have a non-zero line number
location, so don't ignore them.

Fix #195768
---
 llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 17 ++++-
 .../DebugInfo/COFF/builtin-verbose-trap.ll    | 64 +++++++++++++++++++
 2 files changed, 78 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/DebugInfo/COFF/builtin-verbose-trap.ll

diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 61d1db5608878..ccec0b5910658 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -3123,12 +3123,23 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
   CurFn = nullptr;
 }
 
-// Usable locations are valid with non-zero line numbers. A line number of zero
-// corresponds to optimized code that doesn't have a distinct source location.
+// Usable locations are valid with non-zero line numbers, or artificial
+// subprograms because they are associated to the corresponding line within the
+// inlined callee.
+//
+// A line number of zero corresponds to optimized code that doesn't have a
+// distinct source location.
+//
 // In this case, we try to use the previous or next source location depending on
 // the context.
 static bool isUsableDebugLoc(DebugLoc DL) {
-  return DL && DL.getLine() != 0;
+  if (!DL)
+    return false;
+  if (DL.getLine() != 0)
+    return true;
+  if (const DILocalScope *Scope = DL->getScope())
+    return Scope->getSubprogram()->isArtificial();
+  return false;
 }
 
 void CodeViewDebug::beginInstruction(const MachineInstr *MI) {
diff --git a/llvm/test/DebugInfo/COFF/builtin-verbose-trap.ll b/llvm/test/DebugInfo/COFF/builtin-verbose-trap.ll
new file mode 100644
index 0000000000000..879328938fe8a
--- /dev/null
+++ b/llvm/test/DebugInfo/COFF/builtin-verbose-trap.ll
@@ -0,0 +1,64 @@
+; RUN: llc < %s -filetype=obj | llvm-readobj - --codeview | FileCheck %s
+
+; Original C++ source:
+; int done() {
+;         __builtin_verbose_trap("STL_FOO", "broken stuff");
+; }
+
+; Make sure the call to clang-trap is annotated, even though the associated
+; debug location as a line number of 0.
+
+; CHECK:        InlineesSym {
+; CHECK-NEXT:     Kind: S_INLINEES (0x1168)
+; CHECK-NEXT:     Inlinees [
+; CHECK-NEXT:       FuncID: __clang_trap_msg$STL_FOO$broken stuff (0x1002)
+; CHECK-NEXT:     ]
+; CHECK-NEXT:   }
+; CHECK-NEXT:   InlineSiteSym {
+; CHECK-NEXT:     Kind: S_INLINESITE (0x114D)
+; CHECK-NEXT:     PtrParent: 0x0
+; CHECK-NEXT:     PtrEnd: 0x0
+; CHECK-NEXT:     Inlinee: __clang_trap_msg$STL_FOO$broken stuff (0x1002)
+; CHECK-NEXT:     BinaryAnnotations [
+; CHECK-NEXT:       ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x1, LineOffset: 0}
+; CHECK-NEXT:       ChangeCodeLength: 0x7
+; CHECK-NEXT:     ]
+; CHECK-NEXT:   }
+
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-pc-windows-msvc18.0.0"
+
+define dso_local i32 @done() !dbg !10 {
+  %1 = alloca i32
+  call void @llvm.trap(), !dbg !14
+  %2 = load i32, ptr %1, align 4
+  ret i32 %2
+}
+
+declare void @llvm.trap()
+
+
+!llvm.dbg.cu = !{!0}
+!llvm.linker.options = !{!2, !3}
+!llvm.module.flags = !{!4, !5, !6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 20.1.8 (taskcluster-cBNpsXlaTmqEnu_aiQ0ElA)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/Users/jrmuizel/bugs/inline", checksumkind: CSK_MD5, checksum: "ebf5ba4ead45cede7df7db37b24dc58d")
+!2 = !{!"/DEFAULTLIB:libcmt.lib"}
+!3 = !{!"/DEFAULTLIB:oldnames.lib"}
+!4 = !{i32 2, !"CodeView", i32 1}
+!5 = !{i32 2, !"Debug Info Version", i32 3}
+!6 = !{i32 1, !"wchar_size", i32 2}
+!7 = !{i32 8, !"PIC Level", i32 2}
+!8 = !{i32 7, !"uwtable", i32 2}
+!9 = !{!"clang version 20.1.8 (taskcluster-cBNpsXlaTmqEnu_aiQ0ElA)"}
+!10 = distinct !DISubprogram(name: "done", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !DILocation(line: 0, scope: !15, inlinedAt: !17)
+!15 = distinct !DISubprogram(name: "__clang_trap_msg$STL_FOO$broken stuff", scope: !1, file: !1, type: !16, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: !0)
+!16 = !DISubroutineType(types: null)
+!17 = !DILocation(line: 2, scope: !10)



More information about the llvm-commits mailing list