summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp372
1 files changed, 227 insertions, 145 deletions
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 7fba768..91a3d09 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -62,11 +62,6 @@ static cl::opt<bool>
DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
cl::desc("Disable debug info printing"));
-static cl::opt<bool> UnknownLocations(
- "use-unknown-locations", cl::Hidden,
- cl::desc("Make an absence of debug location information explicit."),
- cl::init(false));
-
static cl::opt<bool>
GenerateGnuPubSections("generate-gnu-dwarf-pub-sections", cl::Hidden,
cl::desc("Generate GNU-style pubnames and pubtypes"),
@@ -81,12 +76,19 @@ namespace {
enum DefaultOnOff { Default, Enable, Disable };
}
+static cl::opt<DefaultOnOff> UnknownLocations(
+ "use-unknown-locations", cl::Hidden,
+ cl::desc("Make an absence of debug location information explicit."),
+ cl::values(clEnumVal(Default, "At top of block or after label"),
+ clEnumVal(Enable, "In all cases"), clEnumVal(Disable, "Never")),
+ cl::init(Default));
+
static cl::opt<DefaultOnOff>
DwarfAccelTables("dwarf-accel-tables", cl::Hidden,
cl::desc("Output prototype dwarf accelerator tables."),
cl::values(clEnumVal(Default, "Default for platform"),
clEnumVal(Enable, "Enabled"),
- clEnumVal(Disable, "Disabled"), clEnumValEnd),
+ clEnumVal(Disable, "Disabled")),
cl::init(Default));
static cl::opt<DefaultOnOff>
@@ -94,7 +96,7 @@ SplitDwarf("split-dwarf", cl::Hidden,
cl::desc("Output DWARF5 split debug info."),
cl::values(clEnumVal(Default, "Default for platform"),
clEnumVal(Enable, "Enabled"),
- clEnumVal(Disable, "Disabled"), clEnumValEnd),
+ clEnumVal(Disable, "Disabled")),
cl::init(Default));
static cl::opt<DefaultOnOff>
@@ -102,7 +104,7 @@ DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden,
cl::desc("Generate DWARF pubnames and pubtypes sections"),
cl::values(clEnumVal(Default, "Default for platform"),
clEnumVal(Enable, "Enabled"),
- clEnumVal(Disable, "Disabled"), clEnumValEnd),
+ clEnumVal(Disable, "Disabled")),
cl::init(Default));
enum LinkageNameOption {
@@ -117,12 +119,13 @@ static cl::opt<LinkageNameOption>
"Default for platform"),
clEnumValN(AllLinkageNames, "All", "All"),
clEnumValN(AbstractLinkageNames, "Abstract",
- "Abstract subprograms"),
- clEnumValEnd),
+ "Abstract subprograms")),
cl::init(DefaultLinkageNames));
-static const char *const DWARFGroupName = "DWARF Emission";
-static const char *const DbgTimerName = "DWARF Debug Writer";
+static const char *const DWARFGroupName = "dwarf";
+static const char *const DWARFGroupDescription = "DWARF Emission";
+static const char *const DbgTimerName = "writer";
+static const char *const DbgTimerDescription = "DWARF Debug Writer";
void DebugLocDwarfExpression::EmitOp(uint8_t Op, const char *Comment) {
BS.EmitInt8(
@@ -196,7 +199,16 @@ const DIType *DbgVariable::getType() const {
return Ty;
}
-static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = {
+ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const {
+ std::sort(FrameIndexExprs.begin(), FrameIndexExprs.end(),
+ [](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool {
+ return A.Expr->getFragmentInfo()->OffsetInBits <
+ B.Expr->getFragmentInfo()->OffsetInBits;
+ });
+ return FrameIndexExprs;
+}
+
+static const DwarfAccelTable::Atom TypeAtoms[] = {
DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)};
@@ -205,7 +217,7 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
: DebugHandlerBase(A), DebugLocs(A->OutStreamer->isVerboseAsm()),
InfoHolder(A, "info_string", DIEValueAllocator),
SkeletonHolder(A, "skel_string", DIEValueAllocator),
- IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()),
+ IsDarwin(A->TM.getTargetTriple().isOSDarwin()),
AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
dwarf::DW_FORM_data4)),
AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
@@ -215,7 +227,7 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
AccelTypes(TypeAtoms), DebuggerTuning(DebuggerKind::Default) {
CurFn = nullptr;
- Triple TT(Asm->getTargetTriple());
+ const Triple &TT = Asm->TM.getTargetTriple();
// Make sure we know our "debugger tuning." The target option takes
// precedence; fall back to triple-based defaults.
@@ -255,7 +267,7 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
UseAllLinkageNames = DwarfLinkageNames == AllLinkageNames;
unsigned DwarfVersionNumber = Asm->TM.Options.MCOptions.DwarfVersion;
- DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber
+ unsigned DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber
: MMI->getModule()->getDwarfVersion();
// Use dwarf 4 by default if nothing is requested.
DwarfVersion = DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION;
@@ -349,10 +361,11 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) {
return !getLabelAfterInsn(Ranges.front().second);
}
-template <typename Func> void forBothCUs(DwarfCompileUnit &CU, Func F) {
+template <typename Func> static void forBothCUs(DwarfCompileUnit &CU, Func F) {
F(CU);
if (auto *SkelCU = CU.getSkeleton())
- F(*SkelCU);
+ if (CU.getCUNode()->getSplitDebugInlining())
+ F(*SkelCU);
}
void DwarfDebug::constructAbstractSubprogramScopeDIE(LexicalScope *Scope) {
@@ -360,13 +373,13 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(LexicalScope *Scope) {
assert(Scope->isAbstractScope());
assert(!Scope->getInlinedAt());
- const MDNode *SP = Scope->getScopeNode();
+ auto *SP = cast<DISubprogram>(Scope->getScopeNode());
ProcessedSPNodes.insert(SP);
// Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
// was inlined from another compile unit.
- auto &CU = *CUMap.lookup(cast<DISubprogram>(SP)->getUnit());
+ auto &CU = *CUMap.lookup(SP->getUnit());
forBothCUs(CU, [&](DwarfCompileUnit &CU) {
CU.constructAbstractSubprogramScopeDIE(Scope);
});
@@ -435,9 +448,9 @@ DwarfDebug::constructDwarfCompileUnit(const DICompileUnit *DIUnit) {
}
if (useSplitDwarf())
- NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection());
+ NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection());
else
- NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection());
+ NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());
if (DIUnit->getDWOId()) {
// This CU is either a clang module DWO or a skeleton CU.
@@ -449,8 +462,8 @@ DwarfDebug::constructDwarfCompileUnit(const DICompileUnit *DIUnit) {
DIUnit->getSplitDebugFilename());
}
- CUMap.insert(std::make_pair(DIUnit, &NewCU));
- CUDieMap.insert(std::make_pair(&Die, &NewCU));
+ CUMap.insert({DIUnit, &NewCU});
+ CUDieMap.insert({&Die, &NewCU});
return NewCU;
}
@@ -460,11 +473,34 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
D->addChild(TheCU.constructImportedEntityDIE(N));
}
+/// Sort and unique GVEs by comparing their fragment offset.
+static SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &
+sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) {
+ std::sort(GVEs.begin(), GVEs.end(),
+ [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) {
+ if (A.Expr != B.Expr && A.Expr && B.Expr) {
+ auto FragmentA = A.Expr->getFragmentInfo();
+ auto FragmentB = B.Expr->getFragmentInfo();
+ if (FragmentA && FragmentB)
+ return FragmentA->OffsetInBits < FragmentB->OffsetInBits;
+ }
+ return false;
+ });
+ GVEs.erase(std::unique(GVEs.begin(), GVEs.end(),
+ [](DwarfCompileUnit::GlobalExpr A,
+ DwarfCompileUnit::GlobalExpr B) {
+ return A.Expr == B.Expr;
+ }),
+ GVEs.end());
+ return GVEs;
+}
+
// Emit all Dwarf sections that should come prior to the content. Create
// global DIEs and emit initial debug info sections. This is invoked by
// the target AsmPrinter.
void DwarfDebug::beginModule() {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
+ NamedRegionTimer T(DbgTimerName, DbgTimerDescription, DWARFGroupName,
+ DWARFGroupDescription, TimePassesIsEnabled);
if (DisableDebugInfoPrinting)
return;
@@ -475,13 +511,30 @@ void DwarfDebug::beginModule() {
// Tell MMI whether we have debug info.
MMI->setDebugInfoAvailability(NumDebugCUs > 0);
SingleCU = NumDebugCUs == 1;
+ DenseMap<DIGlobalVariable *, SmallVector<DwarfCompileUnit::GlobalExpr, 1>>
+ GVMap;
+ for (const GlobalVariable &Global : M->globals()) {
+ SmallVector<DIGlobalVariableExpression *, 1> GVs;
+ Global.getDebugInfo(GVs);
+ for (auto *GVE : GVs)
+ GVMap[GVE->getVariable()].push_back({&Global, GVE->getExpression()});
+ }
for (DICompileUnit *CUNode : M->debug_compile_units()) {
DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode);
for (auto *IE : CUNode->getImportedEntities())
CU.addImportedEntity(IE);
- for (auto *GV : CUNode->getGlobalVariables())
- CU.getOrCreateGlobalVariableDIE(GV);
+
+ // Global Variables.
+ for (auto *GVE : CUNode->getGlobalVariables())
+ GVMap[GVE->getVariable()].push_back({nullptr, GVE->getExpression()});
+ DenseSet<DIGlobalVariable *> Processed;
+ for (auto *GVE : CUNode->getGlobalVariables()) {
+ DIGlobalVariable *GV = GVE->getVariable();
+ if (Processed.insert(GV).second)
+ CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV]));
+ }
+
for (auto *Ty : CUNode->getEnumTypes()) {
// The enum types array by design contains pointers to
// MDNodes rather than DIRefs. Unique them here.
@@ -509,7 +562,7 @@ void DwarfDebug::finishVariableDefinitions() {
// FIXME: Consider the time-space tradeoff of just storing the unit pointer
// in the ConcreteVariables list, rather than looking it up again here.
// DIE::getUnit isn't simple - it walks parent pointers, etc.
- DwarfCompileUnit *Unit = lookupUnit(VariableDie->getUnit());
+ DwarfCompileUnit *Unit = CUDieMap.lookup(VariableDie->getUnitDie());
assert(Unit);
DbgVariable *AbsVar = getExistingAbstractVariable(
InlinedVariable(Var->getVariable(), Var->getInlinedAt()));
@@ -522,13 +575,11 @@ void DwarfDebug::finishVariableDefinitions() {
}
void DwarfDebug::finishSubprogramDefinitions() {
- for (auto &F : MMI->getModule()->functions())
- if (auto *SP = F.getSubprogram())
- if (ProcessedSPNodes.count(SP) &&
- SP->getUnit()->getEmissionKind() != DICompileUnit::NoDebug)
- forBothCUs(*CUMap.lookup(SP->getUnit()), [&](DwarfCompileUnit &CU) {
- CU.finishSubprogramDefinition(SP);
- });
+ for (const DISubprogram *SP : ProcessedSPNodes)
+ if (SP->getUnit()->getEmissionKind() != DICompileUnit::NoDebug)
+ forBothCUs(*CUMap.lookup(SP->getUnit()), [&](DwarfCompileUnit &CU) {
+ CU.finishSubprogramDefinition(SP);
+ });
}
void DwarfDebug::finalizeModuleInfo() {
@@ -715,10 +766,10 @@ void DwarfDebug::ensureAbstractVariableIsCreatedIfScoped(
createAbstractVariable(Cleansed, Scope);
}
-// Collect variable information from side table maintained by MMI.
-void DwarfDebug::collectVariableInfoFromMMITable(
+// Collect variable information from side table maintained by MF.
+void DwarfDebug::collectVariableInfoFromMFTable(
DenseSet<InlinedVariable> &Processed) {
- for (const auto &VI : MMI->getVariableDbgInfo()) {
+ for (const auto &VI : Asm->MF->getVariableDbgInfo()) {
if (!VI.Var)
continue;
assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
@@ -765,7 +816,7 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!");
}
-/// \brief If this and Next are describing different pieces of the same
+/// \brief If this and Next are describing different fragments of the same
/// variable, merge them by appending Next's values to the current
/// list of values.
/// Return true if the merge was successful.
@@ -773,15 +824,15 @@ bool DebugLocEntry::MergeValues(const DebugLocEntry &Next) {
if (Begin == Next.Begin) {
auto *FirstExpr = cast<DIExpression>(Values[0].Expression);
auto *FirstNextExpr = cast<DIExpression>(Next.Values[0].Expression);
- if (!FirstExpr->isBitPiece() || !FirstNextExpr->isBitPiece())
+ if (!FirstExpr->isFragment() || !FirstNextExpr->isFragment())
return false;
- // We can only merge entries if none of the pieces overlap any others.
+ // We can only merge entries if none of the fragments overlap any others.
// In doing so, we can take advantage of the fact that both lists are
// sorted.
for (unsigned i = 0, j = 0; i < Values.size(); ++i) {
for (; j < Next.Values.size(); ++j) {
- int res = DebugHandlerBase::pieceCmp(
+ int res = DebugHandlerBase::fragmentCmp(
cast<DIExpression>(Values[i].Expression),
cast<DIExpression>(Next.Values[j].Expression));
if (res == 0) // The two expressions overlap, we can't merge.
@@ -804,27 +855,27 @@ bool DebugLocEntry::MergeValues(const DebugLocEntry &Next) {
/// Build the location list for all DBG_VALUEs in the function that
/// describe the same variable. If the ranges of several independent
-/// pieces of the same variable overlap partially, split them up and
+/// fragments of the same variable overlap partially, split them up and
/// combine the ranges. The resulting DebugLocEntries are will have
/// strict monotonically increasing begin addresses and will never
/// overlap.
//
// Input:
//
-// Ranges History [var, loc, piece ofs size]
-// 0 | [x, (reg0, piece 0, 32)]
-// 1 | | [x, (reg1, piece 32, 32)] <- IsPieceOfPrevEntry
+// Ranges History [var, loc, fragment ofs size]
+// 0 | [x, (reg0, fragment 0, 32)]
+// 1 | | [x, (reg1, fragment 32, 32)] <- IsFragmentOfPrevEntry
// 2 | | ...
// 3 | [clobber reg0]
-// 4 [x, (mem, piece 0, 64)] <- overlapping with both previous pieces of
+// 4 [x, (mem, fragment 0, 64)] <- overlapping with both previous fragments of
// x.
//
// Output:
//
-// [0-1] [x, (reg0, piece 0, 32)]
-// [1-3] [x, (reg0, piece 0, 32), (reg1, piece 32, 32)]
-// [3-4] [x, (reg1, piece 32, 32)]
-// [4- ] [x, (mem, piece 0, 64)]
+// [0-1] [x, (reg0, fragment 0, 32)]
+// [1-3] [x, (reg0, fragment 0, 32), (reg1, fragment 32, 32)]
+// [3-4] [x, (reg1, fragment 32, 32)]
+// [4- ] [x, (mem, fragment 0, 64)]
void
DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
const DbgValueHistoryMap::InstrRanges &Ranges) {
@@ -842,11 +893,10 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
continue;
}
- // If this piece overlaps with any open ranges, truncate them.
+ // If this fragment overlaps with any open ranges, truncate them.
const DIExpression *DIExpr = Begin->getDebugExpression();
- auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(),
- [&](DebugLocEntry::Value R) {
- return piecesOverlap(DIExpr, R.getExpression());
+ auto Last = remove_if(OpenRanges, [&](DebugLocEntry::Value R) {
+ return fragmentsOverlap(DIExpr, R.getExpression());
});
OpenRanges.erase(Last, OpenRanges.end());
@@ -868,12 +918,12 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
DebugLocEntry Loc(StartLabel, EndLabel, Value);
bool couldMerge = false;
- // If this is a piece, it may belong to the current DebugLocEntry.
- if (DIExpr->isBitPiece()) {
+ // If this is a fragment, it may belong to the current DebugLocEntry.
+ if (DIExpr->isFragment()) {
// Add this value to the list of open ranges.
OpenRanges.push_back(Value);
- // Attempt to add the piece to the last entry.
+ // Attempt to add the fragment to the last entry.
if (!DebugLoc.empty())
if (DebugLoc.back().MergeValues(Loc))
couldMerge = true;
@@ -881,7 +931,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
if (!couldMerge) {
// Need to add a new DebugLocEntry. Add all values from still
- // valid non-overlapping pieces.
+ // valid non-overlapping fragments.
if (OpenRanges.size())
Loc.addValues(OpenRanges);
@@ -929,7 +979,7 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,
const DISubprogram *SP,
DenseSet<InlinedVariable> &Processed) {
// Grab the variable info that was squirreled away in the MMI side-table.
- collectVariableInfoFromMMITable(Processed);
+ collectVariableInfoFromMFTable(Processed);
for (const auto &I : DbgValues) {
InlinedVariable IV = I.first;
@@ -996,30 +1046,82 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
DebugHandlerBase::beginInstruction(MI);
assert(CurMI);
- // Check if source location changes, but ignore DBG_VALUE locations.
- if (!MI->isDebugValue()) {
- const DebugLoc &DL = MI->getDebugLoc();
- if (DL != PrevInstLoc) {
- if (DL) {
- unsigned Flags = 0;
- PrevInstLoc = DL;
- if (DL == PrologEndLoc) {
- Flags |= DWARF2_FLAG_PROLOGUE_END;
- PrologEndLoc = DebugLoc();
- Flags |= DWARF2_FLAG_IS_STMT;
- }
- if (DL.getLine() !=
- Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine())
- Flags |= DWARF2_FLAG_IS_STMT;
-
- const MDNode *Scope = DL.getScope();
- recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
- } else if (UnknownLocations) {
- PrevInstLoc = DL;
- recordSourceLine(0, 0, nullptr, 0);
+ // Check if source location changes, but ignore DBG_VALUE and CFI locations.
+ if (MI->isDebugValue() || MI->isCFIInstruction())
+ return;
+ const DebugLoc &DL = MI->getDebugLoc();
+ // When we emit a line-0 record, we don't update PrevInstLoc; so look at
+ // the last line number actually emitted, to see if it was line 0.
+ unsigned LastAsmLine =
+ Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();
+
+ if (DL == PrevInstLoc) {
+ // If we have an ongoing unspecified location, nothing to do here.
+ if (!DL)
+ return;
+ // We have an explicit location, same as the previous location.
+ // But we might be coming back to it after a line 0 record.
+ if (LastAsmLine == 0 && DL.getLine() != 0) {
+ // Reinstate the source location but not marked as a statement.
+ const MDNode *Scope = DL.getScope();
+ recordSourceLine(DL.getLine(), DL.getCol(), Scope, /*Flags=*/0);
+ }
+ return;
+ }
+
+ if (!DL) {
+ // We have an unspecified location, which might want to be line 0.
+ // If we have already emitted a line-0 record, don't repeat it.
+ if (LastAsmLine == 0)
+ return;
+ // If user said Don't Do That, don't do that.
+ if (UnknownLocations == Disable)
+ return;
+ // See if we have a reason to emit a line-0 record now.
+ // Reasons to emit a line-0 record include:
+ // - User asked for it (UnknownLocations).
+ // - Instruction has a label, so it's referenced from somewhere else,
+ // possibly debug information; we want it to have a source location.
+ // - Instruction is at the top of a block; we don't want to inherit the
+ // location from the physically previous (maybe unrelated) block.
+ if (UnknownLocations == Enable || PrevLabel ||
+ (PrevInstBB && PrevInstBB != MI->getParent())) {
+ // Preserve the file and column numbers, if we can, to save space in
+ // the encoded line table.
+ // Do not update PrevInstLoc, it remembers the last non-0 line.
+ const MDNode *Scope = nullptr;
+ unsigned Column = 0;
+ if (PrevInstLoc) {
+ Scope = PrevInstLoc.getScope();
+ Column = PrevInstLoc.getCol();
}
+ recordSourceLine(/*Line=*/0, Column, Scope, /*Flags=*/0);
}
+ return;
+ }
+
+ // We have an explicit location, different from the previous location.
+ // Don't repeat a line-0 record, but otherwise emit the new location.
+ // (The new location might be an explicit line 0, which we do emit.)
+ if (PrevInstLoc && DL.getLine() == 0 && LastAsmLine == 0)
+ return;
+ unsigned Flags = 0;
+ if (DL == PrologEndLoc) {
+ Flags |= DWARF2_FLAG_PROLOGUE_END | DWARF2_FLAG_IS_STMT;
+ PrologEndLoc = DebugLoc();
}
+ // If the line changed, we call that a new statement; unless we went to
+ // line 0 and came back, in which case it is not a new statement.
+ unsigned OldLine = PrevInstLoc ? PrevInstLoc.getLine() : LastAsmLine;
+ if (DL.getLine() && DL.getLine() != OldLine)
+ Flags |= DWARF2_FLAG_IS_STMT;
+
+ const MDNode *Scope = DL.getScope();
+ recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
+
+ // If we're not at line 0, remember this location.
+ if (DL.getLine())
+ PrevInstLoc = DL;
}
static DebugLoc findPrologueEndLoc(const MachineFunction *MF) {
@@ -1093,18 +1195,14 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
"endFunction should be called with the same function as beginFunction");
const DISubprogram *SP = MF->getFunction()->getSubprogram();
- if (!MMI->hasDebugInfo() || LScopes.empty() || !SP ||
+ if (!MMI->hasDebugInfo() || !SP ||
SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug) {
- // If we don't have a lexical scope for this function then there will
- // be a hole in the range information. Keep note of this by setting the
- // previously used section to nullptr.
+ // If we don't have a subprogram for this function then there will be a hole
+ // in the range information. Keep note of this by setting the previously
+ // used section to nullptr.
PrevCU = nullptr;
CurFn = nullptr;
DebugHandlerBase::endFunction(MF);
- // Mark functions with no debug info on any instructions, but a
- // valid DISubprogram as processed.
- if (SP)
- ProcessedSPNodes.insert(SP);
return;
}
@@ -1112,7 +1210,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
Asm->OutStreamer->getContext().setDwarfCompileUnitID(0);
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
- SP = cast<DISubprogram>(FnScope->getScopeNode());
+ assert(!FnScope || SP == FnScope->getScopeNode());
DwarfCompileUnit &TheCU = *CUMap.lookup(SP->getUnit());
DenseSet<InlinedVariable> ProcessedVars;
@@ -1154,10 +1252,12 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
constructAbstractSubprogramScopeDIE(AScope);
}
- TheCU.constructSubprogramScopeDIE(FnScope);
+ ProcessedSPNodes.insert(SP);
+ TheCU.constructSubprogramScopeDIE(SP, FnScope);
if (auto *SkelCU = TheCU.getSkeleton())
- if (!LScopes.getAbstractScopesList().empty())
- SkelCU->constructSubprogramScopeDIE(FnScope);
+ if (!LScopes.getAbstractScopesList().empty() &&
+ TheCU.getCUNode()->getSplitDebugInlining())
+ SkelCU->constructSubprogramScopeDIE(SP, FnScope);
// Clear debug info
// Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the
@@ -1181,7 +1281,8 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
Fn = Scope->getFilename();
Dir = Scope->getDirectory();
if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope))
- Discriminator = LBF->getDiscriminator();
+ if (getDwarfVersion() >= 4)
+ Discriminator = LBF->getDiscriminator();
unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID();
Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
@@ -1396,9 +1497,9 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
ByteStreamer &Streamer,
const DebugLocEntry::Value &Value,
- unsigned PieceOffsetInBits) {
- DebugLocDwarfExpression DwarfExpr(AP.getDwarfDebug()->getDwarfVersion(),
- Streamer);
+ DwarfExpression &DwarfExpr) {
+ DIExpressionCursor ExprCursor(Value.getExpression());
+ DwarfExpr.addFragmentOffset(Value.getExpression());
// Regular entry.
if (Value.isInt()) {
if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
@@ -1408,25 +1509,16 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
DwarfExpr.AddUnsignedConstant(Value.getInt());
} else if (Value.isLocation()) {
MachineLocation Loc = Value.getLoc();
- const DIExpression *Expr = Value.getExpression();
- if (!Expr || !Expr->getNumElements())
- // Regular entry.
- AP.EmitDwarfRegOp(Streamer, Loc);
- else {
- // Complex address entry.
- const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();
- if (Loc.getOffset()) {
- DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset());
- DwarfExpr.AddExpression(Expr->expr_op_begin(), Expr->expr_op_end(),
- PieceOffsetInBits);
- } else
- DwarfExpr.AddMachineRegExpression(TRI, Expr, Loc.getReg(),
- PieceOffsetInBits);
- }
+ const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();
+ if (Loc.getOffset())
+ DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset());
+ else
+ DwarfExpr.AddMachineRegExpression(TRI, ExprCursor, Loc.getReg());
} else if (Value.isConstantFP()) {
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
DwarfExpr.AddUnsignedConstant(RawBytes);
}
+ DwarfExpr.AddExpression(std::move(ExprCursor));
}
void DebugLocEntry::finalize(const AsmPrinter &AP,
@@ -1434,36 +1526,24 @@ void DebugLocEntry::finalize(const AsmPrinter &AP,
const DIBasicType *BT) {
DebugLocStream::EntryBuilder Entry(List, Begin, End);
BufferByteStreamer Streamer = Entry.getStreamer();
+ DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer);
const DebugLocEntry::Value &Value = Values[0];
- if (Value.isBitPiece()) {
- // Emit all pieces that belong to the same variable and range.
- assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) {
- return P.isBitPiece();
- }) && "all values are expected to be pieces");
+ if (Value.isFragment()) {
+ // Emit all fragments that belong to the same variable and range.
+ assert(all_of(Values, [](DebugLocEntry::Value P) {
+ return P.isFragment();
+ }) && "all values are expected to be fragments");
assert(std::is_sorted(Values.begin(), Values.end()) &&
- "pieces are expected to be sorted");
-
- unsigned Offset = 0;
- for (auto Piece : Values) {
- const DIExpression *Expr = Piece.getExpression();
- 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.
- DebugLocDwarfExpression Expr(AP.getDwarfDebug()->getDwarfVersion(),
- Streamer);
- Expr.AddOpPiece(PieceOffset-Offset, 0);
- Offset += PieceOffset-Offset;
- }
- Offset += PieceSize;
+ "fragments are expected to be sorted");
+
+ for (auto Fragment : Values)
+ emitDebugLocValue(AP, BT, Streamer, Fragment, DwarfExpr);
- emitDebugLocValue(AP, BT, Streamer, Piece, PieceOffset);
- }
} else {
- assert(Values.size() == 1 && "only pieces may have >1 value");
- emitDebugLocValue(AP, BT, Streamer, Value, 0);
+ assert(Values.size() == 1 && "only fragments may have >1 value");
+ emitDebugLocValue(AP, BT, Streamer, Value, DwarfExpr);
}
+ DwarfExpr.finalize();
}
void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
@@ -1514,14 +1594,14 @@ void DwarfDebug::emitDebugLocDWO() {
// rather than two. We could get fancier and try to, say, reuse an
// address we know we've emitted elsewhere (the start of the function?
// The start of the CU or CU subrange that encloses this range?)
- Asm->EmitInt8(dwarf::DW_LLE_start_length_entry);
+ Asm->EmitInt8(dwarf::DW_LLE_startx_length);
unsigned idx = AddrPool.getIndex(Entry.BeginSym);
Asm->EmitULEB128(idx);
Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4);
emitDebugLocEntryLocation(Entry);
}
- Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry);
+ Asm->EmitInt8(dwarf::DW_LLE_end_of_list);
}
}
@@ -1807,7 +1887,7 @@ DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {
auto OwnedUnit = make_unique<DwarfCompileUnit>(
CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder);
DwarfCompileUnit &NewCU = *OwnedUnit;
- NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection());
+ NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());
NewCU.initStmtList();
@@ -1889,8 +1969,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
getDwoLineTable(CU));
DwarfTypeUnit &NewTU = *OwnedUnit;
DIE &UnitDie = NewTU.getUnitDie();
- TypeUnitsUnderConstruction.push_back(
- std::make_pair(std::move(OwnedUnit), CTy));
+ TypeUnitsUnderConstruction.emplace_back(std::move(OwnedUnit), CTy);
NewTU.addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
CU.getLanguage());
@@ -1900,11 +1979,10 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
Ins.first->second = Signature;
if (useSplitDwarf())
- NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
+ NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
else {
CU.applyStmtList(UnitDie);
- NewTU.initSection(
- Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+ NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature));
}
NewTU.setType(NewTU.createTypeDIE(CTy));
@@ -1968,3 +2046,7 @@ void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) {
return;
AccelTypes.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die);
}
+
+uint16_t DwarfDebug::getDwarfVersion() const {
+ return Asm->OutStreamer->getContext().getDwarfVersion();
+}
OpenPOWER on IntegriCloud