diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 306 |
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. |