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.
///
class DbgVariable {
DIVariable Var; // Variable Descriptor.
- DIE *TheDIE;
+ DIE *TheDIE; // Variable DIE.
+ unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries.
public:
// AbsVar may be NULL.
- DbgVariable(DIVariable V) : Var(V), TheDIE(0) {}
+ DbgVariable(DIVariable V) : Var(V), TheDIE(0), DotDebugLocOffset(~0U) {}
// Accessors.
DIVariable getVariable() const { return Var; }
void setDIE(DIE *D) { TheDIE = D; }
DIE *getDIE() const { return TheDIE; }
+ void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; }
+ unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; }
};
//===----------------------------------------------------------------------===//
DwarfFrameSectionSym = DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
DwarfStrSectionSym = TextSectionSym = 0;
- DwarfDebugRangeSectionSym = 0;
- FunctionBeginSym = 0;
- if (TimePassesIsEnabled) {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName);
- beginModule(M);
- } else {
- beginModule(M);
+ DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0;
+ DwarfDebugLineSectionSym = CurrentLineSectionSym = 0;
+ FunctionBeginSym = FunctionEndSym = 0;
+ DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);
+ {
+ NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
+ beginModule(M);
}
}
DwarfDebug::~DwarfDebug() {
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);
}
} else if (Context.isNameSpace()) {
DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context));
ContextDIE->addChild(Die);
+ } else if (Context.isSubprogram()) {
+ DIE *ContextDIE = createSubprogramDIE(DISubprogram(Context),
+ /*MakeDecl=*/false);
+ ContextDIE->addChild(Die);
} else if (DIE *ContextDIE = getCompileUnit(Context)->getDIE(Context))
ContextDIE->addChild(Die);
else
if (DIDescriptor(ContainingType).isCompositeType())
addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
getOrCreateTypeDIE(DIType(ContainingType)));
+ else {
+ DIDescriptor Context = CTy.getContext();
+ addToContextOwner(&Buffer, Context);
+ }
break;
}
default:
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);
// DW_TAG_inlined_subroutine may refer to this DIE.
SPCU->insertDIE(SP, SPDie);
+ // Add to context owner.
+ addToContextOwner(SPDie, SP.getContext());
+
return SPDie;
}
DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *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,
DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize());
for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(),
RE = Ranges.end(); RI != RE; ++RI) {
- DebugRangeSymbols.push_back(LabelsBeforeInsn.lookup(RI->first));
- DebugRangeSymbols.push_back(LabelsAfterInsn.lookup(RI->second));
+ DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
+ DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
}
DebugRangeSymbols.push_back(NULL);
DebugRangeSymbols.push_back(NULL);
return ScopeDIE;
}
- MCSymbol *Start = LabelsBeforeInsn.lookup(RI->first);
- MCSymbol *End = LabelsAfterInsn.lookup(RI->second);
+ const MCSymbol *Start = getLabelBeforeInsn(RI->first);
+ const MCSymbol *End = getLabelAfterInsn(RI->second);
- if (Start == 0 || End == 0) return 0;
+ if (End == 0) return 0;
assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
assert(End->isDefined() && "Invalid end label for an inlined scope!");
// For now, use first instruction range and emit low_pc/high_pc pair and
// corresponding .debug_inlined section entry for this pair.
SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin();
- MCSymbol *StartLabel = LabelsBeforeInsn.lookup(RI->first);
- MCSymbol *EndLabel = LabelsAfterInsn.lookup(RI->second);
+ const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
+ const MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
if (StartLabel == 0 || EndLabel == 0) {
assert (0 && "Unexpected Start and End labels for a inlined scope!");
addType(VariableDie, VD.getType());
}
+ if (Tag == dwarf::DW_TAG_formal_parameter && VD.getType().isArtificial())
+ addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1);
+
+ if (Scope->isAbstractScope()) {
+ DV->setDIE(VariableDie);
+ return VariableDie;
+ }
+
// Add variable address.
- if (!Scope->isAbstractScope()) {
- // Check if variable is described by DBG_VALUE instruction.
- DenseMap<const DbgVariable *, const MachineInstr *>::iterator DVI =
- DbgVariableToDbgInstMap.find(DV);
- if (DVI != DbgVariableToDbgInstMap.end()) {
- const MachineInstr *DVInsn = DVI->second;
- const MCSymbol *DVLabel = findVariableLabel(DV);
- bool updated = false;
- // FIXME : Handle getNumOperands != 3
- if (DVInsn->getNumOperands() == 3) {
- if (DVInsn->getOperand(0).isReg())
- 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));
- } else {
- MachineLocation Location = Asm->getDebugValueLocation(DVInsn);
- if (Location.getReg()) {
- addAddress(VariableDie, dwarf::DW_AT_location, Location);
- if (DVLabel)
- addLabel(VariableDie, dwarf::DW_AT_start_scope, dwarf::DW_FORM_addr,
- DVLabel);
- updated = true;
- }
- }
- if (!updated) {
- // If variableDie is not updated then DBG_VALUE instruction does not
- // have valid variable info.
- delete VariableDie;
- return NULL;
- }
- }
- else {
- MachineLocation Location;
- unsigned FrameReg;
- const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
- int FI = 0;
- if (findVariableFrameIndex(DV, &FI)) {
- int Offset = RI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
- Location.set(FrameReg, Offset);
-
- 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);
+
+ unsigned Offset = DV->getDotDebugLocOffset();
+ if (Offset != ~0U) {
+ addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4,
+ Asm->GetTempSymbol("debug_loc", Offset));
+ DV->setDIE(VariableDie);
+ UseDotDebugLocEntry.insert(VariableDie);
+ return VariableDie;
+ }
+
+ // Check if variable is described by a DBG_VALUE instruction.
+ DenseMap<const DbgVariable *, const MachineInstr *>::iterator DVI =
+ DbgVariableToDbgInstMap.find(DV);
+ if (DVI != DbgVariableToDbgInstMap.end()) {
+ const MachineInstr *DVInsn = DVI->second;
+ const MCSymbol *DVLabel = findVariableLabel(DV);
+ bool updated = false;
+ // FIXME : Handle getNumOperands != 3
+ if (DVInsn->getNumOperands() == 3) {
+ if (DVInsn->getOperand(0).isReg())
+ 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));
+ } else {
+ MachineLocation Location = Asm->getDebugValueLocation(DVInsn);
+ if (Location.getReg()) {
+ addAddress(VariableDie, dwarf::DW_AT_location, Location);
+ if (DVLabel)
+ addLabel(VariableDie, dwarf::DW_AT_start_scope, dwarf::DW_FORM_addr,
+ DVLabel);
+ updated = true;
}
}
- }
+ if (!updated) {
+ // If variableDie is not updated then DBG_VALUE instruction does not
+ // have valid variable info.
+ delete VariableDie;
+ return NULL;
+ }
+ DV->setDIE(VariableDie);
+ return VariableDie;
+ }
- if (Tag == dwarf::DW_TAG_formal_parameter && VD.getType().isArtificial())
- addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1);
+ // .. else use frame index, if available.
+ MachineLocation Location;
+ unsigned FrameReg;
+ const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
+ int FI = 0;
+ if (findVariableFrameIndex(DV, &FI)) {
+ int Offset = RI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
+ Location.set(FrameReg, Offset);
+
+ 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;
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);
///
void DwarfDebug::endModule() {
if (!FirstCU) return;
+ const Module *M = MMI->getModule();
+ if (NamedMDNode *AllSPs = M->getNamedMetadata("llvm.dbg.sp")) {
+ for (unsigned SI = 0, SE = AllSPs->getNumOperands(); SI != SE; ++SI) {
+ if (ProcessedSPNodes.count(AllSPs->getOperand(SI)) != 0) continue;
+ DISubprogram SP(AllSPs->getOperand(SI));
+ if (!SP.Verify()) continue;
+
+ // Collect info for variables that were optimized out.
+ StringRef FName = SP.getLinkageName();
+ if (FName.empty())
+ FName = SP.getName();
+ NamedMDNode *NMD =
+ M->getNamedMetadata(Twine("llvm.dbg.lv.", getRealLinkageName(FName)));
+ if (!NMD) continue;
+ unsigned E = NMD->getNumOperands();
+ if (!E) continue;
+ DbgScope *Scope = new DbgScope(NULL, DIDescriptor(SP), NULL);
+ for (unsigned I = 0; I != E; ++I) {
+ DIVariable DV(NMD->getOperand(I));
+ if (!DV.Verify()) continue;
+ Scope->addVariable(new DbgVariable(DV));
+ }
+
+ // Construct subprogram DIE and add variables DIEs.
+ constructSubprogramDIE(SP);
+ DIE *ScopeDIE = getCompileUnit(SP)->getDIE(SP);
+ const SmallVector<DbgVariable *, 8> &Variables = Scope->getVariables();
+ for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
+ DIE *VariableDIE = constructVariableDIE(Variables[i], Scope);
+ if (VariableDIE)
+ ScopeDIE->addChild(VariableDIE);
+ }
+ }
+ }
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
// 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();
}
}
+/// isDbgValueInUndefinedReg - Return true if debug value, encoded by
+/// DBG_VALUE instruction, is in undefined reg.
+static bool isDbgValueInUndefinedReg(const MachineInstr *MI) {
+ assert (MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
+ if (MI->getOperand(0).isReg() && !MI->getOperand(0).getReg())
+ return true;
+ return false;
+}
+
+/// isDbgValueInDefinedReg - Return true if debug value, encoded by
+/// DBG_VALUE instruction, is in a defined reg.
+static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
+ assert (MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
+ if (MI->getOperand(0).isReg() && MI->getOperand(0).getReg())
+ return true;
+ return false;
+}
+
/// collectVariableInfo - Populate DbgScope entries with variables' info.
-void DwarfDebug::collectVariableInfo(const MachineFunction *MF) {
- SmallPtrSet<const MDNode *, 16> Processed;
+void
+DwarfDebug::collectVariableInfo(const MachineFunction *MF,
+ SmallPtrSet<const MDNode *, 16> &Processed) {
/// collection info from MMI table.
collectVariableInfoFromMMITable(MF, Processed);
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
- if (!MInsn->isDebugValue())
- continue;
-
- // Ignore Undef values.
- if (MInsn->getOperand(0).isReg() && !MInsn->getOperand(0).getReg())
+ if (!MInsn->isDebugValue() || isDbgValueInUndefinedReg(MInsn))
continue;
-
DbgValues.push_back(MInsn);
}
+ // This is a collection of DBV_VALUE instructions describing same variable.
+ SmallVector<const MachineInstr *, 4> MultipleValues;
for(SmallVector<const MachineInstr *, 8>::iterator I = DbgValues.begin(),
E = DbgValues.end(); I != E; ++I) {
const MachineInstr *MInsn = *I;
-
+ MultipleValues.clear();
+ if (isDbgValueInDefinedReg(MInsn))
+ MultipleValues.push_back(MInsn);
DIVariable DV(MInsn->getOperand(MInsn->getNumOperands() - 1).getMetadata());
if (Processed.count(DV) != 0)
continue;
+ const MachineInstr *PrevMI = MInsn;
+ for (SmallVector<const MachineInstr *, 8>::iterator MI = I+1,
+ ME = DbgValues.end(); MI != ME; ++MI) {
+ const MDNode *Var =
+ (*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata();
+ if (Var == DV && isDbgValueInDefinedReg(*MI) &&
+ !PrevMI->isIdenticalTo(*MI))
+ MultipleValues.push_back(*MI);
+ PrevMI = *MI;
+ }
+
DbgScope *Scope = findDbgScope(MInsn);
- if (!Scope && DV.getTag() == dwarf::DW_TAG_arg_variable)
+ bool CurFnArg = false;
+ if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
+ DISubprogram(DV.getContext()).describes(MF->getFunction()))
+ CurFnArg = true;
+ if (!Scope && CurFnArg)
Scope = CurrentFnDbgScope;
// If variable scope is not found then skip this variable.
if (!Scope)
Processed.insert(DV);
DbgVariable *RegVar = new DbgVariable(DV);
- DbgVariableToDbgInstMap[RegVar] = MInsn;
Scope->addVariable(RegVar);
- if (DV.getTag() != dwarf::DW_TAG_arg_variable)
- DbgValueStartMap[MInsn] = RegVar;
+ if (!CurFnArg)
+ DbgVariableLabelsMap[RegVar] = getLabelBeforeInsn(MInsn);
if (DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc())) {
DbgVariableToDbgInstMap[AbsVar] = MInsn;
VarToAbstractVarMap[RegVar] = AbsVar;
}
+ if (MultipleValues.size() <= 1) {
+ DbgVariableToDbgInstMap[RegVar] = MInsn;
+ continue;
+ }
+
+ // handle multiple DBG_VALUE instructions describing one variable.
+ if (DotDebugLocEntries.empty())
+ RegVar->setDotDebugLocOffset(0);
+ else
+ RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
+ const MachineInstr *Begin = NULL;
+ const MachineInstr *End = NULL;
+ for (SmallVector<const MachineInstr *, 4>::iterator
+ MVI = MultipleValues.begin(), MVE = MultipleValues.end();
+ MVI != MVE; ++MVI) {
+ if (!Begin) {
+ Begin = *MVI;
+ continue;
+ }
+ End = *MVI;
+ MachineLocation MLoc;
+ MLoc.set(Begin->getOperand(0).getReg(), 0);
+ const MCSymbol *FLabel = getLabelBeforeInsn(Begin);
+ const MCSymbol *SLabel = getLabelBeforeInsn(End);
+ DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc));
+ Begin = End;
+ if (MVI + 1 == MVE) {
+ // If End is the last instruction then its value is valid
+ // until the end of the funtion.
+ MLoc.set(End->getOperand(0).getReg(), 0);
+ DotDebugLocEntries.
+ push_back(DotDebugLocEntry(SLabel, FunctionEndSym, MLoc));
+ }
+ }
+ DotDebugLocEntries.push_back(DotDebugLocEntry());
}
// Collect info for variables that were optimized out.
+ const Function *F = MF->getFunction();
+ const Module *M = F->getParent();
if (NamedMDNode *NMD =
- MF->getFunction()->getParent()->getNamedMetadata("llvm.dbg.lv")) {
+ M->getNamedMetadata(Twine("llvm.dbg.lv.",
+ getRealLinkageName(F->getName())))) {
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIVariable DV(cast_or_null<MDNode>(NMD->getOperand(i)));
if (!DV || !Processed.insert(DV))
Scope->addVariable(new DbgVariable(DV));
}
}
+}
+/// getLabelBeforeInsn - Return Label preceding the instruction.
+const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
+ DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
+ LabelsBeforeInsn.find(MI);
+ if (I == LabelsBeforeInsn.end())
+ // FunctionBeginSym always preceeds all the instruction in current function.
+ return FunctionBeginSym;
+ return I->second;
+}
+
+/// getLabelAfterInsn - Return Label immediately following the instruction.
+const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
+ DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
+ LabelsAfterInsn.find(MI);
+ if (I == LabelsAfterInsn.end())
+ return NULL;
+ return I->second;
}
/// beginScope - Process beginning of a scope.
void DwarfDebug::beginScope(const MachineInstr *MI) {
- // Check location.
- DebugLoc DL = MI->getDebugLoc();
- if (DL.isUnknown()) {
- if (UnknownLocations) {
- // This instruction has no debug location. If the preceding instruction
- // did, emit debug location information to indicate that the debug
- // location is now unknown.
- MCSymbol *Label = NULL;
- if (DL == PrevInstLoc)
- Label = PrevLabel;
- else {
- Label = recordSourceLine(DL.getLine(), DL.getCol(), 0);
- PrevInstLoc = DL;
- PrevLabel = Label;
- }
-
- // If this instruction begins a scope then note down corresponding label
- // even if previous label is reused.
- if (InsnsBeginScopeSet.count(MI) != 0)
- LabelsBeforeInsn[MI] = Label;
- }
-
+ if (InsnNeedsLabel.count(MI) == 0) {
+ LabelsBeforeInsn[MI] = PrevLabel;
return;
}
- const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext());
-
- // FIXME: Should only verify each scope once!
- if (!DIScope(Scope).Verify())
+ // Check location.
+ DebugLoc DL = MI->getDebugLoc();
+ if (!DL.isUnknown()) {
+ const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext());
+ PrevLabel = recordSourceLine(DL.getLine(), DL.getCol(), Scope);
+ PrevInstLoc = DL;
+ LabelsBeforeInsn[MI] = PrevLabel;
return;
+ }
- // DBG_VALUE instruction establishes new value.
+ // If location is unknown then use temp label for this DBG_VALUE
+ // instruction.
if (MI->isDebugValue()) {
- DenseMap<const MachineInstr *, DbgVariable *>::iterator DI
- = DbgValueStartMap.find(MI);
- if (DI != DbgValueStartMap.end()) {
- MCSymbol *Label = NULL;
- if (DL == PrevInstLoc)
- Label = PrevLabel;
- else {
- Label = recordSourceLine(DL.getLine(), DL.getCol(), Scope);
- PrevInstLoc = DL;
- PrevLabel = Label;
- }
- DbgVariableLabelsMap[DI->second] = Label;
- }
+ PrevLabel = MMI->getContext().CreateTempSymbol();
+ Asm->OutStreamer.EmitLabel(PrevLabel);
+ LabelsBeforeInsn[MI] = PrevLabel;
return;
}
- // Emit a label to indicate location change. This is used for line
- // table even if this instruction does not start a new scope.
- MCSymbol *Label = NULL;
- if (DL == PrevInstLoc)
- Label = PrevLabel;
- else {
- Label = recordSourceLine(DL.getLine(), DL.getCol(), Scope);
- PrevInstLoc = DL;
- PrevLabel = Label;
+ if (UnknownLocations) {
+ PrevLabel = recordSourceLine(0, 0, 0);
+ LabelsBeforeInsn[MI] = PrevLabel;
+ return;
}
- // If this instruction begins a scope then note down corresponding label
- // even if previous label is reused.
- if (InsnsBeginScopeSet.count(MI) != 0)
- LabelsBeforeInsn[MI] = Label;
+ assert (0 && "Instruction is not processed!");
}
/// endScope - Process end of a scope.
}
/// 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)
if (!WScope->getParent()) {
StringRef SPName = DISubprogram(Scope).getLinkageName();
- if (SPName == Asm->MF->getFunction()->getName())
+ // We used to check only for a linkage name, but that fails
+ // since we began omitting the linkage name for private
+ // functions. The new way is to check for the name in metadata,
+ // but that's not supported in old .ll test cases. Ergo, we
+ // check both.
+ if (SPName == Asm->MF->getFunction()->getName() ||
+ DISubprogram(Scope).getFunction() == Asm->MF->getFunction())
CurrentFnDbgScope = WScope;
}
return WScope;
}
+ getOrCreateAbstractScope(Scope);
DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
if (WScope)
return WScope;
Parent->addScope(WScope);
ConcreteScopes[InlinedAt] = WScope;
- getOrCreateAbstractScope(Scope);
return WScope;
}
static bool hasValidLocation(LLVMContext &Ctx,
const MachineInstr *MInsn,
const MDNode *&Scope, const MDNode *&InlinedAt) {
- if (MInsn->isDebugValue())
- return false;
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) return false;
// 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);
}
RE = Ranges.end(); RI != RE; ++RI) {
assert(RI->first && "DbgRange does not have first instruction!");
assert(RI->second && "DbgRange does not have second instruction!");
- InsnsBeginScopeSet.insert(RI->first);
InsnsEndScopeSet.insert(RI->second);
}
}
void DwarfDebug::beginFunction(const MachineFunction *MF) {
if (!MMI->hasDebugInfo()) return;
if (!extractScopeInformation()) return;
-
- collectVariableInfo(MF);
FunctionBeginSym = Asm->GetTempSymbol("func_begin",
Asm->getFunctionNumber());
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;
+
+ DebugLoc PrevLoc;
+ 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 *MI = II;
+ DebugLoc DL = MI->getDebugLoc();
+ if (MI->isDebugValue()) {
+ assert (MI->getNumOperands() > 1 && "Invalid machine instruction!");
+ 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
+ && isDbgValueInUndefinedReg(MI) == false)
+ InsnNeedsLabel.insert(MI);
+ // DBG_VALUE for inlined functions argument needs a label.
+ 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))
+ InsnNeedsLabel.insert(MI);
+ } else {
+ // If location is unknown then instruction needs a location only if
+ // UnknownLocations flag is set.
+ if (DL.isUnknown()) {
+ if (UnknownLocations && !PrevLoc.isUnknown())
+ InsnNeedsLabel.insert(MI);
+ } else if (DL != PrevLoc)
+ // Otherwise, instruction needs a location only if it is new location.
+ InsnNeedsLabel.insert(MI);
+ }
+
+ if (!DL.isUnknown() || UnknownLocations)
+ PrevLoc = DL;
+ }
+
+ PrevLabel = FunctionBeginSym;
}
/// endFunction - Gather and emit post-function debug information.
if (!MMI->hasDebugInfo() || DbgScopeMap.empty()) return;
if (CurrentFnDbgScope) {
+
// Define end label for subprogram.
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("func_end",
- Asm->getFunctionNumber()));
+ FunctionEndSym = Asm->GetTempSymbol("func_end",
+ Asm->getFunctionNumber());
+ // Assumes in correct section after the entry point.
+ Asm->OutStreamer.EmitLabel(FunctionEndSym);
+ SmallPtrSet<const MDNode *, 16> ProcessedVars;
+ collectVariableInfo(MF, ProcessedVars);
+
// Get function line info.
if (!Lines.empty()) {
// Get section line info.
// Construct abstract scopes.
for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
- AE = AbstractScopesList.end(); AI != AE; ++AI)
- constructScopeDIE(*AI);
-
+ AE = AbstractScopesList.end(); AI != AE; ++AI) {
+ DISubprogram SP((*AI)->getScopeNode());
+ if (SP.Verify()) {
+ // Collect info for variables that were optimized out.
+ StringRef FName = SP.getLinkageName();
+ if (FName.empty())
+ FName = SP.getName();
+ const Module *M = MF->getFunction()->getParent();
+ if (NamedMDNode *NMD =
+ M->getNamedMetadata(Twine("llvm.dbg.lv.",
+ getRealLinkageName(FName)))) {
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+ DIVariable DV(cast_or_null<MDNode>(NMD->getOperand(i)));
+ if (!DV || !ProcessedVars.insert(DV))
+ continue;
+ 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))
// Clear debug info
CurrentFnDbgScope = NULL;
+ InsnNeedsLabel.clear();
DbgVariableToFrameIndexMap.clear();
VarToAbstractVarMap.clear();
DbgVariableToDbgInstMap.clear();
DbgVariableLabelsMap.clear();
DeleteContainerSeconds(DbgScopeMap);
- InsnsBeginScopeSet.clear();
InsnsEndScopeSet.clear();
- DbgValueStartMap.clear();
ConcreteScopes.clear();
DeleteContainerSeconds(AbstractScopes);
AbstractScopesList.clear();
/// 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;
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());
DwarfDebugRangeSectionSym = EmitSectionSym(Asm, TLOF.getDwarfRangesSection(),
"debug_range");
+ DwarfDebugLocSectionSym = EmitSectionSym(Asm, TLOF.getDwarfLocSection(),
+ "section_debug_loc");
+
TextSectionSym = EmitSectionSym(Asm, TLOF.getTextSection(), "text_begin");
EmitSectionSym(Asm, TLOF.getDataSection());
}
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->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4);
+ } else
+ Values[i]->EmitValue(Asm, Form);
+ break;
+ }
default:
// Emit an attribute using the defined form.
Values[i]->EmitValue(Asm, Form);
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);
/// emitDebugLoc - Emit visible names into a debug loc section.
///
void DwarfDebug::emitDebugLoc() {
+ if (DotDebugLocEntries.empty())
+ return;
+
// Start the dwarf loc section.
Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfLocSection());
+ Asm->getObjFileLowering().getDwarfLocSection());
+ 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) {
+ DotDebugLocEntry Entry = *I;
+ if (Entry.isEmpty()) {
+ Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0);
+ Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0);
+ Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index));
+ } else {
+ Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size, 0);
+ Asm->OutStreamer.EmitSymbolValue(Entry.End, Size, 0);
+ const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
+ unsigned Reg = RI->getDwarfRegNum(Entry.Loc.getReg(), false);
+ if (Reg < 32) {
+ Asm->OutStreamer.AddComment("Loc expr size");
+ Asm->EmitInt16(1);
+ Asm->EmitInt8(dwarf::DW_OP_reg0 + Reg);
+ } else {
+ Asm->OutStreamer.AddComment("Loc expr size");
+ Asm->EmitInt16(1+MCAsmInfo::getULEB128Size(Reg));
+ Asm->EmitInt8(dwarf::DW_OP_regx);
+ Asm->EmitULEB128(Reg);
+ }
+ }
+ }
}
/// EmitDebugARanges - Emit visible names into a debug aranges section.