#include "DIE.h"
#include "DwarfAccelTable.h"
#include "DwarfCompileUnit.h"
-#include "llvm/Constants.h"
-#include "llvm/DebugInfo.h"
-#include "llvm/DIBuilder.h"
-#include "llvm/Module.h"
-#include "llvm/Instructions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/DIBuilder.h"
+#include "llvm/DebugInfo.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/DataLayout.h"
-#include "llvm/Target/TargetFrameLowering.h"
-#include "llvm/Target/TargetLoweringObjectFile.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Timer.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/ValueHandle.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;
static cl::opt<bool> DisableDebugInfoPrinting("disable-debug-info-print",
clEnumValEnd),
cl::init(Default));
-static cl::opt<DefaultOnOff> DwarfFission("dwarf-fission", cl::Hidden,
- cl::desc("Output prototype dwarf fission."),
+static cl::opt<DefaultOnOff> SplitDwarf("split-dwarf", cl::Hidden,
+ cl::desc("Output prototype dwarf split debug info."),
cl::values(
clEnumVal(Default, "Default for platform"),
clEnumVal(Enable, "Enabled"),
//===----------------------------------------------------------------------===//
-/// Configuration values for initial hash set sizes (log2).
-///
+// Configuration values for initial hash set sizes (log2).
+//
static const unsigned InitAbbreviationsSetSize = 9; // log2(512)
namespace llvm {
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
: Asm(A), MMI(Asm->MMI), FirstCU(0),
AbbreviationsSet(InitAbbreviationsSetSize),
- SourceIdMap(DIEValueAllocator), StringPool(DIEValueAllocator),
- PrevLabel(NULL) {
- NextStringPoolNumber = 0;
+ SourceIdMap(DIEValueAllocator), InfoStringPool(DIEValueAllocator),
+ PrevLabel(NULL), GlobalCUIndexCount(0),
+ InfoHolder(A, &AbbreviationsSet, &Abbreviations,
+ &InfoStringPool, "info_string"),
+ SkeletonCU(0),
+ SkeletonAbbrevSet(InitAbbreviationsSetSize),
+ SkeletonStringPool(DIEValueAllocator),
+ SkeletonHolder(A, &SkeletonAbbrevSet, &SkeletonAbbrevs,
+ &SkeletonStringPool, "skel_string") {
DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
DwarfStrSectionSym = TextSectionSym = 0;
DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0;
+ DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0;
FunctionBeginSym = FunctionEndSym = 0;
// Turn on accelerator tables and older gdb compatibility
// for Darwin.
- bool isDarwin = Triple(M->getTargetTriple()).isOSDarwin();
+ bool IsDarwin = Triple(M->getTargetTriple()).isOSDarwin();
if (DarwinGDBCompat == Default) {
- if (isDarwin)
- isDarwinGDBCompat = true;
+ if (IsDarwin)
+ IsDarwinGDBCompat = true;
else
- isDarwinGDBCompat = false;
+ IsDarwinGDBCompat = false;
} else
- isDarwinGDBCompat = DarwinGDBCompat == Enable ? true : false;
+ IsDarwinGDBCompat = DarwinGDBCompat == Enable ? true : false;
if (DwarfAccelTables == Default) {
- if (isDarwin)
- hasDwarfAccelTables = true;
+ if (IsDarwin)
+ HasDwarfAccelTables = true;
else
- hasDwarfAccelTables = false;
+ HasDwarfAccelTables = false;
} else
- hasDwarfAccelTables = DwarfAccelTables == Enable ? true : false;
+ HasDwarfAccelTables = DwarfAccelTables == Enable ? true : false;
- if (DwarfFission == Default)
- hasDwarfFission = false;
+ if (SplitDwarf == Default)
+ HasSplitDwarf = false;
else
- hasDwarfFission = DwarfFission == Enable ? true : false;
+ HasSplitDwarf = SplitDwarf == Enable ? true : false;
{
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
DwarfDebug::~DwarfDebug() {
}
-/// 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,
+// 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,
const char *SymbolStem = 0) {
Asm->OutStreamer.SwitchSection(Section);
if (!SymbolStem) return 0;
return TmpSym;
}
-MCSymbol *DwarfDebug::getStringPool() {
- return Asm->GetTempSymbol("section_str");
+MCSymbol *DwarfUnits::getStringPoolSym() {
+ return Asm->GetTempSymbol(StringPref);
}
-MCSymbol *DwarfDebug::getStringPoolEntry(StringRef Str) {
- std::pair<MCSymbol*, unsigned> &Entry = StringPool[Str];
+MCSymbol *DwarfUnits::getStringPoolEntry(StringRef Str) {
+ std::pair<MCSymbol*, unsigned> &Entry =
+ StringPool->GetOrCreateValue(Str).getValue();
if (Entry.first) return Entry.first;
Entry.second = NextStringPoolNumber++;
- return Entry.first = Asm->GetTempSymbol("string", Entry.second);
+ return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
}
-/// assignAbbrevNumber - Define a unique number for the abbreviation.
-///
-void DwarfDebug::assignAbbrevNumber(DIEAbbrev &Abbrev) {
+// Define a unique number for the abbreviation.
+//
+void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) {
// Profile the node so that we can make it unique.
FoldingSetNodeID ID;
Abbrev.Profile(ID);
// Check the set for priors.
- DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
+ DIEAbbrev *InSet = AbbreviationsSet->GetOrInsertNode(&Abbrev);
// If it's newly added.
if (InSet == &Abbrev) {
// Add to abbreviation list.
- Abbreviations.push_back(&Abbrev);
+ Abbreviations->push_back(&Abbrev);
// Assign the vector position + 1 as its number.
- Abbrev.setNumber(Abbreviations.size());
+ Abbrev.setNumber(Abbreviations->size());
} else {
// Assign existing abbreviation number.
Abbrev.setNumber(InSet->getNumber());
}
}
-/// getRealLinkageName - If special LLVM prefix that is used to inform the asm
-/// printer to not emit usual symbol prefix before the symbol name is used then
-/// return linkage name after skipping this special LLVM prefix.
+// If special LLVM prefix that is used to inform the asm
+// printer to not emit usual symbol prefix before the symbol name is used then
+// return linkage name after skipping this special LLVM prefix.
static StringRef getRealLinkageName(StringRef LinkageName) {
char One = '\1';
if (LinkageName.startswith(StringRef(&One, 1)))
}
}
-/// updateSubprogramScopeDIE - Find DIE for the given subprogram and
-/// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes.
-/// If there are global variables in this scope then create and insert
-/// DIEs for these variables.
+// Find DIE for the given subprogram and attach appropriate DW_AT_low_pc
+// and DW_AT_high_pc attributes. If there are global variables in this
+// scope then create and insert DIEs for these variables.
DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU,
const MDNode *SPNode) {
DIE *SPDie = SPCU->getDIE(SPNode);
return SPDie;
}
-/// constructLexicalScope - Construct new DW_TAG_lexical_block
-/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels.
+// Construct new DW_TAG_lexical_block for this scope and attach
+// DW_AT_low_pc/DW_AT_high_pc labels.
DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
LexicalScope *Scope) {
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
return ScopeDIE;
}
-/// constructInlinedScopeDIE - This scope represents inlined body of
-/// a function. Construct DIE to represent this concrete inlined copy
-/// of the function.
+// This scope represents inlined body of a function. Construct DIE to
+// represent this concrete inlined copy of the function.
DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
LexicalScope *Scope) {
const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
DILocation DL(Scope->getInlinedAt());
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0,
- GetOrCreateSourceID(DL.getFilename(), DL.getDirectory()));
+ getOrCreateSourceID(DL.getFilename(), DL.getDirectory()));
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber());
// Add name to the name table, we do this here because we're guaranteed
return ScopeDIE;
}
-/// constructScopeDIE - Construct a DIE for this scope.
+// Construct a DIE for this scope.
DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) {
if (!Scope || !Scope->getScopeNode())
return NULL;
return ScopeDIE;
}
-/// GetOrCreateSourceID - 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(StringRef FileName,
+// 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(StringRef FileName,
StringRef DirName) {
// If FE did not provide a file name, then assume stdin.
if (FileName.empty())
- return GetOrCreateSourceID("<stdin>", StringRef());
+ return getOrCreateSourceID("<stdin>", StringRef());
// TODO: this might not belong here. See if we can factor this better.
if (DirName == CompilationDir)
return SrcId;
}
-/// constructCompileUnit - Create new CompileUnit for the given
-/// metadata node with tag DW_TAG_compile_unit.
+// Create new CompileUnit for the given metadata node with tag
+// DW_TAG_compile_unit.
CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
DICompileUnit DIUnit(N);
StringRef FN = DIUnit.getFilename();
CompilationDir = DIUnit.getDirectory();
- unsigned ID = GetOrCreateSourceID(FN, CompilationDir);
+ // Call this to emit a .file directive if it wasn't emitted for the source
+ // file this CU comes from yet.
+ getOrCreateSourceID(FN, CompilationDir);
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
- CompileUnit *NewCU = new CompileUnit(ID, DIUnit.getLanguage(), Die,
- Asm, this);
+ CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++,
+ DIUnit.getLanguage(), Die, Asm,
+ this, &InfoHolder);
NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer());
NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
DIUnit.getLanguage());
if (!FirstCU)
FirstCU = NewCU;
+ if (useSplitDwarf() && !SkeletonCU)
+ SkeletonCU = constructSkeletonCU(N);
+
+ InfoHolder.addUnit(NewCU);
+
CUMap.insert(std::make_pair(N, NewCU));
return NewCU;
}
-/// construct SubprogramDIE - Construct subprogram DIE.
+// Construct subprogram DIE.
void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU,
const MDNode *N) {
CompileUnit *&CURef = SPMap[N];
return;
}
-/// collectInfoFromNamedMDNodes - Collect debug info from named mdnodes such
-/// as llvm.dbg.enum and llvm.dbg.ty
+// Collect debug info from named mdnodes such as llvm.dbg.enum and llvm.dbg.ty.
void DwarfDebug::collectInfoFromNamedMDNodes(const Module *M) {
if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp"))
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
}
}
-/// collectLegacyDebugInfo - Collect debug info using DebugInfoFinder.
-/// FIXME - Remove this when dragon-egg and llvm-gcc switch to DIBuilder.
+// Collect debug info using DebugInfoFinder.
+// FIXME - Remove this when dragonegg switches to DIBuilder.
bool DwarfDebug::collectLegacyDebugInfo(const Module *M) {
DebugInfoFinder DbgFinder;
DbgFinder.processModule(*M);
return HasDebugInfo;
}
-/// beginModule - Emit all Dwarf sections that should come prior to the
-/// content. Create global DIEs and emit initial debug info sections.
-/// This is invoked by the target AsmPrinter.
+// Emit all Dwarf sections that should come prior to the content. Create
+// global DIEs and emit initial debug info sections. This is invoked by
+// the target AsmPrinter.
void DwarfDebug::beginModule() {
if (DisableDebugInfoPrinting)
return;
SectionMap.insert(Asm->getObjFileLowering().getTextSection());
}
-/// endModule - Emit all Dwarf sections that should come after the content.
-///
-void DwarfDebug::endModule() {
-
- if (!FirstCU) return;
+// Attach DW_AT_inline attribute with inlined subprogram DIEs.
+void DwarfDebug::computeInlinedDIEs() {
+ // Attach DW_AT_inline attribute with inlined subprogram DIEs.
+ for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
+ AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
+ DIE *ISP = *AI;
+ FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
+ }
+ for (DenseMap<const MDNode *, DIE *>::iterator AI = AbstractSPDies.begin(),
+ AE = AbstractSPDies.end(); AI != AE; ++AI) {
+ DIE *ISP = AI->second;
+ if (InlinedSubprogramDIEs.count(ISP))
+ continue;
+ FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
+ }
+}
+// Collect info for variables that were optimized out.
+void DwarfDebug::collectDeadVariables() {
const Module *M = MMI->getModule();
DenseMap<const MDNode *, LexicalScope *> DeadFnScopeMap;
- // Collect info for variables that were optimized out.
if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) {
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
DICompileUnit TheCU(CU_Nodes->getOperand(i));
}
}
}
+ DeleteContainerSeconds(DeadFnScopeMap);
+}
+
+void DwarfDebug::finalizeModuleInfo() {
+ // Collect info for variables that were optimized out.
+ collectDeadVariables();
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
- for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
- AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
- DIE *ISP = *AI;
- FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
- }
- for (DenseMap<const MDNode *, DIE *>::iterator AI = AbstractSPDies.begin(),
- AE = AbstractSPDies.end(); AI != AE; ++AI) {
- DIE *ISP = AI->second;
- if (InlinedSubprogramDIEs.count(ISP))
- continue;
- FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
- }
+ computeInlinedDIEs();
// Emit DW_AT_containing_type attribute to connect types with their
// vtable holding type.
TheCU->constructContainingTypeDIEs();
}
+ // Compute DIE offsets and sizes.
+ InfoHolder.computeSizeAndOffsets();
+ if (useSplitDwarf())
+ SkeletonHolder.computeSizeAndOffsets();
+}
+
+void DwarfDebug::endSections() {
// Standard sections final addresses.
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end"));
Asm->OutStreamer.SwitchSection(SectionMap[I]);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", I+1));
}
+}
- // Compute DIE offsets and sizes.
- computeSizeAndOffsets();
+// Emit all Dwarf sections that should come after the content.
+void DwarfDebug::endModule() {
+
+ if (!FirstCU) return;
+
+ // End any existing sections.
+ // TODO: Does this need to happen?
+ endSections();
+
+ // Finalize the debug info for the module.
+ finalizeModuleInfo();
// Emit initial sections.
- EmitSectionLabels();
+ emitSectionLabels();
+
+ if (!useSplitDwarf()) {
+ // Emit all the DIEs into a debug info section.
+ emitDebugInfo();
+
+ // Corresponding abbreviations into a abbrev section.
+ emitAbbreviations();
+
+ // Emit info into a debug loc section.
+ emitDebugLoc();
+
+ // Emit info into a debug aranges section.
+ emitDebugARanges();
+
+ // Emit info into a debug ranges section.
+ emitDebugRanges();
+
+ // Emit info into a debug macinfo section.
+ emitDebugMacInfo();
+
+ // Emit inline info.
+ // TODO: When we don't need the option anymore we
+ // can remove all of the code that this section
+ // depends upon.
+ if (useDarwinGDBCompat())
+ emitDebugInlineInfo();
+ } else {
+ // TODO: Fill this in for separated debug sections and separate
+ // out information into new sections.
+
+ // Emit the debug info section and compile units.
+ emitDebugInfo();
+ emitDebugInfoDWO();
+
+ // Corresponding abbreviations into a abbrev section.
+ emitAbbreviations();
+ emitDebugAbbrevDWO();
+
+ // Emit info into a debug loc section.
+ emitDebugLoc();
+
+ // Emit info into a debug aranges section.
+ emitDebugARanges();
- // Emit all the DIEs into a debug info section
- emitDebugInfo();
+ // Emit info into a debug ranges section.
+ emitDebugRanges();
- // Corresponding abbreviations into a abbrev section.
- emitAbbreviations();
+ // Emit info into a debug macinfo section.
+ emitDebugMacInfo();
+
+ // Emit inline info.
+ // TODO: When we don't need the option anymore we
+ // can remove all of the code that this section
+ // depends upon.
+ if (useDarwinGDBCompat())
+ emitDebugInlineInfo();
+ }
// Emit info into the dwarf accelerator table sections.
if (useDwarfAccelTables()) {
if (useDarwinGDBCompat())
emitDebugPubTypes();
- // Emit info into a debug loc section.
- emitDebugLoc();
-
- // Emit info into a debug aranges section.
- EmitDebugARanges();
-
- // Emit info into a debug ranges section.
- emitDebugRanges();
-
- // Emit info into a debug macinfo section.
- emitDebugMacInfo();
-
- // Emit inline info.
- // TODO: When we don't need the option anymore we
- // can remove all of the code that this section
- // depends upon.
- if (useDarwinGDBCompat())
- emitDebugInlineInfo();
-
- // Emit info into a debug str section.
+ // Finally emit string information into a string table.
emitDebugStr();
+ if (useSplitDwarf())
+ emitDebugStrDWO();
// clean up.
- DeleteContainerSeconds(DeadFnScopeMap);
SPMap.clear();
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I)
delete I->second;
- FirstCU = NULL; // Reset for the next Module, if any.
+
+ delete SkeletonCU;
+
+ // Reset these for the next Module if we have one.
+ FirstCU = NULL;
+ SkeletonCU = NULL;
}
-/// findAbstractVariable - Find abstract variable, if any, associated with Var.
+// Find abstract variable, if any, associated with Var.
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV,
DebugLoc ScopeLoc) {
LLVMContext &Ctx = DV->getContext();
return AbsDbgVariable;
}
-/// addCurrentFnArgument - If Var is a current function argument then add
-/// it to CurrentFnArguments list.
+// If Var is a current function argument then add it to CurrentFnArguments list.
bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
DbgVariable *Var, LexicalScope *Scope) {
if (!LScopes.isCurrentFunctionScope(Scope))
return true;
}
-/// collectVariableInfoFromMMITable - Collect variable information from
-/// side table maintained by MMI.
+// Collect variable information from side table maintained by MMI.
void
DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF,
SmallPtrSet<const MDNode *, 16> &Processed) {
}
}
-/// isDbgValueInDefinedReg - Return true if debug value, encoded by
-/// DBG_VALUE instruction, is in a defined reg.
+// Return true if debug value, encoded by DBG_VALUE instruction, is in a
+// defined reg.
static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
return MI->getNumOperands() == 3 &&
MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0;
}
-/// getDebugLocEntry - Get .debug_loc entry for the instruction range starting
-/// at MI.
+// Get .debug_loc entry for the instruction range starting at MI.
static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
const MCSymbol *FLabel,
const MCSymbol *SLabel,
llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!");
}
-/// collectVariableInfo - Find variables for each lexical scope.
+// Find variables for each lexical scope.
void
DwarfDebug::collectVariableInfo(const MachineFunction *MF,
SmallPtrSet<const MDNode *, 16> &Processed) {
- /// collection info from MMI table.
+ // collection info from MMI table.
collectVariableInfoFromMMITable(MF, Processed);
for (SmallVectorImpl<const MDNode*>::const_iterator
}
}
-/// getLabelBeforeInsn - Return Label preceding the instruction.
+// Return Label preceding the instruction.
const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
assert(Label && "Didn't insert label before instruction");
return Label;
}
-/// getLabelAfterInsn - Return Label immediately following the instruction.
+// Return Label immediately following the instruction.
const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
return LabelsAfterInsn.lookup(MI);
}
-/// beginInstruction - Process beginning of an instruction.
+// Process beginning of an instruction.
void DwarfDebug::beginInstruction(const MachineInstr *MI) {
// Check if source location changes, but ignore DBG_VALUE locations.
if (!MI->isDebugValue()) {
I->second = PrevLabel;
}
-/// endInstruction - Process end of an instruction.
+// Process end of an instruction.
void DwarfDebug::endInstruction(const MachineInstr *MI) {
// Don't create a new label after DBG_VALUE instructions.
// They don't generate code.
I->second = PrevLabel;
}
-/// identifyScopeMarkers() -
-/// 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.
+// 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.
void DwarfDebug::identifyScopeMarkers() {
SmallVector<LexicalScope *, 4> WorkList;
WorkList.push_back(LScopes.getCurrentFunctionScope());
}
}
-/// getScopeNode - Get MDNode for DebugLoc's scope.
+// 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.
+// 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);
return DebugLoc();
}
-/// beginFunction - Gather pre-function debug information. Assumes being
-/// emitted immediately after the function entry point.
+// Gather pre-function debug information. Assumes being called immediately
+// after the function entry point has been emitted.
void DwarfDebug::beginFunction(const MachineFunction *MF) {
if (!MMI->hasDebugInfo()) return;
LScopes.initialize(*MF);
assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned");
const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
- /// LiveUserVar - Map physreg numbers to the MDNode they contain.
+ // 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();
MF->getFunction()->getContext());
recordSourceLine(FnStartDL.getLine(), FnStartDL.getCol(),
FnStartDL.getScope(MF->getFunction()->getContext()),
- 0);
+ // We'd like to list the prologue as "not statements" but GDB behaves
+ // poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
+ DWARF2_FLAG_IS_STMT);
}
}
// Vars.push_back(Var);
}
-/// endFunction - Gather and emit post-function debug information.
-///
+// Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
if (!MMI->hasDebugInfo() || LScopes.empty()) return;
PrevLabel = NULL;
}
-/// recordSourceLine - Register a source line with debug info. Returns the
-/// unique label that was emitted and which provides correspondence to
-/// the source line list.
+// 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) {
StringRef Fn;
} else
llvm_unreachable("Unexpected scope info");
- Src = GetOrCreateSourceID(Fn, Dir);
+ Src = getOrCreateSourceID(Fn, Dir);
}
Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn);
}
// Emit Methods
//===----------------------------------------------------------------------===//
-/// computeSizeAndOffset - Compute the size and offset of a DIE.
-///
+// Compute the size and offset of a DIE.
unsigned
-DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) {
+DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) {
// Get the children.
const std::vector<DIE *> &Children = Die->getChildren();
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
- const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
+ const DIEAbbrev *Abbrev = Abbreviations->at(AbbrevNumber - 1);
// Set DIE offset
Die->setOffset(Offset);
"Children flag not set");
for (unsigned j = 0, M = Children.size(); j < M; ++j)
- Offset = computeSizeAndOffset(Children[j], Offset, (j + 1) == M);
+ Offset = computeSizeAndOffset(Children[j], Offset);
// End of children marker.
Offset += sizeof(int8_t);
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.
+// Compute the size and offset of all the DIEs.
+void DwarfUnits::computeSizeAndOffsets() {
+ for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(),
+ E = CUs.end(); I != E; ++I) {
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(I->second->getCUDie(), Offset, true);
+
+ computeSizeAndOffset((*I)->getCUDie(), Offset);
}
}
-/// EmitSectionLabels - Emit initial Dwarf sections with a label at
-/// the start of each one.
-void DwarfDebug::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.
DwarfInfoSectionSym =
- EmitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
+ emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
DwarfAbbrevSectionSym =
- EmitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
- EmitSectionSym(Asm, TLOF.getDwarfARangesSection());
+ emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
+ if (useSplitDwarf())
+ DwarfAbbrevDWOSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfAbbrevDWOSection(),
+ "section_abbrev_dwo");
+ emitSectionSym(Asm, TLOF.getDwarfARangesSection());
if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection())
- EmitSectionSym(Asm, MacroInfo);
+ emitSectionSym(Asm, MacroInfo);
- EmitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
- EmitSectionSym(Asm, TLOF.getDwarfLocSection());
- EmitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
+ emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
+ emitSectionSym(Asm, TLOF.getDwarfLocSection());
+ emitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
DwarfStrSectionSym =
- EmitSectionSym(Asm, TLOF.getDwarfStrSection(), "section_str");
- DwarfDebugRangeSectionSym = EmitSectionSym(Asm, TLOF.getDwarfRangesSection(),
+ emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string");
+ if (useSplitDwarf())
+ DwarfStrDWOSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
+ DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(),
"debug_range");
- DwarfDebugLocSectionSym = EmitSectionSym(Asm, TLOF.getDwarfLocSection(),
+ DwarfDebugLocSectionSym = emitSectionSym(Asm, TLOF.getDwarfLocSection(),
"section_debug_loc");
- TextSectionSym = EmitSectionSym(Asm, TLOF.getTextSection(), "text_begin");
- EmitSectionSym(Asm, TLOF.getDataSection());
+ TextSectionSym = emitSectionSym(Asm, TLOF.getTextSection(), "text_begin");
+ emitSectionSym(Asm, TLOF.getDataSection());
}
-/// emitDIE - Recursively emits a debug information entry.
-///
-void DwarfDebug::emitDIE(DIE *Die) {
+// Recursively emits a debug information entry.
+void DwarfDebug::emitDIE(DIE *Die, std::vector<DIEAbbrev *> *Abbrevs) {
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
- const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
+ const DIEAbbrev *Abbrev = Abbrevs->at(AbbrevNumber - 1);
// Emit the code (index) for the abbreviation.
if (Asm->isVerbose())
const std::vector<DIE *> &Children = Die->getChildren();
for (unsigned j = 0, M = Children.size(); j < M; ++j)
- emitDIE(Children[j]);
+ emitDIE(Children[j], Abbrevs);
if (Asm->isVerbose())
Asm->OutStreamer.AddComment("End Of Children Mark");
}
}
-/// 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;
+// Emit the various dwarf units to the unit section USection with
+// the abbreviations going into ASection.
+void DwarfUnits::emitUnits(DwarfDebug *DD,
+ const MCSection *USection,
+ const MCSection *ASection,
+ const MCSymbol *ASectionSym) {
+ Asm->OutStreamer.SwitchSection(USection);
+ for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(),
+ E = CUs.end(); I != E; ++I) {
+ CompileUnit *TheCU = *I;
DIE *Die = TheCU->getCUDie();
// Emit the compile units header.
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_begin",
- TheCU->getID()));
+ Asm->OutStreamer
+ .EmitLabel(Asm->GetTempSymbol(USection->getLabelBeginName(),
+ TheCU->getUniqueID()));
// Emit size of content not including length itself
unsigned ContentSize = Die->getSize() +
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->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()),
+ ASectionSym);
Asm->OutStreamer.AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
- emitDIE(Die);
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_end", TheCU->getID()));
+ DD->emitDIE(Die, Abbreviations);
+ Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(USection->getLabelEndName(),
+ TheCU->getUniqueID()));
}
}
-/// emitAbbreviations - Emit the abbreviation section.
-///
-void DwarfDebug::emitAbbreviations() const {
+// Emit the debug info section.
+void DwarfDebug::emitDebugInfo() {
+ DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+
+ Holder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoSection(),
+ Asm->getObjFileLowering().getDwarfAbbrevSection(),
+ DwarfAbbrevSectionSym);
+}
+
+// Emit the abbreviation section.
+void DwarfDebug::emitAbbreviations() {
+ if (!useSplitDwarf())
+ emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection(),
+ &Abbreviations);
+ else
+ emitSkeletonAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
+}
+
+void DwarfDebug::emitAbbrevs(const MCSection *Section,
+ std::vector<DIEAbbrev *> *Abbrevs) {
// Check to see if it is worth the effort.
- if (!Abbreviations.empty()) {
+ if (!Abbrevs->empty()) {
// Start the debug abbrev section.
- Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfAbbrevSection());
+ Asm->OutStreamer.SwitchSection(Section);
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_begin"));
+ MCSymbol *Begin = Asm->GetTempSymbol(Section->getLabelBeginName());
+ Asm->OutStreamer.EmitLabel(Begin);
// For each abbrevation.
- for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) {
+ for (unsigned i = 0, N = Abbrevs->size(); i < N; ++i) {
// Get abbreviation data
- const DIEAbbrev *Abbrev = Abbreviations[i];
+ const DIEAbbrev *Abbrev = Abbrevs->at(i);
// Emit the abbrevations code (base 1 index.)
Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
// Mark end of abbreviations.
Asm->EmitULEB128(0, "EOM(3)");
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_end"));
+ MCSymbol *End = Asm->GetTempSymbol(Section->getLabelEndName());
+ Asm->OutStreamer.EmitLabel(End);
}
}
-/// emitEndOfLineMatrix - Emit the last address of the section and the end of
-/// the line matrix.
-///
+// 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(1);
}
-/// emitAccelNames - Emit visible names into a hashed accelerator table
-/// section.
+// Emit visible names into a hashed accelerator table section.
void DwarfDebug::emitAccelNames() {
DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
- AT.Emit(Asm, SectionBegin, this);
+ AT.Emit(Asm, SectionBegin, &InfoHolder);
}
-/// emitAccelObjC - Emit objective C classes and categories into a hashed
-/// accelerator table section.
+// 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));
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
- AT.Emit(Asm, SectionBegin, this);
+ AT.Emit(Asm, SectionBegin, &InfoHolder);
}
-/// emitAccelNamespace - Emit namespace dies into a hashed accelerator
-/// table.
+// Emit namespace dies into a hashed accelerator table.
void DwarfDebug::emitAccelNamespaces() {
DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
- AT.Emit(Asm, SectionBegin, this);
+ AT.Emit(Asm, SectionBegin, &InfoHolder);
}
-/// emitAccelTypes() - Emit type dies into a hashed accelerator table.
+// Emit type dies into a hashed accelerator table.
void DwarfDebug::emitAccelTypes() {
std::vector<DwarfAccelTable::Atom> Atoms;
Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
- AT.Emit(Asm, SectionBegin, this);
+ AT.Emit(Asm, SectionBegin, &InfoHolder);
}
void DwarfDebug::emitDebugPubTypes() {
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->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()),
+ Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()), 4);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_begin",
- TheCU->getID()));
+ TheCU->getUniqueID()));
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()),
+ const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
+ Asm->EmitSectionOffset(Asm->GetTempSymbol(ISec->getLabelBeginName(),
+ TheCU->getUniqueID()),
DwarfInfoSectionSym);
Asm->OutStreamer.AddComment("Compilation Unit Length");
- Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", TheCU->getID()),
- Asm->GetTempSymbol("info_begin", TheCU->getID()),
+ Asm->EmitLabelDifference(Asm->GetTempSymbol(ISec->getLabelEndName(),
+ TheCU->getUniqueID()),
+ Asm->GetTempSymbol(ISec->getLabelBeginName(),
+ TheCU->getUniqueID()),
4);
const StringMap<DIE*> &Globals = TheCU->getGlobalTypes();
Asm->OutStreamer.AddComment("End Mark");
Asm->EmitInt32(0);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_end",
- TheCU->getID()));
+ TheCU->getUniqueID()));
}
}
-/// 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;
+// Emit strings into a string section.
+void DwarfUnits::emitStrings(const MCSection *Section) {
+
+ if (StringPool->empty()) return;
// Start the dwarf str section.
- Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfStrSection());
+ Asm->OutStreamer.SwitchSection(Section);
// 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;
+ StringMapEntry<std::pair<MCSymbol*, unsigned> >*>, 64> Entries;
for (StringMap<std::pair<MCSymbol*, unsigned> >::iterator
- I = StringPool.begin(), E = StringPool.end(); I != E; ++I)
+ 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());
}
}
-/// emitDebugLoc - Emit visible names into a debug loc section.
-///
+// Emit visible names into a debug str section.
+void DwarfDebug::emitDebugStr() {
+ DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
+}
+
+// Emit visible names into a debug loc section.
void DwarfDebug::emitDebugLoc() {
if (DotDebugLocEntries.empty())
return;
}
}
-/// EmitDebugARanges - Emit visible names into a debug aranges section.
-///
-void DwarfDebug::EmitDebugARanges() {
+// Emit visible names into a debug aranges section.
+void DwarfDebug::emitDebugARanges() {
// Start the dwarf aranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfARangesSection());
}
-/// emitDebugRanges - Emit visible names into a debug ranges section.
-///
+// Emit visible names into a debug ranges section.
void DwarfDebug::emitDebugRanges() {
// Start the dwarf ranges section.
Asm->OutStreamer.SwitchSection(
}
}
-/// emitDebugMacInfo - Emit visible names into a debug macinfo section.
-///
+// Emit visible names into a debug macinfo section.
void DwarfDebug::emitDebugMacInfo() {
if (const MCSection *LineInfo =
Asm->getObjFileLowering().getDwarfMacroInfoSection()) {
}
}
-/// 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.
+// 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->doesDwarfUseInlineInfoSection())
return;
Asm->OutStreamer.AddComment("MIPS linkage name");
if (LName.empty())
- Asm->EmitSectionOffset(getStringPoolEntry(Name), DwarfStrSectionSym);
+ Asm->EmitSectionOffset(InfoHolder.getStringPoolEntry(Name),
+ DwarfStrSectionSym);
else
- Asm->EmitSectionOffset(getStringPoolEntry(getRealLinkageName(LName)),
+ Asm->EmitSectionOffset(InfoHolder
+ .getStringPoolEntry(getRealLinkageName(LName)),
DwarfStrSectionSym);
Asm->OutStreamer.AddComment("Function name");
- Asm->EmitSectionOffset(getStringPoolEntry(Name), DwarfStrSectionSym);
+ Asm->EmitSectionOffset(InfoHolder.getStringPoolEntry(Name),
+ DwarfStrSectionSym);
Asm->EmitULEB128(Labels.size(), "Inline count");
for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_end", 1));
}
+
+// DWARF5 Experimental Separate Dwarf emitters.
+
+// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
+// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
+// DW_AT_ranges_base, DW_AT_addr_base. If DW_AT_ranges is present,
+// DW_AT_low_pc and DW_AT_high_pc are not used, and vice versa.
+CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) {
+ DICompileUnit DIUnit(N);
+ StringRef FN = DIUnit.getFilename();
+ CompilationDir = DIUnit.getDirectory();
+
+ DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
+ CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++,
+ DIUnit.getLanguage(), Die, Asm,
+ this, &SkeletonHolder);
+ // FIXME: This should be the .dwo file.
+ NewCU->addString(Die, dwarf::DW_AT_GNU_dwo_name, FN);
+
+ // FIXME: We also need DW_AT_addr_base and DW_AT_dwo_id.
+
+ // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
+ // into an entity.
+ NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
+ // DW_AT_stmt_list is a offset of line number information for this
+ // compile unit in debug_line section.
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
+ Asm->GetTempSymbol("section_line"));
+ else
+ NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
+
+ if (!CompilationDir.empty())
+ NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
+
+ SkeletonHolder.addUnit(NewCU);
+
+ return NewCU;
+}
+
+void DwarfDebug::emitSkeletonCU(const MCSection *Section) {
+ Asm->OutStreamer.SwitchSection(Section);
+ DIE *Die = SkeletonCU->getCUDie();
+
+ // Emit the compile units header.
+ Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(Section->getLabelBeginName(),
+ SkeletonCU->getUniqueID()));
+
+ // 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");
+
+ const MCSection *ASec = Asm->getObjFileLowering().getDwarfAbbrevSection();
+ Asm->EmitSectionOffset(Asm->GetTempSymbol(ASec->getLabelBeginName()),
+ DwarfAbbrevSectionSym);
+ Asm->OutStreamer.AddComment("Address Size (in bytes)");
+ Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
+
+ emitDIE(Die, &SkeletonAbbrevs);
+ Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(Section->getLabelEndName(),
+ SkeletonCU->getUniqueID()));
+}
+
+void DwarfDebug::emitSkeletonAbbrevs(const MCSection *Section) {
+ assert(useSplitDwarf() && "No split dwarf debug info?");
+ emitAbbrevs(Section, &SkeletonAbbrevs);
+}
+
+// Emit the .debug_info.dwo section for separated dwarf. This contains the
+// compile units that would normally be in debug_info.
+void DwarfDebug::emitDebugInfoDWO() {
+ assert(useSplitDwarf() && "No split dwarf debug info?");
+ InfoHolder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoDWOSection(),
+ Asm->getObjFileLowering().getDwarfAbbrevDWOSection(),
+ DwarfAbbrevDWOSectionSym);
+}
+
+// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the
+// abbreviations for the .debug_info.dwo section.
+void DwarfDebug::emitDebugAbbrevDWO() {
+ assert(useSplitDwarf() && "No split dwarf?");
+ emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection(),
+ &Abbreviations);
+}
+
+// Emit the .debug_str.dwo section for separated dwarf. This contains the
+// string section and is identical in format to traditional .debug_str
+// sections.
+void DwarfDebug::emitDebugStrDWO() {
+ assert(useSplitDwarf() && "No split dwarf?");
+ InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection());
+}