aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp306
1 files changed, 127 insertions, 179 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 230ea46..aa1f79f 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -12,16 +12,16 @@
//===----------------------------------------------------------------------===//
#include "DwarfDebug.h"
-
#include "ByteStreamer.h"
-#include "DwarfCompileUnit.h"
-#include "DIE.h"
#include "DIEHash.h"
+#include "DwarfCompileUnit.h"
+#include "DwarfExpression.h"
#include "DwarfUnit.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/Constants.h"
@@ -490,9 +490,6 @@ void DwarfDebug::beginModule() {
// Tell MMI that we have debug info.
MMI->setDebugInfoAvailability(true);
-
- // Prime section data.
- SectionMap[Asm->getObjFileLowering().getTextSection()];
}
void DwarfDebug::finishVariableDefinitions() {
@@ -608,53 +605,6 @@ void DwarfDebug::finalizeModuleInfo() {
SkeletonHolder.computeSizeAndOffsets();
}
-void DwarfDebug::endSections() {
- // Filter labels by section.
- for (const SymbolCU &SCU : ArangeLabels) {
- if (SCU.Sym->isInSection()) {
- // Make a note of this symbol and it's section.
- const MCSection *Section = &SCU.Sym->getSection();
- if (!Section->getKind().isMetadata())
- SectionMap[Section].push_back(SCU);
- } else {
- // Some symbols (e.g. common/bss on mach-o) can have no section but still
- // appear in the output. This sucks as we rely on sections to build
- // arange spans. We can do it without, but it's icky.
- SectionMap[nullptr].push_back(SCU);
- }
- }
-
- // Build a list of sections used.
- std::vector<const MCSection *> Sections;
- for (const auto &it : SectionMap) {
- const MCSection *Section = it.first;
- Sections.push_back(Section);
- }
-
- // Sort the sections into order.
- // This is only done to ensure consistent output order across different runs.
- std::sort(Sections.begin(), Sections.end(), SectionSort);
-
- // Add terminating symbols for each section.
- for (unsigned ID = 0, E = Sections.size(); ID != E; ID++) {
- const MCSection *Section = Sections[ID];
- MCSymbol *Sym = nullptr;
-
- if (Section) {
- // We can't call MCSection::getLabelEndName, as it's only safe to do so
- // if we know the section name up-front. For user-created sections, the
- // resulting label may not be valid to use as a label. (section names can
- // use a greater set of characters on some systems)
- Sym = Asm->GetTempSymbol("debug_end", ID);
- Asm->OutStreamer.SwitchSection(Section);
- Asm->OutStreamer.EmitLabel(Sym);
- }
-
- // Insert a final terminator.
- SectionMap[Section].push_back(SymbolCU(nullptr, Sym));
- }
-}
-
// Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {
assert(CurFn == nullptr);
@@ -666,10 +616,6 @@ void DwarfDebug::endModule() {
if (!DwarfInfoSectionSym)
return;
- // End any existing sections.
- // TODO: Does this need to happen?
- endSections();
-
// Finalize the debug info for the module.
finalizeModuleInfo();
@@ -783,10 +729,9 @@ void DwarfDebug::collectVariableInfoFromMMITable(
DIVariable DV(VI.Var);
DIExpression Expr(VI.Expr);
ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode());
- ConcreteVariables.push_back(make_unique<DbgVariable>(DV, Expr, this));
- DbgVariable *RegVar = ConcreteVariables.back().get();
- RegVar->setFrameIndex(VI.Slot);
- InfoHolder.addScopeVariable(Scope, RegVar);
+ auto RegVar = make_unique<DbgVariable>(DV, Expr, this, VI.Slot);
+ if (InfoHolder.addScopeVariable(Scope, RegVar.get()))
+ ConcreteVariables.push_back(std::move(RegVar));
}
}
@@ -818,12 +763,12 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
/// Determine whether two variable pieces overlap.
static bool piecesOverlap(DIExpression P1, DIExpression P2) {
- if (!P1.isVariablePiece() || !P2.isVariablePiece())
+ if (!P1.isBitPiece() || !P2.isBitPiece())
return true;
- unsigned l1 = P1.getPieceOffset();
- unsigned l2 = P2.getPieceOffset();
- unsigned r1 = l1 + P1.getPieceSize();
- unsigned r2 = l2 + P2.getPieceSize();
+ unsigned l1 = P1.getBitPieceOffset();
+ unsigned l2 = P2.getBitPieceOffset();
+ unsigned r1 = l1 + P1.getBitPieceSize();
+ unsigned r2 = l2 + P2.getBitPieceSize();
// True where [l1,r1[ and [r1,r2[ overlap.
return (l1 < r2) && (l2 < r1);
}
@@ -842,7 +787,8 @@ static bool piecesOverlap(DIExpression P1, DIExpression P2) {
// 1 | | [x, (reg1, piece 32, 32)] <- IsPieceOfPrevEntry
// 2 | | ...
// 3 | [clobber reg0]
-// 4 [x, (mem, piece 0, 64)] <- overlapping with both previous pieces of x.
+// 4 [x, (mem, piece 0, 64)] <- overlapping with both previous pieces of
+// x.
//
// Output:
//
@@ -894,7 +840,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
bool couldMerge = false;
// If this is a piece, it may belong to the current DebugLocEntry.
- if (DIExpr.isVariablePiece()) {
+ if (DIExpr.isBitPiece()) {
// Add this value to the list of open ranges.
OpenRanges.push_back(Value);
@@ -950,11 +896,9 @@ DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, DISubprogram SP,
continue;
LexicalScope *Scope = nullptr;
- if (MDNode *IA = DV.getInlinedAt()) {
- DebugLoc DL = DebugLoc::getFromDILocation(IA);
- Scope = LScopes.findInlinedScope(DebugLoc::get(
- DL.getLine(), DL.getCol(), DV.getContext(), IA));
- } else
+ if (MDNode *IA = DV.getInlinedAt())
+ Scope = LScopes.findInlinedScope(DV.getContext(), IA);
+ else
Scope = LScopes.findLexicalScope(DV.getContext());
// If variable scope is not found then skip this variable.
if (!Scope)
@@ -1026,8 +970,10 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
if (DL == PrologEndLoc) {
Flags |= DWARF2_FLAG_PROLOGUE_END;
PrologEndLoc = DebugLoc();
+ Flags |= DWARF2_FLAG_IS_STMT;
}
- if (PrologEndLoc.isUnknown())
+ if (DL.getLine() !=
+ Asm->OutStreamer.getContext().getCurrentDwarfLoc().getLine())
Flags |= DWARF2_FLAG_IS_STMT;
if (!DL.isUnknown()) {
@@ -1117,8 +1063,12 @@ static DebugLoc findPrologueEndLoc(const MachineFunction *MF) {
for (const auto &MBB : *MF)
for (const auto &MI : MBB)
if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) &&
- !MI.getDebugLoc().isUnknown())
+ !MI.getDebugLoc().isUnknown()) {
+ // Did the target forget to set the FrameSetup flag for CFI insns?
+ assert(!MI.isCFIInstruction() &&
+ "First non-frame-setup instruction is a CFI instruction.");
return MI.getDebugLoc();
+ }
return DebugLoc();
}
@@ -1172,7 +1122,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
Asm->OutStreamer.EmitLabel(FunctionBeginSym);
// Calculate history for local variables.
- calculateDbgValueHistory(MF, Asm->TM.getSubtargetImpl()->getRegisterInfo(),
+ calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(),
DbgValues);
// Request labels for the full history.
@@ -1187,7 +1137,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
if (DIVar.isVariable() && DIVar.getTag() == dwarf::DW_TAG_arg_variable &&
getDISubprogram(DIVar.getContext()).describes(MF->getFunction())) {
LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym;
- if (Ranges.front().first->getDebugExpression().isVariablePiece()) {
+ if (Ranges.front().first->getDebugExpression().isBitPiece()) {
// Mark all non-overlapping initial pieces.
for (auto I = Ranges.begin(); I != Ranges.end(); ++I) {
DIExpression Piece = I->first->getDebugExpression();
@@ -1217,12 +1167,12 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
if (!PrologEndLoc.isUnknown()) {
DebugLoc FnStartDL =
PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext());
- recordSourceLine(
- FnStartDL.getLine(), FnStartDL.getCol(),
- FnStartDL.getScope(MF->getFunction()->getContext()),
- // We'd like to list the prologue as "not statements" but GDB behaves
- // poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
- DWARF2_FLAG_IS_STMT);
+
+ // We'd like to list the prologue as "not statements" but GDB behaves
+ // poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
+ recordSourceLine(FnStartDL.getLine(), FnStartDL.getCol(),
+ FnStartDL.getScope(MF->getFunction()->getContext()),
+ DWARF2_FLAG_IS_STMT);
}
}
@@ -1350,8 +1300,8 @@ void DwarfDebug::emitSectionLabels() {
if (useSplitDwarf()) {
DwarfInfoDWOSectionSym =
emitSectionSym(Asm, TLOF.getDwarfInfoDWOSection(), "section_info_dwo");
- DwarfTypesDWOSectionSym =
- emitSectionSym(Asm, TLOF.getDwarfTypesDWOSection(), "section_types_dwo");
+ DwarfTypesDWOSectionSym = emitSectionSym(
+ Asm, TLOF.getDwarfTypesDWOSection(), "section_types_dwo");
}
DwarfAbbrevSectionSym =
emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
@@ -1553,7 +1503,6 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU,
return dwarf::GIEK_TYPE;
case dwarf::DW_TAG_subprogram:
return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_FUNCTION, Linkage);
- case dwarf::DW_TAG_constant:
case dwarf::DW_TAG_variable:
return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, Linkage);
case dwarf::DW_TAG_enumerator:
@@ -1656,7 +1605,7 @@ void DwarfDebug::emitLocPieces(ByteStreamer &Streamer,
const DITypeIdentifierMap &Map,
ArrayRef<DebugLocEntry::Value> Values) {
assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) {
- return P.isVariablePiece();
+ return P.isBitPiece();
}) && "all values are expected to be pieces");
assert(std::is_sorted(Values.begin(), Values.end()) &&
"pieces are expected to be sorted");
@@ -1664,35 +1613,25 @@ void DwarfDebug::emitLocPieces(ByteStreamer &Streamer,
unsigned Offset = 0;
for (auto Piece : Values) {
DIExpression Expr = Piece.getExpression();
- unsigned PieceOffset = Expr.getPieceOffset();
- unsigned PieceSize = Expr.getPieceSize();
+ unsigned PieceOffset = Expr.getBitPieceOffset();
+ unsigned PieceSize = Expr.getBitPieceSize();
assert(Offset <= PieceOffset && "overlapping or duplicate pieces");
if (Offset < PieceOffset) {
// The DWARF spec seriously mandates pieces with no locations for gaps.
- Asm->EmitDwarfOpPiece(Streamer, (PieceOffset-Offset)*8);
+ Asm->EmitDwarfOpPiece(Streamer, PieceOffset-Offset);
Offset += PieceOffset-Offset;
}
-
Offset += PieceSize;
- const unsigned SizeOfByte = 8;
#ifndef NDEBUG
DIVariable Var = Piece.getVariable();
- assert(!Var.isIndirect() && "indirect address for piece");
unsigned VarSize = Var.getSizeInBits(Map);
- assert(PieceSize+PieceOffset <= VarSize/SizeOfByte
+ assert(PieceSize+PieceOffset <= VarSize
&& "piece is larger than or outside of variable");
- assert(PieceSize*SizeOfByte != VarSize
+ assert(PieceSize != VarSize
&& "piece covers entire variable");
#endif
- if (Piece.isLocation() && Piece.getLoc().isReg())
- Asm->EmitDwarfRegOpPiece(Streamer,
- Piece.getLoc(),
- PieceSize*SizeOfByte);
- else {
- emitDebugLocValue(Streamer, Piece);
- Asm->EmitDwarfOpPiece(Streamer, PieceSize*SizeOfByte);
- }
+ emitDebugLocValue(Streamer, Piece, PieceOffset);
}
}
@@ -1700,7 +1639,7 @@ void DwarfDebug::emitLocPieces(ByteStreamer &Streamer,
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
const DebugLocEntry &Entry) {
const DebugLocEntry::Value Value = Entry.getValues()[0];
- if (Value.isVariablePiece())
+ if (Value.isBitPiece())
// Emit all pieces that belong to the same variable and range.
return emitLocPieces(Streamer, TypeIdentifierMap, Entry.getValues());
@@ -1709,62 +1648,33 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
}
void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer,
- const DebugLocEntry::Value &Value) {
+ const DebugLocEntry::Value &Value,
+ unsigned PieceOffsetInBits) {
DIVariable DV = Value.getVariable();
+ DebugLocDwarfExpression DwarfExpr(*Asm, Streamer);
+
// Regular entry.
if (Value.isInt()) {
DIBasicType BTy(resolve(DV.getType()));
if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed ||
- BTy.getEncoding() == dwarf::DW_ATE_signed_char)) {
- Streamer.EmitInt8(dwarf::DW_OP_consts, "DW_OP_consts");
- Streamer.EmitSLEB128(Value.getInt());
- } else {
- Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu");
- Streamer.EmitULEB128(Value.getInt());
- }
+ BTy.getEncoding() == dwarf::DW_ATE_signed_char))
+ DwarfExpr.AddSignedConstant(Value.getInt());
+ else
+ DwarfExpr.AddUnsignedConstant(Value.getInt());
} else if (Value.isLocation()) {
MachineLocation Loc = Value.getLoc();
DIExpression Expr = Value.getExpression();
- if (!Expr)
+ if (!Expr || (Expr.getNumElements() == 0))
// Regular entry.
- Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
+ Asm->EmitDwarfRegOp(Streamer, Loc);
else {
// Complex address entry.
- unsigned N = Expr.getNumElements();
- unsigned i = 0;
- if (N >= 2 && Expr.getElement(0) == dwarf::DW_OP_plus) {
- if (Loc.getOffset()) {
- i = 2;
- Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
- Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
- Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst");
- Streamer.EmitSLEB128(Expr.getElement(1));
- } else {
- // If first address element is OpPlus then emit
- // DW_OP_breg + Offset instead of DW_OP_reg + Offset.
- MachineLocation TLoc(Loc.getReg(), Expr.getElement(1));
- Asm->EmitDwarfRegOp(Streamer, TLoc, DV.isIndirect());
- i = 2;
- }
- } else {
- Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
- }
-
- // Emit remaining complex address elements.
- for (; i < N; ++i) {
- uint64_t Element = Expr.getElement(i);
- if (Element == dwarf::DW_OP_plus) {
- Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst");
- Streamer.EmitULEB128(Expr.getElement(++i));
- } else if (Element == dwarf::DW_OP_deref) {
- if (!Loc.isReg())
- Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
- } else if (Element == dwarf::DW_OP_piece) {
- i += 3;
- // handled in emitDebugLocEntry.
- } else
- llvm_unreachable("unknown Opcode found in complex address");
- }
+ if (Loc.getOffset()) {
+ DwarfExpr.AddMachineRegIndirect(Loc.getReg(), Loc.getOffset());
+ DwarfExpr.AddExpression(Expr.begin(), Expr.end(), PieceOffsetInBits);
+ } else
+ DwarfExpr.AddMachineRegExpression(Expr, Loc.getReg(),
+ PieceOffsetInBits);
}
}
// else ... ignore constant fp. There is not any good way to
@@ -1841,13 +1751,26 @@ struct ArangeSpan {
// Emit a debug aranges section, containing a CU lookup for any
// address we can tie back to a CU.
void DwarfDebug::emitDebugARanges() {
- // Start the dwarf aranges section.
- Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfARangesSection());
+ // Provides a unique id per text section.
+ DenseMap<const MCSection *, SmallVector<SymbolCU, 8>> SectionMap;
- typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> SpansType;
+ // Prime section data.
+ SectionMap[Asm->getObjFileLowering().getTextSection()];
- SpansType Spans;
+ // Filter labels by section.
+ for (const SymbolCU &SCU : ArangeLabels) {
+ if (SCU.Sym->isInSection()) {
+ // Make a note of this symbol and it's section.
+ const MCSection *Section = &SCU.Sym->getSection();
+ if (!Section->getKind().isMetadata())
+ SectionMap[Section].push_back(SCU);
+ } else {
+ // Some symbols (e.g. common/bss on mach-o) can have no section but still
+ // appear in the output. This sucks as we rely on sections to build
+ // arange spans. We can do it without, but it's icky.
+ SectionMap[nullptr].push_back(SCU);
+ }
+ }
// Build a list of sections used.
std::vector<const MCSection *> Sections;
@@ -1860,12 +1783,45 @@ void DwarfDebug::emitDebugARanges() {
// This is only done to ensure consistent output order across different runs.
std::sort(Sections.begin(), Sections.end(), SectionSort);
- // Build a set of address spans, sorted by CU.
+ // Add terminating symbols for each section.
+ for (unsigned ID = 0, E = Sections.size(); ID != E; ID++) {
+ const MCSection *Section = Sections[ID];
+ MCSymbol *Sym = nullptr;
+
+ if (Section) {
+ // We can't call MCSection::getLabelEndName, as it's only safe to do so
+ // if we know the section name up-front. For user-created sections, the
+ // resulting label may not be valid to use as a label. (section names can
+ // use a greater set of characters on some systems)
+ Sym = Asm->GetTempSymbol("debug_end", ID);
+ Asm->OutStreamer.SwitchSection(Section);
+ Asm->OutStreamer.EmitLabel(Sym);
+ }
+
+ // Insert a final terminator.
+ SectionMap[Section].push_back(SymbolCU(nullptr, Sym));
+ }
+
+ DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> Spans;
+
for (const MCSection *Section : Sections) {
SmallVector<SymbolCU, 8> &List = SectionMap[Section];
if (List.size() < 2)
continue;
+ // If we have no section (e.g. common), just write out
+ // individual spans for each symbol.
+ if (!Section) {
+ for (const SymbolCU &Cur : List) {
+ ArangeSpan Span;
+ Span.Start = Cur.Sym;
+ Span.End = nullptr;
+ if (Cur.CU)
+ Spans[Cur.CU].push_back(Span);
+ }
+ continue;
+ }
+
// Sort the symbols by offset within the section.
std::sort(List.begin(), List.end(),
[&](const SymbolCU &A, const SymbolCU &B) {
@@ -1881,35 +1837,27 @@ void DwarfDebug::emitDebugARanges() {
return IA < IB;
});
- // If we have no section (e.g. common), just write out
- // individual spans for each symbol.
- if (!Section) {
- for (const SymbolCU &Cur : List) {
+ // Build spans between each label.
+ const MCSymbol *StartSym = List[0].Sym;
+ for (size_t n = 1, e = List.size(); n < e; n++) {
+ const SymbolCU &Prev = List[n - 1];
+ const SymbolCU &Cur = List[n];
+
+ // Try and build the longest span we can within the same CU.
+ if (Cur.CU != Prev.CU) {
ArangeSpan Span;
- Span.Start = Cur.Sym;
- Span.End = nullptr;
- if (Cur.CU)
- Spans[Cur.CU].push_back(Span);
- }
- } else {
- // Build spans between each label.
- const MCSymbol *StartSym = List[0].Sym;
- for (size_t n = 1, e = List.size(); n < e; n++) {
- const SymbolCU &Prev = List[n - 1];
- const SymbolCU &Cur = List[n];
-
- // Try and build the longest span we can within the same CU.
- if (Cur.CU != Prev.CU) {
- ArangeSpan Span;
- Span.Start = StartSym;
- Span.End = Cur.Sym;
- Spans[Prev.CU].push_back(Span);
- StartSym = Cur.Sym;
- }
+ Span.Start = StartSym;
+ Span.End = Cur.Sym;
+ Spans[Prev.CU].push_back(Span);
+ StartSym = Cur.Sym;
}
}
}
+ // Start the dwarf aranges section.
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfARangesSection());
+
unsigned PtrSize = Asm->getDataLayout().getPointerSize();
// Build a list of CUs used.