Skip to content

Commit

Permalink
[DebugInfo] Generate DWARF debug information for labels. (Fix leak pr…
Browse files Browse the repository at this point in the history
…oblems)

There are two forms for label debug information in DWARF format.

1. Labels in a non-inlined function:

DW_TAG_label
  DW_AT_name
  DW_AT_decl_file
  DW_AT_decl_line
  DW_AT_low_pc

2. Labels in an inlined function:

DW_TAG_label
  DW_AT_abstract_origin
  DW_AT_low_pc

We will collect label information from DBG_LABEL. Before every DBG_LABEL,
we will generate a temporary symbol to denote the location of the label.
The symbol could be used to get DW_AT_low_pc afterwards. So, we create a
mapping between 'inlined label' and DBG_LABEL MachineInstr in DebugHandlerBase.
The DBG_LABEL in the mapping is used to query the symbol before it.

The AbstractLabels in DwarfCompileUnit is used to process labels in inlined
functions.

We also keep a mapping between scope and labels in DwarfFile to help to
generate correct tree structure of DIEs.

It also generates label debug information under global isel.

Differential Revision: https://reviews.llvm.org/D45556

llvm-svn: 340039
  • Loading branch information
Hsiangkai committed Aug 17, 2018
1 parent 5cd630d commit 2532ac8
Show file tree
Hide file tree
Showing 19 changed files with 534 additions and 149 deletions.
4 changes: 4 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
Expand Up @@ -208,6 +208,10 @@ class MachineIRBuilderBase {
const MDNode *Variable,
const MDNode *Expr);

/// Build and insert a DBG_LABEL instructions specifying that \p Label is
/// given. Convert "llvm.dbg.label Label" to "DBG_LABEL Label".
MachineInstrBuilder buildDbgLabel(const MDNode *Label);

/// Build and insert \p Res = G_FRAME_INDEX \p Idx
///
/// G_FRAME_INDEX materializes the address of an alloca value or other
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt
Expand Up @@ -5,7 +5,7 @@ add_llvm_library(LLVMAsmPrinter
AsmPrinter.cpp
AsmPrinterDwarf.cpp
AsmPrinterInlineAsm.cpp
DbgValueHistoryCalculator.cpp
DbgEntityHistoryCalculator.cpp
DebugHandlerBase.cpp
DebugLocStream.cpp
DIE.cpp
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
Expand Up @@ -14,7 +14,7 @@
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H

#include "DbgValueHistoryCalculator.h"
#include "DbgEntityHistoryCalculator.h"
#include "DebugHandlerBase.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
Expand Down
@@ -1,4 +1,4 @@
//===- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp --------------===//
//===- llvm/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp -------------===//
//
// The LLVM Compiler Infrastructure
//
Expand All @@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//

#include "DbgValueHistoryCalculator.h"
#include "DbgEntityHistoryCalculator.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -78,11 +78,17 @@ unsigned DbgValueHistoryMap::getRegisterForVar(InlinedVariable Var) const {
return isDescribedByReg(*Ranges.back().first);
}

void DbgLabelInstrMap::addInstr(InlinedLabel Label, const MachineInstr &MI) {
assert(MI.isDebugLabel() && "not a DBG_LABEL");
LabelInstr[Label] = &MI;
}

namespace {

// Maps physreg numbers to the variables they describe.
using InlinedVariable = DbgValueHistoryMap::InlinedVariable;
using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedVariable, 1>>;
using InlinedLabel = DbgLabelInstrMap::InlinedLabel;

} // end anonymous namespace

Expand Down Expand Up @@ -187,9 +193,10 @@ static void collectChangingRegs(const MachineFunction *MF,
}
}

void llvm::calculateDbgValueHistory(const MachineFunction *MF,
const TargetRegisterInfo *TRI,
DbgValueHistoryMap &Result) {
void llvm::calculateDbgEntityHistory(const MachineFunction *MF,
const TargetRegisterInfo *TRI,
DbgValueHistoryMap &DbgValues,
DbgLabelInstrMap &DbgLabels) {
BitVector ChangingRegs(TRI->getNumRegs());
collectChangingRegs(MF, TRI, ChangingRegs);

Expand All @@ -210,14 +217,14 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
// If this is a virtual register, only clobber it since it doesn't
// have aliases.
if (TRI->isVirtualRegister(MO.getReg()))
clobberRegisterUses(RegVars, MO.getReg(), Result, MI);
clobberRegisterUses(RegVars, MO.getReg(), DbgValues, MI);
// If this is a register def operand, it may end a debug value
// range.
else {
for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
++AI)
if (ChangingRegs.test(*AI))
clobberRegisterUses(RegVars, *AI, Result, MI);
clobberRegisterUses(RegVars, *AI, DbgValues, MI);
}
} else if (MO.isRegMask()) {
// If this is a register mask operand, clobber all debug values in
Expand All @@ -226,34 +233,42 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
// Don't consider SP to be clobbered by register masks.
if (unsigned(I) != SP && TRI->isPhysicalRegister(I) &&
MO.clobbersPhysReg(I)) {
clobberRegisterUses(RegVars, I, Result, MI);
clobberRegisterUses(RegVars, I, DbgValues, MI);
}
}
}
}
continue;
}

// Skip DBG_LABEL instructions.
if (MI.isDebugLabel())
continue;

assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!");
// Use the base variable (without any DW_OP_piece expressions)
// as index into History. The full variables including the
// piece expressions are attached to the MI.
const DILocalVariable *RawVar = MI.getDebugVariable();
assert(RawVar->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
"Expected inlined-at fields to agree");
InlinedVariable Var(RawVar, MI.getDebugLoc()->getInlinedAt());

if (unsigned PrevReg = Result.getRegisterForVar(Var))
dropRegDescribedVar(RegVars, PrevReg, Var);

Result.startInstrRange(Var, MI);

if (unsigned NewReg = isDescribedByReg(MI))
addRegDescribedVar(RegVars, NewReg, Var);
if (MI.isDebugValue()) {
assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!");
// Use the base variable (without any DW_OP_piece expressions)
// as index into History. The full variables including the
// piece expressions are attached to the MI.
const DILocalVariable *RawVar = MI.getDebugVariable();
assert(RawVar->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
"Expected inlined-at fields to agree");
InlinedVariable Var(RawVar, MI.getDebugLoc()->getInlinedAt());

if (unsigned PrevReg = DbgValues.getRegisterForVar(Var))
dropRegDescribedVar(RegVars, PrevReg, Var);

DbgValues.startInstrRange(Var, MI);

if (unsigned NewReg = isDescribedByReg(MI))
addRegDescribedVar(RegVars, NewReg, Var);
} else if (MI.isDebugLabel()) {
assert(MI.getNumOperands() == 1 && "Invalid DBG_LABEL instruction!");
const DILabel *RawLabel = MI.getDebugLabel();
assert(RawLabel->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
"Expected inlined-at fields to agree");
// When collecting debug information for labels, there is no MCSymbol
// generated for it. So, we keep MachineInstr in DbgLabels in order
// to query MCSymbol afterward.
InlinedLabel L(RawLabel, MI.getDebugLoc()->getInlinedAt());
DbgLabels.addInstr(L, MI);
}
}

// Make sure locations for register-described variables are valid only
Expand All @@ -264,7 +279,7 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
auto CurElem = I++; // CurElem can be erased below.
if (TRI->isVirtualRegister(CurElem->first) ||
ChangingRegs.test(CurElem->first))
clobberRegisterUses(RegVars, CurElem, Result, MBB.back());
clobberRegisterUses(RegVars, CurElem, DbgValues, MBB.back());
}
}
}
Expand Down
@@ -1,4 +1,4 @@
//===- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h ------*- C++ -*-===//
//===- llvm/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.h -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
Expand Down Expand Up @@ -58,9 +58,30 @@ class DbgValueHistoryMap {
#endif
};

void calculateDbgValueHistory(const MachineFunction *MF,
const TargetRegisterInfo *TRI,
DbgValueHistoryMap &Result);
/// For each inlined instance of a source-level label, keep the corresponding
/// DBG_LABEL instruction. The DBG_LABEL instruction could be used to generate
/// a temporary (assembler) label before it.
class DbgLabelInstrMap {
public:
using InlinedLabel = std::pair<const DILabel *, const DILocation *>;
using InstrMap = MapVector<InlinedLabel, const MachineInstr *>;

private:
InstrMap LabelInstr;

public:
void addInstr(InlinedLabel Label, const MachineInstr &MI);

bool empty() const { return LabelInstr.empty(); }
void clear() { LabelInstr.clear(); }
InstrMap::const_iterator begin() const { return LabelInstr.begin(); }
InstrMap::const_iterator end() const { return LabelInstr.end(); }
};

void calculateDbgEntityHistory(const MachineFunction *MF,
const TargetRegisterInfo *TRI,
DbgValueHistoryMap &DbgValues,
DbgLabelInstrMap &DbgLabels);

} // end namespace llvm

Expand Down
12 changes: 10 additions & 2 deletions llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
Expand Up @@ -190,8 +190,9 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) {

// Calculate history for local variables.
assert(DbgValues.empty() && "DbgValues map wasn't cleaned!");
calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(),
DbgValues);
assert(DbgLabels.empty() && "DbgLabels map wasn't cleaned!");
calculateDbgEntityHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(),
DbgValues, DbgLabels);
LLVM_DEBUG(DbgValues.dump());

// Request labels for the full history.
Expand Down Expand Up @@ -229,6 +230,12 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) {
}
}

// Ensure there is a symbol before DBG_LABEL.
for (const auto &I : DbgLabels) {
const MachineInstr *MI = I.second;
requestLabelBeforeInsn(MI);
}

PrevInstLoc = DebugLoc();
PrevLabel = Asm->getFunctionBegin();
beginFunctionImpl(MF);
Expand Down Expand Up @@ -296,6 +303,7 @@ void DebugHandlerBase::endFunction(const MachineFunction *MF) {
if (hasDebugInfo(MMI, MF))
endFunctionImpl(MF);
DbgValues.clear();
DbgLabels.clear();
LabelsBeforeInsn.clear();
LabelsAfterInsn.clear();
}
5 changes: 4 additions & 1 deletion llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
Expand Up @@ -16,7 +16,7 @@
#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGHANDLERBASE_H

#include "AsmPrinterHandler.h"
#include "DbgValueHistoryCalculator.h"
#include "DbgEntityHistoryCalculator.h"
#include "llvm/ADT/Optional.h"
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/CodeGen/MachineInstr.h"
Expand Down Expand Up @@ -82,6 +82,9 @@ class DebugHandlerBase : public AsmPrinterHandler {
/// variable. Variables are listed in order of appearance.
DbgValueHistoryMap DbgValues;

/// Mapping of inlined labels and DBG_LABEL machine instruction.
DbgLabelInstrMap DbgLabels;

/// Maps instruction with label emitted before instruction.
/// FIXME: Make this private from DwarfDebug, we have the necessary accessors
/// for it.
Expand Down
88 changes: 62 additions & 26 deletions llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Expand Up @@ -513,6 +513,18 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) {
return D;
}

DIE *DwarfCompileUnit::constructLabelDIE(DbgLabel &DL,
const LexicalScope &Scope) {
auto LabelDie = DIE::get(DIEValueAllocator, DL.getTag());
insertDIE(DL.getLabel(), LabelDie);
DL.setDIE(*LabelDie);

if (Scope.isAbstractScope())
applyLabelAttributes(DL, *LabelDie);

return LabelDie;
}

DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
bool Abstract) {
// Define variable debug information entry.
Expand Down Expand Up @@ -706,6 +718,9 @@ DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
if (HasNonScopeChildren)
*HasNonScopeChildren = !Children.empty();

for (DbgLabel *DL : DU->getScopeLabels().lookup(Scope))
Children.push_back(constructLabelDIE(*DL, *Scope));

for (LexicalScope *LS : Scope->getChildren())
constructScopeDIE(LS, Children);

Expand Down Expand Up @@ -831,40 +846,52 @@ void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) {
}
}

void DwarfCompileUnit::finishVariableDefinition(const DbgVariable &Var) {
DbgVariable *AbsVar = getExistingAbstractVariable(
InlinedVariable(Var.getVariable(), Var.getInlinedAt()));
auto *VariableDie = Var.getDIE();
if (AbsVar && AbsVar->getDIE()) {
addDIEEntry(*VariableDie, dwarf::DW_AT_abstract_origin,
*AbsVar->getDIE());
} else
applyVariableAttributes(Var, *VariableDie);
}
void DwarfCompileUnit::finishEntityDefinition(const DbgEntity *Entity) {
DbgEntity *AbsEntity = getExistingAbstractEntity(Entity->getEntity());

auto *Die = Entity->getDIE();
/// Label may be used to generate DW_AT_low_pc, so put it outside
/// if/else block.
const DbgLabel *Label = nullptr;
if (AbsEntity && AbsEntity->getDIE()) {
addDIEEntry(*Die, dwarf::DW_AT_abstract_origin, *AbsEntity->getDIE());
Label = dyn_cast<const DbgLabel>(Entity);
} else {
if (const DbgVariable *Var = dyn_cast<const DbgVariable>(Entity))
applyVariableAttributes(*Var, *Die);
else if ((Label = dyn_cast<const DbgLabel>(Entity)))
applyLabelAttributes(*Label, *Die);
else
llvm_unreachable("DbgEntity must be DbgVariable or DbgLabel.");
}

DbgVariable *DwarfCompileUnit::getExistingAbstractVariable(InlinedVariable IV) {
const DILocalVariable *Cleansed;
return getExistingAbstractVariable(IV, Cleansed);
if (Label) {
const MCSymbol *Sym = Label->getSymbol();
addLabelAddress(*Die, dwarf::DW_AT_low_pc, Sym);
}
}

// Find abstract variable, if any, associated with Var.
DbgVariable *DwarfCompileUnit::getExistingAbstractVariable(
InlinedVariable IV, const DILocalVariable *&Cleansed) {
// More then one inlined variable corresponds to one abstract variable.
Cleansed = IV.first;
auto &AbstractVariables = getAbstractVariables();
auto I = AbstractVariables.find(Cleansed);
if (I != AbstractVariables.end())
DbgEntity *DwarfCompileUnit::getExistingAbstractEntity(const DINode *Node) {
auto &AbstractEntities = getAbstractEntities();
auto I = AbstractEntities.find(Node);
if (I != AbstractEntities.end())
return I->second.get();
return nullptr;
}

void DwarfCompileUnit::createAbstractVariable(const DILocalVariable *Var,
LexicalScope *Scope) {
void DwarfCompileUnit::createAbstractEntity(const DINode *Node,
LexicalScope *Scope) {
assert(Scope && Scope->isAbstractScope());
auto AbsDbgVariable = llvm::make_unique<DbgVariable>(Var, /* IA */ nullptr);
DU->addScopeVariable(Scope, AbsDbgVariable.get());
getAbstractVariables()[Var] = std::move(AbsDbgVariable);
auto &Entity = getAbstractEntities()[Node];
if (isa<const DILocalVariable>(Node)) {
Entity = llvm::make_unique<DbgVariable>(
cast<const DILocalVariable>(Node), nullptr /* IA */);;
DU->addScopeVariable(Scope, cast<DbgVariable>(Entity.get()));
} else if (isa<const DILabel>(Node)) {
Entity = llvm::make_unique<DbgLabel>(
cast<const DILabel>(Node), nullptr /* IA */);
DU->addScopeLabel(Scope, cast<DbgLabel>(Entity.get()));
}
}

void DwarfCompileUnit::emitHeader(bool UseOffsets) {
Expand Down Expand Up @@ -1024,6 +1051,15 @@ void DwarfCompileUnit::applyVariableAttributes(const DbgVariable &Var,
addFlag(VariableDie, dwarf::DW_AT_artificial);
}

void DwarfCompileUnit::applyLabelAttributes(const DbgLabel &Label,
DIE &LabelDie) {
StringRef Name = Label.getName();
if (!Name.empty())
addString(LabelDie, dwarf::DW_AT_name, Name);
const auto *DILabel = Label.getLabel();
addSourceLine(LabelDie, DILabel);
}

/// Add a Dwarf expression attribute data and value.
void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form,
const MCExpr *Expr) {
Expand Down

0 comments on commit 2532ac8

Please sign in to comment.