X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfDebug.cpp;h=278907134745ca34eb60e08972cfe2cb5c22ecd0;hp=4acd7271be9aff13f1fcb8ec6818e51365f581f1;hb=4ceab42509518746afef0370e7aba230736a80f5;hpb=5bf8ade9d043d8739b8bfa90e7d7c64ebfe11ef1 diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 4acd7271be9..27890713474 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" @@ -105,6 +105,25 @@ DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden, static const char *const DWARFGroupName = "DWARF Emission"; static const char *const DbgTimerName = "DWARF Debug Writer"; +void DebugLocDwarfExpression::EmitOp(uint8_t Op, const char *Comment) { + BS.EmitInt8( + Op, Comment ? Twine(Comment) + " " + dwarf::OperationEncodingString(Op) + : dwarf::OperationEncodingString(Op)); +} + +void DebugLocDwarfExpression::EmitSigned(int Value) { + BS.EmitSLEB128(Value, Twine(Value)); +} + +void DebugLocDwarfExpression::EmitUnsigned(unsigned Value) { + BS.EmitULEB128(Value, Twine(Value)); +} + +bool DebugLocDwarfExpression::isFrameRegister(unsigned MachineReg) { + // This information is not available while emitting .debug_loc entries. + return false; +} + //===----------------------------------------------------------------------===// /// resolve - Look in the DwarfDebug map for the MDNode that @@ -170,10 +189,11 @@ static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = { DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) : Asm(A), MMI(Asm->MMI), PrevLabel(nullptr), GlobalRangeCount(0), - InfoHolder(A, *this, "info_string", DIEValueAllocator), + InfoHolder(A, "info_string", DIEValueAllocator), UsedNonDefaultText(false), - SkeletonHolder(A, *this, "skel_string", DIEValueAllocator), + SkeletonHolder(A, "skel_string", DIEValueAllocator), IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()), + IsPS4(Triple(A->getTargetTriple()).isPS4()), AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, @@ -212,6 +232,10 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber : MMI->getModule()->getDwarfVersion(); + // Darwin and PS4 use the standard TLS opcode (defined in DWARF 3). + // Everybody else uses GNU's. + UseGNUTLSOpcode = !(IsDarwin || IsPS4) || DwarfVersion < 3; + Asm->OutStreamer.getContext().setDwarfVersion(DwarfVersion); { @@ -458,8 +482,11 @@ void DwarfDebug::beginModule() { ScopesWithImportedEntities.push_back(std::make_pair( DIImportedEntity(ImportedEntities.getElement(i)).getContext(), ImportedEntities.getElement(i))); - std::sort(ScopesWithImportedEntities.begin(), - ScopesWithImportedEntities.end(), less_first()); + // Stable sort to preserve the order of appearance of imported entities. + // This is to avoid out-of-order processing of interdependent declarations + // within the same scope, e.g. { namespace A = base; namespace B = A; } + std::stable_sort(ScopesWithImportedEntities.begin(), + ScopesWithImportedEntities.end(), less_first()); DIArray GVs = CUNode.getGlobalVariables(); for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) CU.getOrCreateGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); @@ -490,9 +517,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 +632,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 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 +643,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 +756,9 @@ void DwarfDebug::collectVariableInfoFromMMITable( DIVariable DV(VI.Var); DIExpression Expr(VI.Expr); ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); - ConcreteVariables.push_back(make_unique(DV, Expr, this)); - DbgVariable *RegVar = ConcreteVariables.back().get(); - RegVar->setFrameIndex(VI.Slot); - InfoHolder.addScopeVariable(Scope, RegVar); + auto RegVar = make_unique(DV, Expr, this, VI.Slot); + if (InfoHolder.addScopeVariable(Scope, RegVar.get())) + ConcreteVariables.push_back(std::move(RegVar)); } } @@ -818,12 +790,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 +814,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 +867,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl &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 +923,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) @@ -983,6 +954,9 @@ DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, DISubprogram SP, // Build the location list for this variable. buildLocationList(LocList.List, Ranges); + // Finalize the entry by lowering it into a DWARF bytestream. + for (auto &Entry : LocList.List) + Entry.finalize(*Asm, TypeIdentifierMap); } // Collect info for variables that were optimized out. @@ -990,7 +964,7 @@ DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, DISubprogram SP, for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { DIVariable DV(Variables.getElement(i)); assert(DV.isVariable()); - if (!Processed.insert(DV)) + if (!Processed.insert(DV).second) continue; if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) { ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); @@ -1026,8 +1000,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 +1093,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 +1152,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 +1167,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 +1197,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); } } @@ -1287,7 +1267,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { DIVariable DV(Variables.getElement(i)); assert(DV && DV.isVariable()); - if (!ProcessedVars.insert(DV)) + if (!ProcessedVars.insert(DV).second) continue; ensureAbstractVariableIsCreated(DV, DV.getContext()); assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes @@ -1350,8 +1330,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"); @@ -1389,49 +1369,6 @@ void DwarfDebug::emitSectionLabels() { emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range"); } -// Recursively emits a debug information entry. -void DwarfDebug::emitDIE(DIE &Die) { - // Get the abbreviation for this DIE. - const DIEAbbrev &Abbrev = Die.getAbbrev(); - - // Emit the code (index) for the abbreviation. - if (Asm->isVerbose()) - Asm->OutStreamer.AddComment("Abbrev [" + Twine(Abbrev.getNumber()) + - "] 0x" + Twine::utohexstr(Die.getOffset()) + - ":0x" + Twine::utohexstr(Die.getSize()) + " " + - dwarf::TagString(Abbrev.getTag())); - Asm->EmitULEB128(Abbrev.getNumber()); - - const SmallVectorImpl &Values = Die.getValues(); - const SmallVectorImpl &AbbrevData = Abbrev.getData(); - - // Emit the DIE attribute values. - for (unsigned i = 0, N = Values.size(); i < N; ++i) { - dwarf::Attribute Attr = AbbrevData[i].getAttribute(); - dwarf::Form Form = AbbrevData[i].getForm(); - assert(Form && "Too many attributes for DIE (check abbreviation)"); - - if (Asm->isVerbose()) { - Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); - if (Attr == dwarf::DW_AT_accessibility) - Asm->OutStreamer.AddComment(dwarf::AccessibilityString( - cast(Values[i])->getValue())); - } - - // Emit an attribute using the defined form. - Values[i]->EmitValue(Asm, Form); - } - - // Emit the DIE children if any. - if (Abbrev.hasChildren()) { - for (auto &Child : Die.getChildren()) - emitDIE(*Child); - - Asm->OutStreamer.AddComment("End Of Children Mark"); - Asm->EmitInt8(0); - } -} - // Emit the debug info section. void DwarfDebug::emitDebugInfo() { DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; @@ -1478,7 +1415,7 @@ void DwarfDebug::emitAccel(DwarfAccelTable &Accel, const MCSection *Section, Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - Accel.Emit(Asm, SectionBegin, &InfoHolder, DwarfStrSectionSym); + Accel.Emit(Asm, SectionBegin, this, DwarfStrSectionSym); } // Emit visible names into a hashed accelerator table section. @@ -1553,7 +1490,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: @@ -1651,120 +1587,46 @@ void DwarfDebug::emitDebugStr() { Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); } -/// Emits an optimal (=sorted) sequence of DW_OP_pieces. -void DwarfDebug::emitLocPieces(ByteStreamer &Streamer, - const DITypeIdentifierMap &Map, - ArrayRef Values) { - assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) { - return P.isVariablePiece(); - }) && "all values are expected to be pieces"); - assert(std::is_sorted(Values.begin(), Values.end()) && - "pieces are expected to be sorted"); - - unsigned Offset = 0; - for (auto Piece : Values) { - DIExpression Expr = Piece.getExpression(); - unsigned PieceOffset = Expr.getPieceOffset(); - unsigned PieceSize = Expr.getPieceSize(); - 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); - 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 - && "piece is larger than or outside of variable"); - assert(PieceSize*SizeOfByte != 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); - } - } -} - void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry) { - const DebugLocEntry::Value Value = Entry.getValues()[0]; - if (Value.isVariablePiece()) - // Emit all pieces that belong to the same variable and range. - return emitLocPieces(Streamer, TypeIdentifierMap, Entry.getValues()); - - assert(Entry.getValues().size() == 1 && "only pieces may have >1 value"); - emitDebugLocValue(Streamer, Value); + auto Comment = Entry.getComments().begin(); + auto End = Entry.getComments().end(); + for (uint8_t Byte : Entry.getDWARFBytes()) + Streamer.EmitInt8(Byte, Comment != End ? *(Comment++) : ""); } -void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer, - const DebugLocEntry::Value &Value) { +static void emitDebugLocValue(const AsmPrinter &AP, + const DITypeIdentifierMap &TypeIdentifierMap, + ByteStreamer &Streamer, + const DebugLocEntry::Value &Value, + unsigned PieceOffsetInBits) { DIVariable DV = Value.getVariable(); + DebugLocDwarfExpression DwarfExpr( + *AP.TM.getSubtargetImpl()->getRegisterInfo(), + AP.getDwarfDebug()->getDwarfVersion(), Streamer); // Regular entry. if (Value.isInt()) { - DIBasicType BTy(resolve(DV.getType())); + DIBasicType BTy(DV.getType().resolve(TypeIdentifierMap)); 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()); + AP.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 @@ -1772,6 +1634,52 @@ void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer, // FIXME: ^ } + +void DebugLocEntry::finalize(const AsmPrinter &AP, + const DITypeIdentifierMap &TypeIdentifierMap) { + BufferByteStreamer Streamer(DWARFBytes, Comments); + 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"); + assert(std::is_sorted(Values.begin(), Values.end()) && + "pieces are expected to be sorted"); + + unsigned Offset = 0; + for (auto Piece : Values) { + 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.TM.getSubtargetImpl()->getRegisterInfo(), + AP.getDwarfDebug()->getDwarfVersion(), Streamer); + Expr.AddOpPiece(PieceOffset-Offset, 0); + Offset += PieceOffset-Offset; + } + Offset += PieceSize; + +#ifndef NDEBUG + DIVariable Var = Piece.getVariable(); + unsigned VarSize = Var.getSizeInBits(TypeIdentifierMap); + assert(PieceSize+PieceOffset <= VarSize + && "piece is larger than or outside of variable"); + assert(PieceSize != VarSize + && "piece covers entire variable"); +#endif + emitDebugLocValue(AP, TypeIdentifierMap, Streamer, Piece, PieceOffset); + } + } else { + assert(Values.size() == 1 && "only pieces may have >1 value"); + emitDebugLocValue(AP, TypeIdentifierMap, Streamer, Value, 0); + } +} + + void DwarfDebug::emitDebugLocEntryLocation(const DebugLocEntry &Entry) { Asm->OutStreamer.AddComment("Loc expr size"); MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol(); @@ -1841,13 +1749,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> SectionMap; - typedef DenseMap> 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 Sections; @@ -1860,12 +1781,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> Spans; + for (const MCSection *Section : Sections) { SmallVector &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 +1835,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. @@ -2110,7 +2056,7 @@ static uint64_t makeTypeSignature(StringRef Identifier) { // appropriately. MD5::MD5Result Result; Hash.final(Result); - return *reinterpret_cast(Result + 8); + return support::endian::read64le(Result + 8); } void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,