static cl::opt<bool> PrintDbgScope("print-dbgscope", cl::Hidden,
cl::desc("Print DbgScope information for each machine instruction"));
-static cl::opt<bool> DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
+static cl::opt<bool> DisableDebugInfoPrinting("disable-debug-info-print",
+ cl::Hidden,
cl::desc("Disable debug info printing"));
static cl::opt<bool> UnknownLocations("use-unknown-locations", cl::Hidden,
/// IndexTyDie - An anonymous type for index type. Owned by CUDie.
DIE *IndexTyDie;
- /// GVToDieMap - Tracks the mapping of unit level debug informaton
+ /// MDNodeToDieMap - Tracks the mapping of unit level debug informaton
/// variables to debug information entries.
- /// FIXME : Rename GVToDieMap -> NodeToDieMap
- DenseMap<const MDNode *, DIE *> GVToDieMap;
+ DenseMap<const MDNode *, DIE *> MDNodeToDieMap;
- /// GVToDIEEntryMap - Tracks the mapping of unit level debug informaton
+ /// MDNodeToDIEEntryMap - Tracks the mapping of unit level debug informaton
/// descriptors to debug information entries using a DIEEntry proxy.
- /// FIXME : Rename
- DenseMap<const MDNode *, DIEEntry *> GVToDIEEntryMap;
+ DenseMap<const MDNode *, DIEEntry *> MDNodeToDIEEntryMap;
/// Globals - A map of globally visible named entities for this unit.
///
/// getDIE - Returns the debug information entry map slot for the
/// specified debug variable.
- DIE *getDIE(const MDNode *N) { return GVToDieMap.lookup(N); }
+ DIE *getDIE(const MDNode *N) { return MDNodeToDieMap.lookup(N); }
/// insertDIE - Insert DIE into the map.
void insertDIE(const MDNode *N, DIE *D) {
- GVToDieMap.insert(std::make_pair(N, D));
+ MDNodeToDieMap.insert(std::make_pair(N, D));
}
/// getDIEEntry - Returns the debug information entry for the speciefied
/// debug variable.
DIEEntry *getDIEEntry(const MDNode *N) {
- DenseMap<const MDNode *, DIEEntry *>::iterator I = GVToDIEEntryMap.find(N);
- if (I == GVToDIEEntryMap.end())
+ DenseMap<const MDNode *, DIEEntry *>::iterator I = MDNodeToDIEEntryMap.find(N);
+ if (I == MDNodeToDIEEntryMap.end())
return NULL;
return I->second;
}
/// insertDIEEntry - Insert debug information entry into the map.
void insertDIEEntry(const MDNode *N, DIEEntry *E) {
- GVToDIEEntryMap.insert(std::make_pair(N, E));
+ MDNodeToDIEEntryMap.insert(std::make_pair(N, E));
}
/// addDie - Adds or interns the DIE to the compile unit.
DwarfFrameSectionSym = DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
DwarfStrSectionSym = TextSectionSym = 0;
DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0;
+ DwarfDebugLineSectionSym = CurrentLineSectionSym = 0;
FunctionBeginSym = FunctionEndSym = 0;
+ DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);
{
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
beginModule(M);
void DwarfDebug::addUInt(DIE *Die, unsigned Attribute,
unsigned Form, uint64_t Integer) {
if (!Form) Form = DIEInteger::BestForm(false, Integer);
- DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer);
+ DIEValue *Value = Integer == 1 ?
+ DIEIntegerOne : new (DIEValueAllocator) DIEInteger(Integer);
Die->addValue(Attribute, Form, Value);
}
if (!Name.empty())
addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
- if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type ||
- Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) {
+ if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type
+ || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type)
+ {
// Add size if non-zero (derived types might be zero-sized.)
if (Size)
addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size);
/// If there are global variables in this scope then create and insert
/// DIEs for these variables.
DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) {
- ProcessedSPNodes.insert(SPNode);
CompileUnit *SPCU = getCompileUnit(SPNode);
DIE *SPDie = SPCU->getDIE(SPNode);
+
assert(SPDie && "Unable to find subprogram DIE!");
DISubprogram SP(SPNode);
SPCU->addDie(SPDie);
}
+ // Pick up abstract subprogram DIE.
+ if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) {
+ SPDie = new DIE(dwarf::DW_TAG_subprogram);
+ addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin,
+ dwarf::DW_FORM_ref4, AbsSPDIE);
+ SPCU->addDie(SPDie);
+ }
+
addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber()));
addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
const MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
- if (StartLabel == FunctionBeginSym || EndLabel == 0) {
+ if (StartLabel == 0 || EndLabel == 0) {
assert (0 && "Unexpected Start and End labels for a inlined scope!");
return 0;
}
// FIXME : Handle getNumOperands != 3
if (DVInsn->getNumOperands() == 3) {
if (DVInsn->getOperand(0).isReg())
- updated = addRegisterAddress(VariableDie, DVLabel, DVInsn->getOperand(0));
+ updated =
+ addRegisterAddress(VariableDie, DVLabel, DVInsn->getOperand(0));
else if (DVInsn->getOperand(0).isImm())
updated = addConstantValue(VariableDie, DVLabel, DVInsn->getOperand(0));
else if (DVInsn->getOperand(0).isFPImm())
- updated = addConstantFPValue(VariableDie, DVLabel, DVInsn->getOperand(0));
+ updated =
+ addConstantFPValue(VariableDie, DVLabel, DVInsn->getOperand(0));
} else {
MachineLocation Location = Asm->getDebugValueLocation(DVInsn);
if (Location.getReg()) {
if (Scope->getInlinedAt())
ScopeDIE = constructInlinedScopeDIE(Scope);
else if (DS.isSubprogram()) {
- if (Scope->isAbstractScope())
+ ProcessedSPNodes.insert(DS);
+ if (Scope->isAbstractScope()) {
ScopeDIE = getCompileUnit(DS)->getDIE(DS);
+ // Note down abstract DIE.
+ if (ScopeDIE)
+ AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
+ }
else
ScopeDIE = updateSubprogramScopeDIE(DS);
}
addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
// Use DW_AT_entry_pc instead of DW_AT_low_pc/DW_AT_high_pc pair. This
// simplifies debug range entries.
- addUInt(Die, dwarf::DW_AT_entry_pc, dwarf::DW_FORM_data4, 0);
+ addUInt(Die, dwarf::DW_AT_entry_pc, dwarf::DW_FORM_addr, 0);
// DW_AT_stmt_list is a offset of line number information for this
- // compile unit in debug_line section. It is always zero when only one
- // compile unit is emitted in one object file.
- addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
+ // compile unit in debug_line section. This offset is calculated
+ // during endMoudle().
+ addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
if (!Dir.empty())
addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir);
// Compute DIE offsets and sizes.
computeSizeAndOffsets();
+ // Emit source line correspondence into a debug line section.
+ emitDebugLines();
+
// Emit all the DIEs into a debug info section
emitDebugInfo();
// Corresponding abbreviations into a abbrev section.
emitAbbreviations();
- // Emit source line correspondence into a debug line section.
- emitDebugLines();
-
// Emit info into a debug pubnames section.
emitDebugPubNames();
const MachineInstr *Begin = NULL;
const MachineInstr *End = NULL;
for (SmallVector<const MachineInstr *, 4>::iterator
- MVI = MultipleValues.begin(), MVE = MultipleValues.end(); MVI != MVE; ++MVI) {
+ MVI = MultipleValues.begin(), MVE = MultipleValues.end();
+ MVI != MVE; ++MVI) {
if (!Begin) {
Begin = *MVI;
continue;
}
/// getOrCreateDbgScope - Create DbgScope for the scope.
-DbgScope *DwarfDebug::getOrCreateDbgScope(const MDNode *Scope, const MDNode *InlinedAt) {
+DbgScope *DwarfDebug::getOrCreateDbgScope(const MDNode *Scope,
+ const MDNode *InlinedAt) {
if (!InlinedAt) {
DbgScope *WScope = DbgScopeMap.lookup(Scope);
if (WScope)
// current instruction scope does not match scope of first instruction
// in this range then create a new instruction range.
DbgRange R(RangeBeginMI, PrevMI);
- MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevScope, PrevInlinedAt);
+ MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevScope,
+ PrevInlinedAt);
MIRanges.push_back(R);
}
if (FDL.isUnknown()) return;
const MDNode *Scope = FDL.getScope(MF->getFunction()->getContext());
+ const MDNode *TheScope = 0;
DISubprogram SP = getDISubprogram(Scope);
unsigned Line, Col;
if (SP.Verify()) {
Line = SP.getLineNumber();
Col = 0;
+ TheScope = SP;
} else {
Line = FDL.getLine();
Col = FDL.getCol();
+ TheScope = Scope;
}
- recordSourceLine(Line, Col, Scope);
+ recordSourceLine(Line, Col, TheScope);
/// ProcessedArgs - Collection of arguments already processed.
SmallPtrSet<const MDNode *, 8> ProcessedArgs;
DIVariable DV(MI->getOperand(MI->getNumOperands() - 1).getMetadata());
if (!DV.Verify()) continue;
// If DBG_VALUE is for a local variable then it needs a label.
- if (DV.getTag() != dwarf::DW_TAG_arg_variable)
+ if (DV.getTag() != dwarf::DW_TAG_arg_variable
+ && isDbgValueInUndefinedReg(MI) == false)
InsnNeedsLabel.insert(MI);
// DBG_VALUE for inlined functions argument needs a label.
- else if (!DISubprogram(DV.getContext()).describes(MF->getFunction()))
+ else if (!DISubprogram(getDISubprogram(DV.getContext())).
+ describes(MF->getFunction()))
InsnNeedsLabel.insert(MI);
// DBG_VALUE indicating argument location change needs a label.
else if (isDbgValueInUndefinedReg(MI) == false && !ProcessedArgs.insert(DV))
// Construct abstract scopes.
for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
AE = AbstractScopesList.end(); AI != AE; ++AI) {
- constructScopeDIE(*AI);
DISubprogram SP((*AI)->getScopeNode());
if (SP.Verify()) {
// Collect info for variables that were optimized out.
DIVariable DV(cast_or_null<MDNode>(NMD->getOperand(i)));
if (!DV || !ProcessedVars.insert(DV))
continue;
- DbgScope *Scope = DbgScopeMap.lookup(DV.getContext());
+ DbgScope *Scope = AbstractScopes.lookup(DV.getContext());
if (Scope)
Scope->addVariable(new DbgVariable(DV));
}
}
}
+ if (ProcessedSPNodes.count((*AI)->getScopeNode()) == 0)
+ constructScopeDIE(*AI);
}
-
+
DIE *CurFnDIE = constructScopeDIE(CurrentFnDbgScope);
if (!DisableFramePointerElim(*MF))
/// recordSourceLine - Register a source line with debug info. Returns the
/// unique label that was emitted and which provides correspondence to
/// the source line list.
-MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S) {
+MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col,
+ const MDNode *S) {
StringRef Dir;
StringRef Fn;
Src = GetOrCreateSourceID(Dir, Fn);
}
-#if 0
- if (!Lines.empty()) {
- SrcLineInfo lastSrcLineInfo = Lines.back();
- // Emitting sequential line records with the same line number (but
- // different addresses) seems to confuse GDB. Avoid this.
- if (lastSrcLineInfo.getLine() == Line)
- return NULL;
- }
-#endif
-
MCSymbol *Label = MMI->getContext().CreateTempSymbol();
Lines.push_back(SrcLineInfo(Line, Col, Src, Label));
if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection())
EmitSectionSym(Asm, MacroInfo);
- EmitSectionSym(Asm, TLOF.getDwarfLineSection());
+ DwarfDebugLineSectionSym =
+ EmitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
EmitSectionSym(Asm, TLOF.getDwarfLocSection());
EmitSectionSym(Asm, TLOF.getDwarfPubNamesSection());
EmitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
4);
break;
}
+ case dwarf::DW_AT_stmt_list: {
+ Asm->EmitLabelDifference(CurrentLineSectionSym,
+ DwarfDebugLineSectionSym, 4);
+ break;
+ }
case dwarf::DW_AT_location: {
if (UseDotDebugLocEntry.count(Die) != 0) {
DIELabel *L = cast<DIELabel>(Values[i]);
Asm->getObjFileLowering().getDwarfLineSection());
// Construct the section header.
+ CurrentLineSectionSym = Asm->GetTempSymbol("section_line_begin");
+ Asm->OutStreamer.EmitLabel(CurrentLineSectionSym);
Asm->OutStreamer.AddComment("Length of Source Line Info");
Asm->EmitLabelDifference(Asm->GetTempSymbol("line_end"),
Asm->GetTempSymbol("line_begin"), 4);
unsigned char Size = Asm->getTargetData().getPointerSize();
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0));
unsigned index = 1;
- for (SmallVector<DotDebugLocEntry, 4>::iterator I = DotDebugLocEntries.begin(),
- E = DotDebugLocEntries.end(); I != E; ++I, ++index) {
+ for (SmallVector<DotDebugLocEntry, 4>::iterator
+ I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
+ I != E; ++I, ++index) {
DotDebugLocEntry Entry = *I;
if (Entry.isEmpty()) {
Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0);