diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 806 |
1 files changed, 553 insertions, 253 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 500e7a00196f..1de2ffb6cfa1 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -39,6 +39,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/Constants.h" @@ -130,11 +131,6 @@ DwarfInlinedStrings("dwarf-inlined-strings", cl::Hidden, cl::init(Default)); static cl::opt<bool> - NoDwarfPubSections("no-dwarf-pub-sections", cl::Hidden, - cl::desc("Disable emission of DWARF pub sections."), - cl::init(false)); - -static cl::opt<bool> NoDwarfRangesSection("no-dwarf-ranges-section", cl::Hidden, cl::desc("Disable emission .debug_ranges section."), cl::init(false)); @@ -188,12 +184,12 @@ bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI, } bool DbgVariable::isBlockByrefVariable() const { - assert(Var && "Invalid complex DbgVariable!"); - return Var->getType().resolve()->isBlockByrefStruct(); + assert(getVariable() && "Invalid complex DbgVariable!"); + return getVariable()->getType().resolve()->isBlockByrefStruct(); } const DIType *DbgVariable::getType() const { - DIType *Ty = Var->getType().resolve(); + DIType *Ty = getVariable()->getType().resolve(); // FIXME: isBlockByrefVariable should be reformulated in terms of complex // addresses instead. if (Ty->isBlockByrefStruct()) { @@ -246,7 +242,7 @@ ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const { return A.Expr->isFragment(); }) && "multiple FI expressions without DW_OP_LLVM_fragment"); - llvm::sort(FrameIndexExprs.begin(), FrameIndexExprs.end(), + llvm::sort(FrameIndexExprs, [](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool { return A.Expr->getFragmentInfo()->OffsetInBits < B.Expr->getFragmentInfo()->OffsetInBits; @@ -258,8 +254,8 @@ ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const { void DbgVariable::addMMIEntry(const DbgVariable &V) { assert(DebugLocListIndex == ~0U && !MInsn && "not an MMI entry"); assert(V.DebugLocListIndex == ~0U && !V.MInsn && "not an MMI entry"); - assert(V.Var == Var && "conflicting variable"); - assert(V.IA == IA && "conflicting inlined-at location"); + 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"); @@ -355,7 +351,6 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) DwarfVersion = TT.isNVPTX() ? 2 : (DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION); - UsePubSections = !NoDwarfPubSections && !TT.isNVPTX(); UseRangesSection = !NoDwarfRangesSection && !TT.isNVPTX(); // Use sections as references. Force for NVPTX. @@ -421,30 +416,35 @@ static StringRef getObjCMethodName(StringRef In) { } // Add the various names to the Dwarf accelerator table names. -void DwarfDebug::addSubprogramNames(const DISubprogram *SP, DIE &Die) { +void DwarfDebug::addSubprogramNames(const DICompileUnit &CU, + const DISubprogram *SP, DIE &Die) { + if (getAccelTableKind() != AccelTableKind::Apple && + CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None) + return; + if (!SP->isDefinition()) return; if (SP->getName() != "") - addAccelName(SP->getName(), Die); + addAccelName(CU, 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.getAbstractSPDies().lookup(SP))) - addAccelName(SP->getLinkageName(), Die); + addAccelName(CU, 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(Class, Die); + addAccelObjC(CU, Class, Die); if (Category != "") - addAccelObjC(Category, Die); + addAccelObjC(CU, Category, Die); // Also add the base method name to the name table. - addAccelName(getObjCMethodName(SP->getName()), Die); + addAccelName(CU, getObjCMethodName(SP->getName()), Die); } } @@ -503,6 +503,64 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, } } +void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, + DwarfCompileUnit &CU, DIE &ScopeDIE, + const MachineFunction &MF) { + // Add a call site-related attribute (DWARF5, Sec. 3.3.1.3). Do this only if + // the subprogram is required to have one. + if (!SP.areAllCallsDescribed() || !SP.isDefinition()) + return; + + // Use DW_AT_call_all_calls to express that call site entries are present + // for both tail and non-tail calls. Don't use DW_AT_call_all_source_calls + // because one of its requirements is not met: call site entries for + // optimized-out calls are elided. + CU.addFlag(ScopeDIE, dwarf::DW_AT_call_all_calls); + + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + assert(TII && "TargetInstrInfo not found: cannot label tail calls"); + + // Emit call site entries for each call or tail call in the function. + for (const MachineBasicBlock &MBB : MF) { + for (const MachineInstr &MI : MBB.instrs()) { + // Skip instructions which aren't calls. Both calls and tail-calling jump + // instructions (e.g TAILJMPd64) are classified correctly here. + if (!MI.isCall()) + continue; + + // TODO: Add support for targets with delay slots (see: beginInstruction). + if (MI.hasDelaySlot()) + return; + + // If this is a direct call, find the callee's subprogram. + const MachineOperand &CalleeOp = MI.getOperand(0); + if (!CalleeOp.isGlobal()) + continue; + const Function *CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal()); + if (!CalleeDecl || !CalleeDecl->getSubprogram()) + continue; + + // TODO: Omit call site entries for runtime calls (objc_msgSend, etc). + // TODO: Add support for indirect calls. + + bool IsTail = TII->isTailCall(MI); + + // For tail calls, no return PC information is needed. For regular calls, + // the return PC is needed to disambiguate paths in the call graph which + // could lead to some target function. + const MCExpr *PCOffset = + IsTail ? nullptr : getFunctionLocalOffsetAfterInsn(&MI); + + assert((IsTail || PCOffset) && "Call without return PC information"); + LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> " + << CalleeDecl->getName() << (IsTail ? " [tail]" : "") + << "\n"); + CU.constructCallSiteEntryDIE(ScopeDIE, *CalleeDecl->getSubprogram(), + IsTail, PCOffset); + } + } +} + void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const { if (!U.hasDwarfPubSections()) return; @@ -510,41 +568,14 @@ void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const { U.addFlag(D, dwarf::DW_AT_GNU_pubnames); } -// Create new DwarfCompileUnit for the given metadata node with tag -// DW_TAG_compile_unit. -DwarfCompileUnit & -DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { - if (auto *CU = CUMap.lookup(DIUnit)) - return *CU; - StringRef FN = DIUnit->getFilename(); - CompilationDir = DIUnit->getDirectory(); - - auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>( - InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); - DwarfCompileUnit &NewCU = *OwnedUnit; +void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, + DwarfCompileUnit &NewCU) { DIE &Die = NewCU.getUnitDie(); - InfoHolder.addUnit(std::move(OwnedUnit)); - if (useSplitDwarf()) { - NewCU.setSkeleton(constructSkeletonCU(NewCU)); - NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name, - Asm->TM.Options.MCOptions.SplitDwarfFile); - } - - for (auto *IE : DIUnit->getImportedEntities()) - NewCU.addImportedEntity(IE); - - // LTO with assembly output shares a single line table amongst multiple CUs. - // To avoid the compilation directory being ambiguous, let the line table - // explicitly describe the directory of all files, never relying on the - // compilation directory. - if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU) - Asm->OutStreamer->emitDwarfFile0Directive( - CompilationDir, FN, NewCU.getMD5AsBytes(DIUnit->getFile()), - DIUnit->getSource(), NewCU.getUniqueID()); + StringRef FN = DIUnit->getFilename(); StringRef Producer = DIUnit->getProducer(); StringRef Flags = DIUnit->getFlags(); - if (!Flags.empty()) { + if (!Flags.empty() && !useAppleExtensionAttributes()) { std::string ProducerWithFlags = Producer.str() + " " + Flags.str(); NewCU.addString(Die, dwarf::DW_AT_producer, ProducerWithFlags); } else @@ -582,11 +613,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { dwarf::DW_FORM_data1, RVer); } - if (useSplitDwarf()) - NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection()); - else - NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); - if (DIUnit->getDWOId()) { // This CU is either a clang module DWO or a skeleton CU. NewCU.addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, @@ -596,9 +622,44 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name, DIUnit->getSplitDebugFilename()); } +} +// Create new DwarfCompileUnit for the given metadata node with tag +// DW_TAG_compile_unit. +DwarfCompileUnit & +DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { + if (auto *CU = CUMap.lookup(DIUnit)) + return *CU; + + CompilationDir = DIUnit->getDirectory(); + + auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>( + InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); + DwarfCompileUnit &NewCU = *OwnedUnit; + InfoHolder.addUnit(std::move(OwnedUnit)); + + for (auto *IE : DIUnit->getImportedEntities()) + NewCU.addImportedEntity(IE); + + // LTO with assembly output shares a single line table amongst multiple CUs. + // To avoid the compilation directory being ambiguous, let the line table + // explicitly describe the directory of all files, never relying on the + // compilation directory. + if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU) + Asm->OutStreamer->emitDwarfFile0Directive( + CompilationDir, DIUnit->getFilename(), + NewCU.getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource(), + NewCU.getUniqueID()); + + if (useSplitDwarf()) { + NewCU.setSkeleton(constructSkeletonCU(NewCU)); + NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection()); + } else { + finishUnitAttributes(DIUnit, NewCU); + NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); + } CUMap.insert({DIUnit, &NewCU}); - CUDieMap.insert({&Die, &NewCU}); + CUDieMap.insert({&NewCU.getUnitDie(), &NewCU}); return NewCU; } @@ -613,22 +674,21 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, /// Sort and unique GVEs by comparing their fragment offset. static SmallVectorImpl<DwarfCompileUnit::GlobalExpr> & sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) { - llvm::sort(GVEs.begin(), GVEs.end(), - [](DwarfCompileUnit::GlobalExpr A, - DwarfCompileUnit::GlobalExpr B) { - // Sort order: first null exprs, then exprs without fragment - // info, then sort by fragment offset in bits. - // FIXME: Come up with a more comprehensive comparator so - // the sorting isn't non-deterministic, and so the following - // std::unique call works correctly. - if (!A.Expr || !B.Expr) - return !!B.Expr; - auto FragmentA = A.Expr->getFragmentInfo(); - auto FragmentB = B.Expr->getFragmentInfo(); - if (!FragmentA || !FragmentB) - return !!FragmentB; - return FragmentA->OffsetInBits < FragmentB->OffsetInBits; - }); + llvm::sort( + GVEs, [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) { + // Sort order: first null exprs, then exprs without fragment + // info, then sort by fragment offset in bits. + // FIXME: Come up with a more comprehensive comparator so + // the sorting isn't non-deterministic, and so the following + // std::unique call works correctly. + if (!A.Expr || !B.Expr) + return !!B.Expr; + auto FragmentA = A.Expr->getFragmentInfo(); + auto FragmentB = B.Expr->getFragmentInfo(); + if (!FragmentA || !FragmentB) + return !!FragmentB; + return FragmentA->OffsetInBits < FragmentB->OffsetInBits; + }); GVEs.erase(std::unique(GVEs.begin(), GVEs.end(), [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) { @@ -644,15 +704,18 @@ sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) { void DwarfDebug::beginModule() { NamedRegionTimer T(DbgTimerName, DbgTimerDescription, DWARFGroupName, DWARFGroupDescription, TimePassesIsEnabled); - if (DisableDebugInfoPrinting) + if (DisableDebugInfoPrinting) { + MMI->setDebugInfoAvailability(false); return; + } const Module *M = MMI->getModule(); unsigned NumDebugCUs = std::distance(M->debug_compile_units_begin(), M->debug_compile_units_end()); // Tell MMI whether we have debug info. - MMI->setDebugInfoAvailability(NumDebugCUs > 0); + assert(MMI->hasDebugInfo() == (NumDebugCUs > 0) && + "DebugInfoAvailabilty initialized unexpectedly"); SingleCU = NumDebugCUs == 1; DenseMap<DIGlobalVariable *, SmallVector<DwarfCompileUnit::GlobalExpr, 1>> GVMap; @@ -670,11 +733,24 @@ void DwarfDebug::beginModule() { (useSplitDwarf() ? SkeletonHolder : InfoHolder) .setStringOffsetsStartSym(Asm->createTempSymbol("str_offsets_base")); - // Create the symbol that designates the start of the DWARF v5 range list - // table. It is located past the header and before the offsets table. - if (getDwarfVersion() >= 5) - (useSplitDwarf() ? SkeletonHolder : InfoHolder) - .setRnglistsTableBaseSym(Asm->createTempSymbol("rnglists_table_base")); + + // Create the symbols that designates the start of the DWARF v5 range list + // and locations list tables. They are located past the table headers. + if (getDwarfVersion() >= 5) { + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + Holder.setRnglistsTableBaseSym( + Asm->createTempSymbol("rnglists_table_base")); + Holder.setLoclistsTableBaseSym( + Asm->createTempSymbol("loclists_table_base")); + + if (useSplitDwarf()) + InfoHolder.setRnglistsTableBaseSym( + Asm->createTempSymbol("rnglists_dwo_table_base")); + } + + // Create the symbol that points to the first entry following the debug + // address table (.debug_addr) header. + AddrPool.setLabel(Asm->createTempSymbol("addr_table_base")); for (DICompileUnit *CUNode : M->debug_compile_units()) { // FIXME: Move local imported entities into a list attached to the @@ -728,16 +804,16 @@ void DwarfDebug::beginModule() { } } -void DwarfDebug::finishVariableDefinitions() { - for (const auto &Var : ConcreteVariables) { - DIE *VariableDie = Var->getDIE(); - assert(VariableDie); +void DwarfDebug::finishEntityDefinitions() { + for (const auto &Entity : ConcreteEntities) { + DIE *Die = Entity->getDIE(); + assert(Die); // FIXME: Consider the time-space tradeoff of just storing the unit pointer - // in the ConcreteVariables list, rather than looking it up again here. + // in the ConcreteEntities list, rather than looking it up again here. // DIE::getUnit isn't simple - it walks parent pointers, etc. - DwarfCompileUnit *Unit = CUDieMap.lookup(VariableDie->getUnitDie()); + DwarfCompileUnit *Unit = CUDieMap.lookup(Die->getUnitDie()); assert(Unit); - Unit->finishVariableDefinition(*Var); + Unit->finishEntityDefinition(Entity.get()); } } @@ -755,7 +831,7 @@ void DwarfDebug::finalizeModuleInfo() { finishSubprogramDefinitions(); - finishVariableDefinitions(); + finishEntityDefinitions(); // Include the DWO file name in the hash if there's more than one CU. // This handles ThinLTO's situation where imported CUs may very easily be @@ -768,6 +844,8 @@ void DwarfDebug::finalizeModuleInfo() { // all other generation. for (const auto &P : CUMap) { auto &TheCU = *P.second; + if (TheCU.getCUNode()->isDebugDirectivesOnly()) + continue; // Emit DW_AT_containing_type attribute to connect types with their // vtable holding type. TheCU.constructContainingTypeDIEs(); @@ -776,7 +854,12 @@ void DwarfDebug::finalizeModuleInfo() { // If we're splitting the dwarf out now that we've got the entire // CU then add the dwo id to it. auto *SkCU = TheCU.getSkeleton(); - if (useSplitDwarf()) { + if (useSplitDwarf() && !empty(TheCU.getUnitDie().children())) { + finishUnitAttributes(TheCU.getCUNode(), TheCU); + TheCU.addString(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + Asm->TM.Options.MCOptions.SplitDwarfFile); + SkCU->addString(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + Asm->TM.Options.MCOptions.SplitDwarfFile); // Emit a unique identifier for this CU. uint64_t ID = DIEHash(Asm).computeCUSignature(DWOName, TheCU.getUnitDie()); @@ -789,18 +872,14 @@ void DwarfDebug::finalizeModuleInfo() { SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, ID); } - // We don't keep track of which addresses are used in which CU so this - // is a bit pessimistic under LTO. - if (!AddrPool.isEmpty()) { - const MCSymbol *Sym = TLOF.getDwarfAddrSection()->getBeginSymbol(); - SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base, - Sym, Sym); - } - if (getDwarfVersion() < 5 && !SkCU->getRangeLists().empty()) { + + if (getDwarfVersion() < 5 && !SkeletonHolder.getRangeLists().empty()) { const MCSymbol *Sym = TLOF.getDwarfRangesSection()->getBeginSymbol(); SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base, Sym, Sym); } + } else if (SkCU) { + finishUnitAttributes(SkCU->getCUNode(), *SkCU); } // If we have code split among multiple sections or non-contiguous @@ -810,6 +889,14 @@ void DwarfDebug::finalizeModuleInfo() { // .subsections_via_symbols in mach-o. This would mean turning on // ranges for all subprogram DIEs for mach-o. DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; + + // We don't keep track of which addresses are used in which CU so this + // is a bit pessimistic under LTO. + if (!AddrPool.isEmpty() && + (getDwarfVersion() >= 5 || + (SkCU && !empty(TheCU.getUnitDie().children())))) + U.addAddrTableBase(); + if (unsigned NumRanges = TheCU.getRanges().size()) { if (NumRanges > 1 && useRangesSection()) // A DW_AT_low_pc attribute may also be specified in combination with @@ -822,9 +909,13 @@ void DwarfDebug::finalizeModuleInfo() { U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges()); } - if (getDwarfVersion() >= 5 && !useSplitDwarf() && - !U.getRangeLists().empty()) - U.addRnglistsBase(); + if (getDwarfVersion() >= 5) { + if (U.hasRangeLists()) + U.addRnglistsBase(); + + if (!DebugLocs.getLists().empty() && !useSplitDwarf()) + U.addLoclistsBase(); + } auto *CUNode = cast<DICompileUnit>(P.first); // If compile Unit has macros, emit "DW_AT_macro_info" attribute. @@ -888,9 +979,11 @@ void DwarfDebug::endModule() { emitDebugInfoDWO(); emitDebugAbbrevDWO(); emitDebugLineDWO(); - emitDebugAddr(); + emitDebugRangesDWO(); } + emitDebugAddr(); + // Emit info into the dwarf accelerator table sections. switch (getAccelTableKind()) { case AccelTableKind::Apple: @@ -915,38 +1008,37 @@ void DwarfDebug::endModule() { // FIXME: AbstractVariables.clear(); } -void DwarfDebug::ensureAbstractVariableIsCreated(DwarfCompileUnit &CU, InlinedVariable IV, - const MDNode *ScopeNode) { - const DILocalVariable *Cleansed = nullptr; - if (CU.getExistingAbstractVariable(IV, Cleansed)) +void DwarfDebug::ensureAbstractEntityIsCreated(DwarfCompileUnit &CU, + const DINode *Node, + const MDNode *ScopeNode) { + if (CU.getExistingAbstractEntity(Node)) return; - CU.createAbstractVariable(Cleansed, LScopes.getOrCreateAbstractScope( + CU.createAbstractEntity(Node, LScopes.getOrCreateAbstractScope( cast<DILocalScope>(ScopeNode))); } -void DwarfDebug::ensureAbstractVariableIsCreatedIfScoped(DwarfCompileUnit &CU, - InlinedVariable IV, const MDNode *ScopeNode) { - const DILocalVariable *Cleansed = nullptr; - if (CU.getExistingAbstractVariable(IV, Cleansed)) +void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, + const DINode *Node, const MDNode *ScopeNode) { + if (CU.getExistingAbstractEntity(Node)) return; if (LexicalScope *Scope = LScopes.findAbstractScope(cast_or_null<DILocalScope>(ScopeNode))) - CU.createAbstractVariable(Cleansed, Scope); + CU.createAbstractEntity(Node, Scope); } // Collect variable information from side table maintained by MF. void DwarfDebug::collectVariableInfoFromMFTable( - DwarfCompileUnit &TheCU, DenseSet<InlinedVariable> &Processed) { - SmallDenseMap<InlinedVariable, DbgVariable *> MFVars; + DwarfCompileUnit &TheCU, DenseSet<InlinedEntity> &Processed) { + SmallDenseMap<InlinedEntity, DbgVariable *> MFVars; for (const auto &VI : Asm->MF->getVariableDbgInfo()) { if (!VI.Var) continue; assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) && "Expected inlined-at fields to agree"); - InlinedVariable Var(VI.Var, VI.Loc->getInlinedAt()); + InlinedEntity Var(VI.Var, VI.Loc->getInlinedAt()); Processed.insert(Var); LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); @@ -954,14 +1046,15 @@ void DwarfDebug::collectVariableInfoFromMFTable( if (!Scope) continue; - ensureAbstractVariableIsCreatedIfScoped(TheCU, Var, Scope->getScopeNode()); - auto RegVar = llvm::make_unique<DbgVariable>(Var.first, Var.second); + ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first, Scope->getScopeNode()); + auto RegVar = llvm::make_unique<DbgVariable>( + cast<DILocalVariable>(Var.first), Var.second); RegVar->initializeMMI(VI.Expr, VI.Slot); if (DbgVariable *DbgVar = MFVars.lookup(Var)) DbgVar->addMMIEntry(*RegVar); else if (InfoHolder.addScopeVariable(Scope, RegVar.get())) { MFVars.insert({Var, RegVar.get()}); - ConcreteVariables.push_back(std::move(RegVar)); + ConcreteEntities.push_back(std::move(RegVar)); } } } @@ -1087,6 +1180,18 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n"); auto Value = getDebugLocValue(Begin); + + // Omit entries with empty ranges as they do not have any effect in DWARF. + if (StartLabel == EndLabel) { + // If this is a fragment, we must still add the value to the list of + // open ranges, since it may describe non-overlapping parts of the + // variable. + if (DIExpr->isFragment()) + OpenRanges.push_back(Value); + LLVM_DEBUG(dbgs() << "Omitting location list entry with empty range.\n"); + continue; + } + DebugLocEntry Loc(StartLabel, EndLabel, Value); bool couldMerge = false; @@ -1126,14 +1231,26 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, } } -DbgVariable *DwarfDebug::createConcreteVariable(DwarfCompileUnit &TheCU, - LexicalScope &Scope, - InlinedVariable IV) { - ensureAbstractVariableIsCreatedIfScoped(TheCU, IV, Scope.getScopeNode()); - ConcreteVariables.push_back( - llvm::make_unique<DbgVariable>(IV.first, IV.second)); - InfoHolder.addScopeVariable(&Scope, ConcreteVariables.back().get()); - return ConcreteVariables.back().get(); +DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU, + LexicalScope &Scope, + const DINode *Node, + const DILocation *Location, + const MCSymbol *Sym) { + ensureAbstractEntityIsCreatedIfScoped(TheCU, Node, Scope.getScopeNode()); + if (isa<const DILocalVariable>(Node)) { + ConcreteEntities.push_back( + llvm::make_unique<DbgVariable>(cast<const DILocalVariable>(Node), + Location)); + InfoHolder.addScopeVariable(&Scope, + cast<DbgVariable>(ConcreteEntities.back().get())); + } else if (isa<const DILabel>(Node)) { + ConcreteEntities.push_back( + llvm::make_unique<DbgLabel>(cast<const DILabel>(Node), + Location, Sym)); + InfoHolder.addScopeLabel(&Scope, + cast<DbgLabel>(ConcreteEntities.back().get())); + } + return ConcreteEntities.back().get(); } /// Determine whether a *singular* DBG_VALUE is valid for the entirety of its @@ -1195,14 +1312,14 @@ static bool validThroughout(LexicalScopes &LScopes, } // Find variables for each lexical scope. -void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, - const DISubprogram *SP, - DenseSet<InlinedVariable> &Processed) { +void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, + const DISubprogram *SP, + DenseSet<InlinedEntity> &Processed) { // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMFTable(TheCU, Processed); for (const auto &I : DbgValues) { - InlinedVariable IV = I.first; + InlinedEntity IV = I.first; if (Processed.count(IV)) continue; @@ -1212,16 +1329,18 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, continue; LexicalScope *Scope = nullptr; + const DILocalVariable *LocalVar = cast<DILocalVariable>(IV.first); if (const DILocation *IA = IV.second) - Scope = LScopes.findInlinedScope(IV.first->getScope(), IA); + Scope = LScopes.findInlinedScope(LocalVar->getScope(), IA); else - Scope = LScopes.findLexicalScope(IV.first->getScope()); + Scope = LScopes.findLexicalScope(LocalVar->getScope()); // If variable scope is not found then skip this variable. if (!Scope) continue; Processed.insert(IV); - DbgVariable *RegVar = createConcreteVariable(TheCU, *Scope, IV); + DbgVariable *RegVar = cast<DbgVariable>(createConcreteEntity(TheCU, + *Scope, LocalVar, IV.second)); const MachineInstr *MInsn = Ranges.front().first; assert(MInsn->isDebugValue() && "History must begin with debug value"); @@ -1247,20 +1366,53 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, // unique identifiers, so don't bother resolving the type with the // identifier map. const DIBasicType *BT = dyn_cast<DIBasicType>( - static_cast<const Metadata *>(IV.first->getType())); + static_cast<const Metadata *>(LocalVar->getType())); // Finalize the entry by lowering it into a DWARF bytestream. for (auto &Entry : Entries) Entry.finalize(*Asm, List, BT); } - // Collect info for variables that were optimized out. + // For each InlinedEntity collected from DBG_LABEL instructions, convert to + // DWARF-related DbgLabel. + for (const auto &I : DbgLabels) { + InlinedEntity IL = I.first; + const MachineInstr *MI = I.second; + if (MI == nullptr) + continue; + + LexicalScope *Scope = nullptr; + const DILabel *Label = cast<DILabel>(IL.first); + // Get inlined DILocation if it is inlined label. + if (const DILocation *IA = IL.second) + Scope = LScopes.findInlinedScope(Label->getScope(), IA); + else + Scope = LScopes.findLexicalScope(Label->getScope()); + // If label scope is not found then skip this label. + if (!Scope) + continue; + + Processed.insert(IL); + /// At this point, the temporary label is created. + /// Save the temporary label to DbgLabel entity to get the + /// actually address when generating Dwarf DIE. + MCSymbol *Sym = getLabelBeforeInsn(MI); + createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym); + } + + // Collect info for variables/labels that were optimized out. for (const DINode *DN : SP->getRetainedNodes()) { + if (!Processed.insert(InlinedEntity(DN, nullptr)).second) + continue; + LexicalScope *Scope = nullptr; if (auto *DV = dyn_cast<DILocalVariable>(DN)) { - if (Processed.insert(InlinedVariable(DV, nullptr)).second) - if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope())) - createConcreteVariable(TheCU, *Scope, InlinedVariable(DV, nullptr)); + Scope = LScopes.findLexicalScope(DV->getScope()); + } else if (auto *DL = dyn_cast<DILabel>(DN)) { + Scope = LScopes.findLexicalScope(DL->getScope()); } + + if (Scope) + createConcreteEntity(TheCU, *Scope, DN, nullptr); } } @@ -1284,6 +1436,11 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { unsigned LastAsmLine = Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine(); + // Request a label after the call in order to emit AT_return_pc information + // in call site entries. TODO: Add support for targets with delay slots. + if (SP->areAllCallsDescribed() && MI->isCall() && !MI->hasDelaySlot()) + requestLabelAfterInsn(MI); + if (DL == PrevInstLoc) { // If we have an ongoing unspecified location, nothing to do here. if (!DL) @@ -1416,9 +1573,14 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); assert(!FnScope || SP == FnScope->getScopeNode()); DwarfCompileUnit &TheCU = *CUMap.lookup(SP->getUnit()); + if (TheCU.getCUNode()->isDebugDirectivesOnly()) { + PrevLabel = nullptr; + CurFn = nullptr; + return; + } - DenseSet<InlinedVariable> ProcessedVars; - collectVariableInfo(TheCU, SP, ProcessedVars); + DenseSet<InlinedEntity> Processed; + collectEntityInfo(TheCU, SP, Processed); // Add the range of this function to the list of ranges for the CU. TheCU.addRange(RangeSpan(Asm->getFunctionBegin(), Asm->getFunctionEnd())); @@ -1442,31 +1604,41 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { auto *SP = cast<DISubprogram>(AScope->getScopeNode()); for (const DINode *DN : SP->getRetainedNodes()) { - if (auto *DV = dyn_cast<DILocalVariable>(DN)) { - // Collect info for variables that were optimized out. - if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second) - continue; - ensureAbstractVariableIsCreated(TheCU, InlinedVariable(DV, nullptr), - DV->getScope()); - assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes - && "ensureAbstractVariableIsCreated inserted abstract scopes"); - } + if (!Processed.insert(InlinedEntity(DN, nullptr)).second) + continue; + + const MDNode *Scope = nullptr; + if (auto *DV = dyn_cast<DILocalVariable>(DN)) + Scope = DV->getScope(); + else if (auto *DL = dyn_cast<DILabel>(DN)) + Scope = DL->getScope(); + else + llvm_unreachable("Unexpected DI type!"); + + // Collect info for variables/labels that were optimized out. + ensureAbstractEntityIsCreated(TheCU, DN, Scope); + assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes + && "ensureAbstractEntityIsCreated inserted abstract scopes"); } constructAbstractSubprogramScopeDIE(TheCU, AScope); } ProcessedSPNodes.insert(SP); - TheCU.constructSubprogramScopeDIE(SP, FnScope); + DIE &ScopeDIE = TheCU.constructSubprogramScopeDIE(SP, FnScope); if (auto *SkelCU = TheCU.getSkeleton()) if (!LScopes.getAbstractScopesList().empty() && TheCU.getCUNode()->getSplitDebugInlining()) SkelCU->constructSubprogramScopeDIE(SP, FnScope); + // Construct call site entries. + constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF); + // Clear debug info // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the // DbgVariables except those that are also in AbstractVariables (since they // can be used cross-function) InfoHolder.getScopeVariables().clear(); + InfoHolder.getScopeLabels().clear(); PrevLabel = nullptr; CurFn = nullptr; } @@ -1530,8 +1702,6 @@ void DwarfDebug::emitAccelDebugNames() { if (getUnits().empty()) return; - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfDebugNamesSection()); emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits()); } @@ -1636,7 +1806,8 @@ void DwarfDebug::emitDebugPubSections() { if (!TheU->hasDwarfPubSections()) continue; - bool GnuStyle = TheU->getCUNode()->getGnuPubnames(); + bool GnuStyle = TheU->getCUNode()->getNameTableKind() == + DICompileUnit::DebugNameTableKind::GNU; Asm->OutStreamer->SwitchSection( GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection() @@ -1692,8 +1863,8 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name, if (GnuStyle) { dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity); Asm->OutStreamer->AddComment( - Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " + - dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); + Twine("Attributes: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + + ", " + dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); Asm->emitInt8(Desc.toBits()); } @@ -1759,6 +1930,7 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, void DebugLocEntry::finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List, const DIBasicType *BT) { + assert(Begin != End && "unexpected location list entry with empty range"); DebugLocStream::EntryBuilder Entry(List, Begin, End); BufferByteStreamer Streamer = Entry.getStreamer(); DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer); @@ -1791,25 +1963,119 @@ void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) { emitDebugLocEntry(Streamer, Entry); } -// Emit locations into the debug loc section. +// Emit the common part of the DWARF 5 range/locations list tables header. +static void emitListsTableHeaderStart(AsmPrinter *Asm, const DwarfFile &Holder, + MCSymbol *TableStart, + MCSymbol *TableEnd) { + // Build the table header, which starts with the length field. + Asm->OutStreamer->AddComment("Length"); + Asm->EmitLabelDifference(TableEnd, TableStart, 4); + Asm->OutStreamer->EmitLabel(TableStart); + // Version number (DWARF v5 and later). + Asm->OutStreamer->AddComment("Version"); + Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion()); + // Address size. + Asm->OutStreamer->AddComment("Address size"); + Asm->emitInt8(Asm->MAI->getCodePointerSize()); + // Segment selector size. + Asm->OutStreamer->AddComment("Segment selector size"); + Asm->emitInt8(0); +} + +// Emit the header of a DWARF 5 range list table list table. Returns the symbol +// that designates the end of the table for the caller to emit when the table is +// complete. +static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, + const DwarfFile &Holder) { + MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start"); + MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end"); + emitListsTableHeaderStart(Asm, Holder, TableStart, TableEnd); + + Asm->OutStreamer->AddComment("Offset entry count"); + Asm->emitInt32(Holder.getRangeLists().size()); + Asm->OutStreamer->EmitLabel(Holder.getRnglistsTableBaseSym()); + + for (const RangeSpanList &List : Holder.getRangeLists()) + Asm->EmitLabelDifference(List.getSym(), Holder.getRnglistsTableBaseSym(), + 4); + + return TableEnd; +} + +// Emit the header of a DWARF 5 locations list table. Returns the symbol that +// designates the end of the table for the caller to emit when the table is +// complete. +static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm, + const DwarfFile &Holder) { + MCSymbol *TableStart = Asm->createTempSymbol("debug_loclist_table_start"); + MCSymbol *TableEnd = Asm->createTempSymbol("debug_loclist_table_end"); + emitListsTableHeaderStart(Asm, Holder, TableStart, TableEnd); + + // FIXME: Generate the offsets table and use DW_FORM_loclistx with the + // DW_AT_loclists_base attribute. Until then set the number of offsets to 0. + Asm->OutStreamer->AddComment("Offset entry count"); + Asm->emitInt32(0); + Asm->OutStreamer->EmitLabel(Holder.getLoclistsTableBaseSym()); + + return TableEnd; +} + +// Emit locations into the .debug_loc/.debug_rnglists section. void DwarfDebug::emitDebugLoc() { if (DebugLocs.getLists().empty()) return; - // Start the dwarf loc section. - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfLocSection()); + bool IsLocLists = getDwarfVersion() >= 5; + MCSymbol *TableEnd = nullptr; + if (IsLocLists) { + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfLoclistsSection()); + TableEnd = emitLoclistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder + : InfoHolder); + } else { + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfLocSection()); + } + unsigned char Size = Asm->MAI->getCodePointerSize(); for (const auto &List : DebugLocs.getLists()) { Asm->OutStreamer->EmitLabel(List.Label); + const DwarfCompileUnit *CU = List.CU; + const MCSymbol *Base = CU->getBaseAddress(); 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.BeginSym, Base, Size); - Asm->EmitLabelDifference(Entry.EndSym, Base, Size); + if (Base) { + // 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 (IsLocLists) { + Asm->OutStreamer->AddComment("DW_LLE_offset_pair"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_offset_pair, 1); + Asm->OutStreamer->AddComment(" starting offset"); + Asm->EmitLabelDifferenceAsULEB128(Entry.BeginSym, Base); + Asm->OutStreamer->AddComment(" ending offset"); + Asm->EmitLabelDifferenceAsULEB128(Entry.EndSym, Base); + } else { + Asm->EmitLabelDifference(Entry.BeginSym, Base, Size); + Asm->EmitLabelDifference(Entry.EndSym, Base, Size); + } + + emitDebugLocEntryLocation(Entry); + continue; + } + + // We have no base address. + if (IsLocLists) { + // TODO: Use DW_LLE_base_addressx + DW_LLE_offset_pair, or + // DW_LLE_startx_length in case if there is only a single range. + // That should reduce the size of the debug data emited. + // For now just use the DW_LLE_startx_length for all cases. + Asm->OutStreamer->AddComment("DW_LLE_startx_length"); + Asm->emitInt8(dwarf::DW_LLE_startx_length); + Asm->OutStreamer->AddComment(" start idx"); + Asm->EmitULEB128(AddrPool.getIndex(Entry.BeginSym)); + Asm->OutStreamer->AddComment(" length"); + Asm->EmitLabelDifferenceAsULEB128(Entry.EndSym, Entry.BeginSym); } else { Asm->OutStreamer->EmitSymbolValue(Entry.BeginSym, Size); Asm->OutStreamer->EmitSymbolValue(Entry.EndSym, Size); @@ -1817,9 +2083,20 @@ void DwarfDebug::emitDebugLoc() { emitDebugLocEntryLocation(Entry); } - Asm->OutStreamer->EmitIntValue(0, Size); - Asm->OutStreamer->EmitIntValue(0, Size); + + if (IsLocLists) { + // .debug_loclists section ends with DW_LLE_end_of_list. + Asm->OutStreamer->AddComment("DW_LLE_end_of_list"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_end_of_list, 1); + } else { + // Terminate the .debug_loc list with two 0 values. + Asm->OutStreamer->EmitIntValue(0, Size); + Asm->OutStreamer->EmitIntValue(0, Size); + } } + + if (TableEnd) + Asm->OutStreamer->EmitLabel(TableEnd); } void DwarfDebug::emitDebugLocDWO() { @@ -1828,10 +2105,13 @@ void DwarfDebug::emitDebugLocDWO() { 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?) + // GDB only supports startx_length in pre-standard split-DWARF. + // (in v5 standard loclists, it currently* /only/ supports base_address + + // offset_pair, so the implementations can't really share much since they + // need to use different representations) + // * as of October 2018, at least + // Ideally/in v5, this could use SectionLabels to reuse existing addresses + // in the address pool to minimize object size/relocations. Asm->emitInt8(dwarf::DW_LLE_startx_length); unsigned idx = AddrPool.getIndex(Entry.BeginSym); Asm->EmitULEB128(idx); @@ -1939,10 +2219,9 @@ void DwarfDebug::emitDebugARanges() { } // Sort the CU list (again, to ensure consistent output order). - llvm::sort(CUs.begin(), CUs.end(), - [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) { - return A->getUniqueID() < B->getUniqueID(); - }); + llvm::sort(CUs, [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) { + return A->getUniqueID() < B->getUniqueID(); + }); // Emit an arange table for each CU we used. for (DwarfCompileUnit *CU : CUs) { @@ -2006,10 +2285,10 @@ void DwarfDebug::emitDebugARanges() { } /// Emit a single range list. We handle both DWARF v5 and earlier. -static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, +static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm, const RangeSpanList &List) { - auto DwarfVersion = CU->getDwarfVersion(); + auto DwarfVersion = DD.getDwarfVersion(); // Emit our symbol so we can find the beginning of the range. Asm->OutStreamer->EmitLabel(List.getSym()); // Gather all the ranges that apply to the same section so they can share @@ -2021,7 +2300,8 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, for (const RangeSpan &Range : List.getRanges()) SectionRanges[&Range.getStart()->getSection()].push_back(&Range); - auto *CUBase = CU->getBaseAddress(); + const DwarfCompileUnit &CU = List.getCU(); + const MCSymbol *CUBase = CU.getBaseAddress(); bool BaseIsSet = false; for (const auto &P : SectionRanges) { // Don't bother with a base address entry if there's only one range in @@ -2031,19 +2311,23 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, // or optnone where there may be holes in a single CU's section // contributions. auto *Base = CUBase; - if (!Base && P.second.size() > 1 && - (UseDwarfRangesBaseAddressSpecifier || DwarfVersion >= 5)) { + if (!Base && (P.second.size() > 1 || DwarfVersion < 5) && + (CU.getCUNode()->getRangesBaseAddress() || DwarfVersion >= 5)) { BaseIsSet = true; // FIXME/use care: This may not be a useful base address if it's not // the lowest address/range in this object. Base = P.second.front()->getStart(); if (DwarfVersion >= 5) { - Asm->OutStreamer->AddComment("DW_RLE_base_address"); - Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1); - } else + Base = DD.getSectionLabel(&Base->getSection()); + Asm->OutStreamer->AddComment("DW_RLE_base_addressx"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_addressx, 1); + Asm->OutStreamer->AddComment(" base address index"); + Asm->EmitULEB128(DD.getAddressPool().getIndex(Base)); + } else { Asm->OutStreamer->EmitIntValue(-1, Size); - Asm->OutStreamer->AddComment(" base address"); - Asm->OutStreamer->EmitSymbolValue(Base, Size); + Asm->OutStreamer->AddComment(" base address"); + Asm->OutStreamer->EmitSymbolValue(Base, Size); + } } else if (BaseIsSet && DwarfVersion < 5) { BaseIsSet = false; assert(!Base); @@ -2070,10 +2354,10 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, Asm->EmitLabelDifference(End, Base, Size); } } else if (DwarfVersion >= 5) { - Asm->OutStreamer->AddComment("DW_RLE_start_length"); - Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_start_length, 1); - Asm->OutStreamer->AddComment(" start"); - Asm->OutStreamer->EmitSymbolValue(Begin, Size); + Asm->OutStreamer->AddComment("DW_RLE_startx_length"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_startx_length, 1); + Asm->OutStreamer->AddComment(" start index"); + Asm->EmitULEB128(DD.getAddressPool().getIndex(Begin)); Asm->OutStreamer->AddComment(" length"); Asm->EmitLabelDifferenceAsULEB128(End, Begin); } else { @@ -2092,31 +2376,13 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, } } -// Emit the header of a DWARF 5 range list table. Returns the symbol that -// designates the end of the table for the caller to emit when the table is -// complete. -static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, DwarfFile &Holder) { - // The length is described by a starting label right after the length field - // and an end label. - MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start"); - MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end"); - // Build the range table header, which starts with the length field. - Asm->EmitLabelDifference(TableEnd, TableStart, 4); - Asm->OutStreamer->EmitLabel(TableStart); - // Version number (DWARF v5 and later). - Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion()); - // Address size. - Asm->emitInt8(Asm->MAI->getCodePointerSize()); - // Segment selector size. - Asm->emitInt8(0); - - MCSymbol *RnglistTableBaseSym = Holder.getRnglistsTableBaseSym(); +static void emitDebugRangesImpl(DwarfDebug &DD, AsmPrinter *Asm, + const DwarfFile &Holder, MCSymbol *TableEnd) { + for (const RangeSpanList &List : Holder.getRangeLists()) + emitRangeList(DD, Asm, List); - // FIXME: Generate the offsets table and use DW_FORM_rnglistx with the - // DW_AT_ranges attribute. Until then set the number of offsets to 0. - Asm->emitInt32(0); - Asm->OutStreamer->EmitLabel(RnglistTableBaseSym); - return TableEnd; + if (TableEnd) + Asm->OutStreamer->EmitLabel(TableEnd); } /// Emit address ranges into the .debug_ranges section or into the DWARF v5 @@ -2125,46 +2391,52 @@ void DwarfDebug::emitDebugRanges() { if (CUMap.empty()) return; - auto NoRangesPresent = [this]() { - return llvm::all_of( - CUMap, [](const decltype(CUMap)::const_iterator::value_type &Pair) { - return Pair.second->getRangeLists().empty(); - }); - }; + const auto &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - if (!useRangesSection()) { - assert(NoRangesPresent() && "No debug ranges expected."); + if (Holder.getRangeLists().empty()) return; - } - if (NoRangesPresent()) - return; + assert(useRangesSection()); + assert(llvm::none_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { + return Pair.second->getCUNode()->isDebugDirectivesOnly(); + })); // Start the dwarf ranges section. MCSymbol *TableEnd = nullptr; if (getDwarfVersion() >= 5) { Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfRnglistsSection()); - TableEnd = emitRnglistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder - : InfoHolder); + TableEnd = emitRnglistsTableHeader(Asm, Holder); } else Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfRangesSection()); - // Grab the specific ranges for the compile units in the module. - for (const auto &I : CUMap) { - DwarfCompileUnit *TheCU = I.second; + emitDebugRangesImpl(*this, Asm, Holder, TableEnd); +} - if (auto *Skel = TheCU->getSkeleton()) - TheCU = Skel; +void DwarfDebug::emitDebugRangesDWO() { + assert(useSplitDwarf()); - // Iterate over the misc ranges for the compile units in the module. - for (const RangeSpanList &List : TheCU->getRangeLists()) - emitRangeList(Asm, TheCU, List); - } + if (CUMap.empty()) + return; - if (TableEnd) - Asm->OutStreamer->EmitLabel(TableEnd); + const auto &Holder = InfoHolder; + + if (Holder.getRangeLists().empty()) + return; + + assert(getDwarfVersion() >= 5); + assert(useRangesSection()); + assert(llvm::none_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { + return Pair.second->getCUNode()->isDebugDirectivesOnly(); + })); + + // Start the dwarf ranges section. + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfRnglistsDWOSection()); + MCSymbol *TableEnd = emitRnglistsTableHeader(Asm, Holder); + + emitDebugRangesImpl(*this, Asm, Holder, TableEnd); } void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) { @@ -2206,12 +2478,19 @@ void DwarfDebug::emitDebugMacinfo() { if (CUMap.empty()) return; + if (llvm::all_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { + return Pair.second->getCUNode()->isDebugDirectivesOnly(); + })) + return; + // Start the dwarf macinfo section. Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfMacinfoSection()); for (const auto &P : CUMap) { auto &TheCU = *P.second; + if (TheCU.getCUNode()->isDebugDirectivesOnly()) + continue; auto *SkCU = TheCU.getSkeleton(); DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; auto *CUNode = cast<DICompileUnit>(P.first); @@ -2229,8 +2508,6 @@ void DwarfDebug::emitDebugMacinfo() { void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, std::unique_ptr<DwarfCompileUnit> NewU) { - NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name, - Asm->TM.Options.MCOptions.SplitDwarfFile); if (!CompilationDir.empty()) NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); @@ -2298,9 +2575,8 @@ void DwarfDebug::emitDebugStrDWO() { OffSec, /* UseRelativeOffsets = */ false); } -// Emit DWO addresses. +// Emit address pool. void DwarfDebug::emitDebugAddr() { - assert(useSplitDwarf() && "No split dwarf?"); AddrPool.emit(*Asm, Asm->getObjFileLowering().getDwarfAddrSection()); } @@ -2356,10 +2632,18 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, NewTU.setTypeSignature(Signature); Ins.first->second = Signature; - if (useSplitDwarf()) - NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesDWOSection()); - else { - NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + if (useSplitDwarf()) { + MCSection *Section = + getDwarfVersion() <= 4 + ? Asm->getObjFileLowering().getDwarfTypesDWOSection() + : Asm->getObjFileLowering().getDwarfInfoDWOSection(); + NewTU.setSection(Section); + } else { + MCSection *Section = + getDwarfVersion() <= 4 + ? Asm->getObjFileLowering().getDwarfTypesSection(Signature) + : Asm->getObjFileLowering().getDwarfInfoSection(Signature); + NewTU.setSection(Section); // Non-split type units reuse the compile unit's line table. CU.applyStmtList(UnitDie); } @@ -2408,14 +2692,18 @@ 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(AccelTable<DataT> &AppleAccel, StringRef Name, +void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU, + AccelTable<DataT> &AppleAccel, StringRef Name, const DIE &Die) { if (getAccelTableKind() == AccelTableKind::None) return; + if (getAccelTableKind() != AccelTableKind::Apple && + CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None) + return; + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - DwarfStringPoolEntryRef Ref = - Holder.getStringPool().getEntry(*Asm, Name); + DwarfStringPoolEntryRef Ref = Holder.getStringPool().getEntry(*Asm, Name); switch (getAccelTableKind()) { case AccelTableKind::Apple: @@ -2431,24 +2719,36 @@ void DwarfDebug::addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name, } } -void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) { - addAccelNameImpl(AccelNames, Name, Die); +void DwarfDebug::addAccelName(const DICompileUnit &CU, StringRef Name, + const DIE &Die) { + addAccelNameImpl(CU, AccelNames, Name, Die); } -void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) { +void DwarfDebug::addAccelObjC(const DICompileUnit &CU, StringRef Name, + const DIE &Die) { // ObjC names go only into the Apple accelerator tables. if (getAccelTableKind() == AccelTableKind::Apple) - addAccelNameImpl(AccelObjC, Name, Die); + addAccelNameImpl(CU, AccelObjC, Name, Die); } -void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) { - addAccelNameImpl(AccelNamespace, Name, Die); +void DwarfDebug::addAccelNamespace(const DICompileUnit &CU, StringRef Name, + const DIE &Die) { + addAccelNameImpl(CU, AccelNamespace, Name, Die); } -void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) { - addAccelNameImpl(AccelTypes, Name, Die); +void DwarfDebug::addAccelType(const DICompileUnit &CU, StringRef Name, + const DIE &Die, char Flags) { + addAccelNameImpl(CU, AccelTypes, Name, Die); } uint16_t DwarfDebug::getDwarfVersion() const { return Asm->OutStreamer->getContext().getDwarfVersion(); } + +void DwarfDebug::addSectionLabel(const MCSymbol *Sym) { + SectionLabels.insert(std::make_pair(&Sym->getSection(), Sym)); +} + +const MCSymbol *DwarfDebug::getSectionLabel(const MCSection *S) { + return SectionLabels.find(S)->second; +} |
