aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp242
1 files changed, 134 insertions, 108 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 1ae17ec9b874..ab29020bf1d7 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -234,7 +234,15 @@ const DIType *DbgVariable::getType() const {
/// Get .debug_loc entry for the instruction range starting at MI.
static DbgValueLoc getDebugLocValue(const MachineInstr *MI) {
const DIExpression *Expr = MI->getDebugExpression();
- const bool IsVariadic = MI->isDebugValueList();
+ auto SingleLocExprOpt = DIExpression::convertToNonVariadicExpression(Expr);
+ const bool IsVariadic = !SingleLocExprOpt;
+ // If we have a variadic debug value instruction that is equivalent to a
+ // non-variadic instruction, then convert it to non-variadic form here.
+ if (!IsVariadic && !MI->isNonListDebugValue()) {
+ assert(MI->getNumDebugOperands() == 1 &&
+ "Mismatched DIExpression and debug operands for debug instruction.");
+ Expr = *SingleLocExprOpt;
+ }
assert(MI->getNumOperands() >= 3);
SmallVector<DbgValueLocEntry, 4> DbgValueLocEntries;
for (const MachineOperand &Op : MI->debug_operands()) {
@@ -257,67 +265,39 @@ static DbgValueLoc getDebugLocValue(const MachineInstr *MI) {
return DbgValueLoc(Expr, DbgValueLocEntries, IsVariadic);
}
-void DbgVariable::initializeDbgValue(const MachineInstr *DbgValue) {
- assert(FrameIndexExprs.empty() && "Already initialized?");
- assert(!ValueLoc.get() && "Already initialized?");
+static uint64_t getFragmentOffsetInBits(const DIExpression &Expr) {
+ std::optional<DIExpression::FragmentInfo> Fragment = Expr.getFragmentInfo();
+ return Fragment ? Fragment->OffsetInBits : 0;
+}
- assert(getVariable() == DbgValue->getDebugVariable() && "Wrong variable");
- assert(getInlinedAt() == DbgValue->getDebugLoc()->getInlinedAt() &&
- "Wrong inlined-at");
+bool llvm::operator<(const FrameIndexExpr &LHS, const FrameIndexExpr &RHS) {
+ return getFragmentOffsetInBits(*LHS.Expr) <
+ getFragmentOffsetInBits(*RHS.Expr);
+}
- ValueLoc = std::make_unique<DbgValueLoc>(getDebugLocValue(DbgValue));
- if (auto *E = DbgValue->getDebugExpression())
- if (E->getNumElements())
- FrameIndexExprs.push_back({0, E});
+bool llvm::operator<(const EntryValueInfo &LHS, const EntryValueInfo &RHS) {
+ return getFragmentOffsetInBits(LHS.Expr) < getFragmentOffsetInBits(RHS.Expr);
}
-ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const {
- if (FrameIndexExprs.size() == 1)
- return FrameIndexExprs;
+Loc::Single::Single(DbgValueLoc ValueLoc)
+ : ValueLoc(std::make_unique<DbgValueLoc>(ValueLoc)),
+ Expr(ValueLoc.getExpression()) {
+ if (!Expr->getNumElements())
+ Expr = nullptr;
+}
- assert(llvm::all_of(FrameIndexExprs,
- [](const FrameIndexExpr &A) {
- return A.Expr->isFragment();
- }) &&
- "multiple FI expressions without DW_OP_LLVM_fragment");
- llvm::sort(FrameIndexExprs,
- [](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool {
- return A.Expr->getFragmentInfo()->OffsetInBits <
- B.Expr->getFragmentInfo()->OffsetInBits;
- });
+Loc::Single::Single(const MachineInstr *DbgValue)
+ : Single(getDebugLocValue(DbgValue)) {}
+const std::set<FrameIndexExpr> &Loc::MMI::getFrameIndexExprs() const {
return FrameIndexExprs;
}
-void DbgVariable::addMMIEntry(const DbgVariable &V) {
- assert(DebugLocListIndex == ~0U && !ValueLoc.get() && "not an MMI entry");
- assert(V.DebugLocListIndex == ~0U && !V.ValueLoc.get() && "not an MMI entry");
- assert(V.getVariable() == getVariable() && "conflicting variable");
- assert(V.getInlinedAt() == getInlinedAt() && "conflicting inlined-at location");
-
- assert(!FrameIndexExprs.empty() && "Expected an MMI entry");
- assert(!V.FrameIndexExprs.empty() && "Expected an MMI entry");
-
- // FIXME: This logic should not be necessary anymore, as we now have proper
- // deduplication. However, without it, we currently run into the assertion
- // below, which means that we are likely dealing with broken input, i.e. two
- // non-fragment entries for the same variable at different frame indices.
- if (FrameIndexExprs.size()) {
- auto *Expr = FrameIndexExprs.back().Expr;
- if (!Expr || !Expr->isFragment())
- return;
- }
-
- for (const auto &FIE : V.FrameIndexExprs)
- // Ignore duplicate entries.
- if (llvm::none_of(FrameIndexExprs, [&](const FrameIndexExpr &Other) {
- return FIE.FI == Other.FI && FIE.Expr == Other.Expr;
- }))
- FrameIndexExprs.push_back(FIE);
-
+void Loc::MMI::addFrameIndexExpr(const DIExpression *Expr, int FI) {
+ FrameIndexExprs.insert({FI, Expr});
assert((FrameIndexExprs.size() == 1 ||
llvm::all_of(FrameIndexExprs,
- [](FrameIndexExpr &FIE) {
+ [](const FrameIndexExpr &FIE) {
return FIE.Expr && FIE.Expr->isFragment();
})) &&
"conflicting locations for variable");
@@ -331,8 +311,9 @@ static AccelTableKind computeAccelTableKind(unsigned DwarfVersion,
if (AccelTables != AccelTableKind::Default)
return AccelTables;
- // Accelerator tables with type units are currently not supported.
- if (GenerateTypeUnits)
+ // Generating DWARF5 acceleration table.
+ // Currently Split dwarf and non ELF format is not supported.
+ if (GenerateTypeUnits && (DwarfVersion < 5 || !TT.isOSBinFormatELF()))
return AccelTableKind::None;
// Accelerator tables get emitted if targetting DWARF v5 or LLDB. DWARF v5
@@ -465,7 +446,7 @@ DwarfDebug::DwarfDebug(AsmPrinter *A)
DwarfDebug::~DwarfDebug() = default;
static bool isObjCClass(StringRef Name) {
- return Name.startswith("+") || Name.startswith("-");
+ return Name.starts_with("+") || Name.starts_with("-");
}
static bool hasObjCCategory(StringRef Name) {
@@ -492,36 +473,38 @@ static StringRef getObjCMethodName(StringRef In) {
}
// Add the various names to the Dwarf accelerator table names.
-void DwarfDebug::addSubprogramNames(const DICompileUnit &CU,
- const DISubprogram *SP, DIE &Die) {
+void DwarfDebug::addSubprogramNames(
+ const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind,
+ const DISubprogram *SP, DIE &Die) {
if (getAccelTableKind() != AccelTableKind::Apple &&
- CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Apple &&
- CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None)
+ NameTableKind != DICompileUnit::DebugNameTableKind::Apple &&
+ NameTableKind == DICompileUnit::DebugNameTableKind::None)
return;
if (!SP->isDefinition())
return;
if (SP->getName() != "")
- addAccelName(CU, SP->getName(), Die);
+ addAccelName(Unit, NameTableKind, SP->getName(), Die);
// If the linkage name is different than the name, go ahead and output that as
// well into the name table. Only do that if we are going to actually emit
// that name.
if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() &&
(useAllLinkageNames() || InfoHolder.getAbstractScopeDIEs().lookup(SP)))
- addAccelName(CU, SP->getLinkageName(), Die);
+ addAccelName(Unit, NameTableKind, SP->getLinkageName(), Die);
// If this is an Objective-C selector name add it to the ObjC accelerator
// too.
if (isObjCClass(SP->getName())) {
StringRef Class, Category;
getObjCClassCategory(SP->getName(), Class, Category);
- addAccelObjC(CU, Class, Die);
+ addAccelObjC(Unit, NameTableKind, Class, Die);
if (Category != "")
- addAccelObjC(CU, Category, Die);
+ addAccelObjC(Unit, NameTableKind, Category, Die);
// Also add the base method name to the name table.
- addAccelName(CU, getObjCMethodName(SP->getName()), Die);
+ addAccelName(Unit, NameTableKind, getObjCMethodName(SP->getName()), Die);
}
}
@@ -603,7 +586,7 @@ static const DIExpression *combineDIExpressions(const DIExpression *Original,
std::vector<uint64_t> Elts = Addition->getElements().vec();
// Avoid multiple DW_OP_stack_values.
if (Original->isImplicit() && Addition->isImplicit())
- erase_value(Elts, dwarf::DW_OP_stack_value);
+ llvm::erase(Elts, dwarf::DW_OP_stack_value);
const DIExpression *CombinedExpr =
(Elts.size() > 0) ? DIExpression::append(Original, Elts) : Original;
return CombinedExpr;
@@ -1409,6 +1392,10 @@ void DwarfDebug::finalizeModuleInfo() {
InfoHolder.computeSizeAndOffsets();
if (useSplitDwarf())
SkeletonHolder.computeSizeAndOffsets();
+
+ // Now that offsets are computed, can replace DIEs in debug_names Entry with
+ // an actual offset.
+ AccelDebugNames.convertDieToOffset();
}
// Emit all Dwarf sections that should come after the content.
@@ -1560,29 +1547,42 @@ void DwarfDebug::collectVariableInfoFromMFTable(
}
ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first, Scope->getScopeNode());
+
+ // If we have already seen information for this variable, add to what we
+ // already know.
+ if (DbgVariable *PreviousLoc = MFVars.lookup(Var)) {
+ auto *PreviousMMI = std::get_if<Loc::MMI>(PreviousLoc);
+ auto *PreviousEntryValue = std::get_if<Loc::EntryValue>(PreviousLoc);
+ // Previous and new locations are both stack slots (MMI).
+ if (PreviousMMI && VI.inStackSlot())
+ PreviousMMI->addFrameIndexExpr(VI.Expr, VI.getStackSlot());
+ // Previous and new locations are both entry values.
+ else if (PreviousEntryValue && VI.inEntryValueRegister())
+ PreviousEntryValue->addExpr(VI.getEntryValueRegister(), *VI.Expr);
+ else {
+ // Locations differ, this should (rarely) happen in optimized async
+ // coroutines.
+ // Prefer whichever location has an EntryValue.
+ if (PreviousLoc->holds<Loc::MMI>())
+ PreviousLoc->emplace<Loc::EntryValue>(VI.getEntryValueRegister(),
+ *VI.Expr);
+ LLVM_DEBUG(dbgs() << "Dropping debug info for " << VI.Var->getName()
+ << ", conflicting fragment location types\n");
+ }
+ continue;
+ }
+
auto RegVar = std::make_unique<DbgVariable>(
cast<DILocalVariable>(Var.first), Var.second);
if (VI.inStackSlot())
- RegVar->initializeMMI(VI.Expr, VI.getStackSlot());
- else {
- MachineLocation MLoc(VI.getEntryValueRegister(), /*IsIndirect*/ true);
- auto LocEntry = DbgValueLocEntry(MLoc);
- RegVar->initializeDbgValue(DbgValueLoc(VI.Expr, LocEntry));
- }
+ RegVar->emplace<Loc::MMI>(VI.Expr, VI.getStackSlot());
+ else
+ RegVar->emplace<Loc::EntryValue>(VI.getEntryValueRegister(), *VI.Expr);
LLVM_DEBUG(dbgs() << "Created DbgVariable for " << VI.Var->getName()
<< "\n");
-
- if (DbgVariable *DbgVar = MFVars.lookup(Var)) {
- if (DbgVar->getValueLoc())
- LLVM_DEBUG(dbgs() << "Dropping repeated entry value debug info for "
- "variable "
- << VI.Var->getName() << "\n");
- else
- DbgVar->addMMIEntry(*RegVar);
- } else if (InfoHolder.addScopeVariable(Scope, RegVar.get())) {
- MFVars.insert({Var, RegVar.get()});
- ConcreteEntities.push_back(std::move(RegVar));
- }
+ InfoHolder.addScopeVariable(Scope, RegVar.get());
+ MFVars.insert({Var, RegVar.get()});
+ ConcreteEntities.push_back(std::move(RegVar));
}
}
@@ -1916,7 +1916,7 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
const auto *End =
SingleValueWithClobber ? HistoryMapEntries[1].getInstr() : nullptr;
if (validThroughout(LScopes, MInsn, End, getInstOrdering())) {
- RegVar->initializeDbgValue(MInsn);
+ RegVar->emplace<Loc::Single>(MInsn);
continue;
}
}
@@ -1926,7 +1926,7 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
continue;
// Handle multiple DBG_VALUE instructions describing one variable.
- DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar, *MInsn);
+ DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar);
// Build the location list for this variable.
SmallVector<DebugLocEntry, 8> Entries;
@@ -1936,7 +1936,7 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
// that is valid throughout the variable's scope. If so, produce single
// value location.
if (isValidSingleLocation) {
- RegVar->initializeDbgValue(Entries[0].getValues()[0]);
+ RegVar->emplace<Loc::Single>(Entries[0].getValues()[0]);
continue;
}
@@ -2639,7 +2639,7 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
DIExpressionCursor ExprCursor(DIExpr);
DwarfExpr.addFragmentOffset(DIExpr);
- // If the DIExpr is is an Entry Value, we want to follow the same code path
+ // If the DIExpr is an Entry Value, we want to follow the same code path
// regardless of whether the DBG_VALUE is variadic or not.
if (DIExpr && DIExpr->isEntryValue()) {
// Entry values can only be a single register with no additional DIExpr,
@@ -3448,6 +3448,7 @@ uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
StringRef Identifier, DIE &RefDie,
const DICompositeType *CTy) {
+ setCurrentDWARF5AccelTable(DWARF5AccelTableKind::TU);
// Fast path if we're building some type units and one has already used the
// address pool we know we're going to throw away all this work anyway, so
// don't bother building dependent types.
@@ -3463,8 +3464,8 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
bool TopLevelType = TypeUnitsUnderConstruction.empty();
AddrPool.resetUsedFlag();
- auto OwnedUnit = std::make_unique<DwarfTypeUnit>(CU, Asm, this, &InfoHolder,
- getDwoLineTable(CU));
+ auto OwnedUnit = std::make_unique<DwarfTypeUnit>(
+ CU, Asm, this, &InfoHolder, NumTypeUnitsCreated++, getDwoLineTable(CU));
DwarfTypeUnit &NewTU = *OwnedUnit;
DIE &UnitDie = NewTU.getUnitDie();
TypeUnitsUnderConstruction.emplace_back(std::move(OwnedUnit), CTy);
@@ -3506,7 +3507,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
// Types referencing entries in the address table cannot be placed in type
// units.
if (AddrPool.hasBeenUsed()) {
-
+ AccelTypeUnitsDebugNames.clear();
// Remove all the types built while building this type.
// This is pessimistic as some of these types might not be dependent on
// the type that used an address.
@@ -3517,6 +3518,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
// This is inefficient because all the dependent types will be rebuilt
// from scratch, including building them in type units, discovering that
// they depend on addresses, throwing them out and rebuilding them.
+ setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
CU.constructTypeDIE(RefDie, cast<DICompositeType>(CTy));
return;
}
@@ -3526,9 +3528,20 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
for (auto &TU : TypeUnitsToAdd) {
InfoHolder.computeSizeAndOffsetsForUnit(TU.first.get());
InfoHolder.emitUnit(TU.first.get(), useSplitDwarf());
+ if (getDwarfVersion() >= 5 &&
+ getAccelTableKind() == AccelTableKind::Dwarf) {
+ if (useSplitDwarf())
+ AccelDebugNames.addTypeUnitSignature(*TU.first);
+ else
+ AccelDebugNames.addTypeUnitSymbol(*TU.first);
+ }
}
+ AccelTypeUnitsDebugNames.convertDieToOffset();
+ AccelDebugNames.addTypeEntries(AccelTypeUnitsDebugNames);
+ AccelTypeUnitsDebugNames.clear();
}
CU.addDIETypeSignature(RefDie, Signature);
+ setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
}
// Add the Name along with its companion DIE to the appropriate accelerator
@@ -3536,15 +3549,16 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
// AccelTableKind::Apple, we use the table we got as an argument). If
// accelerator tables are disabled, this function does nothing.
template <typename DataT>
-void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU,
- AccelTable<DataT> &AppleAccel, StringRef Name,
- const DIE &Die) {
+void DwarfDebug::addAccelNameImpl(
+ const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind,
+ AccelTable<DataT> &AppleAccel, StringRef Name, const DIE &Die) {
if (getAccelTableKind() == AccelTableKind::None || Name.empty())
return;
if (getAccelTableKind() != AccelTableKind::Apple &&
- CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Apple &&
- CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Default)
+ NameTableKind != DICompileUnit::DebugNameTableKind::Apple &&
+ NameTableKind != DICompileUnit::DebugNameTableKind::Default)
return;
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
@@ -3554,9 +3568,13 @@ void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU,
case AccelTableKind::Apple:
AppleAccel.addName(Ref, Die);
break;
- case AccelTableKind::Dwarf:
- AccelDebugNames.addName(Ref, Die);
+ case AccelTableKind::Dwarf: {
+ DWARF5AccelTable &Current = getCurrentDWARF5AccelTable();
+ // The type unit can be discarded, so need to add references to final
+ // acceleration table once we know it's complete and we emit it.
+ Current.addName(Ref, Die, Unit.getUniqueID());
break;
+ }
case AccelTableKind::Default:
llvm_unreachable("Default should have already been resolved.");
case AccelTableKind::None:
@@ -3564,26 +3582,34 @@ void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU,
}
}
-void DwarfDebug::addAccelName(const DICompileUnit &CU, StringRef Name,
- const DIE &Die) {
- addAccelNameImpl(CU, AccelNames, Name, Die);
+void DwarfDebug::addAccelName(
+ const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name,
+ const DIE &Die) {
+ addAccelNameImpl(Unit, NameTableKind, AccelNames, Name, Die);
}
-void DwarfDebug::addAccelObjC(const DICompileUnit &CU, StringRef Name,
- const DIE &Die) {
+void DwarfDebug::addAccelObjC(
+ const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name,
+ const DIE &Die) {
// ObjC names go only into the Apple accelerator tables.
if (getAccelTableKind() == AccelTableKind::Apple)
- addAccelNameImpl(CU, AccelObjC, Name, Die);
+ addAccelNameImpl(Unit, NameTableKind, AccelObjC, Name, Die);
}
-void DwarfDebug::addAccelNamespace(const DICompileUnit &CU, StringRef Name,
- const DIE &Die) {
- addAccelNameImpl(CU, AccelNamespace, Name, Die);
+void DwarfDebug::addAccelNamespace(
+ const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name,
+ const DIE &Die) {
+ addAccelNameImpl(Unit, NameTableKind, AccelNamespace, Name, Die);
}
-void DwarfDebug::addAccelType(const DICompileUnit &CU, StringRef Name,
- const DIE &Die, char Flags) {
- addAccelNameImpl(CU, AccelTypes, Name, Die);
+void DwarfDebug::addAccelType(
+ const DwarfUnit &Unit,
+ const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name,
+ const DIE &Die, char Flags) {
+ addAccelNameImpl(Unit, NameTableKind, AccelTypes, Name, Die);
}
uint16_t DwarfDebug::getDwarfVersion() const {