return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source));
}
- void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params) const;
+ void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
+ MCSection *Section) const;
};
class MCDwarfLineTable {
void DwarfDebug::emitDebugLineDWO() {
assert(useSplitDwarf() && "No split dwarf?");
- if (!HasSplitTypeUnits)
- return;
- Asm->OutStreamer->SwitchSection(
+ SplitTypeUnitFileTable.Emit(
+ *Asm->OutStreamer, MCDwarfLineTableParams(),
Asm->getObjFileLowering().getDwarfLineDWOSection());
- SplitTypeUnitFileTable.Emit(*Asm->OutStreamer, MCDwarfLineTableParams());
}
void DwarfDebug::emitStringOffsetsTableHeaderDWO() {
if (useSplitDwarf())
NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
else {
- CU.applyStmtList(UnitDie);
NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+ // Non-split type units reuse the compile unit's line table.
+ CU.applyStmtList(UnitDie);
}
// Add DW_AT_str_offsets_base to the type unit DIE, but not for split type
InfoHolder.computeSizeAndOffsetsForUnit(TU.first.get());
InfoHolder.emitUnit(TU.first.get(), useSplitDwarf());
}
- HasSplitTypeUnits = useSplitDwarf();
}
CU.addDIETypeSignature(RefDie, Signature);
}
/// a monolithic sequence of string offsets.
bool UseSegmentedStringOffsetsTable;
- /// Whether we have emitted any type units with split DWARF (and therefore
- /// need to emit a line table to the .dwo file).
- bool HasSplitTypeUnits = false;
-
/// Separated Dwarf Variables
/// In general these will all be for bits that are left in the
/// original object file, rather than things that are meant
MCDwarfDwoLineTable *SplitLineTable)
: DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), CU(CU),
SplitLineTable(SplitLineTable) {
- if (SplitLineTable)
- addSectionOffset(getUnitDie(), dwarf::DW_AT_stmt_list, 0);
}
DwarfUnit::~DwarfUnit() {
}
unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) {
- return SplitLineTable
- ? SplitLineTable->getFile(File->getDirectory(),
- File->getFilename(),
- getMD5AsBytes(File),
- File->getSource())
- : getCU().getOrCreateSourceID(File);
+ if (!SplitLineTable)
+ return getCU().getOrCreateSourceID(File);
+ if (!UsedLineTable) {
+ UsedLineTable = true;
+ // This is a split type unit that needs a line table.
+ addSectionOffset(getUnitDie(), dwarf::DW_AT_stmt_list, 0);
+ }
+ return SplitLineTable->getFile(File->getDirectory(), File->getFilename(),
+ getMD5AsBytes(File), File->getSource());
}
void DwarfUnit::addOpAddress(DIELoc &Die, const MCSymbol *Sym) {
const DIE *Ty;
DwarfCompileUnit &CU;
MCDwarfDwoLineTable *SplitLineTable;
+ bool UsedLineTable = false;
unsigned getOrCreateSourceID(const DIFile *File) override;
bool isDwoUnit() const override;
LineStr->emitSection(MCOS);
}
-void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS,
- MCDwarfLineTableParams Params) const {
+void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
+ MCSection *Section) const {
+ if (Header.MCDwarfFiles.empty())
+ return;
Optional<MCDwarfLineStr> NoLineStr(None);
+ MCOS.SwitchSection(Section);
MCOS.EmitLabel(Header.Emit(&MCOS, Params, None, NoLineStr).second);
}
--- /dev/null
+; Verify that split type units with no source locations don't have a
+; DW_AT_stmt_list attribute, and the .debug_line.dwo section is suppressed.
+
+; RUN: llc -split-dwarf-file=foo.dwo -dwarf-version=5 -generate-type-units \
+; RUN: -filetype=obj -O0 -mtriple=x86_64-unknown-linux-gnu < %s \
+; RUN: | llvm-dwarfdump -v - | FileCheck %s
+
+; FIXME: V5 wants type units in .debug_info.dwo not .debug_types.dwo.
+; CHECK-NOT: .debug_line.dwo
+; CHECK: .debug_types.dwo contents:
+; CHECK: 0x00000000: Type Unit: {{.*}} version = 0x0005 unit_type = DW_UT_split_type abbr_offset
+; CHECK: 0x00000018: DW_TAG_type_unit
+; CHECK-NOT: DW_AT_stmt_list
+; CHECK-NOT: DW_AT_decl_file
+; CHECK-NOT: .debug_line.dwo
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.S = type { i32 }
+
+@s = global %struct.S zeroinitializer, align 4, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!8, !9}
+!llvm.ident = !{!10}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "s", scope: !2, file: !3, line: 5, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 5.0.0 (trunk 295942)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "t.cpp", directory: "/home/probinson/projects/scratch")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", size: 32, elements: !7, identifier: "_ZTS1S")
+!7 = !{}
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{!"clang version 5.0.0 (trunk 295942)"}
--- /dev/null
+; Verify that if we have two split type units, one with source locations and
+; one without, the one without locations doesn't have a DW_AT_stmt_list
+; attribute, but the other one does and the .debug_line.dwo section is present.
+
+; RUN: llc -split-dwarf-file=foo.dwo -dwarf-version=5 -generate-type-units \
+; RUN: -filetype=obj -O0 -mtriple=x86_64-unknown-linux-gnu < %s \
+; RUN: | llvm-dwarfdump -v - | FileCheck %s
+
+; Currently the no-source-location type comes out first.
+; FIXME: V5 wants type units in .debug_info.dwo not .debug_types.dwo.
+; CHECK: .debug_types.dwo contents:
+; CHECK: 0x00000000: Type Unit: {{.*}} name = 'S'
+; CHECK-SAME: (next unit at [[TU2:0x[0-9a-f]+]])
+; CHECK: DW_TAG_type_unit
+; CHECK-NOT: DW_AT_stmt_list
+; CHECK-NOT: DW_AT_decl_file
+; CHECK: [[TU2]]: Type Unit: {{.*}} name = 'T'
+; CHECK: DW_TAG_type_unit
+; CHECK: DW_AT_stmt_list
+; CHECK: DW_AT_decl_file
+
+; CHECK: .debug_line.dwo
+; CHECK-NOT: standard_opcode_lengths
+; CHECK: file_names[ 0]:
+; CHECK-NEXT: name: "t.cpp"
+; CHECK-NEXT: dir_index: 0
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.S = type { i32 }
+%struct.T = type { i32 }
+
+@s = global %struct.S zeroinitializer, align 4, !dbg !0
+@t = global %struct.T zeroinitializer, align 4, !dbg !14
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!8, !9}
+!llvm.ident = !{!10}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "s", scope: !2, file: !3, line: 5, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 5.0.0 (trunk 295942)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "t.cpp", directory: "/home/probinson/projects/scratch")
+!4 = !{}
+!5 = !{!0,!14}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", size: 32, elements: !7, identifier: "_ZTS1S")
+!7 = !{}
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{!"clang version 5.0.0 (trunk 295942)"}
+!11 = distinct !DIGlobalVariable(name: "t", scope: !2, file: !3, line: 10, type: !12, isLocal: false, isDefinition: true)
+!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "T", file: !3, line: 8, size: 32, elements: !13, identifier: "_ZTS1S")
+!13 = !{}
+!14 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())