"llvm/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "8c17e6de2b291b006797f513b848dd7291332207"
Newer
Older
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);
for (DenseMap<DIE *, const MDNode *>::iterator CI = ContainingTypeMap.begin(),
Devang Patel
committed
CE = ContainingTypeMap.end(); CI != CE; ++CI) {
DIE *SPDie = CI->first;
const MDNode *N = dyn_cast_or_null<MDNode>(CI->second);
Devang Patel
committed
if (!N) continue;
DIE *NDie = getCompileUnit(N)->getDIE(N);
Devang Patel
committed
if (!NDie) continue;
addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie);
}
// Standard sections final addresses.
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end"));
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection());
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("data_end"));
// End text sections.
for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
Asm->OutStreamer.SwitchSection(SectionMap[i]);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", i));
// Emit common frame information.
emitCommonDebugFrame();
// Emit function debug frame information
for (std::vector<FunctionDebugFrameInfo>::iterator I = DebugFrames.begin(),
E = DebugFrames.end(); I != E; ++I)
emitFunctionDebugFrame(*I);
// Compute DIE offsets and sizes.
computeSizeAndOffsets();
// 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();
// Emit info into a debug pubtypes section.
emitDebugPubTypes();
// 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();
emitDebugInlineInfo();
// Emit info into a debug str section.
emitDebugStr();
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I)
delete I->second;
FirstCU = NULL; // Reset for the next Module, if any.
/// findAbstractVariable - Find abstract variable, if any, associated with Var.
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var,
DebugLoc ScopeLoc) {
Devang Patel
committed
DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
Devang Patel
committed
if (AbsDbgVariable)
return AbsDbgVariable;
LLVMContext &Ctx = Var->getContext();
DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope(Ctx));
Devang Patel
committed
if (!Scope)
return NULL;
AbsDbgVariable = new DbgVariable(Var);
Devang Patel
committed
Scope->addVariable(AbsDbgVariable);
AbstractVariables[Var] = AbsDbgVariable;
Devang Patel
committed
return AbsDbgVariable;
}
/// collectVariableInfoFromMMITable - Collect variable information from
/// side table maintained by MMI.
void
DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF,
SmallPtrSet<const MDNode *, 16> &Processed) {
const LLVMContext &Ctx = Asm->MF->getFunction()->getContext();
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;
DbgScope *Scope = 0;
if (const MDNode *IA = VP.second.getInlinedAt(Ctx))
Scope = ConcreteScopes.lookup(IA);
if (Scope == 0)
Scope = DbgScopeMap.lookup(VP.second.getScope(Ctx));
// If variable scope is not found then skip this variable.
if (Scope == 0)
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second);
DbgVariable *RegVar = new DbgVariable(DV);
recordVariableFrameIndex(RegVar, VP.first);
Scope->addVariable(RegVar);
if (AbsDbgVariable) {
recordVariableFrameIndex(AbsDbgVariable, VP.first);
VarToAbstractVarMap[RegVar] = AbsDbgVariable;
}
}
/// 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;
/// collection info from MMI table.
collectVariableInfoFromMMITable(MF, Processed);
Devang Patel
committed
Devang Patel
committed
// Collect variable information from DBG_VALUE machine instructions;
for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end();
Devang Patel
committed
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
if (!MInsn->isDebugValue() || isDbgValueInUndefinedReg(MInsn))
Devang Patel
committed
continue;
Devang Patel
committed
// 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;
Devang Patel
committed
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))
MultipleValues.push_back(*MI);
}
if (!Scope && DV.getTag() == dwarf::DW_TAG_arg_variable)
Scope = CurrentFnDbgScope;
continue;
Processed.insert(DV);
DbgVariable *RegVar = new DbgVariable(DV);
Scope->addVariable(RegVar);
DbgVariableLabelsMap[RegVar] = getLabelBeforeInsn(MInsn);
if (DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc())) {
DbgVariableToDbgInstMap[AbsVar] = MInsn;
VarToAbstractVarMap[RegVar] = AbsVar;
Devang Patel
committed
}
if (MultipleValues.size() <= 1) {
DbgVariableToDbgInstMap[RegVar] = MInsn;
continue;
}
// handle multiple DBG_VALUE instructions describing one variable.
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
if (DotDebugLocEntries.empty())
DotDebugLocEntries.push_back(DotDebugLocEntry());
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;
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());
Devang Patel
committed
}
Devang Patel
committed
// Collect info for variables that were optimized out.
if (NamedMDNode *NMD =
MF->getFunction()->getParent()->getNamedMetadata("llvm.dbg.lv")) {
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIVariable DV(cast_or_null<MDNode>(NMD->getOperand(i)));
Devang Patel
committed
continue;
DbgScope *Scope = DbgScopeMap.lookup(DV.getContext());
if (Scope)
Scope->addVariable(new DbgVariable(DV));
Devang Patel
committed
}
}
}
/// 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;
}
Devang Patel
committed
/// 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;
}
Devang Patel
committed
/// beginScope - Process beginning of a scope.
void DwarfDebug::beginScope(const MachineInstr *MI) {
// Check location.
DebugLoc DL = MI->getDebugLoc();
if (DL.isUnknown() && !UnknownLocations) {
if (MI->isDebugValue() && PrevLabel)
LabelsBeforeInsn[MI] = PrevLabel;
Devang Patel
committed
return;
Devang Patel
committed
bool LocalVar = false;
if (MI->isDebugValue()) {
Devang Patel
committed
assert (MI->getNumOperands() > 1 && "Invalid machine instruction!");
DIVariable DV(MI->getOperand(MI->getNumOperands() - 1).getMetadata());
if (!DV.Verify()) return;
if (DV.getTag() != dwarf::DW_TAG_arg_variable
&& !isDbgValueInUndefinedReg(MI))
Devang Patel
committed
LocalVar = true;
Devang Patel
committed
}
Devang Patel
committed
MCSymbol *Label = NULL;
if (DL == PrevInstLoc)
Label = PrevLabel;
// Do not emit line number entry for arguments.
else if (!MI->isDebugValue() || LocalVar) {
const MDNode *Scope = 0;
if (DL.isUnknown() == false) {
Scope = DL.getScope(Asm->MF->getFunction()->getContext());
// FIXME: Should only verify each scope once!
if (!DIScope(Scope).Verify())
return;
}
// else ...
// This instruction has no debug location. If the preceding instruction
// did, emit debug location information to indicate that the debug
// location is now unknown.
Devang Patel
committed
Label = recordSourceLine(DL.getLine(), DL.getCol(), Scope);
PrevInstLoc = DL;
PrevLabel = Label;
}
Devang Patel
committed
// If this instruction begins a scope then note down corresponding label
// even if previous label is reused.
if (Label && (InsnsBeginScopeSet.count(MI) != 0 || MI->isDebugValue()))
/// endScope - Process end of a scope.
void DwarfDebug::endScope(const MachineInstr *MI) {
if (InsnsEndScopeSet.count(MI) != 0) {
// Emit a label if this instruction ends a scope.
MCSymbol *Label = MMI->getContext().CreateTempSymbol();
Asm->OutStreamer.EmitLabel(Label);
Devang Patel
committed
LabelsAfterInsn[MI] = Label;
Devang Patel
committed
/// getOrCreateDbgScope - Create DbgScope for the scope.
DbgScope *DwarfDebug::getOrCreateDbgScope(const MDNode *Scope, const MDNode *InlinedAt) {
if (!InlinedAt) {
DbgScope *WScope = DbgScopeMap.lookup(Scope);
if (WScope)
Devang Patel
committed
return WScope;
WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL);
DbgScopeMap.insert(std::make_pair(Scope, WScope));
Devang Patel
committed
if (DIDescriptor(Scope).isLexicalBlock()) {
DbgScope *Parent =
getOrCreateDbgScope(DILexicalBlock(Scope).getContext(), NULL);
Devang Patel
committed
WScope->setParent(Parent);
Parent->addScope(WScope);
}
if (!WScope->getParent()) {
StringRef SPName = DISubprogram(Scope).getLinkageName();
if (SPName == Asm->MF->getFunction()->getName())
CurrentFnDbgScope = WScope;
}
return WScope;
}
DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
if (WScope)
Devang Patel
committed
return WScope;
WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt);
DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
DILocation DL(InlinedAt);
Devang Patel
committed
DbgScope *Parent =
getOrCreateDbgScope(DL.getScope(), DL.getOrigLocation());
Devang Patel
committed
WScope->setParent(Parent);
Parent->addScope(WScope);
ConcreteScopes[InlinedAt] = WScope;
getOrCreateAbstractScope(Scope);
return WScope;
}
/// hasValidLocation - Return true if debug location entry attached with
/// machine instruction encodes valid location info.
static bool hasValidLocation(LLVMContext &Ctx,
const MachineInstr *MInsn,
const MDNode *&Scope, const MDNode *&InlinedAt) {
Devang Patel
committed
if (MInsn->isDebugValue())
return false;
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) return false;
const MDNode *S = DL.getScope(Ctx);
Devang Patel
committed
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
// 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 (DIScope(S).isCompileUnit()) return false;
Scope = S;
InlinedAt = DL.getInlinedAt(Ctx);
return true;
}
/// calculateDominanceGraph - Calculate dominance graph for DbgScope
/// hierarchy.
static void calculateDominanceGraph(DbgScope *Scope) {
assert (Scope && "Unable to calculate scop edominance graph!");
SmallVector<DbgScope *, 4> WorkStack;
WorkStack.push_back(Scope);
unsigned Counter = 0;
while (!WorkStack.empty()) {
DbgScope *WS = WorkStack.back();
const SmallVector<DbgScope *, 4> &Children = WS->getScopes();
bool visitedChildren = false;
for (SmallVector<DbgScope *, 4>::const_iterator SI = Children.begin(),
SE = Children.end(); SI != SE; ++SI) {
DbgScope *ChildScope = *SI;
if (!ChildScope->getDFSOut()) {
WorkStack.push_back(ChildScope);
visitedChildren = true;
ChildScope->setDFSIn(++Counter);
break;
}
}
if (!visitedChildren) {
WorkStack.pop_back();
WS->setDFSOut(++Counter);
}
}
Devang Patel
committed
/// printDbgScopeInfo - Print DbgScope info for each machine instruction.
static
void printDbgScopeInfo(LLVMContext &Ctx, const MachineFunction *MF,
DenseMap<const MachineInstr *, DbgScope *> &MI2ScopeMap)
{
#ifndef NDEBUG
unsigned PrevDFSIn = 0;
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I) {
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
const MDNode *Scope = NULL;
const MDNode *InlinedAt = NULL;
Devang Patel
committed
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
// Check if instruction has valid location information.
if (hasValidLocation(Ctx, MInsn, Scope, InlinedAt)) {
dbgs() << " [ ";
if (InlinedAt)
dbgs() << "*";
DenseMap<const MachineInstr *, DbgScope *>::iterator DI =
MI2ScopeMap.find(MInsn);
if (DI != MI2ScopeMap.end()) {
DbgScope *S = DI->second;
dbgs() << S->getDFSIn();
PrevDFSIn = S->getDFSIn();
} else
dbgs() << PrevDFSIn;
} else
dbgs() << " [ x" << PrevDFSIn;
dbgs() << " ]";
MInsn->dump();
}
dbgs() << "\n";
}
#endif
}
/// extractScopeInformation - Scan machine instructions in this function
/// and collect DbgScopes. Return true, if at least one scope was found.
bool DwarfDebug::extractScopeInformation() {
Devang Patel
committed
// If scope information was extracted using .dbg intrinsics then there is not
// any need to extract these information by scanning each instruction.
if (!DbgScopeMap.empty())
return false;
// Scan each instruction and create scopes. First build working set of scopes.
Devang Patel
committed
LLVMContext &Ctx = Asm->MF->getFunction()->getContext();
SmallVector<DbgRange, 4> MIRanges;
DenseMap<const MachineInstr *, DbgScope *> MI2ScopeMap;
const MDNode *PrevScope = NULL;
const MDNode *PrevInlinedAt = NULL;
Devang Patel
committed
const MachineInstr *RangeBeginMI = NULL;
const MachineInstr *PrevMI = NULL;
for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end();
Devang Patel
committed
I != E; ++I) {
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
const MDNode *Scope = NULL;
const MDNode *InlinedAt = NULL;
Devang Patel
committed
// Check if instruction has valid location information.
if (!hasValidLocation(Ctx, MInsn, Scope, InlinedAt)) {
PrevMI = MInsn;
continue;
}
// If scope has not changed then skip this instruction.
if (Scope == PrevScope && PrevInlinedAt == InlinedAt) {
PrevMI = MInsn;
continue;
}
Devang Patel
committed
if (RangeBeginMI) {
// If we have alread seen a beginning of a instruction range and
// 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);
MIRanges.push_back(R);
}
Devang Patel
committed
// This is a beginning of a new instruction range.
RangeBeginMI = MInsn;
Devang Patel
committed
// Reset previous markers.
PrevMI = MInsn;
PrevScope = Scope;
PrevInlinedAt = InlinedAt;
Devang Patel
committed
}
}
Devang Patel
committed
// Create last instruction range.
if (RangeBeginMI && PrevMI && PrevScope) {
DbgRange R(RangeBeginMI, PrevMI);
MIRanges.push_back(R);
MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevScope, PrevInlinedAt);
}
if (!CurrentFnDbgScope)
return false;
Devang Patel
committed
calculateDominanceGraph(CurrentFnDbgScope);
if (PrintDbgScope)
printDbgScopeInfo(Ctx, Asm->MF, MI2ScopeMap);
// Find ranges of instructions covered by each DbgScope;
DbgScope *PrevDbgScope = NULL;
for (SmallVector<DbgRange, 4>::const_iterator RI = MIRanges.begin(),
RE = MIRanges.end(); RI != RE; ++RI) {
const DbgRange &R = *RI;
DbgScope *S = MI2ScopeMap.lookup(R.first);
assert (S && "Lost DbgScope for a machine instruction!");
if (PrevDbgScope && !PrevDbgScope->dominates(S))
PrevDbgScope->closeInsnRange(S);
S->openInsnRange(R.first);
S->extendInsnRange(R.second);
PrevDbgScope = S;
}
if (PrevDbgScope)
PrevDbgScope->closeInsnRange();
Devang Patel
committed
Devang Patel
committed
/// identifyScopeMarkers() -
/// Each DbgScope 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.
Devang Patel
committed
SmallVector<DbgScope *, 4> WorkList;
WorkList.push_back(CurrentFnDbgScope);
while (!WorkList.empty()) {
DbgScope *S = WorkList.pop_back_val();
Devang Patel
committed
Jeffrey Yasskin
committed
const SmallVector<DbgScope *, 4> &Children = S->getScopes();
Devang Patel
committed
if (!Children.empty())
Jeffrey Yasskin
committed
for (SmallVector<DbgScope *, 4>::const_iterator SI = Children.begin(),
Devang Patel
committed
SE = Children.end(); SI != SE; ++SI)
WorkList.push_back(*SI);
if (S->isAbstractScope())
continue;
Devang Patel
committed
const SmallVector<DbgRange, 4> &Ranges = S->getRanges();
if (Ranges.empty())
continue;
for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(),
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);
Devang Patel
committed
InsnsEndScopeSet.insert(RI->second);
}
Devang Patel
committed
}
}
/// FindFirstDebugLoc - Find the first debug location in the function. This
/// is intended to be an approximation for the source position of the
/// beginning of the function.
static DebugLoc FindFirstDebugLoc(const MachineFunction *MF) {
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I)
for (MachineBasicBlock::const_iterator MBBI = I->begin(), MBBE = I->end();
MBBI != MBBE; ++MBBI) {
DebugLoc DL = MBBI->getDebugLoc();
if (!DL.isUnknown())
return DL;
}
return DebugLoc();
}
/// beginFunction - Gather pre-function debug information. Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::beginFunction(const MachineFunction *MF) {
Chris Lattner
committed
if (!MMI->hasDebugInfo()) return;
if (!extractScopeInformation()) return;
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);
// Emit label for the implicitly defined dbg.stoppoint at the start of the
// function.
DebugLoc FDL = FindFirstDebugLoc(MF);
if (FDL.isUnknown()) return;
const MDNode *Scope = FDL.getScope(MF->getFunction()->getContext());
DISubprogram SP = getDISubprogram(Scope);
unsigned Line, Col;
if (SP.Verify()) {
Line = SP.getLineNumber();
Col = 0;
} else {
Line = FDL.getLine();
Col = FDL.getCol();
}
recordSourceLine(Line, Col, Scope);
/// endFunction - Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
if (!MMI->hasDebugInfo() || DbgScopeMap.empty()) return;
Devang Patel
committed
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);
collectVariableInfo(MF);
// Get function line info.
if (!Lines.empty()) {
// Get section line info.
unsigned ID = SectionMap.insert(Asm->getCurrentSection());
if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
std::vector<SrcLineInfo> &SectionLineInfos = SectionSourceLines[ID-1];
// Append the function info to section info.
SectionLineInfos.insert(SectionLineInfos.end(),
Lines.begin(), Lines.end());
}
// Construct abstract scopes.
for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
AE = AbstractScopesList.end(); AI != AE; ++AI)
constructScopeDIE(*AI);
Devang Patel
committed
DIE *CurFnDIE = constructScopeDIE(CurrentFnDbgScope);
Devang Patel
committed
if (!DisableFramePointerElim(*MF))
addUInt(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr,
dwarf::DW_FORM_flag, 1);
DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(),
DbgVariableToFrameIndexMap.clear();
VarToAbstractVarMap.clear();
DbgVariableToDbgInstMap.clear();
DbgVariableLabelsMap.clear();
Jeffrey Yasskin
committed
DeleteContainerSeconds(DbgScopeMap);
InsnsEndScopeSet.clear();
Jeffrey Yasskin
committed
DeleteContainerSeconds(AbstractScopes);
Jeffrey Yasskin
committed
AbstractVariables.clear();
Devang Patel
committed
LabelsBeforeInsn.clear();
LabelsAfterInsn.clear();
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
/// recordVariableFrameIndex - Record a variable's index.
void DwarfDebug::recordVariableFrameIndex(const DbgVariable *V, int Index) {
assert (V && "Invalid DbgVariable!");
DbgVariableToFrameIndexMap[V] = Index;
}
/// findVariableFrameIndex - Return true if frame index for the variable
/// is found. Update FI to hold value of the index.
bool DwarfDebug::findVariableFrameIndex(const DbgVariable *V, int *FI) {
assert (V && "Invalid DbgVariable!");
DenseMap<const DbgVariable *, int>::iterator I =
DbgVariableToFrameIndexMap.find(V);
if (I == DbgVariableToFrameIndexMap.end())
return false;
*FI = I->second;
return true;
}
/// findVariableLabel - Find MCSymbol for the variable.
const MCSymbol *DwarfDebug::findVariableLabel(const DbgVariable *V) {
DenseMap<const DbgVariable *, const MCSymbol *>::iterator I
= DbgVariableLabelsMap.find(V);
if (I == DbgVariableLabelsMap.end())
return NULL;
else return I->second;
}
/// findDbgScope - Find DbgScope for the debug loc attached with an
/// instruction.
DbgScope *DwarfDebug::findDbgScope(const MachineInstr *MInsn) {
DbgScope *Scope = NULL;
LLVMContext &Ctx =
MInsn->getParent()->getParent()->getFunction()->getContext();
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown())
return Scope;
if (const MDNode *IA = DL.getInlinedAt(Ctx))
Scope = ConcreteScopes.lookup(IA);
if (Scope == 0)
Scope = DbgScopeMap.lookup(DL.getScope(Ctx));
return Scope;
}
/// 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) {
StringRef Dir;
StringRef Fn;
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
unsigned Src = 1;
if (S) {
DIDescriptor Scope(S);
if (Scope.isCompileUnit()) {
DICompileUnit CU(S);
Dir = CU.getDirectory();
Fn = CU.getFilename();
} else if (Scope.isSubprogram()) {
DISubprogram SP(S);
Dir = SP.getDirectory();
Fn = SP.getFilename();
} else if (Scope.isLexicalBlock()) {
DILexicalBlock DB(S);
Dir = DB.getDirectory();
Fn = DB.getFilename();
} else
assert(0 && "Unexpected scope info");
Src = GetOrCreateSourceID(Dir, Fn);
}
MCSymbol *Label = MMI->getContext().CreateTempSymbol();
Lines.push_back(SrcLineInfo(Line, Col, Src, Label));
//===----------------------------------------------------------------------===//
// Emit Methods
//===----------------------------------------------------------------------===//
/// computeSizeAndOffset - Compute the size and offset of a DIE.
unsigned
DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) {
// Get the children.
const std::vector<DIE *> &Children = Die->getChildren();
// If not last sibling and has children then add sibling offset attribute.
if (!Last && !Children.empty())
Die->addSiblingOffset(DIEValueAllocator);
// Record the abbreviation.
assignAbbrevNumber(Die->getAbbrev());
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
// Set DIE offset
Die->setOffset(Offset);
// Start the size with the size of abbreviation code.
Offset += MCAsmInfo::getULEB128Size(AbbrevNumber);
const SmallVector<DIEValue*, 32> &Values = Die->getValues();
const SmallVector<DIEAbbrevData, 8> &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, (j + 1) == M);
// End of children marker.
Offset += sizeof(int8_t);
}
Die->setSize(Offset - Die->getOffset());
return Offset;
/// computeSizeAndOffsets - Compute the size and offset of all the DIEs.
void DwarfDebug::computeSizeAndOffsets() {
unsigned PrevOffset = 0;
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
// Compute size of compile unit header.
static unsigned Offset = PrevOffset +
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)
computeSizeAndOffset(I->second->getCUDie(), Offset, true);
PrevOffset = Offset;
}
/// EmitSectionSym - Switch to the specified MCSection and emit an assembler
/// temporary label to it if SymbolStem is specified.
static MCSymbol *EmitSectionSym(AsmPrinter *Asm, const MCSection *Section,
Asm->OutStreamer.SwitchSection(Section);
MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem);
Asm->OutStreamer.EmitLabel(TmpSym);
return TmpSym;
}
/// EmitSectionLabels - 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.
if (Asm->MAI->doesDwarfRequireFrameSection()) {
DwarfFrameSectionSym =
EmitSectionSym(Asm, TLOF.getDwarfFrameSection(), "section_debug_frame");
}
DwarfInfoSectionSym =
EmitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
DwarfAbbrevSectionSym =
EmitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
EmitSectionSym(Asm, TLOF.getDwarfARangesSection());
if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection())
EmitSectionSym(Asm, TLOF.getDwarfLineSection());
EmitSectionSym(Asm, TLOF.getDwarfLocSection());
EmitSectionSym(Asm, TLOF.getDwarfPubNamesSection());
EmitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
DwarfStrSectionSym =
EmitSectionSym(Asm, TLOF.getDwarfStrSection(), "section_str");
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());
Bill Wendling
committed
}
/// emitDIE - Recusively Emits a debug information entry.
void DwarfDebug::emitDIE(DIE *Die) {
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
const DIEAbbrev *Abbrev = Abbreviations[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 SmallVector<DIEValue*, 32> &Values = Die->getValues();
const SmallVector<DIEAbbrevData, 8> &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_sibling:
Asm->EmitInt32(Die->getSiblingOffset());
break;
case dwarf::DW_AT_abstract_origin: {
DIEEntry *E = cast<DIEEntry>(Values[i]);
DIE *Origin = E->getEntry();
unsigned Addr = Origin->getOffset();
Asm->EmitInt32(Addr);
break;
}
case dwarf::DW_AT_ranges: {
// DW_AT_range Value encodes offset in debug_range section.
DIEInteger *V = cast<DIEInteger>(Values[i]);
Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym,
V->getValue(),
DwarfDebugRangeSectionSym,
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);
// 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]);
if (Asm->isVerbose())
Asm->OutStreamer.AddComment("End Of Children Mark");
Asm->EmitInt8(0);
/// emitDebugInfo - Emit the debug info section.
void DwarfDebug::emitDebugInfo() {
// Start debug info section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfInfoSection());
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
DIE *Die = TheCU->getCUDie();
// Emit the compile units header.
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_begin",
TheCU->getID()));
// 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)
sizeof(int32_t); // FIXME - extra pad for gdb bug.
Asm->OutStreamer.AddComment("Length of Compilation Unit Info");
Asm->EmitInt32(ContentSize);
Asm->OutStreamer.AddComment("DWARF version number");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
Asm->EmitSectionOffset(Asm->GetTempSymbol("abbrev_begin"),
DwarfAbbrevSectionSym);
Asm->OutStreamer.AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getTargetData().getPointerSize());
emitDIE(Die);