mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-25 16:24:23 +00:00
Start using LexicalScopes utility. No intetional functionality change.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137246 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -45,9 +45,6 @@
|
|||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
using namespace llvm;
|
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",
|
static cl::opt<bool> DisableDebugInfoPrinting("disable-debug-info-print",
|
||||||
cl::Hidden,
|
cl::Hidden,
|
||||||
cl::desc("Disable debug info printing"));
|
cl::desc("Disable debug info printing"));
|
||||||
@ -120,143 +117,12 @@ DIType DbgVariable::getType() const {
|
|||||||
return Ty;
|
return Ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
/// 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 {
|
|
||||||
DbgScope *Parent; // Parent to this scope.
|
|
||||||
DIDescriptor Desc; // Debug info descriptor for scope.
|
|
||||||
// Location at which this scope is inlined.
|
|
||||||
AssertingVH<const MDNode> InlinedAtLocation;
|
|
||||||
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, const MDNode *I = 0)
|
|
||||||
: Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false),
|
|
||||||
LastInsn(0), FirstInsn(0),
|
|
||||||
DFSIn(0), DFSOut(0), IndentLevel(0) {
|
|
||||||
if (Parent)
|
|
||||||
Parent->addScope(this);
|
|
||||||
}
|
|
||||||
virtual ~DbgScope();
|
|
||||||
|
|
||||||
// Accessors.
|
|
||||||
DbgScope *getParent() const { return Parent; }
|
|
||||||
DIDescriptor getDesc() const { return Desc; }
|
|
||||||
const MDNode *getInlinedAt() const { return InlinedAtLocation; }
|
|
||||||
const MDNode *getScopeNode() const { return Desc; }
|
|
||||||
const SmallVector<DbgScope *, 4> &getScopes() { return Scopes; }
|
|
||||||
const SmallVector<DbgVariable *, 8> &getDbgVariables() { return Variables; }
|
|
||||||
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; }
|
|
||||||
|
|
||||||
// Depth First Search support to walk and manipulate 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.
|
|
||||||
///
|
|
||||||
void addScope(DbgScope *S) { Scopes.push_back(S); }
|
|
||||||
|
|
||||||
/// addVariable - Add a variable to the scope.
|
|
||||||
///
|
|
||||||
void addVariable(DbgVariable *V) { Variables.push_back(V); }
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
void dump() const;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end llvm namespace
|
} // end llvm namespace
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
void DbgScope::dump() const {
|
|
||||||
raw_ostream &err = dbgs();
|
|
||||||
err.indent(IndentLevel);
|
|
||||||
err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n";
|
|
||||||
const MDNode *N = Desc;
|
|
||||||
N->dump();
|
|
||||||
if (AbstractScope)
|
|
||||||
err << "Abstract Scope\n";
|
|
||||||
|
|
||||||
IndentLevel += 2;
|
|
||||||
if (!Scopes.empty())
|
|
||||||
err << "Children ...\n";
|
|
||||||
for (unsigned i = 0, e = Scopes.size(); i != e; ++i)
|
|
||||||
if (Scopes[i] != this)
|
|
||||||
Scopes[i]->dump();
|
|
||||||
|
|
||||||
IndentLevel -= 2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DbgScope::~DbgScope() {
|
|
||||||
for (unsigned j = 0, M = Variables.size(); j < M; ++j)
|
|
||||||
delete Variables[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
|
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
|
||||||
: Asm(A), MMI(Asm->MMI), FirstCU(0),
|
: Asm(A), MMI(Asm->MMI), FirstCU(0),
|
||||||
AbbreviationsSet(InitAbbreviationsSetSize),
|
AbbreviationsSet(InitAbbreviationsSetSize),
|
||||||
CurrentFnDbgScope(0), PrevLabel(NULL) {
|
PrevLabel(NULL) {
|
||||||
NextStringPoolNumber = 0;
|
NextStringPoolNumber = 0;
|
||||||
|
|
||||||
DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
|
DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
|
||||||
@ -408,29 +274,6 @@ DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) {
|
|||||||
return SPDie;
|
return SPDie;
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgScope *DwarfDebug::getOrCreateAbstractScope(const MDNode *N) {
|
|
||||||
assert(N && "Invalid Scope encoding!");
|
|
||||||
|
|
||||||
DbgScope *AScope = AbstractScopes.lookup(N);
|
|
||||||
if (AScope)
|
|
||||||
return AScope;
|
|
||||||
|
|
||||||
DbgScope *Parent = NULL;
|
|
||||||
|
|
||||||
DIDescriptor Scope(N);
|
|
||||||
if (Scope.isLexicalBlock()) {
|
|
||||||
DILexicalBlock DB(N);
|
|
||||||
DIDescriptor ParentDesc = DB.getContext();
|
|
||||||
Parent = getOrCreateAbstractScope(ParentDesc);
|
|
||||||
}
|
|
||||||
AScope = new DbgScope(Parent, DIDescriptor(N), NULL);
|
|
||||||
AScope->setAbstractScope();
|
|
||||||
AbstractScopes[N] = AScope;
|
|
||||||
if (DIDescriptor(N).isSubprogram())
|
|
||||||
AbstractScopesList.push_back(AScope);
|
|
||||||
return AScope;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// isSubprogramContext - Return true if Context is either a subprogram
|
/// isSubprogramContext - Return true if Context is either a subprogram
|
||||||
/// or another context nested inside a subprogram.
|
/// or another context nested inside a subprogram.
|
||||||
static bool isSubprogramContext(const MDNode *Context) {
|
static bool isSubprogramContext(const MDNode *Context) {
|
||||||
@ -512,25 +355,25 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) {
|
|||||||
|
|
||||||
/// constructLexicalScope - Construct new DW_TAG_lexical_block
|
/// constructLexicalScope - Construct new DW_TAG_lexical_block
|
||||||
/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels.
|
/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels.
|
||||||
DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) {
|
DIE *DwarfDebug::constructLexicalScopeDIE(LexicalScope *Scope) {
|
||||||
|
|
||||||
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
|
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
|
||||||
if (Scope->isAbstractScope())
|
if (Scope->isAbstractScope())
|
||||||
return ScopeDIE;
|
return ScopeDIE;
|
||||||
|
|
||||||
const SmallVector<DbgRange, 4> &Ranges = Scope->getRanges();
|
const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
|
||||||
if (Ranges.empty())
|
if (Ranges.empty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
CompileUnit *TheCU = getCompileUnit(Scope->getScopeNode());
|
CompileUnit *TheCU = getCompileUnit(Scope->getScopeNode());
|
||||||
SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin();
|
SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
|
||||||
if (Ranges.size() > 1) {
|
if (Ranges.size() > 1) {
|
||||||
// .debug_range section has not been laid out yet. Emit offset in
|
// .debug_range section has not been laid out yet. Emit offset in
|
||||||
// .debug_range as a uint, size 4, for now. emitDIE will handle
|
// .debug_range as a uint, size 4, for now. emitDIE will handle
|
||||||
// DW_AT_ranges appropriately.
|
// DW_AT_ranges appropriately.
|
||||||
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
|
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
|
||||||
DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize());
|
DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize());
|
||||||
for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(),
|
for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
|
||||||
RE = Ranges.end(); RI != RE; ++RI) {
|
RE = Ranges.end(); RI != RE; ++RI) {
|
||||||
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
|
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
|
||||||
DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
|
DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
|
||||||
@ -557,11 +400,11 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) {
|
|||||||
/// constructInlinedScopeDIE - This scope represents inlined body of
|
/// constructInlinedScopeDIE - This scope represents inlined body of
|
||||||
/// a function. Construct DIE to represent this concrete inlined copy
|
/// a function. Construct DIE to represent this concrete inlined copy
|
||||||
/// of the function.
|
/// of the function.
|
||||||
DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
|
DIE *DwarfDebug::constructInlinedScopeDIE(LexicalScope *Scope) {
|
||||||
|
|
||||||
const SmallVector<DbgRange, 4> &Ranges = Scope->getRanges();
|
const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
|
||||||
assert (Ranges.empty() == false
|
assert (Ranges.empty() == false
|
||||||
&& "DbgScope does not have instruction markers!");
|
&& "LexicalScope does not have instruction markers!");
|
||||||
|
|
||||||
if (!Scope->getScopeNode())
|
if (!Scope->getScopeNode())
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -574,7 +417,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin();
|
SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
|
||||||
const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
|
const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
|
||||||
const MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
|
const MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
|
||||||
|
|
||||||
@ -597,7 +440,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
|
|||||||
// DW_AT_ranges appropriately.
|
// DW_AT_ranges appropriately.
|
||||||
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
|
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
|
||||||
DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize());
|
DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize());
|
||||||
for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(),
|
for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
|
||||||
RE = Ranges.end(); RI != RE; ++RI) {
|
RE = Ranges.end(); RI != RE; ++RI) {
|
||||||
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
|
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
|
||||||
DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
|
DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
|
||||||
@ -650,7 +493,7 @@ static bool isUnsignedDIType(DIType Ty) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
|
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
|
||||||
DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) {
|
DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, LexicalScope *Scope) {
|
||||||
StringRef Name = DV->getName();
|
StringRef Name = DV->getName();
|
||||||
if (Name.empty())
|
if (Name.empty())
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -784,25 +627,25 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// constructScopeDIE - Construct a DIE for this scope.
|
/// constructScopeDIE - Construct a DIE for this scope.
|
||||||
DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) {
|
DIE *DwarfDebug::constructScopeDIE(LexicalScope *Scope) {
|
||||||
if (!Scope || !Scope->getScopeNode())
|
if (!Scope || !Scope->getScopeNode())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
SmallVector <DIE *, 8> Children;
|
SmallVector <DIE *, 8> Children;
|
||||||
|
|
||||||
// Collect arguments for current function.
|
// Collect arguments for current function.
|
||||||
if (Scope == CurrentFnDbgScope)
|
if (LScopes.isCurrentFunctionScope(Scope))
|
||||||
for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
|
for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
|
||||||
if (DbgVariable *ArgDV = CurrentFnArguments[i])
|
if (DbgVariable *ArgDV = CurrentFnArguments[i])
|
||||||
if (DIE *Arg = constructVariableDIE(ArgDV, Scope))
|
if (DIE *Arg = constructVariableDIE(ArgDV, Scope))
|
||||||
Children.push_back(Arg);
|
Children.push_back(Arg);
|
||||||
|
|
||||||
// Collect lexical scope childrens first.
|
// Collect lexical scope childrens first.
|
||||||
const SmallVector<DbgVariable *, 8> &Variables = Scope->getDbgVariables();
|
const SmallVector<DbgVariable *, 8> &Variables = ScopeVariables.lookup(Scope);
|
||||||
for (unsigned i = 0, N = Variables.size(); i < N; ++i)
|
for (unsigned i = 0, N = Variables.size(); i < N; ++i)
|
||||||
if (DIE *Variable = constructVariableDIE(Variables[i], Scope))
|
if (DIE *Variable = constructVariableDIE(Variables[i], Scope))
|
||||||
Children.push_back(Variable);
|
Children.push_back(Variable);
|
||||||
const SmallVector<DbgScope *, 4> &Scopes = Scope->getScopes();
|
const SmallVector<LexicalScope *, 4> &Scopes = Scope->getChildren();
|
||||||
for (unsigned j = 0, M = Scopes.size(); j < M; ++j)
|
for (unsigned j = 0, M = Scopes.size(); j < M; ++j)
|
||||||
if (DIE *Nested = constructScopeDIE(Scopes[j]))
|
if (DIE *Nested = constructScopeDIE(Scopes[j]))
|
||||||
Children.push_back(Nested);
|
Children.push_back(Nested);
|
||||||
@ -1176,7 +1019,7 @@ void DwarfDebug::beginModule(Module *M) {
|
|||||||
void DwarfDebug::endModule() {
|
void DwarfDebug::endModule() {
|
||||||
if (!FirstCU) return;
|
if (!FirstCU) return;
|
||||||
const Module *M = MMI->getModule();
|
const Module *M = MMI->getModule();
|
||||||
DenseMap<const MDNode *, DbgScope *> DeadFnScopeMap;
|
DenseMap<const MDNode *, LexicalScope *> DeadFnScopeMap;
|
||||||
if (NamedMDNode *AllSPs = M->getNamedMetadata("llvm.dbg.sp")) {
|
if (NamedMDNode *AllSPs = M->getNamedMetadata("llvm.dbg.sp")) {
|
||||||
for (unsigned SI = 0, SE = AllSPs->getNumOperands(); SI != SE; ++SI) {
|
for (unsigned SI = 0, SE = AllSPs->getNumOperands(); SI != SE; ++SI) {
|
||||||
if (ProcessedSPNodes.count(AllSPs->getOperand(SI)) != 0) continue;
|
if (ProcessedSPNodes.count(AllSPs->getOperand(SI)) != 0) continue;
|
||||||
@ -1192,21 +1035,20 @@ void DwarfDebug::endModule() {
|
|||||||
if (!NMD) continue;
|
if (!NMD) continue;
|
||||||
unsigned E = NMD->getNumOperands();
|
unsigned E = NMD->getNumOperands();
|
||||||
if (!E) continue;
|
if (!E) continue;
|
||||||
DbgScope *Scope = new DbgScope(NULL, DIDescriptor(SP), NULL);
|
LexicalScope *Scope = new LexicalScope(NULL, DIDescriptor(SP), NULL, false);
|
||||||
DeadFnScopeMap[SP] = Scope;
|
DeadFnScopeMap[SP] = Scope;
|
||||||
|
SmallVector<DbgVariable *, 8> Variables;
|
||||||
for (unsigned I = 0; I != E; ++I) {
|
for (unsigned I = 0; I != E; ++I) {
|
||||||
DIVariable DV(NMD->getOperand(I));
|
DIVariable DV(NMD->getOperand(I));
|
||||||
if (!DV.Verify()) continue;
|
if (!DV.Verify()) continue;
|
||||||
Scope->addVariable(new DbgVariable(DV));
|
Variables.push_back(new DbgVariable(DV));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct subprogram DIE and add variables DIEs.
|
// Construct subprogram DIE and add variables DIEs.
|
||||||
constructSubprogramDIE(SP);
|
constructSubprogramDIE(SP);
|
||||||
DIE *ScopeDIE = getCompileUnit(SP)->getDIE(SP);
|
DIE *ScopeDIE = getCompileUnit(SP)->getDIE(SP);
|
||||||
const SmallVector<DbgVariable *, 8> &Variables = Scope->getDbgVariables();
|
|
||||||
for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
|
for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
|
||||||
DIE *VariableDIE = constructVariableDIE(Variables[i], Scope);
|
if (DIE *VariableDIE = constructVariableDIE(Variables[i], Scope))
|
||||||
if (VariableDIE)
|
|
||||||
ScopeDIE->addChild(VariableDIE);
|
ScopeDIE->addChild(VariableDIE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1284,20 +1126,23 @@ void DwarfDebug::endModule() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// findAbstractVariable - Find abstract variable, if any, associated with Var.
|
/// findAbstractVariable - Find abstract variable, if any, associated with Var.
|
||||||
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var,
|
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV,
|
||||||
DebugLoc ScopeLoc) {
|
DebugLoc ScopeLoc) {
|
||||||
|
LLVMContext &Ctx = DV->getContext();
|
||||||
|
|
||||||
|
// More then one inlined variable corresponds to one abstract variable.
|
||||||
|
DIVariable Var = cleanseInlinedVariable(DV, Ctx);
|
||||||
|
|
||||||
DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
|
DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
|
||||||
if (AbsDbgVariable)
|
if (AbsDbgVariable)
|
||||||
return AbsDbgVariable;
|
return AbsDbgVariable;
|
||||||
|
|
||||||
LLVMContext &Ctx = Var->getContext();
|
LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx));
|
||||||
DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope(Ctx));
|
|
||||||
if (!Scope)
|
if (!Scope)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
AbsDbgVariable = new DbgVariable(Var);
|
AbsDbgVariable = new DbgVariable(Var);
|
||||||
Scope->addVariable(AbsDbgVariable);
|
addScopeVariable(Scope, AbsDbgVariable);
|
||||||
AbstractVariables[Var] = AbsDbgVariable;
|
AbstractVariables[Var] = AbsDbgVariable;
|
||||||
return AbsDbgVariable;
|
return AbsDbgVariable;
|
||||||
}
|
}
|
||||||
@ -1305,8 +1150,8 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var,
|
|||||||
/// addCurrentFnArgument - If Var is a current function argument then add
|
/// addCurrentFnArgument - If Var is a current function argument then add
|
||||||
/// it to CurrentFnArguments list.
|
/// it to CurrentFnArguments list.
|
||||||
bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
|
bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
|
||||||
DbgVariable *Var, DbgScope *Scope) {
|
DbgVariable *Var, LexicalScope *Scope) {
|
||||||
if (Scope != CurrentFnDbgScope)
|
if (!LScopes.isCurrentFunctionScope(Scope))
|
||||||
return false;
|
return false;
|
||||||
DIVariable DV = Var->getVariable();
|
DIVariable DV = Var->getVariable();
|
||||||
if (DV.getTag() != dwarf::DW_TAG_arg_variable)
|
if (DV.getTag() != dwarf::DW_TAG_arg_variable)
|
||||||
@ -1340,7 +1185,7 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF,
|
|||||||
DIVariable DV(Var);
|
DIVariable DV(Var);
|
||||||
const std::pair<unsigned, DebugLoc> &VP = VI->second;
|
const std::pair<unsigned, DebugLoc> &VP = VI->second;
|
||||||
|
|
||||||
DbgScope *Scope = findDbgScope(VP.second);
|
LexicalScope *Scope = LScopes.findLexicalScope(VP.second);
|
||||||
|
|
||||||
// If variable scope is not found then skip this variable.
|
// If variable scope is not found then skip this variable.
|
||||||
if (Scope == 0)
|
if (Scope == 0)
|
||||||
@ -1350,7 +1195,7 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF,
|
|||||||
DbgVariable *RegVar = new DbgVariable(DV);
|
DbgVariable *RegVar = new DbgVariable(DV);
|
||||||
recordVariableFrameIndex(RegVar, VP.first);
|
recordVariableFrameIndex(RegVar, VP.first);
|
||||||
if (!addCurrentFnArgument(MF, RegVar, Scope))
|
if (!addCurrentFnArgument(MF, RegVar, Scope))
|
||||||
Scope->addVariable(RegVar);
|
addScopeVariable(Scope, RegVar);
|
||||||
if (AbsDbgVariable) {
|
if (AbsDbgVariable) {
|
||||||
recordVariableFrameIndex(AbsDbgVariable, VP.first);
|
recordVariableFrameIndex(AbsDbgVariable, VP.first);
|
||||||
VarToAbstractVarMap[RegVar] = AbsDbgVariable;
|
VarToAbstractVarMap[RegVar] = AbsDbgVariable;
|
||||||
@ -1395,7 +1240,7 @@ static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
|
|||||||
return DotDebugLocEntry();
|
return DotDebugLocEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// collectVariableInfo - Populate DbgScope entries with variables' info.
|
/// collectVariableInfo - Find variables for each lexical scope.
|
||||||
void
|
void
|
||||||
DwarfDebug::collectVariableInfo(const MachineFunction *MF,
|
DwarfDebug::collectVariableInfo(const MachineFunction *MF,
|
||||||
SmallPtrSet<const MDNode *, 16> &Processed) {
|
SmallPtrSet<const MDNode *, 16> &Processed) {
|
||||||
@ -1418,18 +1263,18 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
|
|||||||
const MachineInstr *MInsn = History.front();
|
const MachineInstr *MInsn = History.front();
|
||||||
|
|
||||||
DIVariable DV(Var);
|
DIVariable DV(Var);
|
||||||
DbgScope *Scope = NULL;
|
LexicalScope *Scope = NULL;
|
||||||
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
|
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
|
||||||
DISubprogram(DV.getContext()).describes(MF->getFunction()))
|
DISubprogram(DV.getContext()).describes(MF->getFunction()))
|
||||||
Scope = CurrentFnDbgScope;
|
Scope = LScopes.getCurrentFunctionScope();
|
||||||
else {
|
else {
|
||||||
if (DV.getVersion() <= LLVMDebugVersion9)
|
if (DV.getVersion() <= LLVMDebugVersion9)
|
||||||
Scope = findDbgScope(MInsn->getDebugLoc());
|
Scope = LScopes.findLexicalScope(MInsn->getDebugLoc());
|
||||||
else {
|
else {
|
||||||
if (MDNode *IA = DV.getInlinedAt())
|
if (MDNode *IA = DV.getInlinedAt())
|
||||||
Scope = InlinedDbgScopeMap.lookup(DebugLoc::getFromDILocation(IA));
|
Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA));
|
||||||
else
|
else
|
||||||
Scope = DbgScopeMap.lookup(cast<MDNode>(DV->getOperand(1)));
|
Scope = LScopes.findLexicalScope(cast<MDNode>(DV->getOperand(1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If variable scope is not found then skip this variable.
|
// If variable scope is not found then skip this variable.
|
||||||
@ -1440,7 +1285,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
|
|||||||
assert(MInsn->isDebugValue() && "History must begin with debug value");
|
assert(MInsn->isDebugValue() && "History must begin with debug value");
|
||||||
DbgVariable *RegVar = new DbgVariable(DV);
|
DbgVariable *RegVar = new DbgVariable(DV);
|
||||||
if (!addCurrentFnArgument(MF, RegVar, Scope))
|
if (!addCurrentFnArgument(MF, RegVar, Scope))
|
||||||
Scope->addVariable(RegVar);
|
addScopeVariable(Scope, RegVar);
|
||||||
if (DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc())) {
|
if (DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc())) {
|
||||||
DbgVariableToDbgInstMap[AbsVar] = MInsn;
|
DbgVariableToDbgInstMap[AbsVar] = MInsn;
|
||||||
VarToAbstractVarMap[RegVar] = AbsVar;
|
VarToAbstractVarMap[RegVar] = AbsVar;
|
||||||
@ -1501,9 +1346,8 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
|
|||||||
DIVariable DV(cast<MDNode>(NMD->getOperand(i)));
|
DIVariable DV(cast<MDNode>(NMD->getOperand(i)));
|
||||||
if (!DV || !Processed.insert(DV))
|
if (!DV || !Processed.insert(DV))
|
||||||
continue;
|
continue;
|
||||||
DbgScope *Scope = DbgScopeMap.lookup(DV.getContext());
|
if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext()))
|
||||||
if (Scope)
|
addScopeVariable(Scope, new DbgVariable(DV));
|
||||||
Scope->addVariable(new DbgVariable(DV));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1585,253 +1429,33 @@ void DwarfDebug::endInstruction(const MachineInstr *MI) {
|
|||||||
I->second = PrevLabel;
|
I->second = PrevLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getOrCreateRegularScope - Create regular DbgScope.
|
|
||||||
DbgScope *DwarfDebug::getOrCreateRegularScope(MDNode *Scope) {
|
|
||||||
DbgScope *WScope = DbgScopeMap.lookup(Scope);
|
|
||||||
if (WScope)
|
|
||||||
return WScope;
|
|
||||||
|
|
||||||
DbgScope *Parent = NULL;
|
|
||||||
if (DIDescriptor(Scope).isLexicalBlock())
|
|
||||||
Parent = getOrCreateDbgScope(DebugLoc::getFromDILexicalBlock(Scope));
|
|
||||||
WScope = new DbgScope(Parent, DIDescriptor(Scope), NULL);
|
|
||||||
DbgScopeMap.insert(std::make_pair(Scope, WScope));
|
|
||||||
if (!Parent && DIDescriptor(Scope).isSubprogram()
|
|
||||||
&& DISubprogram(Scope).describes(Asm->MF->getFunction()))
|
|
||||||
CurrentFnDbgScope = WScope;
|
|
||||||
|
|
||||||
return WScope;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// getOrCreateInlinedScope - Create inlined scope.
|
|
||||||
DbgScope *DwarfDebug::getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt){
|
|
||||||
DbgScope *InlinedScope = DbgScopeMap.lookup(InlinedAt);
|
|
||||||
if (InlinedScope)
|
|
||||||
return InlinedScope;
|
|
||||||
|
|
||||||
DebugLoc InlinedLoc = DebugLoc::getFromDILocation(InlinedAt);
|
|
||||||
InlinedScope = new DbgScope(getOrCreateDbgScope(InlinedLoc),
|
|
||||||
DIDescriptor(Scope), InlinedAt);
|
|
||||||
InlinedDbgScopeMap[InlinedLoc] = InlinedScope;
|
|
||||||
DbgScopeMap[InlinedAt] = InlinedScope;
|
|
||||||
return InlinedScope;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// getOrCreateDbgScope - Create DbgScope for the scope.
|
|
||||||
DbgScope *DwarfDebug::getOrCreateDbgScope(DebugLoc DL) {
|
|
||||||
LLVMContext &Ctx = Asm->MF->getFunction()->getContext();
|
|
||||||
MDNode *Scope = NULL;
|
|
||||||
MDNode *InlinedAt = NULL;
|
|
||||||
DL.getScopeAndInlinedAt(Scope, InlinedAt, Ctx);
|
|
||||||
if (!InlinedAt)
|
|
||||||
return getOrCreateRegularScope(Scope);
|
|
||||||
|
|
||||||
// Create an abstract scope for inlined function.
|
|
||||||
getOrCreateAbstractScope(Scope);
|
|
||||||
// Create an inlined scope for inlined function.
|
|
||||||
return getOrCreateInlinedScope(Scope, InlinedAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (PrintDbgScope)
|
|
||||||
dbgs() << "calculate dbgscope dom: In " << Counter << "\n";
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!visitedChildren) {
|
|
||||||
WorkStack.pop_back();
|
|
||||||
WS->setDFSOut(++Counter);
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (PrintDbgScope)
|
|
||||||
dbgs() << "calculate dbgscope dom: In " << WS->getDFSIn()
|
|
||||||
<< " Out " << Counter << "\n";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// printDbgScopeInfo - Print DbgScope info for each machine instruction.
|
|
||||||
static
|
|
||||||
void printDbgScopeInfo(const MachineFunction *MF,
|
|
||||||
DenseMap<const MachineInstr *, DbgScope *> &MI2ScopeMap)
|
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
LLVMContext &Ctx = MF->getFunction()->getContext();
|
|
||||||
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.
|
|
||||||
DebugLoc MIDL = MInsn->getDebugLoc();
|
|
||||||
if (!MIDL.isUnknown()) {
|
|
||||||
MIDL.getScopeAndInlinedAt(Scope, InlinedAt, Ctx);
|
|
||||||
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() {
|
|
||||||
// If scope information was extracted using .dbg intrinsics then there is not
|
|
||||||
// any need to extract these information by scanning each instruction.
|
|
||||||
if (!DbgScopeMap.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Scan each instruction and create scopes. First build working set of scopes.
|
|
||||||
SmallVector<DbgRange, 4> MIRanges;
|
|
||||||
DenseMap<const MachineInstr *, DbgScope *> MI2ScopeMap;
|
|
||||||
for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end();
|
|
||||||
I != E; ++I) {
|
|
||||||
const MachineInstr *RangeBeginMI = NULL;
|
|
||||||
const MachineInstr *PrevMI = NULL;
|
|
||||||
DebugLoc PrevDL;
|
|
||||||
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
|
|
||||||
II != IE; ++II) {
|
|
||||||
const MachineInstr *MInsn = II;
|
|
||||||
|
|
||||||
// Check if instruction has valid location information.
|
|
||||||
const DebugLoc MIDL = MInsn->getDebugLoc();
|
|
||||||
if (MIDL.isUnknown()) {
|
|
||||||
PrevMI = MInsn;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If scope has not changed then skip this instruction.
|
|
||||||
if (MIDL == PrevDL) {
|
|
||||||
PrevMI = MInsn;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore DBG_VALUE. It does not contribute to any instruction in output.
|
|
||||||
if (MInsn->isDebugValue())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (RangeBeginMI) {
|
|
||||||
// If we have already seen a beginning of an instruction range and
|
|
||||||
// current instruction scope does not match scope of first instruction
|
|
||||||
// in this range then create a new instruction range.
|
|
||||||
DEBUG(dbgs() << "Creating new instruction range :\n");
|
|
||||||
DEBUG(dbgs() << "Begin Range at " << *RangeBeginMI);
|
|
||||||
DEBUG(dbgs() << "End Range at " << *PrevMI);
|
|
||||||
DEBUG(dbgs() << "Next Range starting at " << *MInsn);
|
|
||||||
DEBUG(dbgs() << "------------------------\n");
|
|
||||||
DbgRange R(RangeBeginMI, PrevMI);
|
|
||||||
MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevDL);
|
|
||||||
MIRanges.push_back(R);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a beginning of a new instruction range.
|
|
||||||
RangeBeginMI = MInsn;
|
|
||||||
|
|
||||||
// Reset previous markers.
|
|
||||||
PrevMI = MInsn;
|
|
||||||
PrevDL = MIDL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create last instruction range.
|
|
||||||
if (RangeBeginMI && PrevMI && !PrevDL.isUnknown()) {
|
|
||||||
DbgRange R(RangeBeginMI, PrevMI);
|
|
||||||
MIRanges.push_back(R);
|
|
||||||
MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevDL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CurrentFnDbgScope)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
calculateDominanceGraph(CurrentFnDbgScope);
|
|
||||||
if (PrintDbgScope)
|
|
||||||
printDbgScopeInfo(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() -
|
/// identifyScopeMarkers() -
|
||||||
/// Each DbgScope has first instruction and last instruction to mark beginning
|
/// Each LexicalScope has first instruction and last instruction to mark beginning
|
||||||
/// and end of a scope respectively. Create an inverse map that list scopes
|
/// 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)
|
/// starts (and ends) with an instruction. One instruction may start (or end)
|
||||||
/// multiple scopes. Ignore scopes that are not reachable.
|
/// multiple scopes. Ignore scopes that are not reachable.
|
||||||
void DwarfDebug::identifyScopeMarkers() {
|
void DwarfDebug::identifyScopeMarkers() {
|
||||||
SmallVector<DbgScope *, 4> WorkList;
|
SmallVector<LexicalScope *, 4> WorkList;
|
||||||
WorkList.push_back(CurrentFnDbgScope);
|
WorkList.push_back(LScopes.getCurrentFunctionScope());
|
||||||
while (!WorkList.empty()) {
|
while (!WorkList.empty()) {
|
||||||
DbgScope *S = WorkList.pop_back_val();
|
LexicalScope *S = WorkList.pop_back_val();
|
||||||
|
|
||||||
const SmallVector<DbgScope *, 4> &Children = S->getScopes();
|
const SmallVector<LexicalScope *, 4> &Children = S->getChildren();
|
||||||
if (!Children.empty())
|
if (!Children.empty())
|
||||||
for (SmallVector<DbgScope *, 4>::const_iterator SI = Children.begin(),
|
for (SmallVector<LexicalScope *, 4>::const_iterator SI = Children.begin(),
|
||||||
SE = Children.end(); SI != SE; ++SI)
|
SE = Children.end(); SI != SE; ++SI)
|
||||||
WorkList.push_back(*SI);
|
WorkList.push_back(*SI);
|
||||||
|
|
||||||
if (S->isAbstractScope())
|
if (S->isAbstractScope())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const SmallVector<DbgRange, 4> &Ranges = S->getRanges();
|
const SmallVector<InsnRange, 4> &Ranges = S->getRanges();
|
||||||
if (Ranges.empty())
|
if (Ranges.empty())
|
||||||
continue;
|
continue;
|
||||||
for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(),
|
for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
|
||||||
RE = Ranges.end(); RI != RE; ++RI) {
|
RE = Ranges.end(); RI != RE; ++RI) {
|
||||||
assert(RI->first && "DbgRange does not have first instruction!");
|
assert(RI->first && "InsnRange does not have first instruction!");
|
||||||
assert(RI->second && "DbgRange does not have second instruction!");
|
assert(RI->second && "InsnRange does not have second instruction!");
|
||||||
requestLabelBeforeInsn(RI->first);
|
requestLabelBeforeInsn(RI->first);
|
||||||
requestLabelAfterInsn(RI->second);
|
requestLabelAfterInsn(RI->second);
|
||||||
}
|
}
|
||||||
@ -1859,7 +1483,9 @@ static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) {
|
|||||||
/// emitted immediately after the function entry point.
|
/// emitted immediately after the function entry point.
|
||||||
void DwarfDebug::beginFunction(const MachineFunction *MF) {
|
void DwarfDebug::beginFunction(const MachineFunction *MF) {
|
||||||
if (!MMI->hasDebugInfo()) return;
|
if (!MMI->hasDebugInfo()) return;
|
||||||
if (!extractScopeInformation()) return;
|
LScopes.initialize(*MF);
|
||||||
|
if (LScopes.empty()) return;
|
||||||
|
identifyScopeMarkers();
|
||||||
|
|
||||||
FunctionBeginSym = Asm->GetTempSymbol("func_begin",
|
FunctionBeginSym = Asm->GetTempSymbol("func_begin",
|
||||||
Asm->getFunctionNumber());
|
Asm->getFunctionNumber());
|
||||||
@ -2025,12 +1651,16 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
|
||||||
|
// SmallVector<DbgVariable *, 8> &Vars = ScopeVariables.lookup(LS);
|
||||||
|
ScopeVariables[LS].push_back(Var);
|
||||||
|
// Vars.push_back(Var);
|
||||||
|
}
|
||||||
|
|
||||||
/// endFunction - Gather and emit post-function debug information.
|
/// endFunction - Gather and emit post-function debug information.
|
||||||
///
|
///
|
||||||
void DwarfDebug::endFunction(const MachineFunction *MF) {
|
void DwarfDebug::endFunction(const MachineFunction *MF) {
|
||||||
if (!MMI->hasDebugInfo() || DbgScopeMap.empty()) return;
|
if (!MMI->hasDebugInfo() || LScopes.empty()) return;
|
||||||
|
|
||||||
if (CurrentFnDbgScope) {
|
|
||||||
|
|
||||||
// Define end label for subprogram.
|
// Define end label for subprogram.
|
||||||
FunctionEndSym = Asm->GetTempSymbol("func_end",
|
FunctionEndSym = Asm->GetTempSymbol("func_end",
|
||||||
@ -2042,8 +1672,9 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
|
|||||||
collectVariableInfo(MF, ProcessedVars);
|
collectVariableInfo(MF, ProcessedVars);
|
||||||
|
|
||||||
// Construct abstract scopes.
|
// Construct abstract scopes.
|
||||||
for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
|
SmallVector<LexicalScope *, 4> &AList = LScopes.getAbstractScopesList();
|
||||||
AE = AbstractScopesList.end(); AI != AE; ++AI) {
|
for (SmallVector<LexicalScope *, 4>::iterator AI = AList.begin(),
|
||||||
|
AE = AList.end(); AI != AE; ++AI) {
|
||||||
DISubprogram SP((*AI)->getScopeNode());
|
DISubprogram SP((*AI)->getScopeNode());
|
||||||
if (SP.Verify()) {
|
if (SP.Verify()) {
|
||||||
// Collect info for variables that were optimized out.
|
// Collect info for variables that were optimized out.
|
||||||
@ -2056,9 +1687,8 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
|
|||||||
DIVariable DV(cast<MDNode>(NMD->getOperand(i)));
|
DIVariable DV(cast<MDNode>(NMD->getOperand(i)));
|
||||||
if (!DV || !ProcessedVars.insert(DV))
|
if (!DV || !ProcessedVars.insert(DV))
|
||||||
continue;
|
continue;
|
||||||
DbgScope *Scope = AbstractScopes.lookup(DV.getContext());
|
if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext()))
|
||||||
if (Scope)
|
addScopeVariable(Scope, new DbgVariable(DV));
|
||||||
Scope->addVariable(new DbgVariable(DV));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2066,30 +1696,28 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
|
|||||||
constructScopeDIE(*AI);
|
constructScopeDIE(*AI);
|
||||||
}
|
}
|
||||||
|
|
||||||
DIE *CurFnDIE = constructScopeDIE(CurrentFnDbgScope);
|
DIE *CurFnDIE = constructScopeDIE(LScopes.getCurrentFunctionScope());
|
||||||
|
|
||||||
if (!DisableFramePointerElim(*MF))
|
if (!DisableFramePointerElim(*MF)) {
|
||||||
getCompileUnit(CurrentFnDbgScope->getScopeNode())->addUInt(CurFnDIE,
|
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
|
||||||
|
getCompileUnit(FnScope->getScopeNode())->addUInt(CurFnDIE,
|
||||||
dwarf::DW_AT_APPLE_omit_frame_ptr,
|
dwarf::DW_AT_APPLE_omit_frame_ptr,
|
||||||
dwarf::DW_FORM_flag, 1);
|
dwarf::DW_FORM_flag, 1);
|
||||||
|
}
|
||||||
|
|
||||||
DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(),
|
DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(),
|
||||||
MMI->getFrameMoves()));
|
MMI->getFrameMoves()));
|
||||||
}
|
|
||||||
|
|
||||||
// Clear debug info
|
// Clear debug info
|
||||||
CurrentFnDbgScope = NULL;
|
for (DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8> >::iterator
|
||||||
|
I = ScopeVariables.begin(), E = ScopeVariables.end(); I != E; ++I)
|
||||||
|
DeleteContainerPointers(I->second);
|
||||||
|
ScopeVariables.clear();
|
||||||
DeleteContainerPointers(CurrentFnArguments);
|
DeleteContainerPointers(CurrentFnArguments);
|
||||||
DbgVariableToFrameIndexMap.clear();
|
DbgVariableToFrameIndexMap.clear();
|
||||||
VarToAbstractVarMap.clear();
|
VarToAbstractVarMap.clear();
|
||||||
DbgVariableToDbgInstMap.clear();
|
DbgVariableToDbgInstMap.clear();
|
||||||
InlinedDbgScopeMap.clear();
|
|
||||||
DeleteContainerSeconds(DbgScopeMap);
|
|
||||||
UserVariables.clear();
|
UserVariables.clear();
|
||||||
DbgValues.clear();
|
DbgValues.clear();
|
||||||
DeleteContainerSeconds(AbstractScopes);
|
|
||||||
AbstractScopesList.clear();
|
|
||||||
AbstractVariables.clear();
|
AbstractVariables.clear();
|
||||||
LabelsBeforeInsn.clear();
|
LabelsBeforeInsn.clear();
|
||||||
LabelsAfterInsn.clear();
|
LabelsAfterInsn.clear();
|
||||||
@ -2114,21 +1742,6 @@ bool DwarfDebug::findVariableFrameIndex(const DbgVariable *V, int *FI) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// findDbgScope - Find DbgScope for the debug loc.
|
|
||||||
DbgScope *DwarfDebug::findDbgScope(DebugLoc DL) {
|
|
||||||
if (DL.isUnknown())
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
DbgScope *Scope = NULL;
|
|
||||||
LLVMContext &Ctx = Asm->MF->getFunction()->getContext();
|
|
||||||
if (MDNode *IA = DL.getInlinedAt(Ctx))
|
|
||||||
Scope = InlinedDbgScopeMap.lookup(DebugLoc::getFromDILocation(IA));
|
|
||||||
else
|
|
||||||
Scope = DbgScopeMap.lookup(DL.getScope(Ctx));
|
|
||||||
return Scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// recordSourceLine - Register a source line with debug info. Returns the
|
/// recordSourceLine - Register a source line with debug info. Returns the
|
||||||
/// unique label that was emitted and which provides correspondence to
|
/// unique label that was emitted and which provides correspondence to
|
||||||
/// the source line list.
|
/// the source line list.
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#define CODEGEN_ASMPRINTER_DWARFDEBUG_H__
|
#define CODEGEN_ASMPRINTER_DWARFDEBUG_H__
|
||||||
|
|
||||||
#include "llvm/CodeGen/AsmPrinter.h"
|
#include "llvm/CodeGen/AsmPrinter.h"
|
||||||
|
#include "llvm/CodeGen/LexicalScopes.h"
|
||||||
#include "llvm/MC/MachineLocation.h"
|
#include "llvm/MC/MachineLocation.h"
|
||||||
#include "llvm/Analysis/DebugInfo.h"
|
#include "llvm/Analysis/DebugInfo.h"
|
||||||
#include "DIE.h"
|
#include "DIE.h"
|
||||||
@ -30,7 +31,6 @@ namespace llvm {
|
|||||||
|
|
||||||
class CompileUnit;
|
class CompileUnit;
|
||||||
class DbgConcreteScope;
|
class DbgConcreteScope;
|
||||||
class DbgScope;
|
|
||||||
class DbgVariable;
|
class DbgVariable;
|
||||||
class MachineFrameInfo;
|
class MachineFrameInfo;
|
||||||
class MachineModuleInfo;
|
class MachineModuleInfo;
|
||||||
@ -192,33 +192,18 @@ class DwarfDebug {
|
|||||||
///
|
///
|
||||||
UniqueVector<const MCSection*> SectionMap;
|
UniqueVector<const MCSection*> SectionMap;
|
||||||
|
|
||||||
/// CurrentFnDbgScope - Top level scope for the current function.
|
|
||||||
///
|
|
||||||
DbgScope *CurrentFnDbgScope;
|
|
||||||
|
|
||||||
/// CurrentFnArguments - List of Arguments (DbgValues) for current function.
|
/// CurrentFnArguments - List of Arguments (DbgValues) for current function.
|
||||||
SmallVector<DbgVariable *, 8> CurrentFnArguments;
|
SmallVector<DbgVariable *, 8> CurrentFnArguments;
|
||||||
|
|
||||||
/// DbgScopeMap - Tracks the scopes in the current function. Owns the
|
LexicalScopes LScopes;
|
||||||
/// contained DbgScope*s.
|
|
||||||
DenseMap<const MDNode *, DbgScope *> DbgScopeMap;
|
|
||||||
|
|
||||||
/// InlinedDbgScopeMap - Tracks inlined function scopes in current function.
|
|
||||||
DenseMap<DebugLoc, DbgScope *> InlinedDbgScopeMap;
|
|
||||||
|
|
||||||
/// AbstractScopes - Tracks the abstract scopes a module. These scopes are
|
|
||||||
/// not included DbgScopeMap. AbstractScopes owns its DbgScope*s.
|
|
||||||
DenseMap<const MDNode *, DbgScope *> AbstractScopes;
|
|
||||||
|
|
||||||
/// AbstractSPDies - Collection of abstract subprogram DIEs.
|
/// AbstractSPDies - Collection of abstract subprogram DIEs.
|
||||||
DenseMap<const MDNode *, DIE *> AbstractSPDies;
|
DenseMap<const MDNode *, DIE *> AbstractSPDies;
|
||||||
|
|
||||||
/// AbstractScopesList - Tracks abstract scopes constructed while processing
|
/// ScopeVariables - Collection of dbg variables of a scope.
|
||||||
/// a function. This list is cleared during endFunction().
|
DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8> > ScopeVariables;
|
||||||
SmallVector<DbgScope *, 4>AbstractScopesList;
|
|
||||||
|
|
||||||
/// AbstractVariables - Collection on abstract variables. Owned by the
|
/// AbstractVariables - Collection on abstract variables.
|
||||||
/// DbgScopes in AbstractScopes.
|
|
||||||
DenseMap<const MDNode *, DbgVariable *> AbstractVariables;
|
DenseMap<const MDNode *, DbgVariable *> AbstractVariables;
|
||||||
|
|
||||||
/// DbgVariableToFrameIndexMap - Tracks frame index used to find
|
/// DbgVariableToFrameIndexMap - Tracks frame index used to find
|
||||||
@ -316,11 +301,7 @@ private:
|
|||||||
///
|
///
|
||||||
void assignAbbrevNumber(DIEAbbrev &Abbrev);
|
void assignAbbrevNumber(DIEAbbrev &Abbrev);
|
||||||
|
|
||||||
/// getOrCreateDbgScope - Create DbgScope for the scope.
|
void addScopeVariable(LexicalScope *LS, DbgVariable *Var);
|
||||||
DbgScope *getOrCreateDbgScope(DebugLoc DL);
|
|
||||||
DbgScope *getOrCreateRegularScope(MDNode *Scope);
|
|
||||||
DbgScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt);
|
|
||||||
DbgScope *getOrCreateAbstractScope(const MDNode *N);
|
|
||||||
|
|
||||||
/// findAbstractVariable - Find abstract variable associated with Var.
|
/// findAbstractVariable - Find abstract variable associated with Var.
|
||||||
DbgVariable *findAbstractVariable(DIVariable &Var, DebugLoc Loc);
|
DbgVariable *findAbstractVariable(DIVariable &Var, DebugLoc Loc);
|
||||||
@ -333,18 +314,18 @@ private:
|
|||||||
|
|
||||||
/// constructLexicalScope - Construct new DW_TAG_lexical_block
|
/// constructLexicalScope - Construct new DW_TAG_lexical_block
|
||||||
/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels.
|
/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels.
|
||||||
DIE *constructLexicalScopeDIE(DbgScope *Scope);
|
DIE *constructLexicalScopeDIE(LexicalScope *Scope);
|
||||||
|
|
||||||
/// constructInlinedScopeDIE - This scope represents inlined body of
|
/// constructInlinedScopeDIE - This scope represents inlined body of
|
||||||
/// a function. Construct DIE to represent this concrete inlined copy
|
/// a function. Construct DIE to represent this concrete inlined copy
|
||||||
/// of the function.
|
/// of the function.
|
||||||
DIE *constructInlinedScopeDIE(DbgScope *Scope);
|
DIE *constructInlinedScopeDIE(LexicalScope *Scope);
|
||||||
|
|
||||||
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
|
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
|
||||||
DIE *constructVariableDIE(DbgVariable *DV, DbgScope *S);
|
DIE *constructVariableDIE(DbgVariable *DV, LexicalScope *S);
|
||||||
|
|
||||||
/// constructScopeDIE - Construct a DIE for this scope.
|
/// constructScopeDIE - Construct a DIE for this scope.
|
||||||
DIE *constructScopeDIE(DbgScope *Scope);
|
DIE *constructScopeDIE(LexicalScope *Scope);
|
||||||
|
|
||||||
/// EmitSectionLabels - Emit initial Dwarf sections with a label at
|
/// EmitSectionLabels - Emit initial Dwarf sections with a label at
|
||||||
/// the start of each one.
|
/// the start of each one.
|
||||||
@ -449,23 +430,16 @@ private:
|
|||||||
/// is found. Update FI to hold value of the index.
|
/// is found. Update FI to hold value of the index.
|
||||||
bool findVariableFrameIndex(const DbgVariable *V, int *FI);
|
bool findVariableFrameIndex(const DbgVariable *V, int *FI);
|
||||||
|
|
||||||
/// findDbgScope - Find DbgScope for the debug loc.
|
|
||||||
DbgScope *findDbgScope(DebugLoc DL);
|
|
||||||
|
|
||||||
/// identifyScopeMarkers() - Indentify instructions that are marking
|
/// identifyScopeMarkers() - Indentify instructions that are marking
|
||||||
/// beginning of or end of a scope.
|
/// beginning of or end of a scope.
|
||||||
void identifyScopeMarkers();
|
void identifyScopeMarkers();
|
||||||
|
|
||||||
/// extractScopeInformation - Scan machine instructions in this function
|
|
||||||
/// and collect DbgScopes. Return true, if atleast one scope was found.
|
|
||||||
bool extractScopeInformation();
|
|
||||||
|
|
||||||
/// addCurrentFnArgument - If Var is an current function argument that add
|
/// addCurrentFnArgument - If Var is an current function argument that add
|
||||||
/// it in CurrentFnArguments list.
|
/// it in CurrentFnArguments list.
|
||||||
bool addCurrentFnArgument(const MachineFunction *MF,
|
bool addCurrentFnArgument(const MachineFunction *MF,
|
||||||
DbgVariable *Var, DbgScope *Scope);
|
DbgVariable *Var, LexicalScope *Scope);
|
||||||
|
|
||||||
/// collectVariableInfo - Populate DbgScope entries with variables' info.
|
/// collectVariableInfo - Populate LexicalScope entries with variables' info.
|
||||||
void collectVariableInfo(const MachineFunction *,
|
void collectVariableInfo(const MachineFunction *,
|
||||||
SmallPtrSet<const MDNode *, 16> &ProcessedVars);
|
SmallPtrSet<const MDNode *, 16> &ProcessedVars);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user