diff options
Diffstat (limited to 'contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp')
-rw-r--r-- | contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 559 |
1 files changed, 193 insertions, 366 deletions
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index f56c8e4..7fba768 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -26,7 +26,6 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/Constants.h" -#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Instructions.h" @@ -54,6 +53,7 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" + using namespace llvm; #define DEBUG_TYPE "dwarfdebug" @@ -105,13 +105,21 @@ DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden, clEnumVal(Disable, "Disabled"), clEnumValEnd), cl::init(Default)); -static cl::opt<DefaultOnOff> -DwarfLinkageNames("dwarf-linkage-names", cl::Hidden, - cl::desc("Emit DWARF linkage-name attributes."), - cl::values(clEnumVal(Default, "Default for platform"), - clEnumVal(Enable, "Enabled"), - clEnumVal(Disable, "Disabled"), clEnumValEnd), - cl::init(Default)); +enum LinkageNameOption { + DefaultLinkageNames, + AllLinkageNames, + AbstractLinkageNames +}; +static cl::opt<LinkageNameOption> + DwarfLinkageNames("dwarf-linkage-names", cl::Hidden, + cl::desc("Which DWARF linkage-name attributes to emit."), + cl::values(clEnumValN(DefaultLinkageNames, "Default", + "Default for platform"), + clEnumValN(AllLinkageNames, "All", "All"), + clEnumValN(AbstractLinkageNames, "Abstract", + "Abstract subprograms"), + clEnumValEnd), + cl::init(DefaultLinkageNames)); static const char *const DWARFGroupName = "DWARF Emission"; static const char *const DbgTimerName = "DWARF Debug Writer"; @@ -130,28 +138,21 @@ void DebugLocDwarfExpression::EmitUnsigned(uint64_t Value) { BS.EmitULEB128(Value, Twine(Value)); } -bool DebugLocDwarfExpression::isFrameRegister(unsigned MachineReg) { +bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI, + unsigned MachineReg) { // This information is not available while emitting .debug_loc entries. return false; } //===----------------------------------------------------------------------===// -/// resolve - Look in the DwarfDebug map for the MDNode that -/// corresponds to the reference. -template <typename T> T *DbgVariable::resolve(TypedDINodeRef<T> Ref) const { - return DD->resolve(Ref); -} - bool DbgVariable::isBlockByrefVariable() const { assert(Var && "Invalid complex DbgVariable!"); - return Var->getType() - .resolve(DD->getTypeIdentifierMap()) - ->isBlockByrefStruct(); + return Var->getType().resolve()->isBlockByrefStruct(); } const DIType *DbgVariable::getType() const { - DIType *Ty = Var->getType().resolve(DD->getTypeIdentifierMap()); + DIType *Ty = Var->getType().resolve(); // FIXME: isBlockByrefVariable should be reformulated in terms of complex // addresses instead. if (Ty->isBlockByrefStruct()) { @@ -201,8 +202,8 @@ static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = { DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) - : Asm(A), MMI(Asm->MMI), DebugLocs(A->OutStreamer->isVerboseAsm()), - PrevLabel(nullptr), InfoHolder(A, "info_string", DIEValueAllocator), + : DebugHandlerBase(A), DebugLocs(A->OutStreamer->isVerboseAsm()), + InfoHolder(A, "info_string", DIEValueAllocator), SkeletonHolder(A, "skel_string", DIEValueAllocator), IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()), AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, @@ -214,7 +215,6 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) AccelTypes(TypeAtoms), DebuggerTuning(DebuggerKind::Default) { CurFn = nullptr; - CurMI = nullptr; Triple TT(Asm->getTargetTriple()); // Make sure we know our "debugger tuning." The target option takes @@ -234,6 +234,8 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) else HasDwarfAccelTables = DwarfAccelTables == Enable; + HasAppleExtensionAttributes = tuneForLLDB(); + // Handle split DWARF. Off by default for now. if (SplitDwarf == Default) HasSplitDwarf = false; @@ -246,11 +248,11 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) else HasDwarfPubSections = DwarfPubSections == Enable; - // SCE does not use linkage names. - if (DwarfLinkageNames == Default) - UseLinkageNames = !tuneForSCE(); + // SCE defaults to linkage names only for abstract subprograms. + if (DwarfLinkageNames == DefaultLinkageNames) + UseAllLinkageNames = !tuneForSCE(); else - UseLinkageNames = DwarfLinkageNames == Enable; + UseAllLinkageNames = DwarfLinkageNames == AllLinkageNames; unsigned DwarfVersionNumber = Asm->TM.Options.MCOptions.DwarfVersion; DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber @@ -265,12 +267,10 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) // https://sourceware.org/bugzilla/show_bug.cgi?id=11616 UseGNUTLSOpcode = tuneForGDB() || DwarfVersion < 3; - Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion); + // GDB does not fully support the DWARF 4 representation for bitfields. + UseDWARF2Bitfields = (DwarfVersion < 4) || tuneForGDB(); - { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - beginModule(); - } + Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion); } // Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h. @@ -297,7 +297,6 @@ static void getObjCClassCategory(StringRef In, StringRef &Class, Class = In.slice(In.find('[') + 1, In.find('(')); Category = In.slice(In.find('[') + 1, In.find(' ')); - return; } static StringRef getObjCMethodName(StringRef In) { @@ -367,8 +366,8 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(LexicalScope *Scope) { // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram // was inlined from another compile unit. - auto &CU = SPMap[SP]; - forBothCUs(*CU, [&](DwarfCompileUnit &CU) { + auto &CU = *CUMap.lookup(cast<DISubprogram>(SP)->getUnit()); + forBothCUs(CU, [&](DwarfCompileUnit &CU) { CU.constructAbstractSubprogramScopeDIE(Scope); }); } @@ -392,8 +391,11 @@ DwarfDebug::constructDwarfCompileUnit(const DICompileUnit *DIUnit) { DwarfCompileUnit &NewCU = *OwnedUnit; DIE &Die = NewCU.getUnitDie(); InfoHolder.addUnit(std::move(OwnedUnit)); - if (useSplitDwarf()) + if (useSplitDwarf()) { NewCU.setSkeleton(constructSkeletonCU(NewCU)); + NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name, + DIUnit->getSplitDebugFilename()); + } // LTO with assembly output shares a single line table amongst multiple CUs. // To avoid the compilation directory being ambiguous, let the line table @@ -419,16 +421,18 @@ DwarfDebug::constructDwarfCompileUnit(const DICompileUnit *DIUnit) { addGnuPubAttributes(NewCU, Die); } - if (DIUnit->isOptimized()) - NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized); + if (useAppleExtensionAttributes()) { + if (DIUnit->isOptimized()) + NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized); - StringRef Flags = DIUnit->getFlags(); - if (!Flags.empty()) - NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags); + StringRef Flags = DIUnit->getFlags(); + if (!Flags.empty()) + NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags); - if (unsigned RVer = DIUnit->getRuntimeVersion()) - NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, - dwarf::DW_FORM_data1, RVer); + if (unsigned RVer = DIUnit->getRuntimeVersion()) + NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, + dwarf::DW_FORM_data1, RVer); + } if (useSplitDwarf()) NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection()); @@ -460,48 +464,42 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, // global DIEs and emit initial debug info sections. This is invoked by // the target AsmPrinter. void DwarfDebug::beginModule() { + NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); if (DisableDebugInfoPrinting) return; const Module *M = MMI->getModule(); - NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); - if (!CU_Nodes) - return; - TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes); - - SingleCU = CU_Nodes->getNumOperands() == 1; + 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); + SingleCU = NumDebugCUs == 1; - for (MDNode *N : CU_Nodes->operands()) { - auto *CUNode = cast<DICompileUnit>(N); + for (DICompileUnit *CUNode : M->debug_compile_units()) { DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode); for (auto *IE : CUNode->getImportedEntities()) CU.addImportedEntity(IE); for (auto *GV : CUNode->getGlobalVariables()) CU.getOrCreateGlobalVariableDIE(GV); - for (auto *SP : CUNode->getSubprograms()) - SPMap.insert(std::make_pair(SP, &CU)); for (auto *Ty : CUNode->getEnumTypes()) { // The enum types array by design contains pointers to // MDNodes rather than DIRefs. Unique them here. - CU.getOrCreateTypeDIE(cast<DIType>(resolve(Ty->getRef()))); + CU.getOrCreateTypeDIE(cast<DIType>(Ty)); } for (auto *Ty : CUNode->getRetainedTypes()) { // The retained types array by design contains pointers to // MDNodes rather than DIRefs. Unique them here. - DIType *RT = cast<DIType>(resolve(Ty->getRef())); - if (!RT->isExternalTypeRef()) - // There is no point in force-emitting a forward declaration. - CU.getOrCreateTypeDIE(RT); + if (DIType *RT = dyn_cast<DIType>(Ty)) + if (!RT->isExternalTypeRef()) + // There is no point in force-emitting a forward declaration. + CU.getOrCreateTypeDIE(RT); } // Emit imported_modules last so that the relevant context is already // available. for (auto *IE : CUNode->getImportedEntities()) constructAndAddImportedEntityDIE(CU, IE); } - - // Tell MMI that we have debug info. - MMI->setDebugInfoAvailability(true); } void DwarfDebug::finishVariableDefinitions() { @@ -524,31 +522,13 @@ void DwarfDebug::finishVariableDefinitions() { } void DwarfDebug::finishSubprogramDefinitions() { - for (const auto &P : SPMap) - forBothCUs(*P.second, [&](DwarfCompileUnit &CU) { - CU.finishSubprogramDefinition(cast<DISubprogram>(P.first)); - }); -} - - -// Collect info for variables that were optimized out. -void DwarfDebug::collectDeadVariables() { - const Module *M = MMI->getModule(); - - if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { - for (MDNode *N : CU_Nodes->operands()) { - auto *TheCU = cast<DICompileUnit>(N); - // Construct subprogram DIE and add variables DIEs. - DwarfCompileUnit *SPCU = - static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU)); - assert(SPCU && "Unable to find Compile Unit!"); - for (auto *SP : TheCU->getSubprograms()) { - if (ProcessedSPNodes.count(SP) != 0) - continue; - SPCU->collectDeadVariables(SP); - } - } - } + for (auto &F : MMI->getModule()->functions()) + if (auto *SP = F.getSubprogram()) + if (ProcessedSPNodes.count(SP) && + SP->getUnit()->getEmissionKind() != DICompileUnit::NoDebug) + forBothCUs(*CUMap.lookup(SP->getUnit()), [&](DwarfCompileUnit &CU) { + CU.finishSubprogramDefinition(SP); + }); } void DwarfDebug::finalizeModuleInfo() { @@ -558,11 +538,6 @@ void DwarfDebug::finalizeModuleInfo() { finishVariableDefinitions(); - // Collect info for variables that were optimized out. - collectDeadVariables(); - - unsigned MacroOffset = 0; - std::unique_ptr<AsmStreamerBase> AS(new SizeReporterAsmStreamer(Asm)); // Handle anything that needs to be done on a per-unit basis after // all other generation. for (const auto &P : CUMap) { @@ -617,13 +592,11 @@ void DwarfDebug::finalizeModuleInfo() { } auto *CUNode = cast<DICompileUnit>(P.first); - if (CUNode->getMacros()) { - // Compile Unit has macros, emit "DW_AT_macro_info" attribute. - U.addUInt(U.getUnitDie(), dwarf::DW_AT_macro_info, - dwarf::DW_FORM_sec_offset, MacroOffset); - // Update macro section offset - MacroOffset += handleMacroNodes(AS.get(), CUNode->getMacros(), U); - } + // If compile Unit has macros, emit "DW_AT_macro_info" attribute. + if (CUNode->getMacros()) + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_macro_info, + U.getMacroLabelBegin(), + TLOF.getDwarfMacinfoSection()->getBeginSymbol()); } // Compute DIE offsets and sizes. @@ -694,7 +667,6 @@ void DwarfDebug::endModule() { } // clean up. - SPMap.clear(); AbstractVariables.clear(); } @@ -717,7 +689,7 @@ DbgVariable *DwarfDebug::getExistingAbstractVariable(InlinedVariable IV) { void DwarfDebug::createAbstractVariable(const DILocalVariable *Var, LexicalScope *Scope) { - auto AbsDbgVariable = make_unique<DbgVariable>(Var, /* IA */ nullptr, this); + auto AbsDbgVariable = make_unique<DbgVariable>(Var, /* IA */ nullptr); InfoHolder.addScopeVariable(Scope, AbsDbgVariable.get()); AbstractVariables[Var] = std::move(AbsDbgVariable); } @@ -761,7 +733,7 @@ void DwarfDebug::collectVariableInfoFromMMITable( continue; ensureAbstractVariableIsCreatedIfScoped(Var, Scope->getScopeNode()); - auto RegVar = make_unique<DbgVariable>(Var.first, Var.second, this); + auto RegVar = make_unique<DbgVariable>(Var.first, Var.second); RegVar->initializeMMI(VI.Expr, VI.Slot); if (InfoHolder.addScopeVariable(Scope, RegVar.get())) ConcreteVariables.push_back(std::move(RegVar)); @@ -793,29 +765,6 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); } -// Determine the relative position of the pieces described by P1 and P2. -// Returns -1 if P1 is entirely before P2, 0 if P1 and P2 overlap, -// 1 if P1 is entirely after P2. -static int pieceCmp(const DIExpression *P1, const DIExpression *P2) { - unsigned l1 = P1->getBitPieceOffset(); - unsigned l2 = P2->getBitPieceOffset(); - unsigned r1 = l1 + P1->getBitPieceSize(); - unsigned r2 = l2 + P2->getBitPieceSize(); - if (r1 <= l2) - return -1; - else if (r2 <= l1) - return 1; - else - return 0; -} - -/// Determine whether two variable pieces overlap. -static bool piecesOverlap(const DIExpression *P1, const DIExpression *P2) { - if (!P1->isBitPiece() || !P2->isBitPiece()) - return true; - return pieceCmp(P1, P2) == 0; -} - /// \brief If this and Next are describing different pieces of the same /// variable, merge them by appending Next's values to the current /// list of values. @@ -832,8 +781,9 @@ bool DebugLocEntry::MergeValues(const DebugLocEntry &Next) { // sorted. for (unsigned i = 0, j = 0; i < Values.size(); ++i) { for (; j < Next.Values.size(); ++j) { - int res = pieceCmp(cast<DIExpression>(Values[i].Expression), - cast<DIExpression>(Next.Values[j].Expression)); + int res = DebugHandlerBase::pieceCmp( + cast<DIExpression>(Values[i].Expression), + cast<DIExpression>(Next.Values[j].Expression)); if (res == 0) // The two expressions overlap, we can't merge. return false; // Values[i] is entirely before Next.Values[j], @@ -944,7 +894,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, DEBUG({ dbgs() << CurEntry->getValues().size() << " Values:\n"; for (auto &Value : CurEntry->getValues()) - Value.getExpression()->dump(); + Value.dump(); dbgs() << "-----\n"; }); @@ -957,12 +907,23 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, DbgVariable *DwarfDebug::createConcreteVariable(LexicalScope &Scope, InlinedVariable IV) { ensureAbstractVariableIsCreatedIfScoped(IV, Scope.getScopeNode()); - ConcreteVariables.push_back( - make_unique<DbgVariable>(IV.first, IV.second, this)); + ConcreteVariables.push_back(make_unique<DbgVariable>(IV.first, IV.second)); InfoHolder.addScopeVariable(&Scope, ConcreteVariables.back().get()); return ConcreteVariables.back().get(); } +// Determine whether this DBG_VALUE is valid at the beginning of the function. +static bool validAtEntry(const MachineInstr *MInsn) { + auto MBB = MInsn->getParent(); + // Is it in the entry basic block? + if (!MBB->pred_empty()) + return false; + for (MachineBasicBlock::const_reverse_iterator I(MInsn); I != MBB->rend(); ++I) + if (!(I->isDebugValue() || I->getFlag(MachineInstr::FrameSetup))) + return false; + return true; +} + // Find variables for each lexical scope. void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP, @@ -995,8 +956,11 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, const MachineInstr *MInsn = Ranges.front().first; assert(MInsn->isDebugValue() && "History must begin with debug value"); - // Check if the first DBG_VALUE is valid for the rest of the function. - if (Ranges.size() == 1 && Ranges.front().second == nullptr) { + // Check if there is a single DBG_VALUE, valid throughout the function. + // A single constant is also considered valid for the entire function. + if (Ranges.size() == 1 && + (MInsn->getOperand(0).isImm() || + (validAtEntry(MInsn) && Ranges.front().second == nullptr))) { RegVar->initializeDbgValue(MInsn); continue; } @@ -1008,7 +972,7 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, SmallVector<DebugLocEntry, 8> Entries; buildLocationList(Entries, Ranges); - // If the variable has an DIBasicType, extract it. Basic types cannot have + // If the variable has a DIBasicType, extract it. Basic types cannot have // unique identifiers, so don't bother resolving the type with the // identifier map. const DIBasicType *BT = dyn_cast<DIBasicType>( @@ -1027,25 +991,14 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, } } -// Return Label preceding the instruction. -MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) { - MCSymbol *Label = LabelsBeforeInsn.lookup(MI); - assert(Label && "Didn't insert label before instruction"); - return Label; -} - -// Return Label immediately following the instruction. -MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { - return LabelsAfterInsn.lookup(MI); -} - // Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { - assert(CurMI == nullptr); - CurMI = MI; + DebugHandlerBase::beginInstruction(MI); + assert(CurMI); + // Check if source location changes, but ignore DBG_VALUE locations. if (!MI->isDebugValue()) { - DebugLoc DL = MI->getDebugLoc(); + const DebugLoc &DL = MI->getDebugLoc(); if (DL != PrevInstLoc) { if (DL) { unsigned Flags = 0; @@ -1067,78 +1020,6 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { } } } - - // Insert labels where requested. - DenseMap<const MachineInstr *, MCSymbol *>::iterator I = - LabelsBeforeInsn.find(MI); - - // No label needed. - if (I == LabelsBeforeInsn.end()) - return; - - // Label already assigned. - if (I->second) - return; - - if (!PrevLabel) { - PrevLabel = MMI->getContext().createTempSymbol(); - Asm->OutStreamer->EmitLabel(PrevLabel); - } - I->second = PrevLabel; -} - -// Process end of an instruction. -void DwarfDebug::endInstruction() { - assert(CurMI != nullptr); - // Don't create a new label after DBG_VALUE instructions. - // They don't generate code. - if (!CurMI->isDebugValue()) - PrevLabel = nullptr; - - DenseMap<const MachineInstr *, MCSymbol *>::iterator I = - LabelsAfterInsn.find(CurMI); - CurMI = nullptr; - - // No label needed. - if (I == LabelsAfterInsn.end()) - return; - - // Label already assigned. - if (I->second) - return; - - // We need a label after this instruction. - if (!PrevLabel) { - PrevLabel = MMI->getContext().createTempSymbol(); - Asm->OutStreamer->EmitLabel(PrevLabel); - } - I->second = PrevLabel; -} - -// Each LexicalScope has first instruction and last instruction to mark -// beginning and end of a scope respectively. Create an inverse map that list -// scopes starts (and ends) with an instruction. One instruction may start (or -// end) multiple scopes. Ignore scopes that are not reachable. -void DwarfDebug::identifyScopeMarkers() { - SmallVector<LexicalScope *, 4> WorkList; - WorkList.push_back(LScopes.getCurrentFunctionScope()); - while (!WorkList.empty()) { - LexicalScope *S = WorkList.pop_back_val(); - - const SmallVectorImpl<LexicalScope *> &Children = S->getChildren(); - if (!Children.empty()) - WorkList.append(Children.begin(), Children.end()); - - if (S->isAbstractScope()) - continue; - - for (const InsnRange &R : S->getRanges()) { - assert(R.first && "InsnRange does not have first instruction!"); - assert(R.second && "InsnRange does not have second instruction!"); - requestLabelBeforeInsn(R.first); - requestLabelAfterInsn(R.second); - } - } } static DebugLoc findPrologueEndLoc(const MachineFunction *MF) { @@ -1167,15 +1048,10 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Grab the lexical scopes for the function, if we don't have any of those // then we're not going to be able to do anything. - LScopes.initialize(*MF); + DebugHandlerBase::beginFunction(MF); if (LScopes.empty()) return; - assert(DbgValues.empty() && "DbgValues map wasn't cleaned!"); - - // Make sure that each lexical scope will have a begin/end label. - identifyScopeMarkers(); - // Set DwarfDwarfCompileUnitID in MCContext to the Compile Unit this function // belongs to so that we add to the correct per-cu line table in the // non-asm case. @@ -1188,55 +1064,19 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // isn't structurally identical (see: file path/name info from clang, which // includes the directory of the cpp file being built, even when the file name // is absolute (such as an <> lookup header))) - DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); - assert(TheCU && "Unable to find compile unit!"); + auto *SP = cast<DISubprogram>(FnScope->getScopeNode()); + DwarfCompileUnit *TheCU = CUMap.lookup(SP->getUnit()); + if (!TheCU) { + assert(SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug && + "DICompileUnit missing from llvm.dbg.cu?"); + return; + } if (Asm->OutStreamer->hasRawTextSupport()) // Use a single line table if we are generating assembly. Asm->OutStreamer->getContext().setDwarfCompileUnitID(0); else Asm->OutStreamer->getContext().setDwarfCompileUnitID(TheCU->getUniqueID()); - // Calculate history for local variables. - calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(), - DbgValues); - - // Request labels for the full history. - for (const auto &I : DbgValues) { - const auto &Ranges = I.second; - if (Ranges.empty()) - continue; - - // The first mention of a function argument gets the CurrentFnBegin - // label, so arguments are visible when breaking at function entry. - const DILocalVariable *DIVar = Ranges.front().first->getDebugVariable(); - if (DIVar->isParameter() && - getDISubprogram(DIVar->getScope())->describes(MF->getFunction())) { - LabelsBeforeInsn[Ranges.front().first] = Asm->getFunctionBegin(); - if (Ranges.front().first->getDebugExpression()->isBitPiece()) { - // Mark all non-overlapping initial pieces. - for (auto I = Ranges.begin(); I != Ranges.end(); ++I) { - const DIExpression *Piece = I->first->getDebugExpression(); - if (std::all_of(Ranges.begin(), I, - [&](DbgValueHistoryMap::InstrRange Pred) { - return !piecesOverlap(Piece, Pred.first->getDebugExpression()); - })) - LabelsBeforeInsn[I->first] = Asm->getFunctionBegin(); - else - break; - } - } - } - - for (const auto &Range : Ranges) { - requestLabelBeforeInsn(Range.first); - if (Range.second) - requestLabelAfterInsn(Range.second); - } - } - - PrevInstLoc = DebugLoc(); - PrevLabel = Asm->getFunctionBegin(); - // Record beginning of function. PrologEndLoc = findPrologueEndLoc(MF); if (DILocation *L = PrologEndLoc) { @@ -1252,13 +1092,19 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { assert(CurFn == MF && "endFunction should be called with the same function as beginFunction"); - if (!MMI->hasDebugInfo() || LScopes.empty() || - !MF->getFunction()->getSubprogram()) { + const DISubprogram *SP = MF->getFunction()->getSubprogram(); + if (!MMI->hasDebugInfo() || LScopes.empty() || !SP || + SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug) { // If we don't have a lexical scope for this function then there will // be a hole in the range information. Keep note of this by setting the // previously used section to nullptr. PrevCU = nullptr; CurFn = nullptr; + DebugHandlerBase::endFunction(MF); + // Mark functions with no debug info on any instructions, but a + // valid DISubprogram as processed. + if (SP) + ProcessedSPNodes.insert(SP); return; } @@ -1266,8 +1112,8 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { Asm->OutStreamer->getContext().setDwarfCompileUnitID(0); LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - auto *SP = cast<DISubprogram>(FnScope->getScopeNode()); - DwarfCompileUnit &TheCU = *SPMap.lookup(SP); + SP = cast<DISubprogram>(FnScope->getScopeNode()); + DwarfCompileUnit &TheCU = *CUMap.lookup(SP->getUnit()); DenseSet<InlinedVariable> ProcessedVars; collectVariableInfo(TheCU, SP, ProcessedVars); @@ -1277,17 +1123,16 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Under -gmlt, skip building the subprogram if there are no inlined // subroutines inside it. - if (TheCU.getCUNode()->getEmissionKind() == DIBuilder::LineTablesOnly && + if (TheCU.getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly && LScopes.getAbstractScopesList().empty() && !IsDarwin) { assert(InfoHolder.getScopeVariables().empty()); assert(DbgValues.empty()); // FIXME: This wouldn't be true in LTO with a -g (with inlining) CU followed // by a -gmlt CU. Add a test and remove this assertion. assert(AbstractVariables.empty()); - LabelsBeforeInsn.clear(); - LabelsAfterInsn.clear(); PrevLabel = nullptr; CurFn = nullptr; + DebugHandlerBase::endFunction(MF); return; } @@ -1319,11 +1164,9 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // DbgVariables except those that are also in AbstractVariables (since they // can be used cross-function) InfoHolder.getScopeVariables().clear(); - DbgValues.clear(); - LabelsBeforeInsn.clear(); - LabelsAfterInsn.clear(); PrevLabel = nullptr; CurFn = nullptr; + DebugHandlerBase::endFunction(MF); } // Register a source line with debug info. Returns the unique label that was @@ -1535,7 +1378,7 @@ void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { &DwarfCompileUnit::getGlobalTypes); } -// Emit visible names into a debug str section. +/// Emit null-terminated strings into a debug str section. void DwarfDebug::emitDebugStr() { DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); @@ -1554,8 +1397,7 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, ByteStreamer &Streamer, const DebugLocEntry::Value &Value, unsigned PieceOffsetInBits) { - DebugLocDwarfExpression DwarfExpr(*AP.MF->getSubtarget().getRegisterInfo(), - AP.getDwarfDebug()->getDwarfVersion(), + DebugLocDwarfExpression DwarfExpr(AP.getDwarfDebug()->getDwarfVersion(), Streamer); // Regular entry. if (Value.isInt()) { @@ -1572,18 +1414,19 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, AP.EmitDwarfRegOp(Streamer, Loc); else { // Complex address entry. + const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo(); if (Loc.getOffset()) { - DwarfExpr.AddMachineRegIndirect(Loc.getReg(), Loc.getOffset()); + DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset()); DwarfExpr.AddExpression(Expr->expr_op_begin(), Expr->expr_op_end(), PieceOffsetInBits); } else - DwarfExpr.AddMachineRegExpression(Expr, Loc.getReg(), + DwarfExpr.AddMachineRegExpression(TRI, Expr, Loc.getReg(), PieceOffsetInBits); } + } else if (Value.isConstantFP()) { + APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt(); + DwarfExpr.AddUnsignedConstant(RawBytes); } - // else ... ignore constant fp. There is not any good way to - // to represent them here in dwarf. - // FIXME: ^ } void DebugLocEntry::finalize(const AsmPrinter &AP, @@ -1608,8 +1451,7 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, assert(Offset <= PieceOffset && "overlapping or duplicate pieces"); if (Offset < PieceOffset) { // The DWARF spec seriously mandates pieces with no locations for gaps. - DebugLocDwarfExpression Expr(*AP.MF->getSubtarget().getRegisterInfo(), - AP.getDwarfDebug()->getDwarfVersion(), + DebugLocDwarfExpression Expr(AP.getDwarfDebug()->getDwarfVersion(), Streamer); Expr.AddOpPiece(PieceOffset-Offset, 0); Offset += PieceOffset-Offset; @@ -1708,24 +1550,12 @@ void DwarfDebug::emitDebugARanges() { } } - // Add terminating symbols for each section. - for (const auto &I : SectionMap) { - MCSection *Section = I.first; - MCSymbol *Sym = nullptr; - - if (Section) - Sym = Asm->OutStreamer->endSection(Section); - - // Insert a final terminator. - SectionMap[Section].push_back(SymbolCU(nullptr, Sym)); - } - DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> Spans; for (auto &I : SectionMap) { - const MCSection *Section = I.first; + MCSection *Section = I.first; SmallVector<SymbolCU, 8> &List = I.second; - if (List.size() < 2) + if (List.size() < 1) continue; // If we have no section (e.g. common), just write out @@ -1735,26 +1565,29 @@ void DwarfDebug::emitDebugARanges() { ArangeSpan Span; Span.Start = Cur.Sym; Span.End = nullptr; - if (Cur.CU) - Spans[Cur.CU].push_back(Span); + assert(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) { - unsigned IA = A.Sym ? Asm->OutStreamer->GetSymbolOrder(A.Sym) : 0; - unsigned IB = B.Sym ? Asm->OutStreamer->GetSymbolOrder(B.Sym) : 0; - - // Symbols with no order assigned should be placed at the end. - // (e.g. section end labels) - if (IA == 0) - return false; - if (IB == 0) - return true; - return IA < IB; - }); + std::sort( + List.begin(), List.end(), [&](const SymbolCU &A, const SymbolCU &B) { + unsigned IA = A.Sym ? Asm->OutStreamer->GetSymbolOrder(A.Sym) : 0; + unsigned IB = B.Sym ? Asm->OutStreamer->GetSymbolOrder(B.Sym) : 0; + + // Symbols with no order assigned should be placed at the end. + // (e.g. section end labels) + if (IA == 0) + return false; + if (IB == 0) + return true; + return IA < IB; + }); + + // Insert a final terminator. + List.push_back(SymbolCU(nullptr, Asm->OutStreamer->endSection(Section))); // Build spans between each label. const MCSymbol *StartSym = List[0].Sym; @@ -1767,6 +1600,7 @@ void DwarfDebug::emitDebugARanges() { ArangeSpan Span; Span.Start = StartSym; Span.End = Cur.Sym; + assert(Prev.CU); Spans[Prev.CU].push_back(Span); StartSym = Cur.Sym; } @@ -1787,9 +1621,10 @@ void DwarfDebug::emitDebugARanges() { } // Sort the CU list (again, to ensure consistent output order). - std::sort(CUs.begin(), CUs.end(), [](const DwarfUnit *A, const DwarfUnit *B) { - return A->getUniqueID() < B->getUniqueID(); - }); + std::sort(CUs.begin(), CUs.end(), + [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) { + return A->getUniqueID() < B->getUniqueID(); + }); // Emit an arange table for each CU we used. for (DwarfCompileUnit *CU : CUs) { @@ -1827,7 +1662,7 @@ void DwarfDebug::emitDebugARanges() { Asm->OutStreamer->AddComment("Segment Size (in bytes)"); Asm->EmitInt8(0); - Asm->OutStreamer->EmitFill(Padding, 0xff); + Asm->OutStreamer->emitFill(Padding, 0xff); for (const ArangeSpan &Span : List) { Asm->EmitLabelReference(Span.Start, PtrSize); @@ -1852,7 +1687,7 @@ void DwarfDebug::emitDebugARanges() { } } -// Emit visible names into a debug ranges section. +/// Emit address ranges into a debug ranges section. void DwarfDebug::emitDebugRanges() { // Start the dwarf ranges section. Asm->OutStreamer->SwitchSection( @@ -1894,65 +1729,56 @@ void DwarfDebug::emitDebugRanges() { } } -unsigned DwarfDebug::handleMacroNodes(AsmStreamerBase *AS, - DIMacroNodeArray Nodes, - DwarfCompileUnit &U) { - unsigned Size = 0; +void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) { for (auto *MN : Nodes) { if (auto *M = dyn_cast<DIMacro>(MN)) - Size += emitMacro(AS, *M); + emitMacro(*M); else if (auto *F = dyn_cast<DIMacroFile>(MN)) - Size += emitMacroFile(AS, *F, U); + emitMacroFile(*F, U); else llvm_unreachable("Unexpected DI type!"); } - return Size; } -unsigned DwarfDebug::emitMacro(AsmStreamerBase *AS, DIMacro &M) { - int Size = 0; - Size += AS->emitULEB128(M.getMacinfoType()); - Size += AS->emitULEB128(M.getLine()); +void DwarfDebug::emitMacro(DIMacro &M) { + Asm->EmitULEB128(M.getMacinfoType()); + Asm->EmitULEB128(M.getLine()); StringRef Name = M.getName(); StringRef Value = M.getValue(); - Size += AS->emitBytes(Name); + Asm->OutStreamer->EmitBytes(Name); if (!Value.empty()) { // There should be one space between macro name and macro value. - Size += AS->emitInt8(' '); - Size += AS->emitBytes(Value); + Asm->EmitInt8(' '); + Asm->OutStreamer->EmitBytes(Value); } - Size += AS->emitInt8('\0'); - return Size; + Asm->EmitInt8('\0'); } -unsigned DwarfDebug::emitMacroFile(AsmStreamerBase *AS, DIMacroFile &F, - DwarfCompileUnit &U) { - int Size = 0; +void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) { assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file); - Size += AS->emitULEB128(dwarf::DW_MACINFO_start_file); - Size += AS->emitULEB128(F.getLine()); + Asm->EmitULEB128(dwarf::DW_MACINFO_start_file); + Asm->EmitULEB128(F.getLine()); DIFile *File = F.getFile(); unsigned FID = U.getOrCreateSourceID(File->getFilename(), File->getDirectory()); - Size += AS->emitULEB128(FID); - Size += handleMacroNodes(AS, F.getElements(), U); - Size += AS->emitULEB128(dwarf::DW_MACINFO_end_file); - return Size; + Asm->EmitULEB128(FID); + handleMacroNodes(F.getElements(), U); + Asm->EmitULEB128(dwarf::DW_MACINFO_end_file); } -// Emit visible names into a debug macinfo section. +/// Emit macros into a debug macinfo section. void DwarfDebug::emitDebugMacinfo() { - if (MCSection *Macinfo = Asm->getObjFileLowering().getDwarfMacinfoSection()) { - // Start the dwarf macinfo section. - Asm->OutStreamer->SwitchSection(Macinfo); - } - std::unique_ptr<AsmStreamerBase> AS(new EmittingAsmStreamer(Asm)); + // Start the dwarf macinfo section. + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfMacinfoSection()); + for (const auto &P : CUMap) { auto &TheCU = *P.second; auto *SkCU = TheCU.getSkeleton(); DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; auto *CUNode = cast<DICompileUnit>(P.first); - handleMacroNodes(AS.get(), CUNode->getMacros(), U); + Asm->OutStreamer->EmitLabel(U.getMacroLabelBegin()); + handleMacroNodes(CUNode->getMacros(), U); } Asm->OutStreamer->AddComment("End Of Macro List Mark"); Asm->EmitInt8(0); @@ -1961,7 +1787,7 @@ void DwarfDebug::emitDebugMacinfo() { // DWARF5 Experimental Separate Dwarf emitters. void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, - std::unique_ptr<DwarfUnit> NewU) { + std::unique_ptr<DwarfCompileUnit> NewU) { NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name, U.getCUNode()->getSplitDebugFilename()); @@ -2050,21 +1876,19 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed()) return; - const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy]; - if (TU) { - CU.addDIETypeSignature(RefDie, *TU); + auto Ins = TypeSignatures.insert(std::make_pair(CTy, 0)); + if (!Ins.second) { + CU.addDIETypeSignature(RefDie, Ins.first->second); return; } bool TopLevelType = TypeUnitsUnderConstruction.empty(); AddrPool.resetUsedFlag(); - auto OwnedUnit = make_unique<DwarfTypeUnit>( - InfoHolder.getUnits().size() + TypeUnitsUnderConstruction.size(), CU, Asm, - this, &InfoHolder, getDwoLineTable(CU)); + auto OwnedUnit = make_unique<DwarfTypeUnit>(CU, Asm, this, &InfoHolder, + getDwoLineTable(CU)); DwarfTypeUnit &NewTU = *OwnedUnit; DIE &UnitDie = NewTU.getUnitDie(); - TU = &NewTU; TypeUnitsUnderConstruction.push_back( std::make_pair(std::move(OwnedUnit), CTy)); @@ -2073,6 +1897,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, uint64_t Signature = makeTypeSignature(Identifier); NewTU.setTypeSignature(Signature); + Ins.first->second = Signature; if (useSplitDwarf()) NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection()); @@ -2096,7 +1921,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, // This is pessimistic as some of these types might not be dependent on // the type that used an address. for (const auto &TU : TypeUnitsToAdd) - DwarfTypeUnits.erase(TU.second); + TypeSignatures.erase(TU.second); // Construct this type in the CU directly. // This is inefficient because all the dependent types will be rebuilt @@ -2108,10 +1933,12 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, // If the type wasn't dependent on fission addresses, finish adding the type // and all its dependent types. - for (auto &TU : TypeUnitsToAdd) - InfoHolder.addUnit(std::move(TU.first)); + for (auto &TU : TypeUnitsToAdd) { + InfoHolder.computeSizeAndOffsetsForUnit(TU.first.get()); + InfoHolder.emitUnit(TU.first.get(), useSplitDwarf()); + } } - CU.addDIETypeSignature(RefDie, NewTU); + CU.addDIETypeSignature(RefDie, Signature); } // Accelerator table mutators - add each name along with its companion |