summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp153
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.h24
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp1020
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h122
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.cpp89
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.h12
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfPrinter.h2
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfWriter.cpp35
8 files changed, 725 insertions, 732 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index bb6bd95..08e0eae 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -18,6 +18,7 @@
#include "llvm/Module.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
@@ -35,6 +36,7 @@
#include "llvm/Support/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
@@ -512,7 +514,7 @@ void AsmPrinter::EmitXXStructorList(Constant *List) {
//===----------------------------------------------------------------------===//
/// LEB 128 number encoding.
-/// PrintULEB128 - Print a series of hexidecimal values (separated by commas)
+/// PrintULEB128 - Print a series of hexadecimal values (separated by commas)
/// representing an unsigned leb128 value.
void AsmPrinter::PrintULEB128(unsigned Value) const {
char Buffer[20];
@@ -525,7 +527,7 @@ void AsmPrinter::PrintULEB128(unsigned Value) const {
} while (Value);
}
-/// PrintSLEB128 - Print a series of hexidecimal values (separated by commas)
+/// PrintSLEB128 - Print a series of hexadecimal values (separated by commas)
/// representing a signed leb128 value.
void AsmPrinter::PrintSLEB128(int Value) const {
int Sign = Value >> (8 * sizeof(Value) - 1);
@@ -546,7 +548,7 @@ void AsmPrinter::PrintSLEB128(int Value) const {
// Emission and print routines
//
-/// PrintHex - Print a value as a hexidecimal value.
+/// PrintHex - Print a value as a hexadecimal value.
///
void AsmPrinter::PrintHex(int Value) const {
char Buffer[20];
@@ -727,7 +729,7 @@ static void printStringChar(formatted_raw_ostream &O, unsigned char C) {
/// Special characters are emitted properly.
/// \literal (Eg. '\t') \endliteral
void AsmPrinter::EmitString(const std::string &String) const {
- EmitString(String.c_str(), String.size());
+ EmitString(String.data(), String.size());
}
void AsmPrinter::EmitString(const char *String, unsigned Size) const {
@@ -1357,32 +1359,31 @@ void AsmPrinter::PrintSpecial(const MachineInstr *MI, const char *Code) const {
/// instruction's DebugLoc.
void AsmPrinter::processDebugLoc(const MachineInstr *MI,
bool BeforePrintingInsn) {
- if (!MAI || !DW)
+ if (!MAI || !DW || !MAI->doesSupportDebugInformation()
+ || !DW->ShouldEmitDwarfDebug())
return;
DebugLoc DL = MI->getDebugLoc();
- if (MAI->doesSupportDebugInformation() && DW->ShouldEmitDwarfDebug()) {
- if (!DL.isUnknown()) {
- DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
- if (BeforePrintingInsn) {
- if (CurDLT.Scope != 0 && PrevDLT != CurDLT) {
- unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
- CurDLT.Scope);
- printLabel(L);
- O << '\n';
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
- DW->SetDbgScopeBeginLabels(MI, L);
-#endif
- } else {
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
- DW->SetDbgScopeEndLabels(MI, 0);
-#endif
- }
- }
+ if (DL.isUnknown())
+ return;
+ DebugLocTuple CurDLT = MF->getDebugLocTuple(DL);
+ if (CurDLT.Scope == 0)
+ return;
+
+ if (BeforePrintingInsn) {
+ if (CurDLT != PrevDLT) {
+ unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
+ CurDLT.Scope);
+ printLabel(L);
+ DW->BeginScope(MI, L);
PrevDLT = CurDLT;
}
+ } else {
+ // After printing instruction
+ DW->EndScope(MI);
}
}
+
/// printInlineAsm - This method formats and prints the specified machine
/// instruction that is an inline asm.
void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
@@ -1399,6 +1400,8 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
// Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
+ O << '\t';
+
// If this asmstr is empty, just print the #APP/#NOAPP markers.
// These are useful to see where empty asm's wound up.
if (AsmStr[0] == 0) {
@@ -1636,13 +1639,17 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F,
assert(BB->hasName() &&
"Address of anonymous basic block not supported yet!");
- // FIXME: This isn't guaranteed to produce a unique name even if the
- // block and function have a name.
- std::string Mangled =
- Mang->getMangledName(F, Mang->makeNameProper(BB->getName()).c_str(),
- /*ForcePrivate=*/true);
+ // This code must use the function name itself, and not the function number,
+ // since it must be possible to generate the label name from within other
+ // functions.
+ std::string FuncName = Mang->getMangledName(F);
+
+ SmallString<60> Name;
+ raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BA"
+ << FuncName.size() << '_' << FuncName << '_'
+ << Mang->makeNameProper(BB->getName());
- return OutContext.GetOrCreateSymbol(StringRef(Mangled));
+ return OutContext.GetOrCreateSymbol(Name.str());
}
MCSymbol *AsmPrinter::GetMBBSymbol(unsigned MBBID) const {
@@ -1817,21 +1824,80 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) {
/// EmitComments - Pretty-print comments for instructions
void AsmPrinter::EmitComments(const MachineInstr &MI) const {
- assert(VerboseAsm && !MI.getDebugLoc().isUnknown());
-
- DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
+ if (!VerboseAsm)
+ return;
- // Print source line info.
- O.PadToColumn(MAI->getCommentColumn());
- O << MAI->getCommentString() << " SrcLine ";
- if (DLT.Scope) {
- DICompileUnit CU(DLT.Scope);
- if (!CU.isNull())
- O << CU.getFilename() << " ";
+ bool Newline = false;
+
+ if (!MI.getDebugLoc().isUnknown()) {
+ DebugLocTuple DLT = MF->getDebugLocTuple(MI.getDebugLoc());
+
+ // Print source line info.
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << " SrcLine ";
+ if (DLT.Scope) {
+ DICompileUnit CU(DLT.Scope);
+ if (!CU.isNull())
+ O << CU.getFilename() << " ";
+ }
+ O << DLT.Line;
+ if (DLT.Col != 0)
+ O << ":" << DLT.Col;
+ Newline = true;
+ }
+
+ // Check for spills and reloads
+ int FI;
+
+ const MachineFrameInfo *FrameInfo =
+ MI.getParent()->getParent()->getFrameInfo();
+
+ // We assume a single instruction only has a spill or reload, not
+ // both.
+ if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI)) {
+ if (Newline) O << '\n';
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << " Reload";
+ Newline = true;
+ }
+ }
+ else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI)) {
+ if (Newline) O << '\n';
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << " Folded Reload";
+ Newline = true;
+ }
+ }
+ else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI)) {
+ if (Newline) O << '\n';
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << " Spill";
+ Newline = true;
+ }
+ }
+ else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI)) {
+ if (Newline) O << '\n';
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << " Folded Spill";
+ Newline = true;
+ }
+ }
+
+ // Check for spill-induced copies
+ unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
+ if (TM.getInstrInfo()->isMoveInstr(MI, SrcReg, DstReg,
+ SrcSubIdx, DstSubIdx)) {
+ if (MI.getAsmPrinterFlag(ReloadReuse)) {
+ if (Newline) O << '\n';
+ O.PadToColumn(MAI->getCommentColumn());
+ O << MAI->getCommentString() << " Reload Reuse";
+ Newline = true;
+ }
}
- O << DLT.Line;
- if (DLT.Col != 0)
- O << ":" << DLT.Col;
}
/// PrintChildLoopComment - Print comments about child loops within
@@ -1862,8 +1928,7 @@ static void PrintChildLoopComment(formatted_raw_ostream &O,
}
/// EmitComments - Pretty-print comments for basic blocks
-void AsmPrinter::EmitComments(const MachineBasicBlock &MBB) const
-{
+void AsmPrinter::EmitComments(const MachineBasicBlock &MBB) const {
if (VerboseAsm) {
// Add loop depth information
const MachineLoop *loop = LI->getLoopFor(&MBB);
diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h
index 62b51ec..3e50a15 100644
--- a/lib/CodeGen/AsmPrinter/DIE.h
+++ b/lib/CodeGen/AsmPrinter/DIE.h
@@ -29,7 +29,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a
/// Dwarf abbreviation.
- class VISIBILITY_HIDDEN DIEAbbrevData {
+ class DIEAbbrevData {
/// Attribute - Dwarf attribute code.
///
unsigned Attribute;
@@ -52,7 +52,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug
/// information object.
- class VISIBILITY_HIDDEN DIEAbbrev : public FoldingSetNode {
+ class DIEAbbrev : public FoldingSetNode {
/// Tag - Dwarf tag code.
///
unsigned Tag;
@@ -113,7 +113,7 @@ namespace llvm {
class CompileUnit;
class DIEValue;
- class VISIBILITY_HIDDEN DIE : public FoldingSetNode {
+ class DIE : public FoldingSetNode {
protected:
/// Abbrev - Buffer for constructing abbreviation.
///
@@ -202,7 +202,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIEValue - A debug information entry value.
///
- class VISIBILITY_HIDDEN DIEValue : public FoldingSetNode {
+ class DIEValue : public FoldingSetNode {
public:
enum {
isInteger,
@@ -249,7 +249,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIEInteger - An integer value DIE.
///
- class VISIBILITY_HIDDEN DIEInteger : public DIEValue {
+ class DIEInteger : public DIEValue {
uint64_t Integer;
public:
explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
@@ -294,7 +294,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIEString - A string value DIE.
///
- class VISIBILITY_HIDDEN DIEString : public DIEValue {
+ class DIEString : public DIEValue {
const std::string Str;
public:
explicit DIEString(const std::string &S) : DIEValue(isString), Str(S) {}
@@ -326,7 +326,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIEDwarfLabel - A Dwarf internal label expression DIE.
//
- class VISIBILITY_HIDDEN DIEDwarfLabel : public DIEValue {
+ class DIEDwarfLabel : public DIEValue {
const DWLabel Label;
public:
explicit DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
@@ -356,7 +356,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIEObjectLabel - A label to an object in code or data.
//
- class VISIBILITY_HIDDEN DIEObjectLabel : public DIEValue {
+ class DIEObjectLabel : public DIEValue {
const std::string Label;
public:
explicit DIEObjectLabel(const std::string &L)
@@ -389,7 +389,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIESectionOffset - A section offset DIE.
///
- class VISIBILITY_HIDDEN DIESectionOffset : public DIEValue {
+ class DIESectionOffset : public DIEValue {
const DWLabel Label;
const DWLabel Section;
bool IsEH : 1;
@@ -428,7 +428,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIEDelta - A simple label difference DIE.
///
- class VISIBILITY_HIDDEN DIEDelta : public DIEValue {
+ class DIEDelta : public DIEValue {
const DWLabel LabelHi;
const DWLabel LabelLo;
public:
@@ -462,7 +462,7 @@ namespace llvm {
/// DIEntry - A pointer to another debug information entry. An instance of
/// this class can also be used as a proxy for a debug information entry not
/// yet defined (ie. types.)
- class VISIBILITY_HIDDEN DIEEntry : public DIEValue {
+ class DIEEntry : public DIEValue {
DIE *Entry;
public:
explicit DIEEntry(DIE *E) : DIEValue(isEntry), Entry(E) {}
@@ -497,7 +497,7 @@ namespace llvm {
//===--------------------------------------------------------------------===//
/// DIEBlock - A block of values. Primarily used for location expressions.
//
- class VISIBILITY_HIDDEN DIEBlock : public DIEValue, public DIE {
+ class DIEBlock : public DIEValue, public DIE {
unsigned Size; // Size in bytes excluding size header.
public:
DIEBlock()
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 1372fc2..c62c435 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -48,7 +48,7 @@ namespace llvm {
//===----------------------------------------------------------------------===//
/// CompileUnit - This dwarf writer support class manages information associate
/// with a source file.
-class VISIBILITY_HIDDEN CompileUnit {
+class CompileUnit {
/// ID - File identifier for source.
///
unsigned ID;
@@ -127,61 +127,66 @@ public:
class DbgVariable {
DIVariable Var; // Variable Descriptor.
unsigned FrameIndex; // Variable frame index.
- bool InlinedFnVar; // Variable for an inlined function.
+ DbgVariable *AbstractVar; // Abstract variable for this variable.
+ DIE *TheDIE;
public:
- DbgVariable(DIVariable V, unsigned I, bool IFV)
- : Var(V), FrameIndex(I), InlinedFnVar(IFV) {}
+ DbgVariable(DIVariable V, unsigned I)
+ : Var(V), FrameIndex(I), AbstractVar(0), TheDIE(0) {}
// Accessors.
- DIVariable getVariable() const { return Var; }
- unsigned getFrameIndex() const { return FrameIndex; }
- bool isInlinedFnVar() const { return InlinedFnVar; }
+ DIVariable getVariable() const { return Var; }
+ unsigned getFrameIndex() const { return FrameIndex; }
+ void setAbstractVariable(DbgVariable *V) { AbstractVar = V; }
+ DbgVariable *getAbstractVariable() const { return AbstractVar; }
+ void setDIE(DIE *D) { TheDIE = D; }
+ DIE *getDIE() const { return TheDIE; }
};
//===----------------------------------------------------------------------===//
/// DbgScope - This class is used to track scope information.
///
-class DbgConcreteScope;
class DbgScope {
DbgScope *Parent; // Parent to this scope.
- DIDescriptor Desc; // Debug info descriptor for scope.
- // FIXME use WeakVH for Desc.
- WeakVH InlinedAt; // If this scope represents inlined
- // function body then this is the location
- // where this body is inlined.
+ DIDescriptor Desc; // Debug info descriptor for scope.
+ WeakVH InlinedAtLocation; // Location at which scope is inlined.
+ bool AbstractScope; // Abstract Scope
unsigned StartLabelID; // Label ID of the beginning of scope.
unsigned EndLabelID; // Label ID of the end of scope.
const MachineInstr *LastInsn; // Last instruction of this scope.
const MachineInstr *FirstInsn; // First instruction of this scope.
SmallVector<DbgScope *, 4> Scopes; // Scopes defined in scope.
SmallVector<DbgVariable *, 8> Variables;// Variables declared in scope.
- SmallVector<DbgConcreteScope *, 8> ConcreteInsts;// Concrete insts of funcs.
// Private state for dump()
mutable unsigned IndentLevel;
public:
DbgScope(DbgScope *P, DIDescriptor D, MDNode *I = 0)
- : Parent(P), Desc(D), InlinedAt(I), StartLabelID(0), EndLabelID(0),
+ : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false),
+ StartLabelID(0), EndLabelID(0),
LastInsn(0), FirstInsn(0), IndentLevel(0) {}
virtual ~DbgScope();
// Accessors.
DbgScope *getParent() const { return Parent; }
+ void setParent(DbgScope *P) { Parent = P; }
DIDescriptor getDesc() const { return Desc; }
- MDNode *getInlinedAt() const {
- return dyn_cast_or_null<MDNode>(InlinedAt);
+ MDNode *getInlinedAt() const {
+ return dyn_cast_or_null<MDNode>(InlinedAtLocation);
}
+ MDNode *getScopeNode() const { return Desc.getNode(); }
unsigned getStartLabelID() const { return StartLabelID; }
unsigned getEndLabelID() const { return EndLabelID; }
SmallVector<DbgScope *, 4> &getScopes() { return Scopes; }
SmallVector<DbgVariable *, 8> &getVariables() { return Variables; }
- SmallVector<DbgConcreteScope*,8> &getConcreteInsts() { return ConcreteInsts; }
void setStartLabelID(unsigned S) { StartLabelID = S; }
void setEndLabelID(unsigned E) { EndLabelID = E; }
void setLastInsn(const MachineInstr *MI) { LastInsn = MI; }
const MachineInstr *getLastInsn() { return LastInsn; }
void setFirstInsn(const MachineInstr *MI) { FirstInsn = MI; }
+ void setAbstractScope() { AbstractScope = true; }
+ bool isAbstractScope() const { return AbstractScope; }
const MachineInstr *getFirstInsn() { return FirstInsn; }
+
/// AddScope - Add a scope to the scope.
///
void AddScope(DbgScope *S) { Scopes.push_back(S); }
@@ -190,10 +195,6 @@ public:
///
void AddVariable(DbgVariable *V) { Variables.push_back(V); }
- /// AddConcreteInst - Add a concrete instance to the scope.
- ///
- void AddConcreteInst(DbgConcreteScope *C) { ConcreteInsts.push_back(C); }
-
void FixInstructionMarkers() {
assert (getFirstInsn() && "First instruction is missing!");
if (getLastInsn())
@@ -218,11 +219,15 @@ public:
void DbgScope::dump() const {
raw_ostream &err = errs();
err.indent(IndentLevel);
- Desc.dump();
+ MDNode *N = Desc.getNode();
+ N->dump();
err << " [" << StartLabelID << ", " << EndLabelID << "]\n";
+ 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();
@@ -235,7 +240,7 @@ void DbgScope::dump() const {
/// DbgConcreteScope - This class is used to track a scope that holds concrete
/// instance information.
///
-class VISIBILITY_HIDDEN DbgConcreteScope : public DbgScope {
+class DbgConcreteScope : public DbgScope {
CompileUnit *Unit;
DIE *Die; // Debug info for this concrete scope.
public:
@@ -251,8 +256,6 @@ DbgScope::~DbgScope() {
delete Scopes[i];
for (unsigned j = 0, M = Variables.size(); j < M; ++j)
delete Variables[j];
- for (unsigned k = 0, O = ConcreteInsts.size(); k < O; ++k)
- delete ConcreteInsts[k];
}
} // end llvm namespace
@@ -262,7 +265,7 @@ DwarfDebug::DwarfDebug(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T)
AbbreviationsSet(InitAbbreviationsSetSize), Abbreviations(),
ValuesSet(InitValuesSetSize), Values(), StringPool(),
SectionSourceLines(), didInitial(false), shouldEmit(false),
- FunctionDbgScope(0), DebugTimer(0) {
+ CurrentFnDbgScope(0), DebugTimer(0) {
if (TimePassesIsEnabled)
DebugTimer = new Timer("Dwarf Debug Writer",
getDwarfTimerGroup());
@@ -271,11 +274,6 @@ DwarfDebug::~DwarfDebug() {
for (unsigned j = 0, M = Values.size(); j < M; ++j)
delete Values[j];
- for (DenseMap<const MDNode *, DbgScope *>::iterator
- I = AbstractInstanceRootMap.begin(),
- E = AbstractInstanceRootMap.end(); I != E;++I)
- delete I->second;
-
delete DebugTimer;
}
@@ -1097,6 +1095,10 @@ DIE *DwarfDebug::ConstructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) {
/// CreateGlobalVariableDIE - Create new DIE using GV.
DIE *DwarfDebug::CreateGlobalVariableDIE(CompileUnit *DW_Unit,
const DIGlobalVariable &GV) {
+ // If the global variable was optmized out then no need to create debug info entry.
+ if (!GV.getGlobal()) return NULL;
+ if (!GV.getDisplayName()) return NULL;
+
DIE *GVDie = new DIE(dwarf::DW_TAG_variable);
AddString(GVDie, dwarf::DW_AT_name, dwarf::DW_FORM_string,
GV.getDisplayName());
@@ -1233,9 +1235,6 @@ DIE *DwarfDebug::CreateSubprogramDIE(CompileUnit *DW_Unit,
}
}
- if (!SP.isLocalToUnit() && !IsInlined)
- AddUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
-
// DW_TAG_inlined_subroutine may refer to this DIE.
DIE *&Slot = DW_Unit->getDieMapSlotFor(SP.getNode());
Slot = SPDie;
@@ -1283,263 +1282,341 @@ DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) {
AddSourceLine(VariableDie, &VD);
// Add variable type.
- // FIXME: isBlockByrefVariable should be reformulated in terms of complex addresses instead.
+ // FIXME: isBlockByrefVariable should be reformulated in terms of complex
+ // addresses instead.
if (VD.isBlockByrefVariable())
AddType(Unit, VariableDie, GetBlockByrefType(VD.getType(), Name));
else
AddType(Unit, VariableDie, VD.getType());
// Add variable address.
- if (!DV->isInlinedFnVar()) {
- // Variables for abstract instances of inlined functions don't get a
- // location.
- MachineLocation Location;
- Location.set(RI->getFrameRegister(*MF),
- RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
-
-
- if (VD.hasComplexAddress())
- AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
- else if (VD.isBlockByrefVariable())
- AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
- else
- AddAddress(VariableDie, dwarf::DW_AT_location, Location);
- }
+ // Variables for abstract instances of inlined functions don't get a
+ // location.
+ MachineLocation Location;
+ Location.set(RI->getFrameRegister(*MF),
+ RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
+
+
+ if (VD.hasComplexAddress())
+ AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
+ else if (VD.isBlockByrefVariable())
+ AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
+ else
+ AddAddress(VariableDie, dwarf::DW_AT_location, Location);
return VariableDie;
}
-/// getOrCreateScope - Returns the scope associated with the given descriptor.
-///
-DbgScope *DwarfDebug::getDbgScope(MDNode *N, const MachineInstr *MI,
- MDNode *InlinedAt) {
- ValueMap<MDNode *, DbgScope *>::iterator VI = DbgScopeMap.find(N);
- if (VI != DbgScopeMap.end())
- return VI->second;
+/// getUpdatedDbgScope - Find or create DbgScope assicated with the instruction.
+/// Initialize scope and update scope hierarchy.
+DbgScope *DwarfDebug::getUpdatedDbgScope(MDNode *N, const MachineInstr *MI,
+ MDNode *InlinedAt) {
+ assert (N && "Invalid Scope encoding!");
+ assert (MI && "Missing machine instruction!");
+ bool GetConcreteScope = (MI && InlinedAt);
- DbgScope *Parent = NULL;
+ DbgScope *NScope = NULL;
+
+ if (InlinedAt)
+ NScope = DbgScopeMap.lookup(InlinedAt);
+ else
+ NScope = DbgScopeMap.lookup(N);
+ assert (NScope && "Unable to find working scope!");
+
+ if (NScope->getFirstInsn())
+ return NScope;
- if (InlinedAt) {
+ DbgScope *Parent = NULL;
+ if (GetConcreteScope) {
DILocation IL(InlinedAt);
- assert (!IL.isNull() && "Invalid InlindAt location!");
- ValueMap<MDNode *, DbgScope *>::iterator DSI =
- DbgScopeMap.find(IL.getScope().getNode());
- assert (DSI != DbgScopeMap.end() && "Unable to find InlineAt scope!");
- Parent = DSI->second;
- } else {
- DIDescriptor Scope(N);
- if (Scope.isCompileUnit()) {
- return NULL;
- } else if (Scope.isSubprogram()) {
- DISubprogram SP(N);
- DIDescriptor ParentDesc = SP.getContext();
- if (!ParentDesc.isNull() && !ParentDesc.isCompileUnit())
- Parent = getDbgScope(ParentDesc.getNode(), MI, InlinedAt);
- } else if (Scope.isLexicalBlock()) {
- DILexicalBlock DB(N);
- DIDescriptor ParentDesc = DB.getContext();
- if (!ParentDesc.isNull())
- Parent = getDbgScope(ParentDesc.getNode(), MI, InlinedAt);
- } else
- assert (0 && "Unexpected scope info");
- }
-
- DbgScope *NScope = new DbgScope(Parent, DIDescriptor(N), InlinedAt);
+ Parent = getUpdatedDbgScope(IL.getScope().getNode(), MI,
+ IL.getOrigLocation().getNode());
+ assert (Parent && "Unable to find Parent scope!");
+ NScope->setParent(Parent);
+ Parent->AddScope(NScope);
+ } else if (DIDescriptor(N).isLexicalBlock()) {
+ DILexicalBlock DB(N);
+ if (!DB.getContext().isNull()) {
+ Parent = getUpdatedDbgScope(DB.getContext().getNode(), MI, InlinedAt);
+ NScope->setParent(Parent);
+ Parent->AddScope(NScope);
+ }
+ }
+
NScope->setFirstInsn(MI);
- if (Parent)
- Parent->AddScope(NScope);
- else
- // First function is top level function.
- if (!FunctionDbgScope)
- FunctionDbgScope = NScope;
+ if (!Parent && !InlinedAt) {
+ StringRef SPName = DISubprogram(N).getLinkageName();
+ if (SPName == MF->getFunction()->getName())
+ CurrentFnDbgScope = NScope;
+ }
+
+ if (GetConcreteScope) {
+ ConcreteScopes[InlinedAt] = NScope;
+ getOrCreateAbstractScope(N);
+ }
- DbgScopeMap.insert(std::make_pair(N, NScope));
return NScope;
}
+DbgScope *DwarfDebug::getOrCreateAbstractScope(MDNode *N) {
+ assert (N && "Invalid Scope encoding!");
-/// getOrCreateScope - Returns the scope associated with the given descriptor.
-/// FIXME - Remove this method.
-DbgScope *DwarfDebug::getOrCreateScope(MDNode *N) {
- DbgScope *&Slot = DbgScopeMap[N];
- if (Slot) return Slot;
-
+ DbgScope *AScope = AbstractScopes.lookup(N);
+ if (AScope)
+ return AScope;
+
DbgScope *Parent = NULL;
- DILexicalBlock Block(N);
- // Don't create a new scope if we already created one for an inlined function.
- DenseMap<const MDNode *, DbgScope *>::iterator
- II = AbstractInstanceRootMap.find(N);
- if (II != AbstractInstanceRootMap.end())
- return LexicalScopeStack.back();
-
- if (!Block.isNull()) {
- DIDescriptor ParentDesc = Block.getContext();
- Parent =
- ParentDesc.isNull() ? NULL : getOrCreateScope(ParentDesc.getNode());
+ DIDescriptor Scope(N);
+ if (Scope.isLexicalBlock()) {
+ DILexicalBlock DB(N);
+ DIDescriptor ParentDesc = DB.getContext();
+ if (!ParentDesc.isNull())
+ Parent = getOrCreateAbstractScope(ParentDesc.getNode());
}
- Slot = new DbgScope(Parent, DIDescriptor(N));
+ AScope = new DbgScope(Parent, DIDescriptor(N), NULL);
if (Parent)
- Parent->AddScope(Slot);
- else
- // First function is top level function.
- FunctionDbgScope = Slot;
+ Parent->AddScope(AScope);
+ AScope->setAbstractScope();
+ AbstractScopes[N] = AScope;
+ if (DIDescriptor(N).isSubprogram())
+ AbstractScopesList.push_back(AScope);
+ return AScope;
+}
+
+static DISubprogram getDISubprogram(MDNode *N) {
- return Slot;
+ DIDescriptor D(N);
+ if (D.isNull())
+ return DISubprogram();
+
+ if (D.isCompileUnit())
+ return DISubprogram();
+
+ if (D.isSubprogram())
+ return DISubprogram(N);
+
+ if (D.isLexicalBlock())
+ return getDISubprogram(DILexicalBlock(N).getContext().getNode());
+
+ llvm_unreachable("Unexpected Descriptor!");
}
-/// ConstructDbgScope - Construct the components of a scope.
-///
-void DwarfDebug::ConstructDbgScope(DbgScope *ParentScope,
- unsigned ParentStartID,
- unsigned ParentEndID,
- DIE *ParentDie, CompileUnit *Unit) {
- // Add variables to scope.
- SmallVector<DbgVariable *, 8> &Variables = ParentScope->getVariables();
- for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
- DIE *VariableDie = CreateDbgScopeVariable(Variables[i], Unit);
- if (VariableDie) ParentDie->AddChild(VariableDie);
- }
+DIE *DwarfDebug::UpdateSubprogramScopeDIE(MDNode *SPNode) {
+
+ DIE *SPDie = ModuleCU->getDieMapSlotFor(SPNode);
+ assert (SPDie && "Unable to find subprogram DIE!");
+ AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ DWLabel("func_begin", SubprogramCount));
+ AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
+ DWLabel("func_end", SubprogramCount));
+ MachineLocation Location(RI->getFrameRegister(*MF));
+ AddAddress(SPDie, dwarf::DW_AT_frame_base, Location);
+
+ if (!DISubprogram(SPNode).isLocalToUnit())
+ AddUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
+
+ // If there are global variables at this scope then add their dies.
+ for (SmallVector<WeakVH, 4>::iterator SGI = ScopedGVs.begin(),
+ SGE = ScopedGVs.end(); SGI != SGE; ++SGI) {
+ MDNode *N = dyn_cast_or_null<MDNode>(*SGI);
+ if (!N) continue;
+ DIGlobalVariable GV(N);
+ if (GV.getContext().getNode() == SPNode) {
+ DIE *ScopedGVDie = CreateGlobalVariableDIE(ModuleCU, GV);
+ if (ScopedGVDie)
+ SPDie->AddChild(ScopedGVDie);
+ }
+ }
+ return SPDie;
+}
+
+DIE *DwarfDebug::ConstructLexicalScopeDIE(DbgScope *Scope) {
+ unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
+ unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
+
+ // Ignore empty scopes.
+ if (StartID == EndID && StartID != 0)
+ return NULL;
- // Add concrete instances to scope.
- SmallVector<DbgConcreteScope *, 8> &ConcreteInsts =
- ParentScope->getConcreteInsts();
- for (unsigned i = 0, N = ConcreteInsts.size(); i < N; ++i) {
- DbgConcreteScope *ConcreteInst = ConcreteInsts[i];
- DIE *Die = ConcreteInst->getDie();
+ DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
+ if (Scope->isAbstractScope())
+ return ScopeDIE;
- unsigned StartID = ConcreteInst->getStartLabelID();
- unsigned EndID = ConcreteInst->getEndLabelID();
+ AddLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ StartID ?
+ DWLabel("label", StartID)
+ : DWLabel("func_begin", SubprogramCount));
+ AddLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
+ EndID ?
+ DWLabel("label", EndID)
+ : DWLabel("func_end", SubprogramCount));
- // Add the scope bounds.
- if (StartID)
- AddLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("label", StartID));
- else
- AddLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("func_begin", SubprogramCount));
- if (EndID)
- AddLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("label", EndID));
- else
- AddLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("func_end", SubprogramCount));
- ParentDie->AddChild(Die);
- }
+ return ScopeDIE;
+}
- // Add nested scopes.
- SmallVector<DbgScope *, 4> &Scopes = ParentScope->getScopes();
- for (unsigned j = 0, M = Scopes.size(); j < M; ++j) {
- // Define the Scope debug information entry.
- DbgScope *Scope = Scopes[j];
+DIE *DwarfDebug::ConstructInlinedScopeDIE(DbgScope *Scope) {
+ unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
+ unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
+ assert (StartID && "Invalid starting label for an inlined scope!");
+ assert (EndID && "Invalid end label for an inlined scope!");
+ // Ignore empty scopes.
+ if (StartID == EndID && StartID != 0)
+ return NULL;
- unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID());
- unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID());
+ DIScope DS(Scope->getScopeNode());
+ if (DS.isNull())
+ return NULL;
+ DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
- // Ignore empty scopes.
- if (StartID == EndID && StartID != 0) continue;
+ DISubprogram InlinedSP = getDISubprogram(DS.getNode());
+ DIE *&OriginDIE = ModuleCU->getDieMapSlotFor(InlinedSP.getNode());
+ assert (OriginDIE && "Unable to find Origin DIE!");
+ AddDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
+ dwarf::DW_FORM_ref4, OriginDIE);
- // Do not ignore inlined scopes even if they don't have any variables or
- // scopes.
- if (Scope->getScopes().empty() && Scope->getVariables().empty() &&
- Scope->getConcreteInsts().empty())
- continue;
+ AddLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ DWLabel("label", StartID));
+ AddLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
+ DWLabel("label", EndID));
- if (StartID == ParentStartID && EndID == ParentEndID) {
- // Just add stuff to the parent scope.
- ConstructDbgScope(Scope, ParentStartID, ParentEndID, ParentDie, Unit);
- } else {
- DIE *ScopeDie = new DIE(dwarf::DW_TAG_lexical_block);
+ InlinedSubprogramDIEs.insert(OriginDIE);
- // Add the scope bounds.
- if (StartID)
- AddLabel(ScopeDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("label", StartID));
- else
- AddLabel(ScopeDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("func_begin", SubprogramCount));
+ // Track the start label for this inlined function.
+ ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
+ I = InlineInfo.find(InlinedSP.getNode());
- if (EndID)
- AddLabel(ScopeDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("label", EndID));
- else
- AddLabel(ScopeDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("func_end", SubprogramCount));
+ if (I == InlineInfo.end()) {
+ InlineInfo[InlinedSP.getNode()].push_back(std::make_pair(StartID, ScopeDIE));
+ InlinedSPNodes.push_back(InlinedSP.getNode());
+ } else
+ I->second.push_back(std::make_pair(StartID, ScopeDIE));
- // Add the scope's contents.
- ConstructDbgScope(Scope, StartID, EndID, ScopeDie, Unit);
- ParentDie->AddChild(ScopeDie);
- }
- }
+ StringPool.insert(InlinedSP.getName());
+ StringPool.insert(InlinedSP.getLinkageName());
+ DILocation DL(Scope->getInlinedAt());
+ AddUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, ModuleCU->getID());
+ AddUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber());
+
+ return ScopeDIE;
}
-/// ConstructFunctionDbgScope - Construct the scope for the subprogram.
-///
-void DwarfDebug::ConstructFunctionDbgScope(DbgScope *RootScope,
- bool AbstractScope) {
- // Exit if there is no root scope.
- if (!RootScope) return;
- DIDescriptor Desc = RootScope->getDesc();
- if (Desc.isNull())
- return;
+DIE *DwarfDebug::ConstructVariableDIE(DbgVariable *DV,
+ DbgScope *Scope, CompileUnit *Unit) {
+ // Get the descriptor.
+ const DIVariable &VD = DV->getVariable();
+ const char *Name = VD.getName();
+ if (!Name)
+ return NULL;
- // Get the subprogram debug information entry.
- DISubprogram SPD(Desc.getNode());
-
- // Get the subprogram die.
- DIE *SPDie = ModuleCU->getDieMapSlotFor(SPD.getNode());
- if (!SPDie) {
- ConstructSubprogram(SPD.getNode());
- SPDie = ModuleCU->getDieMapSlotFor(SPD.getNode());
- }
- assert(SPDie && "Missing subprogram descriptor");
-
- if (!AbstractScope) {
- // Add the function bounds.
- AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("func_begin", SubprogramCount));
- AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("func_end", SubprogramCount));
- MachineLocation Location(RI->getFrameRegister(*MF));
- AddAddress(SPDie, dwarf::DW_AT_frame_base, Location);
- }
-
- ConstructDbgScope(RootScope, 0, 0, SPDie, ModuleCU);
- // If there are global variables at this scope then add their dies.
- for (SmallVector<WeakVH, 4>::iterator SGI = ScopedGVs.begin(),
- SGE = ScopedGVs.end(); SGI != SGE; ++SGI) {
- MDNode *N = dyn_cast_or_null<MDNode>(*SGI);
- if (!N) continue;
- DIGlobalVariable GV(N);
- if (GV.getContext().getNode() == RootScope->getDesc().getNode()) {
- DIE *ScopedGVDie = CreateGlobalVariableDIE(ModuleCU, GV);
- SPDie->AddChild(ScopedGVDie);
- }
+ // Translate tag to proper Dwarf tag. The result variable is dropped for
+ // now.
+ unsigned Tag;
+ switch (VD.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;
}
-}
-/// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
-///
-void DwarfDebug::ConstructDefaultDbgScope(MachineFunction *MF) {
- StringMap<DIE*> &Globals = ModuleCU->getGlobals();
- StringMap<DIE*>::iterator GI = Globals.find(MF->getFunction()->getName());
- if (GI != Globals.end()) {
- DIE *SPDie = GI->second;
+ // Define variable debug information entry.
+ DIE *VariableDie = new DIE(Tag);
- // Add the function bounds.
- AddLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
- DWLabel("func_begin", SubprogramCount));
- AddLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
- DWLabel("func_end", SubprogramCount));
- MachineLocation Location(RI->getFrameRegister(*MF));
- AddAddress(SPDie, dwarf::DW_AT_frame_base, Location);
+ DIE *AbsDIE = NULL;
+ if (DbgVariable *AV = DV->getAbstractVariable())
+ AbsDIE = AV->getDIE();
+
+ if (AbsDIE) {
+ DIScope DS(Scope->getScopeNode());
+ DISubprogram InlinedSP = getDISubprogram(DS.getNode());
+ DIE *&OriginSPDIE = ModuleCU->getDieMapSlotFor(InlinedSP.getNode());
+ (void) OriginSPDIE;
+ assert (OriginSPDIE && "Unable to find Origin DIE for the SP!");
+ DIE *AbsDIE = DV->getAbstractVariable()->getDIE();
+ assert (AbsDIE && "Unable to find Origin DIE for the Variable!");
+ AddDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin,
+ dwarf::DW_FORM_ref4, AbsDIE);
}
+ else {
+ AddString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
+ AddSourceLine(VariableDie, &VD);
+
+ // Add variable type.
+ // FIXME: isBlockByrefVariable should be reformulated in terms of complex
+ // addresses instead.
+ if (VD.isBlockByrefVariable())
+ AddType(Unit, VariableDie, GetBlockByrefType(VD.getType(), Name));
+ else
+ AddType(Unit, VariableDie, VD.getType());
+ }
+
+ // Add variable address.
+ if (!Scope->isAbstractScope()) {
+ MachineLocation Location;
+ Location.set(RI->getFrameRegister(*MF),
+ RI->getFrameIndexOffset(*MF, DV->getFrameIndex()));
+
+
+ if (VD.hasComplexAddress())
+ AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
+ else if (VD.isBlockByrefVariable())
+ AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
+ else
+ AddAddress(VariableDie, dwarf::DW_AT_location, Location);
+ }
+ DV->setDIE(VariableDie);
+ return VariableDie;
+
+}
+DIE *DwarfDebug::ConstructScopeDIE(DbgScope *Scope) {
+ if (!Scope)
+ return NULL;
+ DIScope DS(Scope->getScopeNode());
+ if (DS.isNull())
+ return NULL;
+
+ DIE *ScopeDIE = NULL;
+ if (Scope->getInlinedAt())
+ ScopeDIE = ConstructInlinedScopeDIE(Scope);
+ else if (DS.isSubprogram()) {
+ if (Scope->isAbstractScope())
+ ScopeDIE = ModuleCU->getDieMapSlotFor(DS.getNode());
+ else
+ ScopeDIE = UpdateSubprogramScopeDIE(DS.getNode());
+ }
+ else {
+ ScopeDIE = ConstructLexicalScopeDIE(Scope);
+ if (!ScopeDIE) return NULL;
+ }
+
+ // Add variables to scope.
+ SmallVector<DbgVariable *, 8> &Variables = Scope->getVariables();
+ for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
+ DIE *VariableDIE = ConstructVariableDIE(Variables[i], Scope, ModuleCU);
+ if (VariableDIE)
+ ScopeDIE->AddChild(VariableDIE);
+ }
+
+ // Add nested scopes.
+ SmallVector<DbgScope *, 4> &Scopes = Scope->getScopes();
+ for (unsigned j = 0, M = Scopes.size(); j < M; ++j) {
+ // Define the Scope debug information entry.
+ DIE *NestedDIE = ConstructScopeDIE(Scopes[j]);
+ if (NestedDIE)
+ ScopeDIE->AddChild(NestedDIE);
+ }
+ return ScopeDIE;
}
/// GetOrCreateSourceID - Look up the source id with the given directory and
@@ -1680,6 +1757,9 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
+ if (!MAI->doesSupportDebugInformation())
+ return;
+
DebugInfoFinder DbgFinder;
DbgFinder.processModule(*M);
@@ -1710,7 +1790,7 @@ void DwarfDebug::BeginModule(Module *M, MachineModuleInfo *mmi) {
ConstructGlobalVariableDIE(*I);
}
- // Create DIEs for each of the externally visible subprograms.
+ // Create DIEs for each subprogram.
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
E = DbgFinder.subprogram_end(); I != E; ++I)
ConstructSubprogram(*I);
@@ -1754,6 +1834,13 @@ void DwarfDebug::EndModule() {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
+ // 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;
+ AddUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
+ }
+
// Standard sections final addresses.
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
EmitLabel("text_end", 0);
@@ -1811,55 +1898,102 @@ void DwarfDebug::EndModule() {
DebugTimer->stopTimer();
}
+/// findAbstractVariable - Find abstract variable, if any, associated with Var.
+DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var, unsigned FrameIdx,
+ DILocation &ScopeLoc) {
+
+ DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var.getNode());
+ if (AbsDbgVariable)
+ return AbsDbgVariable;
+
+ DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope().getNode());
+ if (!Scope)
+ return NULL;
+
+ AbsDbgVariable = new DbgVariable(Var, FrameIdx);
+ Scope->AddVariable(AbsDbgVariable);
+ AbstractVariables[Var.getNode()] = AbsDbgVariable;
+ return AbsDbgVariable;
+}
+
/// CollectVariableInfo - Populate DbgScope entries with variables' info.
void DwarfDebug::CollectVariableInfo() {
if (!MMI) return;
+
MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
VE = VMap.end(); VI != VE; ++VI) {
MetadataBase *MB = VI->first;
MDNode *Var = dyn_cast_or_null<MDNode>(MB);
+ if (!Var) continue;
DIVariable DV (Var);
- if (DV.isNull()) continue;
- unsigned VSlot = VI->second;
- DbgScope *Scope = NULL;
- ValueMap<MDNode *, DbgScope *>::iterator DSI =
- DbgScopeMap.find(DV.getContext().getNode());
- if (DSI != DbgScopeMap.end())
- Scope = DSI->second;
- else
- // There is not any instruction assocated with this scope, so get
- // a new scope.
- Scope = getDbgScope(DV.getContext().getNode(),
- NULL /* Not an instruction */,
- NULL /* Not inlined */);
- assert (Scope && "Unable to find variable scope!");
- Scope->AddVariable(new DbgVariable(DV, VSlot, false));
- }
-}
-
-/// SetDbgScopeBeginLabels - Update DbgScope begin labels for the scopes that
-/// start with this machine instruction.
-void DwarfDebug::SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned Label) {
+ std::pair< unsigned, MDNode *> VP = VI->second;
+ DILocation ScopeLoc(VP.second);
+
+ DbgScope *Scope =
+ ConcreteScopes.lookup(ScopeLoc.getOrigLocation().getNode());
+ if (!Scope)
+ Scope = DbgScopeMap.lookup(ScopeLoc.getScope().getNode());
+ // If variable scope is not found then skip this variable.
+ if (!Scope)
+ continue;
+
+ DbgVariable *RegVar = new DbgVariable(DV, VP.first);
+ Scope->AddVariable(RegVar);
+ if (DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.first, ScopeLoc))
+ RegVar->setAbstractVariable(AbsDbgVariable);
+ }
+}
+
+/// BeginScope - Process beginning of a scope starting at Label.
+void DwarfDebug::BeginScope(const MachineInstr *MI, unsigned Label) {
InsnToDbgScopeMapTy::iterator I = DbgScopeBeginMap.find(MI);
if (I == DbgScopeBeginMap.end())
return;
- SmallVector<DbgScope *, 2> &SD = I->second;
- for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
+ ScopeVector &SD = DbgScopeBeginMap[MI];
+ for (ScopeVector::iterator SDI = SD.begin(), SDE = SD.end();
SDI != SDE; ++SDI)
(*SDI)->setStartLabelID(Label);
}
-/// SetDbgScopeEndLabels - Update DbgScope end labels for the scopes that
-/// end with this machine instruction.
-void DwarfDebug::SetDbgScopeEndLabels(const MachineInstr *MI, unsigned Label) {
+/// EndScope - Process end of a scope.
+void DwarfDebug::EndScope(const MachineInstr *MI) {
InsnToDbgScopeMapTy::iterator I = DbgScopeEndMap.find(MI);
if (I == DbgScopeEndMap.end())
return;
+
+ unsigned Label = MMI->NextLabelID();
+ Asm->printLabel(Label);
+
SmallVector<DbgScope *, 2> &SD = I->second;
for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
SDI != SDE; ++SDI)
(*SDI)->setEndLabelID(Label);
+ return;
+}
+
+/// createDbgScope - Create DbgScope for the scope.
+void DwarfDebug::createDbgScope(MDNode *Scope, MDNode *InlinedAt) {
+
+ if (!InlinedAt) {
+ DbgScope *WScope = DbgScopeMap.lookup(Scope);
+ if (WScope)
+ return;
+ WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL);
+ DbgScopeMap.insert(std::make_pair(Scope, WScope));
+ if (DIDescriptor(Scope).isLexicalBlock())
+ createDbgScope(DILexicalBlock(Scope).getContext().getNode(), NULL);
+ return;
+ }
+
+ DbgScope *WScope = DbgScopeMap.lookup(InlinedAt);
+ if (WScope)
+ return;
+
+ WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt);
+ DbgScopeMap.insert(std::make_pair(InlinedAt, WScope));
+ DILocation DL(InlinedAt);
+ createDbgScope(DL.getScope().getNode(), DL.getOrigLocation().getNode());
}
/// ExtractScopeInformation - Scan machine instructions in this function
@@ -1870,26 +2004,41 @@ bool DwarfDebug::ExtractScopeInformation(MachineFunction *MF) {
if (!DbgScopeMap.empty())
return false;
- // Scan each instruction and create scopes.
+ // Scan each instruction and create scopes. First build working set of scopes.
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I) {
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
II != IE; ++II) {
const MachineInstr *MInsn = II;
DebugLoc DL = MInsn->getDebugLoc();
- if (DL.isUnknown())
- continue;
+ if (DL.isUnknown()) continue;
DebugLocTuple DLT = MF->getDebugLocTuple(DL);
- if (!DLT.Scope)
- continue;
+ if (!DLT.Scope) continue;
// There is no need to create another DIE for compile unit. For all
// other scopes, create one DbgScope now. This will be translated
// into a scope DIE at the end.
- DIDescriptor D(DLT.Scope);
- if (!D.isCompileUnit()) {
- DbgScope *Scope = getDbgScope(DLT.Scope, MInsn, DLT.InlinedAtLoc);
- Scope->setLastInsn(MInsn);
- }
+ if (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
+ createDbgScope(DLT.Scope, DLT.InlinedAtLoc);
+ }
+ }
+
+
+ // Build scope hierarchy using working set of scopes.
+ for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
+ I != E; ++I) {
+ for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
+ II != IE; ++II) {
+ const MachineInstr *MInsn = II;
+ DebugLoc DL = MInsn->getDebugLoc();
+ if (DL.isUnknown()) continue;
+ DebugLocTuple DLT = MF->getDebugLocTuple(DL);
+ if (!DLT.Scope) continue;
+ // There is no need to create another DIE for compile unit. For all
+ // other scopes, create one DbgScope now. This will be translated
+ // into a scope DIE at the end.
+ if (DIDescriptor(DLT.Scope).isCompileUnit()) continue;
+ DbgScope *Scope = getUpdatedDbgScope(DLT.Scope, MInsn, DLT.InlinedAtLoc);
+ Scope->setLastInsn(MInsn);
}
}
@@ -1897,8 +2046,8 @@ bool DwarfDebug::ExtractScopeInformation(MachineFunction *MF) {
// last instruction as this scope's last instrunction.
for (ValueMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
DE = DbgScopeMap.end(); DI != DE; ++DI) {
- DbgScope *S = DI->second;
- if (!S) continue;
+ if (DI->second->isAbstractScope())
+ continue;
assert (DI->second->getFirstInsn() && "Invalid first instruction!");
DI->second->FixInstructionMarkers();
assert (DI->second->getLastInsn() && "Invalid last instruction!");
@@ -1911,7 +2060,8 @@ bool DwarfDebug::ExtractScopeInformation(MachineFunction *MF) {
for (ValueMap<MDNode *, DbgScope *>::iterator DI = DbgScopeMap.begin(),
DE = DbgScopeMap.end(); DI != DE; ++DI) {
DbgScope *S = DI->second;
- if (!S) continue;
+ if (S->isAbstractScope())
+ continue;
const MachineInstr *MI = S->getFirstInsn();
assert (MI && "DbgScope does not have first instruction!");
@@ -1919,8 +2069,7 @@ bool DwarfDebug::ExtractScopeInformation(MachineFunction *MF) {
if (IDI != DbgScopeBeginMap.end())
IDI->second.push_back(S);
else
- DbgScopeBeginMap.insert(std::make_pair(MI,
- SmallVector<DbgScope *, 2>(2, S)));
+ DbgScopeBeginMap[MI].push_back(S);
MI = S->getLastInsn();
assert (MI && "DbgScope does not have last instruction!");
@@ -1928,31 +2077,12 @@ bool DwarfDebug::ExtractScopeInformation(MachineFunction *MF) {
if (IDI != DbgScopeEndMap.end())
IDI->second.push_back(S);
else
- DbgScopeEndMap.insert(std::make_pair(MI,
- SmallVector<DbgScope *, 2>(2, S)));
+ DbgScopeEndMap[MI].push_back(S);
}
return !DbgScopeMap.empty();
}
-static DISubprogram getDISubprogram(MDNode *N) {
-
- DIDescriptor D(N);
- if (D.isNull())
- return DISubprogram();
-
- if (D.isCompileUnit())
- return DISubprogram();
-
- if (D.isSubprogram())
- return DISubprogram(N);
-
- if (D.isLexicalBlock())
- return getDISubprogram(DILexicalBlock(N).getContext().getNode());
-
- llvm_unreachable("Unexpected Descriptor!");
-}
-
/// BeginFunction - Gather pre-function debug information. Assumes being
/// emitted immediately after the function entry point.
void DwarfDebug::BeginFunction(MachineFunction *MF) {
@@ -1963,11 +2093,9 @@ void DwarfDebug::BeginFunction(MachineFunction *MF) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
if (!ExtractScopeInformation(MF))
return;
CollectVariableInfo();
-#endif
// Begin accumulating function debug information.
MMI->BeginFunction(MF);
@@ -1977,7 +2105,6 @@ void DwarfDebug::BeginFunction(MachineFunction *MF) {
// Emit label for the implicitly defined dbg.stoppoint at the start of the
// function.
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
DebugLoc FDL = MF->getDefaultDebugLoc();
if (!FDL.isUnknown()) {
DebugLocTuple DLT = MF->getDebugLocTuple(FDL);
@@ -1990,15 +2117,6 @@ void DwarfDebug::BeginFunction(MachineFunction *MF) {
Asm->printLabel(LabelID);
O << '\n';
}
-#else
- DebugLoc FDL = MF->getDefaultDebugLoc();
- if (!FDL.isUnknown()) {
- DebugLocTuple DLT = MF->getDebugLocTuple(FDL);
- unsigned LabelID = RecordSourceLine(DLT.Line, DLT.Col, DLT.Scope);
- Asm->printLabel(LabelID);
- O << '\n';
- }
-#endif
if (TimePassesIsEnabled)
DebugTimer->stopTimer();
}
@@ -2011,10 +2129,9 @@ void DwarfDebug::EndFunction(MachineFunction *MF) {
if (TimePassesIsEnabled)
DebugTimer->startTimer();
-#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN
if (DbgScopeMap.empty())
return;
-#endif
+
// Define end label for subprogram.
EmitLabel("func_end", SubprogramCount);
@@ -2029,41 +2146,24 @@ void DwarfDebug::EndFunction(MachineFunction *MF) {
Lines.begin(), Lines.end());
}
- // Construct the DbgScope for abstract instances.
- for (SmallVector<DbgScope *, 32>::iterator
- I = AbstractInstanceRootList.begin(),
- E = AbstractInstanceRootList.end(); I != E; ++I)
- ConstructFunctionDbgScope(*I);
+ // Construct abstract scopes.
+ for (SmallVector<DbgScope *, 4>::iterator AI = AbstractScopesList.begin(),
+ AE = AbstractScopesList.end(); AI != AE; ++AI)
+ ConstructScopeDIE(*AI);
- // Construct scopes for subprogram.
- if (FunctionDbgScope)
- ConstructFunctionDbgScope(FunctionDbgScope);
- else
- // FIXME: This is wrong. We are essentially getting past a problem with
- // debug information not being able to handle unreachable blocks that have
- // debug information in them. In particular, those unreachable blocks that
- // have "region end" info in them. That situation results in the "root
- // scope" not being created. If that's the case, then emit a "default"
- // scope, i.e., one that encompasses the whole function. This isn't
- // desirable. And a better way of handling this (and all of the debugging
- // information) needs to be explored.
- ConstructDefaultDbgScope(MF);
+ ConstructScopeDIE(CurrentFnDbgScope);
DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
MMI->getFrameMoves()));
// Clear debug info
- if (FunctionDbgScope) {
- delete FunctionDbgScope;
+ if (CurrentFnDbgScope) {
+ CurrentFnDbgScope = NULL;
DbgScopeMap.clear();
DbgScopeBeginMap.clear();
DbgScopeEndMap.clear();
- DbgAbstractScopeMap.clear();
- DbgConcreteScopeMap.clear();
- FunctionDbgScope = NULL;
- LexicalScopeStack.clear();
- AbstractInstanceRootList.clear();
- AbstractInstanceRootMap.clear();
+ ConcreteScopes.clear();
+ AbstractScopesList.clear();
}
Lines.clear();
@@ -2130,201 +2230,6 @@ unsigned DwarfDebug::getOrCreateSourceID(const std::string &DirName,
return SrcId;
}
-/// RecordRegionStart - Indicate the start of a region.
-unsigned DwarfDebug::RecordRegionStart(MDNode *N) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- DbgScope *Scope = getOrCreateScope(N);
- unsigned ID = MMI->NextLabelID();
- if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
- LexicalScopeStack.push_back(Scope);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return ID;
-}
-
-/// RecordRegionEnd - Indicate the end of a region.
-unsigned DwarfDebug::RecordRegionEnd(MDNode *N) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- DbgScope *Scope = getOrCreateScope(N);
- unsigned ID = MMI->NextLabelID();
- Scope->setEndLabelID(ID);
- // FIXME : region.end() may not be in the last basic block.
- // For now, do not pop last lexical scope because next basic
- // block may start new inlined function's body.
- unsigned LSSize = LexicalScopeStack.size();
- if (LSSize != 0 && LSSize != 1)
- LexicalScopeStack.pop_back();
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return ID;
-}
-
-/// RecordVariable - Indicate the declaration of a local variable.
-void DwarfDebug::RecordVariable(MDNode *N, unsigned FrameIndex) {
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- DIDescriptor Desc(N);
- DbgScope *Scope = NULL;
- bool InlinedFnVar = false;
-
- if (Desc.getTag() == dwarf::DW_TAG_variable)
- Scope = getOrCreateScope(DIGlobalVariable(N).getContext().getNode());
- else {
- bool InlinedVar = false;
- MDNode *Context = DIVariable(N).getContext().getNode();
- DISubprogram SP(Context);
- if (!SP.isNull()) {
- // SP is inserted into DbgAbstractScopeMap when inlined function
- // start was recorded by RecordInlineFnStart.
- ValueMap<MDNode *, DbgScope *>::iterator
- I = DbgAbstractScopeMap.find(SP.getNode());
- if (I != DbgAbstractScopeMap.end()) {
- InlinedVar = true;
- Scope = I->second;
- }
- }
- if (!InlinedVar)
- Scope = getOrCreateScope(Context);
- }
-
- assert(Scope && "Unable to find the variable's scope");
- DbgVariable *DV = new DbgVariable(DIVariable(N), FrameIndex, InlinedFnVar);
- Scope->AddVariable(DV);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-}
-
-//// RecordInlinedFnStart - Indicate the start of inlined subroutine.
-unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
- unsigned Line, unsigned Col) {
- unsigned LabelID = MMI->NextLabelID();
-
- if (!MAI->doesDwarfUsesInlineInfoSection())
- return LabelID;
-
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- MDNode *Node = SP.getNode();
- DenseMap<const MDNode *, DbgScope *>::iterator
- II = AbstractInstanceRootMap.find(Node);
-
- if (II == AbstractInstanceRootMap.end()) {
- // Create an abstract instance entry for this inlined function if it doesn't
- // already exist.
- DbgScope *Scope = new DbgScope(NULL, DIDescriptor(Node));
-
- // Get the compile unit context.
- DIE *SPDie = ModuleCU->getDieMapSlotFor(Node);
- if (!SPDie)
- SPDie = CreateSubprogramDIE(ModuleCU, SP, false, true);
-
- // Mark as being inlined. This makes this subprogram entry an abstract
- // instance root.
- // FIXME: Our debugger doesn't care about the value of DW_AT_inline, only
- // that it's defined. That probably won't change in the future. However,
- // this could be more elegant.
- AddUInt(SPDie, dwarf::DW_AT_inline, 0, dwarf::DW_INL_declared_not_inlined);
-
- // Keep track of the abstract scope for this function.
- DbgAbstractScopeMap[Node] = Scope;
-
- AbstractInstanceRootMap[Node] = Scope;
- AbstractInstanceRootList.push_back(Scope);
- }
-
- // Create a concrete inlined instance for this inlined function.
- DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(Node));
- DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine);
- ScopeDie->setAbstractCompileUnit(ModuleCU);
-
- DIE *Origin = ModuleCU->getDieMapSlotFor(Node);
- AddDIEEntry(ScopeDie, dwarf::DW_AT_abstract_origin,
- dwarf::DW_FORM_ref4, Origin);
- AddUInt(ScopeDie, dwarf::DW_AT_call_file, 0, ModuleCU->getID());
- AddUInt(ScopeDie, dwarf::DW_AT_call_line, 0, Line);
- AddUInt(ScopeDie, dwarf::DW_AT_call_column, 0, Col);
-
- ConcreteScope->setDie(ScopeDie);
- ConcreteScope->setStartLabelID(LabelID);
- MMI->RecordUsedDbgLabel(LabelID);
-
- LexicalScopeStack.back()->AddConcreteInst(ConcreteScope);
-
- // Keep track of the concrete scope that's inlined into this function.
- ValueMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator
- SI = DbgConcreteScopeMap.find(Node);
-
- if (SI == DbgConcreteScopeMap.end())
- DbgConcreteScopeMap[Node].push_back(ConcreteScope);
- else
- SI->second.push_back(ConcreteScope);
-
- // Track the start label for this inlined function.
- ValueMap<MDNode *, SmallVector<unsigned, 4> >::iterator
- I = InlineInfo.find(Node);
-
- if (I == InlineInfo.end())
- InlineInfo[Node].push_back(LabelID);
- else
- I->second.push_back(LabelID);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return LabelID;
-}
-
-/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
-unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) {
- if (!MAI->doesDwarfUsesInlineInfoSection())
- return 0;
-
- if (TimePassesIsEnabled)
- DebugTimer->startTimer();
-
- MDNode *Node = SP.getNode();
- ValueMap<MDNode *, SmallVector<DbgScope *, 8> >::iterator
- I = DbgConcreteScopeMap.find(Node);
-
- if (I == DbgConcreteScopeMap.end()) {
- // FIXME: Can this situation actually happen? And if so, should it?
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return 0;
- }
-
- SmallVector<DbgScope *, 8> &Scopes = I->second;
- if (Scopes.empty()) {
- // Returned ID is 0 if this is unbalanced "end of inlined
- // scope". This could happen if optimizer eats dbg intrinsics
- // or "beginning of inlined scope" is not recoginized due to
- // missing location info. In such cases, ignore this region.end.
- return 0;
- }
-
- DbgScope *Scope = Scopes.back(); Scopes.pop_back();
- unsigned ID = MMI->NextLabelID();
- MMI->RecordUsedDbgLabel(ID);
- Scope->setEndLabelID(ID);
-
- if (TimePassesIsEnabled)
- DebugTimer->stopTimer();
-
- return ID;
-}
-
//===----------------------------------------------------------------------===//
// Emit Methods
//===----------------------------------------------------------------------===//
@@ -2470,10 +2375,7 @@ void DwarfDebug::EmitDIE(DIE *Die) {
case dwarf::DW_AT_abstract_origin: {
DIEEntry *E = cast<DIEEntry>(Values[i]);
DIE *Origin = E->getEntry();
- unsigned Addr =
- CompileUnitOffsets[Die->getAbstractCompileUnit()] +
- Origin->getOffset();
-
+ unsigned Addr = Origin->getOffset();
Asm->EmitInt32(Addr);
break;
}
@@ -3002,10 +2904,14 @@ void DwarfDebug::EmitDebugInlineInfo() {
Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("Dwarf Version");
Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)");
- for (ValueMap<MDNode *, SmallVector<unsigned, 4> >::iterator
- I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) {
- MDNode *Node = I->first;
- SmallVector<unsigned, 4> &Labels = I->second;
+ for (SmallVector<MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
+ E = InlinedSPNodes.end(); I != E; ++I) {
+
+// for (ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator
+ // I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) {
+ MDNode *Node = *I;
+ ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II = InlineInfo.find(Node);
+ SmallVector<InlineInfoLabels, 4> &Labels = II->second;
DISubprogram SP(Node);
const char *LName = SP.getLinkageName();
const char *Name = SP.getName();
@@ -3019,17 +2925,21 @@ void DwarfDebug::EmitDebugInlineInfo() {
// __asm__ attribute.
if (LName[0] == 1)
LName = &LName[1];
- Asm->EmitString(LName);
+// Asm->EmitString(LName);
+ EmitSectionOffset("string", "section_str",
+ StringPool.idFor(LName), false, true);
+
}
Asm->EOL("MIPS linkage name");
-
- Asm->EmitString(Name); Asm->EOL("Function name");
-
+// Asm->EmitString(Name);
+ EmitSectionOffset("string", "section_str",
+ StringPool.idFor(Name), false, true);
+ Asm->EOL("Function name");
Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count");
- for (SmallVector<unsigned, 4>::iterator LI = Labels.begin(),
+ for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
LE = Labels.end(); LI != LE; ++LI) {
- DIE *SP = ModuleCU->getDieMapSlotFor(Node);
+ DIE *SP = LI->second;
Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset");
if (TD->getPointerSize() == sizeof(int32_t))
@@ -3037,7 +2947,7 @@ void DwarfDebug::EmitDebugInlineInfo() {
else
O << MAI->getData64bitsDirective();
- PrintLabelName("label", *LI); Asm->EOL("low_pc");
+ PrintLabelName("label", LI->first); Asm->EOL("low_pc");
}
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index ddb0a15..646de8f 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -30,9 +30,9 @@
namespace llvm {
class CompileUnit;
-class DbgVariable;
-class DbgScope;
class DbgConcreteScope;
+class DbgScope;
+class DbgVariable;
class MachineFrameInfo;
class MachineModuleInfo;
class MCAsmInfo;
@@ -41,7 +41,7 @@ class Timer;
//===----------------------------------------------------------------------===//
/// SrcLineInfo - This class is used to record source line correspondence.
///
-class VISIBILITY_HIDDEN SrcLineInfo {
+class SrcLineInfo {
unsigned Line; // Source line number.
unsigned Column; // Source column.
unsigned SourceID; // Source ID number.
@@ -57,7 +57,7 @@ public:
unsigned getLabelID() const { return LabelID; }
};
-class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
+class DwarfDebug : public Dwarf {
//===--------------------------------------------------------------------===//
// Attributes used to construct specific Dwarf sections.
//
@@ -134,52 +134,52 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
///
bool shouldEmit;
- // FunctionDbgScope - Top level scope for the current function.
+ // CurrentFnDbgScope - Top level scope for the current function.
//
- DbgScope *FunctionDbgScope;
+ DbgScope *CurrentFnDbgScope;
/// DbgScopeMap - Tracks the scopes in the current function.
+ ///
ValueMap<MDNode *, DbgScope *> DbgScopeMap;
+ /// ConcreteScopes - Tracks the concrete scopees in the current function.
+ /// These scopes are also included in DbgScopeMap.
+ ValueMap<MDNode *, DbgScope *> ConcreteScopes;
+
+ /// AbstractScopes - Tracks the abstract scopes a module. These scopes are
+ /// not included DbgScopeMap.
+ ValueMap<MDNode *, DbgScope *> AbstractScopes;
+ SmallVector<DbgScope *, 4>AbstractScopesList;
+
+ /// AbstractVariables - Collection on abstract variables.
+ ValueMap<MDNode *, DbgVariable *> AbstractVariables;
+
+ /// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked
+ /// (at the end of the module) as DW_AT_inline.
+ SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs;
+
+ /// AbstractSubprogramDIEs - Collection of abstruct subprogram DIEs.
+ SmallPtrSet<DIE *, 4> AbstractSubprogramDIEs;
+
/// ScopedGVs - Tracks global variables that are not at file scope.
/// For example void f() { static int b = 42; }
SmallVector<WeakVH, 4> ScopedGVs;
- typedef DenseMap<const MachineInstr *, SmallVector<DbgScope *, 2> >
+ typedef SmallVector<DbgScope *, 2> ScopeVector;
+ typedef DenseMap<const MachineInstr *, ScopeVector>
InsnToDbgScopeMapTy;
- /// DbgScopeBeginMap - Maps instruction with a list DbgScopes it starts.
+ /// DbgScopeBeginMap - Maps instruction with a list of DbgScopes it starts.
InsnToDbgScopeMapTy DbgScopeBeginMap;
/// DbgScopeEndMap - Maps instruction with a list DbgScopes it ends.
InsnToDbgScopeMapTy DbgScopeEndMap;
- /// DbgAbstractScopeMap - Tracks abstract instance scopes in the current
- /// function.
- ValueMap<MDNode *, DbgScope *> DbgAbstractScopeMap;
-
- /// DbgConcreteScopeMap - Tracks concrete instance scopes in the current
- /// function.
- ValueMap<MDNode *,
- SmallVector<DbgScope *, 8> > DbgConcreteScopeMap;
-
/// InlineInfo - Keep track of inlined functions and their location. This
/// information is used to populate debug_inlined section.
- ValueMap<MDNode *, SmallVector<unsigned, 4> > InlineInfo;
-
- /// AbstractInstanceRootMap - Map of abstract instance roots of inlined
- /// functions. These are subroutine entries that contain a DW_AT_inline
- /// attribute.
- DenseMap<const MDNode *, DbgScope *> AbstractInstanceRootMap;
-
- /// AbstractInstanceRootList - List of abstract instance roots of inlined
- /// functions. These are subroutine entries that contain a DW_AT_inline
- /// attribute.
- SmallVector<DbgScope *, 32> AbstractInstanceRootList;
-
- /// LexicalScopeStack - A stack of lexical scopes. The top one is the current
- /// scope.
- SmallVector<DbgScope *, 16> LexicalScopeStack;
+ typedef std::pair<unsigned, DIE *> InlineInfoLabels;
+ ValueMap<MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo;
+ SmallVector<MDNode *, 4> InlinedSPNodes;
/// CompileUnitOffsets - A vector of the offsets of the compile units. This is
/// used when calculating the "origin" of a concrete instance of an inlined
@@ -361,10 +361,24 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
///
DIE *CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit);
- /// getDbgScope - Returns the scope associated with the given descriptor.
- ///
- DbgScope *getOrCreateScope(MDNode *N);
- DbgScope *getDbgScope(MDNode *N, const MachineInstr *MI, MDNode *InlinedAt);
+ /// getUpdatedDbgScope - Find or create DbgScope assicated with
+ /// the instruction. Initialize scope and update scope hierarchy.
+ DbgScope *getUpdatedDbgScope(MDNode *N, const MachineInstr *MI, MDNode *InlinedAt);
+
+ /// createDbgScope - Create DbgScope for the scope.
+ void createDbgScope(MDNode *Scope, MDNode *InlinedAt);
+
+ DbgScope *getOrCreateAbstractScope(MDNode *N);
+
+ /// findAbstractVariable - Find abstract variable associated with Var.
+ DbgVariable *findAbstractVariable(DIVariable &Var, unsigned FrameIdx,
+ DILocation &Loc);
+
+ DIE *UpdateSubprogramScopeDIE(MDNode *SPNode);
+ DIE *ConstructLexicalScopeDIE(DbgScope *Scope);
+ DIE *ConstructScopeDIE(DbgScope *Scope);
+ DIE *ConstructInlinedScopeDIE(DbgScope *Scope);
+ DIE *ConstructVariableDIE(DbgVariable *DV, DbgScope *S, CompileUnit *Unit);
/// ConstructDbgScope - Construct the components of a scope.
///
@@ -372,15 +386,6 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf {
unsigned ParentStartID, unsigned ParentEndID,
DIE *ParentDie, CompileUnit *Unit);
- /// ConstructFunctionDbgScope - Construct the scope for the subprogram.
- ///
- void ConstructFunctionDbgScope(DbgScope *RootScope,
- bool AbstractScope = false);
-
- /// ConstructDefaultDbgScope - Construct a default scope for the subprogram.
- ///
- void ConstructDefaultDbgScope(MachineFunction *MF);
-
/// EmitInitial - Emit initial Dwarf declarations. This is necessary for cc
/// tools to recognize the object file contains Dwarf information.
void EmitInitial();
@@ -535,22 +540,6 @@ public:
unsigned getOrCreateSourceID(const std::string &DirName,
const std::string &FileName);
- /// RecordRegionStart - Indicate the start of a region.
- unsigned RecordRegionStart(MDNode *N);
-
- /// RecordRegionEnd - Indicate the end of a region.
- unsigned RecordRegionEnd(MDNode *N);
-
- /// RecordVariable - Indicate the declaration of a local variable.
- void RecordVariable(MDNode *N, unsigned FrameIndex);
-
- //// RecordInlinedFnStart - Indicate the start of inlined subroutine.
- unsigned RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
- unsigned Line, unsigned Col);
-
- /// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
- unsigned RecordInlinedFnEnd(DISubprogram &SP);
-
/// ExtractScopeInformation - Scan machine instructions in this function
/// and collect DbgScopes. Return true, if atleast one scope was found.
bool ExtractScopeInformation(MachineFunction *MF);
@@ -558,15 +547,16 @@ public:
/// CollectVariableInfo - Populate DbgScope entries with variables' info.
void CollectVariableInfo();
- /// SetDbgScopeBeginLabels - Update DbgScope begin labels for the scopes that
- /// start with this machine instruction.
- void SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned Label);
-
/// SetDbgScopeEndLabels - Update DbgScope end labels for the scopes that
/// end with this machine instruction.
void SetDbgScopeEndLabels(const MachineInstr *MI, unsigned Label);
-};
+ /// BeginScope - Process beginning of a scope starting at Label.
+ void BeginScope(const MachineInstr *MI, unsigned Label);
+
+ /// EndScope - Prcess end of a scope.
+ void EndScope(const MachineInstr *MI);
+};
} // End of namespace llvm
#endif
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index 6c03b55..1c8b8f4 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp
@@ -74,6 +74,25 @@ unsigned DwarfException::SizeOfEncodedValue(unsigned Encoding) {
return 0;
}
+/// CreateLabelDiff - Emit a label and subtract it from the expression we
+/// already have. This is equivalent to emitting "foo - .", but we have to emit
+/// the label for "." directly.
+const MCExpr *DwarfException::CreateLabelDiff(const MCExpr *ExprRef,
+ const char *LabelName,
+ unsigned Index) {
+ SmallString<64> Name;
+ raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
+ << LabelName << Asm->getFunctionNumber()
+ << "_" << Index;
+ MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str());
+ Asm->OutStreamer.EmitLabel(DotSym);
+
+ return MCBinaryExpr::CreateSub(ExprRef,
+ MCSymbolRefExpr::Create(DotSym,
+ Asm->OutContext),
+ Asm->OutContext);
+}
+
/// EmitCIE - Emit a Common Information Entry (CIE). This holds information that
/// is shared among many Frame Description Entries. There is at least one CIE
/// in every non-empty .debug_frame section.
@@ -176,24 +195,10 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) {
// If there is a personality, we need to indicate the function's location.
if (PersonalityRef) {
- // If the reference to the personality function symbol is not already
- // pc-relative, then we need to subtract our current address from it. Do
- // this by emitting a label and subtracting it from the expression we
- // already have. This is equivalent to emitting "foo - .", but we have to
- // emit the label for "." directly.
- if (!IsPersonalityPCRel) {
- SmallString<64> Name;
- raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
- << "personalityref_addr" << Asm->getFunctionNumber() << "_" << Index;
- MCSymbol *DotSym = Asm->OutContext.GetOrCreateSymbol(Name.str());
- Asm->OutStreamer.EmitLabel(DotSym);
-
- PersonalityRef =
- MCBinaryExpr::CreateSub(PersonalityRef,
- MCSymbolRefExpr::Create(DotSym,Asm->OutContext),
- Asm->OutContext);
- }
-
+ if (!IsPersonalityPCRel)
+ PersonalityRef = CreateLabelDiff(PersonalityRef, "personalityref_addr",
+ Index);
+
O << MAI->getData32bitsDirective();
PersonalityRef->print(O, MAI);
Asm->EOL("Personality");
@@ -232,11 +237,16 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
// corresponding function is static, this should not be externally visible.
if (!TheFunc->hasLocalLinkage())
if (const char *GlobalEHDirective = MAI->getGlobalEHDirective())
- O << GlobalEHDirective << EHFrameInfo.FnName << "\n";
+ O << GlobalEHDirective << EHFrameInfo.FnName << '\n';
// If corresponding function is weak definition, this should be too.
if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective())
- O << MAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n";
+ O << MAI->getWeakDefDirective() << EHFrameInfo.FnName << '\n';
+
+ // If corresponding function is hidden, this should be too.
+ if (TheFunc->hasHiddenVisibility())
+ if (const char *HiddenDirective = MAI->getHiddenDirective())
+ O << HiddenDirective << EHFrameInfo.FnName << '\n' ;
// If there are no calls then you can't unwind. This may mean we can omit the
// EH Frame, but some environments do not handle weak absolute symbols. If
@@ -457,6 +467,39 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
return SizeActions;
}
+/// CallToNoUnwindFunction - Return `true' if this is a call to a function
+/// marked `nounwind'. Return `false' otherwise.
+bool DwarfException::CallToNoUnwindFunction(const MachineInstr *MI) {
+ assert(MI->getDesc().isCall() && "This should be a call instruction!");
+
+ bool MarkedNoUnwind = false;
+ bool SawFunc = false;
+
+ for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
+ const MachineOperand &MO = MI->getOperand(I);
+
+ if (MO.isGlobal()) {
+ if (Function *F = dyn_cast<Function>(MO.getGlobal())) {
+ if (SawFunc) {
+ // Be conservative. If we have more than one function operand for this
+ // call, then we can't make the assumption that it's the callee and
+ // not a parameter to the call.
+ //
+ // FIXME: Determine if there's a way to say that `F' is the callee or
+ // parameter.
+ MarkedNoUnwind = false;
+ break;
+ }
+
+ MarkedNoUnwind = F->doesNotThrow();
+ SawFunc = true;
+ }
+ }
+ }
+
+ return MarkedNoUnwind;
+}
+
/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke
/// has a try-range containing the call, a non-zero landing pad, and an
/// appropriate action. The entry for an ordinary call has a try-range
@@ -485,7 +528,9 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
MI != E; ++MI) {
if (!MI->isLabel()) {
- SawPotentiallyThrowing |= MI->getDesc().isCall();
+ if (MI->getDesc().isCall())
+ SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI);
+
continue;
}
@@ -497,7 +542,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
SawPotentiallyThrowing = false;
// Beginning of a new try-range?
- RangeMapType::iterator L = PadMap.find(BeginLabel);
+ RangeMapType::const_iterator L = PadMap.find(BeginLabel);
if (L == PadMap.end())
// Nope, it was just some random label.
continue;
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h
index f6f5025..aff1665 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.h
+++ b/lib/CodeGen/AsmPrinter/DwarfException.h
@@ -25,13 +25,14 @@ namespace llvm {
struct LandingPadInfo;
class MachineModuleInfo;
class MCAsmInfo;
+class MCExpr;
class Timer;
class raw_ostream;
//===----------------------------------------------------------------------===//
/// DwarfException - Emits Dwarf exception handling directives.
///
-class VISIBILITY_HIDDEN DwarfException : public Dwarf {
+class DwarfException : public Dwarf {
struct FunctionEHFrameInfo {
std::string FnName;
unsigned Number;
@@ -155,6 +156,10 @@ class VISIBILITY_HIDDEN DwarfException : public Dwarf {
SmallVectorImpl<ActionEntry> &Actions,
SmallVectorImpl<unsigned> &FirstActions);
+ /// CallToNoUnwindFunction - Return `true' if this is a call to a function
+ /// marked `nounwind'. Return `false' otherwise.
+ bool CallToNoUnwindFunction(const MachineInstr *MI);
+
/// ComputeCallSiteTable - Compute the call-site table. The entry for an
/// invoke has a try-range containing the call, a non-zero landing pad and an
/// appropriate action. The entry for an ordinary call has a try-range
@@ -168,6 +173,11 @@ class VISIBILITY_HIDDEN DwarfException : public Dwarf {
const SmallVectorImpl<unsigned> &FirstActions);
void EmitExceptionTable();
+ /// CreateLabelDiff - Emit a label and subtract it from the expression we
+ /// already have. This is equivalent to emitting "foo - .", but we have to
+ /// emit the label for "." directly.
+ const MCExpr *CreateLabelDiff(const MCExpr *ExprRef, const char *LabelName,
+ unsigned Index);
public:
//===--------------------------------------------------------------------===//
// Main entry points.
diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h
index 33ebb3b..dedd695 100644
--- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h
+++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.h
@@ -29,7 +29,7 @@ namespace llvm {
class TargetData;
class TargetRegisterInfo;
- class VISIBILITY_HIDDEN Dwarf {
+ class Dwarf {
protected:
//===-------------------------------------------------------------==---===//
// Core attributes used by the DWARF printer.
diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
index 0638d35..63ae653 100644
--- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
@@ -81,47 +81,20 @@ unsigned DwarfWriter::RecordSourceLine(unsigned Line, unsigned Col,
return DD->RecordSourceLine(Line, Col, Scope);
}
-/// RecordRegionStart - Indicate the start of a region.
-unsigned DwarfWriter::RecordRegionStart(MDNode *N) {
- return DD->RecordRegionStart(N);
-}
-
-/// RecordRegionEnd - Indicate the end of a region.
-unsigned DwarfWriter::RecordRegionEnd(MDNode *N) {
- return DD->RecordRegionEnd(N);
-}
-
/// getRecordSourceLineCount - Count source lines.
unsigned DwarfWriter::getRecordSourceLineCount() {
return DD->getRecordSourceLineCount();
}
-/// RecordVariable - Indicate the declaration of a local variable.
-///
-void DwarfWriter::RecordVariable(MDNode *N, unsigned FrameIndex) {
- DD->RecordVariable(N, FrameIndex);
-}
-
/// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should
/// be emitted.
bool DwarfWriter::ShouldEmitDwarfDebug() const {
return DD && DD->ShouldEmitDwarfDebug();
}
-//// RecordInlinedFnStart
-unsigned DwarfWriter::RecordInlinedFnStart(DISubprogram SP, DICompileUnit CU,
- unsigned Line, unsigned Col) {
- return DD->RecordInlinedFnStart(SP, CU, Line, Col);
-}
-
-/// RecordInlinedFnEnd - Indicate the end of inlined subroutine.
-unsigned DwarfWriter::RecordInlinedFnEnd(DISubprogram SP) {
- return DD->RecordInlinedFnEnd(SP);
-}
-
-void DwarfWriter::SetDbgScopeBeginLabels(const MachineInstr *MI, unsigned L) {
- DD->SetDbgScopeEndLabels(MI, L);
+void DwarfWriter::BeginScope(const MachineInstr *MI, unsigned L) {
+ DD->BeginScope(MI, L);
}
-void DwarfWriter::SetDbgScopeEndLabels(const MachineInstr *MI, unsigned L) {
- DD->SetDbgScopeBeginLabels(MI, L);
+void DwarfWriter::EndScope(const MachineInstr *MI) {
+ DD->EndScope(MI);
}
OpenPOWER on IntegriCloud