diff options
-rw-r--r-- | include/llvm/CodeGen/DwarfWriter.h | 7 | ||||
-rw-r--r-- | include/llvm/Target/TargetAsmInfo.h | 16 | ||||
-rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfWriter.cpp | 130 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/FastISel.cpp | 18 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp | 22 | ||||
-rw-r--r-- | lib/Target/TargetAsmInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Target/X86/X86TargetAsmInfo.cpp | 2 |
7 files changed, 190 insertions, 7 deletions
diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h index 8e82718..e7d9266 100644 --- a/include/llvm/CodeGen/DwarfWriter.h +++ b/include/llvm/CodeGen/DwarfWriter.h @@ -94,6 +94,9 @@ public: /// RecordRegionStart - Indicate the start of a region. unsigned RecordRegionStart(GlobalVariable *V); + /// RecordRegionStart - Indicate the start of a region. + unsigned RecordRegionStart(GlobalVariable *V, unsigned ID); + /// RecordRegionEnd - Indicate the end of a region. unsigned RecordRegionEnd(GlobalVariable *V); @@ -107,6 +110,10 @@ public: /// ShouldEmitDwarfDebug - Returns true if Dwarf debugging declarations should /// be emitted. bool ShouldEmitDwarfDebug() const; + + //// RecordInlineInfo - Global variable GV is inlined at the location marked + //// by LabelID label. + void RecordInlineInfo(GlobalVariable *GV, unsigned LabelID); }; diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h index b871009..e493538 100644 --- a/include/llvm/Target/TargetAsmInfo.h +++ b/include/llvm/Target/TargetAsmInfo.h @@ -463,6 +463,10 @@ namespace llvm { /// bool DwarfRequiresFrameSection; // Defaults to true. + /// DwarfUsesInlineInfoSection - True if DwarfDebugInlineSection is used to + /// encode inline subroutine information. + bool DwarfUsesInlineInfoSection; // Defaults to false. + /// SupportsMacInfo - true if the Dwarf output supports macro information /// bool SupportsMacInfoSection; // Defaults to true @@ -506,7 +510,11 @@ namespace llvm { /// DwarfPubTypesSection - Section directive for Dwarf info. /// const char *DwarfPubTypesSection; // Defaults to ".debug_pubtypes". - + + /// DwarfDebugInlineSection - Section directive for inline info. + /// + const char *DwarfDebugInlineSection; // Defaults to ".debug_inlined" + /// DwarfStrSection - Section directive for Dwarf info. /// const char *DwarfStrSection; // Defaults to ".debug_str". @@ -847,6 +855,9 @@ namespace llvm { bool doesDwarfRequireFrameSection() const { return DwarfRequiresFrameSection; } + bool doesDwarfUsesInlineInfoSection() const { + return DwarfUsesInlineInfoSection; + } bool doesSupportMacInfoSection() const { return SupportsMacInfoSection; } @@ -880,6 +891,9 @@ namespace llvm { const char *getDwarfPubTypesSection() const { return DwarfPubTypesSection; } + const char *getDwarfDebugInlineSection() const { + return DwarfDebugInlineSection; + } const char *getDwarfStrSection() const { return DwarfStrSection; } diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp index 4582f4a..c619bc5 100644 --- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp @@ -1252,6 +1252,10 @@ class DwarfDebug : public Dwarf { /// DbgScopeMap - Tracks the scopes in the current function. DenseMap<GlobalVariable *, DbgScope *> DbgScopeMap; + /// InlineInfo - Keep track of inlined functions and their location. + /// This information is used to populate debug_inlined section. + DenseMap<GlobalVariable *, SmallVector<unsigned, 4> > InlineInfo; + /// DebugTimer - Timer for the Dwarf debug writer. Timer *DebugTimer; @@ -2027,15 +2031,18 @@ private: for (unsigned j = 0, M = Scopes.size(); j < M; ++j) { // Define the Scope debug information entry. DbgScope *Scope = Scopes[j]; - // FIXME - Ignore inlined functions for the time being. - if (!Scope->getParent()) continue; unsigned StartID = MMI->MappedLabel(Scope->getStartLabelID()); unsigned EndID = MMI->MappedLabel(Scope->getEndLabelID()); // Ignore empty scopes. if (StartID == EndID && StartID != 0) continue; - if (Scope->getScopes().empty() && Scope->getVariables().empty()) continue; + + // Do not ignore inlined scope even if it is empty. Inlined scope + // does not have any parent. + if (Scope->getParent() + && Scope->getScopes().empty() && Scope->getVariables().empty()) + continue; if (StartID == ParentStartID && EndID == ParentEndID) { // Just add stuff to the parent scope. @@ -2781,6 +2788,77 @@ private: } } + /// EmitDebugInlineInfo - Emit inline info using following format. + /// Section Header: + /// 1. length of section + /// 2. Dwarf version number + /// 3. address size. + /// + /// Entries (one "entry" for each function that was inlined): + /// + /// 1. offset into __debug_str section for MIPS linkage name, if exists; + /// otherwise offset into __debug_str for regular function name. + /// 2. offset into __debug_str section for regular function name. + /// 3. an unsigned LEB128 number indicating the number of distinct inlining + /// instances for the function. + /// + /// The rest of the entry consists of a {die_offset, low_pc} pair for each + /// inlined instance; the die_offset points to the inlined_subroutine die in + /// the __debug_info section, and the low_pc is the starting address for the + /// inlining instance. + void EmitDebugInlineInfo() { + if (!TAI->doesDwarfUsesInlineInfoSection()) + return; + + if (!MainCU) + return; + + Asm->SwitchToDataSection(TAI->getDwarfDebugInlineSection()); + Asm->EOL(); + EmitDifference("debug_inlined_end", 1, + "debug_inlined_begin", 1, true); + Asm->EOL("Length of Debug Inlined Information Entry"); + + EmitLabel("debug_inlined_begin", 1); + + Asm->EmitInt16(DWARF_VERSION); Asm->EOL("Dwarf Version"); + Asm->EmitInt8(TD->getPointerSize()); Asm->EOL("Address Size (in bytes)"); + + for (DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator + I = InlineInfo.begin(), E = InlineInfo.end(); I != E; ++I) { + GlobalVariable *GV = I->first; + SmallVector<unsigned, 4> &Labels = I->second; + DISubprogram SP(GV); + std::string Name; + std::string LName; + + SP.getLinkageName(LName); + SP.getName(Name); + + Asm->EmitString(LName.empty() ? Name : LName); + Asm->EOL("MIPS linkage name"); + + Asm->EmitString(Name); Asm->EOL("Function name"); + + Asm->EmitULEB128Bytes(Labels.size()); Asm->EOL("Inline count"); + + for (SmallVector<unsigned, 4>::iterator LI = Labels.begin(), + LE = Labels.end(); LI != LE; ++LI) { + DIE *SP = MainCU->getDieMapSlotFor(GV); + Asm->EmitInt32(SP->getOffset()); Asm->EOL("DIE offset"); + + if (TD->getPointerSize() == sizeof(int32_t)) + O << TAI->getData32bitsDirective(); + else + O << TAI->getData64bitsDirective(); + PrintLabelName("label", *LI); Asm->EOL("low_pc"); + } + } + + EmitLabel("debug_inlined_end", 1); + Asm->EOL(); + } + /// GetOrCreateSourceID - Look up the source id with the given directory and /// source file names. If none currently exists, create a new id and insert it /// in the SourceIds map. This can update DirectoryNames and SourceFileNames maps @@ -3131,6 +3209,9 @@ public: // Emit info into a debug macinfo section. EmitDebugMacInfo(); + // Emit inline info. + EmitDebugInlineInfo(); + if (TimePassesIsEnabled) DebugTimer->stopTimer(); } @@ -3337,6 +3418,20 @@ public: return ID; } + /// RecordRegionStart - Indicate the start of a region. + unsigned RecordRegionStart(GlobalVariable *V, unsigned ID) { + if (TimePassesIsEnabled) + DebugTimer->startTimer(); + + DbgScope *Scope = getOrCreateScope(V); + if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID); + + if (TimePassesIsEnabled) + DebugTimer->stopTimer(); + + return ID; + } + /// RecordRegionEnd - Indicate the end of a region. unsigned RecordRegionEnd(GlobalVariable *V) { if (TimePassesIsEnabled) @@ -3377,6 +3472,23 @@ public: if (TimePassesIsEnabled) DebugTimer->stopTimer(); } + + //// RecordInlineInfo - Global variable GV is inlined at the location marked + //// by LabelID label. + void RecordInlineInfo(GlobalVariable *GV, unsigned LabelID) { + MMI->RecordUsedDbgLabel(LabelID); + DenseMap<GlobalVariable *, SmallVector<unsigned, 4> >::iterator + I = InlineInfo.find(GV); + if (I == InlineInfo.end()) { + SmallVector<unsigned, 4> Labels; + Labels.push_back(LabelID); + InlineInfo[GV] = Labels; + return; + } + + SmallVector<unsigned, 4> &Labels = I->second; + Labels.push_back(LabelID); + } }; //===----------------------------------------------------------------------===// @@ -4535,6 +4647,11 @@ unsigned DwarfWriter::RecordRegionStart(GlobalVariable *V) { return DD->RecordRegionStart(V); } +/// RecordRegionStart - Indicate the start of a region. +unsigned DwarfWriter::RecordRegionStart(GlobalVariable *V, unsigned ID) { + return DD->RecordRegionStart(V, ID); +} + /// RecordRegionEnd - Indicate the end of a region. unsigned DwarfWriter::RecordRegionEnd(GlobalVariable *V) { return DD->RecordRegionEnd(V); @@ -4556,3 +4673,10 @@ void DwarfWriter::RecordVariable(GlobalVariable *GV, unsigned FrameIndex) { bool DwarfWriter::ShouldEmitDwarfDebug() const { return DD->ShouldEmitDwarfDebug(); } + +//// RecordInlineInfo - Global variable GV is inlined at the location marked +//// by LabelID label. +void DwarfWriter::RecordInlineInfo(GlobalVariable *GV, unsigned LabelID) { + DD->RecordInlineInfo(GV, LabelID); +} + diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 251e96a..cc425e5 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -377,11 +377,23 @@ bool FastISel::SelectCall(User *I) { // Record the source line. unsigned Line = Subprogram.getLineNumber(); - DW->RecordSourceLine(Line, 0, SrcFile); + unsigned LabelID = DW->RecordSourceLine(Line, 0, SrcFile); setCurDebugLoc(DebugLoc::get(MF.getOrCreateDebugLocID(SrcFile, Line, 0))); - // llvm.dbg.func_start also defines beginning of function scope. - DW->RecordRegionStart(cast<GlobalVariable>(FSI->getSubprogram())); + std::string SPName; + Subprogram.getLinkageName(SPName); + if (!SPName.empty() + && strcmp(SPName.c_str(), MF.getFunction()->getNameStart())) { + // This is a beginning of inlined function. + DW->RecordRegionStart(cast<GlobalVariable>(FSI->getSubprogram()), + LabelID); + const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); + BuildMI(MBB, DL, II).addImm(LabelID); + DW->RecordInlineInfo(Subprogram.getGV(), LabelID); + } else { + // llvm.dbg.func_start also defines beginning of function scope. + DW->RecordRegionStart(cast<GlobalVariable>(FSI->getSubprogram())); + } } return true; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index effb215..b596643 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -3955,6 +3955,18 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { DwarfWriter *DW = DAG.getDwarfWriter(); DbgRegionEndInst &REI = cast<DbgRegionEndInst>(I); if (DW && DW->ValidDebugInfo(REI.getContext())) { + + MachineFunction &MF = DAG.getMachineFunction(); + DISubprogram Subprogram(cast<GlobalVariable>(REI.getContext())); + std::string SPName; + Subprogram.getLinkageName(SPName); + if (!SPName.empty() + && strcmp(SPName.c_str(), MF.getFunction()->getNameStart())) { + // This is end of inlined function. Debugging information for + // inlined function is not handled yet (only supported by FastISel). + return 0; + } + unsigned LabelID = DW->RecordRegionEnd(cast<GlobalVariable>(REI.getContext())); if (Fast) @@ -3974,6 +3986,16 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { // what (most?) gdb expects. MachineFunction &MF = DAG.getMachineFunction(); DISubprogram Subprogram(cast<GlobalVariable>(SP)); + + std::string SPName; + Subprogram.getLinkageName(SPName); + if (!SPName.empty() + && strcmp(SPName.c_str(), MF.getFunction()->getNameStart())) { + // This is beginning of inlined function. Debugging information for + // inlined function is not handled yet (only supported by FastISel). + return 0; + } + DICompileUnit CompileUnit = Subprogram.getCompileUnit(); std::string Dir, FN; unsigned SrcFile = DW->getOrCreateSourceID(CompileUnit.getDirectory(Dir), diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp index 4d9ec33..6a2de6f 100644 --- a/lib/Target/TargetAsmInfo.cpp +++ b/lib/Target/TargetAsmInfo.cpp @@ -101,6 +101,7 @@ void TargetAsmInfo::fillDefaultValues() { SupportsDebugInformation = false; SupportsExceptionHandling = false; DwarfRequiresFrameSection = true; + DwarfUsesInlineInfoSection = false; SupportsMacInfoSection = true; NonLocalEHFrameLabel = false; GlobalEHDirective = 0; @@ -112,6 +113,7 @@ void TargetAsmInfo::fillDefaultValues() { DwarfFrameSection = ".debug_frame"; DwarfPubNamesSection = ".debug_pubnames"; DwarfPubTypesSection = ".debug_pubtypes"; + DwarfDebugInlineSection = ".debug_inlined"; DwarfStrSection = ".debug_str"; DwarfLocSection = ".debug_loc"; DwarfARangesSection = ".debug_aranges"; diff --git a/lib/Target/X86/X86TargetAsmInfo.cpp b/lib/Target/X86/X86TargetAsmInfo.cpp index f1d97a3..5dda5f4 100644 --- a/lib/Target/X86/X86TargetAsmInfo.cpp +++ b/lib/Target/X86/X86TargetAsmInfo.cpp @@ -112,6 +112,8 @@ X86DarwinTargetAsmInfo::X86DarwinTargetAsmInfo(const X86TargetMachine &TM): DwarfFrameSection = ".section __DWARF,__debug_frame,regular,debug"; DwarfPubNamesSection = ".section __DWARF,__debug_pubnames,regular,debug"; DwarfPubTypesSection = ".section __DWARF,__debug_pubtypes,regular,debug"; + DwarfDebugInlineSection = ".section __DWARF,__debug_inlined,regular,debug"; + DwarfUsesInlineInfoSection = true; DwarfStrSection = ".section __DWARF,__debug_str,regular,debug"; DwarfLocSection = ".section __DWARF,__debug_loc,regular,debug"; DwarfARangesSection = ".section __DWARF,__debug_aranges,regular,debug"; |