diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 731ffb14fb3..6e77c6ca072 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -210,10 +210,10 @@ class MCDwarfLineTable { public: // This emits the Dwarf file and the line tables for all Compile Units. - static const MCSymbol *Emit(MCStreamer *MCOS); + static void Emit(MCStreamer *MCOS); // This emits the Dwarf file and the line tables for a given Compile Unit. - const MCSymbol *EmitCU(MCStreamer *MCOS) const; + void EmitCU(MCStreamer *MCOS) const; unsigned getFile(StringRef &Directory, StringRef &FileName, unsigned FileNumber = 0); @@ -270,7 +270,7 @@ public: // When generating dwarf for assembly source files this emits the Dwarf // sections. // - static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); + static void Emit(MCStreamer *MCOS); }; // When generating dwarf for assembly source files this is the info that is diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index cc30d056a21..fa54c1a8da1 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -1435,7 +1435,20 @@ void MCAsmStreamer::EmitRawTextImpl(StringRef String) { void MCAsmStreamer::FinishImpl() { // If we are generating dwarf for assembly source files dump out the sections. if (getContext().getGenDwarfForAssembly()) - MCGenDwarfInfo::Emit(this, NULL); + MCGenDwarfInfo::Emit(this); + + // Emit the label for the line table, if requested - since the rest of the + // line table will be defined by .loc/.file directives, and not emitted + // directly, the label is the only work required here. + auto &Tables = getContext().getMCDwarfLineTables(); + if (!Tables.empty()) { + // FIXME: assert Tables.size() == 1 here, except that's not currently true + // due to DwarfUnit.cpp:2074. + if (auto *Label = Tables.begin()->second.getLabel()) { + SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection()); + EmitLabel(Label); + } + } if (!UseCFI) EmitFrames(AsmBackend.get(), false); diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 5fa8f66422b..231948eaff5 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -204,24 +204,22 @@ EmitDwarfLineTable(MCStreamer *MCOS, const MCSection *Section, // // This emits the Dwarf file and the line tables. // -const MCSymbol *MCDwarfLineTable::Emit(MCStreamer *MCOS) { +void MCDwarfLineTable::Emit(MCStreamer *MCOS) { MCContext &context = MCOS->getContext(); - // CUID and MCLineTableSymbols are set in DwarfDebug, when DwarfDebug does - // not exist, CUID will be 0 and MCLineTableSymbols will be empty. - // Handle Compile Unit 0, the line table start symbol is the section symbol. - auto I = MCOS->getContext().getMCDwarfLineTables().begin(), - E = MCOS->getContext().getMCDwarfLineTables().end(); + auto &LineTables = context.getMCDwarfLineTables(); + + // Bail out early so we don't switch to the debug_line section needlessly and + // in doing so create an unnecessary (if empty) section. + if (LineTables.empty()) + return; // Switch to the section where the table will be emitted into. MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); - const MCSymbol *LineStartSym = I->second.EmitCU(MCOS); // Handle the rest of the Compile Units. - for (++I; I != E; ++I) - I->second.EmitCU(MCOS); - - return LineStartSym; + for (const auto &CUIDTablePair : LineTables) + CUIDTablePair.second.EmitCU(MCOS); } void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS) const { @@ -320,10 +318,8 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, return std::make_pair(LineStartSym, LineEndSym); } -const MCSymbol *MCDwarfLineTable::EmitCU(MCStreamer *MCOS) const { - MCSymbol *LineStartSym; - MCSymbol *LineEndSym; - std::tie(LineStartSym, LineEndSym) = Header.Emit(MCOS); +void MCDwarfLineTable::EmitCU(MCStreamer *MCOS) const { + MCSymbol *LineEndSym = Header.Emit(MCOS).second; // Put out the line tables. for (const auto &LineSec : MCLineSections.getMCLineEntries()) @@ -344,8 +340,6 @@ const MCSymbol *MCDwarfLineTable::EmitCU(MCStreamer *MCOS) const { // This is the end of the section, so set the value of the symbol at the end // of this section (that was used in a previous expression). MCOS->EmitLabel(LineEndSym); - - return LineStartSym; } unsigned MCDwarfLineTable::getFile(StringRef &Directory, StringRef &FileName, @@ -787,14 +781,17 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, // When generating dwarf for assembly source files this emits the Dwarf // sections. // -void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) { +void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { // Create the dwarf sections in this order (.debug_line already created). MCContext &context = MCOS->getContext(); const MCAsmInfo *AsmInfo = context.getAsmInfo(); bool CreateDwarfSectionSymbols = AsmInfo->doesDwarfUseRelocationsAcrossSections(); - if (!CreateDwarfSectionSymbols) - LineSectionSymbol = NULL; + MCSymbol *LineSectionSymbol = nullptr; + if (CreateDwarfSectionSymbols) { + LineSectionSymbol = context.CreateTempSymbol(); + context.setMCLineTableSymbol(LineSectionSymbol, 0); + } MCSymbol *AbbrevSectionSymbol = NULL; MCSymbol *InfoSectionSymbol = NULL; MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 35786accb42..4451264cff6 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -383,14 +383,12 @@ void MCObjectStreamer::EmitZeros(uint64_t NumBytes) { } void MCObjectStreamer::FinishImpl() { - // Dump out the dwarf file & directory tables and line tables. - const MCSymbol *LineSectionSymbol = NULL; - if (getContext().hasMCLineSections()) - LineSectionSymbol = MCDwarfLineTable::Emit(this); - // If we are generating dwarf for assembly source files dump out the sections. if (getContext().getGenDwarfForAssembly()) - MCGenDwarfInfo::Emit(this, LineSectionSymbol); + MCGenDwarfInfo::Emit(this); + + // Dump out the dwarf file & directory tables and line tables. + MCDwarfLineTable::Emit(this); getAssembler().Finish(); } diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index ac6ebbde7b2..910a424ce84 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -661,11 +661,15 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { return TokError("unmatched .ifs or .elses"); // Check to see there are no empty DwarfFile slots. - const SmallVectorImpl &MCDwarfFiles = - getContext().getMCDwarfFiles(); - for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { - if (MCDwarfFiles[i].Name.empty()) - TokError("unassigned file number: " + Twine(i) + " for .file directives"); + const auto &LineTables = getContext().getMCDwarfLineTables(); + if (!LineTables.empty()) { + unsigned Index = 0; + for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) { + if (File.Name.empty() && Index != 0) + TokError("unassigned file number: " + Twine(Index) + + " for .file directives"); + ++Index; + } } // Check to see that all assembler local symbols were actually defined. diff --git a/test/MC/ELF/gen-dwarf.s b/test/MC/ELF/gen-dwarf.s index a702bc8610c..e83b14c4e38 100644 --- a/test/MC/ELF/gen-dwarf.s +++ b/test/MC/ELF/gen-dwarf.s @@ -1,4 +1,5 @@ // RUN: llvm-mc -g -triple i686-pc-linux-gnu %s -filetype=obj -o - | llvm-readobj -r | FileCheck %s +// RUN: llvm-mc -g -triple i686-pc-linux-gnu %s -filetype=asm -o - | FileCheck --check-prefix=ASM %s // Test that on ELF: @@ -23,4 +24,23 @@ foo: // CHECK-NEXT: 0x6 R_386_32 .debug_info 0x0 // CHECK-NEXT: 0x10 R_386_32 .text 0x0 // CHECK-NEXT: } -// CHECK-NEXT: ] +// CHECK: ] + +// First instance of the section is just to give it a label for debug_aranges to refer to +// ASM: .section .debug_info + +// ASM: .section .debug_abbrev +// ASM-NEXT: [[ABBREV_LABEL:.Ltmp[0-9]+]] + +// Second instance of the section has the CU +// ASM: .section .debug_info +// Dwarf version +// ASM: .short 2 +// ASM-NEXT: .long [[ABBREV_LABEL]] +// First .byte 1 is the abbreviation number for the compile_unit abbrev +// ASM: .byte 1 +// ASM-NEXT: .long [[LINE_LABEL:.Ltmp[0-9]+]] + +// ASM: .section .debug_line +// ASM-NEXT: [[LINE_LABEL]] +