Skip to content

Commit f3dc358

Browse files
authored
[MC] output inlined-at debug info (llvm#106230)
Currently MC print source location of instructions in comments in assembly when debug info is available, however, it does not include inlined-at locations when a function is inlined. For example, function foo is defined in header file a.h and is called multiple times in b.cpp. If foo is inlined, current assembly will only show its instructions with their line numbers in a.h. With inlined-at locations, the assembly will also show where foo is called in b.cpp. This patch adds inlined-at locations to the comments by using DebugLoc::print. It makes the printed source location info consistent with those printed by machine passes.
1 parent 2674034 commit f3dc358

File tree

10 files changed

+104
-25
lines changed

10 files changed

+104
-25
lines changed

llvm/include/llvm/MC/MCObjectStreamer.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ class MCObjectStreamer : public MCStreamer {
141141
SMLoc Loc) override;
142142
void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
143143
unsigned Flags, unsigned Isa,
144-
unsigned Discriminator,
145-
StringRef FileName) override;
144+
unsigned Discriminator, StringRef FileName,
145+
StringRef Comment = {}) override;
146146
void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel,
147147
const MCSymbol *Label,
148148
unsigned PointerSize) override;

llvm/include/llvm/MC/MCStreamer.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,8 @@ class MCStreamer {
887887
virtual void emitDwarfLocDirective(unsigned FileNo, unsigned Line,
888888
unsigned Column, unsigned Flags,
889889
unsigned Isa, unsigned Discriminator,
890-
StringRef FileName);
890+
StringRef FileName,
891+
StringRef Comment = {});
891892

892893
/// This implements the '.loc_label Name' directive.
893894
virtual void emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name);

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

+15-8
Original file line numberDiff line numberDiff line change
@@ -2057,6 +2057,14 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
20572057
}
20582058
}
20592059

2060+
auto RecordSourceLine = [&](auto &DL, auto Flags) {
2061+
SmallString<128> LocationString;
2062+
raw_svector_ostream OS(LocationString);
2063+
DL.print(OS);
2064+
2065+
const MDNode *Scope = DL.getScope();
2066+
recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags, LocationString);
2067+
};
20602068
// When we emit a line-0 record, we don't update PrevInstLoc; so look at
20612069
// the last line number actually emitted, to see if it was line 0.
20622070
unsigned LastAsmLine =
@@ -2084,8 +2092,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
20842092
// But we might be coming back to it after a line 0 record.
20852093
if ((LastAsmLine == 0 && DL.getLine() != 0) || Flags) {
20862094
// Reinstate the source location but not marked as a statement.
2087-
const MDNode *Scope = DL.getScope();
2088-
recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
2095+
RecordSourceLine(DL, Flags);
20892096
}
20902097
return;
20912098
}
@@ -2136,8 +2143,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
21362143
if (DL.getLine() && (DL.getLine() != OldLine || ForceIsStmt))
21372144
Flags |= DWARF2_FLAG_IS_STMT;
21382145

2139-
const MDNode *Scope = DL.getScope();
2140-
recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
2146+
RecordSourceLine(DL, Flags);
21412147

21422148
// If we're not at line 0, remember this location.
21432149
if (DL.getLine())
@@ -2272,7 +2278,8 @@ findPrologueEndLoc(const MachineFunction *MF) {
22722278
static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col,
22732279
const MDNode *S, unsigned Flags, unsigned CUID,
22742280
uint16_t DwarfVersion,
2275-
ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs) {
2281+
ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs,
2282+
StringRef Comment = {}) {
22762283
StringRef Fn;
22772284
unsigned FileNo = 1;
22782285
unsigned Discriminator = 0;
@@ -2286,7 +2293,7 @@ static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col,
22862293
.getOrCreateSourceID(Scope->getFile());
22872294
}
22882295
Asm.OutStreamer->emitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
2289-
Discriminator, Fn);
2296+
Discriminator, Fn, Comment);
22902297
}
22912298

22922299
const MachineInstr *
@@ -2617,10 +2624,10 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
26172624
// Register a source line with debug info. Returns the unique label that was
26182625
// emitted and which provides correspondence to the source line list.
26192626
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
2620-
unsigned Flags) {
2627+
unsigned Flags, StringRef Location) {
26212628
::recordSourceLine(*Asm, Line, Col, S, Flags,
26222629
Asm->OutStreamer->getContext().getDwarfCompileUnitID(),
2623-
getDwarfVersion(), getUnits());
2630+
getDwarfVersion(), getUnits(), Location);
26242631
}
26252632

26262633
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ class DwarfDebug : public DebugHandlerBase {
679679
/// label that was emitted and which provides correspondence to the
680680
/// source line list.
681681
void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope,
682-
unsigned Flags);
682+
unsigned Flags, StringRef Location = {});
683683

684684
/// Populate LexicalScope entries with variables' info.
685685
void collectEntityInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP,

llvm/lib/MC/MCAsmStreamer.cpp

+11-7
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,8 @@ class MCAsmStreamer final : public MCStreamer {
294294
unsigned CUID = 0) override;
295295
void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
296296
unsigned Flags, unsigned Isa,
297-
unsigned Discriminator,
298-
StringRef FileName) override;
297+
unsigned Discriminator, StringRef FileName,
298+
StringRef Location = {}) override;
299299
virtual void emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) override;
300300

301301
MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
@@ -1688,15 +1688,16 @@ void MCAsmStreamer::emitDwarfFile0Directive(
16881688
void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
16891689
unsigned Column, unsigned Flags,
16901690
unsigned Isa, unsigned Discriminator,
1691-
StringRef FileName) {
1691+
StringRef FileName,
1692+
StringRef Comment) {
16921693
// If target doesn't support .loc/.file directive, we need to record the lines
16931694
// same way like we do in object mode.
16941695
if (MAI->isAIX()) {
16951696
// In case we see two .loc directives in a row, make sure the
16961697
// first one gets a line entry.
16971698
MCDwarfLineEntry::make(this, getCurrentSectionOnly());
16981699
this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1699-
Discriminator, FileName);
1700+
Discriminator, FileName, Comment);
17001701
return;
17011702
}
17021703

@@ -1727,12 +1728,15 @@ void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
17271728

17281729
if (IsVerboseAsm) {
17291730
OS.PadToColumn(MAI->getCommentColumn());
1730-
OS << MAI->getCommentString() << ' ' << FileName << ':'
1731-
<< Line << ':' << Column;
1731+
OS << MAI->getCommentString() << ' ';
1732+
if (Comment.empty())
1733+
OS << FileName << ':' << Line << ':' << Column;
1734+
else
1735+
OS << Comment;
17321736
}
17331737
EmitEOL();
17341738
this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1735-
Discriminator, FileName);
1739+
Discriminator, FileName, Comment);
17361740
}
17371741

17381742
void MCAsmStreamer::emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) {

llvm/lib/MC/MCObjectStreamer.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -418,13 +418,14 @@ void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
418418
unsigned Column, unsigned Flags,
419419
unsigned Isa,
420420
unsigned Discriminator,
421-
StringRef FileName) {
421+
StringRef FileName,
422+
StringRef Comment) {
422423
// In case we see two .loc directives in a row, make sure the
423424
// first one gets a line entry.
424425
MCDwarfLineEntry::make(this, getCurrentSectionOnly());
425426

426427
this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
427-
Discriminator, FileName);
428+
Discriminator, FileName, Comment);
428429
}
429430

430431
static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,

llvm/lib/MC/MCStreamer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ void MCStreamer::emitCFIMTETaggedFrame() {
238238
void MCStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
239239
unsigned Column, unsigned Flags,
240240
unsigned Isa, unsigned Discriminator,
241-
StringRef FileName) {
241+
StringRef FileName, StringRef Comment) {
242242
getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa,
243243
Discriminator);
244244
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
2+
; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx908 < %s | FileCheck %s
3+
4+
define amdgpu_kernel void @_Z3fooPiiii(ptr addrspace(1) nocapture noundef writeonly %c.coerce, i32 noundef %a, i32 noundef %b, i32 noundef %d) !dbg !9 {
5+
; CHECK-LABEL: _Z3fooPiiii:
6+
; CHECK: .Lfunc_begin0:
7+
; CHECK-NEXT: .file 0 "test" "a.hip" md5 0x004a28df8cfd98cdd2c71d5d814d9c6b
8+
; CHECK-NEXT: .cfi_sections .debug_frame
9+
; CHECK-NEXT: .cfi_startproc
10+
; CHECK-NEXT: ; %bb.0: ; %entry
11+
; CHECK-NEXT: .file 1 "." "a.h"
12+
; CHECK-NEXT: .loc 1 5 12 prologue_end ; ./a.h:5:12 @[ a.hip:12:8 ]
13+
; CHECK-NEXT: s_load_dwordx4 s[0:3], s[8:9], 0x8
14+
; CHECK-NEXT: s_load_dwordx2 s[4:5], s[8:9], 0x0
15+
; CHECK-NEXT: v_mov_b32_e32 v0, 0
16+
; CHECK-NEXT: s_waitcnt lgkmcnt(0)
17+
; CHECK-NEXT: s_add_i32 s1, s1, s0
18+
; CHECK-NEXT: .Ltmp0:
19+
; CHECK-NEXT: .loc 1 5 12 is_stmt 0 ; ./a.h:5:12 @[ a.hip:13:9 ]
20+
; CHECK-NEXT: s_add_i32 s0, s2, s0
21+
; CHECK-NEXT: .Ltmp1:
22+
; CHECK-NEXT: .file 2 "a.hip"
23+
; CHECK-NEXT: .loc 2 13 6 is_stmt 1 ; a.hip:13:6
24+
; CHECK-NEXT: s_mul_i32 s0, s0, s1
25+
; CHECK-NEXT: v_mov_b32_e32 v1, s0
26+
; CHECK-NEXT: global_store_dword v0, v1, s[4:5]
27+
; CHECK-NEXT: .loc 2 14 1 ; a.hip:14:1
28+
; CHECK-NEXT: s_endpgm
29+
; CHECK-NEXT: .Ltmp2:
30+
entry:
31+
%add.i = add nsw i32 %b, %a, !dbg !13
32+
%add.i3 = add nsw i32 %d, %a, !dbg !17
33+
%mul = mul nsw i32 %add.i3, %add.i, !dbg !19
34+
store i32 %mul, ptr addrspace(1) %c.coerce, align 4, !dbg !19, !tbaa !20
35+
ret void, !dbg !24
36+
}
37+
38+
!llvm.dbg.cu = !{!0}
39+
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7}
40+
!llvm.ident = !{!8}
41+
42+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 20.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None)
43+
!1 = !DIFile(filename: "a.hip", directory: "test", checksumkind: CSK_MD5, checksum: "004a28df8cfd98cdd2c71d5d814d9c6b")
44+
!2 = !{i32 1, !"amdhsa_code_object_version", i32 500}
45+
!3 = !{i32 1, !"amdgpu_printf_kind", !"hostcall"}
46+
!4 = !{i32 7, !"Dwarf Version", i32 5}
47+
!5 = !{i32 2, !"Debug Info Version", i32 3}
48+
!6 = !{i32 1, !"wchar_size", i32 4}
49+
!7 = !{i32 8, !"PIC Level", i32 2}
50+
!8 = !{!"clang version 20.0.0"}
51+
!9 = distinct !DISubprogram(name: "foo", scope: !10, file: !10, line: 11, type: !11, scopeLine: 11, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
52+
!10 = !DIFile(filename: "a.hip", directory: "test")
53+
!11 = !DISubroutineType(types: !12)
54+
!12 = !{}
55+
!13 = !DILocation(line: 5, column: 12, scope: !14, inlinedAt: !16)
56+
!14 = distinct !DISubprogram(name: "bar", scope: !15, file: !15, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
57+
!15 = !DIFile(filename: "./a.h", directory: "test")
58+
!16 = distinct !DILocation(line: 12, column: 8, scope: !9)
59+
!17 = !DILocation(line: 5, column: 12, scope: !14, inlinedAt: !18)
60+
!18 = distinct !DILocation(line: 13, column: 9, scope: !9)
61+
!19 = !DILocation(line: 13, column: 6, scope: !9)
62+
!20 = !{!21, !21, i64 0}
63+
!21 = !{!"int", !22, i64 0}
64+
!22 = !{!"omnipotent char", !23, i64 0}
65+
!23 = !{!"Simple C++ TBAA"}
66+
!24 = !DILocation(line: 14, column: 1, scope: !9)

llvm/test/CodeGen/XCore/dwarf_debug.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
; CHECK-LABEL: f
77
; CHECK: entsp [[S:[0-9]+]]
88
; ...the prologue...
9-
; CHECK: .loc 1 2 0 prologue_end # test.c:2:0
9+
; CHECK: .loc 1 2 0 prologue_end # test.c:2
1010
; CHECK: add r0, r0, 1
1111
; CHECK: retsp [[S]]
1212
define i32 @f(i32 %a) !dbg !4 {

llvm/test/DebugInfo/X86/inline-seldag-test.ll

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
; Make sure the condition test is attributed to the inline function, not the
1919
; location of the test's operands within the caller.
2020

21-
; ASM: # inline-seldag-test.c:2:0
22-
; ASM-NOT: .loc
21+
; ASM: # inline-seldag-test.c:4:0
22+
; ASM: .loc 1 2 0 # inline-seldag-test.c:2 @[ inline-seldag-test.c:6:7 ]
2323
; ASM: testl
2424

2525
; Function Attrs: nounwind uwtable

0 commit comments

Comments
 (0)