"llvm/lib/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "f9c1291fdedc22bf77d1a9cdba1da575bec3baf1"
Newer
Older
// Emit info into a debug ranges section.
emitDebugRanges();
// Emit info into a debug macinfo section.
emitDebugMacInfo();
// Emit inline info.
// TODO: When we don't need the option anymore we
// can remove all of the code that this section
// depends upon.
if (useDarwinGDBCompat())
emitDebugInlineInfo();
} else {
// TODO: Fill this in for separated debug sections and separate
// out information into new sections.
// Emit the debug info section and compile units.
emitDebugInfo();
emitDebugInfoDWO();
// Corresponding abbreviations into a abbrev section.
emitAbbreviations();
emitDebugAbbrevDWO();
// Emit info into a debug loc section.
emitDebugLoc();
// Emit info into a debug aranges section.
emitDebugARanges();
// Emit info into a debug ranges section.
emitDebugRanges();
// Emit info into a debug macinfo section.
emitDebugMacInfo();
// Emit DWO addresses.
InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection());
// Emit inline info.
// TODO: When we don't need the option anymore we
// can remove all of the code that this section
// depends upon.
if (useDarwinGDBCompat())
emitDebugInlineInfo();
}
if (useDwarfAccelTables()) {
Eric Christopher
committed
emitAccelNames();
emitAccelObjC();
emitAccelNamespaces();
emitAccelTypes();
}
// Emit info into a debug pubnames section, if requested.
if (GenerateDwarfPubNamesSection)
emitDebugPubnames();
// TODO: When we don't need the option anymore we can
// remove all of the code that adds to the table.
if (useDarwinGDBCompat())
emitDebugPubTypes();
// Finally emit string information into a string table.
emitDebugStr();
if (useSplitDwarf())
emitDebugStrDWO();
Devang Patel
committed
SPMap.clear();
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I)
delete I->second;
for (SmallVector<CompileUnit *, 1>::iterator I = SkeletonCUs.begin(),
E = SkeletonCUs.end(); I != E; ++I)
delete *I;
// Reset these for the next Module if we have one.
FirstCU = NULL;
// Find abstract variable, if any, associated with Var.
DebugLoc ScopeLoc) {
LLVMContext &Ctx = DV->getContext();
// More then one inlined variable corresponds to one abstract variable.
DIVariable Var = cleanseInlinedVariable(DV, Ctx);
DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
Devang Patel
committed
if (AbsDbgVariable)
return AbsDbgVariable;
LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx));
Devang Patel
committed
if (!Scope)
return NULL;
AbsDbgVariable = new DbgVariable(Var, NULL);
addScopeVariable(Scope, AbsDbgVariable);
AbstractVariables[Var] = AbsDbgVariable;
Devang Patel
committed
return AbsDbgVariable;
}
// If Var is a current function argument then add it to CurrentFnArguments list.
Devang Patel
committed
bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
DbgVariable *Var, LexicalScope *Scope) {
if (!LScopes.isCurrentFunctionScope(Scope))
Devang Patel
committed
return false;
DIVariable DV = Var->getVariable();
if (DV.getTag() != dwarf::DW_TAG_arg_variable)
return false;
unsigned ArgNo = DV.getArgNumber();
Devang Patel
committed
return false;
Devang Patel
committed
size_t Size = CurrentFnArguments.size();
if (Size == 0)
Devang Patel
committed
CurrentFnArguments.resize(MF->getFunction()->arg_size());
// llvm::Function argument size is not good indicator of how many
// arguments does the function have at source level.
if (ArgNo > Size)
Devang Patel
committed
CurrentFnArguments.resize(ArgNo * 2);
Devang Patel
committed
CurrentFnArguments[ArgNo - 1] = Var;
return true;
}
// Collect variable information from side table maintained by MMI.
Nick Lewycky
committed
DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF,
MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
VE = VMap.end(); VI != VE; ++VI) {
Devang Patel
committed
Processed.insert(Var);
DIVariable DV(Var);
const std::pair<unsigned, DebugLoc> &VP = VI->second;
LexicalScope *Scope = LScopes.findLexicalScope(VP.second);
// If variable scope is not found then skip this variable.
if (Scope == 0)
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second);
DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable);
Devang Patel
committed
RegVar->setFrameIndex(VP.first);
Devang Patel
committed
if (!addCurrentFnArgument(MF, RegVar, Scope))
addScopeVariable(Scope, RegVar);
if (AbsDbgVariable)
Devang Patel
committed
AbsDbgVariable->setFrameIndex(VP.first);
}
// Return true if debug value, encoded by DBG_VALUE instruction, is in a
// defined reg.
static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
Nick Lewycky
committed
assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
return MI->getNumOperands() == 3 &&
MI->getOperand(0).isReg() && MI->getOperand(0).getReg() &&
Adrian Prantl
committed
MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0;
// Get .debug_loc entry for the instruction range starting at MI.
static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
const MCSymbol *FLabel,
const MCSymbol *SLabel,
const MachineInstr *MI) {
const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata();
if (MI->getNumOperands() != 3) {
MachineLocation MLoc = Asm->getDebugValueLocation(MI);
return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
}
Adrian Prantl
committed
if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) {
Adrian Prantl
committed
// TODO: Currently an offset of 0 in a DBG_VALUE means
// we need to generate a direct register value.
// There is no way to specify an indirect value with offset 0.
if (MI->getOperand(1).getImm() == 0)
MLoc.set(MI->getOperand(0).getReg());
else
MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
}
if (MI->getOperand(0).isImm())
return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm());
if (MI->getOperand(0).isFPImm())
return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm());
if (MI->getOperand(0).isCImm())
return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm());
llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!");
// Find variables for each lexical scope.
DwarfDebug::collectVariableInfo(const MachineFunction *MF,
SmallPtrSet<const MDNode *, 16> &Processed) {
// collection info from MMI table.
Devang Patel
committed
Jakob Stoklund Olesen
committed
for (SmallVectorImpl<const MDNode*>::const_iterator
UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI != UVE;
++UVI) {
const MDNode *Var = *UVI;
if (Processed.count(Var))
Devang Patel
committed
Jakob Stoklund Olesen
committed
// History contains relevant DBG_VALUE instructions for Var and instructions
// clobbering it.
SmallVectorImpl<const MachineInstr*> &History = DbgValues[Var];
if (History.empty())
continue;
const MachineInstr *MInsn = History.front();
Jakob Stoklund Olesen
committed
DIVariable DV(Var);
LexicalScope *Scope = NULL;
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(DV.getContext()).describes(MF->getFunction()))
Scope = LScopes.getCurrentFunctionScope();
else if (MDNode *IA = DV.getInlinedAt())
Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA));
else
Scope = LScopes.findLexicalScope(cast<MDNode>(DV->getOperand(1)));
Jakob Stoklund Olesen
committed
assert(MInsn->isDebugValue() && "History must begin with debug value");
DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc());
DbgVariable *RegVar = new DbgVariable(DV, AbsVar);
Devang Patel
committed
if (!addCurrentFnArgument(MF, RegVar, Scope))
addScopeVariable(Scope, RegVar);
if (AbsVar)
Devang Patel
committed
AbsVar->setMInsn(MInsn);
Jakob Stoklund Olesen
committed
Jakob Stoklund Olesen
committed
if (History.size() <= 1 || (History.size() == 2 &&
MInsn->isIdenticalTo(History.back()))) {
Devang Patel
committed
RegVar->setMInsn(MInsn);
// Handle multiple DBG_VALUE instructions describing one variable.
Jakob Stoklund Olesen
committed
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
Jakob Stoklund Olesen
committed
for (SmallVectorImpl<const MachineInstr*>::const_iterator
HI = History.begin(), HE = History.end(); HI != HE; ++HI) {
const MachineInstr *Begin = *HI;
assert(Begin->isDebugValue() && "Invalid History entry");
// Check if DBG_VALUE is truncating a range.
if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg()
&& !Begin->getOperand(0).getReg())
continue;
// Compute the range for a register location.
const MCSymbol *FLabel = getLabelBeforeInsn(Begin);
const MCSymbol *SLabel = 0;
Jakob Stoklund Olesen
committed
if (HI + 1 == HE)
// If Begin is the last instruction in History then its value is valid
// until the end of the function.
SLabel = FunctionEndSym;
Jakob Stoklund Olesen
committed
else {
const MachineInstr *End = HI[1];
Jakob Stoklund Olesen
committed
if (End->isDebugValue())
SLabel = getLabelBeforeInsn(End);
else {
// End is a normal instruction clobbering the range.
SLabel = getLabelAfterInsn(End);
assert(SLabel && "Forgot label after clobber instruction");
++HI;
}
}
Jakob Stoklund Olesen
committed
// The value is valid until the next DBG_VALUE or clobber.
DotDebugLocEntries.push_back(getDebugLocEntry(Asm, FLabel, SLabel,
Begin));
}
DotDebugLocEntries.push_back(DotDebugLocEntry());
Devang Patel
committed
}
Devang Patel
committed
// Collect info for variables that were optimized out.
Devang Patel
committed
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables();
for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
DIVariable DV(Variables.getElement(i));
if (!DV || !DV.Verify() || !Processed.insert(DV))
continue;
if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext()))
addScopeVariable(Scope, new DbgVariable(DV, NULL));
Devang Patel
committed
}
// Return Label preceding the instruction.
MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
Jakob Stoklund Olesen
committed
MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
assert(Label && "Didn't insert label before instruction");
return Label;
Devang Patel
committed
// Return Label immediately following the instruction.
MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
Jakob Stoklund Olesen
committed
return LabelsAfterInsn.lookup(MI);
}
// Process beginning of an instruction.
void DwarfDebug::beginInstruction(const MachineInstr *MI) {
Jakob Stoklund Olesen
committed
// Check if source location changes, but ignore DBG_VALUE locations.
if (!MI->isDebugValue()) {
DebugLoc DL = MI->getDebugLoc();
if (DL != PrevInstLoc && (!DL.isUnknown() || UnknownLocations)) {
unsigned Flags = 0;
Jakob Stoklund Olesen
committed
PrevInstLoc = DL;
if (DL == PrologEndLoc) {
Flags |= DWARF2_FLAG_PROLOGUE_END;
PrologEndLoc = DebugLoc();
}
if (PrologEndLoc.isUnknown())
Flags |= DWARF2_FLAG_IS_STMT;
Jakob Stoklund Olesen
committed
if (!DL.isUnknown()) {
const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext());
recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
Jakob Stoklund Olesen
committed
} else
recordSourceLine(0, 0, 0, 0);
Jakob Stoklund Olesen
committed
}
}
Jakob Stoklund Olesen
committed
// Insert labels where requested.
Jakob Stoklund Olesen
committed
DenseMap<const MachineInstr*, MCSymbol*>::iterator I =
LabelsBeforeInsn.find(MI);
// No label needed.
if (I == LabelsBeforeInsn.end())
return;
// Label already assigned.
if (I->second)
Devang Patel
committed
return;
Jakob Stoklund Olesen
committed
if (!PrevLabel) {
Devang Patel
committed
PrevLabel = MMI->getContext().CreateTempSymbol();
Asm->OutStreamer.EmitLabel(PrevLabel);
Devang Patel
committed
}
Jakob Stoklund Olesen
committed
I->second = PrevLabel;
// Process end of an instruction.
void DwarfDebug::endInstruction(const MachineInstr *MI) {
Jakob Stoklund Olesen
committed
// Don't create a new label after DBG_VALUE instructions.
// They don't generate code.
if (!MI->isDebugValue())
PrevLabel = 0;
Jakob Stoklund Olesen
committed
DenseMap<const MachineInstr*, MCSymbol*>::iterator I =
LabelsAfterInsn.find(MI);
// No label needed.
if (I == LabelsAfterInsn.end())
return;
// Label already assigned.
if (I->second)
Jakob Stoklund Olesen
committed
return;
// We need a label after this instruction.
if (!PrevLabel) {
PrevLabel = MMI->getContext().CreateTempSymbol();
Asm->OutStreamer.EmitLabel(PrevLabel);
Jakob Stoklund Olesen
committed
I->second = PrevLabel;
// Each LexicalScope has first instruction and last instruction to mark
// beginning and end of a scope respectively. Create an inverse map that list
// scopes starts (and ends) with an instruction. One instruction may start (or
// end) multiple scopes. Ignore scopes that are not reachable.
SmallVector<LexicalScope *, 4> WorkList;
WorkList.push_back(LScopes.getCurrentFunctionScope());
Devang Patel
committed
while (!WorkList.empty()) {
LexicalScope *S = WorkList.pop_back_val();
const SmallVector<LexicalScope *, 4> &Children = S->getChildren();
for (SmallVector<LexicalScope *, 4>::const_iterator SI = Children.begin(),
Devang Patel
committed
SE = Children.end(); SI != SE; ++SI)
WorkList.push_back(*SI);
if (S->isAbstractScope())
continue;
const SmallVector<InsnRange, 4> &Ranges = S->getRanges();
Devang Patel
committed
if (Ranges.empty())
continue;
for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
Devang Patel
committed
RE = Ranges.end(); RI != RE; ++RI) {
assert(RI->first && "InsnRange does not have first instruction!");
assert(RI->second && "InsnRange does not have second instruction!");
Jakob Stoklund Olesen
committed
requestLabelBeforeInsn(RI->first);
requestLabelAfterInsn(RI->second);
Devang Patel
committed
}
Devang Patel
committed
}
}
// Get MDNode for DebugLoc's scope.
Devang Patel
committed
static MDNode *getScopeNode(DebugLoc DL, const LLVMContext &Ctx) {
if (MDNode *InlinedAt = DL.getInlinedAt(Ctx))
return getScopeNode(DebugLoc::getFromDILocation(InlinedAt), Ctx);
return DL.getScope(Ctx);
}
// Walk up the scope chain of given debug loc and find line number info
// for the function.
static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) {
const MDNode *Scope = getScopeNode(DL, Ctx);
DISubprogram SP = getDISubprogram(Scope);
if (SP.Verify()) {
// Check for number of operands since the compatibility is
// cheap here.
if (SP->getNumOperands() > 19)
return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);
else
return DebugLoc::get(SP.getLineNumber(), 0, SP);
}
return DebugLoc();
}
// Gather pre-function debug information. Assumes being called immediately
// after the function entry point has been emitted.
void DwarfDebug::beginFunction(const MachineFunction *MF) {
Chris Lattner
committed
if (!MMI->hasDebugInfo()) return;
LScopes.initialize(*MF);
if (LScopes.empty()) return;
identifyScopeMarkers();
Manman Ren
committed
// Set DwarfCompileUnitID in MCContext to the Compile Unit this function
// belongs to.
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
assert(TheCU && "Unable to find compile unit!");
if (Asm->TM.hasMCUseLoc() &&
Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer)
// Use a single line table if we are using .loc and generating assembly.
Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
else
Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID());
Manman Ren
committed
Devang Patel
committed
FunctionBeginSym = Asm->GetTempSymbol("func_begin",
Asm->getFunctionNumber());
// Assumes in correct section after the entry point.
Devang Patel
committed
Asm->OutStreamer.EmitLabel(FunctionBeginSym);
Jakob Stoklund Olesen
committed
assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned");
const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
// LiveUserVar - Map physreg numbers to the MDNode they contain.
std::vector<const MDNode*> LiveUserVar(TRI->getNumRegs());
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
Jakob Stoklund Olesen
committed
I != E; ++I) {
bool AtBlockEntry = true;
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MI = II;
Jakob Stoklund Olesen
committed
if (MI->isDebugValue()) {
Nick Lewycky
committed
assert(MI->getNumOperands() > 1 && "Invalid machine instruction!");
Jakob Stoklund Olesen
committed
// Keep track of user variables.
const MDNode *Var =
MI->getOperand(MI->getNumOperands() - 1).getMetadata();
Jakob Stoklund Olesen
committed
// Variable is in a register, we need to check for clobbers.
if (isDbgValueInDefinedReg(MI))
LiveUserVar[MI->getOperand(0).getReg()] = Var;
Jakob Stoklund Olesen
committed
// Check the history of this variable.
SmallVectorImpl<const MachineInstr*> &History = DbgValues[Var];
if (History.empty()) {
UserVariables.push_back(Var);
// The first mention of a function argument gets the FunctionBeginSym
// label, so arguments are visible when breaking at function entry.
DIVariable DV(Var);
if (DV.Verify() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(getDISubprogram(DV.getContext()))
.describes(MF->getFunction()))
LabelsBeforeInsn[MI] = FunctionBeginSym;
} else {
// We have seen this variable before. Try to coalesce DBG_VALUEs.
const MachineInstr *Prev = History.back();
if (Prev->isDebugValue()) {
// Coalesce identical entries at the end of History.
if (History.size() >= 2 &&
DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
Jakob Stoklund Olesen
committed
History.pop_back();
Jakob Stoklund Olesen
committed
// Terminate old register assignments that don't reach MI;
MachineFunction::const_iterator PrevMBB = Prev->getParent();
if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB) != I) &&
isDbgValueInDefinedReg(Prev)) {
// Previous register assignment needs to terminate at the end of
// its basic block.
MachineBasicBlock::const_iterator LastMI =
PrevMBB->getLastNonDebugInstr();
Jakob Stoklund Olesen
committed
// Drop DBG_VALUE for empty range.
DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
Jakob Stoklund Olesen
committed
History.pop_back();
Jakob Stoklund Olesen
committed
else {
// Terminate after LastMI.
History.push_back(LastMI);
}
}
}
}
History.push_back(MI);
} else {
Jakob Stoklund Olesen
committed
// Not a DBG_VALUE instruction.
if (!MI->isLabel())
AtBlockEntry = false;
// First known non-DBG_VALUE and non-frame setup location marks
// the beginning of the function body.
if (!MI->getFlag(MachineInstr::FrameSetup) &&
(PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown()))
PrologEndLoc = MI->getDebugLoc();
// Check if the instruction clobbers any registers with debug vars.
for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(),
MOE = MI->operands_end(); MOI != MOE; ++MOI) {
if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg())
continue;
for (MCRegAliasIterator AI(MOI->getReg(), TRI, true);
AI.isValid(); ++AI) {
unsigned Reg = *AI;
const MDNode *Var = LiveUserVar[Reg];
if (!Var)
continue;
// Reg is now clobbered.
LiveUserVar[Reg] = 0;
// Was MD last defined by a DBG_VALUE referring to Reg?
Jakob Stoklund Olesen
committed
DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);
if (HistI == DbgValues.end())
continue;
SmallVectorImpl<const MachineInstr*> &History = HistI->second;
if (History.empty())
Jakob Stoklund Olesen
committed
const MachineInstr *Prev = History.back();
// Sanity-check: Register assignments are terminated at the end of
// their block.
if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent())
Jakob Stoklund Olesen
committed
// Is the variable still in Reg?
if (!isDbgValueInDefinedReg(Prev) ||
Prev->getOperand(0).getReg() != Reg)
continue;
// Var is clobbered. Make sure the next instruction gets a label.
History.push_back(MI);
}
}
Jakob Stoklund Olesen
committed
}
for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end();
I != E; ++I) {
SmallVectorImpl<const MachineInstr*> &History = I->second;
if (History.empty())
continue;
// Make sure the final register assignments are terminated.
const MachineInstr *Prev = History.back();
if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {
const MachineBasicBlock *PrevMBB = Prev->getParent();
Jakob Stoklund Olesen
committed
if (LastMI == PrevMBB->end())
// Drop DBG_VALUE for empty range.
History.pop_back();
else {
// Terminate after LastMI.
History.push_back(LastMI);
}
}
// Request labels for the full history.
for (unsigned i = 0, e = History.size(); i != e; ++i) {
const MachineInstr *MI = History[i];
if (MI->isDebugValue())
requestLabelBeforeInsn(MI);
else
requestLabelAfterInsn(MI);
}
}
Jakob Stoklund Olesen
committed
PrevInstLoc = DebugLoc();
PrevLabel = FunctionBeginSym;
// Record beginning of function.
if (!PrologEndLoc.isUnknown()) {
DebugLoc FnStartDL = getFnDebugLoc(PrologEndLoc,
MF->getFunction()->getContext());
recordSourceLine(FnStartDL.getLine(), FnStartDL.getCol(),
FnStartDL.getScope(MF->getFunction()->getContext()),
// We'd like to list the prologue as "not statements" but GDB behaves
// poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
David Blaikie
committed
DWARF2_FLAG_IS_STMT);
void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
DIVariable DV = Var->getVariable();
if (DV.getTag() == dwarf::DW_TAG_arg_variable) {
DISubprogram Ctxt(DV.getContext());
DIArray Variables = Ctxt.getVariables();
// If the variable is a parameter (arg_variable) and this is an optimized
// build (the subprogram has a 'variables' list) make sure we keep the
// parameters in order. Otherwise we would produce an incorrect function
// type with parameters out of order if function parameters were used out of
// order or unused (see the call to addScopeVariable in endFunction where
// the remaining unused variables (including parameters) are added).
if (unsigned NumVariables = Variables.getNumElements()) {
// Keep the parameters at the start of the variables list. Search through
// current variable list (Vars) and the full function variable list in
// lock-step looking for this parameter in the full list to find the
// insertion point.
SmallVectorImpl<DbgVariable *>::iterator I = Vars.begin();
unsigned j = 0;
while (I != Vars.end() && j != NumVariables &&
Variables.getElement(j) != DV &&
(*I)->getVariable().getTag() == dwarf::DW_TAG_arg_variable) {
if (Variables.getElement(j) == (*I)->getVariable())
++I;
++j;
}
Vars.insert(I, Var);
return;
}
}
Vars.push_back(Var);
}
// Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
if (!MMI->hasDebugInfo() || LScopes.empty()) return;
Devang Patel
committed
// Define end label for subprogram.
FunctionEndSym = Asm->GetTempSymbol("func_end",
Asm->getFunctionNumber());
// Assumes in correct section after the entry point.
Asm->OutStreamer.EmitLabel(FunctionEndSym);
Manman Ren
committed
// Set DwarfCompileUnitID in MCContext to default value.
Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
SmallPtrSet<const MDNode *, 16> ProcessedVars;
collectVariableInfo(MF, ProcessedVars);
Devang Patel
committed
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
Devang Patel
committed
CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
Nick Lewycky
committed
assert(TheCU && "Unable to find compile unit!");
Devang Patel
committed
// Construct abstract scopes.
ArrayRef<LexicalScope *> AList = LScopes.getAbstractScopesList();
for (unsigned i = 0, e = AList.size(); i != e; ++i) {
LexicalScope *AScope = AList[i];
DISubprogram SP(AScope->getScopeNode());
if (SP.Verify()) {
// Collect info for variables that were optimized out.
Devang Patel
committed
DIArray Variables = SP.getVariables();
for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
DIVariable DV(Variables.getElement(i));
if (!DV || !DV.Verify() || !ProcessedVars.insert(DV))
continue;
// Check that DbgVariable for DV wasn't created earlier, when
// findAbstractVariable() was called for inlined instance of DV.
LLVMContext &Ctx = DV->getContext();
DIVariable CleanDV = cleanseInlinedVariable(DV, Ctx);
if (AbstractVariables.lookup(CleanDV))
continue;
Devang Patel
committed
if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext()))
addScopeVariable(Scope, new DbgVariable(DV, NULL));
}
}
}
Devang Patel
committed
DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope);
Nick Lewycky
committed
if (!MF->getTarget().Options.DisableFramePointerElim(*MF))
TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr);
Devang Patel
committed
for (DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8> >::iterator
I = ScopeVariables.begin(), E = ScopeVariables.end(); I != E; ++I)
DeleteContainerPointers(I->second);
ScopeVariables.clear();
DeleteContainerPointers(CurrentFnArguments);
Jakob Stoklund Olesen
committed
UserVariables.clear();
DbgValues.clear();
Jeffrey Yasskin
committed
AbstractVariables.clear();
Devang Patel
committed
LabelsBeforeInsn.clear();
LabelsAfterInsn.clear();
// Register a source line with debug info. Returns the unique label that was
// emitted and which provides correspondence to the source line list.
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
unsigned Flags) {
Devang Patel
committed
StringRef Dir;
unsigned Src = 1;
if (S) {
DIDescriptor Scope(S);
if (Scope.isCompileUnit()) {
DICompileUnit CU(S);
Fn = CU.getFilename();
Devang Patel
committed
Dir = CU.getDirectory();
} else if (Scope.isFile()) {
DIFile F(S);
Fn = F.getFilename();
Devang Patel
committed
Dir = F.getDirectory();
} else if (Scope.isSubprogram()) {
DISubprogram SP(S);
Fn = SP.getFilename();
Devang Patel
committed
Dir = SP.getDirectory();
} else if (Scope.isLexicalBlockFile()) {
DILexicalBlockFile DBF(S);
Fn = DBF.getFilename();
Dir = DBF.getDirectory();
} else if (Scope.isLexicalBlock()) {
DILexicalBlock DB(S);
Fn = DB.getFilename();
Devang Patel
committed
Dir = DB.getDirectory();
} else
llvm_unreachable("Unexpected scope info");
Src = getOrCreateSourceID(Fn, Dir,
Asm->OutStreamer.getContext().getDwarfCompileUnitID());
Nick Lewycky
committed
Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn);
//===----------------------------------------------------------------------===//
// Emit Methods
//===----------------------------------------------------------------------===//
// Compute the size and offset of a DIE.
DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) {
// Get the children.
const std::vector<DIE *> &Children = Die->getChildren();
// Record the abbreviation.
assignAbbrevNumber(Die->getAbbrev());
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
const DIEAbbrev *Abbrev = Abbreviations->at(AbbrevNumber - 1);
// Set DIE offset
Die->setOffset(Offset);
// Start the size with the size of abbreviation code.
Offset += MCAsmInfo::getULEB128Size(AbbrevNumber);
const SmallVectorImpl<DIEValue*> &Values = Die->getValues();
const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData();
// Size the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i)
// Size attribute value.
Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
// Size the DIE children if any.
if (!Children.empty()) {
assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes &&
"Children flag not set");
for (unsigned j = 0, M = Children.size(); j < M; ++j)
Offset = computeSizeAndOffset(Children[j], Offset);
// End of children marker.
Offset += sizeof(int8_t);
}
Die->setSize(Offset - Die->getOffset());
return Offset;
// Compute the size and offset of all the DIEs.
void DwarfUnits::computeSizeAndOffsets() {
// Offset from the beginning of debug info section.
for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I) {
(*I)->setDebugInfoOffset(SecOffset);
unsigned Offset =
sizeof(int32_t) + // Length of Compilation Unit Info
sizeof(int16_t) + // DWARF version number
sizeof(int32_t) + // Offset Into Abbrev. Section
sizeof(int8_t); // Pointer Size (in bytes)
unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset);
// Emit initial Dwarf sections with a label at the start of each one.
void DwarfDebug::emitSectionLabels() {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
// Dwarf sections base addresses.
emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
if (useSplitDwarf())
DwarfAbbrevDWOSectionSym =
emitSectionSym(Asm, TLOF.getDwarfAbbrevDWOSection(),
"section_abbrev_dwo");
emitSectionSym(Asm, TLOF.getDwarfARangesSection());
if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection())
emitSectionSym(Asm, MacroInfo);
DwarfLineSectionSym =
emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
emitSectionSym(Asm, TLOF.getDwarfLocSection());
if (GenerateDwarfPubNamesSection)
emitSectionSym(Asm, TLOF.getDwarfPubNamesSection());
emitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string");
if (useSplitDwarf()) {
DwarfStrDWOSectionSym =
emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
DwarfAddrSectionSym =
emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
}
DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(),
DwarfDebugLocSectionSym = emitSectionSym(Asm, TLOF.getDwarfLocSection(),
TextSectionSym = emitSectionSym(Asm, TLOF.getTextSection(), "text_begin");
emitSectionSym(Asm, TLOF.getDataSection());
Bill Wendling
committed
}
// Recursively emits a debug information entry.
void DwarfDebug::emitDIE(DIE *Die, std::vector<DIEAbbrev *> *Abbrevs) {
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
const DIEAbbrev *Abbrev = Abbrevs->at(AbbrevNumber - 1);
Bill Wendling
committed
// Emit the code (index) for the abbreviation.
if (Asm->isVerbose())
Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" +
Twine::utohexstr(Die->getOffset()) + ":0x" +
Twine::utohexstr(Die->getSize()) + " " +
dwarf::TagString(Abbrev->getTag()));
Asm->EmitULEB128(AbbrevNumber);
Bill Wendling
committed
const SmallVectorImpl<DIEValue*> &Values = Die->getValues();
const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData();
// Emit the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
unsigned Attr = AbbrevData[i].getAttribute();
unsigned Form = AbbrevData[i].getForm();
assert(Form && "Too many attributes for DIE (check abbreviation)");
if (Asm->isVerbose())
Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr));
switch (Attr) {
case dwarf::DW_AT_abstract_origin: {
DIEEntry *E = cast<DIEEntry>(Values[i]);
DIE *Origin = E->getEntry();
unsigned Addr = Origin->getOffset();
if (Form == dwarf::DW_FORM_ref_addr) {
// For DW_FORM_ref_addr, output the offset from beginning of debug info
// section. Origin->getOffset() returns the offset from start of the
// compile unit.
DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
Addr += Holder.getCUOffset(Origin->getCompileUnit());
}
case dwarf::DW_AT_ranges: {
// DW_AT_range Value encodes offset in debug_range section.
DIEInteger *V = cast<DIEInteger>(Values[i]);
Nick Lewycky
committed
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) {
Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym,
V->getValue(),
4);
} else {
Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym,
V->getValue(),
DwarfDebugRangeSectionSym,
4);
}
case dwarf::DW_AT_location: {
Nick Lewycky
committed
if (DIELabel *L = dyn_cast<DIELabel>(Values[i])) {
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
Asm->EmitLabelReference(L->getValue(), 4);
else
Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4);
} else {
Values[i]->EmitValue(Asm, Form);
Nick Lewycky
committed
}
}
case dwarf::DW_AT_accessibility: {
if (Asm->isVerbose()) {
DIEInteger *V = cast<DIEInteger>(Values[i]);
Asm->OutStreamer.AddComment(dwarf::AccessibilityString(V->getValue()));
}
Values[i]->EmitValue(Asm, Form);
break;
default:
// Emit an attribute using the defined form.
Values[i]->EmitValue(Asm, Form);
// Emit the DIE children if any.
if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) {
const std::vector<DIE *> &Children = Die->getChildren();
for (unsigned j = 0, M = Children.size(); j < M; ++j)
emitDIE(Children[j], Abbrevs);
if (Asm->isVerbose())
Asm->OutStreamer.AddComment("End Of Children Mark");
Asm->EmitInt8(0);
// Emit the various dwarf units to the unit section USection with
// the abbreviations going into ASection.
void DwarfUnits::emitUnits(DwarfDebug *DD,
const MCSection *USection,
const MCSection *ASection,
const MCSymbol *ASectionSym) {
Asm->OutStreamer.SwitchSection(USection);
for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I) {
CompileUnit *TheCU = *I;
DIE *Die = TheCU->getCUDie();
// Emit the compile units header.
Asm->OutStreamer
.EmitLabel(Asm->GetTempSymbol(USection->getLabelBeginName(),
TheCU->getUniqueID()));
// Emit size of content not including length itself
unsigned ContentSize = Die->getSize() +
sizeof(int16_t) + // DWARF version number
sizeof(int32_t) + // Offset Into Abbrev. Section
sizeof(int8_t); // Pointer Size (in bytes)
Asm->OutStreamer.AddComment("Length of Compilation Unit Info");
Asm->EmitInt32(ContentSize);
Asm->OutStreamer.AddComment("DWARF version number");
Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()),
ASectionSym);
Asm->OutStreamer.AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());