diff options
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 110 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.h | 17 | ||||
-rw-r--r-- | test/DebugInfo/X86/fission-cu.ll | 26 |
3 files changed, 145 insertions, 8 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 10061e1907..c4c9d3f2b3 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -153,7 +153,7 @@ DIType DbgVariable::getType() const { } // end llvm namespace DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) - : Asm(A), MMI(Asm->MMI), FirstCU(0), + : Asm(A), MMI(Asm->MMI), FirstCU(0), FissionCU(0), AbbreviationsSet(InitAbbreviationsSetSize), SourceIdMap(DIEValueAllocator), StringPool(DIEValueAllocator), PrevLabel(NULL) { @@ -650,6 +650,9 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { if (!FirstCU) FirstCU = NewCU; + if (useDwarfFission() && !FissionCU) + FissionCU = constructFissionCU(N); + CUMap.insert(std::make_pair(N, NewCU)); return NewCU; } @@ -927,8 +930,9 @@ void DwarfDebug::endModule() { // TODO: Fill this in for Fission sections and separate // out information into new sections. - // Emit all the DIEs into a debug info section. + // Emit the debug info section and compile units. emitDebugInfo(); + emitDebugInfoDWO(); // Corresponding abbreviations into a abbrev section. emitAbbreviations(); @@ -975,7 +979,9 @@ void DwarfDebug::endModule() { for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) delete I->second; - FirstCU = NULL; // Reset for the next Module, if any. + // Reset these for the next Module if we have one. + FirstCU = NULL; + FissionCU = NULL; } // Find abstract variable, if any, associated with Var. @@ -1665,6 +1671,15 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset) { // Compute the size and offset of all the DIEs. void DwarfDebug::computeSizeAndOffsets() { + if (FissionCU) { + unsigned Offset = + sizeof(int32_t) + // Length of Compilation Unit Info + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t); // Pointer Size (in bytes) + + computeSizeAndOffset(FissionCU->getCUDie(), Offset); + } for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { // Compute size of compile unit header. @@ -1795,11 +1810,8 @@ void DwarfDebug::emitDIE(DIE *Die) { } } -// Emit the debug info section. -void DwarfDebug::emitDebugInfo() { - // Start debug info section. - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfInfoSection()); +void DwarfDebug::emitCompileUnits(const MCSection *Section) { + Asm->OutStreamer.SwitchSection(Section); for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { CompileUnit *TheCU = I->second; @@ -1830,6 +1842,14 @@ void DwarfDebug::emitDebugInfo() { } } +// Emit the debug info section. +void DwarfDebug::emitDebugInfo() { + if (!useDwarfFission()) + emitCompileUnits(Asm->getObjFileLowering().getDwarfInfoSection()); + else + emitFissionSkeletonCU(Asm->getObjFileLowering().getDwarfInfoSection()); +} + // Emit the abbreviation section. void DwarfDebug::emitAbbreviations() { // Check to see if it is worth the effort. @@ -2286,3 +2306,77 @@ void DwarfDebug::emitDebugInlineInfo() { Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_end", 1)); } + +// DWARF5 Experimental Fission emitters. + +// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, +// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, +// DW_AT_ranges_base, DW_AT_addr_base. If DW_AT_ranges is present, +// DW_AT_low_pc and DW_AT_high_pc are not used, and vice versa. +CompileUnit *DwarfDebug::constructFissionCU(const MDNode *N) { + DICompileUnit DIUnit(N); + StringRef FN = DIUnit.getFilename(); + CompilationDir = DIUnit.getDirectory(); + unsigned ID = getOrCreateSourceID(FN, CompilationDir); + + DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); + CompileUnit *NewCU = new CompileUnit(ID, DIUnit.getLanguage(), Die, + Asm, this); + // FIXME: This should be the .dwo file. + NewCU->addString(Die, dwarf::DW_AT_GNU_dwo_name, FN); + + // FIXME: We also need DW_AT_addr_base and DW_AT_dwo_id. + + // 2.17.1 requires that we use DW_AT_low_pc for a single entry point + // into an entity. + NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0); + // DW_AT_stmt_list is a offset of line number information for this + // compile unit in debug_line section. + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, + Asm->GetTempSymbol("section_line")); + else + NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); + + if (!CompilationDir.empty()) + NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + + return NewCU; +} + +void DwarfDebug::emitFissionSkeletonCU(const MCSection *Section) { + Asm->OutStreamer.SwitchSection(Section); + DIE *Die = FissionCU->getCUDie(); + + // Emit the compile units header. + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("skel_info_begin", + FissionCU->getID())); + + // Emit size of content not including length itself + unsigned ContentSize = Die->getSize() + + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t); // Pointer Size (in bytes) + + Asm->OutStreamer.AddComment("Length of Compilation Unit Info"); + Asm->EmitInt32(ContentSize); + Asm->OutStreamer.AddComment("DWARF version number"); + Asm->EmitInt16(dwarf::DWARF_VERSION); + Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); + Asm->EmitSectionOffset(Asm->GetTempSymbol("abbrev_begin"), + DwarfAbbrevSectionSym); + Asm->OutStreamer.AddComment("Address Size (in bytes)"); + Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); + + emitDIE(Die); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("skel_info_end", FissionCU->getID())); + + +} + +// Emit the .debug_info.dwo section for fission. This contains the compile +// units that would normally be in debug_info. +void DwarfDebug::emitDebugInfoDWO() { + assert(useDwarfFission() && "Got fission?"); + emitCompileUnits(Asm->getObjFileLowering().getDwarfInfoDWOSection()); +} diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index b6b28fa7e9..35bddee41b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -205,6 +205,9 @@ class DwarfDebug { CompileUnit *FirstCU; + // The CU left in the original object file for Fission debug info. + CompileUnit *FissionCU; + // Maps MDNode with its corresponding CompileUnit. DenseMap <const MDNode *, CompileUnit *> CUMap; @@ -369,6 +372,9 @@ private: /// open. void endSections(); + /// \brief Emit all of the compile units to the target section. + void emitCompileUnits(const MCSection *); + /// \brief Emit the debug info section. void emitDebugInfo(); @@ -413,6 +419,17 @@ private: /// \brief Emit inline info using custom format. void emitDebugInlineInfo(); + /// DWARF 5 Experimental Fission Emitters + + /// \brief Construct the fission compile unit for the debug info section. + CompileUnit *constructFissionCU(const MDNode *); + + /// \brief Emit the fission debug info section. + void emitFissionSkeletonCU(const MCSection *); + + /// \brief Emit the debug info dwo section. + void emitDebugInfoDWO(); + /// \brief Create new CompileUnit for the given metadata node with tag /// DW_TAG_compile_unit. CompileUnit *constructCompileUnit(const MDNode *N); diff --git a/test/DebugInfo/X86/fission-cu.ll b/test/DebugInfo/X86/fission-cu.ll new file mode 100644 index 0000000000..2c2c01ab88 --- /dev/null +++ b/test/DebugInfo/X86/fission-cu.ll @@ -0,0 +1,26 @@ +; RUN: llc -dwarf-fission=Enable -O0 %s -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t +; RUN: llvm-dwarfdump %t | FileCheck %s + +@a = common global i32 0, align 4 + +!llvm.dbg.cu = !{!0} + +!0 = metadata !{i32 786449, i32 0, i32 12, metadata !"baz.c", metadata !"/usr/local/google/home/echristo/tmp", metadata !"clang version 3.3 (trunk 169021) (llvm/trunk 169020)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !1, metadata !3} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/echristo/tmp/baz.c] [DW_LANG_C99] +!1 = metadata !{metadata !2} +!2 = metadata !{i32 0} +!3 = metadata !{metadata !4} +!4 = metadata !{metadata !5} +!5 = metadata !{i32 786484, i32 0, null, metadata !"a", metadata !"a", metadata !"", metadata !6, i32 1, metadata !7, i32 0, i32 1, i32* @a} ; [ DW_TAG_variable ] [a] [line 1] [def] +!6 = metadata !{i32 786473, metadata !"baz.c", metadata !"/usr/local/google/home/echristo/tmp", null} ; [ DW_TAG_file_type ] +!7 = metadata !{i32 786468, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] + +; Check that the skeleton compile unit contains the proper attributes: +; This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, +; DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, +; DW_AT_ranges_base, DW_AT_addr_base. + +; CHECK: DW_TAG_compile_unit [1] +; CHECK: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000035] = "baz.c") +; CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) +; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x00000000) +; CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x0000003b] = "/usr/local/google/home/echristo/tmp") |