//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "dwarfdebug"
#include "ByteStreamer.h"
#include "DwarfDebug.h"
#include "DIE.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"));
} // 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();
-}
-
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
: Asm(A), MMI(Asm->MMI), FirstCU(0), PrevLabel(NULL), GlobalRangeCount(0),
InfoHolder(A, "info_string", DIEValueAllocator),
DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = 0;
DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0;
- DwarfAddrSectionSym = DwarfDebugLocDWOSectionSym = 0;
+ DwarfAddrSectionSym = 0;
DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0;
FunctionBeginSym = FunctionEndSym = 0;
CurFn = 0;
DwarfVersion = DwarfVersionNumber
? DwarfVersionNumber
- : getDwarfVersionFromModule(MMI->getModule());
+ : MMI->getModule()->getDwarfVersion();
{
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
// 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;
- }
+ for (DbgVariable &ArgDV : CurrentFnArguments)
+ if (ArgDV.getVariable()) {
+ DIE *Arg = TheCU->constructVariableDIE(ArgDV, Scope->isAbstractScope());
+ Children.push_back(Arg);
+ if (ArgDV.isObjectPointer())
+ ObjectPointer = Arg;
+ }
// If this is a variadic function, add an unspecified parameter.
DISubprogram SP(Scope->getScopeNode());
}
// Collect lexical scope children first.
- for (DbgVariable *DV : ScopeVariables.lookup(Scope))
- if (DIE *Variable = TheCU->constructVariableDIE(*DV,
+ for (DbgVariable &DV : ScopeVariables.lookup(Scope))
+ if (DIE *Variable = TheCU->constructVariableDIE(DV,
Scope->isAbstractScope())) {
Children.push_back(Variable);
- if (DV->isObjectPointer())
+ if (DV.isObjectPointer())
ObjectPointer = Variable;
}
for (LexicalScope *LS : Scope->getChildren())
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 = Module.getEntity();
+ DIDescriptor Entity = resolve(Module.getEntity());
if (Entity.isNameSpace())
EntityDie = TheCU->getOrCreateNameSpace(DINameSpace(Entity));
else if (Entity.isSubprogram())
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
// 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();
emitDebugLineDWO();
// Emit DWO addresses.
InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection());
- }
+ emitDebugLocDWO();
+ } else
+ // Emit info into a debug loc section.
+ emitDebugLoc();
// Emit info into the dwarf accelerator table sections.
if (useDwarfAccelTables()) {
if (!Scope)
return NULL;
- AbsDbgVariable = new DbgVariable(Var, NULL, this);
- addScopeVariable(Scope, AbsDbgVariable);
+ AbsDbgVariable = &addScopeVariable(Scope, DbgVariable(Var, NULL, this));
AbstractVariables[Var] = AbsDbgVariable;
return AbsDbgVariable;
}
// If Var is a current function argument then add it to CurrentFnArguments list.
-bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) {
+DbgVariable *DwarfDebug::addCurrentFnArgument(DbgVariable &Var, LexicalScope *Scope) {
if (!LScopes.isCurrentFunctionScope(Scope))
- return false;
- DIVariable DV = Var->getVariable();
+ return nullptr;
+ DIVariable DV = Var.getVariable();
if (DV.getTag() != dwarf::DW_TAG_arg_variable)
- return false;
+ return nullptr;
unsigned ArgNo = DV.getArgNumber();
if (ArgNo == 0)
- return false;
+ return nullptr;
- size_t Size = CurrentFnArguments.size();
- if (Size == 0)
- CurrentFnArguments.resize(CurFn->getFunction()->arg_size());
- // llvm::Function argument size is not good indicator of how many
- // arguments does the function have at source level.
- if (ArgNo > Size)
- CurrentFnArguments.resize(ArgNo * 2);
- CurrentFnArguments[ArgNo - 1] = Var;
- return true;
+ auto I = CurrentFnArguments.begin();
+ for (; I != CurrentFnArguments.end(); ++I)
+ if (ArgNo < I->getVariable().getArgNumber())
+ break;
+ return &*CurrentFnArguments.insert(I, std::move(Var));
+}
+
+DbgVariable &DwarfDebug::addVariable(DbgVariable Var, LexicalScope *Scope) {
+ if (DbgVariable *Res = addCurrentFnArgument(Var, Scope))
+ return *Res;
+ return addScopeVariable(Scope, std::move(Var));
}
// Collect variable information from side table maintained by MMI.
continue;
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VI.Loc);
- DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable, this);
- RegVar->setFrameIndex(VI.Slot);
- if (!addCurrentFnArgument(RegVar, Scope))
- addScopeVariable(Scope, RegVar);
+ DbgVariable RegVar(DV, AbsDbgVariable, this);
+ RegVar.setFrameIndex(VI.Slot);
+ addVariable(std::move(RegVar), Scope);
if (AbsDbgVariable)
AbsDbgVariable->setFrameIndex(VI.Slot);
}
const MCSymbol *SLabel,
const MachineInstr *MI,
DwarfCompileUnit *Unit) {
- const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata();
+ const MDNode *Var = MI->getDebugVariable();
assert(MI->getNumOperands() == 3);
if (MI->getOperand(0).isReg()) {
return DebugLocEntry(FLabel, SLabel, MLoc, Var, Unit);
}
if (MI->getOperand(0).isImm())
- return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm(), Unit);
+ return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm(), Var, Unit);
if (MI->getOperand(0).isFPImm())
- return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm(), Unit);
+ return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm(),
+ Var, Unit);
if (MI->getOperand(0).isCImm())
- return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm(), Unit);
+ return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm(),
+ Var, Unit);
llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!");
}
Processed.insert(DV);
assert(MInsn->isDebugValue() && "History must begin with debug value");
DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc());
- DbgVariable *RegVar = new DbgVariable(DV, AbsVar, this);
- if (!addCurrentFnArgument(RegVar, Scope))
- addScopeVariable(Scope, RegVar);
+ DbgVariable &RegVar = addVariable(DbgVariable(DV, AbsVar, this), Scope);
if (AbsVar)
AbsVar->setMInsn(MInsn);
// Simplify ranges that are fully coalesced.
if (History.size() <= 1 ||
(History.size() == 2 && MInsn->isIdenticalTo(History.back()))) {
- RegVar->setMInsn(MInsn);
+ RegVar.setMInsn(MInsn);
continue;
}
// Handle multiple DBG_VALUE instructions describing one variable.
- RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
+ 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();
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.
if (!DV || !DV.isVariable() || !Processed.insert(DV))
continue;
if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext()))
- addScopeVariable(Scope, new DbgVariable(DV, NULL, this));
+ addScopeVariable(Scope, DbgVariable(DV, NULL, this));
}
}
assert(MI->getNumOperands() > 1 && "Invalid machine instruction!");
// Keep track of user variables.
- const MDNode *Var =
- MI->getOperand(MI->getNumOperands() - 1).getMetadata();
+ const MDNode *Var = MI->getDebugVariable();
// Variable is in a register, we need to check for clobbers.
if (isDbgValueInDefinedReg(MI))
}
}
-void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
- SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
- DIVariable DV = Var->getVariable();
+DbgVariable &DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable Var) {
+ auto &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
// 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();
+ auto I = Vars.begin();
while (I != Vars.end()) {
- unsigned CurNum = (*I)->getVariable().getArgNumber();
+ unsigned CurNum = I->getVariable().getArgNumber();
// A local (non-parameter) variable has been found, insert immediately
// before it.
if (CurNum == 0)
break;
++I;
}
- Vars.insert(I, Var);
- return;
+ return *Vars.insert(I, std::move(Var));
}
- Vars.push_back(Var);
+ Vars.push_back(std::move(Var));
+ return Vars.back();
}
// Gather and emit post-function debug information.
if (AbstractVariables.lookup(CleanDV))
continue;
if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext()))
- addScopeVariable(Scope, new DbgVariable(DV, NULL, this));
+ addScopeVariable(Scope, DbgVariable(DV, NULL, this));
}
}
if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0)
PrevCU = TheCU;
// Clear debug info
- for (auto &I : ScopeVariables)
- DeleteContainerPointers(I.second);
ScopeVariables.clear();
- DeleteContainerPointers(CurrentFnArguments);
+ CurrentFnArguments.clear();
UserVariables.clear();
DbgValues.clear();
AbstractVariables.clear();
// 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) {
+unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
// Record the abbreviation.
- assignAbbrevNumber(Die->getAbbrev());
+ assignAbbrevNumber(Die.getAbbrev());
// Get the abbreviation for this DIE.
- const DIEAbbrev &Abbrev = Die->getAbbrev();
+ const DIEAbbrev &Abbrev = Die.getAbbrev();
// Set DIE offset
- Die->setOffset(Offset);
+ Die.setOffset(Offset);
// Start the size with the size of abbreviation code.
- Offset += getULEB128Size(Die->getAbbrevNumber());
+ Offset += getULEB128Size(Die.getAbbrevNumber());
- const SmallVectorImpl<DIEValue *> &Values = Die->getValues();
+ const SmallVectorImpl<DIEValue *> &Values = Die.getValues();
const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
// Size the DIE attribute values.
Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
// Get the children.
- const std::vector<DIE *> &Children = Die->getChildren();
+ const auto &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);
+ for (auto &Child : Children)
+ Offset = computeSizeAndOffset(*Child, Offset);
// End of children marker.
Offset += sizeof(int8_t);
}
- Die->setSize(Offset - Die->getOffset());
+ Die.setSize(Offset - Die.getOffset());
return Offset;
}
// EndOffset here is CU-relative, after laying out
// all of the CU DIE.
- unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
+ unsigned EndOffset = computeSizeAndOffset(*TheU->getUnitDie(), Offset);
SecOffset += EndOffset;
}
}
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);
TheU->emitHeader(ASectionSym);
- DD->emitDIE(Die);
+ DD->emitDIE(*Die);
Asm->OutStreamer.EmitLabel(TheU->getLabelEnd());
}
}
// 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 = InfoHolder.getAddrPoolIndex(Entry.getBeginSym());
+ Asm->EmitULEB128(idx);
+ Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4);
+
+ emitDebugLocEntryLocation(Entry);
}
- ++index;
+ Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry);
}
}
// Build a set of address spans, sorted by CU.
for (const MCSection *Section : Sections) {
- SmallVector<SymbolCU, 8> &List = SectionMap[Section];
+ auto &List = SectionMap[Section];
if (List.size() < 2)
continue;
// 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