Skip to content

Commit 87e22bd

Browse files
committed
Allow for mixing source/no-source DIFiles in one CU
The DWARF proposal that the DW_LNCT_LLVM_source extension is based on (https://dwarfstd.org/issues/180201.1.html) allows to mix source and non-source files in the same CU by storing an empty string as a sentinel value. This patch implements this feature. Review in #73877
1 parent 4e724c2 commit 87e22bd

File tree

4 files changed

+59
-21
lines changed

4 files changed

+59
-21
lines changed

llvm/include/llvm/MC/MCDwarf.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ struct MCDwarfLineTableHeader {
265265
StringMap<unsigned> SourceIdMap;
266266
std::string CompilationDir;
267267
MCDwarfFile RootFile;
268-
bool HasSource = false;
268+
bool HasAnySource = false;
269+
269270
private:
270271
bool HasAllMD5 = true;
271272
bool HasAnyMD5 = false;
@@ -305,15 +306,15 @@ struct MCDwarfLineTableHeader {
305306
RootFile.Checksum = Checksum;
306307
RootFile.Source = Source;
307308
trackMD5Usage(Checksum.has_value());
308-
HasSource = Source.has_value();
309+
HasAnySource |= Source.has_value();
309310
}
310311

311312
void resetFileTable() {
312313
MCDwarfDirs.clear();
313314
MCDwarfFiles.clear();
314315
RootFile.Name.clear();
315316
resetMD5Usage();
316-
HasSource = false;
317+
HasAnySource = false;
317318
}
318319

319320
private:
@@ -385,7 +386,7 @@ class MCDwarfLineTable {
385386
Header.RootFile.Checksum = Checksum;
386387
Header.RootFile.Source = Source;
387388
Header.trackMD5Usage(Checksum.has_value());
388-
Header.HasSource = Source.has_value();
389+
Header.HasAnySource |= Source.has_value();
389390
}
390391

391392
void resetFileTable() { Header.resetFileTable(); }

llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,14 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
170170
if (ContentTypes.HasLength)
171171
OS << format(" length: 0x%8.8" PRIx64 "\n", FileEntry.Length);
172172
if (ContentTypes.HasSource) {
173-
OS << " source: ";
174-
FileEntry.Source.dump(OS, DumpOptions);
175-
OS << '\n';
173+
auto Source = FileEntry.Source.getAsCString();
174+
if (!Source)
175+
consumeError(Source.takeError());
176+
else if ((*Source)[0]) {
177+
OS << " source: ";
178+
FileEntry.Source.dump(OS, DumpOptions);
179+
OS << '\n';
180+
}
176181
}
177182
}
178183
}

llvm/lib/MC/MCDwarf.cpp

+9-14
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const {
386386
}
387387

388388
static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
389-
bool EmitMD5, bool HasSource,
389+
bool EmitMD5, bool HasAnySource,
390390
std::optional<MCDwarfLineStr> &LineStr) {
391391
assert(!DwarfFile.Name.empty());
392392
if (LineStr)
@@ -401,7 +401,7 @@ static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
401401
MCOS->emitBinaryData(
402402
StringRef(reinterpret_cast<const char *>(Cksum.data()), Cksum.size()));
403403
}
404-
if (HasSource) {
404+
if (HasAnySource) {
405405
if (LineStr)
406406
LineStr->emitRef(MCOS, DwarfFile.Source.value_or(StringRef()));
407407
else {
@@ -452,7 +452,7 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
452452
uint64_t Entries = 2;
453453
if (HasAllMD5)
454454
Entries += 1;
455-
if (HasSource)
455+
if (HasAnySource)
456456
Entries += 1;
457457
MCOS->emitInt8(Entries);
458458
MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
@@ -464,7 +464,7 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
464464
MCOS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);
465465
MCOS->emitULEB128IntValue(dwarf::DW_FORM_data16);
466466
}
467-
if (HasSource) {
467+
if (HasAnySource) {
468468
MCOS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
469469
MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
470470
: dwarf::DW_FORM_string);
@@ -479,9 +479,9 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
479479
assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) &&
480480
"No root file and no .file directives");
481481
emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,
482-
HasAllMD5, HasSource, LineStr);
482+
HasAllMD5, HasAnySource, LineStr);
483483
for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)
484-
emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasSource, LineStr);
484+
emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasAnySource, LineStr);
485485
}
486486

487487
std::pair<MCSymbol *, MCSymbol *>
@@ -598,7 +598,7 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
598598
// If any files have embedded source, they all must.
599599
if (MCDwarfFiles.empty()) {
600600
trackMD5Usage(Checksum.has_value());
601-
HasSource = (Source != std::nullopt);
601+
HasAnySource |= Source.has_value();
602602
}
603603
if (DwarfVersion >= 5 && isRootFile(RootFile, Directory, FileName, Checksum))
604604
return 0;
@@ -625,11 +625,6 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
625625
return make_error<StringError>("file number already allocated",
626626
inconvertibleErrorCode());
627627

628-
// If any files have embedded source, they all must.
629-
if (HasSource != (Source != std::nullopt))
630-
return make_error<StringError>("inconsistent use of embedded source",
631-
inconvertibleErrorCode());
632-
633628
if (Directory.empty()) {
634629
// Separate the directory part from the basename of the FileName.
635630
StringRef tFileName = sys::path::filename(FileName);
@@ -662,8 +657,8 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
662657
File.Checksum = Checksum;
663658
trackMD5Usage(Checksum.has_value());
664659
File.Source = Source;
665-
if (Source)
666-
HasSource = true;
660+
if (Source.has_value())
661+
HasAnySource = true;
667662

668663
// return the allocated FileNumber.
669664
return FileNumber;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
; RUN: %llc_dwarf -O0 -filetype=obj -o - < %s | llvm-dwarfdump -debug-line - | FileCheck %s
2+
3+
; CHECK: include_directories[ 0] = "dir"
4+
; CHECK-NEXT: file_names[ 0]:
5+
; CHECK-NEXT: name: "foo.c"
6+
; CHECK-NEXT: dir_index: 0
7+
; CHECK-NEXT: source: "void foo() { }\n"
8+
; CHECK-NEXT: file_names[ 1]:
9+
; CHECK-NEXT: name: "bar.h"
10+
; CHECK-NEXT: dir_index: 0
11+
; CHECK-NOT: source:
12+
13+
; Test that DIFiles mixing source and no-source within a DICompileUnit works.
14+
15+
define dso_local void @foo() !dbg !5 {
16+
ret void, !dbg !7
17+
}
18+
19+
define dso_local void @bar() !dbg !6 {
20+
ret void, !dbg !8
21+
}
22+
23+
!llvm.dbg.cu = !{!4}
24+
!llvm.module.flags = !{!0, !1}
25+
26+
!0 = !{i32 2, !"Dwarf Version", i32 5}
27+
!1 = !{i32 2, !"Debug Info Version", i32 3}
28+
29+
!2 = !DIFile(filename: "foo.c", directory: "dir", source: "void foo() { }\0A")
30+
!3 = !DIFile(filename: "bar.h", directory: "dir")
31+
32+
!4 = distinct !DICompileUnit(language: DW_LANG_C99, emissionKind: FullDebug, file: !2)
33+
!5 = distinct !DISubprogram(name: "foo", file: !2, line: 1, type: !9, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !4)
34+
!6 = distinct !DISubprogram(name: "bar", file: !3, line: 1, type: !9, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !4)
35+
!7 = !DILocation(line: 1, scope: !5)
36+
!8 = !DILocation(line: 1, scope: !6)
37+
!9 = !DISubroutineType(types: !{})

0 commit comments

Comments
 (0)