diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 153 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DIE.h | 24 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 1020 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfDebug.h | 122 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.cpp | 89 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfException.h | 12 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfPrinter.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfWriter.cpp | 35 |
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); } |