index a21fa673118386582b17a4e5545fc6cfa69d9d98..967c7b1b5964228e04983602962e33e1201eb909 100644 (file)
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "dwarfdebug"
#include "ByteStreamer.h"
#include "DwarfDebug.h"
#include "DIE.h"
#include "DIEHash.h"
-#include "DwarfAccelTable.h"
#include "DwarfUnit.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;
+#define DEBUG_TYPE "dwarfdebug"
+
static cl::opt<bool>
DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
cl::desc("Disable debug info printing"));
//===----------------------------------------------------------------------===//
-namespace llvm {
-
/// resolve - Look in the DwarfDebug map for the MDNode that
/// corresponds to the reference.
template <typename T> T DbgVariable::resolve(DIRef<T> Ref) const {
return Var.isBlockByrefVariable(DD->getTypeIdentifierMap());
}
-
DIType DbgVariable::getType() const {
DIType Ty = Var.getType().resolve(DD->getTypeIdentifierMap());
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
return Ty;
}
-} // end llvm namespace
-
-/// Return Dwarf Version by checking module flags.
-static unsigned getDwarfVersionFromModule(const Module *M) {
- Value *Val = M->getModuleFlag("Dwarf Version");
- if (!Val)
- return dwarf::DWARF_VERSION;
- return cast<ConstantInt>(Val)->getZExtValue();
-}
+static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = {
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)};
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
- : Asm(A), MMI(Asm->MMI), FirstCU(0), PrevLabel(NULL), GlobalRangeCount(0),
- InfoHolder(A, "info_string", DIEValueAllocator),
+ : Asm(A), MMI(Asm->MMI), FirstCU(nullptr), PrevLabel(nullptr),
+ GlobalRangeCount(0), InfoHolder(A, "info_string", DIEValueAllocator),
UsedNonDefaultText(false),
- SkeletonHolder(A, "skel_string", DIEValueAllocator) {
-
- DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = 0;
- DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0;
- DwarfAddrSectionSym = DwarfDebugLocDWOSectionSym = 0;
- DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0;
- FunctionBeginSym = FunctionEndSym = 0;
- CurFn = 0;
- CurMI = 0;
+ SkeletonHolder(A, "skel_string", DIEValueAllocator),
+ AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
+ dwarf::DW_FORM_data4)),
+ AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
+ dwarf::DW_FORM_data4)),
+ AccelNamespace(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
+ dwarf::DW_FORM_data4)),
+ AccelTypes(TypeAtoms) {
+
+ DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = nullptr;
+ DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = nullptr;
+ DwarfLineSectionSym = nullptr;
+ DwarfAddrSectionSym = nullptr;
+ DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = nullptr;
+ FunctionBeginSym = FunctionEndSym = nullptr;
+ CurFn = nullptr;
+ CurMI = nullptr;
// Turn on accelerator tables for Darwin by default, pubnames by
// default for non-Darwin, and handle split dwarf.
else
HasDwarfPubSections = DwarfPubSections == Enable;
- DwarfVersion = DwarfVersionNumber
- ? DwarfVersionNumber
- : getDwarfVersionFromModule(MMI->getModule());
+ DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber
+ : MMI->getModule()->getDwarfVersion();
{
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
}
}
+// Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h.
+DwarfDebug::~DwarfDebug() { }
+
// 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) {
+ const char *SymbolStem = nullptr) {
Asm->OutStreamer.SwitchSection(Section);
if (!SymbolStem)
- return 0;
+ return nullptr;
MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem);
Asm->OutStreamer.EmitLabel(TmpSym);
return TmpSym;
}
-DwarfFile::~DwarfFile() {
- for (DwarfUnit *DU : CUs)
- delete DU;
-}
-
-MCSymbol *DwarfFile::getStringPoolSym() {
- return Asm->GetTempSymbol(StringPref);
-}
-
-MCSymbol *DwarfFile::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(StringPref, Entry.second);
-}
-
-unsigned DwarfFile::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 DwarfFile::getAddrPoolIndex(const MCSymbol *Sym, bool TLS) {
- std::pair<AddrPool::iterator, bool> P = AddressPool.insert(
- std::make_pair(Sym, AddressPoolEntry(NextAddrPoolNumber, TLS)));
- if (P.second)
- ++NextAddrPoolNumber;
- return P.first->second.Number;
-}
-
-// Define a unique number for the abbreviation.
-//
-void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) {
- // Check the set for priors.
- DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
-
- // If it's newly added.
- if (InSet == &Abbrev) {
- // Add to abbreviation list.
- Abbreviations.push_back(&Abbrev);
-
- // Assign the vector position + 1 as its number.
- Abbrev.setNumber(Abbreviations.size());
- } else {
- // Assign existing abbreviation number.
- Abbrev.setNumber(InSet->getNumber());
- }
-}
-
static bool isObjCClass(StringRef Name) {
return Name.startswith("+") || Name.startswith("-");
}
// TODO: Determine whether or not we should add names for programs
// that do not have a DW_AT_name or DW_AT_linkage_name field - this
// is only slightly different than the lookup of non-standard ObjC names.
-static void addSubprogramNames(DwarfUnit *TheU, DISubprogram SP, DIE *Die) {
+void DwarfDebug::addSubprogramNames(DISubprogram SP, DIE &Die) {
if (!SP.isDefinition())
return;
- TheU->addAccelName(SP.getName(), Die);
+ addAccelName(SP.getName(), Die);
// If the linkage name is different than the name, go ahead and output
// that as well into the name table.
if (SP.getLinkageName() != "" && SP.getName() != SP.getLinkageName())
- TheU->addAccelName(SP.getLinkageName(), Die);
+ addAccelName(SP.getLinkageName(), Die);
// If this is an Objective-C selector name add it to the ObjC accelerator
// too.
if (isObjCClass(SP.getName())) {
StringRef Class, Category;
getObjCClassCategory(SP.getName(), Class, Category);
- TheU->addAccelObjC(Class, Die);
+ addAccelObjC(Class, Die);
if (Category != "")
- TheU->addAccelObjC(Category, Die);
+ addAccelObjC(Category, Die);
// Also add the base method name to the name table.
- TheU->addAccelName(getObjCMethodName(SP.getName()), Die);
+ addAccelName(getObjCMethodName(SP.getName()), Die);
}
}
// 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(DwarfCompileUnit *SPCU,
+DIE &DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit &SPCU,
DISubprogram SP) {
- DIE *SPDie = SPCU->getDIE(SP);
-
- assert(SPDie && "Unable to find subprogram DIE!");
-
- // 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(SP)) {
- // Pick up abstract subprogram DIE.
- SPDie =
- SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getUnitDie());
- SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, AbsSPDIE);
- } else {
- DISubprogram SPDecl = SP.getFunctionDeclaration();
- if (!SPDecl.isSubprogram()) {
- // There is not any need to generate specification DIE for a function
- // defined at compile unit level. If a function is defined inside another
- // function then gdb prefers the definition at top level and but does not
- // expect specification DIE in parent function. So avoid creating
- // specification DIE for a function defined inside a function.
- DIScope SPContext = resolve(SP.getContext());
- if (SP.isDefinition() && !SPContext.isCompileUnit() &&
- !SPContext.isFile() && !isSubprogramContext(SPContext)) {
- SPCU->addFlag(SPDie, dwarf::DW_AT_declaration);
-
- // Add arguments.
- DICompositeType SPTy = SP.getType();
- DIArray Args = SPTy.getTypeArray();
- uint16_t SPTag = SPTy.getTag();
- if (SPTag == dwarf::DW_TAG_subroutine_type)
- SPCU->constructSubprogramArguments(*SPDie, Args);
- DIE *SPDeclDie = SPDie;
- SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram,
- *SPCU->getUnitDie());
- SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, SPDeclDie);
- }
- }
- }
+ DIE *SPDie = SPCU.getOrCreateSubprogramDIE(SP);
- attachLowHighPC(SPCU, SPDie, FunctionBeginSym, FunctionEndSym);
+ attachLowHighPC(SPCU, *SPDie, FunctionBeginSym, FunctionEndSym);
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
- SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
+ SPCU.addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
// Add name to the name table, we do this here because we're guaranteed
// to have concrete versions of our DW_TAG_subprogram nodes.
- addSubprogramNames(SPCU, SP, SPDie);
+ addSubprogramNames(SP, *SPDie);
- return SPDie;
+ return *SPDie;
}
/// Check whether we should create a DIE for the given Scope, return true
return !End;
}
-static void addSectionLabel(AsmPrinter *Asm, DwarfUnit *U, DIE *D,
+static void addSectionLabel(AsmPrinter &Asm, DwarfUnit &U, DIE &D,
dwarf::Attribute A, const MCSymbol *L,
const MCSymbol *Sec) {
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- U->addSectionLabel(D, A, L);
+ if (Asm.MAI->doesDwarfUseRelocationsAcrossSections())
+ U.addSectionLabel(D, A, L);
else
- U->addSectionDelta(D, A, L, Sec);
+ U.addSectionDelta(D, A, L, Sec);
}
-void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE,
+void DwarfDebug::addScopeRangeList(DwarfCompileUnit &TheCU, DIE &ScopeDIE,
const SmallVectorImpl<InsnRange> &Range) {
// Emit offset in .debug_range as a relocatable label. emitDIE will handle
// emitting it appropriately.
// Under fission, ranges are specified by constant offsets relative to the
// CU's DW_AT_GNU_ranges_base.
if (useSplitDwarf())
- TheCU->addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, RangeSym,
- DwarfDebugRangeSectionSym);
+ TheCU.addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, RangeSym,
+ DwarfDebugRangeSectionSym);
else
- addSectionLabel(Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym,
+ addSectionLabel(*Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym,
DwarfDebugRangeSectionSym);
RangeSpanList List(RangeSym);
}
// Add the range list to the set of ranges to be emitted.
- TheCU->addRangeList(std::move(List));
+ TheCU.addRangeList(std::move(List));
+}
+
+void DwarfDebug::attachRangesOrLowHighPC(DwarfCompileUnit &TheCU, DIE &Die,
+ const SmallVectorImpl<InsnRange> &Ranges) {
+ assert(!Ranges.empty());
+ if (Ranges.size() == 1)
+ attachLowHighPC(TheCU, Die, getLabelBeforeInsn(Ranges.front().first),
+ getLabelAfterInsn(Ranges.front().second));
+ else
+ addScopeRangeList(TheCU, Die, Ranges);
}
// Construct new DW_TAG_lexical_block for this scope and attach
// DW_AT_low_pc/DW_AT_high_pc labels.
-DIE *DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit *TheCU,
- LexicalScope *Scope) {
+std::unique_ptr<DIE>
+DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
if (isLexicalScopeDIENull(Scope))
- return 0;
+ return nullptr;
- DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
+ auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_lexical_block);
if (Scope->isAbstractScope())
return ScopeDIE;
- const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges();
-
- // If we have multiple ranges, emit them into the range section.
- if (ScopeRanges.size() > 1) {
- addScopeRangeList(TheCU, ScopeDIE, ScopeRanges);
- return ScopeDIE;
- }
-
- // Construct the address range for this DIE.
- SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.begin();
- MCSymbol *Start = getLabelBeforeInsn(RI->first);
- MCSymbol *End = getLabelAfterInsn(RI->second);
- assert(End && "End label should not be null!");
-
- assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
- assert(End->isDefined() && "Invalid end label for an inlined scope!");
-
- attachLowHighPC(TheCU, ScopeDIE, Start, End);
+ attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges());
return ScopeDIE;
}
// This scope represents inlined body of a function. Construct DIE to
// represent this concrete inlined copy of the function.
-DIE *DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit *TheCU,
- LexicalScope *Scope) {
- const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges();
- assert(!ScopeRanges.empty() &&
- "LexicalScope does not have instruction markers!");
-
- if (!Scope->getScopeNode())
- return NULL;
+std::unique_ptr<DIE>
+DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
+ assert(Scope->getScopeNode());
DIScope DS(Scope->getScopeNode());
DISubprogram InlinedSP = getDISubprogram(DS);
- DIE *OriginDIE = TheCU->getDIE(InlinedSP);
- if (!OriginDIE) {
- DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram.");
- return NULL;
- }
+ // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
+ // was inlined from another compile unit.
+ DIE *OriginDIE = AbstractSPDies[InlinedSP];
+ assert(OriginDIE && "Unable to find original DIE for an inlined subprogram.");
- DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
- TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, OriginDIE);
+ auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_inlined_subroutine);
+ TheCU.addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE);
- // If we have multiple ranges, emit them into the range section.
- if (ScopeRanges.size() > 1)
- addScopeRangeList(TheCU, ScopeDIE, ScopeRanges);
- else {
- SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.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!");
-
- attachLowHighPC(TheCU, ScopeDIE, StartLabel, EndLabel);
- }
+ attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges());
InlinedSubprogramDIEs.insert(OriginDIE);
// Add the call site information to the DIE.
DILocation DL(Scope->getInlinedAt());
- TheCU->addUInt(
- ScopeDIE, dwarf::DW_AT_call_file, None,
- TheCU->getOrCreateSourceID(DL.getFilename(), DL.getDirectory()));
- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, None, DL.getLineNumber());
+ TheCU.addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None,
+ TheCU.getOrCreateSourceID(DL.getFilename(), DL.getDirectory()));
+ TheCU.addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, DL.getLineNumber());
// 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);
+ addSubprogramNames(InlinedSP, *ScopeDIE);
return ScopeDIE;
}
-DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU,
- LexicalScope *Scope,
- SmallVectorImpl<DIE *> &Children) {
- DIE *ObjectPointer = NULL;
+static std::unique_ptr<DIE> constructVariableDIE(DwarfCompileUnit &TheCU,
+ DbgVariable &DV,
+ const LexicalScope &Scope,
+ DIE *&ObjectPointer) {
+ auto Var = TheCU.constructVariableDIE(DV, Scope.isAbstractScope());
+ if (DV.isObjectPointer())
+ ObjectPointer = Var.get();
+ return Var;
+}
+
+DIE *DwarfDebug::createScopeChildrenDIE(
+ DwarfCompileUnit &TheCU, LexicalScope *Scope,
+ SmallVectorImpl<std::unique_ptr<DIE>> &Children) {
+ DIE *ObjectPointer = nullptr;
// Collect arguments for current function.
if (LScopes.isCurrentFunctionScope(Scope)) {
for (DbgVariable *ArgDV : CurrentFnArguments)
if (ArgDV)
- if (DIE *Arg =
- TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) {
- Children.push_back(Arg);
- if (ArgDV->isObjectPointer())
- ObjectPointer = Arg;
- }
+ Children.push_back(
+ constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer));
// If this is a variadic function, add an unspecified parameter.
DISubprogram SP(Scope->getScopeNode());
DIArray FnArgs = SP.getType().getTypeArray();
if (FnArgs.getElement(FnArgs.getNumElements() - 1)
.isUnspecifiedParameter()) {
- DIE *Ellipsis = new DIE(dwarf::DW_TAG_unspecified_parameters);
- Children.push_back(Ellipsis);
+ Children.push_back(
+ make_unique<DIE>(dwarf::DW_TAG_unspecified_parameters));
}
}
// Collect lexical scope children first.
for (DbgVariable *DV : ScopeVariables.lookup(Scope))
- if (DIE *Variable = TheCU->constructVariableDIE(*DV,
- Scope->isAbstractScope())) {
- Children.push_back(Variable);
- if (DV->isObjectPointer())
- ObjectPointer = Variable;
- }
+ Children.push_back(constructVariableDIE(TheCU, *DV, *Scope, ObjectPointer));
+
for (LexicalScope *LS : Scope->getChildren())
- if (DIE *Nested = constructScopeDIE(TheCU, LS))
- Children.push_back(Nested);
+ if (std::unique_ptr<DIE> Nested = constructScopeDIE(TheCU, LS))
+ Children.push_back(std::move(Nested));
return ObjectPointer;
}
+void DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope, DIE &ScopeDIE) {
+ // We create children when the scope DIE is not null.
+ SmallVector<std::unique_ptr<DIE>, 8> Children;
+ if (DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children))
+ TheCU.addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
+
+ // Add children
+ for (auto &I : Children)
+ ScopeDIE.addChild(std::move(I));
+}
+
+void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
+ assert(Scope && Scope->getScopeNode());
+ assert(Scope->isAbstractScope());
+ assert(!Scope->getInlinedAt());
+
+ DISubprogram SP(Scope->getScopeNode());
+
+ ProcessedSPNodes.insert(SP);
+
+ DIE *&AbsDef = AbstractSPDies[SP];
+ if (AbsDef)
+ return;
+
+ // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
+ // was inlined from another compile unit.
+ DwarfCompileUnit &SPCU = *SPMap[SP];
+ DIE *ContextDIE;
+
+ // Some of this is duplicated from DwarfUnit::getOrCreateSubprogramDIE, with
+ // the important distinction that the DIDescriptor is not associated with the
+ // DIE (since the DIDescriptor will be associated with the concrete DIE, if
+ // any). It could be refactored to some common utility function.
+ if (DISubprogram SPDecl = SP.getFunctionDeclaration()) {
+ ContextDIE = &SPCU.getUnitDie();
+ SPCU.getOrCreateSubprogramDIE(SPDecl);
+ } else
+ ContextDIE = SPCU.getOrCreateContextDIE(resolve(SP.getContext()));
+
+ // Passing null as the associated DIDescriptor because the abstract definition
+ // shouldn't be found by lookup.
+ AbsDef = &SPCU.createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE,
+ DIDescriptor());
+ SPCU.applySubprogramAttributes(SP, *AbsDef);
+ SPCU.addGlobalName(SP.getName(), *AbsDef, resolve(SP.getContext()));
+
+ SPCU.addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
+ createAndAddScopeChildren(SPCU, Scope, *AbsDef);
+}
+
+DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
+ assert(Scope && Scope->getScopeNode());
+ assert(!Scope->getInlinedAt());
+ assert(!Scope->isAbstractScope());
+ DISubprogram Sub(Scope->getScopeNode());
+
+ assert(Sub.isSubprogram());
+
+ ProcessedSPNodes.insert(Sub);
+
+ DIE &ScopeDIE = updateSubprogramScopeDIE(TheCU, Sub);
+
+ createAndAddScopeChildren(TheCU, Scope, ScopeDIE);
+
+ return ScopeDIE;
+}
+
// Construct a DIE for this scope.
-DIE *DwarfDebug::constructScopeDIE(DwarfCompileUnit *TheCU,
- LexicalScope *Scope) {
+std::unique_ptr<DIE> DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU,
+ LexicalScope *Scope) {
if (!Scope || !Scope->getScopeNode())
- return NULL;
+ return nullptr;
DIScope DS(Scope->getScopeNode());
- SmallVector<DIE *, 8> Children;
- DIE *ObjectPointer = NULL;
- bool ChildrenCreated = false;
+ assert((Scope->getInlinedAt() || !DS.isSubprogram()) &&
+ "Only handle inlined subprograms here, use "
+ "constructSubprogramScopeDIE for non-inlined "
+ "subprograms");
+
+ SmallVector<std::unique_ptr<DIE>, 8> Children;
// We try to create the scope DIE first, then the children DIEs. This will
// avoid creating un-used children then removing them later when we find out
// the scope DIE is null.
- DIE *ScopeDIE = NULL;
- if (Scope->getInlinedAt())
+ std::unique_ptr<DIE> ScopeDIE;
+ if (Scope->getParent() && DS.isSubprogram()) {
ScopeDIE = constructInlinedScopeDIE(TheCU, Scope);
- else if (DS.isSubprogram()) {
- ProcessedSPNodes.insert(DS);
- if (Scope->isAbstractScope()) {
- ScopeDIE = TheCU->getDIE(DS);
- // Note down abstract DIE.
- if (ScopeDIE)
- AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
- } else
- ScopeDIE = updateSubprogramScopeDIE(TheCU, DISubprogram(DS));
+ if (!ScopeDIE)
+ return nullptr;
+ // We create children when the scope DIE is not null.
+ createScopeChildrenDIE(TheCU, Scope, Children);
} else {
// Early exit when we know the scope DIE is going to be null.
if (isLexicalScopeDIENull(Scope))
- return NULL;
+ return nullptr;
// We create children here when we know the scope DIE is not going to be
// null and the children will be added to the scope DIE.
- ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children);
- ChildrenCreated = true;
+ createScopeChildrenDIE(TheCU, Scope, Children);
// There is no need to emit empty lexical block DIE.
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),
- less_first());
+ std::equal_range(ScopesWithImportedEntities.begin(),
+ ScopesWithImportedEntities.end(),
+ std::pair<const MDNode *, const MDNode *>(DS, nullptr),
+ less_first());
if (Children.empty() && Range.first == Range.second)
- return NULL;
+ return nullptr;
ScopeDIE = constructLexicalScopeDIE(TheCU, Scope);
assert(ScopeDIE && "Scope DIE should not be null.");
for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second;
++i)
- constructImportedEntityDIE(TheCU, i->second, ScopeDIE);
- }
-
- if (!ScopeDIE) {
- assert(Children.empty() &&
- "We create children only when the scope DIE is not null.");
- return NULL;
+ constructImportedEntityDIE(TheCU, i->second, *ScopeDIE);
}
- if (!ChildrenCreated)
- // We create children when the scope DIE is not null.
- ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children);
// Add children
- for (DIE *I : Children)
- ScopeDIE->addChild(I);
-
- if (DS.isSubprogram() && ObjectPointer != NULL)
- TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer);
+ for (auto &I : Children)
+ ScopeDIE->addChild(std::move(I));
return ScopeDIE;
}
-void DwarfDebug::addGnuPubAttributes(DwarfUnit *U, DIE *D) const {
+void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const {
if (!GenerateGnuPubSections)
return;
- U->addFlag(D, dwarf::DW_AT_GNU_pubnames);
+ U.addFlag(D, dwarf::DW_AT_GNU_pubnames);
}
// Create new DwarfCompileUnit for the given metadata node with tag
// DW_TAG_compile_unit.
-DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) {
+DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) {
StringRef FN = DIUnit.getFilename();
CompilationDir = DIUnit.getDirectory();
- DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
- DwarfCompileUnit *NewCU = new DwarfCompileUnit(
- InfoHolder.getUnits().size(), Die, DIUnit, Asm, this, &InfoHolder);
- InfoHolder.addUnit(NewCU);
+ auto OwnedUnit = make_unique<DwarfCompileUnit>(
+ InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder);
+ DwarfCompileUnit &NewCU = *OwnedUnit;
+ DIE &Die = NewCU.getUnitDie();
+ InfoHolder.addUnit(std::move(OwnedUnit));
// LTO with assembly output shares a single line table amongst multiple CUs.
// To avoid the compilation directory being ambiguous, let the line table
@@ -701,116 +638,89 @@ DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) {
// compilation directory.
if (!Asm->OutStreamer.hasRawTextSupport() || SingleCU)
Asm->OutStreamer.getContext().setMCLineTableCompilationDir(
- NewCU->getUniqueID(), CompilationDir);
+ NewCU.getUniqueID(), CompilationDir);
- 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);
+ 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);
if (!useSplitDwarf()) {
- NewCU->initStmtList(DwarfLineSectionSym);
+ NewCU.initStmtList(DwarfLineSectionSym);
// 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 (!CompilationDir.empty())
- NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
+ NewCU.addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
addGnuPubAttributes(NewCU, Die);
}
if (DIUnit.isOptimized())
- NewCU->addFlag(Die, dwarf::DW_AT_APPLE_optimized);
+ NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized);
StringRef Flags = DIUnit.getFlags();
if (!Flags.empty())
- NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, Flags);
+ NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags);
if (unsigned RVer = DIUnit.getRunTimeVersion())
- NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
- dwarf::DW_FORM_data1, RVer);
+ NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
+ dwarf::DW_FORM_data1, RVer);
if (!FirstCU)
- FirstCU = NewCU;
+ FirstCU = &NewCU;
if (useSplitDwarf()) {
- NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(),
- DwarfInfoDWOSectionSym);
- NewCU->setSkeleton(constructSkeletonCU(NewCU));
+ NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(),
+ DwarfInfoDWOSectionSym);
+ NewCU.setSkeleton(constructSkeletonCU(NewCU));
} else
- NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(),
- DwarfInfoSectionSym);
+ NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection(),
+ DwarfInfoSectionSym);
- CUMap.insert(std::make_pair(DIUnit, NewCU));
- CUDieMap.insert(std::make_pair(Die, NewCU));
+ CUMap.insert(std::make_pair(DIUnit, &NewCU));
+ CUDieMap.insert(std::make_pair(&Die, &NewCU));
return NewCU;
}
-// Construct subprogram DIE.
-void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit *TheCU,
- const MDNode *N) {
- // FIXME: We should only call this routine once, however, during LTO if a
- // program is defined in multiple CUs we could end up calling it out of
- // beginModule as we walk the CUs.
-
- DwarfCompileUnit *&CURef = SPMap[N];
- if (CURef)
- return;
- CURef = TheCU;
-
- DISubprogram SP(N);
- if (!SP.isDefinition())
- // This is a method declaration which will be handled while constructing
- // class type.
- return;
-
- DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP);
-
- // Expose as a global name.
- TheCU->addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext()));
-}
-
-void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU,
+void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
const MDNode *N) {
DIImportedEntity Module(N);
assert(Module.Verify());
- if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext()))
- constructImportedEntityDIE(TheCU, Module, D);
+ if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext()))
+ constructImportedEntityDIE(TheCU, Module, *D);
}
-void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU,
- const MDNode *N, DIE *Context) {
+void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
+ const MDNode *N, DIE &Context) {
DIImportedEntity Module(N);
assert(Module.Verify());
return constructImportedEntityDIE(TheCU, Module, Context);
}
-void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU,
+void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU,
const DIImportedEntity &Module,
- DIE *Context) {
+ 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 &IMDie = TheCU.createAndAddDIE(Module.getTag(), Context, Module);
DIE *EntityDie;
DIDescriptor Entity = resolve(Module.getEntity());
if (Entity.isNameSpace())
- EntityDie = TheCU->getOrCreateNameSpace(DINameSpace(Entity));
+ EntityDie = TheCU.getOrCreateNameSpace(DINameSpace(Entity));
else if (Entity.isSubprogram())
- EntityDie = TheCU->getOrCreateSubprogramDIE(DISubprogram(Entity));
+ EntityDie = TheCU.getOrCreateSubprogramDIE(DISubprogram(Entity));
else if (Entity.isType())
- EntityDie = TheCU->getOrCreateTypeDIE(DIType(Entity));
+ EntityDie = TheCU.getOrCreateTypeDIE(DIType(Entity));
else
- EntityDie = TheCU->getDIE(Entity);
- TheCU->addSourceLine(IMDie, Module.getLineNumber(),
- Module.getContext().getFilename(),
- Module.getContext().getDirectory());
- TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, EntityDie);
+ EntityDie = TheCU.getDIE(Entity);
+ TheCU.addSourceLine(IMDie, Module.getLineNumber(),
+ Module.getContext().getFilename(),
+ Module.getContext().getDirectory());
+ TheCU.addDIEEntry(IMDie, dwarf::DW_AT_import, *EntityDie);
StringRef Name = Module.getName();
if (!Name.empty())
- TheCU->addString(IMDie, dwarf::DW_AT_name, Name);
- Context->addChild(IMDie);
+ TheCU.addString(IMDie, dwarf::DW_AT_name, Name);
}
// Emit all Dwarf sections that should come prior to the content. Create
for (MDNode *N : CU_Nodes->operands()) {
DICompileUnit CUNode(N);
- DwarfCompileUnit *CU = constructDwarfCompileUnit(CUNode);
+ DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode);
DIArray ImportedEntities = CUNode.getImportedEntities();
for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i)
ScopesWithImportedEntities.push_back(std::make_pair(
ScopesWithImportedEntities.end(), less_first());
DIArray GVs = CUNode.getGlobalVariables();
for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i)
- CU->createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i)));
+ CU.createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i)));
DIArray SPs = CUNode.getSubprograms();
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i)
- constructSubprogramDIE(CU, SPs.getElement(i));
+ SPMap.insert(std::make_pair(SPs.getElement(i), &CU));
DIArray EnumTypes = CUNode.getEnumTypes();
for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i)
- CU->getOrCreateTypeDIE(EnumTypes.getElement(i));
+ CU.getOrCreateTypeDIE(EnumTypes.getElement(i));
DIArray RetainedTypes = CUNode.getRetainedTypes();
for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) {
DIType Ty(RetainedTypes.getElement(i));
// The retained types array by design contains pointers to
// MDNodes rather than DIRefs. Unique them here.
DIType UniqueTy(resolve(Ty.getRef()));
- CU->getOrCreateTypeDIE(UniqueTy);
+ CU.getOrCreateTypeDIE(UniqueTy);
}
// Emit imported_modules last so that the relevant context is already
// available.
SectionMap[Asm->getObjFileLowering().getTextSection()];
}
-// Attach DW_AT_inline attribute with inlined subprogram DIEs.
-void DwarfDebug::computeInlinedDIEs() {
- // Attach DW_AT_inline attribute with inlined subprogram DIEs.
- for (DIE *ISP : InlinedSubprogramDIEs)
- FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
+void DwarfDebug::finishSubprogramDefinitions() {
+ const Module *M = MMI->getModule();
- for (const auto &AI : AbstractSPDies) {
- DIE *ISP = AI.second;
- if (InlinedSubprogramDIEs.count(ISP))
- continue;
- FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
+ NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
+ for (MDNode *N : CU_Nodes->operands()) {
+ DICompileUnit TheCU(N);
+ // Construct subprogram DIE and add variables DIEs.
+ DwarfCompileUnit *SPCU =
+ static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU));
+ DIArray Subprograms = TheCU.getSubprograms();
+ for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) {
+ DISubprogram SP(Subprograms.getElement(i));
+ // Perhaps the subprogram is in another CU (such as due to comdat
+ // folding, etc), in which case ignore it here.
+ if (SPMap[SP] != SPCU)
+ continue;
+ DIE *D = SPCU->getDIE(SP);
+ if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) {
+ if (D)
+ // If this subprogram has an abstract definition, reference that
+ SPCU->addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
+ } else {
+ if (!D)
+ // Lazily construct the subprogram if we didn't see either concrete or
+ // inlined versions during codegen.
+ D = SPCU->getOrCreateSubprogramDIE(SP);
+ // And attach the attributes
+ SPCU->applySubprogramAttributes(SP, *D);
+ SPCU->addGlobalName(SP.getName(), *D, resolve(SP.getContext()));
+ }
+ }
}
}
+
// Collect info for variables that were optimized out.
void DwarfDebug::collectDeadVariables() {
const Module *M = MMI->getModule();
if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) {
for (MDNode *N : CU_Nodes->operands()) {
DICompileUnit TheCU(N);
+ // Construct subprogram DIE and add variables DIEs.
+ DwarfCompileUnit *SPCU =
+ static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU));
+ assert(SPCU && "Unable to find Compile Unit!");
DIArray Subprograms = TheCU.getSubprograms();
for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) {
DISubprogram SP(Subprograms.getElement(i));
if (ProcessedSPNodes.count(SP) != 0)
continue;
- if (!SP.isSubprogram())
- continue;
- if (!SP.isDefinition())
- continue;
+ assert(SP.isSubprogram() &&
+ "CU's subprogram list contains a non-subprogram");
+ assert(SP.isDefinition() &&
+ "CU's subprogram list contains a subprogram declaration");
DIArray Variables = SP.getVariables();
if (Variables.getNumElements() == 0)
continue;
- // Construct subprogram DIE and add variables DIEs.
- DwarfCompileUnit *SPCU =
- static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU));
- assert(SPCU && "Unable to find Compile Unit!");
- // FIXME: See the comment in constructSubprogramDIE about duplicate
- // subprogram DIEs.
- constructSubprogramDIE(SPCU, SP);
- DIE *SPDIE = SPCU->getDIE(SP);
+ DIE *SPDIE = AbstractSPDies.lookup(SP);
+ if (!SPDIE)
+ SPDIE = SPCU->getDIE(SP);
+ assert(SPDIE);
for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) {
DIVariable DV(Variables.getElement(vi));
- if (!DV.isVariable())
- continue;
- DbgVariable NewVar(DV, NULL, this);
- if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, false))
- SPDIE->addChild(VariableDIE);
+ assert(DV.isVariable());
+ DbgVariable NewVar(DV, nullptr, this);
+ SPDIE->addChild(SPCU->constructVariableDIE(NewVar));
}
}
}
}
void DwarfDebug::finalizeModuleInfo() {
+ finishSubprogramDefinitions();
+
// Collect info for variables that were optimized out.
collectDeadVariables();
- // Attach DW_AT_inline attribute with inlined subprogram DIEs.
- computeInlinedDIEs();
-
// Handle anything that needs to be done on a per-unit basis after
// all other generation.
- for (DwarfUnit *TheU : getUnits()) {
+ for (const auto &TheU : getUnits()) {
// Emit DW_AT_containing_type attribute to connect types with their
// vtable holding type.
TheU->constructContainingTypeDIEs();
// Add CU specific attributes if we need to add any.
- if (TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) {
+ if (TheU->getUnitDie().getTag() == dwarf::DW_TAG_compile_unit) {
// If we're splitting the dwarf out now that we've got the entire
// CU then add the dwo id to it.
DwarfCompileUnit *SkCU =
static_cast<DwarfCompileUnit *>(TheU->getSkeleton());
if (useSplitDwarf()) {
// Emit a unique identifier for this CU.
- uint64_t ID = DIEHash(Asm).computeCUSignature(*TheU->getUnitDie());
+ uint64_t ID = DIEHash(Asm).computeCUSignature(TheU->getUnitDie());
TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
dwarf::DW_FORM_data8, ID);
SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
// We don't keep track of which addresses are used in which CU so this
// is a bit pessimistic under LTO.
- if (!InfoHolder.getAddrPool()->empty())
- addSectionLabel(Asm, SkCU, SkCU->getUnitDie(),
+ if (!AddrPool.isEmpty())
+ addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(),
dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym,
DwarfAddrSectionSym);
if (!TheU->getRangeLists().empty())
- addSectionLabel(Asm, SkCU, SkCU->getUnitDie(),
+ addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(),
dwarf::DW_AT_GNU_ranges_base,
DwarfDebugRangeSectionSym, DwarfDebugRangeSectionSym);
}
// FIXME: We should use ranges allow reordering of code ala
// .subsections_via_symbols in mach-o. This would mean turning on
// ranges for all subprogram DIEs for mach-o.
- DwarfCompileUnit *U = SkCU ? SkCU : static_cast<DwarfCompileUnit *>(TheU);
+ DwarfCompileUnit &U =
+ SkCU ? *SkCU : static_cast<DwarfCompileUnit &>(*TheU);
unsigned NumRanges = TheU->getRanges().size();
if (NumRanges) {
if (NumRanges > 1) {
- addSectionLabel(Asm, U, U->getUnitDie(), dwarf::DW_AT_ranges,
- Asm->GetTempSymbol("cu_ranges", U->getUniqueID()),
+ addSectionLabel(*Asm, U, U.getUnitDie(), dwarf::DW_AT_ranges,
+ Asm->GetTempSymbol("cu_ranges", U.getUniqueID()),
DwarfDebugRangeSectionSym);
// A DW_AT_low_pc attribute may also be specified in combination with
// DW_AT_ranges to specify the default base address for use in
// location lists (see Section 2.6.2) and range lists (see Section
// 2.17.3).
- U->addUInt(U->getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- 0);
+ U.addUInt(U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ 0);
} else {
RangeSpan &Range = TheU->getRanges().back();
- U->addLocalLabelAddress(U->getUnitDie(), dwarf::DW_AT_low_pc,
- Range.getStart());
- U->addLabelDelta(U->getUnitDie(), dwarf::DW_AT_high_pc,
- Range.getEnd(), Range.getStart());
+ U.addLocalLabelAddress(U.getUnitDie(), dwarf::DW_AT_low_pc,
+ Range.getStart());
+ U.addLabelDelta(U.getUnitDie(), dwarf::DW_AT_high_pc, Range.getEnd(),
+ Range.getStart());
}
}
}
// Some symbols (e.g. common/bss on mach-o) can have no section but still
// appear in the output. This sucks as we rely on sections to build
// arange spans. We can do it without, but it's icky.
- SectionMap[NULL].push_back(SCU);
+ SectionMap[nullptr].push_back(SCU);
}
}
// Add terminating symbols for each section.
for (unsigned ID = 0, E = Sections.size(); ID != E; ID++) {
const MCSection *Section = Sections[ID];
- MCSymbol *Sym = NULL;
+ MCSymbol *Sym = nullptr;
if (Section) {
// We can't call MCSection::getLabelEndName, as it's only safe to do so
}
// Insert a final terminator.
- SectionMap[Section].push_back(SymbolCU(NULL, Sym));
+ SectionMap[Section].push_back(SymbolCU(nullptr, Sym));
}
}
// Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {
- assert(CurFn == 0);
- assert(CurMI == 0);
+ assert(CurFn == nullptr);
+ assert(CurMI == nullptr);
if (!FirstCU)
return;
// Corresponding abbreviations into a abbrev section.
emitAbbreviations();
- // Emit info into a debug loc section.
- emitDebugLoc();
-
// Emit info into a debug aranges section.
if (GenerateARangeSection)
emitDebugARanges();
emitDebugAbbrevDWO();
emitDebugLineDWO();
// Emit DWO addresses.
- InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection());
- }
+ AddrPool.emit(*Asm, Asm->getObjFileLowering().getDwarfAddrSection());
+ emitDebugLocDWO();
+ } else
+ // Emit info into a debug loc section.
+ emitDebugLoc();
// Emit info into the dwarf accelerator table sections.
if (useDwarfAccelTables()) {
// clean up.
SPMap.clear();
+ AbstractVariables.clear();
// Reset these for the next Module if we have one.
- FirstCU = NULL;
+ FirstCU = nullptr;
}
// Find abstract variable, if any, associated with Var.
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV,
DebugLoc ScopeLoc) {
+ return findAbstractVariable(DV, ScopeLoc.getScope(DV->getContext()));
+}
+
+DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV,
+ const MDNode *ScopeNode) {
LLVMContext &Ctx = DV->getContext();
// More then one inlined variable corresponds to one abstract variable.
DIVariable Var = cleanseInlinedVariable(DV, Ctx);
- DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
- if (AbsDbgVariable)
- return AbsDbgVariable;
+ auto I = AbstractVariables.find(Var);
+ if (I != AbstractVariables.end())
+ return I->second.get();
- LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx));
+ LexicalScope *Scope = LScopes.findAbstractScope(ScopeNode);
if (!Scope)
- return NULL;
+ return nullptr;
- AbsDbgVariable = new DbgVariable(Var, NULL, this);
- addScopeVariable(Scope, AbsDbgVariable);
- AbstractVariables[Var] = AbsDbgVariable;
- return AbsDbgVariable;
+ auto AbsDbgVariable = make_unique<DbgVariable>(Var, nullptr, this);
+ addScopeVariable(Scope, AbsDbgVariable.get());
+ return (AbstractVariables[Var] = std::move(AbsDbgVariable)).get();
}
// If Var is a current function argument then add it to CurrentFnArguments list.
LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
// If variable scope is not found then skip this variable.
- if (Scope == 0)
+ if (!Scope)
continue;
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VI.Loc);
RegVar->setFrameIndex(VI.Slot);
if (!addCurrentFnArgument(RegVar, Scope))
addScopeVariable(Scope, RegVar);
- if (AbsDbgVariable)
- AbsDbgVariable->setFrameIndex(VI.Slot);
}
}
-// 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).isReg() && MI->getOperand(1).getReg() == 0U));
-}
-
// Get .debug_loc entry for the instruction range starting at MI.
-static DebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
- const MCSymbol *FLabel,
- const MCSymbol *SLabel,
- const MachineInstr *MI,
- DwarfCompileUnit *Unit) {
- const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata();
+static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
+ const MDNode *Var = MI->getDebugVariable();
assert(MI->getNumOperands() == 3);
if (MI->getOperand(0).isReg()) {
MLoc.set(MI->getOperand(0).getReg());
else
MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
- return DebugLocEntry(FLabel, SLabel, MLoc, Var, Unit);
+ return DebugLocEntry::Value(Var, MLoc);
}
if (MI->getOperand(0).isImm())
- return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm(), Unit);
+ return DebugLocEntry::Value(Var, MI->getOperand(0).getImm());
if (MI->getOperand(0).isFPImm())
- return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm(), Unit);
+ return DebugLocEntry::Value(Var, MI->getOperand(0).getFPImm());
if (MI->getOperand(0).isCImm())
- return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm(), Unit);
+ return DebugLocEntry::Value(Var, MI->getOperand(0).getCImm());
llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!");
}
// Find variables for each lexical scope.
void
DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) {
+ LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
+ DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
// Grab the variable info that was squirreled away in the MMI side-table.
collectVariableInfoFromMMITable(Processed);
- for (const MDNode *Var : UserVariables) {
- if (Processed.count(Var))
+ for (const auto &I : DbgValues) {
+ DIVariable DV(I.first);
+ if (Processed.count(DV))
continue;
- // History contains relevant DBG_VALUE instructions for Var and instructions
+ // History contains relevant DBG_VALUE instructions for DV and instructions
// clobbering it.
- SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
+ const SmallVectorImpl<const MachineInstr *> &History = I.second;
if (History.empty())
continue;
const MachineInstr *MInsn = History.front();
- DIVariable DV(Var);
- LexicalScope *Scope = NULL;
+ LexicalScope *Scope = nullptr;
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(DV.getContext()).describes(CurFn->getFunction()))
Scope = LScopes.getCurrentFunctionScope();
- 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()) {
+ DebugLoc DL = DebugLoc::getFromDILocation(IA);
+ Scope = LScopes.findInlinedScope(DebugLoc::get(
+ DL.getLine(), DL.getCol(), DV.getContext(), IA));
+ } else
+ Scope = LScopes.findLexicalScope(DV.getContext());
// If variable scope is not found then skip this variable.
if (!Scope)
continue;
@@ -1271,7 +1193,11 @@ DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) {
// Handle multiple DBG_VALUE instructions describing one variable.
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
- SmallVector<DebugLocEntry, 4> DebugLoc;
+ DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1);
+ DebugLocList &LocList = DotDebugLocEntries.back();
+ LocList.Label =
+ Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1);
+ SmallVector<DebugLocEntry, 4> &DebugLoc = LocList.List;
for (SmallVectorImpl<const MachineInstr *>::const_iterator
HI = History.begin(),
HE = History.end();
// Compute the range for a register location.
const MCSymbol *FLabel = getLabelBeforeInsn(Begin);
- const MCSymbol *SLabel = 0;
+ const MCSymbol *SLabel = nullptr;
if (HI + 1 == HE)
// If Begin is the last instruction in History then its value is valid
@@ -1296,10 +1222,10 @@ DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) {
const MachineInstr *End = HI[1];
DEBUG(dbgs() << "DotDebugLoc Pair:\n"
<< "\t" << *Begin << "\t" << *End << "\n");
- if (End->isDebugValue())
+ if (End->isDebugValue() && End->getDebugVariable() == DV)
SLabel = getLabelBeforeInsn(End);
else {
- // End is a normal instruction clobbering the range.
+ // End is clobbering the range.
SLabel = getLabelAfterInsn(End);
assert(SLabel && "Forgot label after clobber instruction");
++HI;
@@ -1307,24 +1233,24 @@ DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) {
}
// The value is valid until the next DBG_VALUE or clobber.
- LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
- DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
- DebugLocEntry Loc = getDebugLocEntry(Asm, FLabel, SLabel, Begin, TheCU);
+ DebugLocEntry Loc(FLabel, SLabel, getDebugLocValue(Begin), TheCU);
if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc))
DebugLoc.push_back(std::move(Loc));
}
- DotDebugLocEntries.push_back(std::move(DebugLoc));
}
// Collect info for variables that were optimized out.
- LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables();
for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
DIVariable DV(Variables.getElement(i));
- if (!DV || !DV.isVariable() || !Processed.insert(DV))
+ assert(DV.isVariable());
+ if (!Processed.insert(DV))
continue;
if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext()))
- addScopeVariable(Scope, new DbgVariable(DV, NULL, this));
+ addScopeVariable(
+ Scope,
+ new DbgVariable(DV, findAbstractVariable(DV, Scope->getScopeNode()),
+ this));
}
}
// Process beginning of an instruction.
void DwarfDebug::beginInstruction(const MachineInstr *MI) {
- assert(CurMI == 0);
+ assert(CurMI == nullptr);
CurMI = MI;
// Check if source location changes, but ignore DBG_VALUE locations.
if (!MI->isDebugValue()) {
const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext());
recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
} else
- recordSourceLine(0, 0, 0, 0);
+ recordSourceLine(0, 0, nullptr, 0);
}
}
// Process end of an instruction.
void DwarfDebug::endInstruction() {
- assert(CurMI != 0);
+ assert(CurMI != nullptr);
// Don't create a new label after DBG_VALUE instructions.
// They don't generate code.
if (!CurMI->isDebugValue())
- PrevLabel = 0;
+ PrevLabel = nullptr;
DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
LabelsAfterInsn.find(CurMI);
- CurMI = 0;
+ CurMI = nullptr;
// No label needed.
if (I == LabelsAfterInsn.end())
if (LScopes.empty())
return;
- assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned");
+ assert(DbgValues.empty() && "DbgValues map wasn't cleaned!");
// Make sure that each lexical scope will have a begin/end label.
identifyScopeMarkers();
// Assumes in correct section after the entry point.
Asm->OutStreamer.EmitLabel(FunctionBeginSym);
- const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
- // 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(); I != E;
- ++I) {
- bool AtBlockEntry = true;
- for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
- II != IE; ++II) {
- const MachineInstr *MI = II;
-
- if (MI->isDebugValue()) {
- assert(MI->getNumOperands() > 1 && "Invalid machine instruction!");
-
- // Keep track of user variables.
- const MDNode *Var =
- MI->getOperand(MI->getNumOperands() - 1).getMetadata();
-
- // Variable is in a register, we need to check for clobbers.
- if (isDbgValueInDefinedReg(MI))
- LiveUserVar[MI->getOperand(0).getReg()] = Var;
-
- // Check the history of this variable.
- SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
- if (History.empty()) {
- UserVariables.push_back(Var);
- // The first mention of a function argument gets the FunctionBeginSym
- // label, so arguments are visible when breaking at function entry.
- DIVariable DV(Var);
- if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
- getDISubprogram(DV.getContext()).describes(MF->getFunction()))
- LabelsBeforeInsn[MI] = FunctionBeginSym;
- } else {
- // We have seen this variable before. Try to coalesce DBG_VALUEs.
- const MachineInstr *Prev = History.back();
- if (Prev->isDebugValue()) {
- // Coalesce identical entries at the end of History.
- if (History.size() >= 2 &&
- Prev->isIdenticalTo(History[History.size() - 2])) {
- DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
- << "\t" << *Prev << "\t"
- << *History[History.size() - 2] << "\n");
- History.pop_back();
- }
-
- // Terminate old register assignments that don't reach MI;
- MachineFunction::const_iterator PrevMBB = Prev->getParent();
- if (PrevMBB != I && (!AtBlockEntry || std::next(PrevMBB) != I) &&
- isDbgValueInDefinedReg(Prev)) {
- // Previous register assignment needs to terminate at the end of
- // its basic block.
- MachineBasicBlock::const_iterator LastMI =
- PrevMBB->getLastNonDebugInstr();
- if (LastMI == PrevMBB->end()) {
- // Drop DBG_VALUE for empty range.
- DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
- << "\t" << *Prev << "\n");
- History.pop_back();
- } else if (std::next(PrevMBB) != PrevMBB->getParent()->end())
- // Terminate after LastMI.
- History.push_back(LastMI);
- }
- }
- }
- History.push_back(MI);
- } else {
- // Not a DBG_VALUE instruction.
- if (!MI->isPosition())
- AtBlockEntry = false;
-
+ // Collect user variables, find the end of the prologue.
+ for (const auto &MBB : *MF) {
+ for (const auto &MI : MBB) {
+ if (MI.isDebugValue()) {
+ assert(MI.getNumOperands() > 1 && "Invalid machine instruction!");
+ // Keep track of user variables in order of appearance. Create the
+ // empty history for each variable so that the order of keys in
+ // DbgValues is correct. Actual history will be populated in
+ // calculateDbgValueHistory() function.
+ const MDNode *Var = MI.getDebugVariable();
+ DbgValues.insert(
+ std::make_pair(Var, SmallVector<const MachineInstr *, 4>()));
+ } else if (!MI.getFlag(MachineInstr::FrameSetup) &&
+ PrologEndLoc.isUnknown() && !MI.getDebugLoc().isUnknown()) {
// First known non-DBG_VALUE and non-frame setup location marks
// the beginning of the function body.
- if (!MI->getFlag(MachineInstr::FrameSetup) &&
- (PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown()))
- PrologEndLoc = MI->getDebugLoc();
-
- // Check if the instruction clobbers any registers with debug vars.
- for (const MachineOperand &MO : MI->operands()) {
- if (!MO.isReg() || !MO.isDef() || !MO.getReg())
- continue;
- for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
- ++AI) {
- unsigned Reg = *AI;
- const MDNode *Var = LiveUserVar[Reg];
- if (!Var)
- continue;
- // Reg is now clobbered.
- LiveUserVar[Reg] = 0;
-
- // Was MD last defined by a DBG_VALUE referring to Reg?
- DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);
- if (HistI == DbgValues.end())
- continue;
- SmallVectorImpl<const MachineInstr *> &History = HistI->second;
- if (History.empty())
- continue;
- const MachineInstr *Prev = History.back();
- // Sanity-check: Register assignments are terminated at the end of
- // their block.
- if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent())
- continue;
- // Is the variable still in Reg?
- if (!isDbgValueInDefinedReg(Prev) ||
- Prev->getOperand(0).getReg() != Reg)
- continue;
- // Var is clobbered. Make sure the next instruction gets a label.
- History.push_back(MI);
- }
- }
+ PrologEndLoc = MI.getDebugLoc();
}
}
}
+ // Calculate history for local variables.
+ calculateDbgValueHistory(MF, Asm->TM.getRegisterInfo(), DbgValues);
+
+ // Request labels for the full history.
for (auto &I : DbgValues) {
- SmallVectorImpl<const MachineInstr *> &History = I.second;
+ const SmallVectorImpl<const MachineInstr *> &History = I.second;
if (History.empty())
continue;
- // Make sure the final register assignments are terminated.
- const MachineInstr *Prev = History.back();
- if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {
- const MachineBasicBlock *PrevMBB = Prev->getParent();
- MachineBasicBlock::const_iterator LastMI =
- PrevMBB->getLastNonDebugInstr();
- if (LastMI == PrevMBB->end())
- // Drop DBG_VALUE for empty range.
- History.pop_back();
- else if (PrevMBB != &PrevMBB->getParent()->back()) {
- // Terminate after LastMI.
- History.push_back(LastMI);
- }
- }
- // Request labels for the full history.
+ // The first mention of a function argument gets the FunctionBeginSym
+ // label, so arguments are visible when breaking at function entry.
+ DIVariable DV(I.first);
+ if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
+ getDISubprogram(DV.getContext()).describes(MF->getFunction()))
+ LabelsBeforeInsn[History.front()] = FunctionBeginSym;
+
for (const MachineInstr *MI : History) {
- if (MI->isDebugValue())
+ if (MI->isDebugValue() && MI->getDebugVariable() == DV)
requestLabelBeforeInsn(MI);
else
requestLabelAfterInsn(MI);
// Every beginFunction(MF) call should be followed by an endFunction(MF) call,
// though the beginFunction may not be called at all.
// We should handle both cases.
- if (CurFn == 0)
+ if (!CurFn)
CurFn = MF;
else
assert(CurFn == MF);
- assert(CurFn != 0);
+ assert(CurFn != nullptr);
if (!MMI->hasDebugInfo() || LScopes.empty()) {
// If we don't have a lexical scope for this function then there will
// previously used section to nullptr.
PrevSection = nullptr;
PrevCU = nullptr;
- CurFn = 0;
+ CurFn = nullptr;
return;
}
collectVariableInfo(ProcessedVars);
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
- DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
- assert(TheCU && "Unable to find compile unit!");
+ DwarfCompileUnit &TheCU = *SPMap.lookup(FnScope->getScopeNode());
// Construct abstract scopes.
for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {
DISubprogram SP(AScope->getScopeNode());
- if (SP.isSubprogram()) {
- // Collect info for variables that were optimized out.
- DIArray Variables = SP.getVariables();
- for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
- DIVariable DV(Variables.getElement(i));
- if (!DV || !DV.isVariable() || !ProcessedVars.insert(DV))
- continue;
- // Check that DbgVariable for DV wasn't created earlier, when
- // findAbstractVariable() was called for inlined instance of DV.
- LLVMContext &Ctx = DV->getContext();
- DIVariable CleanDV = cleanseInlinedVariable(DV, Ctx);
- if (AbstractVariables.lookup(CleanDV))
- continue;
- if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext()))
- addScopeVariable(Scope, new DbgVariable(DV, NULL, this));
- }
+ if (!SP.isSubprogram())
+ continue;
+ // Collect info for variables that were optimized out.
+ DIArray Variables = SP.getVariables();
+ for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
+ DIVariable DV(Variables.getElement(i));
+ assert(DV && DV.isVariable());
+ if (!ProcessedVars.insert(DV))
+ continue;
+ findAbstractVariable(DV, DV.getContext());
}
- if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0)
- constructScopeDIE(TheCU, AScope);
+ constructAbstractSubprogramScopeDIE(TheCU, AScope);
}
- DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope);
+ DIE &CurFnDIE = constructSubprogramScopeDIE(TheCU, FnScope);
if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn))
- TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr);
+ TheCU.addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr);
// Add the range of this function to the list of ranges for the CU.
RangeSpan Span(FunctionBeginSym, FunctionEndSym);
- TheCU->addRange(std::move(Span));
+ TheCU.addRange(std::move(Span));
PrevSection = Asm->getCurrentSection();
- PrevCU = TheCU;
+ PrevCU = &TheCU;
// Clear debug info
- for (auto &I : ScopeVariables)
- DeleteContainerPointers(I.second);
+ // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the
+ // DbgVariables except those that are also in AbstractVariables (since they
+ // can be used cross-function)
+ for (const auto &I : ScopeVariables)
+ for (const auto *Var : I.second)
+ if (!AbstractVariables.count(Var->getVariable()) || Var->getAbstractVariable())
+ delete Var;
ScopeVariables.clear();
DeleteContainerPointers(CurrentFnArguments);
- UserVariables.clear();
DbgValues.clear();
- AbstractVariables.clear();
LabelsBeforeInsn.clear();
LabelsAfterInsn.clear();
- PrevLabel = NULL;
- CurFn = 0;
+ PrevLabel = nullptr;
+ CurFn = nullptr;
}
// Register a source line with debug info. Returns the unique label that was
@@ -1755,36 +1580,16 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
StringRef Dir;
unsigned Src = 1;
unsigned Discriminator = 0;
- if (S) {
- DIDescriptor Scope(S);
-
- if (Scope.isCompileUnit()) {
- DICompileUnit CU(S);
- Fn = CU.getFilename();
- Dir = CU.getDirectory();
- } else if (Scope.isFile()) {
- DIFile F(S);
- Fn = F.getFilename();
- Dir = F.getDirectory();
- } else if (Scope.isSubprogram()) {
- DISubprogram SP(S);
- Fn = SP.getFilename();
- Dir = SP.getDirectory();
- } else if (Scope.isLexicalBlockFile()) {
- DILexicalBlockFile DBF(S);
- Fn = DBF.getFilename();
- Dir = DBF.getDirectory();
- } else if (Scope.isLexicalBlock()) {
- DILexicalBlock DB(S);
- Fn = DB.getFilename();
- Dir = DB.getDirectory();
- Discriminator = DB.getDiscriminator();
- } else
- llvm_unreachable("Unexpected scope info");
+ if (DIScope Scope = DIScope(S)) {
+ assert(Scope.isScope());
+ Fn = Scope.getFilename();
+ Dir = Scope.getDirectory();
+ if (Scope.isLexicalBlock())
+ Discriminator = DILexicalBlock(S).getDiscriminator();
unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID();
- Src = static_cast<DwarfCompileUnit *>(InfoHolder.getUnits()[CUID])
- ->getOrCreateSourceID(Fn, Dir);
+ Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
+ .getOrCreateSourceID(Fn, Dir);
}
Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0,
Discriminator, Fn);
@@ -1794,68 +1599,6 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
// Emit Methods
//===----------------------------------------------------------------------===//
-// Compute the size and offset of a DIE. The offset is relative to start of the
-// CU. It returns the offset after laying out the DIE.
-unsigned DwarfFile::computeSizeAndOffset(DIE *Die, unsigned Offset) {
- // Record the abbreviation.
- assignAbbrevNumber(Die->getAbbrev());
-
- // Get the abbreviation for this DIE.
- const DIEAbbrev &Abbrev = Die->getAbbrev();
-
- // Set DIE offset
- Die->setOffset(Offset);
-
- // Start the size with the size of abbreviation code.
- Offset += getULEB128Size(Die->getAbbrevNumber());
-
- 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)
- // Size attribute value.
- Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
-
- // Get the children.
- const std::vector<DIE *> &Children = Die->getChildren();
-
- // Size the DIE children if any.
- if (!Children.empty()) {
- assert(Abbrev.hasChildren() && "Children flag not set");
-
- for (DIE *Child : Children)
- Offset = computeSizeAndOffset(Child, Offset);
-
- // End of children marker.
- Offset += sizeof(int8_t);
- }
-
- Die->setSize(Offset - Die->getOffset());
- return Offset;
-}
-
-// Compute the size and offset for each DIE.
-void DwarfFile::computeSizeAndOffsets() {
- // Offset from the first CU in the debug info section is 0 initially.
- unsigned SecOffset = 0;
-
- // Iterate over each compile unit and set the size and offsets for each
- // DIE within each compile unit. All offsets are CU relative.
- for (DwarfUnit *TheU : CUs) {
- TheU->setDebugInfoOffset(SecOffset);
-
- // CU-relative offset is reset to 0 here.
- unsigned Offset = sizeof(int32_t) + // Length of Unit Info
- TheU->getHeaderSize(); // Unit-specific headers
-
- // EndOffset here is CU-relative, after laying out
- // all of the CU DIE.
- unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
- SecOffset += EndOffset;
- }
-}
-
// Emit initial Dwarf sections with a label at the start of each one.
void DwarfDebug::emitSectionLabels() {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
DwarfAddrSectionSym =
emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
- DwarfDebugLocDWOSectionSym =
+ DwarfDebugLocSectionSym =
emitSectionSym(Asm, TLOF.getDwarfLocDWOSection(), "skel_loc");
} else
DwarfDebugLocSectionSym =
}
// Recursively emits a debug information entry.
-void DwarfDebug::emitDIE(DIE *Die) {
+void DwarfDebug::emitDIE(DIE &Die) {
// Get the abbreviation for this DIE.
- const DIEAbbrev &Abbrev = Die->getAbbrev();
+ const DIEAbbrev &Abbrev = Die.getAbbrev();
// Emit the code (index) for the abbreviation.
if (Asm->isVerbose())
Asm->OutStreamer.AddComment("Abbrev [" + Twine(Abbrev.getNumber()) +
- "] 0x" + Twine::utohexstr(Die->getOffset()) +
- ":0x" + Twine::utohexstr(Die->getSize()) + " " +
+ "] 0x" + Twine::utohexstr(Die.getOffset()) +
+ ":0x" + Twine::utohexstr(Die.getSize()) + " " +
dwarf::TagString(Abbrev.getTag()));
Asm->EmitULEB128(Abbrev.getNumber());
- const SmallVectorImpl<DIEValue *> &Values = Die->getValues();
+ const SmallVectorImpl<DIEValue *> &Values = Die.getValues();
const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
// Emit the DIE attribute values.
// Emit the DIE children if any.
if (Abbrev.hasChildren()) {
- const std::vector<DIE *> &Children = Die->getChildren();
-
- for (DIE *Child : Children)
- emitDIE(Child);
+ for (auto &Child : Die.getChildren())
+ emitDIE(*Child);
Asm->OutStreamer.AddComment("End Of Children Mark");
Asm->EmitInt8(0);
}
}
-// Emit the various dwarf units to the unit section USection with
-// the abbreviations going into ASection.
-void DwarfFile::emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym) {
- for (DwarfUnit *TheU : CUs) {
- DIE *Die = TheU->getUnitDie();
- const MCSection *USection = TheU->getSection();
- Asm->OutStreamer.SwitchSection(USection);
-
- // Emit the compile units header.
- Asm->OutStreamer.EmitLabel(TheU->getLabelBegin());
-
- // Emit size of content not including length itself
- Asm->OutStreamer.AddComment("Length of Unit");
- Asm->EmitInt32(TheU->getHeaderSize() + Die->getSize());
-
- TheU->emitHeader(ASectionSym);
-
- DD->emitDIE(Die);
- Asm->OutStreamer.EmitLabel(TheU->getLabelEnd());
- }
-}
-
// Emit the debug info section.
void DwarfDebug::emitDebugInfo() {
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
}
-void DwarfFile::emitAbbrevs(const MCSection *Section) {
- // Check to see if it is worth the effort.
- if (!Abbreviations.empty()) {
- // Start the debug abbrev section.
- Asm->OutStreamer.SwitchSection(Section);
-
- // For each abbrevation.
- for (const DIEAbbrev *Abbrev : Abbreviations) {
- // Emit the abbrevations code (base 1 index.)
- Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
-
- // Emit the abbreviations data.
- Abbrev->Emit(Asm);
- }
-
- // Mark end of abbreviations.
- Asm->EmitULEB128(0, "EOM(3)");
- }
-}
-
// Emit the last address of the section and the end of the line matrix.
void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
// Define last address of section.
// Emit visible names into a hashed accelerator table section.
void DwarfDebug::emitAccelNames() {
- DwarfAccelTable AT(
- DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
- for (DwarfUnit *TheU : getUnits()) {
- for (const auto &GI : TheU->getAccelNames()) {
- StringRef Name = GI.getKey();
- for (const DIE *D : GI.second)
- AT.AddName(Name, D);
- }
- }
-
- AT.FinalizeTable(Asm, "Names");
+ AccelNames.FinalizeTable(Asm, "Names");
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfAccelNamesSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
- AT.Emit(Asm, SectionBegin, &InfoHolder);
+ AccelNames.Emit(Asm, SectionBegin, &InfoHolder);
}
// Emit objective C classes and categories into a hashed accelerator table
// section.
void DwarfDebug::emitAccelObjC() {
- DwarfAccelTable AT(
- DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
- for (DwarfUnit *TheU : getUnits()) {
- for (const auto &GI : TheU->getAccelObjC()) {
- StringRef Name = GI.getKey();
- for (const DIE *D : GI.second)
- AT.AddName(Name, D);
- }
- }
-
- AT.FinalizeTable(Asm, "ObjC");
+ AccelObjC.FinalizeTable(Asm, "ObjC");
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfAccelObjCSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
- AT.Emit(Asm, SectionBegin, &InfoHolder);
+ AccelObjC.Emit(Asm, SectionBegin, &InfoHolder);
}
// Emit namespace dies into a hashed accelerator table.
void DwarfDebug::emitAccelNamespaces() {
- DwarfAccelTable AT(
- DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
- for (DwarfUnit *TheU : getUnits()) {
- for (const auto &GI : TheU->getAccelNamespace()) {
- StringRef Name = GI.getKey();
- for (const DIE *D : GI.second)
- AT.AddName(Name, D);
- }
- }
-
- AT.FinalizeTable(Asm, "namespac");
+ AccelNamespace.FinalizeTable(Asm, "namespac");
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfAccelNamespaceSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
- AT.Emit(Asm, SectionBegin, &InfoHolder);
+ AccelNamespace.Emit(Asm, SectionBegin, &InfoHolder);
}
// Emit type dies into a hashed accelerator table.
void DwarfDebug::emitAccelTypes() {
- std::vector<DwarfAccelTable::Atom> Atoms;
- Atoms.push_back(
- DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
- Atoms.push_back(
- DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2));
- Atoms.push_back(
- DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1));
- DwarfAccelTable AT(Atoms);
- for (DwarfUnit *TheU : getUnits()) {
- for (const auto &GI : TheU->getAccelTypes()) {
- StringRef Name = GI.getKey();
- for (const auto &DI : GI.second)
- AT.AddName(Name, DI.first, DI.second);
- }
- }
- AT.FinalizeTable(Asm, "types");
+ AccelTypes.FinalizeTable(Asm, "types");
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfAccelTypesSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
- AT.Emit(Asm, SectionBegin, &InfoHolder);
+ AccelTypes.Emit(Asm, SectionBegin, &InfoHolder);
}
// Public name handling.
// look for that now.
DIEValue *SpecVal = Die->findAttribute(dwarf::DW_AT_specification);
if (SpecVal) {
- DIE *SpecDIE = cast<DIEEntry>(SpecVal)->getEntry();
- if (SpecDIE->findAttribute(dwarf::DW_AT_external))
+ DIE &SpecDIE = cast<DIEEntry>(SpecVal)->getEntry();
+ if (SpecDIE.findAttribute(dwarf::DW_AT_external))
Linkage = dwarf::GIEL_EXTERNAL;
} else if (Die->findAttribute(dwarf::DW_AT_external))
Linkage = dwarf::GIEL_EXTERNAL;
emitDebugPubSection(GnuStyle, PSec, "Types", &DwarfUnit::getGlobalTypes);
}
-// Emit strings into a string section.
-void DwarfFile::emitStrings(const MCSection *StrSection,
- const MCSection *OffsetSection = NULL,
- const MCSymbol *StrSecSym = NULL) {
-
- if (StringPool.empty())
- return;
-
- // Start the dwarf str section.
- 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, const StrPool::value_type *>, 64 > Entries;
-
- for (const auto &I : StringPool)
- Entries.push_back(std::make_pair(I.second.second, &I));
-
- array_pod_sort(Entries.begin(), Entries.end());
-
- for (const auto &Entry : Entries) {
- // Emit a label for reference from debug information entries.
- Asm->OutStreamer.EmitLabel(Entry.second->getValue().first);
-
- // Emit the string itself with a terminating null byte.
- Asm->OutStreamer.EmitBytes(StringRef(Entry.second->getKeyData(),
- Entry.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 (const auto &Entry : Entries) {
- Asm->OutStreamer.EmitIntValue(offset, size);
- offset += Entry.second->getKeyLength() + 1;
- }
- }
-}
-
-// Emit addresses into the section given.
-void DwarfFile::emitAddresses(const MCSection *AddrSection) {
-
- if (AddressPool.empty())
- return;
-
- // Start the dwarf addr section.
- Asm->OutStreamer.SwitchSection(AddrSection);
-
- // Order the address pool entries by ID
- SmallVector<const MCExpr *, 64> Entries(AddressPool.size());
-
- for (const auto &I : AddressPool)
- Entries[I.second.Number] =
- I.second.TLS
- ? Asm->getObjFileLowering().getDebugThreadLocalSymbol(I.first)
- : MCSymbolRefExpr::Create(I.first, Asm->OutContext);
-
- for (const MCExpr *Entry : Entries)
- Asm->OutStreamer.EmitValue(Entry, Asm->getDataLayout().getPointerSize());
-}
-
// Emit visible names into a debug str section.
void DwarfDebug::emitDebugStr() {
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
const DebugLocEntry &Entry) {
- DIVariable DV(Entry.getVariable());
- if (Entry.isInt()) {
+ assert(Entry.getValues().size() == 1 &&
+ "multi-value entries are not supported yet.");
+ const DebugLocEntry::Value Value = Entry.getValues()[0];
+ DIVariable DV(Value.getVariable());
+ if (Value.isInt()) {
DIBasicType BTy(resolve(DV.getType()));
if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed ||
BTy.getEncoding() == dwarf::DW_ATE_signed_char)) {
Streamer.EmitInt8(dwarf::DW_OP_consts, "DW_OP_consts");
- Streamer.EmitSLEB128(Entry.getInt());
+ Streamer.EmitSLEB128(Value.getInt());
} else {
Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu");
- Streamer.EmitULEB128(Entry.getInt());
+ Streamer.EmitULEB128(Value.getInt());
}
- } else if (Entry.isLocation()) {
- MachineLocation Loc = Entry.getLoc();
+ } else if (Value.isLocation()) {
+ MachineLocation Loc = Value.getLoc();
if (!DV.hasComplexAddress())
// Regular entry.
Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
// FIXME: ^
}
+void DwarfDebug::emitDebugLocEntryLocation(const DebugLocEntry &Entry) {
+ Asm->OutStreamer.AddComment("Loc expr size");
+ MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
+ MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
+ Asm->EmitLabelDifference(end, begin, 2);
+ Asm->OutStreamer.EmitLabel(begin);
+ // Emit the entry.
+ APByteStreamer Streamer(*Asm);
+ emitDebugLocEntry(Streamer, Entry);
+ // Close the range.
+ Asm->OutStreamer.EmitLabel(end);
+}
+
// Emit locations into the debug loc section.
void DwarfDebug::emitDebugLoc() {
// Start the dwarf loc section.
Asm->OutStreamer.SwitchSection(
- useSplitDwarf() ? Asm->getObjFileLowering().getDwarfLocDWOSection()
- : Asm->getObjFileLowering().getDwarfLocSection());
+ Asm->getObjFileLowering().getDwarfLocSection());
unsigned char Size = Asm->getDataLayout().getPointerSize();
- unsigned index = 0;
for (const auto &DebugLoc : DotDebugLocEntries) {
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index));
- for (const auto &Entry : DebugLoc) {
+ Asm->OutStreamer.EmitLabel(DebugLoc.Label);
+ for (const auto &Entry : DebugLoc.List) {
// Set up the range. This range is relative to the entry point of the
// compile unit. This is a hard coded 0 for low_pc when we're emitting
// ranges, or the DW_AT_low_pc on the compile unit otherwise.
const DwarfCompileUnit *CU = Entry.getCU();
- if (useSplitDwarf()) {
- // Just always use start_length for now - at least that's one address
- // rather than two. We could get fancier and try to, say, reuse an
- // address we know we've emitted elsewhere (the start of the function?
- // The start of the CU or CU subrange that encloses this range?)
- Asm->EmitInt8(dwarf::DW_LLE_start_length_entry);
- unsigned idx = InfoHolder.getAddrPoolIndex(Entry.getBeginSym());
- Asm->EmitULEB128(idx);
- Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4);
- } else if (CU->getRanges().size() == 1) {
+ if (CU->getRanges().size() == 1) {
// Grab the begin symbol from the first range as our base.
const MCSymbol *Base = CU->getRanges()[0].getStart();
Asm->EmitLabelDifference(Entry.getBeginSym(), Base, Size);
Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size);
Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size);
}
- Asm->OutStreamer.AddComment("Loc expr size");
- MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
- MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
- Asm->EmitLabelDifference(end, begin, 2);
- Asm->OutStreamer.EmitLabel(begin);
- // Emit the entry.
- APByteStreamer Streamer(*Asm);
- emitDebugLocEntry(Streamer, Entry);
- // Close the range.
- Asm->OutStreamer.EmitLabel(end);
+
+ emitDebugLocEntryLocation(Entry);
}
- if (useSplitDwarf())
- Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry);
- else {
- Asm->OutStreamer.EmitIntValue(0, Size);
- Asm->OutStreamer.EmitIntValue(0, Size);
+ Asm->OutStreamer.EmitIntValue(0, Size);
+ Asm->OutStreamer.EmitIntValue(0, Size);
+ }
+}
+
+void DwarfDebug::emitDebugLocDWO() {
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfLocDWOSection());
+ for (const auto &DebugLoc : DotDebugLocEntries) {
+ Asm->OutStreamer.EmitLabel(DebugLoc.Label);
+ for (const auto &Entry : DebugLoc.List) {
+ // Just always use start_length for now - at least that's one address
+ // rather than two. We could get fancier and try to, say, reuse an
+ // address we know we've emitted elsewhere (the start of the function?
+ // The start of the CU or CU subrange that encloses this range?)
+ Asm->EmitInt8(dwarf::DW_LLE_start_length_entry);
+ unsigned idx = AddrPool.getIndex(Entry.getBeginSym());
+ Asm->EmitULEB128(idx);
+ Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4);
+
+ emitDebugLocEntryLocation(Entry);
}
- ++index;
+ Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry);
}
}
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfARangesSection());
- typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan> > SpansType;
+ typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> SpansType;
SpansType Spans;
// If we have no section (e.g. common), just write out
// individual spans for each symbol.
- if (Section == NULL) {
+ if (!Section) {
for (const SymbolCU &Cur : List) {
ArangeSpan Span;
Span.Start = Cur.Sym;
- Span.End = NULL;
+ Span.End = nullptr;
if (Cur.CU)
Spans[Cur.CU].push_back(Span);
}
for (const auto &I : CUMap) {
DwarfCompileUnit *TheCU = I.second;
- // Emit a symbol so we can find the beginning of our ranges.
- Asm->OutStreamer.EmitLabel(TheCU->getLabelRange());
-
// Iterate over the misc ranges for the compile units in the module.
for (const RangeSpanList &List : TheCU->getRangeLists()) {
// Emit our symbol so we can find the beginning of the range.
const MCSymbol *End = Range.getEnd();
assert(Begin && "Range without a begin symbol?");
assert(End && "Range without an end symbol?");
- Asm->OutStreamer.EmitSymbolValue(Begin, Size);
- Asm->OutStreamer.EmitSymbolValue(End, Size);
+ if (TheCU->getRanges().size() == 1) {
+ // Grab the begin symbol from the first range as our base.
+ const MCSymbol *Base = TheCU->getRanges()[0].getStart();
+ Asm->EmitLabelDifference(Begin, Base, Size);
+ Asm->EmitLabelDifference(End, Base, Size);
+ } else {
+ Asm->OutStreamer.EmitSymbolValue(Begin, Size);
+ Asm->OutStreamer.EmitSymbolValue(End, Size);
+ }
}
// And terminate the list with two 0 values.
// DWARF5 Experimental Separate Dwarf emitters.
-void DwarfDebug::initSkeletonUnit(const DwarfUnit *U, DIE *Die,
- DwarfUnit *NewU) {
+void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,
+ std::unique_ptr<DwarfUnit> NewU) {
NewU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name,
- U->getCUNode().getSplitDebugFilename());
+ U.getCUNode().getSplitDebugFilename());
if (!CompilationDir.empty())
NewU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
- addGnuPubAttributes(NewU, Die);
+ addGnuPubAttributes(*NewU, Die);
- SkeletonHolder.addUnit(NewU);
+ SkeletonHolder.addUnit(std::move(NewU));
}
// 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_addr_base, DW_AT_ranges_base.
-DwarfCompileUnit *DwarfDebug::constructSkeletonCU(const DwarfCompileUnit *CU) {
+DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {
- DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
- DwarfCompileUnit *NewCU = new DwarfCompileUnit(
- CU->getUniqueID(), Die, CU->getCUNode(), Asm, this, &SkeletonHolder);
- NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(),
- DwarfInfoSectionSym);
+ auto OwnedUnit = make_unique<DwarfCompileUnit>(
+ CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder);
+ DwarfCompileUnit &NewCU = *OwnedUnit;
+ NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection(),
+ DwarfInfoSectionSym);
- NewCU->initStmtList(DwarfLineSectionSym);
+ NewCU.initStmtList(DwarfLineSectionSym);
- initSkeletonUnit(CU, Die, NewCU);
+ initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit));
return NewCU;
}
// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_dwo_name,
// DW_AT_addr_base.
-DwarfTypeUnit *DwarfDebug::constructSkeletonTU(DwarfTypeUnit *TU) {
+DwarfTypeUnit &DwarfDebug::constructSkeletonTU(DwarfTypeUnit &TU) {
DwarfCompileUnit &CU = static_cast<DwarfCompileUnit &>(
- *SkeletonHolder.getUnits()[TU->getCU().getUniqueID()]);
+ *SkeletonHolder.getUnits()[TU.getCU().getUniqueID()]);
- DIE *Die = new DIE(dwarf::DW_TAG_type_unit);
- DwarfTypeUnit *NewTU =
- new DwarfTypeUnit(TU->getUniqueID(), Die, CU, Asm, this, &SkeletonHolder);
- NewTU->setTypeSignature(TU->getTypeSignature());
- NewTU->setType(NULL);
- NewTU->initSection(
- Asm->getObjFileLowering().getDwarfTypesSection(TU->getTypeSignature()));
+ auto OwnedUnit = make_unique<DwarfTypeUnit>(TU.getUniqueID(), CU, Asm, this,
+ &SkeletonHolder);
+ DwarfTypeUnit &NewTU = *OwnedUnit;
+ NewTU.setTypeSignature(TU.getTypeSignature());
+ NewTU.setType(nullptr);
+ NewTU.initSection(
+ Asm->getObjFileLowering().getDwarfTypesSection(TU.getTypeSignature()));
- initSkeletonUnit(TU, Die, NewTU);
+ initSkeletonUnit(TU, NewTU.getUnitDie(), std::move(OwnedUnit));
return NewTU;
}
// compile units that would normally be in debug_info.
void DwarfDebug::emitDebugInfoDWO() {
assert(useSplitDwarf() && "No split dwarf debug info?");
- InfoHolder.emitUnits(this, nullptr);
+ // Don't pass an abbrev symbol, using a constant zero instead so as not to
+ // emit relocations into the dwo file.
+ InfoHolder.emitUnits(this, /* AbbrevSymbol */ nullptr);
}
// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the
@@ -2733,14 +2343,25 @@ MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {
return &SplitTypeUnitFileTable;
}
+static uint64_t makeTypeSignature(StringRef Identifier) {
+ MD5 Hash;
+ Hash.update(Identifier);
+ // ... take the least significant 8 bytes and return those. Our MD5
+ // implementation always returns its results in little endian, swap bytes
+ // appropriately.
+ MD5::MD5Result Result;
+ Hash.final(Result);
+ return *reinterpret_cast<support::ulittle64_t *>(Result + 8);
+}
+
void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
- StringRef Identifier, DIE *RefDie,
+ StringRef Identifier, DIE &RefDie,
DICompositeType CTy) {
- // Flag the type unit reference as a declaration so that if it contains
- // members (implicit special members, static data member definitions, member
- // declarations for definitions in this CU, etc) consumers don't get confused
- // and think this is a full definition.
- CU.addFlag(RefDie, dwarf::DW_AT_declaration);
+ // Fast path if we're building some type units and one has already used the
+ // address pool we know we're going to throw away all this work anyway, so
+ // don't bother building dependent types.
+ if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed())
+ return;
const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy];
if (TU) {
return;
}
- DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit);
- DwarfTypeUnit *NewTU =
- new DwarfTypeUnit(InfoHolder.getUnits().size(), UnitDie, CU, Asm, this,
- &InfoHolder, getDwoLineTable(CU));
- TU = NewTU;
- InfoHolder.addUnit(NewTU);
+ bool TopLevelType = TypeUnitsUnderConstruction.empty();
+ AddrPool.resetUsedFlag();
- NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
- CU.getLanguage());
+ auto OwnedUnit =
+ make_unique<DwarfTypeUnit>(InfoHolder.getUnits().size(), CU, Asm, this,
+ &InfoHolder, getDwoLineTable(CU));
+ DwarfTypeUnit &NewTU = *OwnedUnit;
+ DIE &UnitDie = NewTU.getUnitDie();
+ TU = &NewTU;
+ TypeUnitsUnderConstruction.push_back(
+ std::make_pair(std::move(OwnedUnit), CTy));
- MD5 Hash;
- Hash.update(Identifier);
- // ... take the least significant 8 bytes and return those. Our MD5
- // implementation always returns its results in little endian, swap bytes
- // appropriately.
- MD5::MD5Result Result;
- Hash.final(Result);
- uint64_t Signature = *reinterpret_cast<support::ulittle64_t *>(Result + 8);
- NewTU->setTypeSignature(Signature);
- if (useSplitDwarf())
- NewTU->setSkeleton(constructSkeletonTU(NewTU));
- else
- CU.applyStmtList(*UnitDie);
+ NewTU.addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ CU.getLanguage());
+
+ uint64_t Signature = makeTypeSignature(Identifier);
+ NewTU.setTypeSignature(Signature);
- NewTU->setType(NewTU->createTypeDIE(CTy));
+ if (!useSplitDwarf())
+ CU.applyStmtList(UnitDie);
- NewTU->initSection(
+ // FIXME: Skip using COMDAT groups for type units in the .dwo file once tools
+ // such as DWP ( http://gcc.gnu.org/wiki/DebugFissionDWP ) can cope with it.
+ NewTU.initSection(
useSplitDwarf()
? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature)
: Asm->getObjFileLowering().getDwarfTypesSection(Signature));
- CU.addDIETypeSignature(RefDie, *NewTU);
+ NewTU.setType(NewTU.createTypeDIE(CTy));
+
+ if (TopLevelType) {
+ auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction);
+ TypeUnitsUnderConstruction.clear();
+
+ // Types referencing entries in the address table cannot be placed in type
+ // units.
+ if (AddrPool.hasBeenUsed()) {
+
+ // Remove all the types built while building this type.
+ // This is pessimistic as some of these types might not be dependent on
+ // the type that used an address.
+ for (const auto &TU : TypeUnitsToAdd)
+ DwarfTypeUnits.erase(TU.second);
+
+ // Construct this type in the CU directly.
+ // This is inefficient because all the dependent types will be rebuilt
+ // from scratch, including building them in type units, discovering that
+ // they depend on addresses, throwing them out and rebuilding them.
+ CU.constructTypeDIE(RefDie, CTy);
+ return;
+ }
+
+ // If the type wasn't dependent on fission addresses, finish adding the type
+ // and all its dependent types.
+ for (auto &TU : TypeUnitsToAdd) {
+ if (useSplitDwarf())
+ TU.first->setSkeleton(constructSkeletonTU(*TU.first));
+ InfoHolder.addUnit(std::move(TU.first));
+ }
+ }
+ CU.addDIETypeSignature(RefDie, NewTU);
}
-void DwarfDebug::attachLowHighPC(DwarfCompileUnit *Unit, DIE *D,
+void DwarfDebug::attachLowHighPC(DwarfCompileUnit &Unit, DIE &D,
MCSymbol *Begin, MCSymbol *End) {
- Unit->addLabelAddress(D, dwarf::DW_AT_low_pc, Begin);
+ assert(Begin && "Begin label should not be null!");
+ assert(End && "End label should not be null!");
+ assert(Begin->isDefined() && "Invalid starting label");
+ assert(End->isDefined() && "Invalid end label");
+
+ Unit.addLabelAddress(D, dwarf::DW_AT_low_pc, Begin);
if (DwarfVersion < 4)
- Unit->addLabelAddress(D, dwarf::DW_AT_high_pc, End);
+ Unit.addLabelAddress(D, dwarf::DW_AT_high_pc, End);
else
- Unit->addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin);
+ Unit.addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin);
+}
+
+// Accelerator table mutators - add each name along with its companion
+// DIE to the proper table while ensuring that the name that we're going
+// to reference is in the string table. We do this since the names we
+// add may not only be identical to the names in the DIE.
+void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) {
+ if (!useDwarfAccelTables())
+ return;
+ AccelNames.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
+}
+
+void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) {
+ if (!useDwarfAccelTables())
+ return;
+ AccelObjC.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
+}
+
+void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) {
+ if (!useDwarfAccelTables())
+ return;
+ AccelNamespace.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
+}
+
+void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) {
+ if (!useDwarfAccelTables())
+ return;
+ AccelTypes.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
}