Implement support to debug inlined functions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86748 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp
index 390ebf9..7d7ed6f 100644
--- a/lib/Analysis/DebugInfo.cpp
+++ b/lib/Analysis/DebugInfo.cpp
@@ -1487,22 +1487,4 @@
return DebugLoc::get(Id);
}
-
- /// isInlinedFnStart - Return true if FSI is starting an inlined function.
- bool isInlinedFnStart(DbgFuncStartInst &FSI, const Function *CurrentFn) {
- DISubprogram Subprogram(cast<MDNode>(FSI.getSubprogram()));
- if (Subprogram.describes(CurrentFn))
- return false;
-
- return true;
- }
-
- /// isInlinedFnEnd - Return true if REI is ending an inlined function.
- bool isInlinedFnEnd(DbgRegionEndInst &REI, const Function *CurrentFn) {
- DISubprogram Subprogram(cast<MDNode>(REI.getContext()));
- if (Subprogram.isNull() || Subprogram.describes(CurrentFn))
- return false;
-
- return true;
- }
}
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index cedf775..dbe60de 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1357,32 +1357,31 @@
/// instruction's DebugLoc.
void AsmPrinter::processDebugLoc(const MachineInstr *MI,
bool BeforePrintingInsn) {
- if (!MAI || !DW)
+ if (!MAI || !DW || !MAI->doesSupportDebugInformation()
+ || !DW->ShouldEmitDwarfDebug())
return;
DebugLoc DL = MI->getDebugLoc();
- if (MAI->doesSupportDebugInformation() && DW->ShouldEmitDwarfDebug()) {
- if (!DL.isUnknown()) {
- DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
- if (BeforePrintingInsn) {
- if (CurDLT.Scope != 0 && PrevDLT != CurDLT) {
- unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
- CurDLT.Scope);
- printLabel(L);
- O << '\n';
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
- DW->SetDbgScopeBeginLabels(MI, L);
-#endif
- } else {
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
- DW->SetDbgScopeEndLabels(MI, 0);
-#endif
- }
- }
+ if (DL.isUnknown())
+ return;
+ DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
+ if (CurDLT.Scope == 0)
+ return;
+
+ if (BeforePrintingInsn) {
+ if (CurDLT != PrevDLT) {
+ unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
+ CurDLT.Scope);
+ printLabel(L);
+ DW->BeginScope(MI, L);
PrevDLT = CurDLT;
}
+ } else {
+ // After printing instruction
+ DW->EndScope(MI);
}
}
+
/// printInlineAsm - This method formats and prints the specified machine
/// instruction that is an inline asm.
void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index de8cfc6..82b48ac 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -127,15 +127,19 @@
class DbgVariable {
DIVariable Var; // Variable Descriptor.
unsigned FrameIndex; // Variable frame index.
- bool InlinedFnVar; // Variable for an inlined function.
+ DbgVariable *AbstractVar; // Abstract variable for this variable.
+ DIE *TheDIE;
public:
- DbgVariable(DIVariable V, unsigned I, bool IFV)
- : Var(V), FrameIndex(I), InlinedFnVar(IFV) {}
+ DbgVariable(DIVariable V, unsigned I)
+ : Var(V), FrameIndex(I), AbstractVar(0), TheDIE(0) {}
// Accessors.
- DIVariable getVariable() const { return Var; }
- unsigned getFrameIndex() const { return FrameIndex; }
- bool isInlinedFnVar() const { return InlinedFnVar; }
+ DIVariable getVariable() const { return Var; }
+ unsigned getFrameIndex() const { return FrameIndex; }
+ void setAbstractVariable(DbgVariable *V) { AbstractVar = V; }
+ DbgVariable *getAbstractVariable() const { return AbstractVar; }
+ void setDIE(DIE *D) { TheDIE = D; }
+ DIE *getDIE() const { return TheDIE; }
};
//===----------------------------------------------------------------------===//
@@ -144,44 +148,46 @@
class DbgConcreteScope;
class DbgScope {
DbgScope *Parent; // Parent to this scope.
- DIDescriptor Desc; // Debug info descriptor for scope.
- // FIXME use WeakVH for Desc.
- WeakVH InlinedAt; // If this scope represents inlined
- // function body then this is the location
- // where this body is inlined.
+ DIDescriptor Desc; // Debug info descriptor for scope.
+ WeakVH InlinedAtLocation; // Location at which scope is inlined.
+ bool AbstractScope; // Abstract Scope
unsigned StartLabelID; // Label ID of the beginning of scope.
unsigned EndLabelID; // Label ID of the end of scope.
const MachineInstr *LastInsn; // Last instruction of this scope.
const MachineInstr *FirstInsn; // First instruction of this scope.
SmallVector<DbgScope *, 4> Scopes; // Scopes defined in scope.
SmallVector<DbgVariable *, 8> Variables;// Variables declared in scope.
- SmallVector<DbgConcreteScope *, 8> ConcreteInsts;// Concrete insts of funcs.
// Private state for dump()
mutable unsigned IndentLevel;
public:
DbgScope(DbgScope *P, DIDescriptor D, MDNode *I = 0)
- : Parent(P), Desc(D), InlinedAt(I), StartLabelID(0), EndLabelID(0),
+ : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false),
+ StartLabelID(0), EndLabelID(0),
LastInsn(0), FirstInsn(0), IndentLevel(0) {}
virtual ~DbgScope();
// Accessors.
DbgScope *getParent() const { return Parent; }
+ void setParent(DbgScope *P) { Parent = P; }
DIDescriptor getDesc() const { return Desc; }
- MDNode *getInlinedAt() const {
- return dyn_cast_or_null<MDNode>(InlinedAt);
+ MDNode *getInlinedAt() const {
+ return dyn_cast_or_null<MDNode>(InlinedAtLocation);
}
+ MDNode *getScopeNode() const { return Desc.getNode(); }
unsigned getStartLabelID() const { return StartLabelID; }
unsigned getEndLabelID() const { return EndLabelID; }
SmallVector<DbgScope *, 4> &getScopes() { return Scopes; }
SmallVector<DbgVariable *, 8> &getVariables() { return Variables; }
- SmallVector<DbgConcreteScope*,8> &getConcreteInsts() { return ConcreteInsts; }
void setStartLabelID(unsigned S) { StartLabelID = S; }
void setEndLabelID(unsigned E) { EndLabelID = E; }
void setLastInsn(const MachineInstr *MI) { LastInsn = MI; }
const MachineInstr *getLastInsn() { return LastInsn; }
void setFirstInsn(const MachineInstr *MI) { FirstInsn = MI; }
+ void setAbstractScope() { AbstractScope = true; }
+ bool isAbstractScope() const { return AbstractScope; }
const MachineInstr *getFirstInsn() { return FirstInsn; }
+
/// AddScope - Add a scope to the scope.
///
void AddScope(DbgScope *S) { Scopes.push_back(S); }
@@ -190,10 +196,6 @@
///
void AddVariable(DbgVariable *V) { Variables.push_back(V); }
- /// AddConcreteInst - Add a concrete instance to the scope.
- ///
- void AddConcreteInst(DbgConcreteScope *C) { ConcreteInsts.push_back(C); }
-
void FixInstructionMarkers() {
assert (getFirstInsn() && "First instruction is missing!");
if (getLastInsn())
@@ -218,11 +220,15 @@
void DbgScope::dump() const {
raw_ostream &err = errs();
err.indent(IndentLevel);
- Desc.dump();
+ MDNode *N = Desc.getNode();
+ N->dump();
err << " [" << StartLabelID << ", " << EndLabelID << "]\n";
+ 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();
@@ -251,8 +257,6 @@
delete Scopes[i];
for (unsigned j = 0, M = Variables.size(); j < M; ++j)
delete Variables[j];
- for (unsigned k = 0, O = ConcreteInsts.size(); k < O; ++k)
- delete ConcreteInsts[k];
}
} // end llvm namespace
@@ -262,7 +266,7 @@
AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(),
ValuesSet(InitValuesSetSize), Values(), StringPool(),
SectionSourceLines(), didInitial(false), shouldEmit(false),
- FunctionDbgScope(0), DebugTimer(0) {
+ CurrentFnDbgScope(0), DebugTimer(0) {
if (TimePassesIsEnabled)
DebugTimer = new Timer("Dwarf Debug Writer",
getDwarfTimerGroup());
@@ -271,11 +275,6 @@
for (unsigned j = 0, M = Values.size(); j < M; ++j)
delete Values[j];
- for (DenseMap<const MDNode *, DbgScope *>::iterator
- I = AbstractInstanceRootMap.begin(),
- E = AbstractInstanceRootMap.end(); I != E;++I)
- delete I->second;
-
delete DebugTimer;
}
@@ -1237,9 +1236,6 @@
}
}
- if (!SP.isLocalToUnit() && !IsInlined)
- AddUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
-
// DW_TAG_inlined_subroutine may refer to this DIE.
DIE *&Slot = DW_Unit->getDieMapSlotFor(SP.getNode());
Slot = SPDie;
@@ -1287,81 +1283,109 @@
AddSourceLine(VariableDie, &VD);
// Add variable type.
- // FIXME: isBlockByrefVariable should be reformulated in terms of complex addresses instead.
+ // FIXME: isBlockByrefVariable should be reformulated in terms of complex
+ // addresses instead.
if (VD.isBlockByrefVariable())
AddType(Unit, VariableDie, GetBlockByrefType(VD.getType(), Name));
else
AddType(Unit, VariableDie, VD.getType());
// Add variable address.
- if (!DV->isInlinedFnVar()) {
- // Variables for abstract instances of inlined functions don't get a
- // location.
- MachineLocation Location;
- Location.set(RI->getFrameRegister(*MF),
- RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
-
-
- if (VD.hasComplexAddress())
- AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
- else if (VD.isBlockByrefVariable())
- AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
- else
- AddAddress(VariableDie, dwarf::DW_AT_location, Location);
- }
+ // Variables for abstract instances of inlined functions don't get a
+ // location.
+ MachineLocation Location;
+ Location.set(RI->getFrameRegister(*MF),
+ RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
+
+
+ if (VD.hasComplexAddress())
+ AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
+ else if (VD.isBlockByrefVariable())
+ AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
+ else
+ AddAddress(VariableDie, dwarf::DW_AT_location, Location);
return VariableDie;
}
-/// getOrCreateScope - Returns the scope associated with the given descriptor.
-///
-DbgScope *DwarfDebug::getDbgScope(MDNode *N, const MachineInstr *MI,
- MDNode *InlinedAt) {
- ValueMap<MDNode *, DbgScope *>::iterator VI = DbgScopeMap.find(N);
- if (VI != DbgScopeMap.end())
- return VI->second;
+/// getUpdatedDbgScope - Find or create DbgScope assicated with the instruction.
+/// Initialize scope and update scope hierarchy.
+DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI,
+ MDNode *InlinedAt) {
+ assert (N && "Invalid Scope encoding!");
+ assert (MI && "Missing machine instruction!");
+ bool GetConcreteScope = (MI && InlinedAt);
+
+ 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 (InlinedAt) {
+ if (GetConcreteScope) {
DILocation IL(InlinedAt);
- assert (!IL.isNull() && "Invalid InlindAt location!");
- ValueMap<MDNode *, DbgScope *>::iterator DSI =
- DbgScopeMap.find(IL.getScope().getNode());
- assert (DSI != DbgScopeMap.end() && "Unable to find InlineAt scope!");
- Parent = DSI->second;
- } else {
- DIDescriptor Scope(N);
- if (Scope.isCompileUnit()) {
- return NULL;
- } else if (Scope.isSubprogram()) {
- DISubprogram SP(N);
- DIDescriptor ParentDesc = SP.getContext();
- if (!ParentDesc.isNull() && !ParentDesc.isCompileUnit())
- Parent = getDbgScope(ParentDesc.getNode(), MI, InlinedAt);
- } else if (Scope.isLexicalBlock()) {
- DILexicalBlock DB(N);
- DIDescriptor ParentDesc = DB.getContext();
- if (!ParentDesc.isNull())
- Parent = getDbgScope(ParentDesc.getNode(), MI, InlinedAt);
- } else
- assert (0 && "Unexpected scope info");
+ 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);
+ if (!DB.getContext().isNull()) {
+ Parent = getUpdatedDbgScope(DB.getContext().getNode(), MI, InlinedAt);
+ NScope->setParent(Parent);
+ Parent->AddScope(NScope);
+ }
}
- DbgScope *NScope = new DbgScope(Parent, DIDescriptor(N), InlinedAt);
NScope->setFirstInsn(MI);
- if (Parent)
- Parent->AddScope(NScope);
- else
- // First function is top level function.
- if (!FunctionDbgScope)
- FunctionDbgScope = NScope;
+ if (!Parent && !InlinedAt) {
+ assert (!CurrentFnDbgScope && "Unexpected function scope!");
+ CurrentFnDbgScope = NScope;
+ }
- DbgScopeMap.insert(std::make_pair(N, NScope));
+ if (GetConcreteScope) {
+ ConcreteScopes[InlinedAt] = NScope;
+ getOrCreateAbstractScope(N);
+ }
+
return NScope;
}
+DbgScope *DwarfDebug::getOrCreateAbstractScope(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();
+ if (!ParentDesc.isNull())
+ Parent = getOrCreateAbstractScope(ParentDesc.getNode());
+ }
+
+ AScope = new DbgScope(Parent, DIDescriptor(N), NULL);
+
+ if (Parent)
+ Parent->AddScope(AScope);
+ AScope->setAbstractScope();
+ AbstractScopes[N] = AScope;
+ if (DIDescriptor(N).isSubprogram())
+ AbstractScopesList.push_back(AScope);
+ return AScope;
+}
/// getOrCreateScope - Returns the scope associated with the given descriptor.
/// FIXME - Remove this method.
@@ -1372,12 +1396,6 @@
DbgScope *Parent = NULL;
DILexicalBlock Block(N);
- // Don't create a new scope if we already created one for an inlined function.
- DenseMap<const MDNode *, DbgScope *>::iterator
- II = AbstractInstanceRootMap.find(N);
- if (II != AbstractInstanceRootMap.end())
- return LexicalScopeStack.back();
-
if (!Block.isNull()) {
DIDescriptor ParentDesc = Block.getContext();
Parent =
@@ -1390,13 +1408,241 @@
Parent->AddScope(Slot);
else
// First function is top level function.
- FunctionDbgScope = Slot;
+ CurrentFnDbgScope = Slot;
return Slot;
}
+static DISubprogram getDISubprogram(MDNode *N) {
+
+ DIDescriptor D(N);
+ if (D.isNull())
+ return DISubprogram();
+
+ if (D.isCompileUnit())
+ return DISubprogram();
+
+ if (D.isSubprogram())
+ return DISubprogram(N);
+
+ if (D.isLexicalBlock())
+ return getDISubprogram(DILexicalBlock(N).getContext().getNode());
+
+ llvm_unreachable("Unexpected Descriptor!");
+}
+
+DIE *DwarfDebug::UpdateSubprogramScopeDIE(MDNode *SPNode) {
+
+ DIE *SPDie = ModuleCU->getDieMapSlotFor(SPNode);
+ assert (SPDie && "Unable to find subprogram DIE!");
+ AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ DWLabel("func_begin", SubprogramCount));
+ AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
+ DWLabel("func_end", SubprogramCount));
+ MachineLocation Location(RI->getFrameRegister(*MF));
+ AddAddress(SPDie, dwarf::DW_AT_frame_base, Location);
+
+ if (!DISubprogram(SPNode).isLocalToUnit())
+ AddUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
+
+ // If there are global variables at this scope then add their dies.
+ for (SmallVector<WeakVH, 4>::iterator SGI = ScopedGVs.begin(),
+ SGE = ScopedGVs.end(); SGI != SGE; ++SGI) {
+ MDNode *N = dyn_cast_or_null<MDNode>(*SGI);
+ if (!N) continue;
+ DIGlobalVariable GV(N);
+ if (GV.getContext().getNode() == SPNode) {
+ DIE *ScopedGVDie = CreateGlobalVariableDIE(ModuleCU, GV);
+ SPDie->AddChild(ScopedGVDie);
+ }
+ }
+ return SPDie;
+}
+
+DIE *DwarfDebug::ConstructLexicalScopeDIE(DbgScope *Scope) {
+ unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
+ unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
+
+ // Ignore empty scopes.
+ if (StartID == EndID && StartID != 0)
+ return NULL;
+
+ 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,
+ StartID ?
+ DWLabel("label", StartID)
+ : DWLabel("func_begin", SubprogramCount));
+ AddLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
+ EndID ?
+ DWLabel("label", EndID)
+ : DWLabel("func_end", SubprogramCount));
+
+
+
+ return ScopeDIE;
+}
+
+DIE *DwarfDebug::ConstructInlinedScopeDIE(DbgScope *Scope) {
+ unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
+ unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
+ assert (StartID && "Invalid starting label for an inlined scope!");
+ assert (EndID && "Invalid end label for an inlined scope!");
+ // Ignore empty scopes.
+ if (StartID == EndID && StartID != 0)
+ return NULL;
+
+ DIScope DS(Scope->getScopeNode());
+ if (DS.isNull())
+ return NULL;
+ DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
+
+ DISubprogram InlinedSP = getDISubprogram(DS.getNode());
+ DIE *&OriginDIE = ModuleCU->getDieMapSlotFor(InlinedSP.getNode());
+ assert (OriginDIE && "Unable to find Origin DIE!");
+ AddDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
+ dwarf::DW_FORM_ref4, OriginDIE);
+
+ AddLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ DWLabel("label", StartID));
+ AddLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
+ DWLabel("label", EndID));
+
+ InlinedSubprogramDIEs.insert(OriginDIE);
+
+ // Track the start label for this inlined function.
+ ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
+ I = InlineInfo.find(InlinedSP.getNode());
+
+ if (I == InlineInfo.end()) {
+ InlineInfo[InlinedSP.getNode()].push_back(std::make_pair(StartID, ScopeDIE));
+ InlinedSPNodes.push_back(InlinedSP.getNode());
+ } else
+ I->second.push_back(std::make_pair(StartID, ScopeDIE));
+
+ StringPool.insert(InlinedSP.getName());
+ StringPool.insert(InlinedSP.getLinkageName());
+ DILocation DL(Scope->getInlinedAt());
+ AddUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, ModuleCU->getID());
+ AddUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber());
+
+ return ScopeDIE;
+}
+
+DIE *DwarfDebug::ConstructVariableDIE(DbgVariable *DV,
+ DbgScope *Scope, CompileUnit *Unit) {
+ // Get the descriptor.
+ const DIVariable &VD = DV->getVariable();
+
+ // Translate tag to proper Dwarf tag. The result variable is dropped for
+ // now.
+ unsigned Tag;
+ switch (VD.getTag()) {
+ case dwarf::DW_TAG_return_variable:
+ return NULL;
+ case dwarf::DW_TAG_arg_variable:
+ Tag = dwarf::DW_TAG_formal_parameter;
+ break;
+ case dwarf::DW_TAG_auto_variable: // fall thru
+ default:
+ Tag = dwarf::DW_TAG_variable;
+ break;
+ }
+
+ // Define variable debug information entry.
+ DIE *VariableDie = new DIE(Tag);
+
+
+ DIE *AbsDIE = NULL;
+ if (DbgVariable *AV = DV->getAbstractVariable())
+ AbsDIE = AV->getDIE();
+
+ if (AbsDIE) {
+ DIScope DS(Scope->getScopeNode());
+ DISubprogram InlinedSP = getDISubprogram(DS.getNode());
+ DIE *&OriginSPDIE = ModuleCU->getDieMapSlotFor(InlinedSP.getNode());
+ assert (OriginSPDIE && "Unable to find Origin DIE for the SP!");
+ DIE *AbsDIE = DV->getAbstractVariable()->getDIE();
+ assert (AbsDIE && "Unable to find Origin DIE for the Variable!");
+ AddDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin,
+ dwarf::DW_FORM_ref4, AbsDIE);
+ }
+ else {
+ const char *Name = VD.getName();
+ AddString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
+ AddSourceLine(VariableDie, &VD);
+
+ // Add variable type.
+ // FIXME: isBlockByrefVariable should be reformulated in terms of complex
+ // addresses instead.
+ if (VD.isBlockByrefVariable())
+ AddType(Unit, VariableDie, GetBlockByrefType(VD.getType(), Name));
+ else
+ AddType(Unit, VariableDie, VD.getType());
+ }
+
+ // Add variable address.
+ if (!Scope->isAbstractScope()) {
+ MachineLocation Location;
+ Location.set(RI->getFrameRegister(*MF),
+ RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
+
+
+ if (VD.hasComplexAddress())
+ AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
+ else if (VD.isBlockByrefVariable())
+ AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
+ else
+ AddAddress(VariableDie, dwarf::DW_AT_location, Location);
+ }
+ DV->setDIE(VariableDie);
+ return VariableDie;
+
+}
+DIE *DwarfDebug::ConstructScopeDIE(DbgScope *Scope) {
+ if (!Scope)
+ return NULL;
+ DIScope DS(Scope->getScopeNode());
+ if (DS.isNull())
+ return NULL;
+
+ DIE *ScopeDIE = NULL;
+ if (Scope->getInlinedAt())
+ ScopeDIE = ConstructInlinedScopeDIE(Scope);
+ else if (DS.isSubprogram()) {
+ if (Scope->isAbstractScope())
+ ScopeDIE = ModuleCU->getDieMapSlotFor(DS.getNode());
+ else
+ ScopeDIE = UpdateSubprogramScopeDIE(DS.getNode());
+ }
+ else {
+ ScopeDIE = ConstructLexicalScopeDIE(Scope);
+ if (!ScopeDIE) return NULL;
+ }
+
+ // Add variables to scope.
+ SmallVector<DbgVariable *, 8> &Variables = Scope->getVariables();
+ for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
+ DIE *VariableDIE = ConstructVariableDIE(Variables[i], Scope, ModuleCU);
+ if (VariableDIE)
+ ScopeDIE->AddChild(VariableDIE);
+ }
+
+ // Add nested scopes.
+ SmallVector<DbgScope *, 4> &Scopes = Scope->getScopes();
+ for (unsigned j = 0, M = Scopes.size(); j < M; ++j) {
+ // Define the Scope debug information entry.
+ DIE *NestedDIE = ConstructScopeDIE(Scopes[j]);
+ if (NestedDIE)
+ ScopeDIE->AddChild(NestedDIE);
+ }
+ return ScopeDIE;
+}
+
/// ConstructDbgScope - Construct the components of a scope.
-///
+/// FIXME: Remove
void DwarfDebug::ConstructDbgScope(DbgScope *ParentScope,
unsigned ParentStartID,
unsigned ParentEndID,
@@ -1408,34 +1654,6 @@
if (VariableDie) ParentDie->AddChild(VariableDie);
}
- // Add concrete instances to scope.
- SmallVector<DbgConcreteScope *, 8> &ConcreteInsts =
- ParentScope->getConcreteInsts();
- for (unsigned i = 0, N = ConcreteInsts.size(); i < N; ++i) {
- DbgConcreteScope *ConcreteInst = ConcreteInsts[i];
- DIE *Die = ConcreteInst->getDie();
-
- unsigned StartID = ConcreteInst->getStartLabelID();
- unsigned EndID = ConcreteInst->getEndLabelID();
-
- // Add the scope bounds.
- if (StartID)
- AddLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("label", StartID));
- else
- AddLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("func_begin", SubprogramCount));
-
- if (EndID)
- AddLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("label", EndID));
- else
- AddLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("func_end", SubprogramCount));
-
- ParentDie->AddChild(Die);
- }
-
// Add nested scopes.
SmallVector<DbgScope *, 4> &Scopes = ParentScope->getScopes();
for (unsigned j = 0, M = Scopes.size(); j < M; ++j) {
@@ -1450,8 +1668,7 @@
// Do not ignore inlined scopes even if they don't have any variables or
// scopes.
- if (Scope->getScopes().empty() && Scope->getVariables().empty() &&
- Scope->getConcreteInsts().empty())
+ if (Scope->getScopes().empty() && Scope->getVariables().empty())
continue;
if (StartID == ParentStartID && EndID == ParentEndID) {
@@ -1482,9 +1699,9 @@
}
}
-/// ConstructFunctionDbgScope - Construct the scope for the subprogram.
-///
-void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope,
+/// ConstructCurrentFnDbgScope - Construct the scope for the subprogram.
+/// FIXME: Remove
+void DwarfDebug::ConstructCurrentFnDbgScope(DbgScope *RootScope,
bool AbstractScope) {
// Exit if there is no root scope.
if (!RootScope) return;
@@ -1529,7 +1746,7 @@
}
/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
-///
+/// FIXME: Remove
void DwarfDebug::ConstructDefaultDbgScope(MachineFunction *MF) {
StringMap<DIE*> &Globals = ModuleCU->getGlobals();
StringMap<DIE*>::iterator GI = Globals.find(MF->getFunction()->getName());
@@ -1715,7 +1932,7 @@
ConstructGlobalVariableDIE(*I);
}
- // Create DIEs for each of the externally visible subprograms.
+ // Create DIEs for each subprogram.
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
E = DbgFinder.subprogram_end(); I != E; ++I)
ConstructSubprogram(*I);
@@ -1759,6 +1976,13 @@
if (TimePassesIsEnabled)
DebugTimer->startTimer();
+ // Attach DW_AT_inline attribute with inlined subprogram DIEs.
+ for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
+ AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
+ DIE *ISP = *AI;
+ AddUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
+ }
+
// Standard sections final addresses.
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
EmitLabel("text_end", 0);
@@ -1816,55 +2040,98 @@
DebugTimer->stopTimer();
}
+/// findAbstractVariable - Find abstract variable, if any, associated with Var.
+DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var, unsigned FrameIdx,
+ DILocation &ScopeLoc) {
+
+ DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var.getNode());
+ if (AbsDbgVariable)
+ return AbsDbgVariable;
+
+ DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope().getNode());
+ if (!Scope)
+ return NULL;
+
+ AbsDbgVariable = new DbgVariable(Var, FrameIdx);
+ Scope->AddVariable(AbsDbgVariable);
+ AbstractVariables[Var.getNode()] = AbsDbgVariable;
+ return AbsDbgVariable;
+}
+
/// CollectVariableInfo - Populate DbgScope entries with variables' info.
void DwarfDebug::CollectVariableInfo() {
if (!MMI) return;
+
MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
VE = VMap.end(); VI != VE; ++VI) {
MetadataBase *MB = VI->first;
MDNode *Var = dyn_cast_or_null<MDNode>(MB);
+ if (!Var) continue;
DIVariable DV (Var);
- if (DV.isNull()) continue;
- unsigned VSlot = VI->second;
- DbgScope *Scope = NULL;
- ValueMap<MDNode *, DbgScope *>::iterator DSI =
- DbgScopeMap.find(DV.getContext().getNode());
- if (DSI != DbgScopeMap.end())
- Scope = DSI->second;
- else
- // There is not any instruction assocated with this scope, so get
- // a new scope.
- Scope = getDbgScope(DV.getContext().getNode(),
- NULL /* Not an instruction */,
- NULL /* Not inlined */);
+ std::pair< unsigned, MDNode *> VP = VI->second;
+ DILocation ScopeLoc(VP.second);
+
+ DbgScope *Scope =
+ ConcreteScopes.lookup(ScopeLoc.getOrigLocation().getNode());
+ if (!Scope)
+ Scope = DbgScopeMap.lookup(ScopeLoc.getScope().getNode());
assert (Scope && "Unable to find variable scope!");
- Scope->AddVariable(new DbgVariable(DV, VSlot, false));
+
+ DbgVariable *RegVar = new DbgVariable(DV, VP.first);
+ Scope->AddVariable(RegVar);
+ if (DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.first, ScopeLoc))
+ RegVar->setAbstractVariable(AbsDbgVariable);
}
}
-/// SetDbgScopeBeginLabels - Update DbgScope begin labels for the scopes that
-/// start with this machine instruction.
-void DwarfDebug::SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned Label) {
+/// BeginScope - Process beginning of a scope starting at Label.
+void DwarfDebug::BeginScope(const MachineInstr *MI, unsigned Label) {
InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI);
if (I == DbgScopeBeginMap.end())
return;
- SmallVector<DbgScope *, 2> &SD = I->second;
- for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
+ ScopeVector &SD = DbgScopeBeginMap[MI];
+ for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end();
SDI != SDE; ++SDI)
(*SDI)->setStartLabelID(Label);
}
-/// SetDbgScopeEndLabels - Update DbgScope end labels for the scopes that
-/// end with this machine instruction.
-void DwarfDebug::SetDbgScopeEndLabels(const MachineInstr *MI, unsigned Label) {
+/// EndScope - Process end of a scope.
+void DwarfDebug::EndScope(const MachineInstr *MI) {
InsnToDbgScopeMapTy::iterator I = DbgScopeEndMap.find(MI);
if (I == DbgScopeEndMap.end())
return;
+
+ unsigned Label = MMI->NextLabelID();
+ Asm->printLabel(Label);
+
SmallVector<DbgScope *, 2> &SD = I->second;
for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
SDI != SDE; ++SDI)
(*SDI)->setEndLabelID(Label);
+ return;
+}
+
+/// createDbgScope - Create DbgScope for the scope.
+void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) {
+
+ if (!InlinedAt) {
+ DbgScope *WScope = DbgScopeMap.lookup(Scope);
+ if (WScope)
+ return;
+ WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL);
+ DbgScopeMap.insert(std::make_pair(Scope, WScope));
+ return;
+ }
+
+ DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
+ if (WScope)
+ return;
+
+ WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt);
+ DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
+ DILocation DL(InlinedAt);
+ createDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode());
}
/// ExtractScopeInformation - Scan machine instructions in this function
@@ -1875,26 +2142,41 @@
if (!DbgScopeMap.empty())
return false;
- // Scan each instruction and create scopes.
+ // Scan each instruction and create scopes. First build working set of scopes.
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;
DebugLoc DL = MInsn->getDebugLoc();
- if (DL.isUnknown())
- continue;
+ if (DL.isUnknown()) continue;
DebugLocTuple DLT = MF->getDebugLocTuple(DL);
- if (!DLT.Scope)
- continue;
+ if (!DLT.Scope) continue;
// 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.
- DIDescriptor D(DLT.Scope);
- if (!D.isCompileUnit()) {
- DbgScope *Scope = getDbgScope(DLT.Scope, MInsn, DLT.InlinedAtLoc);
- Scope->setLastInsn(MInsn);
- }
+ if (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
+ createDbgScope(DLT.Scope, DLT.InlinedAtLoc);
+ }
+ }
+
+
+ // Build scope hierarchy using working set of scopes.
+ 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;
+ DebugLoc DL = MInsn->getDebugLoc();
+ if (DL.isUnknown()) continue;
+ DebugLocTuple DLT = MF->getDebugLocTuple(DL);
+ if (!DLT.Scope) continue;
+ // 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 (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
+ DbgScope *Scope = getUpdatedDbgScope(DLT.Scope, MInsn, DLT.InlinedAtLoc);
+ Scope->setLastInsn(MInsn);
}
}
@@ -1902,8 +2184,8 @@
// last instruction as this scope's last instrunction.
for (ValueMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
DE = DbgScopeMap.end(); DI != DE; ++DI) {
- DbgScope *S = DI->second;
- if (!S) continue;
+ if (DI->second->isAbstractScope())
+ continue;
assert (DI->second->getFirstInsn() && "Invalid first instruction!");
DI->second->FixInstructionMarkers();
assert (DI->second->getLastInsn() && "Invalid last instruction!");
@@ -1916,7 +2198,8 @@
for (ValueMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
DE = DbgScopeMap.end(); DI != DE; ++DI) {
DbgScope *S = DI->second;
- if (!S) continue;
+ if (S->isAbstractScope())
+ continue;
const MachineInstr *MI = S->getFirstInsn();
assert (MI && "DbgScope does not have first instruction!");
@@ -1924,8 +2207,7 @@
if (IDI != DbgScopeBeginMap.end())
IDI->second.push_back(S);
else
- DbgScopeBeginMap.insert(std::make_pair(MI,
- SmallVector<DbgScope *, 2>(2, S)));
+ DbgScopeBeginMap[MI].push_back(S);
MI = S->getLastInsn();
assert (MI && "DbgScope does not have last instruction!");
@@ -1933,31 +2215,12 @@
if (IDI != DbgScopeEndMap.end())
IDI->second.push_back(S);
else
- DbgScopeEndMap.insert(std::make_pair(MI,
- SmallVector<DbgScope *, 2>(2, S)));
+ DbgScopeEndMap[MI].push_back(S);
}
return !DbgScopeMap.empty();
}
-static DISubprogram getDISubprogram(MDNode *N) {
-
- DIDescriptor D(N);
- if (D.isNull())
- return DISubprogram();
-
- if (D.isCompileUnit())
- return DISubprogram();
-
- if (D.isSubprogram())
- return DISubprogram(N);
-
- if (D.isLexicalBlock())
- return getDISubprogram(DILexicalBlock(N).getContext().getNode());
-
- llvm_unreachable("Unexpected Descriptor!");
-}
-
/// BeginFunction - Gather pre-function debug information. Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::BeginFunction(MachineFunction *MF) {
@@ -2034,15 +2297,10 @@
Lines.begin(), Lines.end());
}
- // Construct the DbgScope for abstract instances.
- for (SmallVector<DbgScope *, 32>::iterator
- I = AbstractInstanceRootList.begin(),
- E = AbstractInstanceRootList.end(); I != E; ++I)
- ConstructFunctionDbgScope(*I);
-
+#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
// Construct scopes for subprogram.
- if (FunctionDbgScope)
- ConstructFunctionDbgScope(FunctionDbgScope);
+ if (CurrentFnDbgScope)
+ ConstructCurrentFnDbgScope(CurrentFnDbgScope);
else
// FIXME: This is wrong. We are essentially getting past a problem with
// debug information not being able to handle unreachable blocks that have
@@ -2053,22 +2311,25 @@
// desirable. And a better way of handling this (and all of the debugging
// information) needs to be explored.
ConstructDefaultDbgScope(MF);
+#else
+ // Construct abstract scopes.
+ for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
+ AE = AbstractScopesList.end(); AI != AE; ++AI)
+ ConstructScopeDIE(*AI);
+ ConstructScopeDIE(CurrentFnDbgScope);
+#endif
DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
MMI->getFrameMoves()));
// Clear debug info
- if (FunctionDbgScope) {
- delete FunctionDbgScope;
+ if (CurrentFnDbgScope) {
+ CurrentFnDbgScope = NULL;
DbgScopeMap.clear();
DbgScopeBeginMap.clear();
DbgScopeEndMap.clear();
- DbgAbstractScopeMap.clear();
- DbgConcreteScopeMap.clear();
- FunctionDbgScope = NULL;
- LexicalScopeStack.clear();
- AbstractInstanceRootList.clear();
- AbstractInstanceRootMap.clear();
+ ConcreteScopes.clear();
+ AbstractScopesList.clear();
}
Lines.clear();
@@ -2143,7 +2404,6 @@
DbgScope *Scope = getOrCreateScope(N);
unsigned ID = MMI->NextLabelID();
if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
- LexicalScopeStack.push_back(Scope);
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
@@ -2159,12 +2419,6 @@
DbgScope *Scope = getOrCreateScope(N);
unsigned ID = MMI->NextLabelID();
Scope->setEndLabelID(ID);
- // FIXME : region.end() may not be in the last basic block.
- // For now, do not pop last lexical scope because next basic
- // block may start new inlined function's body.
- unsigned LSSize = LexicalScopeStack.size();
- if (LSSize != 0 && LSSize != 1)
- LexicalScopeStack.pop_back();
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
@@ -2179,157 +2433,22 @@
DIDescriptor Desc(N);
DbgScope *Scope = NULL;
- bool InlinedFnVar = false;
if (Desc.getTag() == dwarf::DW_TAG_variable)
Scope = getOrCreateScope(DIGlobalVariable(N).getContext().getNode());
else {
- bool InlinedVar = false;
MDNode *Context = DIVariable(N).getContext().getNode();
- DISubprogram SP(Context);
- if (!SP.isNull()) {
- // SP is inserted into DbgAbstractScopeMap when inlined function
- // start was recorded by RecordInlineFnStart.
- ValueMap<MDNode *, DbgScope *>::iterator
- I = DbgAbstractScopeMap.find(SP.getNode());
- if (I != DbgAbstractScopeMap.end()) {
- InlinedVar = true;
- Scope = I->second;
- }
- }
- if (!InlinedVar)
- Scope = getOrCreateScope(Context);
+ Scope = getOrCreateScope(Context);
}
assert(Scope && "Unable to find the variable's scope");
- DbgVariable *DV = new DbgVariable(DIVariable(N), FrameIndex, InlinedFnVar);
+ DbgVariable *DV = new DbgVariable(DIVariable(N), FrameIndex);
Scope->AddVariable(DV);
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
}
-//// RecordInlinedFnStart - Indicate the start of inlined subroutine.
-unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
- unsigned Line, unsigned Col) {
- unsigned LabelID = MMI->NextLabelID();
-
- if (!MAI->doesDwarfUsesInlineInfoSection())
- return LabelID;
-
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- MDNode *Node = SP.getNode();
- DenseMap<const MDNode *, DbgScope *>::iterator
- II = AbstractInstanceRootMap.find(Node);
-
- if (II == AbstractInstanceRootMap.end()) {
- // Create an abstract instance entry for this inlined function if it doesn't
- // already exist.
- DbgScope *Scope = new DbgScope(NULL, DIDescriptor(Node));
-
- // Get the compile unit context.
- DIE *SPDie = ModuleCU->getDieMapSlotFor(Node);
- if (!SPDie)
- SPDie = CreateSubprogramDIE(ModuleCU, SP, false, true);
-
- // Mark as being inlined. This makes this subprogram entry an abstract
- // instance root.
- // FIXME: Our debugger doesn't care about the value of DW_AT_inline, only
- // that it's defined. That probably won't change in the future. However,
- // this could be more elegant.
- AddUInt(SPDie, dwarf::DW_AT_inline, 0, dwarf::DW_INL_declared_not_inlined);
-
- // Keep track of the abstract scope for this function.
- DbgAbstractScopeMap[Node] = Scope;
-
- AbstractInstanceRootMap[Node] = Scope;
- AbstractInstanceRootList.push_back(Scope);
- }
-
- // Create a concrete inlined instance for this inlined function.
- DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(Node));
- DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine);
- ScopeDie->setAbstractCompileUnit(ModuleCU);
-
- DIE *Origin = ModuleCU->getDieMapSlotFor(Node);
- AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin,
- dwarf::DW_FORM_ref4, Origin);
- AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, ModuleCU->getID());
- AddUInt(ScopeDie, dwarf::DW_AT_call_line, 0, Line);
- AddUInt(ScopeDie, dwarf::DW_AT_call_column, 0, Col);
-
- ConcreteScope->setDie(ScopeDie);
- ConcreteScope->setStartLabelID(LabelID);
- MMI->RecordUsedDbgLabel(LabelID);
-
- LexicalScopeStack.back()->AddConcreteInst(ConcreteScope);
-
- // Keep track of the concrete scope that's inlined into this function.
- ValueMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator
- SI = DbgConcreteScopeMap.find(Node);
-
- if (SI == DbgConcreteScopeMap.end())
- DbgConcreteScopeMap[Node].push_back(ConcreteScope);
- else
- SI->second.push_back(ConcreteScope);
-
- // Track the start label for this inlined function.
- ValueMap<MDNode *, SmallVector<unsigned, 4> >::iterator
- I = InlineInfo.find(Node);
-
- if (I == InlineInfo.end())
- InlineInfo[Node].push_back(LabelID);
- else
- I->second.push_back(LabelID);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return LabelID;
-}
-
-/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
-unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) {
- if (!MAI->doesDwarfUsesInlineInfoSection())
- return 0;
-
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- MDNode *Node = SP.getNode();
- ValueMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator
- I = DbgConcreteScopeMap.find(Node);
-
- if (I == DbgConcreteScopeMap.end()) {
- // FIXME: Can this situation actually happen? And if so, should it?
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return 0;
- }
-
- SmallVector<DbgScope *, 8> &Scopes = I->second;
- if (Scopes.empty()) {
- // Returned ID is 0 if this is unbalanced "end of inlined
- // scope". This could happen if optimizer eats dbg intrinsics
- // or "beginning of inlined scope" is not recoginized due to
- // missing location info. In such cases, ignore this region.end.
- return 0;
- }
-
- DbgScope *Scope = Scopes.back(); Scopes.pop_back();
- unsigned ID = MMI->NextLabelID();
- MMI->RecordUsedDbgLabel(ID);
- Scope->setEndLabelID(ID);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return ID;
-}
-
//===----------------------------------------------------------------------===//
// Emit Methods
//===----------------------------------------------------------------------===//
@@ -2475,10 +2594,7 @@
case dwarf::DW_AT_abstract_origin: {
DIEEntry *E = cast<DIEEntry>(Values[i]);
DIE *Origin = E->getEntry();
- unsigned Addr =
- CompileUnitOffsets[Die->getAbstractCompileUnit()] +
- Origin->getOffset();
-
+ unsigned Addr = Origin->getOffset();
Asm->EmitInt32(Addr);
break;
}
@@ -3007,10 +3123,14 @@
Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
- for (ValueMap<MDNode *, SmallVector<unsigned, 4> >::iterator
- I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) {
- MDNode *Node = I->first;
- SmallVector<unsigned, 4> &Labels = I->second;
+ for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
+ E = InlinedSPNodes.end(); I != E; ++I) {
+
+// for (ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
+ // I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) {
+ MDNode *Node = *I;
+ ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II = InlineInfo.find(Node);
+ SmallVector<InlineInfoLabels, 4> &Labels = II->second;
DISubprogram SP(Node);
const char *LName = SP.getLinkageName();
const char *Name = SP.getName();
@@ -3024,17 +3144,21 @@
// __asm__ attribute.
if (LName[0] == 1)
LName = &LName[1];
- Asm->EmitString(LName);
+// Asm->EmitString(LName);
+ EmitSectionOffset("string", "section_str",
+ StringPool.idFor(LName), false, true);
+
}
Asm->EOL("MIPS linkage name");
-
- Asm->EmitString(Name); Asm->EOL("Function name");
-
+// Asm->EmitString(Name);
+ EmitSectionOffset("string", "section_str",
+ StringPool.idFor(Name), false, true);
+ Asm->EOL("Function name");
Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count");
- for (SmallVector<unsigned, 4>::iterator LI = Labels.begin(),
+ for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
LE = Labels.end(); LI != LE; ++LI) {
- DIE *SP = ModuleCU->getDieMapSlotFor(Node);
+ DIE *SP = LI->second;
Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset");
if (TD->getPointerSize() == sizeof(int32_t))
@@ -3042,7 +3166,7 @@
else
O << MAI->getData64bitsDirective();
- PrintLabelName("label", *LI); Asm->EOL("low_pc");
+ PrintLabelName("label", LI->first); Asm->EOL("low_pc");
}
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index ddb0a15..8694264 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -134,52 +134,52 @@
///
bool shouldEmit;
- // FunctionDbgScope - Top level scope for the current function.
+ // CurrentFnDbgScope - Top level scope for the current function.
//
- DbgScope *FunctionDbgScope;
+ DbgScope *CurrentFnDbgScope;
/// DbgScopeMap - Tracks the scopes in the current function.
+ ///
ValueMap<MDNode *, DbgScope *> DbgScopeMap;
+ /// ConcreteScopes - Tracks the concrete scopees in the current function.
+ /// These scopes are also included in DbgScopeMap.
+ ValueMap<MDNode *, DbgScope *> ConcreteScopes;
+
+ /// AbstractScopes - Tracks the abstract scopes a module. These scopes are
+ /// not included DbgScopeMap.
+ ValueMap<MDNode *, DbgScope *> AbstractScopes;
+ SmallVector<DbgScope *, 4>AbstractScopesList;
+
+ /// AbstractVariables - Collection on abstract variables.
+ ValueMap<MDNode *, DbgVariable *> AbstractVariables;
+
+ /// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked
+ /// (at the end of the module) as DW_AT_inline.
+ SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs;
+
+ /// AbstractSubprogramDIEs - Collection of abstruct subprogram DIEs.
+ SmallPtrSet<DIE *, 4> AbstractSubprogramDIEs;
+
/// ScopedGVs - Tracks global variables that are not at file scope.
/// For example void f() { static int b = 42; }
SmallVector<WeakVH, 4> ScopedGVs;
- typedef DenseMap<const MachineInstr *, SmallVector<DbgScope *, 2> >
+ typedef SmallVector<DbgScope *, 2> ScopeVector;
+ typedef DenseMap<const MachineInstr *, ScopeVector>
InsnToDbgScopeMapTy;
- /// DbgScopeBeginMap - Maps instruction with a list DbgScopes it starts.
+ /// DbgScopeBeginMap - Maps instruction with a list of DbgScopes it starts.
InsnToDbgScopeMapTy DbgScopeBeginMap;
/// DbgScopeEndMap - Maps instruction with a list DbgScopes it ends.
InsnToDbgScopeMapTy DbgScopeEndMap;
- /// DbgAbstractScopeMap - Tracks abstract instance scopes in the current
- /// function.
- ValueMap<MDNode *, DbgScope *> DbgAbstractScopeMap;
-
- /// DbgConcreteScopeMap - Tracks concrete instance scopes in the current
- /// function.
- ValueMap<MDNode *,
- SmallVector<DbgScope *, 8> > DbgConcreteScopeMap;
-
/// InlineInfo - Keep track of inlined functions and their location. This
/// information is used to populate debug_inlined section.
- ValueMap<MDNode *, SmallVector<unsigned, 4> > InlineInfo;
-
- /// AbstractInstanceRootMap - Map of abstract instance roots of inlined
- /// functions. These are subroutine entries that contain a DW_AT_inline
- /// attribute.
- DenseMap<const MDNode *, DbgScope *> AbstractInstanceRootMap;
-
- /// AbstractInstanceRootList - List of abstract instance roots of inlined
- /// functions. These are subroutine entries that contain a DW_AT_inline
- /// attribute.
- SmallVector<DbgScope *, 32> AbstractInstanceRootList;
-
- /// LexicalScopeStack - A stack of lexical scopes. The top one is the current
- /// scope.
- SmallVector<DbgScope *, 16> LexicalScopeStack;
+ typedef std::pair<unsigned, DIE *> InlineInfoLabels;
+ ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo;
+ SmallVector<MDNode *, 4> InlinedSPNodes;
/// CompileUnitOffsets - A vector of the offsets of the compile units. This is
/// used when calculating the "origin" of a concrete instance of an inlined
@@ -361,10 +361,24 @@
///
DIE *CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit);
- /// getDbgScope - Returns the scope associated with the given descriptor.
- ///
+ /// 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);
DbgScope *getOrCreateScope(MDNode *N);
- DbgScope *getDbgScope(MDNode *N, const MachineInstr *MI, MDNode *InlinedAt);
+ DbgScope *getOrCreateAbstractScope(MDNode *N);
+
+ /// findAbstractVariable - Find abstract variable associated with Var.
+ DbgVariable *findAbstractVariable(DIVariable &Var, unsigned FrameIdx,
+ DILocation &Loc);
+
+ DIE *UpdateSubprogramScopeDIE(MDNode *SPNode);
+ DIE *ConstructLexicalScopeDIE(DbgScope *Scope);
+ DIE *ConstructScopeDIE(DbgScope *Scope);
+ DIE *ConstructInlinedScopeDIE(DbgScope *Scope);
+ DIE *ConstructVariableDIE(DbgVariable *DV, DbgScope *S, CompileUnit *Unit);
/// ConstructDbgScope - Construct the components of a scope.
///
@@ -372,10 +386,10 @@
unsigned ParentStartID, unsigned ParentEndID,
DIE *ParentDie, CompileUnit *Unit);
- /// ConstructFunctionDbgScope - Construct the scope for the subprogram.
+ /// ConstructCurrentFnDbgScope - Construct the scope for the subprogram.
///
- void ConstructFunctionDbgScope(DbgScope *RootScope,
- bool AbstractScope = false);
+ void ConstructCurrentFnDbgScope(DbgScope *RootScope,
+ bool AbstractScope = false);
/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
///
@@ -544,13 +558,6 @@
/// RecordVariable - Indicate the declaration of a local variable.
void RecordVariable(MDNode *N, unsigned FrameIndex);
- //// RecordInlinedFnStart - Indicate the start of inlined subroutine.
- unsigned RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
- unsigned Line, unsigned Col);
-
- /// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
- unsigned RecordInlinedFnEnd(DISubprogram &SP);
-
/// ExtractScopeInformation - Scan machine instructions in this function
/// and collect DbgScopes. Return true, if atleast one scope was found.
bool ExtractScopeInformation(MachineFunction *MF);
@@ -558,15 +565,16 @@
/// CollectVariableInfo - Populate DbgScope entries with variables' info.
void CollectVariableInfo();
- /// SetDbgScopeBeginLabels - Update DbgScope begin labels for the scopes that
- /// start with this machine instruction.
- void SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned Label);
-
/// SetDbgScopeEndLabels - Update DbgScope end labels for the scopes that
/// end with this machine instruction.
void SetDbgScopeEndLabels(const MachineInstr *MI, unsigned Label);
-};
+ /// BeginScope - Process beginning of a scope starting at Label.
+ void BeginScope(const MachineInstr *MI, unsigned Label);
+
+ /// EndScope - Prcess end of a scope.
+ void EndScope(const MachineInstr *MI);
+};
} // End of namespace llvm
#endif
diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
index 0638d35..41da4df 100644
--- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
@@ -108,20 +108,9 @@
return DD && DD->ShouldEmitDwarfDebug();
}
-//// RecordInlinedFnStart
-unsigned DwarfWriter::RecordInlinedFnStart(DISubprogram SP, DICompileUnit CU,
- unsigned Line, unsigned Col) {
- return DD->RecordInlinedFnStart(SP, CU, Line, Col);
+void DwarfWriter::BeginScope(const MachineInstr *MI, unsigned L) {
+ DD->BeginScope(MI, L);
}
-
-/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
-unsigned DwarfWriter::RecordInlinedFnEnd(DISubprogram SP) {
- return DD->RecordInlinedFnEnd(SP);
-}
-
-void DwarfWriter::SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned L) {
- DD->SetDbgScopeEndLabels(MI, L);
-}
-void DwarfWriter::SetDbgScopeEndLabels(const MachineInstr *MI, unsigned L) {
- DD->SetDbgScopeBeginLabels(MI, L);
+void DwarfWriter::EndScope(const MachineInstr *MI) {
+ DD->EndScope(MI);
}
diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp
index 8e955af..72fa3a9 100644
--- a/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -43,6 +43,7 @@
#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
+#include "llvm/LLVMContext.h"
#include "llvm/CodeGen/FastISel.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
@@ -347,21 +348,9 @@
&& DW->ShouldEmitDwarfDebug()) {
unsigned ID = 0;
DISubprogram Subprogram(REI->getContext());
- if (isInlinedFnEnd(*REI, MF.getFunction())) {
- // This is end of an inlined function.
- const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
- ID = DW->RecordInlinedFnEnd(Subprogram);
- if (ID)
- // Returned ID is 0 if this is unbalanced "end of inlined
- // scope". This could happen if optimizer eats dbg intrinsics
- // or "beginning of inlined scope" is not recoginized due to
- // missing location info. In such cases, ignore this region.end.
- BuildMI(MBB, DL, II).addImm(ID);
- } else {
- const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
- ID = DW->RecordRegionEnd(REI->getContext());
- BuildMI(MBB, DL, II).addImm(ID);
- }
+ const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
+ ID = DW->RecordRegionEnd(REI->getContext());
+ BuildMI(MBB, DL, II).addImm(ID);
}
return true;
}
@@ -371,28 +360,6 @@
|| !DW->ShouldEmitDwarfDebug())
return true;
- if (isInlinedFnStart(*FSI, MF.getFunction())) {
- // This is a beginning of an inlined function.
-
- // If llvm.dbg.func.start is seen in a new block before any
- // llvm.dbg.stoppoint intrinsic then the location info is unknown.
- // FIXME : Why DebugLoc is reset at the beginning of each block ?
- DebugLoc PrevLoc = DL;
- if (PrevLoc.isUnknown())
- return true;
- // Record the source line.
- setCurDebugLoc(ExtractDebugLocation(*FSI, MF.getDebugLocInfo()));
-
- DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc);
- DISubprogram SP(FSI->getSubprogram());
- unsigned LabelID =
- DW->RecordInlinedFnStart(SP,DICompileUnit(PrevLocTpl.Scope),
- PrevLocTpl.Line, PrevLocTpl.Col);
- const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
- BuildMI(MBB, DL, II).addImm(LabelID);
- return true;
- }
-
// This is a beginning of a new function.
MF.setDefaultDebugLoc(ExtractDebugLocation(*FSI, MF.getDebugLocInfo()));
@@ -416,8 +383,13 @@
StaticAllocaMap.find(AI);
if (SI == StaticAllocaMap.end()) break; // VLAs.
int FI = SI->second;
- if (MMI)
- MMI->setVariableDbgInfo(DI->getVariable(), FI);
+ if (MMI) {
+ MetadataContext &TheMetadata =
+ DI->getParent()->getContext().getMetadata();
+ unsigned MDDbgKind = TheMetadata.getMDKind("dbg");
+ MDNode *Dbg = TheMetadata.getMD(MDDbgKind, DI);
+ MMI->setVariableDbgInfo(DI->getVariable(), FI, Dbg);
+ }
#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
DW->RecordVariable(DI->getVariable(), FI);
#endif
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index 9818e62..3161bd0 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -26,6 +26,7 @@
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/IntrinsicInst.h"
+#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/FastISel.h"
#include "llvm/CodeGen/GCStrategy.h"
@@ -3931,25 +3932,8 @@
|| !DW->ShouldEmitDwarfDebug())
return 0;
- MachineFunction &MF = DAG.getMachineFunction();
DISubprogram Subprogram(REI.getContext());
- if (isInlinedFnEnd(REI, MF.getFunction())) {
- // This is end of inlined function. Debugging information for inlined
- // function is not handled yet (only supported by FastISel).
- if (OptLevel == CodeGenOpt::None) {
- unsigned ID = DW->RecordInlinedFnEnd(Subprogram);
- if (ID != 0)
- // Returned ID is 0 if this is unbalanced "end of inlined
- // scope". This could happen if optimizer eats dbg intrinsics or
- // "beginning of inlined scope" is not recoginized due to missing
- // location info. In such cases, do ignore this region.end.
- DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(),
- getRoot(), ID));
- }
- return 0;
- }
-
unsigned LabelID =
DW->RecordRegionEnd(REI.getContext());
DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(),
@@ -3963,37 +3947,6 @@
return 0;
MachineFunction &MF = DAG.getMachineFunction();
- // This is a beginning of an inlined function.
- if (isInlinedFnStart(FSI, MF.getFunction())) {
- if (OptLevel != CodeGenOpt::None)
- // FIXME: Debugging informaation for inlined function is only
- // supported at CodeGenOpt::Node.
- return 0;
-
- DebugLoc PrevLoc = CurDebugLoc;
- // If llvm.dbg.func.start is seen in a new block before any
- // llvm.dbg.stoppoint intrinsic then the location info is unknown.
- // FIXME : Why DebugLoc is reset at the beginning of each block ?
- if (PrevLoc.isUnknown())
- return 0;
-
- // Record the source line.
- setCurDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo()));
-
- if (!DW || !DW->ShouldEmitDwarfDebug())
- return 0;
- DebugLocTuple PrevLocTpl = MF.getDebugLocTuple(PrevLoc);
- DISubprogram SP(FSI.getSubprogram());
- DICompileUnit CU(PrevLocTpl.Scope);
- unsigned LabelID = DW->RecordInlinedFnStart(SP, CU,
- PrevLocTpl.Line,
- PrevLocTpl.Col);
- DAG.setRoot(DAG.getLabel(ISD::DBG_LABEL, getCurDebugLoc(),
- getRoot(), LabelID));
- return 0;
- }
-
- // This is a beginning of a new function.
MF.setDefaultDebugLoc(ExtractDebugLocation(FSI, MF.getDebugLocInfo()));
if (!DW || !DW->ShouldEmitDwarfDebug())
@@ -4028,8 +3981,13 @@
int FI = SI->second;
#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
- if (MMI)
- MMI->setVariableDbgInfo(Variable, FI);
+ if (MMI) {
+ MetadataContext &TheMetadata =
+ DI.getParent()->getContext().getMetadata();
+ unsigned MDDbgKind = TheMetadata.getMDKind("dbg");
+ MDNode *Dbg = TheMetadata.getMD(MDDbgKind, &DI);
+ MMI->setVariableDbgInfo(Variable, FI, Dbg);
+ }
#else
DW->RecordVariable(Variable, FI);
#endif
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 9c28c91..ab5f21e 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -387,13 +387,14 @@
if (MDDbgKind) {
// Update DebugLoc if debug information is attached with this
// instruction.
- if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, I)) {
- DILocation DILoc(Dbg);
- DebugLoc Loc = ExtractDebugLocation(DILoc, MF->getDebugLocInfo());
- SDL->setCurDebugLoc(Loc);
- if (MF->getDefaultDebugLoc().isUnknown())
- MF->setDefaultDebugLoc(Loc);
- }
+ if (!isa<DbgInfoIntrinsic>(I))
+ if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, I)) {
+ DILocation DILoc(Dbg);
+ DebugLoc Loc = ExtractDebugLocation(DILoc, MF->getDebugLocInfo());
+ SDL->setCurDebugLoc(Loc);
+ if (MF->getDefaultDebugLoc().isUnknown())
+ MF->setDefaultDebugLoc(Loc);
+ }
}
if (!isa<TerminatorInst>(I))
SDL->visit(*I);
@@ -750,14 +751,15 @@
if (MDDbgKind) {
// Update DebugLoc if debug information is attached with this
// instruction.
- if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, BI)) {
- DILocation DILoc(Dbg);
- DebugLoc Loc = ExtractDebugLocation(DILoc,
- MF.getDebugLocInfo());
- FastIS->setCurDebugLoc(Loc);
- if (MF.getDefaultDebugLoc().isUnknown())
- MF.setDefaultDebugLoc(Loc);
- }
+ if (!isa<DbgInfoIntrinsic>(BI))
+ if (MDNode *Dbg = TheMetadata.getMD(MDDbgKind, BI)) {
+ DILocation DILoc(Dbg);
+ DebugLoc Loc = ExtractDebugLocation(DILoc,
+ MF.getDebugLocInfo());
+ FastIS->setCurDebugLoc(Loc);
+ if (MF.getDefaultDebugLoc().isUnknown())
+ MF.setDefaultDebugLoc(Loc);
+ }
}
// Just before the terminator instruction, insert instructions to
diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp
index 24542a5..e562606 100644
--- a/lib/Transforms/Utils/CloneFunction.cpp
+++ b/lib/Transforms/Utils/CloneFunction.cpp
@@ -20,6 +20,7 @@
#include "llvm/IntrinsicInst.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Function.h"
+#include "llvm/LLVMContext.h"
#include "llvm/Support/CFG.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include "llvm/Analysis/ConstantFolding.h"
@@ -346,6 +347,27 @@
Ops.size(), TD);
}
+static MDNode *UpdateInlinedAtInfo(MDNode *InsnMD, MDNode *TheCallMD,
+ LLVMContext &Context) {
+ DILocation ILoc(InsnMD);
+ if (ILoc.isNull()) return InsnMD;
+
+ DILocation CallLoc(TheCallMD);
+ if (CallLoc.isNull()) return InsnMD;
+
+ DILocation OrigLocation = ILoc.getOrigLocation();
+ MDNode *NewLoc = TheCallMD;
+ if (!OrigLocation.isNull())
+ NewLoc = UpdateInlinedAtInfo(OrigLocation.getNode(), TheCallMD, Context);
+
+ SmallVector<Value *, 4> MDVs;
+ MDVs.push_back(InsnMD->getElement(0)); // Line
+ MDVs.push_back(InsnMD->getElement(1)); // Col
+ MDVs.push_back(InsnMD->getElement(2)); // Scope
+ MDVs.push_back(NewLoc);
+ return MDNode::get(Context, MDVs.data(), MDVs.size());
+}
+
/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
/// except that it does some simple constant prop and DCE on the fly. The
/// effect of this is to copy significantly less code in cases where (for
@@ -358,7 +380,8 @@
SmallVectorImpl<ReturnInst*> &Returns,
const char *NameSuffix,
ClonedCodeInfo *CodeInfo,
- const TargetData *TD) {
+ const TargetData *TD,
+ Instruction *TheCall) {
assert(NameSuffix && "NameSuffix cannot be null!");
#ifndef NDEBUG
@@ -397,19 +420,49 @@
// references as we go. This uses ValueMap to do all the hard work.
//
BasicBlock::iterator I = NewBB->begin();
+
+ LLVMContext &Context = OldFunc->getContext();
+ unsigned DbgKind = Context.getMetadata().getMDKind("dbg");
+ MDNode *TheCallMD = NULL;
+ SmallVector<Value *, 4> MDVs;
+ if (TheCall && TheCall->hasMetadata())
+ TheCallMD = Context.getMetadata().getMD(DbgKind, TheCall);
// Handle PHI nodes specially, as we have to remove references to dead
// blocks.
if (PHINode *PN = dyn_cast<PHINode>(I)) {
// Skip over all PHI nodes, remembering them for later.
BasicBlock::const_iterator OldI = BI->begin();
- for (; (PN = dyn_cast<PHINode>(I)); ++I, ++OldI)
+ for (; (PN = dyn_cast<PHINode>(I)); ++I, ++OldI) {
+ if (I->hasMetadata())
+ if (TheCallMD) {
+ if (MDNode *IMD = Context.getMetadata().getMD(DbgKind, I)) {
+ MDNode *NewMD = UpdateInlinedAtInfo(IMD, TheCallMD, Context);
+ Context.getMetadata().addMD(DbgKind, NewMD, I);
+ }
+ } else
+ // The cloned instruction has dbg info but the call instruction
+ // does not have dbg info. Remove dbg info from cloned instruction.
+ Context.getMetadata().removeMD(DbgKind, I);
PHIToResolve.push_back(cast<PHINode>(OldI));
+ }
}
// Otherwise, remap the rest of the instructions normally.
- for (; I != NewBB->end(); ++I)
+ for (; I != NewBB->end(); ++I) {
+ if (I->hasMetadata())
+ if (TheCallMD) {
+ if (MDNode *IMD = Context.getMetadata().getMD(DbgKind, I)) {
+ MDNode *NewMD = UpdateInlinedAtInfo(IMD, TheCallMD, Context);
+ Context.getMetadata().addMD(DbgKind, NewMD, I);
+ }
+ } else
+ // The cloned instruction has dbg info but the call instruction
+ // does not have dbg info. Remove dbg info from cloned instruction.
+ Context.getMetadata().removeMD(DbgKind, I);
+
RemapInstruction(I, ValueMap);
+ }
}
// Defer PHI resolution until rest of function is resolved, PHI resolution
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index 20f5a4a..043046c 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -386,7 +386,7 @@
// (which can happen, e.g., because an argument was constant), but we'll be
// happy with whatever the cloner can do.
CloneAndPruneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i",
- &InlinedFunctionInfo, TD);
+ &InlinedFunctionInfo, TD, TheCall);
// Remember the first block that is newly cloned over.
FirstNewBlock = LastBlock; ++FirstNewBlock;