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
namespace {
const char *DWARFGroupName = "DWARF Emission";
const char *DbgTimerName = "DWARF Debug Writer";
+
+ struct CompareFirst {
+ template <typename T> bool operator()(const T &lhs, const T &rhs) const {
+ return lhs.first < rhs.first;
+ }
+ };
} // end anonymous namespace
//===----------------------------------------------------------------------===//
} // end llvm namespace
+/// Return Dwarf Version by checking module flags.
+static unsigned getDwarfVersionFromModule(const Module *M) {
+ SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
+ M->getModuleFlagsMetadata(ModuleFlags);
+ for (unsigned I = 0, E = ModuleFlags.size(); I < E; ++I) {
+ const Module::ModuleFlagEntry &MFE = ModuleFlags[I];
+ StringRef Key = MFE.Key->getString();
+ Value *Val = MFE.Val;
+
+ if (Key == "Dwarf Version")
+ return cast<ConstantInt>(Val)->getZExtValue();
+ }
+ return dwarf::DWARF_VERSION;
+}
+
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
: Asm(A), MMI(Asm->MMI), FirstCU(0),
AbbreviationsSet(InitAbbreviationsSetSize),
PrevLabel(NULL), GlobalCUIndexCount(0),
InfoHolder(A, &AbbreviationsSet, &Abbreviations, "info_string",
DIEValueAllocator),
- SkeletonCU(0),
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
HasSplitDwarf = SplitDwarf == Enable ? true : false;
+ DwarfVersion = getDwarfVersionFromModule(MMI->getModule());
+
{
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
beginModule();
return Entry.second;
}
-unsigned DwarfUnits::getAddrPoolIndex(MCSymbol *Sym) {
- std::pair<MCSymbol*, unsigned> &Entry = AddressPool[Sym];
- if (Entry.first) return Entry.second;
+unsigned DwarfUnits::getAddrPoolIndex(const MCSymbol *Sym) {
+ return getAddrPoolIndex(MCSymbolRefExpr::Create(Sym, Asm->OutContext));
+}
- Entry.second = NextAddrPoolNumber++;
- Entry.first = Sym;
- return Entry.second;
+unsigned DwarfUnits::getAddrPoolIndex(const MCExpr *Sym) {
+ std::pair<DenseMap<const MCExpr *, unsigned>::iterator, bool> P =
+ AddressPool.insert(std::make_pair(Sym, NextAddrPoolNumber));
+ if (P.second)
+ ++NextAddrPoolNumber;
+ return P.first->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);
}
}
-// 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)))
- return LinkageName.substr(1);
- return LinkageName;
-}
-
static bool isObjCClass(StringRef Name) {
return Name.startswith("+") || Name.startswith("-");
}
// 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();
if (Scope->isAbstractScope())
return ScopeDIE;
- const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
+ const SmallVectorImpl<InsnRange> &Ranges = Scope->getRanges();
if (Ranges.empty())
return 0;
- SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
+ // If we have multiple ranges, emit them into the range section.
if (Ranges.size() > 1) {
// .debug_range section has not been laid out yet. Emit offset in
// .debug_range as a uint, size 4, for now. emitDIE will handle
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
DebugRangeSymbols.size()
* Asm->getDataLayout().getPointerSize());
- for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
+ for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
RE = Ranges.end(); RI != RE; ++RI) {
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
}
+
+ // Terminate the range list.
DebugRangeSymbols.push_back(NULL);
DebugRangeSymbols.push_back(NULL);
return ScopeDIE;
}
+ // Construct the address range for this DIE.
+ SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin();
MCSymbol *Start = getLabelBeforeInsn(RI->first);
MCSymbol *End = getLabelAfterInsn(RI->second);
// represent this concrete inlined copy of the function.
DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
LexicalScope *Scope) {
- const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
+ const SmallVectorImpl<InsnRange> &Ranges = Scope->getRanges();
assert(Ranges.empty() == false &&
"LexicalScope does not have instruction markers!");
return NULL;
}
- SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
- 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!");
- }
- assert(StartLabel->isDefined() &&
- "Invalid starting label for an inlined scope!");
- assert(EndLabel->isDefined() &&
- "Invalid end label for an inlined scope!");
-
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
dwarf::DW_FORM_ref4, OriginDIE);
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
DebugRangeSymbols.size()
* Asm->getDataLayout().getPointerSize());
- for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
+ for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
RE = Ranges.end(); RI != RE; ++RI) {
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
DebugRangeSymbols.push_back(NULL);
DebugRangeSymbols.push_back(NULL);
} else {
+ SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin();
+ 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!");
+
+ assert(StartLabel->isDefined() &&
+ "Invalid starting label for an inlined scope!");
+ assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!");
+
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, StartLabel);
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, EndLabel);
}
InlinedSubprogramDIEs.insert(OriginDIE);
- // Track the start label for this inlined function.
- //.debug_inlined section specification does not clearly state how
- // to emit inlined scope that is split into multiple instruction ranges.
- // For now, use first instruction range and emit low_pc/high_pc pair and
- // corresponding .debug_inlined section entry for this pair.
- DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
- I = InlineInfo.find(InlinedSP);
-
- if (I == InlineInfo.end()) {
- InlineInfo[InlinedSP].push_back(std::make_pair(StartLabel, ScopeDIE));
- InlinedSPNodes.push_back(InlinedSP);
- } else
- I->second.push_back(std::make_pair(StartLabel, ScopeDIE));
-
+ // Add the call site information to the DIE.
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());
+ // Track the start label for this inlined function.
+ //.debug_inlined section specification does not clearly state how
+ // to emit inlined scopes that are split into multiple instruction ranges.
+ // For now, use the first instruction range and emit low_pc/high_pc pair and
+ // corresponding the .debug_inlined section entry for this pair.
+ if (Asm->MAI->doesDwarfUseInlineInfoSection()) {
+ MCSymbol *StartLabel = getLabelBeforeInsn(Ranges.begin()->first);
+ InlineInfoMap::iterator I = InlineInfo.find(InlinedSP);
+
+ if (I == InlineInfo.end()) {
+ InlineInfo[InlinedSP].push_back(std::make_pair(StartLabel, ScopeDIE));
+ InlinedSPNodes.push_back(InlinedSP);
+ } else
+ I->second.push_back(std::make_pair(StartLabel, ScopeDIE));
+ }
+
// Add name to the name table, we do this here because we're guaranteed
// to have concrete versions of our DW_TAG_inlined_subprogram nodes.
addSubprogramNames(TheCU, InlinedSP, ScopeDIE);
}
// Collect lexical scope children first.
- const SmallVector<DbgVariable *, 8> &Variables = ScopeVariables.lookup(Scope);
+ const SmallVectorImpl<DbgVariable *> &Variables =ScopeVariables.lookup(Scope);
for (unsigned i = 0, N = Variables.size(); i < N; ++i)
if (DIE *Variable =
TheCU->constructVariableDIE(Variables[i], Scope->isAbstractScope())) {
Children.push_back(Variable);
if (Variables[i]->isObjectPointer()) ObjectPointer = Variable;
}
- const SmallVector<LexicalScope *, 4> &Scopes = Scope->getChildren();
+ const SmallVectorImpl<LexicalScope *> &Scopes = Scope->getChildren();
for (unsigned j = 0, M = Scopes.size(); j < M; ++j)
if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j]))
Children.push_back(Nested);
}
else {
// There is no need to emit empty lexical block DIE.
- if (Children.empty())
+ std::pair<ImportedEntityMap::const_iterator,
+ ImportedEntityMap::const_iterator> Range = std::equal_range(
+ ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(),
+ std::pair<const MDNode *, const MDNode *>(DS, (const MDNode*)0),
+ CompareFirst());
+ if (Children.empty() && Range.first == Range.second)
return NULL;
ScopeDIE = constructLexicalScopeDIE(TheCU, Scope);
+ for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second;
+ ++i)
+ constructImportedEntityDIE(TheCU, i->second, ScopeDIE);
}
if (!ScopeDIE) return NULL;
// Add children
- for (SmallVector<DIE *, 8>::iterator I = Children.begin(),
+ for (SmallVectorImpl<DIE *>::iterator I = Children.begin(),
E = Children.end(); I != E; ++I)
ScopeDIE->addChild(*I);
// 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;
}
DICompileUnit DIUnit(N);
StringRef FN = DIUnit.getFilename();
CompilationDir = DIUnit.getDirectory();
- // 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(GlobalCUIndexCount++,
- DIUnit.getLanguage(), Die, Asm,
+ DIUnit.getLanguage(), Die, N, 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. We're using 0 (or a NULL label) for this.
- NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL);
+ // 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());
+
+ // Use a single line table if we are using .loc and generating assembly.
+ bool UseTheFirstCU =
+ (Asm->TM.hasMCUseLoc() &&
+ Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer) ||
+ (NewCU->getUniqueID() == 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);
+ // 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,
+ UseTheFirstCU ?
+ Asm->GetTempSymbol("section_line") : LineTableStartSym);
+ else if (UseTheFirstCU)
+ 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;
- if (useSplitDwarf()) {
- // 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);
- // Now construct the skeleton CU associated.
- constructSkeletonCU(N);
- }
-
InfoHolder.addUnit(NewCU);
CUMap.insert(std::make_pair(N, NewCU));
// Add to context owner.
TheCU->addToContextOwner(SubprogramDie, SP.getContext());
- return;
+ // Expose as global, if requested.
+ if (GenerateDwarfPubNamesSection)
+ TheCU->addGlobalName(SP.getName(), SubprogramDie);
}
-// 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);
- }
+void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU,
+ const MDNode *N) {
+ DIImportedEntity Module(N);
+ if (!Module.Verify())
+ return;
+ if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext()))
+ constructImportedEntityDIE(TheCU, Module, D);
}
-// Collect debug info using DebugInfoFinder.
-// FIXME - Remove this when dragonegg switches 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;
+void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, const MDNode *N,
+ DIE *Context) {
+ DIImportedEntity Module(N);
+ if (!Module.Verify())
+ return;
+ return constructImportedEntityDIE(TheCU, Module, Context);
+}
+
+void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU,
+ const DIImportedEntity &Module,
+ DIE *Context) {
+ assert(Module.Verify() &&
+ "Use one of the MDNode * overloads to handle invalid metadata");
+ assert(Context && "Should always have a context for an imported_module");
+ DIE *IMDie = new DIE(Module.getTag());
+ TheCU->insertDIE(Module, IMDie);
+ DIE *EntityDie;
+ DIDescriptor Entity = Module.getEntity();
+ if (Entity.isNameSpace())
+ EntityDie = TheCU->getOrCreateNameSpace(DINameSpace(Entity));
+ else if (Entity.isSubprogram())
+ EntityDie = TheCU->getOrCreateSubprogramDIE(DISubprogram(Entity));
+ else if (Entity.isType())
+ EntityDie = TheCU->getOrCreateTypeDIE(DIType(Entity));
+ else
+ EntityDie = TheCU->getDIE(Entity);
+ 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,
+ EntityDie);
+ StringRef Name = Module.getName();
+ if (!Name.empty())
+ TheCU->addString(IMDie, dwarf::DW_AT_name, Name);
+ Context->addChild(IMDie);
}
// Emit all Dwarf sections that should come prior to the content. Create
// 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 ImportedEntities = CUNode.getImportedEntities();
+ for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i)
+ ScopesWithImportedEntities.push_back(std::make_pair(
+ DIImportedEntity(ImportedEntities.getElement(i)).getContext(),
+ ImportedEntities.getElement(i)));
+ std::sort(ScopesWithImportedEntities.begin(),
+ ScopesWithImportedEntities.end(), CompareFirst());
+ 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.
+ for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i)
+ constructImportedEntityDIE(CU, ImportedEntities.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);
// Finalize the debug info for the module.
finalizeModuleInfo();
- // Emit initial sections.
- emitSectionLabels();
-
if (!useSplitDwarf()) {
// Emit all the DIEs into a debug info section.
emitDebugInfo();
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.
E = CUMap.end(); I != E; ++I)
delete I->second;
- delete SkeletonCU;
+ for (SmallVectorImpl<CompileUnit *>::iterator I = SkeletonCUs.begin(),
+ E = SkeletonCUs.end(); I != E; ++I)
+ delete *I;
// Reset these for the next Module if we have one.
FirstCU = NULL;
- SkeletonCU = NULL;
}
// Find abstract variable, if any, associated with Var.
const MachineInstr *MI) {
const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata();
- if (MI->getNumOperands() != 3) {
- MachineLocation MLoc = Asm->getDebugValueLocation(MI);
- return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
- }
+ assert(MI->getNumOperands() == 3);
if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) {
MachineLocation MLoc;
- MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
+ // TODO: Currently an offset of 0 in a DBG_VALUE means
+ // we need to generate a direct register value.
+ // There is no way to specify an indirect value with offset 0.
+ if (MI->getOperand(1).getImm() == 0)
+ 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())
DwarfDebug::collectVariableInfo(const MachineFunction *MF,
SmallPtrSet<const MDNode *, 16> &Processed) {
- // collection info from MMI table.
+ // Grab the variable info that was squirreled away in the MMI side-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;
while (!WorkList.empty()) {
LexicalScope *S = WorkList.pop_back_val();
- const SmallVector<LexicalScope *, 4> &Children = S->getChildren();
+ const SmallVectorImpl<LexicalScope *> &Children = S->getChildren();
if (!Children.empty())
- for (SmallVector<LexicalScope *, 4>::const_iterator SI = Children.begin(),
+ for (SmallVectorImpl<LexicalScope *>::const_iterator SI = Children.begin(),
SE = Children.end(); SI != SE; ++SI)
WorkList.push_back(*SI);
if (S->isAbstractScope())
continue;
- const SmallVector<InsnRange, 4> &Ranges = S->getRanges();
+ const SmallVectorImpl<InsnRange> &Ranges = S->getRanges();
if (Ranges.empty())
continue;
- for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
+ for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
RE = Ranges.end(); RI != RE; ++RI) {
assert(RI->first && "InsnRange does not have first instruction!");
assert(RI->second && "InsnRange does not have second instruction!");
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!");
+ if (Asm->TM.hasMCUseLoc() &&
+ Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer)
+ // Use a single line table if we are using .loc and generating assembly.
+ Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
+ else
+ Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID());
+
FunctionBeginSym = Asm->GetTempSymbol("func_begin",
Asm->getFunctionNumber());
// Assumes in correct section after the entry point.
DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
<< "\t" << *Prev << "\n");
History.pop_back();
- }
- else {
+ } else if (llvm::next(PrevMBB) != PrevMBB->getParent()->end())
// Terminate after LastMI.
History.push_back(LastMI);
- }
}
}
}
if (LastMI == PrevMBB->end())
// Drop DBG_VALUE for empty range.
History.pop_back();
- else {
+ else if (PrevMBB != &PrevMBB->getParent()->back()) {
// Terminate after LastMI.
History.push_back(LastMI);
}
}
void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
-// SmallVector<DbgVariable *, 8> &Vars = ScopeVariables.lookup(LS);
- ScopeVariables[LS].push_back(Var);
-// Vars.push_back(Var);
+ SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
+ DIVariable DV = Var->getVariable();
+ // Variables with positive arg numbers are parameters.
+ if (unsigned ArgNum = DV.getArgNumber()) {
+ // Keep all parameters in order at the start of the variable list to ensure
+ // function types are correct (no out-of-order parameters)
+ //
+ // This could be improved by only doing it for optimized builds (unoptimized
+ // builds have the right order to begin with), searching from the back (this
+ // would catch the unoptimized case quickly), or doing a binary search
+ // rather than linear search.
+ SmallVectorImpl<DbgVariable *>::iterator I = Vars.begin();
+ while (I != Vars.end()) {
+ unsigned CurNum = (*I)->getVariable().getArgNumber();
+ // A local (non-parameter) variable has been found, insert immediately
+ // before it.
+ if (CurNum == 0)
+ break;
+ // A later indexed parameter has been found, insert immediately before it.
+ if (CurNum > ArgNum)
+ break;
+ ++I;
+ }
+ Vars.insert(I, Var);
+ return;
+ }
+
+ Vars.push_back(Var);
}
// Gather and emit post-function debug information.
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);
if (!MF->getTarget().Options.DisableFramePointerElim(*MF))
TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr);
- DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(),
- MMI->getFrameMoves()));
-
// Clear debug info
- for (DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8> >::iterator
+ for (ScopeVariablesMap::iterator
I = ScopeVariables.begin(), E = ScopeVariables.end(); I != E; ++I)
DeleteContainerPointers(I->second);
ScopeVariables.clear();
} 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);
}
// 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)
// Compute the size and offset of all the DIEs.
void DwarfUnits::computeSizeAndOffsets() {
- for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(),
+ // Offset from the beginning of debug info section.
+ unsigned SecOffset = 0;
+ for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I) {
+ (*I)->setDebugInfoOffset(SecOffset);
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)->getCUDie(), Offset);
+ unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset);
+ SecOffset += EndOffset;
}
}
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(), "info_string");
- if (useSplitDwarf())
+ if (useSplitDwarf()) {
DwarfStrDWOSectionSym =
emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
+ DwarfAddrSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
+ }
DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(),
"debug_range");
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();
- Asm->EmitInt32(Addr);
+ 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->OutStreamer.EmitIntValue(Addr,
+ Form == dwarf::DW_FORM_ref_addr ? DIEEntry::getRefAddrSize(Asm) : 4);
break;
}
case dwarf::DW_AT_ranges: {
const MCSection *ASection,
const MCSymbol *ASectionSym) {
Asm->OutStreamer.SwitchSection(USection);
- for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(),
+ for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I) {
CompileUnit *TheCU = *I;
DIE *Die = TheCU->getCUDie();
Asm->OutStreamer.AddComment("Length of Compilation Unit Info");
Asm->EmitInt32(ContentSize);
Asm->OutStreamer.AddComment("DWARF version number");
- Asm->EmitInt16(dwarf::DWARF_VERSION);
+ Asm->EmitInt16(DD->getDwarfVersion());
Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()),
ASectionSym);
}
}
+/// 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;
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNames();
for (StringMap<std::vector<DIE*> >::const_iterator
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
- const char *Name = GI->getKeyData();
+ StringRef Name = GI->getKey();
const std::vector<DIE *> &Entities = GI->second;
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE = Entities.end(); DI != DE; ++DI)
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelObjC();
for (StringMap<std::vector<DIE*> >::const_iterator
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
- const char *Name = GI->getKeyData();
+ StringRef Name = GI->getKey();
const std::vector<DIE *> &Entities = GI->second;
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE = Entities.end(); DI != DE; ++DI)
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNamespace();
for (StringMap<std::vector<DIE*> >::const_iterator
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
- const char *Name = GI->getKeyData();
+ StringRef Name = GI->getKey();
const std::vector<DIE *> &Entities = GI->second;
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE = Entities.end(); DI != DE; ++DI)
= TheCU->getAccelTypes();
for (StringMap<std::vector<std::pair<DIE*, unsigned> > >::const_iterator
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
- const char *Name = GI->getKeyData();
+ StringRef Name = GI->getKey();
const std::vector<std::pair<DIE *, unsigned> > &Entities = GI->second;
for (std::vector<std::pair<DIE *, unsigned> >::const_iterator DI
= Entities.begin(), DE = Entities.end(); DI !=DE; ++DI)
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(DwarfVersion);
+
+ 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, GI->getKeyLength()+1));
+ }
+
+ Asm->OutStreamer.AddComment("End Mark");
+ Asm->EmitInt32(0);
+ Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", ID));
+ }
+}
+
void DwarfDebug::emitDebugPubTypes() {
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
TheCU->getUniqueID()));
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version");
- Asm->EmitInt16(dwarf::DWARF_VERSION);
+ Asm->EmitInt16(DwarfVersion);
Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
// 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;
+ // Order the address pool entries by ID
+ SmallVector<const MCExpr *, 64> Entries(AddressPool.size());
- for (DenseMap<MCSymbol*, std::pair<MCSymbol*, unsigned> >::iterator
- I = AddressPool.begin(), E = AddressPool.end();
+ for (DenseMap<const MCExpr *, 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());
+ Entries[I->second] = I->first;
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());
+ // Emit an expression for reference from debug information entries.
+ if (const MCExpr *Expr = Entries[i])
+ Asm->OutStreamer.EmitValue(Expr, Asm->getDataLayout().getPointerSize());
else
Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize());
}
Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
}
-// Emit visible names into a debug loc section.
+// Emit locations into the 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;
Asm->OutStreamer.EmitIntValue(0, Size);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index));
} else {
- Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size);
- Asm->OutStreamer.EmitSymbolValue(Entry.End, Size);
- DIVariable DV(Entry.Variable);
+ Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size);
+ Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size);
+ DIVariable DV(Entry.getVariable());
Asm->OutStreamer.AddComment("Loc expr size");
MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
Asm->EmitULEB128(Entry.getInt());
}
} else if (Entry.isLocation()) {
+ MachineLocation Loc = Entry.getLoc();
if (!DV.hasComplexAddress())
// Regular entry.
- Asm->EmitDwarfRegOp(Entry.Loc);
+ Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
else {
// Complex address entry.
unsigned N = DV.getNumAddrElements();
unsigned i = 0;
if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) {
- if (Entry.Loc.getOffset()) {
+ if (Loc.getOffset()) {
i = 2;
- Asm->EmitDwarfRegOp(Entry.Loc);
+ Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
Asm->OutStreamer.AddComment("DW_OP_deref");
Asm->EmitInt8(dwarf::DW_OP_deref);
Asm->OutStreamer.AddComment("DW_OP_plus_uconst");
} else {
// If first address element is OpPlus then emit
// DW_OP_breg + Offset instead of DW_OP_reg + Offset.
- MachineLocation Loc(Entry.Loc.getReg(), DV.getAddrElement(1));
- Asm->EmitDwarfRegOp(Loc);
+ MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1));
+ Asm->EmitDwarfRegOp(TLoc, DV.isIndirect());
i = 2;
}
} else {
- Asm->EmitDwarfRegOp(Entry.Loc);
+ Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
}
// Emit remaining complex address elements.
Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
Asm->EmitULEB128(DV.getAddrElement(++i));
} else if (Element == DIBuilder::OpDeref) {
- if (!Entry.Loc.isReg())
+ if (!Loc.isReg())
Asm->EmitInt8(dwarf::DW_OP_deref);
} else
llvm_unreachable("unknown Opcode found in complex address");
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.EmitLabel(Asm->GetTempSymbol("debug_inlined_begin", 1));
Asm->OutStreamer.AddComment("Dwarf Version");
- Asm->EmitInt16(dwarf::DWARF_VERSION);
+ Asm->EmitInt16(DwarfVersion);
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;
+ InlineInfoMap::iterator II = InlineInfo.find(Node);
+ SmallVectorImpl<InlineInfoLabels> &Labels = II->second;
DISubprogram SP(Node);
StringRef LName = SP.getLinkageName();
StringRef Name = SP.getName();
Asm->EmitSectionOffset(InfoHolder.getStringPoolEntry(Name),
DwarfStrSectionSym);
else
- Asm->EmitSectionOffset(InfoHolder
- .getStringPoolEntry(getRealLinkageName(LName)),
- DwarfStrSectionSym);
+ Asm->EmitSectionOffset(
+ InfoHolder.getStringPoolEntry(Function::getRealLinkageName(LName)),
+ DwarfStrSectionSym);
Asm->OutStreamer.AddComment("Function name");
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());
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++,
- DIUnit.getLanguage(), Die, Asm,
+ DIUnit.getLanguage(), Die, N, Asm,
this, &SkeletonHolder);
- SmallString<16> T(DIUnit.getFilename());
- sys::path::replace_extension(T, ".dwo");
- StringRef FN = sys::path::filename(T);
- NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, FN);
+ 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);
- // FIXME: The addr base should be relative for each compile unit, however,
- // this one is going to be 0 anyhow.
- NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset, 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.
// 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,
- Asm->GetTempSymbol("section_line"));
+ 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);
- if (!SkeletonCU)
- SkeletonCU = NewCU;
-
SkeletonHolder.addUnit(NewCU);
+ SkeletonCUs.push_back(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);