Newer
Older
//===-- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains support for writing dwarf debug info into asm files.
//
//===----------------------------------------------------------------------===//
#include "DwarfDebug.h"
#include "DwarfCompileUnit.h"
Bill Wendling
committed
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
Anton Korobeynikov
committed
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/ADT/Statistic.h"
Jeffrey Yasskin
committed
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
Devang Patel
committed
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Timer.h"
using namespace llvm;
static cl::opt<bool> DisableDebugInfoPrinting("disable-debug-info-print",
Devang Patel
committed
cl::desc("Disable debug info printing"));
static cl::opt<bool> UnknownLocations("use-unknown-locations", cl::Hidden,
cl::desc("Make an absence of debug location information explicit."),
cl::init(false));
namespace {
const char *DWARFGroupName = "DWARF Emission";
const char *DbgTimerName = "DWARF Debug Writer";
} // end anonymous namespace
//===----------------------------------------------------------------------===//
/// Configuration values for initial hash set sizes (log2).
///
static const unsigned InitAbbreviationsSetSize = 9; // log2(512)
namespace llvm {
Nick Lewycky
committed
DIType DbgVariable::getType() const {
Devang Patel
committed
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
DIType Ty = Var.getType();
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
// addresses instead.
if (Var.isBlockByrefVariable()) {
/* Byref variables, in Blocks, are declared by the programmer as
"SomeType VarName;", but the compiler creates a
__Block_byref_x_VarName struct, and gives the variable VarName
either the struct, or a pointer to the struct, as its type. This
is necessary for various behind-the-scenes things the compiler
needs to do with by-reference variables in blocks.
However, as far as the original *programmer* is concerned, the
variable should still have type 'SomeType', as originally declared.
The following function dives into the __Block_byref_x_VarName
struct to find the original type of the variable. This will be
passed back to the code generating the type for the Debug
Information Entry for the variable 'VarName'. 'VarName' will then
have the original type 'SomeType' in its debug information.
The original type 'SomeType' will be the type of the field named
'VarName' inside the __Block_byref_x_VarName struct.
NOTE: In order for this to not completely fail on the debugger
side, the Debug Information Entry for the variable VarName needs to
have a DW_AT_location that tells the debugger how to unwind through
the pointers and __Block_byref_x_VarName struct to find the actual
value of the variable. The function addBlockByrefType does this. */
DIType subType = Ty;
unsigned tag = Ty.getTag();
if (tag == dwarf::DW_TAG_pointer_type) {
DIDerivedType DTy = DIDerivedType(Ty);
subType = DTy.getTypeDerivedFrom();
}
DICompositeType blockStruct = DICompositeType(subType);
DIArray Elements = blockStruct.getTypeArray();
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIDescriptor Element = Elements.getElement(i);
DIDerivedType DT = DIDerivedType(Element);
if (getName() == DT.getName())
return (DT.getTypeDerivedFrom());
}
return Ty;
}
Devang Patel
committed
return Ty;
}
} // end llvm namespace
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
: Asm(A), MMI(Asm->MMI), FirstCU(0),
AbbreviationsSet(InitAbbreviationsSetSize),
PrevLabel(NULL) {
NextStringPoolNumber = 0;
DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
DwarfStrSectionSym = TextSectionSym = 0;
DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0;
FunctionBeginSym = FunctionEndSym = 0;
{
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
beginModule(M);
}
DwarfDebug::~DwarfDebug() {
}
MCSymbol *DwarfDebug::getStringPoolEntry(StringRef Str) {
std::pair<MCSymbol*, unsigned> &Entry = StringPool[Str];
if (Entry.first) return Entry.first;
Entry.second = NextStringPoolNumber++;
return Entry.first = Asm->GetTempSymbol("string", Entry.second);
/// assignAbbrevNumber - Define a unique number for the abbreviation.
void DwarfDebug::assignAbbrevNumber(DIEAbbrev &Abbrev) {
// Profile the node so that we can make it unique.
FoldingSetNodeID ID;
Abbrev.Profile(ID);
// Check the set for priors.
DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
// If 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());
}
}
/// getRealLinkageName - If special LLVM prefix that is used to inform the asm
/// printer to not emit usual symbol prefix before the symbol name is used then
/// return linkage name after skipping this special LLVM prefix.
static StringRef getRealLinkageName(StringRef LinkageName) {
char One = '\1';
if (LinkageName.startswith(StringRef(&One, 1)))
return LinkageName.substr(1);
return LinkageName;
}
/// updateSubprogramScopeDIE - Find DIE for the given subprogram and
/// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes.
/// If there are global variables in this scope then create and insert
/// DIEs for these variables.
Devang Patel
committed
DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU,
const MDNode *SPNode) {
DIE *SPDie = SPCU->getDIE(SPNode);
assert(SPDie && "Unable to find subprogram DIE!");
DISubprogram SP(SPNode);
Devang Patel
committed
DISubprogram SPDecl = SP.getFunctionDeclaration();
if (SPDecl.isSubprogram())
// Refer function declaration directly.
Devang Patel
committed
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
Devang Patel
committed
SPCU->getOrCreateSubprogramDIE(SPDecl));
Devang Patel
committed
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
else {
// 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.
if (SP.isDefinition() && !SP.getContext().isCompileUnit() &&
!SP.getContext().isFile() &&
!isSubprogramContext(SP.getContext())) {
SPCU-> addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
// Add arguments.
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
unsigned 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);
DIType ATy = DIType(DIType(Args.getElement(i)));
SPCU->addType(Arg, ATy);
if (ATy.isArtificial())
SPCU->addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1);
SPDie->addChild(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);
}
// Pick up abstract subprogram DIE.
if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) {
SPDie = new DIE(dwarf::DW_TAG_subprogram);
Devang Patel
committed
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin,
dwarf::DW_FORM_ref4, AbsSPDIE);
SPCU->addDie(SPDie);
}
Devang Patel
committed
SPCU->addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber()));
SPCU->addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
Asm->GetTempSymbol("func_end", Asm->getFunctionNumber()));
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
Devang Patel
committed
SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
/// constructLexicalScope - Construct new DW_TAG_lexical_block
/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels.
Devang Patel
committed
DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
LexicalScope *Scope) {
Devang Patel
committed
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
if (Scope->isAbstractScope())
return ScopeDIE;
const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
Devang Patel
committed
if (Ranges.empty())
return 0;
SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
Devang Patel
committed
if (Ranges.size() > 1) {
// .debug_range section has not been laid out yet. Emit offset in
// .debug_range as a uint, size 4, for now. emitDIE will handle
Devang Patel
committed
// DW_AT_ranges appropriately.
Devang Patel
committed
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
DebugRangeSymbols.size()
* Asm->getTargetData().getPointerSize());
for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
Devang Patel
committed
RE = Ranges.end(); RI != RE; ++RI) {
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
Devang Patel
committed
}
DebugRangeSymbols.push_back(NULL);
DebugRangeSymbols.push_back(NULL);
return ScopeDIE;
}
const MCSymbol *Start = getLabelBeforeInsn(RI->first);
const MCSymbol *End = getLabelAfterInsn(RI->second);
Devang Patel
committed
Devang Patel
committed
assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
assert(End->isDefined() && "Invalid end label for an inlined scope!");
Devang Patel
committed
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start);
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End);
return ScopeDIE;
}
/// constructInlinedScopeDIE - This scope represents inlined body of
/// a function. Construct DIE to represent this concrete inlined copy
/// of the function.
Devang Patel
committed
DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
LexicalScope *Scope) {
Devang Patel
committed
const SmallVector<InsnRange, 4> &Ranges = Scope->getRanges();
assert (Ranges.empty() == false
&& "LexicalScope does not have instruction markers!");
Devang Patel
committed
Devang Patel
committed
if (!Scope->getScopeNode())
return NULL;
DIScope DS(Scope->getScopeNode());
DISubprogram InlinedSP = getDISubprogram(DS);
DIE *OriginDIE = TheCU->getDIE(InlinedSP);
if (!OriginDIE) {
DEBUG(dbgs() << "Unable to find original DIE for inlined subprogram.");
return NULL;
}
SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
const MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
Devang Patel
committed
Devang Patel
committed
if (StartLabel == 0 || EndLabel == 0) {
Nick Lewycky
committed
assert (0 && "Unexpected Start and End labels for a inlined scope!");
Devang Patel
committed
return 0;
}
assert(StartLabel->isDefined() &&
"Invalid starting label for an inlined scope!");
assert(EndLabel->isDefined() &&
"Invalid end label for an inlined scope!");
Devang Patel
committed
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
Devang Patel
committed
TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
dwarf::DW_FORM_ref4, OriginDIE);
Devang Patel
committed
if (Ranges.size() > 1) {
// .debug_range section has not been laid out yet. Emit offset in
// .debug_range as a uint, size 4, for now. emitDIE will handle
// DW_AT_ranges appropriately.
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
DebugRangeSymbols.size()
* Asm->getTargetData().getPointerSize());
for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
Devang Patel
committed
RE = Ranges.end(); RI != RE; ++RI) {
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
}
DebugRangeSymbols.push_back(NULL);
DebugRangeSymbols.push_back(NULL);
} else {
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
StartLabel);
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
EndLabel);
Devang Patel
committed
}
InlinedSubprogramDIEs.insert(OriginDIE);
// Track the start label for this inlined function.
Devang Patel
committed
//.debug_inlined section specification does not clearly state how
// to emit inlined scope that is split into multiple instruction ranges.
// For now, use first instruction range and emit low_pc/high_pc pair and
// corresponding .debug_inlined section entry for this pair.
DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
I = InlineInfo.find(InlinedSP);
if (I == InlineInfo.end()) {
InlineInfo[InlinedSP].push_back(std::make_pair(StartLabel,
InlinedSPNodes.push_back(InlinedSP);
I->second.push_back(std::make_pair(StartLabel, ScopeDIE));
DILocation DL(Scope->getInlinedAt());
Devang Patel
committed
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, TheCU->getID());
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber());
return ScopeDIE;
}
/// constructScopeDIE - Construct a DIE for this scope.
Devang Patel
committed
DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) {
if (!Scope || !Scope->getScopeNode())
return NULL;
Devang Patel
committed
SmallVector <DIE *, 8> Children;
Devang Patel
committed
// Collect arguments for current function.
if (LScopes.isCurrentFunctionScope(Scope))
Devang Patel
committed
for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
if (DbgVariable *ArgDV = CurrentFnArguments[i])
Devang Patel
committed
if (DIE *Arg =
TheCU->constructVariableDIE(ArgDV, Scope->isAbstractScope()))
Devang Patel
committed
Children.push_back(Arg);
const SmallVector<DbgVariable *, 8> &Variables = ScopeVariables.lookup(Scope);
Devang Patel
committed
for (unsigned i = 0, N = Variables.size(); i < N; ++i)
Devang Patel
committed
if (DIE *Variable =
TheCU->constructVariableDIE(Variables[i], Scope->isAbstractScope()))
Devang Patel
committed
Children.push_back(Variable);
const SmallVector<LexicalScope *, 4> &Scopes = Scope->getChildren();
Devang Patel
committed
for (unsigned j = 0, M = Scopes.size(); j < M; ++j)
Devang Patel
committed
if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j]))
Devang Patel
committed
Children.push_back(Nested);
DIScope DS(Scope->getScopeNode());
DIE *ScopeDIE = NULL;
if (Scope->getInlinedAt())
Devang Patel
committed
ScopeDIE = constructInlinedScopeDIE(TheCU, Scope);
ProcessedSPNodes.insert(DS);
if (Scope->isAbstractScope()) {
Devang Patel
committed
ScopeDIE = TheCU->getDIE(DS);
// Note down abstract DIE.
if (ScopeDIE)
AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
}
Devang Patel
committed
ScopeDIE = updateSubprogramScopeDIE(TheCU, DS);
Devang Patel
committed
else {
// There is no need to emit empty lexical block DIE.
if (Children.empty())
return NULL;
Devang Patel
committed
ScopeDIE = constructLexicalScopeDIE(TheCU, Scope);
Devang Patel
committed
if (!ScopeDIE) return NULL;
Devang Patel
committed
// Add children
for (SmallVector<DIE *, 8>::iterator I = Children.begin(),
E = Children.end(); I != E; ++I)
ScopeDIE->addChild(*I);
Devang Patel
committed
TheCU->addPubTypes(DISubprogram(DS));
/// GetOrCreateSourceID - Look up the source id with the given directory and
/// source file names. If none currently exists, create a new id and insert it
/// in the SourceIds map. This can update DirectoryNames and SourceFileNames
/// maps as well.
Devang Patel
committed
Devang Patel
committed
unsigned DwarfDebug::GetOrCreateSourceID(StringRef FileName,
StringRef DirName) {
Devang Patel
committed
// If FE did not provide a file name, then assume stdin.
if (FileName.empty())
Devang Patel
committed
return GetOrCreateSourceID("<stdin>", StringRef());
unsigned SrcId = SourceIdMap.size()+1;
std::pair<std::string, std::string> SourceName =
std::make_pair(FileName, DirName);
std::pair<std::pair<std::string, std::string>, unsigned> Entry =
make_pair(SourceName, SrcId);
std::map<std::pair<std::string, std::string>, unsigned>::iterator I;
bool NewlyInserted;
tie(I, NewlyInserted) = SourceIdMap.insert(Entry);
if (!NewlyInserted)
return I->second;
Rafael Espindola
committed
// Print out a .file directive to specify files for .loc directives.
Asm->OutStreamer.EmitDwarfFileDirective(SrcId, Entry.first.second,
Entry.first.first);
/// constructCompileUnit - Create new CompileUnit for the given
/// metadata node with tag DW_TAG_compile_unit.
Devang Patel
committed
CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
StringRef FN = DIUnit.getFilename();
StringRef Dir = DIUnit.getDirectory();
Devang Patel
committed
unsigned ID = GetOrCreateSourceID(FN, Dir);
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
Devang Patel
committed
CompileUnit *NewCU = new CompileUnit(ID, Die, Asm, this);
NewCU->addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
DIUnit.getProducer());
NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
DIUnit.getLanguage());
NewCU->addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
Devang Patel
committed
// Use DW_AT_entry_pc instead of DW_AT_low_pc/DW_AT_high_pc pair. This
// simplifies debug range entries.
Devang Patel
committed
NewCU->addUInt(Die, dwarf::DW_AT_entry_pc, dwarf::DW_FORM_addr, 0);
// DW_AT_stmt_list is a offset of line number information for this
// compile unit in debug_line section.
if(Asm->MAI->doesDwarfRequireRelocationForSectionOffset())
NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
Devang Patel
committed
Asm->GetTempSymbol("section_line"));
Devang Patel
committed
else
Devang Patel
committed
NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
Devang Patel
committed
NewCU->addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir);
Devang Patel
committed
NewCU->addUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1);
StringRef Flags = DIUnit.getFlags();
if (!Flags.empty())
NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string,
Flags);
Devang Patel
committed
unsigned RVer = DIUnit.getRunTimeVersion();
if (RVer)
Devang Patel
committed
NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
dwarf::DW_FORM_data1, RVer);
if (!FirstCU)
FirstCU = NewCU;
CUMap.insert(std::make_pair(N, NewCU));
Devang Patel
committed
return NewCU;
/// construct SubprogramDIE - Construct subprogram DIE.
Devang Patel
committed
void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU,
const MDNode *N) {
if (!SP.isDefinition())
// This is a method declaration which will be handled while constructing
// class type.
Bill Wendling
committed
Devang Patel
committed
DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP);
// Add to map.
TheCU->insertDIE(N, SubprogramDie);
Devang Patel
committed
TheCU->addToContextOwner(SubprogramDie, SP.getContext());
TheCU->addGlobal(SP.getName(), SubprogramDie);
Devang Patel
committed
SPMap[N] = TheCU;
/// collectInfoFromNamedMDNodes - Collect debug info from named mdnodes such
/// as llvm.dbg.enum and llvm.dbg.ty
void DwarfDebug::collectInfoFromNamedMDNodes(Module *M) {
Devang Patel
committed
if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp"))
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
const MDNode *N = NMD->getOperand(i);
if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit()))
constructSubprogramDIE(CU, N);
}
if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"))
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
const MDNode *N = NMD->getOperand(i);
if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit()))
CU->createGlobalVariableDIE(N);
Devang Patel
committed
}
if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum"))
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIType Ty(NMD->getOperand(i));
Devang Patel
committed
if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit()))
CU->getOrCreateTypeDIE(Ty);
}
if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty"))
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIType Ty(NMD->getOperand(i));
Devang Patel
committed
if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit()))
CU->getOrCreateTypeDIE(Ty);
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
}
}
/// collectLegacyDebugInfo - Collect debug info using DebugInfoFinder.
/// FIXME - Remove this when dragon-egg and llvm-gcc switch to DIBuilder.
bool DwarfDebug::collectLegacyDebugInfo(Module *M) {
DebugInfoFinder DbgFinder;
DbgFinder.processModule(*M);
bool HasDebugInfo = false;
// Scan all the compile-units to see if there are any marked as the main
// unit. If not, we do not generate debug info.
for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
E = DbgFinder.compile_unit_end(); I != E; ++I) {
if (DICompileUnit(*I).isMain()) {
HasDebugInfo = true;
break;
}
}
if (!HasDebugInfo) return false;
// Create all the compile unit DIEs.
for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(),
E = DbgFinder.compile_unit_end(); I != E; ++I)
constructCompileUnit(*I);
// Create DIEs for each global variable.
for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
E = DbgFinder.global_variable_end(); I != E; ++I) {
const MDNode *N = *I;
Devang Patel
committed
if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit()))
CU->createGlobalVariableDIE(N);
Devang Patel
committed
// Create DIEs for each subprogram.
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
E = DbgFinder.subprogram_end(); I != E; ++I) {
const MDNode *N = *I;
Devang Patel
committed
if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit()))
constructSubprogramDIE(CU, N);
/// beginModule - Emit all Dwarf sections that should come prior to the
/// content. Create global DIEs and emit initial debug info sections.
Nick Lewycky
committed
/// This is invoked by the target AsmPrinter.
void DwarfDebug::beginModule(Module *M) {
Devang Patel
committed
if (DisableDebugInfoPrinting)
return;
Nick Lewycky
committed
// If module has named metadata anchors then use them, otherwise scan the
// module using debug info finder to collect debug info.
Devang Patel
committed
NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
if (CU_Nodes) {
Devang Patel
committed
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
DICompileUnit CUNode(CU_Nodes->getOperand(i));
CompileUnit *CU = constructCompileUnit(CUNode);
DIArray GVs = CUNode.getGlobalVariables();
for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i)
CU->createGlobalVariableDIE(GVs.getElement(i));
Devang Patel
committed
DIArray SPs = CUNode.getSubprograms();
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i)
constructSubprogramDIE(CU, SPs.getElement(i));
DIArray EnumTypes = CUNode.getEnumTypes();
for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i)
CU->getOrCreateTypeDIE(EnumTypes.getElement(i));
DIArray RetainedTypes = CUNode.getRetainedTypes();
for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i)
CU->getOrCreateTypeDIE(RetainedTypes.getElement(i));
}
Devang Patel
committed
// Tell MMI that we have debug info.
MMI->setDebugInfoAvailability(true);
Devang Patel
committed
// Emit initial sections.
EmitSectionLabels();
SectionMap.insert(Asm->getObjFileLowering().getTextSection());
/// endModule - Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {
const Module *M = MMI->getModule();
DenseMap<const MDNode *, LexicalScope *> DeadFnScopeMap;
Devang Patel
committed
// Collect info for variables that were optimized out.
if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) {
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
DICompileUnit TheCU(CU_Nodes->getOperand(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.Verify()) continue;
if (!SP.isDefinition()) continue;
Devang Patel
committed
DIArray Variables = SP.getVariables();
if (Variables.getNumElements() == 0) continue;
Devang Patel
committed
LexicalScope *Scope =
new LexicalScope(NULL, DIDescriptor(SP), NULL, false);
DeadFnScopeMap[SP] = Scope;
// Construct subprogram DIE and add variables DIEs.
CompileUnit *SPCU = CUMap.lookup(TheCU);
assert (SPCU && "Unable to find Compile Unit!");
constructSubprogramDIE(SPCU, SP);
DIE *ScopeDIE = SPCU->getDIE(SP);
Devang Patel
committed
for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) {
DIVariable DV(Variables.getElement(vi));
if (!DV.Verify()) continue;
DbgVariable *NewVar = new DbgVariable(DV, NULL);
Devang Patel
committed
if (DIE *VariableDIE =
Devang Patel
committed
SPCU->constructVariableDIE(NewVar, Scope->isAbstractScope()))
Devang Patel
committed
ScopeDIE->addChild(VariableDIE);
}
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
DIE *ISP = *AI;
Devang Patel
committed
FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
Devang Patel
committed
// Emit DW_AT_containing_type attribute to connect types with their
// vtable holding type.
for (DenseMap<const MDNode *, CompileUnit *>::iterator CUI = CUMap.begin(),
CUE = CUMap.end(); CUI != CUE; ++CUI) {
CompileUnit *TheCU = CUI->second;
TheCU->constructContainingTypeDIEs();
Devang Patel
committed
}
// Standard sections final addresses.
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end"));
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection());
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("data_end"));
// End text sections.
for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
Asm->OutStreamer.SwitchSection(SectionMap[i]);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", i));
// Compute DIE offsets and sizes.
computeSizeAndOffsets();
// Emit all the DIEs into a debug info section
emitDebugInfo();
// Corresponding abbreviations into a abbrev section.
emitAbbreviations();
// Emit info into a debug pubnames section.
emitDebugPubNames();
// Emit info into a debug pubtypes section.
emitDebugPubTypes();
// Emit info into a debug loc section.
emitDebugLoc();
// Emit info into a debug aranges section.
EmitDebugARanges();
// Emit info into a debug ranges section.
emitDebugRanges();
// Emit info into a debug macinfo section.
emitDebugMacInfo();
emitDebugInlineInfo();
// Emit info into a debug str section.
emitDebugStr();
// clean up.
DeleteContainerSeconds(DeadFnScopeMap);
Devang Patel
committed
SPMap.clear();
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I)
delete I->second;
FirstCU = NULL; // Reset for the next Module, if any.
/// findAbstractVariable - Find abstract variable, if any, associated with Var.
DebugLoc ScopeLoc) {
LLVMContext &Ctx = DV->getContext();
// More then one inlined variable corresponds to one abstract variable.
DIVariable Var = cleanseInlinedVariable(DV, Ctx);
DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
Devang Patel
committed
if (AbsDbgVariable)
return AbsDbgVariable;
LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx));
Devang Patel
committed
if (!Scope)
return NULL;
AbsDbgVariable = new DbgVariable(Var, NULL);
addScopeVariable(Scope, AbsDbgVariable);
AbstractVariables[Var] = AbsDbgVariable;
Devang Patel
committed
return AbsDbgVariable;
}
Nick Lewycky
committed
/// addCurrentFnArgument - If Var is a current function argument then add
/// it to CurrentFnArguments list.
Devang Patel
committed
bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
DbgVariable *Var, LexicalScope *Scope) {
if (!LScopes.isCurrentFunctionScope(Scope))
Devang Patel
committed
return false;
DIVariable DV = Var->getVariable();
if (DV.getTag() != dwarf::DW_TAG_arg_variable)
return false;
unsigned ArgNo = DV.getArgNumber();
if (ArgNo == 0)
return false;
Devang Patel
committed
size_t Size = CurrentFnArguments.size();
if (Size == 0)
Devang Patel
committed
CurrentFnArguments.resize(MF->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)
Devang Patel
committed
CurrentFnArguments.resize(ArgNo * 2);
Devang Patel
committed
CurrentFnArguments[ArgNo - 1] = Var;
return true;
}
/// collectVariableInfoFromMMITable - Collect variable information from
/// side table maintained by MMI.
Nick Lewycky
committed
DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF,
MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
VE = VMap.end(); VI != VE; ++VI) {
Devang Patel
committed
Processed.insert(Var);
DIVariable DV(Var);
const std::pair<unsigned, DebugLoc> &VP = VI->second;
LexicalScope *Scope = LScopes.findLexicalScope(VP.second);
// If variable scope is not found then skip this variable.
if (Scope == 0)
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second);
DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable);
Devang Patel
committed
RegVar->setFrameIndex(VP.first);
Devang Patel
committed
if (!addCurrentFnArgument(MF, RegVar, Scope))
addScopeVariable(Scope, RegVar);
if (AbsDbgVariable)
Devang Patel
committed
AbsDbgVariable->setFrameIndex(VP.first);
}
/// isDbgValueInDefinedReg - Return true if debug value, encoded by
/// DBG_VALUE instruction, is in a defined reg.
static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
assert (MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
return MI->getNumOperands() == 3 &&
MI->getOperand(0).isReg() && MI->getOperand(0).getReg() &&
MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0;
Nick Lewycky
committed
/// getDebugLocEntry - Get .debug_loc entry for the instruction range starting
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
/// at MI.
static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
const MCSymbol *FLabel,
const MCSymbol *SLabel,
const MachineInstr *MI) {
const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata();
if (MI->getNumOperands() != 3) {
MachineLocation MLoc = Asm->getDebugValueLocation(MI);
return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
}
if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) {
MachineLocation MLoc;
MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
}
if (MI->getOperand(0).isImm())
return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm());
if (MI->getOperand(0).isFPImm())
return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm());
if (MI->getOperand(0).isCImm())
return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm());
assert (0 && "Unexpected 3 operand DBG_VALUE instruction!");
return DotDebugLocEntry();
}
/// collectVariableInfo - Find variables for each lexical scope.
DwarfDebug::collectVariableInfo(const MachineFunction *MF,
SmallPtrSet<const MDNode *, 16> &Processed) {
/// collection info from MMI table.
collectVariableInfoFromMMITable(MF, Processed);
Devang Patel
committed
Jakob Stoklund Olesen
committed
for (SmallVectorImpl<const MDNode*>::const_iterator
UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI != UVE;
++UVI) {
const MDNode *Var = *UVI;
if (Processed.count(Var))
Devang Patel
committed
Jakob Stoklund Olesen
committed
// History contains relevant DBG_VALUE instructions for Var and instructions
// clobbering it.
SmallVectorImpl<const MachineInstr*> &History = DbgValues[Var];
if (History.empty())
continue;
const MachineInstr *MInsn = History.front();
Jakob Stoklund Olesen
committed
DIVariable DV(Var);
LexicalScope *Scope = NULL;
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
DISubprogram(DV.getContext()).describes(MF->getFunction()))
Scope = LScopes.getCurrentFunctionScope();
else {
if (DV.getVersion() <= LLVMDebugVersion9)
Scope = LScopes.findLexicalScope(MInsn->getDebugLoc());
else {
if (MDNode *IA = DV.getInlinedAt())
Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA));
else
Scope = LScopes.findLexicalScope(cast<MDNode>(DV->getOperand(1)));
}
}
Jakob Stoklund Olesen
committed
assert(MInsn->isDebugValue() && "History must begin with debug value");
DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc());
DbgVariable *RegVar = new DbgVariable(DV, AbsVar);
Devang Patel
committed
if (!addCurrentFnArgument(MF, RegVar, Scope))
addScopeVariable(Scope, RegVar);
if (AbsVar)
Devang Patel
committed
AbsVar->setMInsn(MInsn);
Jakob Stoklund Olesen
committed
// Simple ranges that are fully coalesced.
if (History.size() <= 1 || (History.size() == 2 &&
MInsn->isIdenticalTo(History.back()))) {
Devang Patel
committed
RegVar->setMInsn(MInsn);
continue;
}
// handle multiple DBG_VALUE instructions describing one variable.
Jakob Stoklund Olesen
committed
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
Jakob Stoklund Olesen
committed
for (SmallVectorImpl<const MachineInstr*>::const_iterator
HI = History.begin(), HE = History.end(); HI != HE; ++HI) {
const MachineInstr *Begin = *HI;
assert(Begin->isDebugValue() && "Invalid History entry");
// Check if DBG_VALUE is truncating a range.
if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg()
&& !Begin->getOperand(0).getReg())
continue;
// Compute the range for a register location.
const MCSymbol *FLabel = getLabelBeforeInsn(Begin);
const MCSymbol *SLabel = 0;
Jakob Stoklund Olesen
committed
if (HI + 1 == HE)
// If Begin is the last instruction in History then its value is valid
// until the end of the function.
SLabel = FunctionEndSym;
Jakob Stoklund Olesen
committed
else {
const MachineInstr *End = HI[1];
DEBUG(dbgs() << "DotDebugLoc Pair:\n"
<< "\t" << *Begin << "\t" << *End << "\n");
Jakob Stoklund Olesen
committed
if (End->isDebugValue())
SLabel = getLabelBeforeInsn(End);
else {
// End is a normal instruction clobbering the range.
SLabel = getLabelAfterInsn(End);
assert(SLabel && "Forgot label after clobber instruction");
++HI;
}
}
Jakob Stoklund Olesen
committed
// The value is valid until the next DBG_VALUE or clobber.
DotDebugLocEntries.push_back(getDebugLocEntry(Asm, FLabel, SLabel, Begin));
}
DotDebugLocEntries.push_back(DotDebugLocEntry());
Devang Patel
committed
}
Devang Patel
committed
// Collect info for variables that were optimized out.
Devang Patel
committed
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.Verify() || !Processed.insert(DV))
continue;
if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext()))
addScopeVariable(Scope, new DbgVariable(DV, NULL));
Devang Patel
committed
}
}
/// getLabelBeforeInsn - Return Label preceding the instruction.
const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
Jakob Stoklund Olesen
committed
MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
assert(Label && "Didn't insert label before instruction");
return Label;
Devang Patel
committed
/// getLabelAfterInsn - Return Label immediately following the instruction.
const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
Jakob Stoklund Olesen
committed
return LabelsAfterInsn.lookup(MI);
}
/// beginInstruction - Process beginning of an instruction.
void DwarfDebug::beginInstruction(const MachineInstr *MI) {
Jakob Stoklund Olesen
committed
// Check if source location changes, but ignore DBG_VALUE locations.
if (!MI->isDebugValue()) {
DebugLoc DL = MI->getDebugLoc();
if (DL != PrevInstLoc && (!DL.isUnknown() || UnknownLocations)) {
unsigned Flags = DWARF2_FLAG_IS_STMT;