diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -730,13 +730,14 @@ /// instruction will be created. void setCurrentDwarfLoc(unsigned FileNum, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, - unsigned Discriminator) { + unsigned Discriminator, uint64_t Addr = -1ULL) { CurrentDwarfLoc.setFileNum(FileNum); CurrentDwarfLoc.setLine(Line); CurrentDwarfLoc.setColumn(Column); CurrentDwarfLoc.setFlags(Flags); CurrentDwarfLoc.setIsa(Isa); CurrentDwarfLoc.setDiscriminator(Discriminator); + CurrentDwarfLoc.setAbsoluteAddr(Addr); DwarfLocSeen = true; } diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -81,6 +81,7 @@ uint8_t Flags; uint8_t Isa; uint32_t Discriminator; + uint64_t AbsoluteAddr; // Flag that indicates the initial value of the is_stmt_start flag. #define DWARF2_LINE_DEFAULT_IS_STMT 1 @@ -95,14 +96,17 @@ friend class MCDwarfLineEntry; MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, - unsigned isa, unsigned discriminator) + unsigned isa, unsigned discriminator, uint64_t addr=-1ULL) : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), - Discriminator(discriminator) {} + Discriminator(discriminator), AbsoluteAddr(addr) {} // Allow the default copy constructor and assignment operator to be used // for an MCDwarfLoc object. public: + /// \brief Get the AbsoluteAddr of this MCDwarfLoc. + uint64_t getAbsoluteAddr() const { return AbsoluteAddr; } + /// Get the FileNum of this MCDwarfLoc. unsigned getFileNum() const { return FileNum; } @@ -149,6 +153,11 @@ void setDiscriminator(unsigned discriminator) { Discriminator = discriminator; } + + /// \brief Set the AbsoluteAddr of this MCDwarfLoc. + void setAbsoluteAddr(uint64_t addr) { + AbsoluteAddr = addr; + } }; /// Instances of this class represent the line information for diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -149,6 +149,9 @@ const MCSymbol *Label, unsigned PointerSize) override; void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override; + void emitDwarfAdvanceLineAddrAbs(int64_t LineDelta, uint64_t Address, + uint64_t AddressDelta, + unsigned PointerSize) override; void emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label); void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -1110,6 +1110,10 @@ const MCSymbol *Label, unsigned PointerSize) {} + virtual void emitDwarfAdvanceLineAddrAbs(int64_t LineDelta, uint64_t Address, + uint64_t AddressDelta, + unsigned PointerSize) {} + /// Do finalization for the streamer at the end of a section. virtual void doFinalizationAtSectionEnd(MCSection *Section) {} }; diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -171,12 +171,27 @@ unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; unsigned Isa = 0; unsigned Discriminator = 0; + uint64_t LastAddress = -1ULL; MCSymbol *LastLabel = nullptr; + const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); // Loop through each MCDwarfLineEntry and encode the dwarf line number table. - for (const MCDwarfLineEntry &LineEntry : LineEntries) { + for (auto it = LineEntries.begin(), + ie = LineEntries.end(); + it != ie; ++it) { + const MCDwarfLineEntry &LineEntry = *it; int64_t LineDelta = static_cast(LineEntry.getLine()) - LastLine; + const uint64_t Address = LineEntry.getAbsoluteAddr(); + if (Address != -1ULL && std::next(it) == ie) { + // If emitting absolute addresses, the last entry only carries address + // info for the DW_LNE_end_sequence. This entry compensates for the lack + // of the section context used to emit the end of section label. + MCOS->emitDwarfAdvanceLineAddrAbs(INT64_MAX, -1ULL, Address - LastAddress, + AsmInfo->getCodePointerSize()); + return; + } + if (FileNum != LineEntry.getFileNum()) { FileNum = LineEntry.getFileNum(); MCOS->emitInt8(dwarf::DW_LNS_set_file); @@ -212,18 +227,34 @@ if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); - MCSymbol *Label = LineEntry.getLabel(); + if (Address == -1ULL) { + assert(LastAddress == -1ULL && + "Absolute addresses can only be added at the end of the table."); + + MCSymbol *Label = LineEntry.getLabel(); - // At this point we want to emit/create the sequence to encode the delta in - // line numbers and the increment of the address from the previous Label - // and the current Label. - const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo(); - MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, - asmInfo->getCodePointerSize()); + // At this point we want to emit/create the sequence to encode the delta + // in line numbers and the increment of the address from the previous + // Label and the current Label. + MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, + AsmInfo->getCodePointerSize()); + LastLabel = Label; + LastAddress = -1ULL; + } else { + if (LastAddress == -1ULL) { + MCOS->emitDwarfAdvanceLineAddrAbs(LineDelta, Address, 0, + AsmInfo->getCodePointerSize()); + } else { + MCOS->emitDwarfAdvanceLineAddrAbs(LineDelta, -1ULL, + Address - LastAddress, + AsmInfo->getCodePointerSize()); + } + LastAddress = Address; + LastLabel = nullptr; + } Discriminator = 0; LastLine = LineEntry.getLine(); - LastLabel = Label; } // Generate DWARF line end entry. diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -469,6 +469,33 @@ return AddrDelta; } +static void emitDwarfSetLineAddrAbs(MCObjectStreamer &OS, + MCDwarfLineTableParams Params, + int64_t LineDelta, uint64_t Address, + int PointerSize) { + // emit the sequence to set the address + OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); + OS.emitULEB128IntValue(PointerSize + 1); + OS.emitIntValue(dwarf::DW_LNE_set_address, 1); + OS.emitIntValue(Address, PointerSize); + + // emit the sequence for the LineDelta (from 1) and a zero address delta. + MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); +} + +void MCObjectStreamer::emitDwarfAdvanceLineAddrAbs(int64_t LineDelta, + uint64_t Address, + uint64_t AddressDelta, + unsigned PointerSize) { + if (Address != -1ULL) { + emitDwarfSetLineAddrAbs(*this, Assembler->getDWARFLinetableParams(), + LineDelta, Address, PointerSize); + return; + } + MCDwarfLineAddr::Emit(this, Assembler->getDWARFLinetableParams(), LineDelta, + AddressDelta); +} + static void emitDwarfSetLineAddr(MCObjectStreamer &OS, MCDwarfLineTableParams Params, int64_t LineDelta, const MCSymbol *Label,