"llvm/lib/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "191ba00b83bf4d79209145f78c1c08b0f7ca41e0"
Newer
Older
TheCU->insertDIE(N, VariableDIE);
DIDescriptor GVContext = GV.getContext();
Devang Patel
committed
TheCU->addToContextOwner(VariableDIE, GVContext);
if (isGlobalVariable) {
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
Devang Patel
committed
TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getSymbol(GV.getGlobal()));
// Do not create specification DIE if context is either compile unit
// or a subprogram.
if (GV.isDefinition() && !GVContext.isCompileUnit() &&
!GVContext.isFile() && !isSubprogramContext(GVContext)) {
// Create specification DIE.
DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable);
Devang Patel
committed
TheCU->addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification,
Devang Patel
committed
TheCU->addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
TheCU->addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
TheCU->addDie(VariableSpecDIE);
} else {
Devang Patel
committed
TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block);
} else if (const ConstantInt *CI =
Devang Patel
committed
TheCU->addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy));
else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) {
// GV is a merged global.
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
Devang Patel
committed
TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getSymbol(cast<GlobalValue>(CE->getOperand(0))));
ConstantInt *CII = cast<ConstantInt>(CE->getOperand(2));
Devang Patel
committed
TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
TheCU->addUInt(Block, 0, dwarf::DW_FORM_udata, CII->getZExtValue());
TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block);
/// construct SubprogramDIE - Construct subprogram DIE.
void DwarfDebug::constructSubprogramDIE(const MDNode *N) {
Bill Wendling
committed
// Check for pre-existence.
CompileUnit *TheCU = getCompileUnit(N);
if (TheCU->getDIE(N))
return;
if (!SP.isDefinition())
// This is a method declaration which will be handled while constructing
// class type.
Bill Wendling
committed
DIE *SubprogramDie = createSubprogramDIE(SP);
// Add to map.
TheCU->insertDIE(N, SubprogramDie);
Devang Patel
committed
TheCU->addToContextOwner(SubprogramDie, SP.getContext());
TheCU->addGlobal(SP.getName(), SubprogramDie);
/// beginModule - Emit all Dwarf sections that should come prior to the
/// content. Create global DIEs and emit initial debug info sections.
/// This is inovked by the target AsmPrinter.
void DwarfDebug::beginModule(Module *M) {
Devang Patel
committed
if (DisableDebugInfoPrinting)
return;
Devang Patel
committed
// If module has named metadata anchors then use them, otherwise scan the module
// using debug info finder to collect debug info.
NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
if (CU_Nodes) {
Devang Patel
committed
NamedMDNode *GV_Nodes = M->getNamedMetadata("llvm.dbg.gv");
NamedMDNode *SP_Nodes = M->getNamedMetadata("llvm.dbg.sp");
if (!GV_Nodes && !SP_Nodes)
// If there are not any global variables or any functions then
// there is not any debug info in this module.
Devang Patel
committed
return;
Devang Patel
committed
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i)
constructCompileUnit(CU_Nodes->getOperand(i));
if (GV_Nodes)
for (unsigned i = 0, e = GV_Nodes->getNumOperands(); i != e; ++i)
constructGlobalVariableDIE(GV_Nodes->getOperand(i));
Devang Patel
committed
Devang Patel
committed
if (SP_Nodes)
for (unsigned i = 0, e = SP_Nodes->getNumOperands(); i != e; ++i)
constructSubprogramDIE(SP_Nodes->getOperand(i));
Devang Patel
committed
} else {
Devang Patel
committed
DebugInfoFinder DbgFinder;
DbgFinder.processModule(*M);
Devang Patel
committed
bool HasDebugInfo = false;
Devang Patel
committed
// Scan all the compile-units to see if there are any marked as the main unit.
// if not, we do not generate debug info.
for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
E = DbgFinder.compile_unit_end(); I != E; ++I) {
if (DICompileUnit(*I).isMain()) {
HasDebugInfo = true;
break;
}
}
Devang Patel
committed
if (!HasDebugInfo) return;
Devang Patel
committed
// Create all the compile unit DIEs.
for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
E = DbgFinder.compile_unit_end(); I != E; ++I)
constructCompileUnit(*I);
// Create DIEs for each global variable.
for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
E = DbgFinder.global_variable_end(); I != E; ++I)
constructGlobalVariableDIE(*I);
// Create DIEs for each subprogram.
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
E = DbgFinder.subprogram_end(); I != E; ++I)
constructSubprogramDIE(*I);
}
// Tell MMI that we have debug info.
MMI->setDebugInfoAvailability(true);
Devang Patel
committed
// Emit initial sections.
EmitSectionLabels();
Devang Patel
committed
//getOrCreateTypeDIE
if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum"))
Devang Patel
committed
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIType Ty(NMD->getOperand(i));
getCompileUnit(Ty)->getOrCreateTypeDIE(Ty);
}
Devang Patel
committed
if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty"))
Devang Patel
committed
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIType Ty(NMD->getOperand(i));
getCompileUnit(Ty)->getOrCreateTypeDIE(Ty);
}
SectionMap.insert(Asm->getObjFileLowering().getTextSection());
/// endModule - Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {
const Module *M = MMI->getModule();
DenseMap<const MDNode *, DbgScope *> DeadFnScopeMap;
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 = getFnSpecificMDNode(*(MMI->getModule()), 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->getDbgVariables();
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(),
AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
DIE *ISP = *AI;
Devang Patel
committed
FirstCU->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;
Devang Patel
committed
getCompileUnit(N)->addDIEEntry(SPDie, dwarf::DW_AT_containing_type,
dwarf::DW_FORM_ref4, NDie);
Devang Patel
committed
}
// 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));
// Compute DIE offsets and sizes.
computeSizeAndOffsets();
// Emit all the DIEs into a debug info section
emitDebugInfo();
// Corresponding abbreviations into a abbrev section.
emitAbbreviations();
// 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();
// clean up.
DeleteContainerSeconds(DeadFnScopeMap);
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 &DV,
DebugLoc ScopeLoc) {
LLVMContext &Ctx = DV->getContext();
// More then one inlined variable corresponds to one abstract variable.
DIVariable Var = cleanseInlinedVariable(DV, Ctx);
Devang Patel
committed
DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
Devang Patel
committed
if (AbsDbgVariable)
return AbsDbgVariable;
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;
}
Devang Patel
committed
/// addCurrentFnArgument - If Var is an current function argument that add
/// it in CurrentFnArguments list.
bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
DbgVariable *Var, DbgScope *Scope) {
if (Scope != CurrentFnDbgScope)
return false;
DIVariable DV = Var->getVariable();
if (DV.getTag() != dwarf::DW_TAG_arg_variable)
return false;
unsigned ArgNo = DV.getArgNumber();
if (ArgNo == 0)
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;
}
/// collectVariableInfoFromMMITable - Collect variable information from
/// side table maintained by MMI.
DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF,
SmallPtrSet<const MDNode *, 16> &Processed) {
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;
// 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);
Devang Patel
committed
if (!addCurrentFnArgument(MF, RegVar, Scope))
Scope->addVariable(RegVar);
if (AbsDbgVariable) {
recordVariableFrameIndex(AbsDbgVariable, VP.first);
VarToAbstractVarMap[RegVar] = AbsDbgVariable;
}
}
/// 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!");
return MI->getNumOperands() == 3 &&
MI->getOperand(0).isReg() && MI->getOperand(0).getReg() &&
MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0;
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
/// getDebugLocEntry - Get .debug_loc entry for the instraction 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);
}
if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) {
MachineLocation MLoc;
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());
assert (0 && "Unexpected 3 operand DBG_VALUE instruction!");
return DotDebugLocEntry();
}
/// collectVariableInfo - Populate DbgScope entries with variables' info.
DwarfDebug::collectVariableInfo(const MachineFunction *MF,
SmallPtrSet<const MDNode *, 16> &Processed) {
/// collection info from MMI table.
collectVariableInfoFromMMITable(MF, Processed);
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);
DbgScope *Scope = NULL;
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(DV.getContext()).describes(MF->getFunction()))
Jakob Stoklund Olesen
committed
assert(MInsn->isDebugValue() && "History must begin with debug value");
Devang Patel
committed
if (!addCurrentFnArgument(MF, RegVar, Scope))
Scope->addVariable(RegVar);
if (DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc())) {
DbgVariableToDbgInstMap[AbsVar] = MInsn;
VarToAbstractVarMap[RegVar] = AbsVar;
Devang Patel
committed
}
Jakob Stoklund Olesen
committed
// Simple ranges that are fully coalesced.
if (History.size() <= 1 || (History.size() == 2 &&
MInsn->isIdenticalTo(History.back()))) {
DbgVariableToDbgInstMap[RegVar] = MInsn;
continue;
}
// 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];
DEBUG(dbgs() << "DotDebugLoc Pair:\n"
<< "\t" << *Begin << "\t" << *End << "\n");
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.
const Function *F = MF->getFunction();
if (NamedMDNode *NMD = getFnSpecificMDNode(*(F->getParent()), F->getName())) {
Devang Patel
committed
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIVariable DV(cast<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) {
Jakob Stoklund Olesen
committed
MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
assert(Label && "Didn't insert label before instruction");
return Label;
Devang Patel
committed
/// getLabelAfterInsn - Return Label immediately following the instruction.
const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
Jakob Stoklund Olesen
committed
return LabelsAfterInsn.lookup(MI);
}
/// beginInstruction - 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 = DWARF2_FLAG_IS_STMT;
Jakob Stoklund Olesen
committed
PrevInstLoc = DL;
if (DL == PrologEndLoc) {
Flags |= DWARF2_FLAG_PROLOGUE_END;
PrologEndLoc = DebugLoc();
}
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;
/// endInstruction - 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;
Devang Patel
committed
/// getOrCreateDbgScope - Create DbgScope for the scope.
DbgScope *DwarfDebug::getOrCreateDbgScope(DebugLoc DL) {
LLVMContext &Ctx = Asm->MF->getFunction()->getContext();
Devang Patel
committed
MDNode *Scope = NULL;
MDNode *InlinedAt = NULL;
DL.getScopeAndInlinedAt(Scope, InlinedAt, Ctx);
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()) {
getOrCreateDbgScope(DebugLoc::getFromDILexicalBlock(Scope));
Devang Patel
committed
WScope->setParent(Parent);
Parent->addScope(WScope);
} else if (DIDescriptor(Scope).isSubprogram()
&& DISubprogram(Scope).describes(Asm->MF->getFunction()))
CurrentFnDbgScope = WScope;
Devang Patel
committed
return WScope;
getOrCreateAbstractScope(Scope);
DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
Devang Patel
committed
return WScope;
WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt);
DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
Devang Patel
committed
InlinedDbgScopeMap[DebugLoc::getFromDILocation(InlinedAt)] = WScope;
Devang Patel
committed
DbgScope *Parent =
getOrCreateDbgScope(DebugLoc::getFromDILocation(InlinedAt));
Devang Patel
committed
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
WScope->setParent(Parent);
Parent->addScope(WScope);
return WScope;
}
/// 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.
void printDbgScopeInfo(const MachineFunction *MF,
Devang Patel
committed
DenseMap<const MachineInstr *, DbgScope *> &MI2ScopeMap)
{
#ifndef NDEBUG
LLVMContext &Ctx = MF->getFunction()->getContext();
Devang Patel
committed
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;
Devang Patel
committed
MDNode *Scope = NULL;
MDNode *InlinedAt = NULL;
Devang Patel
committed
// Check if instruction has valid location information.
Devang Patel
committed
DebugLoc MIDL = MInsn->getDebugLoc();
if (!MIDL.isUnknown()) {
MIDL.getScopeAndInlinedAt(Scope, InlinedAt, Ctx);
Devang Patel
committed
dbgs() << " [ ";
Devang Patel
committed
dbgs() << "*";
DenseMap<const MachineInstr *, DbgScope *>::iterator DI =
Devang Patel
committed
MI2ScopeMap.find(MInsn);
if (DI != MI2ScopeMap.end()) {
DbgScope *S = DI->second;
dbgs() << S->getDFSIn();
PrevDFSIn = S->getDFSIn();
} else
dbgs() << PrevDFSIn;
Devang Patel
committed
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
SmallVector<DbgRange, 4> MIRanges;
DenseMap<const MachineInstr *, DbgScope *> MI2ScopeMap;
Devang Patel
committed
DebugLoc PrevDL;
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;
Devang Patel
committed
// Check if instruction has valid location information.
Devang Patel
committed
const DebugLoc MIDL = MInsn->getDebugLoc();
if (MIDL.isUnknown()) {
Devang Patel
committed
PrevMI = MInsn;
continue;
}
Devang Patel
committed
// If scope has not changed then skip this instruction.
Devang Patel
committed
if (MIDL == PrevDL) {
Devang Patel
committed
PrevMI = MInsn;
continue;
}
Devang Patel
committed
// Ignore DBG_VALUE. It does not contribute any instruction in output.
if (MInsn->isDebugValue())
continue;
if (RangeBeginMI) {
// If we have alread seen a beginning of a instruction range and
Devang Patel
committed
// current instruction scope does not match scope of first instruction
// in this range then create a new instruction range.
DEBUG(dbgs() << "Creating new instruction range :\n");
DEBUG(dbgs() << "Begin Range at " << *RangeBeginMI);
DEBUG(dbgs() << "End Range at " << *PrevMI);
DEBUG(dbgs() << "Next Range starting at " << *MInsn);
Devang Patel
committed
DbgRange R(RangeBeginMI, PrevMI);
MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevDL);
Devang Patel
committed
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;
Devang Patel
committed
PrevDL = MIDL;
Devang Patel
committed
}
}
Devang Patel
committed
// Create last instruction range.
Devang Patel
committed
if (RangeBeginMI && PrevMI && !PrevDL.isUnknown()) {
Devang Patel
committed
DbgRange R(RangeBeginMI, PrevMI);
MIRanges.push_back(R);
MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevDL);
Devang Patel
committed
}
if (!CurrentFnDbgScope)
return false;
Devang Patel
committed
calculateDominanceGraph(CurrentFnDbgScope);
if (PrintDbgScope)
printDbgScopeInfo(Asm->MF, MI2ScopeMap);
Devang Patel
committed
// 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
/// 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();
Jeffrey Yasskin
committed
const SmallVector<DbgScope *, 4> &Children = S->getScopes();
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!");
Jakob Stoklund Olesen
committed
requestLabelBeforeInsn(RI->first);
requestLabelAfterInsn(RI->second);
Devang Patel
committed
}
Devang Patel
committed
}
}
Devang Patel
committed
/// getScopeNode - Get MDNode for DebugLoc's scope.
static MDNode *getScopeNode(DebugLoc DL, const LLVMContext &Ctx) {
if (MDNode *InlinedAt = DL.getInlinedAt(Ctx))
return getScopeNode(DebugLoc::getFromDILocation(InlinedAt), Ctx);
return DL.getScope(Ctx);
}
/// getFnDebugLoc - 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())
return DebugLoc::get(SP.getLineNumber(), 0, SP);
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);
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()) {
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 &&
Prev->isIdenticalTo(History[History.size() - 2])) {
DEBUG(dbgs() << "Coalesce identical DBG_VALUE entries:\n"
<< "\t" << *Prev
<< "\t" << *History[History.size() - 2] << "\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() << "Drop DBG_VALUE for empty range:\n"
<< "\t" << *Prev << "\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 location marks beginning of function
// body.
if (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 (const unsigned *AI = TRI->getOverlaps(MOI->getReg());
unsigned Reg = *AI; ++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
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
}
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();
MachineBasicBlock::const_iterator LastMI = PrevMBB->getLastNonDebugInstr();
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()),
DWARF2_FLAG_IS_STMT);
}
/// 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",