Skip to content

Commit 3a87fa7

Browse files
committed
[MC] output inlined-at debug info
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 fc39cc1 commit 3a87fa7

File tree

10 files changed

+104
-25
lines changed

10 files changed

+104
-25
lines changed

llvm/include/llvm/MC/MCObjectStreamer.h

Lines changed: 2 additions & 2 deletions
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 Location = {}) override;
146146
void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel,
147147
const MCSymbol *Label,
148148
unsigned PointerSize) override;

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,8 @@ class MCStreamer {
910910
virtual void emitDwarfLocDirective(unsigned FileNo, unsigned Line,
911911
unsigned Column, unsigned Flags,
912912
unsigned Isa, unsigned Discriminator,
913-
StringRef FileName);
913+
StringRef FileName,
914+
StringRef Location = {});
914915

915916
/// Associate a filename with a specified logical file number, and also
916917
/// specify that file's checksum information. This implements the '.cv_file 4

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2056,6 +2056,14 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
20562056
}
20572057
}
20582058

2059+
auto RecordSourceLine = [&](auto &DL, auto Flags) {
2060+
SmallString<128> LocationString;
2061+
raw_svector_ostream OS(LocationString);
2062+
DL.print(OS);
2063+
2064+
const MDNode *Scope = DL.getScope();
2065+
recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags, LocationString);
2066+
};
20592067
// When we emit a line-0 record, we don't update PrevInstLoc; so look at
20602068
// the last line number actually emitted, to see if it was line 0.
20612069
unsigned LastAsmLine =
@@ -2072,8 +2080,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
20722080
// But we might be coming back to it after a line 0 record.
20732081
if ((LastAsmLine == 0 && DL.getLine() != 0) || Flags) {
20742082
// Reinstate the source location but not marked as a statement.
2075-
const MDNode *Scope = DL.getScope();
2076-
recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
2083+
RecordSourceLine(DL, Flags);
20772084
}
20782085
return;
20792086
}
@@ -2124,8 +2131,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
21242131
if (DL.getLine() && DL.getLine() != OldLine)
21252132
Flags |= DWARF2_FLAG_IS_STMT;
21262133

2127-
const MDNode *Scope = DL.getScope();
2128-
recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
2134+
RecordSourceLine(DL, Flags);
21292135

21302136
// If we're not at line 0, remember this location.
21312137
if (DL.getLine())
@@ -2168,7 +2174,8 @@ static std::pair<DebugLoc, bool> findPrologueEndLoc(const MachineFunction *MF) {
21682174
static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col,
21692175
const MDNode *S, unsigned Flags, unsigned CUID,
21702176
uint16_t DwarfVersion,
2171-
ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs) {
2177+
ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs,
2178+
StringRef Location = {}) {
21722179
StringRef Fn;
21732180
unsigned FileNo = 1;
21742181
unsigned Discriminator = 0;
@@ -2182,7 +2189,7 @@ static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col,
21822189
.getOrCreateSourceID(Scope->getFile());
21832190
}
21842191
Asm.OutStreamer->emitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
2185-
Discriminator, Fn);
2192+
Discriminator, Fn, Location);
21862193
}
21872194

21882195
DebugLoc DwarfDebug::emitInitialLocDirective(const MachineFunction &MF,
@@ -2356,10 +2363,10 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
23562363
// Register a source line with debug info. Returns the unique label that was
23572364
// emitted and which provides correspondence to the source line list.
23582365
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
2359-
unsigned Flags) {
2366+
unsigned Flags, StringRef Location) {
23602367
::recordSourceLine(*Asm, Line, Col, S, Flags,
23612368
Asm->OutStreamer->getContext().getDwarfCompileUnitID(),
2362-
getDwarfVersion(), getUnits());
2369+
getDwarfVersion(), getUnits(), Location);
23632370
}
23642371

23652372
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ class DwarfDebug : public DebugHandlerBase {
677677
/// label that was emitted and which provides correspondence to the
678678
/// source line list.
679679
void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope,
680-
unsigned Flags);
680+
unsigned Flags, StringRef Location = {});
681681

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

llvm/lib/MC/MCAsmStreamer.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,8 @@ class MCAsmStreamer final : public MCStreamer {
299299
unsigned CUID = 0) override;
300300
void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
301301
unsigned Flags, unsigned Isa,
302-
unsigned Discriminator,
303-
StringRef FileName) override;
302+
unsigned Discriminator, StringRef FileName,
303+
StringRef Location = {}) override;
304304
MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
305305

306306
bool emitCVFileDirective(unsigned FileNo, StringRef Filename,
@@ -1720,15 +1720,16 @@ void MCAsmStreamer::emitDwarfFile0Directive(
17201720
void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
17211721
unsigned Column, unsigned Flags,
17221722
unsigned Isa, unsigned Discriminator,
1723-
StringRef FileName) {
1723+
StringRef FileName,
1724+
StringRef Location) {
17241725
// If target doesn't support .loc/.file directive, we need to record the lines
17251726
// same way like we do in object mode.
17261727
if (!MAI->usesDwarfFileAndLocDirectives()) {
17271728
// In case we see two .loc directives in a row, make sure the
17281729
// first one gets a line entry.
17291730
MCDwarfLineEntry::make(this, getCurrentSectionOnly());
17301731
this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1731-
Discriminator, FileName);
1732+
Discriminator, FileName, Location);
17321733
return;
17331734
}
17341735

@@ -1759,12 +1760,15 @@ void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
17591760

17601761
if (IsVerboseAsm) {
17611762
OS.PadToColumn(MAI->getCommentColumn());
1762-
OS << MAI->getCommentString() << ' ' << FileName << ':'
1763-
<< Line << ':' << Column;
1763+
OS << MAI->getCommentString() << ' ';
1764+
if (Location.empty())
1765+
OS << FileName << ':' << Line << ':' << Column;
1766+
else
1767+
OS << Location;
17641768
}
17651769
EmitEOL();
17661770
this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1767-
Discriminator, FileName);
1771+
Discriminator, FileName, Location);
17681772
}
17691773

17701774
MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {

llvm/lib/MC/MCObjectStreamer.cpp

Lines changed: 3 additions & 2 deletions
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 Location) {
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, Location);
428429
}
429430

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

llvm/lib/MC/MCStreamer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ void MCStreamer::emitCFIMTETaggedFrame() {
262262
void MCStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
263263
unsigned Column, unsigned Flags,
264264
unsigned Isa, unsigned Discriminator,
265-
StringRef FileName) {
265+
StringRef FileName, StringRef Location) {
266266
getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa,
267267
Discriminator);
268268
}
Lines changed: 66 additions & 0 deletions
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
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[6:7], 0x8
14+
; CHECK-NEXT: s_load_dwordx2 s[4:5], s[6:7], 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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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)