"llvm/lib/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "8d5e128bd48a9c481150251c9761ce7838e65e87"
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/Mangler.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;
Devang Patel
committed
static cl::opt<bool> PrintDbgScope("print-dbgscope", cl::Hidden,
cl::desc("Print DbgScope information for each machine instruction"));
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 {
Devang Patel
committed
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
113
114
115
116
DIType DbgVariable::getType() const {
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;
}
Devang Patel
committed
//===----------------------------------------------------------------------===//
/// DbgRange - This is used to track range of instructions with identical
/// debug info scope.
///
typedef std::pair<const MachineInstr *, const MachineInstr *> DbgRange;
//===----------------------------------------------------------------------===//
/// DbgScope - This class is used to track scope information.
///
DbgScope *Parent; // Parent to this scope.
DIDescriptor Desc; // Debug info descriptor for scope.
// Location at which this scope is inlined.
AssertingVH<const MDNode> InlinedAtLocation;
bool AbstractScope; // Abstract Scope
const MachineInstr *LastInsn; // Last instruction of this scope.
const MachineInstr *FirstInsn; // First instruction of this scope.
Devang Patel
committed
unsigned DFSIn, DFSOut;
Jeffrey Yasskin
committed
// Scopes defined in scope. Contents not owned.
SmallVector<DbgScope *, 4> Scopes;
// Variables declared in scope. Contents owned.
SmallVector<DbgVariable *, 8> Variables;
Devang Patel
committed
SmallVector<DbgRange, 4> Ranges;
// Private state for dump()
mutable unsigned IndentLevel;
DbgScope(DbgScope *P, DIDescriptor D, const MDNode *I = 0)
: Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false),
Devang Patel
committed
LastInsn(0), FirstInsn(0),
DFSIn(0), DFSOut(0), IndentLevel(0) {}
virtual ~DbgScope();
// Accessors.
DbgScope *getParent() const { return Parent; }
void setParent(DbgScope *P) { Parent = P; }
DIDescriptor getDesc() const { return Desc; }
const MDNode *getInlinedAt() const { return InlinedAtLocation; }
const MDNode *getScopeNode() const { return Desc; }
Jeffrey Yasskin
committed
const SmallVector<DbgScope *, 4> &getScopes() { return Scopes; }
const SmallVector<DbgVariable *, 8> &getDbgVariables() { return Variables; }
Devang Patel
committed
const SmallVector<DbgRange, 4> &getRanges() { return Ranges; }
/// openInsnRange - This scope covers instruction range starting from MI.
void openInsnRange(const MachineInstr *MI) {
Devang Patel
committed
FirstInsn = MI;
Devang Patel
committed
if (Parent)
Parent->openInsnRange(MI);
}
/// extendInsnRange - Extend the current instruction range covered by
Devang Patel
committed
/// this scope.
void extendInsnRange(const MachineInstr *MI) {
assert (FirstInsn && "MI Range is not open!");
LastInsn = MI;
if (Parent)
Parent->extendInsnRange(MI);
}
/// closeInsnRange - Create a range based on FirstInsn and LastInsn collected
/// until now. This is used when a new scope is encountered while walking
/// machine instructions.
void closeInsnRange(DbgScope *NewScope = NULL) {
assert (LastInsn && "Last insn missing!");
Ranges.push_back(DbgRange(FirstInsn, LastInsn));
Devang Patel
committed
LastInsn = NULL;
// If Parent dominates NewScope then do not close Parent's instruction
Devang Patel
committed
// range.
if (Parent && (!NewScope || !Parent->dominates(NewScope)))
Parent->closeInsnRange(NewScope);
}
void setAbstractScope() { AbstractScope = true; }
bool isAbstractScope() const { return AbstractScope; }
Devang Patel
committed
// Depth First Search support to walk and mainpluate DbgScope hierarchy.
unsigned getDFSOut() const { return DFSOut; }
void setDFSOut(unsigned O) { DFSOut = O; }
unsigned getDFSIn() const { return DFSIn; }
void setDFSIn(unsigned I) { DFSIn = I; }
bool dominates(const DbgScope *S) {
Devang Patel
committed
return true;
if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut())
return true;
return false;
}
/// addScope - Add a scope to the scope.
void addScope(DbgScope *S) { Scopes.push_back(S); }
/// addVariable - Add a variable to the scope.
void addVariable(DbgVariable *V) { Variables.push_back(V); }
#ifndef NDEBUG
void dump() const;
#endif
};
Devang Patel
committed
} // end llvm namespace
#ifndef NDEBUG
void DbgScope::dump() const {
err.indent(IndentLevel);
N->dump();
if (AbstractScope)
err << "Abstract Scope\n";
IndentLevel += 2;
if (!Scopes.empty())
err << "Children ...\n";
for (unsigned i = 0, e = Scopes.size(); i != e; ++i)
if (Scopes[i] != this)
Scopes[i]->dump();
IndentLevel -= 2;
}
#endif
DbgScope::~DbgScope() {
for (unsigned j = 0, M = Variables.size(); j < M; ++j)
delete Variables[j];
}
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
: Asm(A), MMI(Asm->MMI), FirstCU(0),
AbbreviationsSet(InitAbbreviationsSetSize),
CurrentFnDbgScope(0), 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;
}
/// createSubprogramDIE - Create new DIE using SP.
DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) {
CompileUnit *SPCU = getCompileUnit(SP);
DIE *SPDie = SPCU->getDIE(SP);
if (SPDie)
return SPDie;
SPDie = new DIE(dwarf::DW_TAG_subprogram);
Devang Patel
committed
// DW_TAG_inlined_subroutine may refer to this DIE.
SPCU->insertDIE(SP, SPDie);
// Add to context owner.
SPCU->addToContextOwner(SPDie, SP.getContext());
// Add function template parameters.
SPCU->addTemplateParams(*SPDie, SP.getTemplateParams());
StringRef LinkageName = SP.getLinkageName();
if (!LinkageName.empty())
SPCU->addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string,
getRealLinkageName(LinkageName));
Devang Patel
committed
// If this DIE is going to refer declaration info using AT_specification
// then there is no need to add other attributes.
if (SP.getFunctionDeclaration().isSubprogram())
return SPDie;
// Constructors and operators for anonymous aggregates do not have names.
Devang Patel
committed
if (!SP.getName().empty())
Devang Patel
committed
SPCU->addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string,
SP.getName());
Devang Patel
committed
SPCU->addSourceLine(SPDie, SP);
Devang Patel
committed
if (SP.isPrototyped())
Devang Patel
committed
SPCU->addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1);
Devang Patel
committed
// Add Return Type.
DICompositeType SPTy = SP.getType();
DIArray Args = SPTy.getTypeArray();
unsigned SPTag = SPTy.getTag();
Devang Patel
committed
if (Args.getNumElements() == 0 || SPTag != dwarf::DW_TAG_subroutine_type)
Devang Patel
committed
SPCU->addType(SPDie, SPTy);
else
Devang Patel
committed
SPCU->addType(SPDie, DIType(Args.getElement(0)));
Devang Patel
committed
unsigned VK = SP.getVirtuality();
if (VK) {
Devang Patel
committed
SPCU->addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK);
DIEBlock *Block = SPCU->getDIEBlock();
SPCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
SPCU->addUInt(Block, 0, dwarf::DW_FORM_udata, SP.getVirtualIndex());
SPCU->addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block);
ContainingTypeMap.insert(std::make_pair(SPDie,
SP.getContainingType()));
Devang Patel
committed
}
Devang Patel
committed
SPCU->addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
// Add arguments. Do not add arguments for subprogram definition. They will
// be handled while processing variables.
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)));
Devang Patel
committed
SPCU->addType(Arg, ATy);
if (ATy.isArtificial())
Devang Patel
committed
SPCU->addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1);
SPDie->addChild(Arg);
}
}
if (SP.isArtificial())
Devang Patel
committed
SPCU->addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1);
if (!SP.isLocalToUnit())
Devang Patel
committed
SPCU->addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
if (SP.isOptimized())
Devang Patel
committed
SPCU->addUInt(SPDie, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1);
Jim Grosbach
committed
if (unsigned isa = Asm->getISAEncoding()) {
Devang Patel
committed
SPCU->addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa);
Jim Grosbach
committed
}
return SPDie;
}
DbgScope *DwarfDebug::getOrCreateAbstractScope(const MDNode *N) {
assert(N && "Invalid Scope encoding!");
DbgScope *AScope = AbstractScopes.lookup(N);
if (AScope)
return AScope;
DbgScope *Parent = NULL;
DIDescriptor Scope(N);
if (Scope.isLexicalBlock()) {
DILexicalBlock DB(N);
DIDescriptor ParentDesc = DB.getContext();
Parent = getOrCreateAbstractScope(ParentDesc);
}
AScope = new DbgScope(Parent, DIDescriptor(N), NULL);
if (Parent)
Parent->addScope(AScope);
AScope->setAbstractScope();
AbstractScopes[N] = AScope;
if (DIDescriptor(N).isSubprogram())
AbstractScopesList.push_back(AScope);
return AScope;
}
Devang Patel
committed
Devang Patel
committed
/// isSubprogramContext - Return true if Context is either a subprogram
/// or another context nested inside a subprogram.
static bool isSubprogramContext(const MDNode *Context) {
Devang Patel
committed
if (!Context)
return false;
DIDescriptor D(Context);
if (D.isSubprogram())
return true;
if (D.isType())
return isSubprogramContext(DIType(Context).getContext());
Devang Patel
committed
return false;
}
/// 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.
DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) {
CompileUnit *SPCU = getCompileUnit(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
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
createSubprogramDIE(SPDecl));
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.
DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) {
Devang Patel
committed
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
if (Scope->isAbstractScope())
return ScopeDIE;
Devang Patel
committed
const SmallVector<DbgRange, 4> &Ranges = Scope->getRanges();
if (Ranges.empty())
return 0;
Devang Patel
committed
CompileUnit *TheCU = getCompileUnit(Scope->getScopeNode());
Devang Patel
committed
SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin();
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());
Devang Patel
committed
for (SmallVector<DbgRange, 4>::const_iterator RI = Ranges.begin(),
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.
DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
Devang Patel
committed
const SmallVector<DbgRange, 4> &Ranges = Scope->getRanges();
assert (Ranges.empty() == false
Devang Patel
committed
&& "DbgScope does not have instruction markers!");
// FIXME : .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.
SmallVector<DbgRange, 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) {
Devang Patel
committed
assert (0 && "Unexpected Start and End labels for a inlined scope!");
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
DISubprogram InlinedSP = getDISubprogram(DS);
CompileUnit *TheCU = getCompileUnit(InlinedSP);
DIE *OriginDIE = TheCU->getDIE(InlinedSP);
if (!OriginDIE) {
DEBUG(dbgs() << "Unable to find original DIE for inlined subprogram.");
return NULL;
}
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
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);
InlinedSubprogramDIEs.insert(OriginDIE);
// Track the start label for this inlined function.
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;
}
/// isUnsignedDIType - Return true if type encoding is unsigned.
static bool isUnsignedDIType(DIType Ty) {
DIDerivedType DTy(Ty);
if (DTy.Verify())
return isUnsignedDIType(DTy.getTypeDerivedFrom());
DIBasicType BTy(Ty);
if (BTy.Verify()) {
unsigned Encoding = BTy.getEncoding();
if (Encoding == dwarf::DW_ATE_unsigned ||
Encoding == dwarf::DW_ATE_unsigned_char)
return true;
}
return false;
}
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) {
StringRef Name = DV->getName();
// Translate tag to proper Dwarf tag. The result variable is dropped for
// now.
unsigned Tag;
switch (DV->getTag()) {
case dwarf::DW_TAG_return_variable:
return NULL;
case dwarf::DW_TAG_arg_variable:
Tag = dwarf::DW_TAG_formal_parameter;
break;
case dwarf::DW_TAG_auto_variable: // fall thru
default:
Tag = dwarf::DW_TAG_variable;
break;
}
// Define variable debug information entry.
DIE *VariableDie = new DIE(Tag);
CompileUnit *VariableCU = getCompileUnit(DV->getVariable());
DenseMap<const DbgVariable *, const DbgVariable *>::iterator
V2AVI = VarToAbstractVarMap.find(DV);
if (V2AVI != VarToAbstractVarMap.end())
AbsDIE = V2AVI->second->getDIE();
if (AbsDIE)
VariableCU->addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin,
Devang Patel
committed
dwarf::DW_FORM_ref4, AbsDIE);
VariableCU->addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string,
Name);
VariableCU->addSourceLine(VariableDie, DV->getVariable());
VariableCU->addType(VariableDie, DV->getType());
if (Tag == dwarf::DW_TAG_formal_parameter && DV->getType().isArtificial())
VariableCU->addUInt(VariableDie, dwarf::DW_AT_artificial,
dwarf::DW_FORM_flag, 1);
else if (DIVariable(DV->getVariable()).isArtificial())
VariableCU->addUInt(VariableDie, dwarf::DW_AT_artificial,
dwarf::DW_FORM_flag, 1);
if (Scope->isAbstractScope()) {
DV->setDIE(VariableDie);
return VariableDie;
}
unsigned Offset = DV->getDotDebugLocOffset();
if (Offset != ~0U) {
VariableCU->addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4,
Asm->GetTempSymbol("debug_loc", Offset));
DV->setDIE(VariableDie);
UseDotDebugLocEntry.insert(VariableDie);
return VariableDie;
}
// Check if variable is described by a DBG_VALUE instruction.
DenseMap<const DbgVariable *, const MachineInstr *>::iterator DVI =
DbgVariableToDbgInstMap.find(DV);
if (DVI != DbgVariableToDbgInstMap.end()) {
const MachineInstr *DVInsn = DVI->second;
bool updated = false;
// FIXME : Handle getNumOperands != 3
if (DVInsn->getNumOperands() == 3) {
if (DVInsn->getOperand(0).isReg()) {
const MachineOperand RegOp = DVInsn->getOperand(0);
const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
if (DVInsn->getOperand(1).isImm() &&
TRI->getFrameRegister(*Asm->MF) == RegOp.getReg()) {
unsigned FrameReg = 0;
const TargetFrameLowering *TFI = Asm->TM.getFrameLowering();
int Offset =
TFI->getFrameIndexReference(*Asm->MF,
DVInsn->getOperand(1).getImm(),
FrameReg);
MachineLocation Location(FrameReg, Offset);
VariableCU->addVariableAddress(DV, VariableDie, Location);
} else if (RegOp.getReg())
VariableCU->addVariableAddress(DV, VariableDie,
MachineLocation(RegOp.getReg()));
updated = true;
else if (DVInsn->getOperand(0).isImm())
updated =
VariableCU->addConstantValue(VariableDie, DVInsn->getOperand(0),
DV->getType());
else if (DVInsn->getOperand(0).isFPImm())
updated =
VariableCU->addConstantFPValue(VariableDie, DVInsn->getOperand(0));
else if (DVInsn->getOperand(0).isCImm())
updated =
VariableCU->addConstantValue(VariableDie,
DVInsn->getOperand(0).getCImm(),
isUnsignedDIType(DV->getType()));
VariableCU->addVariableAddress(DV, VariableDie,
Asm->getDebugValueLocation(DVInsn));
updated = true;
Devang Patel
committed
}
if (!updated) {
// If variableDie is not updated then DBG_VALUE instruction does not
// have valid variable info.
delete VariableDie;
return NULL;
}
DV->setDIE(VariableDie);
return VariableDie;
// .. else use frame index, if available.
int FI = 0;
if (findVariableFrameIndex(DV, &FI)) {
unsigned FrameReg = 0;
const TargetFrameLowering *TFI = Asm->TM.getFrameLowering();
int Offset =
TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
MachineLocation Location(FrameReg, Offset);
VariableCU->addVariableAddress(DV, VariableDie, Location);
}
DV->setDIE(VariableDie);
return VariableDie;
}
/// constructScopeDIE - Construct a DIE for this scope.
DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) {
if (!Scope || !Scope->getScopeNode())
return NULL;
Devang Patel
committed
SmallVector <DIE *, 8> Children;
Devang Patel
committed
// Collect arguments for current function.
if (Scope == CurrentFnDbgScope)
for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
if (DbgVariable *ArgDV = CurrentFnArguments[i])
if (DIE *Arg = constructVariableDIE(ArgDV, Scope))
Children.push_back(Arg);
Devang Patel
committed
// Collect lexical scope childrens first.
const SmallVector<DbgVariable *, 8> &Variables = Scope->getDbgVariables();
for (unsigned i = 0, N = Variables.size(); i < N; ++i)
if (DIE *Variable = constructVariableDIE(Variables[i], Scope))
Children.push_back(Variable);
const SmallVector<DbgScope *, 4> &Scopes = Scope->getScopes();
for (unsigned j = 0, M = Scopes.size(); j < M; ++j)
if (DIE *Nested = constructScopeDIE(Scopes[j]))
Children.push_back(Nested);
DIScope DS(Scope->getScopeNode());
DIE *ScopeDIE = NULL;
if (Scope->getInlinedAt())
ScopeDIE = constructInlinedScopeDIE(Scope);
else if (DS.isSubprogram()) {
ProcessedSPNodes.insert(DS);
if (Scope->isAbstractScope()) {
ScopeDIE = getCompileUnit(DS)->getDIE(DS);
// Note down abstract DIE.
if (ScopeDIE)
AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
}
ScopeDIE = updateSubprogramScopeDIE(DS);
Devang Patel
committed
else {
// There is no need to emit empty lexical block DIE.
if (Children.empty())
return NULL;
ScopeDIE = constructLexicalScopeDIE(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
getCompileUnit(DS)->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());
// MCStream expects full path name as filename.
if (!DirName.empty() && !sys::path::is_absolute(FileName)) {
SmallString<128> FullPathName = DirName;
sys::path::append(FullPathName, FileName);
Devang Patel
committed
// Here FullPathName will be copied into StringMap by GetOrCreateSourceID.
return GetOrCreateSourceID(StringRef(FullPathName), StringRef());
}
Devang Patel
committed
Rafael Espindola
committed
StringMapEntry<unsigned> &Entry = SourceIdMap.GetOrCreateValue(FileName);
if (Entry.getValue())
return Entry.getValue();
Rafael Espindola
committed
unsigned SrcId = SourceIdMap.size();
Entry.setValue(SrcId);
Rafael Espindola
committed
// Print out a .file directive to specify files for .loc directives.
Devang Patel
committed
Asm->OutStreamer.EmitDwarfFileDirective(SrcId, Entry.getKey());
/// constructCompileUnit - Create new CompileUnit for the given
/// metadata node with tag DW_TAG_compile_unit.
void 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())
Devang Patel
committed
NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags);
unsigned RVer = DIUnit.getRunTimeVersion();
if (RVer)
Devang Patel
committed
NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
dwarf::DW_FORM_data1, RVer);
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
if (!FirstCU)
FirstCU = NewCU;
CUMap.insert(std::make_pair(N, NewCU));
}
/// getCompielUnit - Get CompileUnit DIE.
CompileUnit *DwarfDebug::getCompileUnit(const MDNode *N) const {
assert (N && "Invalid DwarfDebug::getCompileUnit argument!");
DIDescriptor D(N);
const MDNode *CUNode = NULL;
if (D.isCompileUnit())
CUNode = N;
else if (D.isSubprogram())
CUNode = DISubprogram(N).getCompileUnit();
else if (D.isType())
CUNode = DIType(N).getCompileUnit();
else if (D.isGlobalVariable())
CUNode = DIGlobalVariable(N).getCompileUnit();
else if (D.isVariable())
CUNode = DIVariable(N).getCompileUnit();
else if (D.isNameSpace())
CUNode = DINameSpace(N).getCompileUnit();
else if (D.isFile())
CUNode = DIFile(N).getCompileUnit();
else
return FirstCU;
DenseMap<const MDNode *, CompileUnit *>::const_iterator I
= CUMap.find(CUNode);
if (I == CUMap.end())
return FirstCU;
return I->second;
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
// Return const exprssion if value is a GEP to access merged global
// constant. e.g.
// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0)
static const ConstantExpr *getMergedGlobalExpr(const Value *V) {
const ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(V);
if (!CE || CE->getNumOperands() != 3 ||
CE->getOpcode() != Instruction::GetElementPtr)
return NULL;
// First operand points to a global value.
if (!isa<GlobalValue>(CE->getOperand(0)))
return NULL;
// Second operand is zero.
const ConstantInt *CI =
dyn_cast_or_null<ConstantInt>(CE->getOperand(1));
if (!CI || !CI->isZero())
return NULL;
// Third operand is offset.
if (!isa<ConstantInt>(CE->getOperand(2)))
return NULL;
return CE;
}
/// constructGlobalVariableDIE - Construct global variable DIE.
void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) {
DIGlobalVariable GV(N);
// If debug information is malformed then ignore it.
if (GV.Verify() == false)
// Check for pre-existence.
CompileUnit *TheCU = getCompileUnit(N);
if (TheCU->getDIE(GV))
DIType GTy = GV.getType();
DIE *VariableDIE = new DIE(GV.getTag());
bool isGlobalVariable = GV.getGlobal() != NULL;
Devang Patel
committed
TheCU->addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string,
GV.getDisplayName());
StringRef LinkageName = GV.getLinkageName();
if (!LinkageName.empty() && isGlobalVariable)
Devang Patel
committed
TheCU->addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name,
dwarf::DW_FORM_string,
getRealLinkageName(LinkageName));
Devang Patel
committed
TheCU->addType(VariableDIE, GTy);
Devang Patel
committed
// Add scoping info.
if (!GV.isLocalToUnit()) {
Devang Patel
committed
TheCU->addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
// Expose as global.
TheCU->addGlobal(GV.getName(), VariableDIE);
}
// Add line number info.
Devang Patel
committed
TheCU->addSourceLine(VariableDIE, GV);
TheCU->insertDIE(N, VariableDIE);