Newer
Older
if (AbsVar)
Devang Patel
committed
AbsVar->setMInsn(MInsn);
Jakob Stoklund Olesen
committed
// Simple ranges that are fully coalesced.
if (History.size() <= 1 || (History.size() == 2 &&
MInsn->isIdenticalTo(History.back()))) {
Devang Patel
committed
RegVar->setMInsn(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.
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
}
}
/// 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;
/// 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
}
}
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;
LScopes.initialize(*MF);
if (LScopes.empty()) return;
identifyScopeMarkers();
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 &&
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
}
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();
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()),
DWARF2_FLAG_IS_STMT);
}
void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
// SmallVector<DbgVariable *, 8> &Vars = ScopeVariables.lookup(LS);
ScopeVariables[LS].push_back(Var);
// Vars.push_back(Var);
}
/// endFunction - 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);
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;
if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext()))
addScopeVariable(Scope, new DbgVariable(DV, NULL));
}
}
Devang Patel
committed
constructScopeDIE(TheCU, AScope);
}
Devang Patel
committed
DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope);
Devang Patel
committed
if (!DisableFramePointerElim(*MF))
TheCU->addUInt(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr,
dwarf::DW_FORM_flag, 1);
Devang Patel
committed
DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(),
MMI->getFrameMoves()));
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();
/// recordSourceLine - 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
assert(0 && "Unexpected scope info");
Devang Patel
committed
Src = GetOrCreateSourceID(Fn, Dir);
Nick Lewycky
committed
Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn);
//===----------------------------------------------------------------------===//
// 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() {
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
// Compute size of compile unit header.
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);
}
/// 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.
EmitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
EmitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
EmitSectionSym(Asm, TLOF.getDwarfARangesSection());
if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection())
EmitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
EmitSectionSym(Asm, TLOF.getDwarfLocSection());
EmitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
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
}
Nick Lewycky
committed
/// emitDIE - Recursively 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]);
if (Asm->MAI->doesDwarfUsesLabelOffsetForRanges()) {
Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym,
V->getValue(),
4);
} else {
Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym,
V->getValue(),
DwarfDebugRangeSectionSym,
4);
}
case dwarf::DW_AT_location: {
if (DIELabel *L = dyn_cast<DIELabel>(Values[i]))
Daniel Dunbar
committed
Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4);
else
Values[i]->EmitValue(Asm, Form);
break;
}
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]);
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());
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)
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);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_end", TheCU->getID()));
}
Bill Wendling
committed
}
/// emitAbbreviations - Emit the abbreviation section.
Bill Wendling
committed
///
void DwarfDebug::emitAbbreviations() const {
// Check to see if it is worth the effort.
if (!Abbreviations.empty()) {
// Start the debug abbrev section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfAbbrevSection());
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_begin"));
// For each abbrevation.
for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) {
// Get abbreviation data
const DIEAbbrev *Abbrev = Abbreviations[i];
// Emit the abbrevations code (base 1 index.)
Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
// Emit the abbreviations data.
Abbrev->Emit(Asm);
// Mark end of abbreviations.
Asm->EmitULEB128(0, "EOM(3)");
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_end"));
/// emitEndOfLineMatrix - Emit the last address of the section and the end of
/// the line matrix.
///
void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
// Define last address of section.
Asm->OutStreamer.AddComment("Extended Op");
Asm->EmitInt8(0);
Asm->OutStreamer.AddComment("Op size");
Asm->EmitInt8(Asm->getTargetData().getPointerSize() + 1);
Asm->OutStreamer.AddComment("DW_LNE_set_address");
Asm->EmitInt8(dwarf::DW_LNE_set_address);
Asm->OutStreamer.AddComment("Section end label");
Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd),
Asm->getTargetData().getPointerSize(),
0/*AddrSpace*/);
Asm->OutStreamer.AddComment("DW_LNE_end_sequence");
Asm->EmitInt8(0);
Asm->EmitInt8(1);
Eric Christopher
committed
/// emitAccelNames - Emit visible names into a hashed accelerator table
/// section.
void DwarfDebug::emitAccelNames() {
DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNames();
for (StringMap<std::vector<DIE*> >::const_iterator
Eric Christopher
committed
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
std::vector<DIE *> Entities = GI->second;
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE = Entities.end(); DI != DE; ++DI)
AT.AddName(Name, (*DI));
Eric Christopher
committed
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
}
}
AT.FinalizeTable(Asm, "Names");
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfAccelNamesSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
AT.Emit(Asm, SectionBegin, this);
}
/// emitAccelObjC - Emit objective C classes and categories into a hashed
/// accelerator table section.
void DwarfDebug::emitAccelObjC() {
DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelObjC();
for (StringMap<std::vector<DIE*> >::const_iterator
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
std::vector<DIE *> Entities = GI->second;
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE = Entities.end(); DI != DE; ++DI)
AT.AddName(Name, (*DI));
}
}
AT.FinalizeTable(Asm, "ObjC");
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
.getDwarfAccelObjCSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
AT.Emit(Asm, SectionBegin, this);
}
/// emitAccelNamespace - Emit namespace dies into a hashed accelerator
/// table.
void DwarfDebug::emitAccelNamespaces() {
DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNamespace();
for (StringMap<std::vector<DIE*> >::const_iterator
Eric Christopher
committed
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
std::vector<DIE *> Entities = GI->second;
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE = Entities.end(); DI != DE; ++DI)
AT.AddName(Name, (*DI));
Eric Christopher
committed
}
}
AT.FinalizeTable(Asm, "namespac");
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
.getDwarfAccelNamespaceSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
AT.Emit(Asm, SectionBegin, this);
}
/// emitAccelTypes() - Emit type dies into a hashed accelerator table.
void DwarfDebug::emitAccelTypes() {
DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelTypes();
for (StringMap<std::vector<DIE*> >::const_iterator
Eric Christopher
committed
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
std::vector<DIE *> Entities = GI->second;
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE= Entities.end(); DI !=DE; ++DI)
AT.AddName(Name, (*DI));
Eric Christopher
committed
}
}
AT.FinalizeTable(Asm, "types");
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
.getDwarfAccelTypesSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
AT.Emit(Asm, SectionBegin, this);
}
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubTypesSection());
Asm->OutStreamer.AddComment("Length of Public Types Info");
Asm->EmitLabelDifference(
Asm->GetTempSymbol("pubtypes_end", TheCU->getID()),
Asm->GetTempSymbol("pubtypes_begin", TheCU->getID()), 4);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_begin",
TheCU->getID()));
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", TheCU->getID()),
DwarfInfoSectionSym);
Asm->OutStreamer.AddComment("Compilation Unit Length");
Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", TheCU->getID()),
Asm->GetTempSymbol("info_begin", TheCU->getID()),
4);
const StringMap<DIE*> &Globals = TheCU->getGlobalTypes();
for (StringMap<DIE*>::const_iterator
GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
Nick Lewycky
committed
DIE *Entity = GI->second;
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(Entity->getOffset());
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name");
Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0);
}
Asm->OutStreamer.AddComment("End Mark");
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_end",
TheCU->getID()));
/// emitDebugStr - Emit visible names into a debug str section.
void DwarfDebug::emitDebugStr() {
// Check to see if it is worth the effort.
if (StringPool.empty()) return;
// Start the dwarf str section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfStrSection());
// Get all of the string pool entries and put them in an array by their ID so
// we can sort them.
SmallVector<std::pair<unsigned,
StringMapEntry<std::pair<MCSymbol*, unsigned> >*>, 64> Entries;
for (StringMap<std::pair<MCSymbol*, unsigned> >::iterator
I = StringPool.begin(), E = StringPool.end(); I != E; ++I)
Entries.push_back(std::make_pair(I->second.second, &*I));
array_pod_sort(Entries.begin(), Entries.end());
for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
// Emit a label for reference from debug information entries.
Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first);
// Emit the string itself with a terminating null byte.
Benjamin Kramer
committed
Asm->OutStreamer.EmitBytes(StringRef(Entries[i].second->getKeyData(),
Entries[i].second->getKeyLength()+1),
0/*addrspace*/);
/// emitDebugLoc - Emit visible names into a debug loc section.
void DwarfDebug::emitDebugLoc() {
if (DotDebugLocEntries.empty())
return;
for (SmallVector<DotDebugLocEntry, 4>::iterator
I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
I != E; ++I) {
DotDebugLocEntry &Entry = *I;
if (I + 1 != DotDebugLocEntries.end())
Entry.Merge(I+1);
}
Daniel Dunbar
committed
// Start the dwarf loc section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLocSection());
unsigned char Size = Asm->getTargetData().getPointerSize();
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0));
unsigned index = 1;
for (SmallVector<DotDebugLocEntry, 4>::iterator
I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
DotDebugLocEntry &Entry = *I;
if (Entry.isMerged()) continue;
if (Entry.isEmpty()) {
Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0);
Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index));
} else {
Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size, 0);
Asm->OutStreamer.EmitSymbolValue(Entry.End, Size, 0);
Devang Patel
committed
DIVariable DV(Entry.Variable);
Asm->OutStreamer.AddComment("Loc expr size");
MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
Asm->EmitLabelDifference(end, begin, 2);
Asm->OutStreamer.EmitLabel(begin);
if (Entry.isInt()) {
Devang Patel
committed
DIBasicType BTy(DV.getType());
if (BTy.Verify() &&
(BTy.getEncoding() == dwarf::DW_ATE_signed
|| BTy.getEncoding() == dwarf::DW_ATE_signed_char)) {
Asm->OutStreamer.AddComment("DW_OP_consts");
Asm->EmitInt8(dwarf::DW_OP_consts);
Asm->EmitSLEB128(Entry.getInt());
Devang Patel
committed
} else {
Asm->OutStreamer.AddComment("DW_OP_constu");
Asm->EmitInt8(dwarf::DW_OP_constu);
Asm->EmitULEB128(Entry.getInt());
Devang Patel
committed
}
} else if (Entry.isLocation()) {
if (!DV.hasComplexAddress())
// Regular entry.
Asm->EmitDwarfRegOp(Entry.Loc);
else {
// Complex address entry.
unsigned N = DV.getNumAddrElements();