Newer
Older
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
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
}
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;
/// 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);
SmallPtrSet<const MDNode *, 16> ProcessedVars;
collectVariableInfo(MF, ProcessedVars);
// Construct abstract scopes.
for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
AE = AbstractScopesList.end(); AI != AE; ++AI) {
DISubprogram SP((*AI)->getScopeNode());
if (SP.Verify()) {
// Collect info for variables that were optimized out.
StringRef FName = SP.getLinkageName();
if (FName.empty())
FName = SP.getName();
if (NamedMDNode *NMD =
getFnSpecificMDNode(*(MF->getFunction()->getParent()), FName)) {
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIVariable DV(cast<MDNode>(NMD->getOperand(i)));
if (!DV || !ProcessedVars.insert(DV))
continue;
Devang Patel
committed
DbgScope *Scope = AbstractScopes.lookup(DV.getContext());
if (Scope)
Scope->addVariable(new DbgVariable(DV));
}
}
}
if (ProcessedSPNodes.count((*AI)->getScopeNode()) == 0)
constructScopeDIE(*AI);
Devang Patel
committed
DIE *CurFnDIE = constructScopeDIE(CurrentFnDbgScope);
Devang Patel
committed
if (!DisableFramePointerElim(*MF))
addUInt(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr,
Devang Patel
committed
dwarf::DW_FORM_flag, 1);
DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(),
Devang Patel
committed
CurrentFnArguments.clear();
DbgVariableToFrameIndexMap.clear();
VarToAbstractVarMap.clear();
DbgVariableToDbgInstMap.clear();
Jeffrey Yasskin
committed
DeleteContainerSeconds(DbgScopeMap);
Jakob Stoklund Olesen
committed
UserVariables.clear();
DbgValues.clear();
Jeffrey Yasskin
committed
DeleteContainerSeconds(AbstractScopes);
Jeffrey Yasskin
committed
AbstractVariables.clear();
Devang Patel
committed
LabelsBeforeInsn.clear();
LabelsAfterInsn.clear();
/// 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;
}
/// findDbgScope - Find DbgScope for the debug loc attached with an
/// instruction.
DbgScope *DwarfDebug::findDbgScope(const MachineInstr *MInsn) {
DbgScope *Scope = NULL;
MInsn->getParent()->getParent()->getFunction()->getContext();
DebugLoc DL = MInsn->getDebugLoc();
return Scope;
if (const MDNode *IA = DL.getInlinedAt(Ctx))
Scope = ConcreteScopes.lookup(IA);
if (Scope == 0)
Scope = DbgScopeMap.lookup(DL.getScope(Ctx));
/// recordSourceLine - Register a source line with debug info. Returns the
/// unique label that was emitted and which provides correspondence to
/// the source line list.
Jakob Stoklund Olesen
committed
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S){
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.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);
Rafael Espindola
committed
Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, DWARF2_FLAG_IS_STMT,
0, 0);
//===----------------------------------------------------------------------===//
// 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");
}
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.getDwarfPubNamesSection());
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
}
/// 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]);
if (Asm->MAI->doesDwarfUsesLabelOffsetForRanges()) {
Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym,
V->getValue(),
4);
} else {
Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym,
V->getValue(),
DwarfDebugRangeSectionSym,
4);
}
case dwarf::DW_AT_location: {
if (UseDotDebugLocEntry.count(Die) != 0) {
DIELabel *L = 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)
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);
// FIXME - extra padding for gdb bug.
Asm->OutStreamer.AddComment("4 extra padding bytes for GDB");
Asm->EmitInt8(0);
Asm->EmitInt8(0);
Asm->EmitInt8(0);
Asm->EmitInt8(0);
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);
/// emitCommonDebugFrame - Emit common frame info into a debug frame section.
void DwarfDebug::emitCommonDebugFrame() {
if (!Asm->MAI->doesDwarfRequireFrameSection())
int stackGrowth = Asm->getTargetData().getPointerSize();
Anton Korobeynikov
committed
if (Asm->TM.getFrameLowering()->getStackGrowthDirection() ==
TargetFrameLowering::StackGrowsDown)
stackGrowth *= -1;
// Start the dwarf frame section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfFrameSection());
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common"));
Asm->OutStreamer.AddComment("Length of Common Information Entry");
Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_frame_common_end"),
Asm->GetTempSymbol("debug_frame_common_begin"), 4);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_begin"));
Asm->OutStreamer.AddComment("CIE Identifier Tag");
Asm->EmitInt32((int)dwarf::DW_CIE_ID);
Asm->OutStreamer.AddComment("CIE Version");
Asm->EmitInt8(dwarf::DW_CIE_VERSION);
Asm->OutStreamer.AddComment("CIE Augmentation");
Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator.
Asm->EmitULEB128(1, "CIE Code Alignment Factor");
Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
Asm->OutStreamer.AddComment("CIE RA Column");
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
Anton Korobeynikov
committed
const TargetFrameLowering *TFI = Asm->TM.getFrameLowering();
Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
std::vector<MachineMove> Moves;
TFI->getInitialFrameState(Moves);
Asm->EmitFrameMoves(Moves, 0, false);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_end"));
/// emitFunctionDebugFrame - Emit per function frame info into a debug frame
void DwarfDebug::
emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) {
if (!Asm->MAI->doesDwarfRequireFrameSection())
// Start the dwarf frame section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfFrameSection());
Asm->OutStreamer.AddComment("Length of Frame Information Entry");
Asm->GetTempSymbol("debug_frame_begin", DebugFrameInfo.Number);
Asm->GetTempSymbol("debug_frame_end", DebugFrameInfo.Number);
Asm->EmitLabelDifference(DebugFrameEnd, DebugFrameBegin, 4);
Asm->OutStreamer.AddComment("FDE CIE offset");
Asm->EmitSectionOffset(Asm->GetTempSymbol("debug_frame_common"),
DwarfFrameSectionSym);
Asm->OutStreamer.AddComment("FDE initial location");
MCSymbol *FuncBeginSym =
Asm->GetTempSymbol("func_begin", DebugFrameInfo.Number);
Asm->OutStreamer.EmitSymbolValue(FuncBeginSym,
Asm->getTargetData().getPointerSize(),
0/*AddrSpace*/);
Asm->OutStreamer.AddComment("FDE address range");
Asm->EmitLabelDifference(Asm->GetTempSymbol("func_end",DebugFrameInfo.Number),
FuncBeginSym, Asm->getTargetData().getPointerSize());
Asm->EmitFrameMoves(DebugFrameInfo.Moves, FuncBeginSym, false);
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
///
void DwarfDebug::emitDebugPubNames() {
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
// Start the dwarf pubnames section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubNamesSection());
Asm->OutStreamer.AddComment("Length of Public Names Info");
Asm->EmitLabelDifference(
Asm->GetTempSymbol("pubnames_end", TheCU->getID()),
Asm->GetTempSymbol("pubnames_begin", TheCU->getID()), 4);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin",
TheCU->getID()));
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()),
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->getGlobals();
for (StringMap<DIE*>::const_iterator
GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
DIE *Entity = GI->second;
Asm->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(Entity->getOffset());
if (Asm->isVerbose())
Asm->OutStreamer.AddComment("External Name");
Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0);
}
Asm->OutStreamer.AddComment("End Mark");
Asm->EmitInt32(0);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end",
TheCU->getID()));
}
}
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
// Start the dwarf pubnames section.
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();
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.
Asm->OutStreamer.EmitBytes(Entries[i].second->getKey(), 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);
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
unsigned Reg = RI->getDwarfRegNum(Entry.Loc.getReg(), false);
Devang Patel
committed
if (int Offset = Entry.Loc.getOffset()) {
// If the value is at a certain offset from frame register then
// use DW_OP_fbreg.
unsigned OffsetSize = Offset ? MCAsmInfo::getSLEB128Size(Offset) : 1;
Asm->OutStreamer.AddComment("Loc expr size");
Devang Patel
committed
Asm->EmitInt16(1 + OffsetSize);
Asm->OutStreamer.AddComment(
dwarf::OperationEncodingString(dwarf::DW_OP_fbreg));
Asm->EmitInt8(dwarf::DW_OP_fbreg);
Asm->OutStreamer.AddComment("Offset");
Asm->EmitSLEB128(Offset);
Devang Patel
committed
if (Reg < 32) {
Asm->OutStreamer.AddComment("Loc expr size");
Asm->EmitInt16(1);
Asm->OutStreamer.AddComment(
dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg));
Devang Patel
committed
Asm->EmitInt8(dwarf::DW_OP_reg0 + Reg);
} else {
Asm->OutStreamer.AddComment("Loc expr size");
Asm->EmitInt16(1 + MCAsmInfo::getULEB128Size(Reg));
Asm->EmitInt8(dwarf::DW_OP_regx);
Asm->EmitULEB128(Reg);
}
/// EmitDebugARanges - Emit visible names into a debug aranges section.
///
void DwarfDebug::EmitDebugARanges() {
// Start the dwarf aranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfARangesSection());
Bill Wendling
committed
}
/// emitDebugRanges - Emit visible names into a debug ranges section.
void DwarfDebug::emitDebugRanges() {
// Start the dwarf ranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfRangesSection());
Devang Patel
committed
unsigned char Size = Asm->getTargetData().getPointerSize();
for (SmallVector<const MCSymbol *, 8>::iterator
I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end();
Devang Patel
committed
I != E; ++I) {
if (*I)
Asm->OutStreamer.EmitSymbolValue(const_cast<MCSymbol*>(*I), Size, 0);
Devang Patel
committed
Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0);
/// emitDebugMacInfo - Emit visible names into a debug macinfo section.
void DwarfDebug::emitDebugMacInfo() {
Asm->getObjFileLowering().getDwarfMacroInfoSection()) {
// Start the dwarf macinfo section.
Asm->OutStreamer.SwitchSection(LineInfo);
/// emitDebugInlineInfo - Emit inline info using following format.
/// Section Header:
/// 1. length of section
/// 2. Dwarf version number
/// 3. address size.
///
/// Entries (one "entry" for each function that was inlined):
///
/// 1. offset into __debug_str section for MIPS linkage name, if exists;
/// otherwise offset into __debug_str for regular function name.
/// 2. offset into __debug_str section for regular function name.
/// 3. an unsigned LEB128 number indicating the number of distinct inlining
/// instances for the function.
///
/// The rest of the entry consists of a {die_offset, low_pc} pair for each
/// inlined instance; the die_offset points to the inlined_subroutine die in the
/// __debug_info section, and the low_pc is the starting address for the
/// inlining instance.
void DwarfDebug::emitDebugInlineInfo() {
if (!Asm->MAI->doesDwarfUsesInlineInfoSection())
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfDebugInlineSection());
Asm->OutStreamer.AddComment("Length of Debug Inlined Information Entry");
Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_inlined_end", 1),
Asm->GetTempSymbol("debug_inlined_begin", 1), 4);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_begin", 1));
Asm->OutStreamer.AddComment("Dwarf Version");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Asm->OutStreamer.AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getTargetData().getPointerSize());
for (SmallVector<const MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
E = InlinedSPNodes.end(); I != E; ++I) {
const MDNode *Node = *I;
DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
SmallVector<InlineInfoLabels, 4> &Labels = II->second;
StringRef LName = SP.getLinkageName();
StringRef Name = SP.getName();
Asm->OutStreamer.AddComment("MIPS linkage name");
if (LName.empty()) {
Asm->OutStreamer.EmitBytes(Name, 0);
Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator.
Asm->EmitSectionOffset(getStringPoolEntry(getRealLinkageName(LName)),
DwarfStrSectionSym);
Asm->OutStreamer.AddComment("Function name");
Asm->EmitSectionOffset(getStringPoolEntry(Name), DwarfStrSectionSym);
Asm->EmitULEB128(Labels.size(), "Inline count");
for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
LE = Labels.end(); LI != LE; ++LI) {
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(LI->second->getOffset());
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("low_pc");
Asm->OutStreamer.EmitSymbolValue(LI->first,
Asm->getTargetData().getPointerSize(),0);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_end", 1));