#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",
cl::desc("Make an absence of debug location information explicit."),
cl::init(false));
+static cl::opt<bool> GenerateDwarfPubNamesSection("generate-dwarf-pubnames",
+ cl::Hidden, cl::init(false),
+ cl::desc("Generate DWARF pubnames section"));
+
namespace {
enum DefaultOnOff {
Default, Enable, Disable
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),
+ PrevLabel(NULL), GlobalCUIndexCount(0),
+ InfoHolder(A, &AbbreviationsSet, &Abbreviations, "info_string",
+ DIEValueAllocator),
+ SkeletonAbbrevSet(InitAbbreviationsSetSize),
+ SkeletonHolder(A, &SkeletonAbbrevSet, &SkeletonAbbrevs, "skel_string",
+ DIEValueAllocator) {
DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
DwarfStrSectionSym = TextSectionSym = 0;
- DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0;
+ DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0;
+ DwarfAddrSectionSym = 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(A->getTargetTriple()).isOSDarwin();
if (DarwinGDBCompat == Default) {
if (IsDarwin)
IsDarwinGDBCompat = true;
} else
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.
+// 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);
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) {
+unsigned DwarfUnits::getStringPoolIndex(StringRef Str) {
+ std::pair<MCSymbol*, unsigned> &Entry =
+ StringPool.GetOrCreateValue(Str).getValue();
+ if (Entry.first) return Entry.second;
+
+ Entry.second = NextStringPoolNumber++;
+ Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
+ return Entry.second;
+}
+
+unsigned DwarfUnits::getAddrPoolIndex(MCSymbol *Sym) {
+ std::pair<MCSymbol*, unsigned> &Entry = AddressPool[Sym];
+ if (Entry.first) return Entry.second;
+
+ Entry.second = NextAddrPoolNumber++;
+ Entry.first = Sym;
+ return Entry.second;
+}
+
+// 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);
// If we're updating an abstract DIE, then we will be adding the children and
// object pointer later on. But what we don't want to do is process the
// concrete DIE twice.
- if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) {
+ DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode);
+ if (AbsSPDIE) {
+ bool InSameCU = (AbsSPDIE->getCompileUnit() == SPCU->getCUDie());
// Pick up abstract subprogram DIE.
SPDie = new DIE(dwarf::DW_TAG_subprogram);
+ // If AbsSPDIE belongs to a different CU, use DW_FORM_ref_addr instead of
+ // DW_FORM_ref4.
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin,
- dwarf::DW_FORM_ref4, AbsSPDIE);
+ InSameCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
+ AbsSPDIE);
SPCU->addDie(SPDie);
} else {
DISubprogram SPDecl = SP.getFunctionDeclaration();
}
}
- SPCU->addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber()));
- SPCU->addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- Asm->GetTempSymbol("func_end", Asm->getFunctionNumber()));
+ SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc,
+ Asm->GetTempSymbol("func_begin",
+ Asm->getFunctionNumber()));
+ SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc,
+ Asm->GetTempSymbol("func_end",
+ Asm->getFunctionNumber()));
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
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;
}
- const MCSymbol *Start = getLabelBeforeInsn(RI->first);
- const MCSymbol *End = getLabelAfterInsn(RI->second);
+ MCSymbol *Start = getLabelBeforeInsn(RI->first);
+ MCSymbol *End = getLabelAfterInsn(RI->second);
if (End == 0) return 0;
assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
assert(End->isDefined() && "Invalid end label for an inlined scope!");
- TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start);
- TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End);
+ TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, Start);
+ TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, End);
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();
}
SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
- const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
- const MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
+ MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
+ MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
if (StartLabel == 0 || EndLabel == 0) {
llvm_unreachable("Unexpected Start and End labels for an inlined scope!");
DebugRangeSymbols.push_back(NULL);
DebugRangeSymbols.push_back(NULL);
} else {
- TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- StartLabel);
- TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- EndLabel);
+ TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, StartLabel);
+ TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, EndLabel);
}
InlinedSubprogramDIEs.insert(OriginDIE);
DILocation DL(Scope->getInlinedAt());
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0,
- getOrCreateSourceID(DL.getFilename(), DL.getDirectory()));
+ getOrCreateSourceID(DL.getFilename(), DL.getDirectory(),
+ TheCU->getUniqueID()));
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;
+ DIScope DS(Scope->getScopeNode());
+ // Early return to avoid creating dangling variable|scope DIEs.
+ if (!Scope->getInlinedAt() && DS.isSubprogram() && Scope->isAbstractScope() &&
+ !TheCU->getDIE(DS))
+ return NULL;
+
SmallVector<DIE *, 8> Children;
DIE *ObjectPointer = NULL;
for (unsigned j = 0, M = Scopes.size(); j < M; ++j)
if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j]))
Children.push_back(Nested);
- DIScope DS(Scope->getScopeNode());
DIE *ScopeDIE = NULL;
if (Scope->getInlinedAt())
ScopeDIE = constructInlinedScopeDIE(TheCU, Scope);
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.
+// 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) {
+ StringRef DirName, unsigned CUID) {
+ // If we use .loc in assembly, we can't separate .file entries according to
+ // compile units. Thus all files will belong to the default compile unit.
+ if (Asm->TM.hasMCUseLoc() &&
+ Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer)
+ CUID = 0;
+
// If FE did not provide a file name, then assume stdin.
if (FileName.empty())
- return getOrCreateSourceID("<stdin>", StringRef());
+ return getOrCreateSourceID("<stdin>", StringRef(), CUID);
// TODO: this might not belong here. See if we can factor this better.
if (DirName == CompilationDir)
DirName = "";
- unsigned SrcId = SourceIdMap.size()+1;
+ // FileIDCUMap stores the current ID for the given compile unit.
+ unsigned SrcId = FileIDCUMap[CUID] + 1;
- // We look up the file/dir pair by concatenating them with a zero byte.
+ // We look up the CUID/file/dir by concatenating them with a zero byte.
SmallString<128> NamePair;
+ NamePair += utostr(CUID);
+ NamePair += '\0';
NamePair += DirName;
NamePair += '\0'; // Zero bytes are not allowed in paths.
NamePair += FileName;
if (Ent.getValue() != SrcId)
return Ent.getValue();
+ FileIDCUMap[CUID] = SrcId;
// Print out a .file directive to specify files for .loc directives.
- Asm->OutStreamer.EmitDwarfFileDirective(SrcId, DirName, FileName);
+ Asm->OutStreamer.EmitDwarfFileDirective(SrcId, DirName, FileName, CUID);
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);
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);
+
+ FileIDCUMap[NewCU->getUniqueID()] = 0;
+ // Call this to emit a .file directive if it wasn't emitted for the source
+ // file this CU comes from yet.
+ getOrCreateSourceID(FN, CompilationDir, NewCU->getUniqueID());
+
NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer());
NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
DIUnit.getLanguage());
NewCU->addString(Die, dwarf::DW_AT_name, FN);
+
// 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);
+ // into an entity. We're using 0 (or a NULL label) for this. For
+ // split dwarf it's in the skeleton CU so omit it here.
+ if (!useSplitDwarf())
+ NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL);
+
+ // Define start line table label for each Compile Unit.
+ MCSymbol *LineTableStartSym = Asm->GetTempSymbol("line_table_start",
+ NewCU->getUniqueID());
+ Asm->OutStreamer.getContext().setMCLineTableSymbol(LineTableStartSym,
+ NewCU->getUniqueID());
+
// 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);
+ // compile unit in debug_line section. For split dwarf this is
+ // left in the skeleton CU and so not included.
+ // The line table entries are not always emitted in assembly, so it
+ // is not okay to use line_table_start here.
+ if (!useSplitDwarf()) {
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
+ NewCU->getUniqueID() == 0 ?
+ Asm->GetTempSymbol("section_line") : LineTableStartSym);
+ else if (NewCU->getUniqueID() == 0)
+ NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
+ else
+ NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
+ LineTableStartSym, DwarfLineSectionSym);
+ }
- if (!CompilationDir.empty())
+ // If we're using split dwarf the compilation dir is going to be in the
+ // skeleton CU and so we don't need to duplicate it here.
+ if (!useSplitDwarf() && !CompilationDir.empty())
NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
if (DIUnit.isOptimized())
NewCU->addFlag(Die, dwarf::DW_AT_APPLE_optimized);
if (!FirstCU)
FirstCU = NewCU;
+
+ 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];
// Add to context owner.
TheCU->addToContextOwner(SubprogramDie, SP.getContext());
- return;
+ // Expose as global, if requested.
+ if (GenerateDwarfPubNamesSection)
+ TheCU->addGlobalName(SP.getName(), SubprogramDie);
}
-/// collectInfoFromNamedMDNodes - 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) {
- const MDNode *N = NMD->getOperand(i);
- if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit()))
- constructSubprogramDIE(CU, N);
- }
-
- if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"))
- for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
- const MDNode *N = NMD->getOperand(i);
- if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit()))
- CU->createGlobalVariableDIE(N);
- }
-
- if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum"))
- for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
- DIType Ty(NMD->getOperand(i));
- if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit()))
- CU->getOrCreateTypeDIE(Ty);
- }
-
- if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty"))
- for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
- DIType Ty(NMD->getOperand(i));
- if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit()))
- CU->getOrCreateTypeDIE(Ty);
- }
-}
-
-/// collectLegacyDebugInfo - Collect debug info using DebugInfoFinder.
-/// FIXME - Remove this when dragon-egg and llvm-gcc switch to DIBuilder.
-bool DwarfDebug::collectLegacyDebugInfo(const Module *M) {
- DebugInfoFinder DbgFinder;
- DbgFinder.processModule(*M);
-
- bool HasDebugInfo = false;
- // Scan all the compile-units to see if there are any marked as the main
- // unit. If not, we do not generate debug info.
- for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
- E = DbgFinder.compile_unit_end(); I != E; ++I) {
- if (DICompileUnit(*I).isMain()) {
- HasDebugInfo = true;
- break;
- }
- }
- if (!HasDebugInfo) return false;
-
- // Create all the compile unit DIEs.
- for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
- E = DbgFinder.compile_unit_end(); I != E; ++I)
- constructCompileUnit(*I);
-
- // Create DIEs for each global variable.
- for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
- E = DbgFinder.global_variable_end(); I != E; ++I) {
- const MDNode *N = *I;
- if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit()))
- CU->createGlobalVariableDIE(N);
- }
-
- // Create DIEs for each subprogram.
- for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
- E = DbgFinder.subprogram_end(); I != E; ++I) {
- const MDNode *N = *I;
- if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit()))
- constructSubprogramDIE(CU, N);
- }
-
- 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.
+void DwarfDebug::constructImportedModuleDIE(CompileUnit *TheCU,
+ const MDNode *N) {
+ DIImportedModule Module(N);
+ if (!Module.Verify())
+ return;
+ DIE *IMDie = new DIE(dwarf::DW_TAG_imported_module);
+ TheCU->insertDIE(Module, IMDie);
+ DIE *NSDie = TheCU->getOrCreateNameSpace(Module.getNameSpace());
+ unsigned FileID = getOrCreateSourceID(Module.getContext().getFilename(),
+ Module.getContext().getDirectory(),
+ TheCU->getUniqueID());
+ TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, 0, FileID);
+ TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, 0, Module.getLineNumber());
+ TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, dwarf::DW_FORM_ref4, NSDie);
+ TheCU->addToContextOwner(IMDie, Module.getContext());
+}
+
+// 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;
// If module has named metadata anchors then use them, otherwise scan the
// module using debug info finder to collect debug info.
NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
- if (CU_Nodes) {
- for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
- DICompileUnit CUNode(CU_Nodes->getOperand(i));
- CompileUnit *CU = constructCompileUnit(CUNode);
- DIArray GVs = CUNode.getGlobalVariables();
- for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i)
- CU->createGlobalVariableDIE(GVs.getElement(i));
- DIArray SPs = CUNode.getSubprograms();
- for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i)
- constructSubprogramDIE(CU, SPs.getElement(i));
- DIArray EnumTypes = CUNode.getEnumTypes();
- for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i)
- CU->getOrCreateTypeDIE(EnumTypes.getElement(i));
- DIArray RetainedTypes = CUNode.getRetainedTypes();
- for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i)
- CU->getOrCreateTypeDIE(RetainedTypes.getElement(i));
- }
- } else if (!collectLegacyDebugInfo(M))
+ if (!CU_Nodes)
return;
- collectInfoFromNamedMDNodes(M);
+ // Emit initial sections so we can reference labels later.
+ emitSectionLabels();
+
+ for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
+ DICompileUnit CUNode(CU_Nodes->getOperand(i));
+ CompileUnit *CU = constructCompileUnit(CUNode);
+ DIArray GVs = CUNode.getGlobalVariables();
+ for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i)
+ CU->createGlobalVariableDIE(GVs.getElement(i));
+ DIArray SPs = CUNode.getSubprograms();
+ for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i)
+ constructSubprogramDIE(CU, SPs.getElement(i));
+ DIArray EnumTypes = CUNode.getEnumTypes();
+ for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i)
+ CU->getOrCreateTypeDIE(EnumTypes.getElement(i));
+ DIArray RetainedTypes = CUNode.getRetainedTypes();
+ for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i)
+ CU->getOrCreateTypeDIE(RetainedTypes.getElement(i));
+ // Emit imported_modules last so that the relevant context is already
+ // available.
+ DIArray ImportedModules = CUNode.getImportedModules();
+ for (unsigned i = 0, e = ImportedModules.getNumElements(); i != e; ++i)
+ constructImportedModuleDIE(CU, ImportedModules.getElement(i));
+ // If we're splitting the dwarf out now that we've got the entire
+ // CU then construct a skeleton CU based upon it.
+ if (useSplitDwarf()) {
+ // This should be a unique identifier when we want to build .dwp files.
+ CU->addUInt(CU->getCUDie(), dwarf::DW_AT_GNU_dwo_id,
+ dwarf::DW_FORM_data8, 0);
+ // Now construct the skeleton CU associated.
+ constructSkeletonCU(CUNode);
+ }
+ }
// Tell MMI that we have debug info.
MMI->setDebugInfoAvailability(true);
}
// Compute DIE offsets and sizes.
- computeSizeAndOffsets();
+ InfoHolder.computeSizeAndOffsets();
+ if (useSplitDwarf())
+ SkeletonHolder.computeSizeAndOffsets();
}
void DwarfDebug::endSections() {
}
}
-/// endModule - Emit all Dwarf sections that should come after the content.
-///
+// Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {
if (!FirstCU) return;
// Finalize the debug info for the module.
finalizeModuleInfo();
- // Emit initial sections.
- emitSectionLabels();
-
- if (!useDwarfFission()) {
+ if (!useSplitDwarf()) {
// Emit all the DIEs into a debug info section.
emitDebugInfo();
if (useDarwinGDBCompat())
emitDebugInlineInfo();
} else {
- // TODO: Fill this in for Fission sections and separate
+ // TODO: Fill this in for separated debug sections and separate
// out information into new sections.
- // Emit all the DIEs into a debug info section.
+ // 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 macinfo section.
emitDebugMacInfo();
+ // Emit DWO addresses.
+ InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection());
+
// Emit inline info.
// TODO: When we don't need the option anymore we
// can remove all of the code that this section
emitAccelTypes();
}
+ // Emit info into a debug pubnames section, if requested.
+ if (GenerateDwarfPubNamesSection)
+ emitDebugPubnames();
+
// Emit info into a debug pubtypes section.
// TODO: When we don't need the option anymore we can
// remove all of the code that adds to the table.
// Finally emit string information into a string table.
emitDebugStr();
+ if (useSplitDwarf())
+ emitDebugStrDWO();
// clean up.
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.
+
+ for (SmallVector<CompileUnit *, 1>::iterator I = SkeletonCUs.begin(),
+ E = SkeletonCUs.end(); I != E; ++I)
+ delete *I;
+
+ // Reset these for the next Module if we have one.
+ FirstCU = 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(0).isReg() && MI->getOperand(0).getReg() &&
- MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0;
+ (MI->getOperand(1).isImm() ||
+ (MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U));
}
-/// 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,
MachineLocation MLoc = Asm->getDebugValueLocation(MI);
return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
}
- if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) {
+ if (MI->getOperand(0).isReg()) {
MachineLocation MLoc;
- MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
+ // If the second operand is an immediate, this is a
+ // register-indirect address.
+ if (!MI->getOperand(1).isImm())
+ MLoc.set(MI->getOperand(0).getReg());
+ else
+ MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
}
if (MI->getOperand(0).isImm())
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
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(DV.getContext()).describes(MF->getFunction()))
Scope = LScopes.getCurrentFunctionScope();
- else {
- if (DV.getVersion() <= LLVMDebugVersion9)
- Scope = LScopes.findLexicalScope(MInsn->getDebugLoc());
- else {
- if (MDNode *IA = DV.getInlinedAt())
- Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA));
- else
- Scope = LScopes.findLexicalScope(cast<MDNode>(DV->getOperand(1)));
- }
- }
+ else if (MDNode *IA = DV.getInlinedAt())
+ Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA));
+ else
+ Scope = LScopes.findLexicalScope(cast<MDNode>(DV->getOperand(1)));
// If variable scope is not found then skip this variable.
if (!Scope)
continue;
continue;
}
- // handle multiple DBG_VALUE instructions describing one variable.
+ // Handle multiple DBG_VALUE instructions describing one variable.
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
for (SmallVectorImpl<const MachineInstr*>::const_iterator
}
}
-/// getLabelBeforeInsn - Return Label preceding the instruction.
-const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
+// Return Label preceding the instruction.
+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.
-const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
+// Return Label immediately following the instruction.
+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);
if (LScopes.empty()) return;
identifyScopeMarkers();
+ // Set DwarfCompileUnitID in MCContext to the Compile Unit this function
+ // belongs to.
+ LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
+ CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
+ assert(TheCU && "Unable to find compile unit!");
+ Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID());
+
FunctionBeginSym = Asm->GetTempSymbol("func_begin",
Asm->getFunctionNumber());
// Assumes in correct section after the entry point.
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;
Asm->getFunctionNumber());
// Assumes in correct section after the entry point.
Asm->OutStreamer.EmitLabel(FunctionEndSym);
+ // Set DwarfCompileUnitID in MCContext to default value.
+ Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
SmallPtrSet<const MDNode *, 16> ProcessedVars;
collectVariableInfo(MF, ProcessedVars);
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.getContext().getDwarfCompileUnitID());
}
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) {
+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);
// 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();
+ const SmallVectorImpl<DIEValue*> &Values = Die->getValues();
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData();
// Size the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i)
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() {
+ // Offset from the beginning of debug info section.
+ unsigned AccuOffset = 0;
+ for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
+ E = CUs.end(); I != E; ++I) {
+ (*I)->setDebugInfoOffset(AccuOffset);
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);
+
+ unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset);
+ AccuOffset += EndOffset;
}
}
-/// emitSectionLabels - Emit initial Dwarf sections with a label at
-/// the start of each one.
+// Emit initial Dwarf sections with a label at the start of each one.
void DwarfDebug::emitSectionLabels() {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
DwarfAbbrevSectionSym =
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, TLOF.getDwarfLineSection(), "section_line");
+ DwarfLineSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
emitSectionSym(Asm, TLOF.getDwarfLocSection());
+ if (GenerateDwarfPubNamesSection)
+ emitSectionSym(Asm, TLOF.getDwarfPubNamesSection());
emitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
DwarfStrSectionSym =
- emitSectionSym(Asm, TLOF.getDwarfStrSection(), "section_str");
+ emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string");
+ if (useSplitDwarf()) {
+ DwarfStrDWOSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
+ DwarfAddrSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
+ }
DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(),
"debug_range");
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())
dwarf::TagString(Abbrev->getTag()));
Asm->EmitULEB128(AbbrevNumber);
- const SmallVector<DIEValue*, 32> &Values = Die->getValues();
- const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev->getData();
+ const SmallVectorImpl<DIEValue*> &Values = Die->getValues();
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData();
// Emit the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
DIEEntry *E = cast<DIEEntry>(Values[i]);
DIE *Origin = E->getEntry();
unsigned Addr = Origin->getOffset();
+ if (Form == dwarf::DW_FORM_ref_addr) {
+ // For DW_FORM_ref_addr, output the offset from beginning of debug info
+ // section. Origin->getOffset() returns the offset from start of the
+ // compile unit.
+ DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ Addr += Holder.getCUOffset(Origin->getCompileUnit());
+ }
Asm->EmitInt32(Addr);
break;
}
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 (SmallVectorImpl<CompileUnit *>::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.
-///
+/// For a given compile unit DIE, returns offset from beginning of debug info.
+unsigned DwarfUnits::getCUOffset(DIE *Die) {
+ assert(Die->getTag() == dwarf::DW_TAG_compile_unit &&
+ "Input DIE should be compile unit in getCUOffset.");
+ for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
+ E = CUs.end(); I != E; ++I) {
+ CompileUnit *TheCU = *I;
+ if (TheCU->getCUDie() == Die)
+ return TheCU->getDebugInfoOffset();
+ }
+ llvm_unreachable("The compile unit DIE should belong to CUs in DwarfUnits.");
+}
+
+// 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->OutStreamer.AddComment("Section end label");
Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd),
- Asm->getDataLayout().getPointerSize(),
- 0/*AddrSpace*/);
+ Asm->getDataLayout().getPointerSize());
// Mark end of matrix.
Asm->OutStreamer.AddComment("DW_LNE_end_sequence");
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);
+}
+
+/// emitDebugPubnames - Emit visible names into a debug pubnames section.
+///
+void DwarfDebug::emitDebugPubnames() {
+ const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
+
+ typedef DenseMap<const MDNode*, CompileUnit*> CUMapType;
+ for (CUMapType::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) {
+ CompileUnit *TheCU = I->second;
+ unsigned ID = TheCU->getUniqueID();
+
+ if (TheCU->getGlobalNames().empty())
+ continue;
+
+ // 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", ID),
+ Asm->GetTempSymbol("pubnames_begin", ID), 4);
+
+ Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", ID));
+
+ Asm->OutStreamer.AddComment("DWARF Version");
+ Asm->EmitInt16(dwarf::DWARF_VERSION);
+
+ Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
+ Asm->EmitSectionOffset(Asm->GetTempSymbol(ISec->getLabelBeginName(), ID),
+ DwarfInfoSectionSym);
+
+ Asm->OutStreamer.AddComment("Compilation Unit Length");
+ Asm->EmitLabelDifference(Asm->GetTempSymbol(ISec->getLabelEndName(), ID),
+ Asm->GetTempSymbol(ISec->getLabelBeginName(), ID),
+ 4);
+
+ const StringMap<DIE*> &Globals = TheCU->getGlobalNames();
+ for (StringMap<DIE*>::const_iterator
+ GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
+ const char *Name = GI->getKeyData();
+ const 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", ID));
+ }
}
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();
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name");
// Emit the name with a terminating null byte.
- Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0);
+ Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1));
}
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.
+// Emit strings into a string section.
+void DwarfUnits::emitStrings(const MCSection *StrSection,
+ const MCSection *OffsetSection = NULL,
+ const MCSymbol *StrSecSym = NULL) {
+
if (StringPool.empty()) return;
// Start the dwarf str section.
- Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfStrSection());
+ Asm->OutStreamer.SwitchSection(StrSection);
// 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());
// Emit the string itself with a terminating null byte.
Asm->OutStreamer.EmitBytes(StringRef(Entries[i].second->getKeyData(),
- Entries[i].second->getKeyLength()+1),
- 0/*addrspace*/);
+ Entries[i].second->getKeyLength()+1));
+ }
+
+ // If we've got an offset section go ahead and emit that now as well.
+ if (OffsetSection) {
+ Asm->OutStreamer.SwitchSection(OffsetSection);
+ unsigned offset = 0;
+ unsigned size = 4; // FIXME: DWARF64 is 8.
+ for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
+ Asm->OutStreamer.EmitIntValue(offset, size);
+ offset += Entries[i].second->getKeyLength() + 1;
+ }
}
}
-/// emitDebugLoc - Emit visible names into a debug loc section.
-///
+// Emit strings into a string section.
+void DwarfUnits::emitAddresses(const MCSection *AddrSection) {
+
+ if (AddressPool.empty()) return;
+
+ // Start the dwarf addr section.
+ Asm->OutStreamer.SwitchSection(AddrSection);
+
+ // 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,
+ std::pair<MCSymbol*, unsigned>* >, 64> Entries;
+
+ for (DenseMap<MCSymbol*, std::pair<MCSymbol*, unsigned> >::iterator
+ I = AddressPool.begin(), E = AddressPool.end();
+ I != E; ++I)
+ Entries.push_back(std::make_pair(I->second.second, &(I->second)));
+
+ 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.
+ MCSymbol *Sym = Entries[i].second->first;
+ if (Sym)
+ Asm->EmitLabelReference(Entries[i].second->first,
+ Asm->getDataLayout().getPointerSize());
+ else
+ Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize());
+ }
+
+}
+
+// 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;
- for (SmallVector<DotDebugLocEntry, 4>::iterator
+ for (SmallVectorImpl<DotDebugLocEntry>::iterator
I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
I != E; ++I) {
DotDebugLocEntry &Entry = *I;
unsigned char Size = Asm->getDataLayout().getPointerSize();
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0));
unsigned index = 1;
- for (SmallVector<DotDebugLocEntry, 4>::iterator
+ for (SmallVectorImpl<DotDebugLocEntry>::iterator
I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
I != E; ++I, ++index) {
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.EmitIntValue(0, Size);
+ Asm->OutStreamer.EmitIntValue(0, Size);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index));
} else {
- Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size, 0);
- Asm->OutStreamer.EmitSymbolValue(Entry.End, Size, 0);
+ Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size);
+ Asm->OutStreamer.EmitSymbolValue(Entry.End, Size);
DIVariable DV(Entry.Variable);
Asm->OutStreamer.AddComment("Loc expr size");
MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
}
}
-/// emitDebugARanges - Emit visible names into a debug aranges section.
-///
+// 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(
Asm->getObjFileLowering().getDwarfRangesSection());
unsigned char Size = Asm->getDataLayout().getPointerSize();
- for (SmallVector<const MCSymbol *, 8>::iterator
+ for (SmallVectorImpl<const MCSymbol *>::iterator
I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end();
I != E; ++I) {
if (*I)
- Asm->OutStreamer.EmitSymbolValue(const_cast<MCSymbol*>(*I), Size, 0);
+ Asm->OutStreamer.EmitSymbolValue(const_cast<MCSymbol*>(*I), Size);
else
- Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0);
+ Asm->OutStreamer.EmitIntValue(0, Size);
}
}
-/// 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("Address Size (in bytes)");
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
- for (SmallVector<const MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
+ for (SmallVectorImpl<const MDNode *>::iterator I = InlinedSPNodes.begin(),
E = InlinedSPNodes.end(); I != E; ++I) {
const MDNode *Node = *I;
DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
= InlineInfo.find(Node);
- SmallVector<InlineInfoLabels, 4> &Labels = II->second;
+ SmallVectorImpl<InlineInfoLabels> &Labels = II->second;
DISubprogram SP(Node);
StringRef LName = SP.getLinkageName();
StringRef Name = SP.getName();
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(),
+ for (SmallVectorImpl<InlineInfoLabels>::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->getDataLayout().getPointerSize(),0);
+ Asm->getDataLayout().getPointerSize());
}
}
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);
+ CompilationDir = DIUnit.getDirectory();
+
+ DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
+ CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++,
+ DIUnit.getLanguage(), Die, Asm,
+ this, &SkeletonHolder);
+
+ NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name,
+ DIUnit.getSplitDebugFilename());
+
+ // This should be a unique identifier when we want to build .dwp files.
+ NewCU->addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, 0);
+
+ // Relocate to the beginning of the addr_base section, else 0 for the
+ // beginning of the one for this compile unit.
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ NewCU->addLabel(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset,
+ DwarfAddrSectionSym);
+ else
+ NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base,
+ dwarf::DW_FORM_sec_offset, 0);
+
+ // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
+ // into an entity. We're using 0, or a NULL label for this.
+ 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.
+ // FIXME: Should handle multiple compile units.
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
+ DwarfLineSectionSym);
+ else
+ NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, 0);
+
+ if (!CompilationDir.empty())
+ NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
+
+ SkeletonHolder.addUnit(NewCU);
+ SkeletonCUs.push_back(NewCU);
+
+ return NewCU;
+}
+
+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?");
+ const MCSection *OffSec = Asm->getObjFileLowering()
+ .getDwarfStrOffDWOSection();
+ const MCSymbol *StrSym = DwarfStrSectionSym;
+ InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
+ OffSec, StrSym);
+}