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 DD->resolve(Ref);
+}
+
DIType DbgVariable::getType() const {
DIType Ty = Var.getType();
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
uint16_t tag = Ty.getTag();
if (tag == dwarf::DW_TAG_pointer_type)
- subType = DD->resolve(DIDerivedType(Ty).getTypeDerivedFrom());
+ subType = resolve(DIDerivedType(Ty).getTypeDerivedFrom());
DIArray Elements = DICompositeType(subType).getTypeArray();
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIDerivedType DT = DIDerivedType(Elements.getElement(i));
if (getName() == DT.getName())
- return (DD->resolve(DT.getTypeDerivedFrom()));
+ return (resolve(DT.getTypeDerivedFrom()));
}
}
return Ty;
AbbreviationsSet(InitAbbreviationsSetSize),
SourceIdMap(DIEValueAllocator),
PrevLabel(NULL), GlobalCUIndexCount(0),
- InfoHolder(A, &AbbreviationsSet, &Abbreviations, "info_string",
+ InfoHolder(A, &AbbreviationsSet, Abbreviations, "info_string",
DIEValueAllocator),
SkeletonAbbrevSet(InitAbbreviationsSetSize),
- SkeletonHolder(A, &SkeletonAbbrevSet, &SkeletonAbbrevs, "skel_string",
+ SkeletonHolder(A, &SkeletonAbbrevSet, SkeletonAbbrevs, "skel_string",
DIEValueAllocator) {
DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0;
FunctionBeginSym = FunctionEndSym = 0;
- // Turn on accelerator tables and older gdb compatibility
- // for Darwin by default, pubnames by default for non-Darwin,
- // and handle split dwarf.
+ // Turn on accelerator tables for Darwin by default, pubnames by
+ // default for non-Darwin, and handle split dwarf.
bool IsDarwin = Triple(A->getTargetTriple()).isOSDarwin();
if (DwarfAccelTables == Default)
beginModule();
}
}
-DwarfDebug::~DwarfDebug() {
-}
// Switch to the specified MCSection and emit an assembler
// temporary label to it if SymbolStem is specified.
// If it's newly added.
if (InSet == &Abbrev) {
// Add to abbreviation list.
- Abbreviations->push_back(&Abbrev);
+ Abbreviations.push_back(&Abbrev);
// Assign the vector position + 1 as its number.
- Abbrev.setNumber(Abbreviations->size());
+ Abbrev.setNumber(Abbreviations.size());
} else {
// Assign existing abbreviation number.
Abbrev.setNumber(InSet->getNumber());
// scope then create and insert DIEs for these variables.
DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU,
const MDNode *SPNode) {
- DIE *SPDie = getSPDIE(SPNode);
+ DIE *SPDie = SPCU->getDIE(DIDescriptor(SPNode));
assert(SPDie && "Unable to find subprogram DIE!");
DISubprogram SP(SPNode);
// If we're updating an abstract DIE, then we will be adding the children and
// object pointer later on. But what we don't want to do is process the
// concrete DIE twice.
- DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode);
- if (AbsSPDIE) {
- bool InSameCU = (AbsSPDIE->getCompileUnit() == SPCU->getCUDie());
+ if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) {
// Pick up abstract subprogram DIE.
- SPDie = new DIE(dwarf::DW_TAG_subprogram);
- // If AbsSPDIE belongs to a different CU, use DW_FORM_ref_addr instead of
- // DW_FORM_ref4.
- SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin,
- InSameCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
- AbsSPDIE);
- SPCU->addDie(SPDie);
+ SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getCUDie());
+ SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, AbsSPDIE);
} else {
DISubprogram SPDecl = SP.getFunctionDeclaration();
if (!SPDecl.isSubprogram()) {
// 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.
- if (SP.isDefinition() && !SP.getContext().isCompileUnit() &&
- !SP.getContext().isFile() &&
- !isSubprogramContext(SP.getContext())) {
+ DIScope SPContext = resolve(SP.getContext());
+ if (SP.isDefinition() && !SPContext.isCompileUnit() &&
+ !SPContext.isFile() &&
+ !isSubprogramContext(SPContext)) {
SPCU->addFlag(SPDie, dwarf::DW_AT_declaration);
// Add arguments.
uint16_t SPTag = SPTy.getTag();
if (SPTag == dwarf::DW_TAG_subroutine_type)
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
- DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
+ DIE *Arg =
+ SPCU->createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie);
DIType ATy = DIType(Args.getElement(i));
SPCU->addType(Arg, ATy);
if (ATy.isArtificial())
SPCU->addFlag(Arg, dwarf::DW_AT_artificial);
if (ATy.isObjectPointer())
- SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer,
- dwarf::DW_FORM_ref4, Arg);
- SPDie->addChild(Arg);
+ SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, Arg);
}
DIE *SPDeclDie = SPDie;
- SPDie = new DIE(dwarf::DW_TAG_subprogram);
- SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification,
- dwarf::DW_FORM_ref4, SPDeclDie);
- SPCU->addDie(SPDie);
+ SPDie =
+ SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getCUDie());
+ SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, SPDeclDie);
}
}
}
return NULL;
DIScope DS(Scope->getScopeNode());
DISubprogram InlinedSP = getDISubprogram(DS);
- DIE *OriginDIE = getSPDIE(InlinedSP);
+ DIE *OriginDIE = TheCU->getDIE(InlinedSP);
if (!OriginDIE) {
DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram.");
return NULL;
}
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
- TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
- dwarf::DW_FORM_ref4, OriginDIE);
+ TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, OriginDIE);
if (Ranges.size() > 1) {
// .debug_range section has not been laid out yet. Emit offset in
// Add the call site information to the DIE.
DILocation DL(Scope->getInlinedAt());
- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0,
+ TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, None,
getOrCreateSourceID(DL.getFilename(), DL.getDirectory(),
TheCU->getUniqueID()));
- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber());
+ 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.
for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
if (DbgVariable *ArgDV = CurrentFnArguments[i])
if (DIE *Arg =
- TheCU->constructVariableDIE(ArgDV, Scope->isAbstractScope())) {
+ TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) {
Children.push_back(Arg);
if (ArgDV->isObjectPointer()) ObjectPointer = Arg;
}
const SmallVectorImpl<DbgVariable *> &Variables =ScopeVariables.lookup(Scope);
for (unsigned i = 0, N = Variables.size(); i < N; ++i)
if (DIE *Variable =
- TheCU->constructVariableDIE(Variables[i], Scope->isAbstractScope())) {
+ TheCU->constructVariableDIE(*Variables[i], Scope->isAbstractScope())) {
Children.push_back(Variable);
if (Variables[i]->isObjectPointer()) ObjectPointer = Variable;
}
else if (DS.isSubprogram()) {
ProcessedSPNodes.insert(DS);
if (Scope->isAbstractScope()) {
- ScopeDIE = getSPDIE(DS);
+ ScopeDIE = TheCU->getDIE(DS);
// Note down abstract DIE.
if (ScopeDIE)
AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
ScopeDIE->addChild(*I);
if (DS.isSubprogram() && ObjectPointer != NULL)
- TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer,
- dwarf::DW_FORM_ref4, ObjectPointer);
+ TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer);
if (DS.isSubprogram())
TheCU->addPubTypes(DISubprogram(DS));
StringRef DirName, unsigned CUID) {
// If we use .loc in assembly, we can't separate .file entries according to
// compile units. Thus all files will belong to the default compile unit.
- if (Asm->TM.hasMCUseLoc() &&
- Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer)
+
+ // FIXME: add a better feature test than hasRawTextSupport. Even better,
+ // extend .file to support this.
+ if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport())
CUID = 0;
// If FE did not provide a file name, then assume stdin.
// Use a single line table if we are using .loc and generating assembly.
bool UseTheFirstCU =
- (Asm->TM.hasMCUseLoc() &&
- Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer) ||
- (NewCU->getUniqueID() == 0);
+ (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) ||
+ (NewCU->getUniqueID() == 0);
if (!useSplitDwarf()) {
// DW_AT_stmt_list is a offset of line number information for this
InfoHolder.addUnit(NewCU);
CUMap.insert(std::make_pair(N, NewCU));
+ CUDieMap.insert(std::make_pair(Die, NewCU));
return NewCU;
}
// Construct subprogram DIE.
-void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU,
- const MDNode *N) {
+void DwarfDebug::constructSubprogramDIE(CompileUnit *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.
+
CompileUnit *&CURef = SPMap[N];
if (CURef)
return;
DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP);
// Expose as a global name.
- TheCU->addGlobalName(SP.getName(), SubprogramDie);
+ TheCU->addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext()));
}
void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU,
unsigned FileID = getOrCreateSourceID(Module.getContext().getFilename(),
Module.getContext().getDirectory(),
TheCU->getUniqueID());
- TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, 0, FileID);
- TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, 0, Module.getLineNumber());
- TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, dwarf::DW_FORM_ref4,
- EntityDie);
+ TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, None, FileID);
+ TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, None, Module.getLineNumber());
+ TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, EntityDie);
StringRef Name = Module.getName();
if (!Name.empty())
TheCU->addString(IMDie, dwarf::DW_AT_name, Name);
for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
DIE *ISP = *AI;
- FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
+ FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
}
for (DenseMap<const MDNode *, DIE *>::iterator AI = AbstractSPDies.begin(),
AE = AbstractSPDies.end(); AI != AE; ++AI) {
DIE *ISP = AI->second;
if (InlinedSubprogramDIEs.count(ISP))
continue;
- FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
+ FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
}
}
// Collect info for variables that were optimized out.
void DwarfDebug::collectDeadVariables() {
const Module *M = MMI->getModule();
- DenseMap<const MDNode *, LexicalScope *> DeadFnScopeMap;
if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) {
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
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;
+ if (ProcessedSPNodes.count(SP) != 0)
+ continue;
+ if (!SP.isSubprogram())
+ continue;
+ if (!SP.isDefinition())
+ continue;
DIArray Variables = SP.getVariables();
- if (Variables.getNumElements() == 0) continue;
-
- LexicalScope *Scope =
- new LexicalScope(NULL, DIDescriptor(SP), NULL, false);
- DeadFnScopeMap[SP] = Scope;
+ if (Variables.getNumElements() == 0)
+ continue;
// Construct subprogram DIE and add variables DIEs.
CompileUnit *SPCU = CUMap.lookup(TheCU);
assert(SPCU && "Unable to find Compile Unit!");
+ // FIXME: See the comment in constructSubprogramDIE about duplicate
+ // subprogram DIEs.
constructSubprogramDIE(SPCU, SP);
- DIE *ScopeDIE = getSPDIE(SP);
+ DIE *SPDIE = SPCU->getDIE(SP);
for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) {
DIVariable DV(Variables.getElement(vi));
- if (!DV.isVariable()) continue;
+ if (!DV.isVariable())
+ continue;
DbgVariable NewVar(DV, NULL, this);
if (DIE *VariableDIE =
- SPCU->constructVariableDIE(&NewVar, Scope->isAbstractScope()))
- ScopeDIE->addChild(VariableDIE);
+ SPCU->constructVariableDIE(NewVar, false))
+ SPDIE->addChild(VariableDIE);
}
}
}
}
- DeleteContainerSeconds(DeadFnScopeMap);
}
// Type Signature [7.27] and ODR Hash code.
if (GenerateODRHash && shouldAddODRHash(CUMap.begin()->second, Die))
CUMap.begin()->second->addUInt(Die, dwarf::DW_AT_GNU_odr_signature,
dwarf::DW_FORM_data8,
- Hash.computeDIEODRSignature(Die));
- }
-
- // Process the worklist to add attributes with the correct form (ref_addr or
- // ref4).
- for (unsigned I = 0, E = DIEEntryWorklist.size(); I < E; I++) {
- addDIEEntry(DIEEntryWorklist[I].Die, DIEEntryWorklist[I].Attribute,
- dwarf::DW_FORM_ref4, DIEEntryWorklist[I].Entry);
- assert(E == DIEEntryWorklist.size() &&
- "We should not add to the worklist during finalization.");
+ Hash.computeDIEODRSignature(*Die));
}
// Handle anything that needs to be done on a per-cu basis.
uint64_t ID = 0;
if (GenerateCUHash) {
DIEHash CUHash;
- ID = CUHash.computeCUSignature(TheCU->getCUDie());
+ ID = CUHash.computeCUSignature(*TheCU->getCUDie());
}
// This should be a unique identifier when we want to build .dwp files.
TheCU->addUInt(TheCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id,
// Gather pre-function debug information. Assumes being called immediately
// after the function entry point has been emitted.
void DwarfDebug::beginFunction(const MachineFunction *MF) {
- if (!MMI->hasDebugInfo()) return;
+
+ // If there's no debug info for the function we're not going to do anything.
+ if (!MMI->hasDebugInfo())
+ return;
+
+ // Grab the lexical scopes for the function, if we don't have any of those
+ // then we're not going to be able to do anything.
LScopes.initialize(*MF);
- if (LScopes.empty()) return;
+ if (LScopes.empty())
+ return;
+
+ assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned");
+
+ // Make sure that each lexical scope will have a begin/end label.
identifyScopeMarkers();
// Set DwarfCompileUnitID in MCContext to the Compile Unit this function
- // belongs to.
+ // belongs to so that we add to the correct per-cu line table in the
+ // non-asm case.
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
assert(TheCU && "Unable to find compile unit!");
- if (Asm->TM.hasMCUseLoc() &&
- Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer)
+ if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport())
// Use a single line table if we are using .loc and generating assembly.
Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
else
Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID());
- FunctionBeginSym = Asm->GetTempSymbol("func_begin",
- Asm->getFunctionNumber());
+ // Emit a label for the function so that we have a beginning address.
+ FunctionBeginSym = Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber());
// Assumes in correct section after the entry point.
Asm->OutStreamer.EmitLabel(FunctionBeginSym);
- assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned");
-
const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
// LiveUserVar - Map physreg numbers to the MDNode they contain.
- std::vector<const MDNode*> LiveUserVar(TRI->getNumRegs());
+ std::vector<const MDNode *> LiveUserVar(TRI->getNumRegs());
- for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
- I != E; ++I) {
+ 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) {
// Keep track of user variables.
const MDNode *Var =
- MI->getOperand(MI->getNumOperands() - 1).getMetadata();
+ 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];
+ SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
if (History.empty()) {
UserVariables.push_back(Var);
// The first mention of a function argument gets the FunctionBeginSym
DIVariable DV(Var);
if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(getDISubprogram(DV.getContext()))
- .describes(MF->getFunction()))
+ .describes(MF->getFunction()))
LabelsBeforeInsn[MI] = FunctionBeginSym;
} else {
// We have seen this variable before. Try to coalesce DBG_VALUEs.
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");
+ << "\t" << *Prev << "\t"
+ << *History[History.size() - 2] << "\n");
History.pop_back();
}
// Previous register assignment needs to terminate at the end of
// its basic block.
MachineBasicBlock::const_iterator LastMI =
- PrevMBB->getLastNonDebugInstr();
+ PrevMBB->getLastNonDebugInstr();
if (LastMI == PrevMBB->end()) {
// Drop DBG_VALUE for empty range.
DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
- << "\t" << *Prev << "\n");
+ << "\t" << *Prev << "\n");
History.pop_back();
} else if (llvm::next(PrevMBB) != PrevMBB->getParent()->end())
// Terminate after LastMI.
// Check if the instruction clobbers any registers with debug vars.
for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(),
- MOE = MI->operands_end(); MOI != MOE; ++MOI) {
+ MOE = MI->operands_end();
+ MOI != MOE; ++MOI) {
if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg())
continue;
- for (MCRegAliasIterator AI(MOI->getReg(), TRI, true);
- AI.isValid(); ++AI) {
+ for (MCRegAliasIterator AI(MOI->getReg(), TRI, true); AI.isValid();
+ ++AI) {
unsigned Reg = *AI;
const MDNode *Var = LiveUserVar[Reg];
if (!Var)
DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);
if (HistI == DbgValues.end())
continue;
- SmallVectorImpl<const MachineInstr*> &History = HistI->second;
+ SmallVectorImpl<const MachineInstr *> &History = HistI->second;
if (History.empty())
continue;
const MachineInstr *Prev = History.back();
for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end();
I != E; ++I) {
- SmallVectorImpl<const MachineInstr*> &History = I->second;
+ SmallVectorImpl<const MachineInstr *> &History = I->second;
if (History.empty())
continue;
if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {
const MachineBasicBlock *PrevMBB = Prev->getParent();
MachineBasicBlock::const_iterator LastMI =
- PrevMBB->getLastNonDebugInstr();
+ PrevMBB->getLastNonDebugInstr();
if (LastMI == PrevMBB->end())
// Drop DBG_VALUE for empty range.
History.pop_back();
// Record beginning of function.
if (!PrologEndLoc.isUnknown()) {
- DebugLoc FnStartDL = getFnDebugLoc(PrologEndLoc,
- MF->getFunction()->getContext());
- recordSourceLine(FnStartDL.getLine(), FnStartDL.getCol(),
- FnStartDL.getScope(MF->getFunction()->getContext()),
- // We'd like to list the prologue as "not statements" but GDB behaves
- // poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
- DWARF2_FLAG_IS_STMT);
+ DebugLoc FnStartDL =
+ getFnDebugLoc(PrologEndLoc, MF->getFunction()->getContext());
+ recordSourceLine(
+ FnStartDL.getLine(), FnStartDL.getCol(),
+ FnStartDL.getScope(MF->getFunction()->getContext()),
+ // We'd like to list the prologue as "not statements" but GDB behaves
+ // poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
+ DWARF2_FLAG_IS_STMT);
}
}
// Emit Methods
//===----------------------------------------------------------------------===//
-// Compute the size and offset of a DIE.
+// 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
DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) {
// Get the children.
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
- const DIEAbbrev *Abbrev = Abbreviations->at(AbbrevNumber - 1);
+ const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
// Set DIE offset
Die->setOffset(Offset);
return Offset;
}
-// Compute the size and offset of all the DIEs.
+// Compute the size and offset for each DIE.
void DwarfUnits::computeSizeAndOffsets() {
- // Offset from the beginning of debug info section.
+ // 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 (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I) {
(*I)->setDebugInfoOffset(SecOffset);
- unsigned Offset =
- sizeof(int32_t) + // Length of Compilation Unit Info
- sizeof(int16_t) + // DWARF version number
- sizeof(int32_t) + // Offset Into Abbrev. Section
- sizeof(int8_t); // Pointer Size (in bytes)
+ // CU-relative offset is reset to 0 here.
+ unsigned Offset = sizeof(int32_t) + // Length of Unit Info
+ (*I)->getHeaderSize(); // Unit-specific headers
+
+ // EndOffset here is CU-relative, after laying out
+ // all of the CU DIE.
unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset);
SecOffset += EndOffset;
}
}
// Recursively emits a debug information entry.
-void DwarfDebug::emitDIE(DIE *Die, std::vector<DIEAbbrev *> *Abbrevs) {
+void DwarfDebug::emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs) {
// Get the abbreviation for this DIE.
unsigned AbbrevNumber = Die->getAbbrevNumber();
- const DIEAbbrev *Abbrev = Abbrevs->at(AbbrevNumber - 1);
+ const DIEAbbrev *Abbrev = Abbrevs[AbbrevNumber - 1];
// Emit the code (index) for the abbreviation.
if (Asm->isVerbose())
// Emit the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
- unsigned Attr = AbbrevData[i].getAttribute();
- unsigned Form = AbbrevData[i].getForm();
+ dwarf::Attribute Attr = AbbrevData[i].getAttribute();
+ dwarf::Form Form = AbbrevData[i].getForm();
assert(Form && "Too many attributes for DIE (check abbreviation)");
if (Asm->isVerbose())
case dwarf::DW_AT_type:
case dwarf::DW_AT_friend:
case dwarf::DW_AT_specification:
+ case dwarf::DW_AT_import:
case dwarf::DW_AT_containing_type: {
DIEEntry *E = cast<DIEEntry>(Values[i]);
DIE *Origin = E->getEntry();
unsigned Addr = Origin->getOffset();
if (Form == dwarf::DW_FORM_ref_addr) {
+ assert(!useSplitDwarf() && "TODO: dwo files can't have relocations.");
// For DW_FORM_ref_addr, output the offset from beginning of debug info
// section. Origin->getOffset() returns the offset from start of the
// compile unit.
- DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
- Addr += Holder.getCUOffset(Origin->getCompileUnit());
+ CompileUnit *CU = CUDieMap.lookup(Origin->getCompileUnit());
+ assert(CU && "CUDie should belong to a CU.");
+ Addr += CU->getDebugInfoOffset();
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ Asm->EmitLabelPlusOffset(DwarfInfoSectionSym, Addr,
+ DIEEntry::getRefAddrSize(Asm));
+ else
+ Asm->EmitLabelOffsetDifference(DwarfInfoSectionSym, Addr,
+ DwarfInfoSectionSym,
+ DIEEntry::getRefAddrSize(Asm));
+ } else {
+ // Make sure Origin belong to the same CU.
+ assert(Die->getCompileUnit() == Origin->getCompileUnit() &&
+ "The referenced DIE should belong to the same CU in ref4");
+ Asm->EmitInt32(Addr);
}
- Asm->OutStreamer.EmitIntValue(Addr,
- Form == dwarf::DW_FORM_ref_addr ? DIEEntry::getRefAddrSize(Asm) : 4);
break;
}
case dwarf::DW_AT_ranges: {
TheCU->getUniqueID()));
// Emit size of content not including length itself
- unsigned ContentSize = Die->getSize() +
- sizeof(int16_t) + // DWARF version number
- sizeof(int32_t) + // Offset Into Abbrev. Section
- sizeof(int8_t); // Pointer Size (in bytes)
+ Asm->OutStreamer.AddComment("Length of Unit");
+ Asm->EmitInt32(TheCU->getHeaderSize() + Die->getSize());
- Asm->OutStreamer.AddComment("Length of Compilation Unit Info");
- Asm->EmitInt32(ContentSize);
- Asm->OutStreamer.AddComment("DWARF version number");
- Asm->EmitInt16(DD->getDwarfVersion());
- Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
- Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()),
- ASectionSym);
- Asm->OutStreamer.AddComment("Address Size (in bytes)");
- Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
+ TheCU->emitHeader(ASection, ASectionSym);
DD->emitDIE(Die, Abbreviations);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(USection->getLabelEndName(),
}
}
-/// For a given compile unit DIE, returns offset from beginning of debug info.
-unsigned DwarfUnits::getCUOffset(DIE *Die) {
- assert(Die->getTag() == dwarf::DW_TAG_compile_unit &&
- "Input DIE should be compile unit in getCUOffset.");
- for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(), E = CUs.end();
- I != E; ++I) {
- CompileUnit *TheCU = *I;
- if (TheCU->getCUDie() == Die)
- return TheCU->getDebugInfoOffset();
- }
- llvm_unreachable("The compile unit DIE should belong to CUs in DwarfUnits.");
-}
-
// Emit the debug info section.
void DwarfDebug::emitDebugInfo() {
DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
/// computeIndexValue - Compute the gdb index value for the DIE and CU.
static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU,
DIE *Die) {
- dwarf::GDBIndexEntryLinkage Linkage =
- Die->findAttribute(dwarf::DW_AT_external) ? dwarf::GIEL_EXTERNAL
- : dwarf::GIEL_STATIC;
+ dwarf::GDBIndexEntryLinkage Linkage = dwarf::GIEL_STATIC;
+
+ // We could have a specification DIE that has our most of our knowledge,
+ // 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))
+ Linkage = dwarf::GIEL_EXTERNAL;
+ } else if (Die->findAttribute(dwarf::DW_AT_external))
+ Linkage = dwarf::GIEL_EXTERNAL;
switch (Die->getTag()) {
case dwarf::DW_TAG_class_type:
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
OffSec, StrSym);
}
-
-/// When we don't know whether the correct form is ref4 or ref_addr, we create
-/// a worklist item and insert it to DIEEntryWorklist.
-void DwarfDebug::addDIEEntry(DIE *Die, uint16_t Attribute, uint16_t Form,
- DIEEntry *Entry) {
- /// Early exit when we only have a single CU.
- if (GlobalCUIndexCount == 1 || Form != dwarf::DW_FORM_ref4) {
- Die->addValue(Attribute, Form, Entry);
- return;
- }
- DIE *DieCU = Die->checkCompileUnit();
- DIE *EntryCU = Entry->getEntry()->checkCompileUnit();
- if (!DieCU || !EntryCU) {
- // Die or Entry is not added to an owner yet.
- insertDIEEntryWorklist(Die, Attribute, Entry);
- return;
- }
- Die->addValue(Attribute,
- EntryCU == DieCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
- Entry);
-}