forked from OSchip/llvm-project
[BOLT] Fix debug info update for inlining.
Summary: When inlining, if a callee has debug info and a caller does not (i.e. a containing compilation unit was compiled without "-g"), we try to update a nonexistent compilation unit. Instead we should skip updating debug info in such cases. Minor refactoring of line number emitting code. (cherry picked from FBD4823982)
This commit is contained in:
parent
0bde796e50
commit
c166a8c1a7
|
@ -2526,7 +2526,6 @@ void BinaryFunction::modifyLayout(LayoutType Type, bool MinBranchClusters,
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart) {
|
void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart) {
|
||||||
auto ULT = getDWARFUnitLineTable();
|
|
||||||
int64_t CurrentGnuArgsSize = 0;
|
int64_t CurrentGnuArgsSize = 0;
|
||||||
for (auto BB : layout()) {
|
for (auto BB : layout()) {
|
||||||
if (EmitColdPart != BB->isCold())
|
if (EmitColdPart != BB->isCold())
|
||||||
|
@ -2536,14 +2535,9 @@ void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart) {
|
||||||
Streamer.EmitCodeAlignment(BB->getAlignment());
|
Streamer.EmitCodeAlignment(BB->getAlignment());
|
||||||
Streamer.EmitLabel(BB->getLabel());
|
Streamer.EmitLabel(BB->getLabel());
|
||||||
|
|
||||||
// Remember last .debug_line entry emitted so that we don't repeat them in
|
|
||||||
// subsequent instructions, as gdb can figure it out by looking at the
|
|
||||||
// previous instruction with available line number info.
|
|
||||||
SMLoc LastLocSeen;
|
|
||||||
|
|
||||||
// Remember if last instruction emitted was a prefix
|
// Remember if last instruction emitted was a prefix
|
||||||
bool LastIsPrefix = false;
|
bool LastIsPrefix = false;
|
||||||
|
SMLoc LastLocSeen;
|
||||||
for (auto I = BB->begin(), E = BB->end(); I != E; ++I) {
|
for (auto I = BB->begin(), E = BB->end(); I != E; ++I) {
|
||||||
auto &Instr = *I;
|
auto &Instr = *I;
|
||||||
// Handle pseudo instructions.
|
// Handle pseudo instructions.
|
||||||
|
@ -2558,52 +2552,8 @@ void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart) {
|
||||||
Streamer.EmitCFIInstruction(*getCFIFor(Instr));
|
Streamer.EmitCFIInstruction(*getCFIFor(Instr));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (opts::UpdateDebugSections) {
|
if (opts::UpdateDebugSections && UnitLineTable.first) {
|
||||||
auto RowReference = DebugLineTableRowRef::fromSMLoc(Instr.getLoc());
|
LastLocSeen = emitLineInfo(Instr.getLoc(), LastLocSeen);
|
||||||
if (RowReference != DebugLineTableRowRef::NULL_ROW &&
|
|
||||||
Instr.getLoc().getPointer() != LastLocSeen.getPointer()) {
|
|
||||||
auto Unit = ULT.first;
|
|
||||||
auto OriginalLineTable = ULT.second;
|
|
||||||
const auto OrigUnitID = Unit->getOffset();
|
|
||||||
unsigned NewFilenum = 0;
|
|
||||||
|
|
||||||
// If the CU id from the current instruction location does not
|
|
||||||
// match the CU id from the current function, it means that we
|
|
||||||
// have come across some inlined code. We must look up the CU
|
|
||||||
// for the instruction's original function and get the line table
|
|
||||||
// from that. We also update the current CU debug info with the
|
|
||||||
// filename of the inlined function.
|
|
||||||
if (RowReference.DwCompileUnitIndex != OrigUnitID) {
|
|
||||||
Unit = BC.DwCtx->
|
|
||||||
getCompileUnitForOffset(RowReference.DwCompileUnitIndex);
|
|
||||||
OriginalLineTable = BC.DwCtx->getLineTableForUnit(Unit);
|
|
||||||
const auto Filenum =
|
|
||||||
OriginalLineTable->Rows[RowReference.RowIndex - 1].File;
|
|
||||||
NewFilenum =
|
|
||||||
BC.addDebugFilenameToUnit(OrigUnitID,
|
|
||||||
RowReference.DwCompileUnitIndex,
|
|
||||||
Filenum);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(Unit && OriginalLineTable &&
|
|
||||||
"Invalid CU offset set in instruction debug info.");
|
|
||||||
|
|
||||||
const auto &OriginalRow =
|
|
||||||
OriginalLineTable->Rows[RowReference.RowIndex - 1];
|
|
||||||
|
|
||||||
BC.Ctx->setCurrentDwarfLoc(
|
|
||||||
NewFilenum == 0 ? OriginalRow.File : NewFilenum,
|
|
||||||
OriginalRow.Line,
|
|
||||||
OriginalRow.Column,
|
|
||||||
(DWARF2_FLAG_IS_STMT * OriginalRow.IsStmt) |
|
|
||||||
(DWARF2_FLAG_BASIC_BLOCK * OriginalRow.BasicBlock) |
|
|
||||||
(DWARF2_FLAG_PROLOGUE_END * OriginalRow.PrologueEnd) |
|
|
||||||
(DWARF2_FLAG_EPILOGUE_BEGIN * OriginalRow.EpilogueBegin),
|
|
||||||
OriginalRow.Isa,
|
|
||||||
OriginalRow.Discriminator);
|
|
||||||
BC.Ctx->setDwarfCompileUnitID(OrigUnitID);
|
|
||||||
LastLocSeen = Instr.getLoc();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit GNU_args_size CFIs as necessary.
|
// Emit GNU_args_size CFIs as necessary.
|
||||||
|
@ -3497,6 +3447,56 @@ bool BinaryFunction::isSymbolValidInScope(const SymbolRef &Symbol,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SMLoc BinaryFunction::emitLineInfo(SMLoc NewLoc, SMLoc PrevLoc) const {
|
||||||
|
auto *FunctionCU = UnitLineTable.first;
|
||||||
|
const auto *FunctionLineTable = UnitLineTable.second;
|
||||||
|
assert(FunctionCU && "cannot emit line info for function without CU");
|
||||||
|
|
||||||
|
auto RowReference = DebugLineTableRowRef::fromSMLoc(NewLoc);
|
||||||
|
|
||||||
|
// Check if no new line info needs to be emitted.
|
||||||
|
if (RowReference == DebugLineTableRowRef::NULL_ROW ||
|
||||||
|
NewLoc.getPointer() == PrevLoc.getPointer())
|
||||||
|
return PrevLoc;
|
||||||
|
|
||||||
|
unsigned CurrentFilenum = 0;
|
||||||
|
const auto *CurrentLineTable = FunctionLineTable;
|
||||||
|
|
||||||
|
// If the CU id from the current instruction location does not
|
||||||
|
// match the CU id from the current function, it means that we
|
||||||
|
// have come across some inlined code. We must look up the CU
|
||||||
|
// for the instruction's original function and get the line table
|
||||||
|
// from that.
|
||||||
|
const auto FunctionUnitIndex = FunctionCU->getOffset();
|
||||||
|
const auto CurrentUnitIndex = RowReference.DwCompileUnitIndex;
|
||||||
|
if (CurrentUnitIndex != FunctionUnitIndex) {
|
||||||
|
CurrentLineTable = BC.DwCtx->getLineTableForUnit(
|
||||||
|
BC.DwCtx->getCompileUnitForOffset(CurrentUnitIndex));
|
||||||
|
// Add filename from the inlined function to the current CU.
|
||||||
|
CurrentFilenum =
|
||||||
|
BC.addDebugFilenameToUnit(FunctionUnitIndex, CurrentUnitIndex,
|
||||||
|
CurrentLineTable->Rows[RowReference.RowIndex - 1].File);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &CurrentRow = CurrentLineTable->Rows[RowReference.RowIndex - 1];
|
||||||
|
if (!CurrentFilenum)
|
||||||
|
CurrentFilenum = CurrentRow.File;
|
||||||
|
|
||||||
|
BC.Ctx->setCurrentDwarfLoc(
|
||||||
|
CurrentFilenum,
|
||||||
|
CurrentRow.Line,
|
||||||
|
CurrentRow.Column,
|
||||||
|
(DWARF2_FLAG_IS_STMT * CurrentRow.IsStmt) |
|
||||||
|
(DWARF2_FLAG_BASIC_BLOCK * CurrentRow.BasicBlock) |
|
||||||
|
(DWARF2_FLAG_PROLOGUE_END * CurrentRow.PrologueEnd) |
|
||||||
|
(DWARF2_FLAG_EPILOGUE_BEGIN * CurrentRow.EpilogueBegin),
|
||||||
|
CurrentRow.Isa,
|
||||||
|
CurrentRow.Discriminator);
|
||||||
|
BC.Ctx->setDwarfCompileUnitID(FunctionUnitIndex);
|
||||||
|
|
||||||
|
return NewLoc;
|
||||||
|
}
|
||||||
|
|
||||||
BinaryFunction::~BinaryFunction() {
|
BinaryFunction::~BinaryFunction() {
|
||||||
for (auto BB : BasicBlocks) {
|
for (auto BB : BasicBlocks) {
|
||||||
delete BB;
|
delete BB;
|
||||||
|
|
|
@ -315,6 +315,12 @@ private:
|
||||||
std::vector<std::pair<const DWARFDebugInfoEntryMinimal *,
|
std::vector<std::pair<const DWARFDebugInfoEntryMinimal *,
|
||||||
DWARFCompileUnit *>> SubprogramDIEs;
|
DWARFCompileUnit *>> SubprogramDIEs;
|
||||||
|
|
||||||
|
/// Line table for the function with containing compilation unit.
|
||||||
|
/// Because of identical code folding the function could have multiple
|
||||||
|
/// associated compilation units. The first of them with line number info
|
||||||
|
/// is referenced by UnitLineTable.
|
||||||
|
DWARFUnitLineTable UnitLineTable{nullptr, nullptr};
|
||||||
|
|
||||||
/// Offset of this function's address ranges in the .debug_ranges section of
|
/// Offset of this function's address ranges in the .debug_ranges section of
|
||||||
/// the output binary.
|
/// the output binary.
|
||||||
uint32_t AddressRangesOffset{-1U};
|
uint32_t AddressRangesOffset{-1U};
|
||||||
|
@ -753,6 +759,12 @@ private:
|
||||||
unsigned Size,
|
unsigned Size,
|
||||||
uint64_t Offset);
|
uint64_t Offset);
|
||||||
|
|
||||||
|
/// Emit line number information corresponding to \p NewLoc. \p PrevLoc
|
||||||
|
/// provides a context for de-duplication of line number info.
|
||||||
|
///
|
||||||
|
/// Return new current location which is either \p NewLoc or \p PrevLoc.
|
||||||
|
SMLoc emitLineInfo(SMLoc NewLoc, SMLoc PrevLoc) const;
|
||||||
|
|
||||||
BinaryFunction& operator=(const BinaryFunction &) = delete;
|
BinaryFunction& operator=(const BinaryFunction &) = delete;
|
||||||
BinaryFunction(const BinaryFunction &) = delete;
|
BinaryFunction(const BinaryFunction &) = delete;
|
||||||
|
|
||||||
|
@ -1670,20 +1682,22 @@ public:
|
||||||
void addSubprogramDIE(DWARFCompileUnit *Unit,
|
void addSubprogramDIE(DWARFCompileUnit *Unit,
|
||||||
const DWARFDebugInfoEntryMinimal *DIE) {
|
const DWARFDebugInfoEntryMinimal *DIE) {
|
||||||
SubprogramDIEs.emplace_back(DIE, Unit);
|
SubprogramDIEs.emplace_back(DIE, Unit);
|
||||||
|
if (!UnitLineTable.first) {
|
||||||
|
if (const auto *LineTable = BC.DwCtx->getLineTableForUnit(Unit)) {
|
||||||
|
UnitLineTable = std::make_pair(Unit, LineTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return all compilation units with entry for this function.
|
||||||
|
/// Because of identical code folding there could be multiple of these.
|
||||||
const decltype(SubprogramDIEs) &getSubprogramDIEs() const {
|
const decltype(SubprogramDIEs) &getSubprogramDIEs() const {
|
||||||
return SubprogramDIEs;
|
return SubprogramDIEs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return DWARF compile unit with line info.
|
/// Return DWARF compile unit with line info for this function.
|
||||||
DWARFUnitLineTable getDWARFUnitLineTable() const {
|
DWARFUnitLineTable getDWARFUnitLineTable() const {
|
||||||
for (auto &DIEUnitPair : SubprogramDIEs) {
|
return UnitLineTable;
|
||||||
if (auto *LT = BC.DwCtx->getLineTableForUnit(DIEUnitPair.second)) {
|
|
||||||
return std::make_pair(DIEUnitPair.second, LT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(nullptr, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the size of the basic block in the original binary.
|
/// Returns the size of the basic block in the original binary.
|
||||||
|
|
Loading…
Reference in New Issue