Skip to content

Commit b9752d2

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 llvm#73877 (cherry picked from commit 87e22bd)
1 parent 1e608f9 commit b9752d2

File tree

4 files changed

+59
-21
lines changed

4 files changed

+59
-21
lines changed

llvm/include/llvm/MC/MCDwarf.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ struct MCDwarfLineTableHeader {
276276
StringMap<unsigned> SourceIdMap;
277277
std::string CompilationDir;
278278
MCDwarfFile RootFile;
279-
bool HasSource = false;
279+
bool HasAnySource = false;
280+
280281
private:
281282
bool HasAllMD5 = true;
282283
bool HasAnyMD5 = false;
@@ -316,15 +317,15 @@ struct MCDwarfLineTableHeader {
316317
RootFile.Checksum = Checksum;
317318
RootFile.Source = Source;
318319
trackMD5Usage(Checksum.has_value());
319-
HasSource = Source.has_value();
320+
HasAnySource |= Source.has_value();
320321
}
321322

322323
void resetFileTable() {
323324
MCDwarfDirs.clear();
324325
MCDwarfFiles.clear();
325326
RootFile.Name.clear();
326327
resetMD5Usage();
327-
HasSource = false;
328+
HasAnySource = false;
328329
}
329330

330331
private:
@@ -396,7 +397,7 @@ class MCDwarfLineTable {
396397
Header.RootFile.Checksum = Checksum;
397398
Header.RootFile.Source = Source;
398399
Header.trackMD5Usage(Checksum.has_value());
399-
Header.HasSource = Source.has_value();
400+
Header.HasAnySource |= Source.has_value();
400401
}
401402

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

llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp

Lines changed: 8 additions & 3 deletions
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

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const {
393393
}
394394

395395
static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
396-
bool EmitMD5, bool HasSource,
396+
bool EmitMD5, bool HasAnySource,
397397
std::optional<MCDwarfLineStr> &LineStr) {
398398
assert(!DwarfFile.Name.empty());
399399
if (LineStr)
@@ -408,7 +408,7 @@ static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
408408
MCOS->emitBinaryData(
409409
StringRef(reinterpret_cast<const char *>(Cksum.data()), Cksum.size()));
410410
}
411-
if (HasSource) {
411+
if (HasAnySource) {
412412
if (LineStr)
413413
LineStr->emitRef(MCOS, DwarfFile.Source.value_or(StringRef()));
414414
else {
@@ -459,7 +459,7 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
459459
uint64_t Entries = 2;
460460
if (HasAllMD5)
461461
Entries += 1;
462-
if (HasSource)
462+
if (HasAnySource)
463463
Entries += 1;
464464
MCOS->emitInt8(Entries);
465465
MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
@@ -471,7 +471,7 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
471471
MCOS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);
472472
MCOS->emitULEB128IntValue(dwarf::DW_FORM_data16);
473473
}
474-
if (HasSource) {
474+
if (HasAnySource) {
475475
MCOS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
476476
MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
477477
: dwarf::DW_FORM_string);
@@ -486,9 +486,9 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
486486
assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) &&
487487
"No root file and no .file directives");
488488
emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,
489-
HasAllMD5, HasSource, LineStr);
489+
HasAllMD5, HasAnySource, LineStr);
490490
for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)
491-
emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasSource, LineStr);
491+
emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasAnySource, LineStr);
492492
}
493493

494494
std::pair<MCSymbol *, MCSymbol *>
@@ -605,7 +605,7 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
605605
// If any files have embedded source, they all must.
606606
if (MCDwarfFiles.empty()) {
607607
trackMD5Usage(Checksum.has_value());
608-
HasSource = (Source != std::nullopt);
608+
HasAnySource |= Source.has_value();
609609
}
610610
if (DwarfVersion >= 5 && isRootFile(RootFile, Directory, FileName, Checksum))
611611
return 0;
@@ -632,11 +632,6 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
632632
return make_error<StringError>("file number already allocated",
633633
inconvertibleErrorCode());
634634

635-
// If any files have embedded source, they all must.
636-
if (HasSource != (Source != std::nullopt))
637-
return make_error<StringError>("inconsistent use of embedded source",
638-
inconvertibleErrorCode());
639-
640635
if (Directory.empty()) {
641636
// Separate the directory part from the basename of the FileName.
642637
StringRef tFileName = sys::path::filename(FileName);
@@ -669,8 +664,8 @@ MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
669664
File.Checksum = Checksum;
670665
trackMD5Usage(Checksum.has_value());
671666
File.Source = Source;
672-
if (Source)
673-
HasSource = true;
667+
if (Source.has_value())
668+
HasAnySource = true;
674669

675670
// return the allocated FileNumber.
676671
return FileNumber;
Lines changed: 37 additions & 0 deletions
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)