diff options
author | Devang Patel <dpatel@apple.com> | 2010-04-27 19:46:33 +0000 |
---|---|---|
committer | Devang Patel <dpatel@apple.com> | 2010-04-27 19:46:33 +0000 |
commit | eac9c07fde0620a3b19cc923c0e80397530b26b0 (patch) | |
tree | b393f17c80f5c08b00ddc852b31421761c292fd6 | |
parent | ed33b13a10258fe1589bf6a76d6d65ec33823076 (diff) | |
download | external_llvm-eac9c07fde0620a3b19cc923c0e80397530b26b0.zip external_llvm-eac9c07fde0620a3b19cc923c0e80397530b26b0.tar.gz external_llvm-eac9c07fde0620a3b19cc923c0e80397530b26b0.tar.bz2 |
Identify when a lexical scope is split in to multiple instruction ranges. Emit such ranges using DW_AT_ranges.
This patch fixes bug (PR6894) introduced by previous version of this patch.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@102454 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 544 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.h | 20 |
2 files changed, 350 insertions, 214 deletions
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 3ce0711..f7b4c09 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -32,6 +32,7 @@ #include "llvm/Analysis/DebugInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ValueHandle.h" @@ -40,6 +41,12 @@ #include "llvm/System/Path.h" using namespace llvm; +static cl::opt<bool> PrintDbgScope("print-dbgscope", cl::Hidden, + cl::desc("Print DbgScope information for each machine instruction")); + +static cl::opt<bool> DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden, + cl::desc("Disable debug info printing")); + namespace { const char *DWARFGroupName = "DWARF Emission"; const char *DbgTimerName = "DWARF Debug Writer"; @@ -185,6 +192,12 @@ public: }; //===----------------------------------------------------------------------===// +/// DbgRange - This is used to track range of instructions with identical +/// debug info scope. +/// +typedef std::pair<const MachineInstr *, const MachineInstr *> DbgRange; + +//===----------------------------------------------------------------------===// /// DbgScope - This class is used to track scope information. /// class DbgScope { @@ -195,17 +208,19 @@ class DbgScope { bool AbstractScope; // Abstract Scope const MachineInstr *LastInsn; // Last instruction of this scope. const MachineInstr *FirstInsn; // First instruction of this scope. + unsigned DFSIn, DFSOut; // Scopes defined in scope. Contents not owned. SmallVector<DbgScope *, 4> Scopes; // Variables declared in scope. Contents owned. SmallVector<DbgVariable *, 8> Variables; - + SmallVector<DbgRange, 4> Ranges; // Private state for dump() mutable unsigned IndentLevel; public: DbgScope(DbgScope *P, DIDescriptor D, MDNode *I = 0) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false), - LastInsn(0), FirstInsn(0), IndentLevel(0) {} + LastInsn(0), FirstInsn(0), + DFSIn(0), DFSOut(0), IndentLevel(0) {} virtual ~DbgScope(); // Accessors. @@ -216,12 +231,55 @@ public: MDNode *getScopeNode() const { return Desc.getNode(); } const SmallVector<DbgScope *, 4> &getScopes() { return Scopes; } const SmallVector<DbgVariable *, 8> &getVariables() { return Variables; } - void setLastInsn(const MachineInstr *MI) { LastInsn = MI; } - const MachineInstr *getLastInsn() { return LastInsn; } - void setFirstInsn(const MachineInstr *MI) { FirstInsn = MI; } + const SmallVector<DbgRange, 4> &getRanges() { return Ranges; } + + /// openInsnRange - This scope covers instruction range starting from MI. + void openInsnRange(const MachineInstr *MI) { + if (!FirstInsn) + FirstInsn = MI; + + if (Parent) + Parent->openInsnRange(MI); + } + + /// extendInsnRange - Extend the current instruction range covered by + /// this scope. + void extendInsnRange(const MachineInstr *MI) { + assert (FirstInsn && "MI Range is not open!"); + LastInsn = MI; + if (Parent) + Parent->extendInsnRange(MI); + } + + /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected + /// until now. This is used when a new scope is encountered while walking + /// machine instructions. + void closeInsnRange(DbgScope *NewScope = NULL) { + assert (LastInsn && "Last insn missing!"); + Ranges.push_back(DbgRange(FirstInsn, LastInsn)); + FirstInsn = NULL; + LastInsn = NULL; + // If Parent dominates NewScope then do not close Parent's instruction + // range. + if (Parent && (!NewScope || !Parent->dominates(NewScope))) + Parent->closeInsnRange(NewScope); + } + void setAbstractScope() { AbstractScope = true; } bool isAbstractScope() const { return AbstractScope; } - const MachineInstr *getFirstInsn() { return FirstInsn; } + + // Depth First Search support to walk and mainpluate DbgScope hierarchy. + unsigned getDFSOut() const { return DFSOut; } + void setDFSOut(unsigned O) { DFSOut = O; } + unsigned getDFSIn() const { return DFSIn; } + void setDFSIn(unsigned I) { DFSIn = I; } + bool dominates(const DbgScope *S) { + if (S == this) + return true; + if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut()) + return true; + return false; + } /// addScope - Add a scope to the scope. /// @@ -231,48 +289,11 @@ public: /// void addVariable(DbgVariable *V) { Variables.push_back(V); } - void fixInstructionMarkers(DenseMap<const MachineInstr *, - unsigned> &MIIndexMap) { - assert(getFirstInsn() && "First instruction is missing!"); - - // Use the end of last child scope as end of this scope. - const SmallVector<DbgScope *, 4> &Scopes = getScopes(); - const MachineInstr *LastInsn = getFirstInsn(); - unsigned LIndex = 0; - if (Scopes.empty()) { - assert(getLastInsn() && "Inner most scope does not have last insn!"); - return; - } - for (SmallVector<DbgScope *, 4>::const_iterator SI = Scopes.begin(), - SE = Scopes.end(); SI != SE; ++SI) { - DbgScope *DS = *SI; - DS->fixInstructionMarkers(MIIndexMap); - const MachineInstr *DSLastInsn = DS->getLastInsn(); - unsigned DSI = MIIndexMap[DSLastInsn]; - if (DSI > LIndex) { - LastInsn = DSLastInsn; - LIndex = DSI; - } - } - - unsigned CurrentLastInsnIndex = 0; - if (const MachineInstr *CL = getLastInsn()) - CurrentLastInsnIndex = MIIndexMap[CL]; - unsigned FIndex = MIIndexMap[getFirstInsn()]; - - // Set LastInsn as the last instruction for this scope only if - // it follows - // 1) this scope's first instruction and - // 2) current last instruction for this scope, if any. - if (LIndex >= CurrentLastInsnIndex && LIndex >= FIndex) - setLastInsn(LastInsn); - } - #ifndef NDEBUG void dump() const; #endif }; - + } // end llvm namespace #ifndef NDEBUG @@ -308,7 +329,8 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) DwarfFrameSectionSym = DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0; DwarfStrSectionSym = TextSectionSym = 0; - + DwarfDebugRangeSectionSym = 0; + FunctionBeginSym = 0; if (TimePassesIsEnabled) { NamedRegionTimer T(DbgTimerName, DWARFGroupName); beginModule(M); @@ -1257,56 +1279,6 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) { return SPDie; } -/// getUpdatedDbgScope - Find DbgScope assicated with the instruction. -/// Update scope hierarchy. Create abstract scope if required. -DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, - MDNode *InlinedAt) { - assert(N && "Invalid Scope encoding!"); - assert(MI && "Missing machine instruction!"); - bool isAConcreteScope = InlinedAt != 0; - - DbgScope *NScope = NULL; - - if (InlinedAt) - NScope = DbgScopeMap.lookup(InlinedAt); - else - NScope = DbgScopeMap.lookup(N); - assert(NScope && "Unable to find working scope!"); - - if (NScope->getFirstInsn()) - return NScope; - - DbgScope *Parent = NULL; - if (isAConcreteScope) { - DILocation IL(InlinedAt); - Parent = getUpdatedDbgScope(IL.getScope().getNode(), MI, - IL.getOrigLocation().getNode()); - assert(Parent && "Unable to find Parent scope!"); - NScope->setParent(Parent); - Parent->addScope(NScope); - } else if (DIDescriptor(N).isLexicalBlock()) { - DILexicalBlock DB(N); - Parent = getUpdatedDbgScope(DB.getContext().getNode(), MI, InlinedAt); - NScope->setParent(Parent); - Parent->addScope(NScope); - } - - NScope->setFirstInsn(MI); - - if (!Parent && !InlinedAt) { - StringRef SPName = DISubprogram(N).getLinkageName(); - if (SPName == Asm->MF->getFunction()->getName()) - CurrentFnDbgScope = NScope; - } - - if (isAConcreteScope) { - ConcreteScopes[InlinedAt] = NScope; - getOrCreateAbstractScope(N); - } - - return NScope; -} - DbgScope *DwarfDebug::getOrCreateAbstractScope(MDNode *N) { assert(N && "Invalid Scope encoding!"); @@ -1403,23 +1375,42 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { /// constructLexicalScope - Construct new DW_TAG_lexical_block /// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { - - MCSymbol *Start = InsnBeforeLabelMap.lookup(Scope->getFirstInsn()); - MCSymbol *End = InsnAfterLabelMap.lookup(Scope->getLastInsn()); - if (Start == 0 || End == 0) return 0; - assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); - assert(End->isDefined() && "Invalid end label for an inlined scope!"); - DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block); if (Scope->isAbstractScope()) return ScopeDIE; - addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - Start ? Start : Asm->GetTempSymbol("func_begin", - Asm->getFunctionNumber())); - addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - End ? End : Asm->GetTempSymbol("func_end",Asm->getFunctionNumber())); + const SmallVector<DbgRange, 4> &Ranges = Scope->getRanges(); + if (Ranges.empty()) + return 0; + + SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(); + if (Ranges.size() > 1) { + // .debug_range section has not been laid out yet. Emit offset in + // .debug_range as a uint, size 4, for now. emitDIE will handle + // DW_AT_ranges appropriately. + addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, + DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize()); + for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(), + RE = Ranges.end(); RI != RE; ++RI) { + DebugRangeSymbols.push_back(LabelsBeforeInsn.lookup(RI->first)); + DebugRangeSymbols.push_back(LabelsAfterInsn.lookup(RI->second)); + } + DebugRangeSymbols.push_back(NULL); + DebugRangeSymbols.push_back(NULL); + return ScopeDIE; + } + + MCSymbol *Start = LabelsBeforeInsn.lookup(RI->first); + MCSymbol *End = LabelsAfterInsn.lookup(RI->second); + + if (Start == 0 || End == 0) return 0; + + assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); + assert(End->isDefined() && "Invalid end label for an inlined scope!"); + + addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start); + addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End); return ScopeDIE; } @@ -1428,14 +1419,28 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { /// a function. Construct DIE to represent this concrete inlined copy /// of the function. DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { - MCSymbol *StartLabel = InsnBeforeLabelMap.lookup(Scope->getFirstInsn()); - MCSymbol *EndLabel = InsnAfterLabelMap.lookup(Scope->getLastInsn()); - if (StartLabel == 0 || EndLabel == 0) return 0; - + + const SmallVector<DbgRange, 4> &Ranges = Scope->getRanges(); + assert (Ranges.empty() == false + && "DbgScope does not have instruction markers!"); + + // FIXME : .debug_inlined section specification does not clearly state how + // to emit inlined scope that is split into multiple instruction ranges. + // For now, use first instruction range and emit low_pc/high_pc pair and + // corresponding .debug_inlined section entry for this pair. + SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(); + MCSymbol *StartLabel = LabelsBeforeInsn.lookup(RI->first); + MCSymbol *EndLabel = LabelsAfterInsn.lookup(RI->second); + + if (StartLabel == 0 || EndLabel == 0) { + assert (0 && "Unexpected Start and End labels for a inlined scope!"); + return 0; + } assert(StartLabel->isDefined() && "Invalid starting label for an inlined scope!"); assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!"); + if (!Scope->getScopeNode()) return NULL; DIScope DS(Scope->getScopeNode()); @@ -1849,6 +1854,9 @@ void DwarfDebug::constructSubprogramDIE(MDNode *N) { /// content. Create global DIEs and emit initial debug info sections. /// This is inovked by the target AsmPrinter. void DwarfDebug::beginModule(Module *M) { + if (DisableDebugInfoPrinting) + return; + DebugInfoFinder DbgFinder; DbgFinder.processModule(*M); @@ -2111,10 +2119,6 @@ void DwarfDebug::beginScope(const MachineInstr *MI) { if (DL.isUnknown()) return; - // Check and update last known location info. - if (DL == PrevInstLoc) - return; - MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext()); // FIXME: Should only verify each scope once! @@ -2126,65 +2130,174 @@ void DwarfDebug::beginScope(const MachineInstr *MI) { DenseMap<const MachineInstr *, DbgVariable *>::iterator DI = DbgValueStartMap.find(MI); if (DI != DbgValueStartMap.end()) { - MCSymbol *Label = recordSourceLine(DL.getLine(), DL.getCol(), Scope); - PrevInstLoc = DL; + MCSymbol *Label = NULL; + if (DL == PrevInstLoc) + Label = PrevLabel; + else { + Label = recordSourceLine(DL.getLine(), DL.getCol(), Scope); + PrevInstLoc = DL; + PrevLabel = Label; + } DI->second->setDbgValueLabel(Label); } return; } // Emit a label to indicate location change. This is used for line - // table even if this instruction does start a new scope. - MCSymbol *Label = recordSourceLine(DL.getLine(), DL.getCol(), Scope); - PrevInstLoc = DL; + // table even if this instruction does not start a new scope. + MCSymbol *Label = NULL; + if (DL == PrevInstLoc) + Label = PrevLabel; + else { + Label = recordSourceLine(DL.getLine(), DL.getCol(), Scope); + PrevInstLoc = DL; + PrevLabel = Label; + } // If this instruction begins a scope then note down corresponding label. if (InsnsBeginScopeSet.count(MI) != 0) - InsnBeforeLabelMap[MI] = Label; + LabelsBeforeInsn[MI] = Label; } /// endScope - Process end of a scope. void DwarfDebug::endScope(const MachineInstr *MI) { - // Ignore DBG_VALUE instruction. - if (MI->isDebugValue()) - return; - - // Check location. - DebugLoc DL = MI->getDebugLoc(); - if (DL.isUnknown()) - return; - if (InsnsEndScopeSet.count(MI) != 0) { // Emit a label if this instruction ends a scope. MCSymbol *Label = MMI->getContext().CreateTempSymbol(); Asm->OutStreamer.EmitLabel(Label); - InsnAfterLabelMap[MI] = Label; + LabelsAfterInsn[MI] = Label; } } -/// createDbgScope - Create DbgScope for the scope. -void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) { +/// getOrCreateDbgScope - Create DbgScope for the scope. +DbgScope *DwarfDebug::getOrCreateDbgScope(MDNode *Scope, MDNode *InlinedAt) { if (!InlinedAt) { DbgScope *WScope = DbgScopeMap.lookup(Scope); if (WScope) - return; + return WScope; WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL); DbgScopeMap.insert(std::make_pair(Scope, WScope)); - if (DIDescriptor(Scope).isLexicalBlock()) - createDbgScope(DILexicalBlock(Scope).getContext().getNode(), NULL); - return; + if (DIDescriptor(Scope).isLexicalBlock()) { + DbgScope *Parent = + getOrCreateDbgScope(DILexicalBlock(Scope).getContext().getNode(), NULL); + WScope->setParent(Parent); + Parent->addScope(WScope); + } + + if (!WScope->getParent()) { + StringRef SPName = DISubprogram(Scope).getLinkageName(); + if (SPName == Asm->MF->getFunction()->getName()) + CurrentFnDbgScope = WScope; + } + + return WScope; } DbgScope *WScope = DbgScopeMap.lookup(InlinedAt); if (WScope) - return; + return WScope; WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt); DbgScopeMap.insert(std::make_pair(InlinedAt, WScope)); DILocation DL(InlinedAt); - createDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode()); + DbgScope *Parent = + getOrCreateDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode()); + WScope->setParent(Parent); + Parent->addScope(WScope); + + ConcreteScopes[InlinedAt] = WScope; + getOrCreateAbstractScope(Scope); + + return WScope; +} + +/// hasValidLocation - Return true if debug location entry attached with +/// machine instruction encodes valid location info. +static bool hasValidLocation(LLVMContext &Ctx, + const MachineInstr *MInsn, + MDNode *&Scope, MDNode *&InlinedAt) { + if (MInsn->isDebugValue()) + return false; + DebugLoc DL = MInsn->getDebugLoc(); + if (DL.isUnknown()) return false; + + MDNode *S = DL.getScope(Ctx); + + // There is no need to create another DIE for compile unit. For all + // other scopes, create one DbgScope now. This will be translated + // into a scope DIE at the end. + if (DIScope(S).isCompileUnit()) return false; + + Scope = S; + InlinedAt = DL.getInlinedAt(Ctx); + return true; +} + +/// calculateDominanceGraph - Calculate dominance graph for DbgScope +/// hierarchy. +static void calculateDominanceGraph(DbgScope *Scope) { + assert (Scope && "Unable to calculate scop edominance graph!"); + SmallVector<DbgScope *, 4> WorkStack; + WorkStack.push_back(Scope); + unsigned Counter = 0; + while (!WorkStack.empty()) { + DbgScope *WS = WorkStack.back(); + const SmallVector<DbgScope *, 4> &Children = WS->getScopes(); + bool visitedChildren = false; + for (SmallVector<DbgScope *, 4>::const_iterator SI = Children.begin(), + SE = Children.end(); SI != SE; ++SI) { + DbgScope *ChildScope = *SI; + if (!ChildScope->getDFSOut()) { + WorkStack.push_back(ChildScope); + visitedChildren = true; + ChildScope->setDFSIn(++Counter); + break; + } + } + if (!visitedChildren) { + WorkStack.pop_back(); + WS->setDFSOut(++Counter); + } + } } +/// printDbgScopeInfo - Print DbgScope info for each machine instruction. +static +void printDbgScopeInfo(LLVMContext &Ctx, const MachineFunction *MF, + DenseMap<const MachineInstr *, DbgScope *> &MI2ScopeMap) +{ +#ifndef NDEBUG + unsigned PrevDFSIn = 0; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MInsn = II; + MDNode *Scope = NULL; + MDNode *InlinedAt = NULL; + + // Check if instruction has valid location information. + if (hasValidLocation(Ctx, MInsn, Scope, InlinedAt)) { + dbgs() << " [ "; + if (InlinedAt) + dbgs() << "*"; + DenseMap<const MachineInstr *, DbgScope *>::iterator DI = + MI2ScopeMap.find(MInsn); + if (DI != MI2ScopeMap.end()) { + DbgScope *S = DI->second; + dbgs() << S->getDFSIn(); + PrevDFSIn = S->getDFSIn(); + } else + dbgs() << PrevDFSIn; + } else + dbgs() << " [ x" << PrevDFSIn; + dbgs() << " ]"; + MInsn->dump(); + } + dbgs() << "\n"; + } +#endif +} /// extractScopeInformation - Scan machine instructions in this function /// and collect DbgScopes. Return true, if at least one scope was found. bool DwarfDebug::extractScopeInformation() { @@ -2193,80 +2306,100 @@ bool DwarfDebug::extractScopeInformation() { if (!DbgScopeMap.empty()) return false; - DenseMap<const MachineInstr *, unsigned> MIIndexMap; - unsigned MIIndex = 0; - LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); - // Scan each instruction and create scopes. First build working set of scopes. + LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); + SmallVector<DbgRange, 4> MIRanges; + DenseMap<const MachineInstr *, DbgScope *> MI2ScopeMap; + MDNode *PrevScope = NULL; + MDNode *PrevInlinedAt = NULL; + const MachineInstr *RangeBeginMI = NULL; + const MachineInstr *PrevMI = NULL; for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { const MachineInstr *MInsn = II; - // FIXME : Remove DBG_VALUE check. - if (MInsn->isDebugValue()) continue; - MIIndexMap[MInsn] = MIIndex++; - - DebugLoc DL = MInsn->getDebugLoc(); - if (DL.isUnknown()) continue; - - MDNode *Scope = DL.getScope(Ctx); - - // There is no need to create another DIE for compile unit. For all - // other scopes, create one DbgScope now. This will be translated - // into a scope DIE at the end. - if (DIScope(Scope).isCompileUnit()) continue; - createDbgScope(Scope, DL.getInlinedAt(Ctx)); - } - } + MDNode *Scope = NULL; + MDNode *InlinedAt = NULL; + // Check if instruction has valid location information. + if (!hasValidLocation(Ctx, MInsn, Scope, InlinedAt)) { + PrevMI = MInsn; + continue; + } + + // If scope has not changed then skip this instruction. + if (Scope == PrevScope && PrevInlinedAt == InlinedAt) { + PrevMI = MInsn; + continue; + } - // Build scope hierarchy using working set of scopes. - for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); - I != E; ++I) { - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - const MachineInstr *MInsn = II; - // FIXME : Remove DBG_VALUE check. - if (MInsn->isDebugValue()) continue; - DebugLoc DL = MInsn->getDebugLoc(); - if (DL.isUnknown()) continue; + if (RangeBeginMI) { + // If we have alread seen a beginning of a instruction range and + // current instruction scope does not match scope of first instruction + // in this range then create a new instruction range. + DbgRange R(RangeBeginMI, PrevMI); + MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevScope, PrevInlinedAt); + MIRanges.push_back(R); + } - MDNode *Scope = DL.getScope(Ctx); - if (Scope == 0) continue; + // This is a beginning of a new instruction range. + RangeBeginMI = MInsn; - // There is no need to create another DIE for compile unit. For all - // other scopes, create one DbgScope now. This will be translated - // into a scope DIE at the end. - if (DIScope(Scope).isCompileUnit()) continue; - DbgScope *DScope = getUpdatedDbgScope(Scope, MInsn, DL.getInlinedAt(Ctx)); - DScope->setLastInsn(MInsn); + // Reset previous markers. + PrevMI = MInsn; + PrevScope = Scope; + PrevInlinedAt = InlinedAt; } } + // Create last instruction range. + if (RangeBeginMI && PrevMI && PrevScope) { + DbgRange R(RangeBeginMI, PrevMI); + MIRanges.push_back(R); + MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevScope, PrevInlinedAt); + } + if (!CurrentFnDbgScope) return false; - CurrentFnDbgScope->fixInstructionMarkers(MIIndexMap); + calculateDominanceGraph(CurrentFnDbgScope); + if (PrintDbgScope) + printDbgScopeInfo(Ctx, Asm->MF, MI2ScopeMap); + + // Find ranges of instructions covered by each DbgScope; + DbgScope *PrevDbgScope = NULL; + for (SmallVector<DbgRange, 4>::const_iterator RI = MIRanges.begin(), + RE = MIRanges.end(); RI != RE; ++RI) { + const DbgRange &R = *RI; + DbgScope *S = MI2ScopeMap.lookup(R.first); + assert (S && "Lost DbgScope for a machine instruction!"); + if (PrevDbgScope && !PrevDbgScope->dominates(S)) + PrevDbgScope->closeInsnRange(S); + S->openInsnRange(R.first); + S->extendInsnRange(R.second); + PrevDbgScope = S; + } + + if (PrevDbgScope) + PrevDbgScope->closeInsnRange(); identifyScopeMarkers(); return !DbgScopeMap.empty(); } -/// identifyScopeMarkers() - Indentify instructions that are marking -/// beginning of or end of a scope. +/// identifyScopeMarkers() - +/// Each DbgScope 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() { - - // Each scope 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. SmallVector<DbgScope *, 4> WorkList; WorkList.push_back(CurrentFnDbgScope); while (!WorkList.empty()) { DbgScope *S = WorkList.pop_back_val(); - + const SmallVector<DbgScope *, 4> &Children = S->getScopes(); if (!Children.empty()) for (SmallVector<DbgScope *, 4>::const_iterator SI = Children.begin(), @@ -2275,11 +2408,17 @@ void DwarfDebug::identifyScopeMarkers() { if (S->isAbstractScope()) continue; - assert(S->getFirstInsn() && "DbgScope does not have first instruction!"); - InsnsBeginScopeSet.insert(S->getFirstInsn()); - - assert(S->getLastInsn() && "DbgScope does not have last instruction!"); - InsnsEndScopeSet.insert(S->getLastInsn()); + + const SmallVector<DbgRange, 4> &Ranges = S->getRanges(); + if (Ranges.empty()) + continue; + for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(), + RE = Ranges.end(); RI != RE; ++RI) { + assert(RI->first && "DbgRange does not have first instruction!"); + assert(RI->second && "DbgRange does not have second instruction!"); + InsnsBeginScopeSet.insert(RI->first); + InsnsEndScopeSet.insert(RI->second); + } } } @@ -2306,9 +2445,10 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { collectVariableInfo(); + FunctionBeginSym = Asm->GetTempSymbol("func_begin", + Asm->getFunctionNumber()); // Assumes in correct section after the entry point. - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("func_begin", - Asm->getFunctionNumber())); + Asm->OutStreamer.EmitLabel(FunctionBeginSym); // Emit label for the implicitly defined dbg.stoppoint at the start of the // function. @@ -2372,8 +2512,8 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { DeleteContainerSeconds(AbstractScopes); AbstractScopesList.clear(); AbstractVariables.clear(); - InsnBeforeLabelMap.clear(); - InsnAfterLabelMap.clear(); + LabelsBeforeInsn.clear(); + LabelsAfterInsn.clear(); Lines.clear(); PrevLabel = NULL; } @@ -3088,14 +3228,14 @@ void DwarfDebug::emitDebugRanges() { // Start the dwarf ranges section. Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfRangesSection()); - for (SmallVector<const MCSymbol *, 8>::const_iterator I = DebugRangeSymbols.begin(), - E = DebugRangeSymbols.end(); I != E; ++I) { - if (*I) - Asm->EmitLabelDifference(*I, TextSectionSym, - Asm->getTargetData().getPointerSize()); + unsigned char Size = Asm->getTargetData().getPointerSize(); + for (SmallVector<const MCSymbol *, 8>::iterator + I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end(); + I != E; ++I) { + if (*I) + Asm->OutStreamer.EmitSymbolValue(const_cast<MCSymbol*>(*I), Size, 0); else - Asm->OutStreamer.EmitIntValue(0, Asm->getTargetData().getPointerSize(), - /*addrspace*/0); + Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0); } } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index bfd6f48..698f710 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -188,13 +188,13 @@ class DwarfDebug { DenseMap<MDNode*, SmallVector<InlineInfoLabels, 4> > InlineInfo; SmallVector<MDNode *, 4> InlinedSPNodes; - /// InsnBeforeLabelMap - Maps instruction with label emitted before + /// LabelsBeforeInsn - Maps instruction with label emitted before /// instruction. - DenseMap<const MachineInstr *, MCSymbol *> InsnBeforeLabelMap; + DenseMap<const MachineInstr *, MCSymbol *> LabelsBeforeInsn; - /// InsnAfterLabelMap - Maps instruction with label emitted after + /// LabelsAfterInsn - Maps instruction with label emitted after /// instruction. - DenseMap<const MachineInstr *, MCSymbol *> InsnAfterLabelMap; + DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn; SmallVector<const MCSymbol *, 8> DebugRangeSymbols; @@ -218,7 +218,8 @@ class DwarfDebug { // section offsets and are created by EmitSectionLabels. MCSymbol *DwarfFrameSectionSym, *DwarfInfoSectionSym, *DwarfAbbrevSectionSym; MCSymbol *DwarfStrSectionSym, *TextSectionSym, *DwarfDebugRangeSectionSym; - + + MCSymbol *FunctionBeginSym; private: /// getSourceDirectoryAndFileIds - Return the directory and file ids that @@ -368,13 +369,8 @@ private: /// createSubprogramDIE - Create new DIE using SP. DIE *createSubprogramDIE(const DISubprogram &SP, bool MakeDecl = false); - /// getUpdatedDbgScope - Find or create DbgScope assicated with - /// the instruction. Initialize scope and update scope hierarchy. - DbgScope *getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, - MDNode *InlinedAt); - - /// createDbgScope - Create DbgScope for the scope. - void createDbgScope(MDNode *Scope, MDNode *InlinedAt); + /// getOrCreateDbgScope - Create DbgScope for the scope. + DbgScope *getOrCreateDbgScope(MDNode *Scope, MDNode *InlinedAt); DbgScope *getOrCreateAbstractScope(MDNode *N); |