#include "DwarfDebug.h"
#include "ByteStreamer.h"
#include "DIEHash.h"
+#include "DebugLocEntry.h"
#include "DwarfCompileUnit.h"
#include "DwarfExpression.h"
#include "DwarfUnit.h"
/// resolve - Look in the DwarfDebug map for the MDNode that
/// corresponds to the reference.
-template <typename T> T DbgVariable::resolve(DIRef<T> Ref) const {
+template <typename T> T *DbgVariable::resolve(TypedDebugNodeRef<T> Ref) const {
return DD->resolve(Ref);
}
->isBlockByrefStruct();
}
-DIType DbgVariable::getType() const {
- DIType Ty = Var->getType().resolve(DD->getTypeIdentifierMap());
+const MDType *DbgVariable::getType() const {
+ MDType *Ty = Var->getType().resolve(DD->getTypeIdentifierMap());
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
// addresses instead.
if (Ty->isBlockByrefStruct()) {
have a DW_AT_location that tells the debugger how to unwind through
the pointers and __Block_byref_x_VarName struct to find the actual
value of the variable. The function addBlockByrefType does this. */
- DIType subType = Ty;
- uint16_t tag = Ty.getTag();
+ MDType *subType = Ty;
+ uint16_t tag = Ty->getTag();
if (tag == dwarf::DW_TAG_pointer_type)
- subType = resolve(DITypeRef(cast<MDDerivedType>(Ty)->getBaseType()));
+ subType = resolve(cast<MDDerivedType>(Ty)->getBaseType());
- DIArray Elements(cast<MDCompositeTypeBase>(subType)->getElements());
+ auto Elements = cast<MDCompositeTypeBase>(subType)->getElements();
for (unsigned i = 0, N = Elements.size(); i < N; ++i) {
- DIDerivedType DT = cast<MDDerivedTypeBase>(Elements[i]);
- if (getName() == DT.getName())
- return (resolve(DT.getTypeDerivedFrom()));
+ auto *DT = cast<MDDerivedTypeBase>(Elements[i]);
+ if (getName() == DT->getName())
+ return resolve(DT->getBaseType());
}
}
return Ty;
return false;
if (isa<MDSubprogram>(Context))
return true;
- if (DIType T = dyn_cast<MDType>(Context))
- return isSubprogramContext(resolve(T.getContext()));
+ if (auto *T = dyn_cast<MDType>(Context))
+ return isSubprogramContext(resolve(T->getScope()));
return false;
}
// Create new DwarfCompileUnit for the given metadata node with tag
// DW_TAG_compile_unit.
DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) {
- StringRef FN = DIUnit.getFilename();
- CompilationDir = DIUnit.getDirectory();
+ StringRef FN = DIUnit->getFilename();
+ CompilationDir = DIUnit->getDirectory();
auto OwnedUnit = make_unique<DwarfCompileUnit>(
InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder);
Asm->OutStreamer.getContext().setMCLineTableCompilationDir(
NewCU.getUniqueID(), CompilationDir);
- NewCU.addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer());
+ NewCU.addString(Die, dwarf::DW_AT_producer, DIUnit->getProducer());
NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
- DIUnit.getLanguage());
+ DIUnit->getSourceLanguage());
NewCU.addString(Die, dwarf::DW_AT_name, FN);
if (!useSplitDwarf()) {
addGnuPubAttributes(NewCU, Die);
}
- if (DIUnit.isOptimized())
+ if (DIUnit->isOptimized())
NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized);
- StringRef Flags = DIUnit.getFlags();
+ StringRef Flags = DIUnit->getFlags();
if (!Flags.empty())
NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags);
- if (unsigned RVer = DIUnit.getRunTimeVersion())
+ if (unsigned RVer = DIUnit->getRuntimeVersion())
NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
dwarf::DW_FORM_data1, RVer);
CU.getOrCreateGlobalVariableDIE(GV);
for (auto *SP : CUNode->getSubprograms())
SPMap.insert(std::make_pair(SP, &CU));
- for (DIType Ty : CUNode->getEnumTypes()) {
+ for (auto *Ty : CUNode->getEnumTypes()) {
// The enum types array by design contains pointers to
// MDNodes rather than DIRefs. Unique them here.
- DIType UniqueTy = cast<MDType>(resolve(Ty.getRef()));
- CU.getOrCreateTypeDIE(UniqueTy);
+ CU.getOrCreateTypeDIE(cast<MDType>(resolve(Ty->getRef())));
}
- for (DIType Ty : CUNode->getRetainedTypes()) {
+ for (auto *Ty : CUNode->getRetainedTypes()) {
// The retained types array by design contains pointers to
// MDNodes rather than DIRefs. Unique them here.
- DIType UniqueTy = cast<MDType>(resolve(Ty.getRef()));
- CU.getOrCreateTypeDIE(UniqueTy);
+ CU.getOrCreateTypeDIE(cast<MDType>(resolve(Ty->getRef())));
}
// Emit imported_modules last so that the relevant context is already
// available.
for (const auto &VI : MMI->getVariableDbgInfo()) {
if (!VI.Var)
continue;
- InlinedVariable Var(VI.Var, VI.Loc ? VI.Loc->getInlinedAt() : nullptr);
+ assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
+ "Expected inlined-at fields to agree");
+
+ InlinedVariable Var(VI.Var, VI.Loc->getInlinedAt());
Processed.insert(Var);
LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
if (!Scope)
continue;
- assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
- "Expected inlined-at fields to agree");
DIExpression Expr = cast_or_null<MDExpression>(VI.Expr);
ensureAbstractVariableIsCreatedIfScoped(Var, Scope->getScopeNode());
auto RegVar =
// Get .debug_loc entry for the instruction range starting at MI.
static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
- const MDNode *Expr = MI->getDebugExpression();
- const MDNode *Var = MI->getDebugVariable();
+ const MDExpression *Expr = MI->getDebugExpression();
assert(MI->getNumOperands() == 4);
if (MI->getOperand(0).isReg()) {
MLoc.set(MI->getOperand(0).getReg());
else
MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
- return DebugLocEntry::Value(Var, Expr, MLoc);
+ return DebugLocEntry::Value(Expr, MLoc);
}
if (MI->getOperand(0).isImm())
- return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getImm());
+ return DebugLocEntry::Value(Expr, MI->getOperand(0).getImm());
if (MI->getOperand(0).isFPImm())
- return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getFPImm());
+ return DebugLocEntry::Value(Expr, MI->getOperand(0).getFPImm());
if (MI->getOperand(0).isCImm())
- return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getCImm());
+ return DebugLocEntry::Value(Expr, MI->getOperand(0).getCImm());
llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!");
}
DEBUG({
dbgs() << CurEntry->getValues().size() << " Values:\n";
for (auto Value : CurEntry->getValues()) {
- Value.getVariable()->dump();
Value.getExpression()->dump();
}
dbgs() << "-----\n";
continue;
// Handle multiple DBG_VALUE instructions describing one variable.
- RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
-
- DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1);
- DebugLocList &LocList = DotDebugLocEntries.back();
- LocList.CU = &TheCU;
- LocList.Label = Asm->createTempSymbol("debug_loc");
+ RegVar->setDebugLocListIndex(
+ DebugLocs.startList(&TheCU, Asm->createTempSymbol("debug_loc")));
// Build the location list for this variable.
- buildLocationList(LocList.List, Ranges);
+ SmallVector<DebugLocEntry, 8> Entries;
+ buildLocationList(Entries, Ranges);
+
+ // If the variable has an MDBasicType, extract it. Basic types cannot have
+ // unique identifiers, so don't bother resolving the type with the
+ // identifier map.
+ const MDBasicType *BT = dyn_cast<MDBasicType>(
+ static_cast<const Metadata *>(IV.first->getType()));
+
// Finalize the entry by lowering it into a DWARF bytestream.
- for (auto &Entry : LocList.List)
- Entry.finalize(*Asm, TypeIdentifierMap);
+ for (auto &Entry : Entries)
+ Entry.finalize(*Asm, DebugLocs, BT);
}
// Collect info for variables that were optimized out.
// Under -gmlt, skip building the subprogram if there are no inlined
// subroutines inside it.
- if (TheCU.getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly &&
+ if (TheCU.getCUNode()->getEmissionKind() == DIBuilder::LineTablesOnly &&
LScopes.getAbstractScopesList().empty() && !IsDarwin) {
assert(InfoHolder.getScopeVariables().empty());
assert(DbgValues.empty());
StringRef Dir;
unsigned Src = 1;
unsigned Discriminator = 0;
- if (DIScope Scope = cast_or_null<MDScope>(S)) {
- Fn = Scope.getFilename();
- Dir = Scope.getDirectory();
+ if (auto *Scope = cast_or_null<MDScope>(S)) {
+ Fn = Scope->getFilename();
+ Dir = Scope->getDirectory();
if (auto *LBF = dyn_cast<MDLexicalBlockFile>(Scope))
Discriminator = LBF->getDiscriminator();
Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
}
-
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
- const DebugLocEntry &Entry) {
- auto Comment = Entry.getComments().begin();
- auto End = Entry.getComments().end();
- for (uint8_t Byte : Entry.getDWARFBytes())
+ const DebugLocStream::Entry &Entry) {
+ auto &&Comments = DebugLocs.getComments(Entry);
+ auto Comment = Comments.begin();
+ auto End = Comments.end();
+ for (uint8_t Byte : DebugLocs.getBytes(Entry))
Streamer.EmitInt8(Byte, Comment != End ? *(Comment++) : "");
}
-static void emitDebugLocValue(const AsmPrinter &AP,
- const DITypeIdentifierMap &TypeIdentifierMap,
+static void emitDebugLocValue(const AsmPrinter &AP, const MDBasicType *BT,
ByteStreamer &Streamer,
const DebugLocEntry::Value &Value,
unsigned PieceOffsetInBits) {
- DIVariable DV = Value.getVariable();
DebugLocDwarfExpression DwarfExpr(*AP.MF->getSubtarget().getRegisterInfo(),
AP.getDwarfDebug()->getDwarfVersion(),
Streamer);
// Regular entry.
if (Value.isInt()) {
- MDType *T = DV->getType().resolve(TypeIdentifierMap);
- auto *B = dyn_cast<MDBasicType>(T);
- if (B && (B->getEncoding() == dwarf::DW_ATE_signed ||
- B->getEncoding() == dwarf::DW_ATE_signed_char))
+ if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
+ BT->getEncoding() == dwarf::DW_ATE_signed_char))
DwarfExpr.AddSignedConstant(Value.getInt());
else
DwarfExpr.AddUnsignedConstant(Value.getInt());
// FIXME: ^
}
-
-void DebugLocEntry::finalize(const AsmPrinter &AP,
- const DITypeIdentifierMap &TypeIdentifierMap) {
- BufferByteStreamer Streamer(DWARFBytes, Comments);
- const DebugLocEntry::Value Value = Values[0];
+void DebugLocEntry::finalize(const AsmPrinter &AP, DebugLocStream &Locs,
+ const MDBasicType *BT) {
+ Locs.startEntry(Begin, End);
+ BufferByteStreamer Streamer = Locs.getStreamer();
+ 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) {
}
Offset += PieceSize;
- emitDebugLocValue(AP, TypeIdentifierMap, Streamer, Piece, PieceOffset);
+ emitDebugLocValue(AP, BT, Streamer, Piece, PieceOffset);
}
} else {
assert(Values.size() == 1 && "only pieces may have >1 value");
- emitDebugLocValue(AP, TypeIdentifierMap, Streamer, Value, 0);
+ emitDebugLocValue(AP, BT, Streamer, Value, 0);
}
}
-
-void DwarfDebug::emitDebugLocEntryLocation(const DebugLocEntry &Entry) {
+void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
Asm->OutStreamer.AddComment("Loc expr size");
MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLocSection());
unsigned char Size = Asm->getDataLayout().getPointerSize();
- for (const auto &DebugLoc : DotDebugLocEntries) {
- Asm->OutStreamer.EmitLabel(DebugLoc.Label);
- const DwarfCompileUnit *CU = DebugLoc.CU;
- for (const auto &Entry : DebugLoc.List) {
+ for (const auto &List : DebugLocs.getLists()) {
+ Asm->OutStreamer.EmitLabel(List.Label);
+ const DwarfCompileUnit *CU = List.CU;
+ for (const auto &Entry : DebugLocs.getEntries(List)) {
// Set up the range. This range is relative to the entry point of the
// compile unit. This is a hard coded 0 for low_pc when we're emitting
// ranges, or the DW_AT_low_pc on the compile unit otherwise.
if (auto *Base = CU->getBaseAddress()) {
- Asm->EmitLabelDifference(Entry.getBeginSym(), Base, Size);
- Asm->EmitLabelDifference(Entry.getEndSym(), Base, Size);
+ Asm->EmitLabelDifference(Entry.BeginSym, Base, Size);
+ Asm->EmitLabelDifference(Entry.EndSym, Base, Size);
} else {
- Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size);
- Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size);
+ Asm->OutStreamer.EmitSymbolValue(Entry.BeginSym, Size);
+ Asm->OutStreamer.EmitSymbolValue(Entry.EndSym, Size);
}
emitDebugLocEntryLocation(Entry);
void DwarfDebug::emitDebugLocDWO() {
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLocDWOSection());
- for (const auto &DebugLoc : DotDebugLocEntries) {
- Asm->OutStreamer.EmitLabel(DebugLoc.Label);
- for (const auto &Entry : DebugLoc.List) {
+ for (const auto &List : DebugLocs.getLists()) {
+ Asm->OutStreamer.EmitLabel(List.Label);
+ for (const auto &Entry : DebugLocs.getEntries(List)) {
// Just always use start_length for now - at least that's one address
// 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);
- unsigned idx = AddrPool.getIndex(Entry.getBeginSym());
+ unsigned idx = AddrPool.getIndex(Entry.BeginSym);
Asm->EmitULEB128(idx);
- Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4);
+ Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4);
emitDebugLocEntryLocation(Entry);
}
void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,
std::unique_ptr<DwarfUnit> NewU) {
NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name,
- U.getCUNode().getSplitDebugFilename());
+ U.getCUNode()->getSplitDebugFilename());
if (!CompilationDir.empty())
NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
if (!useSplitDwarf())
return nullptr;
if (SingleCU)
- SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode().getDirectory());
+ SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode()->getDirectory());
return &SplitTypeUnitFileTable;
}
void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
StringRef Identifier, DIE &RefDie,
- DICompositeType CTy) {
+ const MDCompositeType *CTy) {
// 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.
// 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.
- CU.constructTypeDIE(RefDie, CTy);
+ CU.constructTypeDIE(RefDie, cast<MDCompositeType>(CTy));
return;
}