Newer
Older
DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
DILocation DL(InlinedAt);
createDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode());
/// extractScopeInformation - Scan machine instructions in this function
Devang Patel
committed
/// and collect DbgScopes. Return true, if atleast 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;
DenseMap<const MachineInstr *, unsigned> MIIndexMap;
unsigned MIIndex = 0;
// Scan each instruction and create scopes. First build working set of scopes.
Devang Patel
committed
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;
MIIndexMap[MInsn] = MIIndex++;
Devang Patel
committed
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) continue;
DILocation DLT = MF->getDILocation(DL);
DIScope DLTScope = DLT.getScope();
Devang Patel
committed
// There is no need to create another DIE for compile unit. For all
// other scopes, create one DbgScope now. This will be translated
Devang Patel
committed
// into a scope DIE at the end.
if (DLTScope.isCompileUnit()) continue;
createDbgScope(DLTScope.getNode(), DLT.getOrigLocation().getNode());
}
}
// Build scope hierarchy using working set of scopes.
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;
DebugLoc DL = MInsn->getDebugLoc();
if (DL.isUnknown()) continue;
DILocation DLT = MF->getDILocation(DL);
DIScope DLTScope = DLT.getScope();
// There is no need to create another DIE for compile unit. For all
// other scopes, create one DbgScope now. This will be translated
// into a scope DIE at the end.
if (DLTScope.isCompileUnit()) continue;
DbgScope *Scope = getUpdatedDbgScope(DLTScope.getNode(), MInsn,
DLT.getOrigLocation().getNode());
Scope->setLastInsn(MInsn);
Devang Patel
committed
}
}
if (!CurrentFnDbgScope)
return false;
CurrentFnDbgScope->fixInstructionMarkers(MIIndexMap);
Devang Patel
committed
// Each scope 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)
Devang Patel
committed
// multiple scopes. Ignore scopes that are not reachable.
SmallVector<DbgScope *, 4> WorkList;
WorkList.push_back(CurrentFnDbgScope);
while (!WorkList.empty()) {
DbgScope *S = WorkList.back(); WorkList.pop_back();
SmallVector<DbgScope *, 4> &Children = S->getScopes();
Devang Patel
committed
if (!Children.empty())
for (SmallVector<DbgScope *, 4>::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 MachineInstr *MI = S->getFirstInsn();
assert (MI && "DbgScope does not have first instruction!");
InsnToDbgScopeMapTy::iterator IDI = DbgScopeBeginMap.find(MI);
if (IDI != DbgScopeBeginMap.end())
IDI->second.push_back(S);
else
DbgScopeBeginMap[MI].push_back(S);
Devang Patel
committed
MI = S->getLastInsn();
assert (MI && "DbgScope does not have last instruction!");
IDI = DbgScopeEndMap.find(MI);
if (IDI != DbgScopeEndMap.end())
IDI->second.push_back(S);
else
DbgScopeEndMap[MI].push_back(S);
Devang Patel
committed
}
return !DbgScopeMap.empty();
}
/// beginFunction - Gather pre-function debug information. Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::beginFunction(const MachineFunction *MF) {
if (!ShouldEmitDwarfDebug()) return;
if (TimePassesIsEnabled)
DebugTimer->startTimer();
if (!extractScopeInformation())
collectVariableInfo();
// Assumes in correct section after the entry point.
Asm->OutStreamer.EmitLabel(getDWLabel("func_begin", ++SubprogramCount));
// Emit label for the implicitly defined dbg.stoppoint at the start of the
// function.
DebugLoc FDL = MF->getDefaultDebugLoc();
if (!FDL.isUnknown()) {
DILocation DLT = MF->getDILocation(FDL);
unsigned LabelID = 0;
DISubprogram SP = getDISubprogram(DLT.getScope().getNode());
LabelID = recordSourceLine(SP.getLineNumber(), 0,
DLT.getScope().getNode());
else
LabelID = recordSourceLine(DLT.getLineNumber(),
DLT.getColumnNumber(),
DLT.getScope().getNode());
Asm->printLabel(LabelID);
O << '\n';
}
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// endFunction - Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
if (!ShouldEmitDwarfDebug()) return;
if (TimePassesIsEnabled)
DebugTimer->startTimer();
if (DbgScopeMap.empty())
return;
Devang Patel
committed
if (CurrentFnDbgScope) {
// Define end label for subprogram.
Asm->OutStreamer.EmitLabel(getDWLabel("func_end", SubprogramCount));
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
// Get function line info.
if (!Lines.empty()) {
// Get section line info.
unsigned ID = SectionMap.insert(Asm->getCurrentSection());
if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
std::vector<SrcLineInfo> &SectionLineInfos = SectionSourceLines[ID-1];
// Append the function info to section info.
SectionLineInfos.insert(SectionLineInfos.end(),
Lines.begin(), Lines.end());
}
// Construct abstract scopes.
for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
AE = AbstractScopesList.end(); AI != AE; ++AI)
constructScopeDIE(*AI);
constructScopeDIE(CurrentFnDbgScope);
DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
MMI->getFrameMoves()));
DbgScopeMap.clear();
DbgScopeBeginMap.clear();
DbgScopeEndMap.clear();
ConcreteScopes.clear();
AbstractScopesList.clear();
Devang Patel
committed
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// recordSourceLine - Records location information and associates it with a
/// label. Returns a unique label ID used to generate a label and provide
/// correspondence to the source line list.
unsigned DwarfDebug::recordSourceLine(unsigned Line, unsigned Col,
MDNode *S) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
StringRef Dir;
StringRef Fn;
DIDescriptor Scope(S);
if (Scope.isCompileUnit()) {
DICompileUnit CU(S);
Dir = CU.getDirectory();
Fn = CU.getFilename();
} else if (Scope.isSubprogram()) {
DISubprogram SP(S);
Dir = SP.getDirectory();
Fn = SP.getFilename();
} else if (Scope.isLexicalBlock()) {
DILexicalBlock DB(S);
Dir = DB.getDirectory();
Fn = DB.getFilename();
} else
assert (0 && "Unexpected scope info");
unsigned Src = GetOrCreateSourceID(Dir, Fn);
unsigned ID = MMI->NextLabelID();
Lines.push_back(SrcLineInfo(Line, Col, Src, ID));
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
/// getOrCreateSourceID - Public version of GetOrCreateSourceID. This can be
/// timed. Look up the source id with the given directory and source file
/// names. If none currently exists, create a new id and insert it in the
/// SourceIds map. This can update DirectoryNames and SourceFileNames maps as
/// well.
unsigned DwarfDebug::getOrCreateSourceID(const std::string &DirName,
const std::string &FileName) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
unsigned SrcId = GetOrCreateSourceID(DirName.c_str(), FileName.c_str());
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
return SrcId;
//===----------------------------------------------------------------------===//
// 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();
// 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(TD, 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() {
// Compute size of compile unit header.
static unsigned Offset =
sizeof(int32_t) + // Length of Compilation Unit Info
sizeof(int16_t) + // DWARF version number
sizeof(int32_t) + // Offset Into Abbrev. Section
sizeof(int8_t); // Pointer Size (in bytes)
computeSizeAndOffset(ModuleCU->getCUDie(), Offset, true);
/// emitInitial - Emit initial Dwarf declarations. This is necessary for cc
/// tools to recognize the object file contains Dwarf information.
void DwarfDebug::emitInitial() {
// Check to see if we already emitted intial headers.
if (didInitial) return;
didInitial = true;
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
// Dwarf sections base addresses.
if (MAI->doesDwarfRequireFrameSection()) {
Asm->OutStreamer.SwitchSection(TLOF.getDwarfFrameSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_debug_frame"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfInfoSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_info"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfAbbrevSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_abbrev"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfARangesSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_aranges"));
if (const MCSection *LineInfoDirective = TLOF.getDwarfMacroInfoSection()) {
Asm->OutStreamer.SwitchSection(LineInfoDirective);
Asm->OutStreamer.EmitLabel(getTempLabel("section_macinfo"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfLineSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_line"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfLocSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_loc"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubNamesSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_pubnames"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfPubTypesSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_pubtypes"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfStrSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_str"));
Asm->OutStreamer.SwitchSection(TLOF.getDwarfRangesSection());
Asm->OutStreamer.EmitLabel(getTempLabel("section_ranges"));
Asm->OutStreamer.SwitchSection(TLOF.getTextSection());
Asm->OutStreamer.EmitLabel(getTempLabel("text_begin"));
Asm->OutStreamer.SwitchSection(TLOF.getDataSection());
Asm->OutStreamer.EmitLabel(getTempLabel("data_begin"));
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
Bill Wendling
committed
// Emit the code (index) for the abbreviation.
if (Asm->VerboseAsm)
Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" +
Twine::utohexstr(Die->getOffset()) + ":0x" +
Twine::utohexstr(Die->getSize()) + " " +
dwarf::TagString(Abbrev->getTag()));
EmitULEB128(AbbrevNumber);
Bill Wendling
committed
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->VerboseAsm)
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;
}
default:
// Emit an attribute using the defined form.
Values[i]->EmitValue(this, Form);
O << "\n"; // REMOVE This once all EmitValue impls emit their own newline.
// 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]);
Asm->EmitInt8(0); EOL("End Of Children Mark");
/// emitDebugInfo - Emit the debug info section.
void DwarfDebug::emitDebugInfo() {
// Start debug info section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfInfoSection());
DIE *Die = ModuleCU->getCUDie();
// Emit the compile units header.
Asm->OutStreamer.EmitLabel(getDWLabel("info_begin", ModuleCU->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->EmitInt32(ContentSize); EOL("Length of Compilation Unit Info");
Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number");
EmitSectionOffset(getTempLabel("abbrev_begin"),getTempLabel("section_abbrev"),
true, false);
EOL("Offset Into Abbrev. Section");
Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)");
emitDIE(Die);
// FIXME - extra padding for gdb bug.
Asm->EmitInt8(0); EOL("Extra Pad For GDB");
Asm->EmitInt8(0); EOL("Extra Pad For GDB");
Asm->EmitInt8(0); EOL("Extra Pad For GDB");
Asm->EmitInt8(0); EOL("Extra Pad For GDB");
Asm->OutStreamer.EmitLabel(getDWLabel("info_end", ModuleCU->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(getTempLabel("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.)
EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
// Emit the abbreviations data.
Abbrev->Emit(this);
// Mark end of abbreviations.
EmitULEB128(0, "EOM(3)");
Asm->OutStreamer.EmitLabel(getTempLabel("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->EmitInt8(0); EOL("Extended Op");
Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size");
Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address");
EmitReference(getDWLabel("section_end", SectionEnd));
EOL("Section end label");
Asm->EmitInt8(0); EOL("DW_LNE_end_sequence");
Asm->EmitInt8(1);
/// emitDebugLines - Emit source line information.
void DwarfDebug::emitDebugLines() {
// If the target is using .loc/.file, the assembler will be emitting the
// .debug_line table automatically.
if (MAI->hasDotLocAndDotFile())
// Minimum line delta, thus ranging from -10..(255-10).
const int MinLineDelta = -(dwarf::DW_LNS_fixed_advance_pc + 1);
// Maximum line delta, thus ranging from -10..(255-10).
const int MaxLineDelta = 255 + MinLineDelta;
// Start the dwarf line section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLineSection());
// Construct the section header.
EmitDifference(getTempLabel("line_end"), getTempLabel("line_begin"), true);
EOL("Length of Source Line Info");
Asm->OutStreamer.EmitLabel(getTempLabel("line_begin"));
Bill Wendling
committed
Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF version number");
EmitDifference(getTempLabel("line_prolog_end"),
getTempLabel("line_prolog_begin"), true);
EOL("Prolog Length");
Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_begin"));
Asm->EmitInt8(1); EOL("Minimum Instruction Length");
Asm->EmitInt8(1); EOL("Default is_stmt_start flag");
Asm->EmitInt8(MinLineDelta); EOL("Line Base Value (Special Opcodes)");
Asm->EmitInt8(MaxLineDelta); EOL("Line Range Value (Special Opcodes)");
Asm->EmitInt8(-MinLineDelta); EOL("Special Opcode Base");
// Line number standard opcode encodings argument count
Asm->EmitInt8(0); EOL("DW_LNS_copy arg count");
Asm->EmitInt8(1); EOL("DW_LNS_advance_pc arg count");
Asm->EmitInt8(1); EOL("DW_LNS_advance_line arg count");
Asm->EmitInt8(1); EOL("DW_LNS_set_file arg count");
Asm->EmitInt8(1); EOL("DW_LNS_set_column arg count");
Asm->EmitInt8(0); EOL("DW_LNS_negate_stmt arg count");
Asm->EmitInt8(0); EOL("DW_LNS_set_basic_block arg count");
Asm->EmitInt8(0); EOL("DW_LNS_const_add_pc arg count");
Asm->EmitInt8(1); EOL("DW_LNS_fixed_advance_pc arg count");
Bill Wendling
committed
// Emit directories.
for (unsigned DI = 1, DE = getNumSourceDirectories()+1; DI != DE; ++DI) {
const std::string &Dir = getSourceDirectoryName(DI);
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Directory");
Asm->OutStreamer.EmitBytes(StringRef(Dir.c_str(), Dir.size()+1), 0);
Asm->EmitInt8(0); EOL("End of directories");
// Emit files.
for (unsigned SI = 1, SE = getNumSourceIds()+1; SI != SE; ++SI) {
// Remember source id starts at 1.
std::pair<unsigned, unsigned> Id = getSourceDirectoryAndFileIds(SI);
const std::string &FN = getSourceFileName(Id.second);
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("Source");
Asm->OutStreamer.EmitBytes(StringRef(FN.c_str(), FN.size()+1), 0);
EmitULEB128(Id.first, "Directory #");
EmitULEB128(0, "Mod date");
EmitULEB128(0, "File size");
Asm->EmitInt8(0); EOL("End of files");
Asm->OutStreamer.EmitLabel(getTempLabel("line_prolog_end"));
// A sequence for each text section.
unsigned SecSrcLinesSize = SectionSourceLines.size();
for (unsigned j = 0; j < SecSrcLinesSize; ++j) {
// Isolate current sections line info.
const std::vector<SrcLineInfo> &LineInfos = SectionSourceLines[j];
Chris Lattner
committed
/*if (Asm->isVerbose()) {
const MCSection *S = SectionMap[j + 1];
O << '\t' << MAI->getCommentString() << " Section"
Chris Lattner
committed
}*/
// Dwarf assumes we start with first line of first source file.
unsigned Source = 1;
unsigned Line = 1;
// Construct rows of the address, source, line, column matrix.
for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
const SrcLineInfo &LineInfo = LineInfos[i];
unsigned LabelID = MMI->MappedLabel(LineInfo.getLabelID());
if (!LabelID) continue;
if (LineInfo.getLine() == 0) continue;
else {
std::pair<unsigned, unsigned> SourceID =
getSourceDirectoryAndFileIds(LineInfo.getSourceID());
O << '\t' << MAI->getCommentString() << ' '
<< getSourceDirectoryName(SourceID.first) << '/'
<< getSourceFileName(SourceID.second)
<< ':' << utostr_32(LineInfo.getLine()) << '\n';
// Define the line address.
Asm->EmitInt8(0); EOL("Extended Op");
Asm->EmitInt8(TD->getPointerSize() + 1); EOL("Op size");
Asm->EmitInt8(dwarf::DW_LNE_set_address); EOL("DW_LNE_set_address");
EmitReference(getDWLabel("label", LabelID)); EOL("Location label");
// If change of source, then switch to the new source.
if (Source != LineInfo.getSourceID()) {
Source = LineInfo.getSourceID();
Asm->EmitInt8(dwarf::DW_LNS_set_file); EOL("DW_LNS_set_file");
EmitULEB128(Source, "New Source");
// If change of line.
if (Line != LineInfo.getLine()) {
// Determine offset.
int Offset = LineInfo.getLine() - Line;
int Delta = Offset - MinLineDelta;
// Update line.
Line = LineInfo.getLine();
// If delta is small enough and in range...
if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
// ... then use fast opcode.
Asm->EmitInt8(Delta - MinLineDelta); EOL("Line Delta");
} else {
// ... otherwise use long hand.
Asm->EmitInt8(dwarf::DW_LNS_advance_line);
EOL("DW_LNS_advance_line");
EmitSLEB128(Offset, "Line Offset");
Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy");
}
} else {
// Copy the previous row (different address or source)
Asm->EmitInt8(dwarf::DW_LNS_copy); EOL("DW_LNS_copy");
emitEndOfLineMatrix(j + 1);
if (SecSrcLinesSize == 0)
// Because we're emitting a debug_line section, we still need a line
// table. The linker and friends expect it to exist. If there's nothing to
// put into it, emit an empty table.
emitEndOfLineMatrix(1);
Asm->OutStreamer.EmitLabel(getTempLabel("line_end"));
/// emitCommonDebugFrame - Emit common frame info into a debug frame section.
void DwarfDebug::emitCommonDebugFrame() {
if (!MAI->doesDwarfRequireFrameSection())
int stackGrowth =
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
TargetFrameInfo::StackGrowsUp ?
TD->getPointerSize() : -TD->getPointerSize();
// Start the dwarf frame section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfFrameSection());
Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common"));
EmitDifference("debug_frame_common_end", 0,
"debug_frame_common_begin", 0, true);
EOL("Length of Common Information Entry");
Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_begin"));
Asm->EmitInt32((int)dwarf::DW_CIE_ID);
EOL("CIE Identifier Tag");
Asm->EmitInt8(dwarf::DW_CIE_VERSION);
EOL("CIE Version");
Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator.
EOL("CIE Augmentation");
EmitULEB128(1, "CIE Code Alignment Factor");
EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false));
EOL("CIE RA Column");
std::vector<MachineMove> Moves;
RI->getInitialFrameState(Moves);
EmitFrameMoves(NULL, 0, Moves, false);
Asm->EmitAlignment(2, 0, 0, false);
Asm->OutStreamer.EmitLabel(getTempLabel("debug_frame_common_end"));
/// emitFunctionDebugFrame - Emit per function frame info into a debug frame
DwarfDebug::emitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){
if (!MAI->doesDwarfRequireFrameSection())
// Start the dwarf frame section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfFrameSection());
EmitDifference("debug_frame_end", DebugFrameInfo.Number,
"debug_frame_begin", DebugFrameInfo.Number, true);
EOL("Length of Frame Information Entry");
Asm->OutStreamer.EmitLabel(getDWLabel("debug_frame_begin",
DebugFrameInfo.Number));
EmitSectionOffset(getTempLabel("debug_frame_common"),
getTempLabel("section_debug_frame"), true, false);
EOL("FDE CIE offset");
EmitReference(getDWLabel("func_begin", DebugFrameInfo.Number));
EOL("FDE initial location");
EmitDifference(getDWLabel("func_end", DebugFrameInfo.Number),
getDWLabel("func_begin", DebugFrameInfo.Number));
EOL("FDE address range");
EmitFrameMoves("func_begin", DebugFrameInfo.Number, DebugFrameInfo.Moves,
false);
Asm->EmitAlignment(2, 0, 0, false);
Asm->OutStreamer.EmitLabel(getDWLabel("debug_frame_end",
DebugFrameInfo.Number));
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
///
void DwarfDebug::emitDebugPubNames() {
// Start the dwarf pubnames section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubNamesSection());
EmitDifference("pubnames_end", ModuleCU->getID(),
"pubnames_begin", ModuleCU->getID(), true);
EOL("Length of Public Names Info");
Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_begin", ModuleCU->getID()));
Bill Wendling
committed
Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("DWARF Version");
Bill Wendling
committed
EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()),
getTempLabel("section_info"),
true, false);
EOL("Offset of Compilation Unit Info");
Bill Wendling
committed
EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(),
EOL("Compilation Unit Length");
const StringMap<DIE*> &Globals = ModuleCU->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->EmitInt32(Entity->getOffset()); EOL("DIE offset");
if (Asm->VerboseAsm)
Asm->OutStreamer.AddComment("External Name");
Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0);
Asm->EmitInt32(0); EOL("End Mark");
Asm->OutStreamer.EmitLabel(getDWLabel("pubnames_end", ModuleCU->getID()));
// Start the dwarf pubnames section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubTypesSection());
EmitDifference("pubtypes_end", ModuleCU->getID(),
"pubtypes_begin", ModuleCU->getID(), true);
EOL("Length of Public Types Info");
Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_begin", ModuleCU->getID()));
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("DWARF Version");
Asm->EmitInt16(dwarf::DWARF_VERSION);
EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()),
getTempLabel("section_info"), true, false);
EOL("Offset of Compilation ModuleCU Info");
EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(),
true);
EOL("Compilation ModuleCU Length");
const StringMap<DIE*> &Globals = ModuleCU->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->VerboseAsm) Asm->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(Entity->getOffset());
if (Asm->VerboseAsm) Asm->OutStreamer.AddComment("External Name");
Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0);
Asm->EmitInt32(0); EOL("End Mark");
Asm->OutStreamer.EmitLabel(getDWLabel("pubtypes_end", ModuleCU->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()) {
// Start the dwarf str section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfStrSection());
// For each of strings in the string pool.
for (unsigned StringID = 1, N = StringPool.size();
StringID <= N; ++StringID) {
// Emit a label for reference from debug information entries.
Asm->OutStreamer.EmitLabel(getDWLabel("string", StringID));
// Emit the string itself.
const std::string &String = StringPool[StringID];
Asm->OutStreamer.EmitBytes(StringRef(String.c_str(), String.size()+1), 0);
/// emitDebugLoc - Emit visible names into a debug loc section.
void DwarfDebug::emitDebugLoc() {
// Start the dwarf loc section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLocSection());
/// EmitDebugARanges - Emit visible names into a debug aranges section.
///
void DwarfDebug::EmitDebugARanges() {
// Start the dwarf aranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfARangesSection());
// FIXME - Mock up
#if 0
CompileUnit *Unit = GetBaseCompileUnit();
// Don't include size of length
Asm->EmitInt32(0x1c); EOL("Length of Address Ranges Info");
Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version");
EmitReference("info_begin", Unit->getID());
EOL("Offset of Compilation Unit Info");
Asm->EmitInt8(TD->getPointerSize()); EOL("Size of Address");
Asm->EmitInt8(0); EOL("Size of Segment Descriptor");
Asm->EmitInt16(0); EOL("Pad (1)");
Asm->EmitInt16(0); EOL("Pad (2)");
EmitReference("text_begin", 0); EOL("Address");
EmitDifference("text_end", 0, "text_begin", 0, true); EOL("Length");
Asm->EmitInt32(0); EOL("EOM (1)");
Asm->EmitInt32(0); EOL("EOM (2)");
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());
/// 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 (!MAI->doesDwarfUsesInlineInfoSection())
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfDebugInlineSection());
EmitDifference("debug_inlined_end", 1,
"debug_inlined_begin", 1, true);
EOL("Length of Debug Inlined Information Entry");
Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_begin", 1));
Asm->EmitInt16(dwarf::DWARF_VERSION); EOL("Dwarf Version");
Asm->EmitInt8(TD->getPointerSize()); EOL("Address Size (in bytes)");
for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
E = InlinedSPNodes.end(); I != E; ++I) {
Devang Patel
committed
DenseMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
SmallVector<InlineInfoLabels, 4> &Labels = II->second;
StringRef LName = SP.getLinkageName();
StringRef Name = SP.getName();
if (LName.empty()) {
Asm->OutStreamer.EmitBytes(Name, 0);
Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator.
} else
EmitSectionOffset(getDWLabel("string",
StringPool.idFor(getRealLinkageName(LName))),
getTempLabel("section_str"), true);
EOL("MIPS linkage name");
EmitSectionOffset(getDWLabel("string", StringPool.idFor(Name)),
getTempLabel("section_str"), false, true);
EOL("Function name");
EmitULEB128(Labels.size(), "Inline count");
for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
LE = Labels.end(); LI != LE; ++LI) {
Asm->EmitInt32(SP->getOffset()); EOL("DIE offset");
if (TD->getPointerSize() == sizeof(int32_t))
O << MAI->getData32bitsDirective();
O << MAI->getData64bitsDirective();
PrintLabelName("label", LI->first); EOL("low_pc");
Asm->OutStreamer.EmitLabel(getDWLabel("debug_inlined_end", 1));