This patch adds basic debug info support with basic block sections.
authorKrzysztof Pszeniczny <krzysztof.pszeniczny@gmail.com>
Thu, 2 Jul 2020 06:47:30 +0000 (23:47 -0700)
committerSriraman Tallam <tmsriram@google.com>
Thu, 2 Jul 2020 06:53:00 +0000 (23:53 -0700)
This patch uses ranges for debug information when a function contains basic block sections rather than using [lowpc, highpc]. This is also the first in a series of patches for debug info and does not contain the support for linker relaxation. That will be done as a follow up patch.

Differential Revision: https://reviews.llvm.org/D78851

llvm/include/llvm/CodeGen/AsmPrinter.h
llvm/include/llvm/CodeGen/AsmPrinterHandler.h
llvm/include/llvm/CodeGen/DebugHandlerBase.h
llvm/include/llvm/CodeGen/MachineBasicBlock.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
llvm/test/DebugInfo/X86/basicblock-sections_1.ll [new file with mode: 0644]

index eb313ac..0eb9508 100644 (file)
@@ -126,6 +126,14 @@ public:
   /// default, this is equal to CurrentFnSym.
   MCSymbol *CurrentFnSymForSize = nullptr;
 
+  /// Map a basic block section ID to the begin and end symbols of that section
+  ///  which determine the section's range.
+  struct MBBSectionRange {
+    MCSymbol *BeginLabel, *EndLabel;
+  };
+
+  MapVector<unsigned, MBBSectionRange> MBBSectionRanges;
+
   /// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of
   /// its number of uses by other globals.
   using GOTEquivUsePair = std::pair<const GlobalVariable *, unsigned>;
index affb558..899d067 100644 (file)
@@ -67,6 +67,12 @@ public:
 
   /// Process end of an instruction.
   virtual void endInstruction() = 0;
+
+  /// Process beginning of a basic block during basic block sections.
+  virtual void beginBasicBlock(const MachineBasicBlock &MBB) {}
+
+  /// Process end of a basic block during basic block sections.
+  virtual void endBasicBlock(const MachineBasicBlock &MBB) {}
 };
 } // End of namespace llvm
 
index 06a3c85..4ff0fde 100644 (file)
@@ -118,6 +118,9 @@ public:
   void beginFunction(const MachineFunction *MF) override;
   void endFunction(const MachineFunction *MF) override;
 
+  void beginBasicBlock(const MachineBasicBlock &MBB) override;
+  void endBasicBlock(const MachineBasicBlock &MBB) override;
+
   /// Return Label preceding the instruction.
   MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
 
index 412f75a..d6cb721 100644 (file)
@@ -465,6 +465,12 @@ public:
   /// Returns the section ID of this basic block.
   MBBSectionID getSectionID() const { return SectionID; }
 
+  /// Returns the unique section ID number of this basic block.
+  unsigned getSectionIDNum() const {
+    return ((unsigned)MBBSectionID::SectionType::Cold) -
+           ((unsigned)SectionID.Type) + SectionID.Number;
+  }
+
   /// Sets the section ID for this basic block.
   void setSectionID(MBBSectionID V) { SectionID = V; }
 
index a5dffdb..98b047d 100644 (file)
@@ -1207,6 +1207,8 @@ void AsmPrinter::emitFunctionBody() {
       if (!MBB.sameSection(&MF->front())) {
         if (MAI->hasDotTypeDotSizeDirective())
           emitELFSizeDirective(CurrentSectionBeginSym);
+        MBBSectionRanges[MBB.getSectionIDNum()] =
+            MBBSectionRange{CurrentSectionBeginSym, CurrentBBEnd};
       }
     }
     emitBasicBlockEnd(MBB);
@@ -1283,6 +1285,8 @@ void AsmPrinter::emitFunctionBody() {
     HI.Handler->markFunctionEnd();
   }
 
+  MBBSectionRanges[MF->front().getSectionIDNum()] =
+      MBBSectionRange{CurrentFnBegin, CurrentFnEnd};
 
   // Print out jump tables referenced by the function.
   emitJumpTableInfo();
@@ -1782,6 +1786,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
   CurrentFnSymForSize = CurrentFnSym;
   CurrentFnBegin = nullptr;
   CurrentSectionBeginSym = nullptr;
+  MBBSectionRanges.clear();
   CurExceptionSym = nullptr;
   bool NeedsLocalForSize = MAI->needsLocalForSize();
   if (F.hasFnAttribute("patchable-function-entry") ||
index 9f0781d..880791a 100644 (file)
@@ -327,3 +327,17 @@ void DebugHandlerBase::endFunction(const MachineFunction *MF) {
   LabelsBeforeInsn.clear();
   LabelsAfterInsn.clear();
 }
+
+void DebugHandlerBase::beginBasicBlock(const MachineBasicBlock &MBB) {
+  if (!MBB.isBeginSection())
+    return;
+
+  PrevLabel = MBB.getSymbol();
+}
+
+void DebugHandlerBase::endBasicBlock(const MachineBasicBlock &MBB) {
+  if (!MBB.isEndSection())
+    return;
+
+  PrevLabel = nullptr;
+}
index c04d9f7..296c380 100644 (file)
@@ -396,7 +396,14 @@ void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin,
 DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
   DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes());
 
-  attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd());
+  SmallVector<RangeSpan, 2> BB_List;
+  // If basic block sections are on, ranges for each basic block section has
+  // to be emitted separately.
+  for (const auto &R : Asm->MBBSectionRanges)
+    BB_List.push_back({R.second.BeginLabel, R.second.EndLabel});
+
+  attachRangesOrLowHighPC(*SPDie, BB_List);
+
   if (DD->useAppleExtensionAttributes() &&
       !DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim(
           *DD->getCurrentFunction()))
@@ -570,9 +577,33 @@ void DwarfCompileUnit::attachRangesOrLowHighPC(
     DIE &Die, const SmallVectorImpl<InsnRange> &Ranges) {
   SmallVector<RangeSpan, 2> List;
   List.reserve(Ranges.size());
-  for (const InsnRange &R : Ranges)
-    List.push_back(
-        {DD->getLabelBeforeInsn(R.first), DD->getLabelAfterInsn(R.second)});
+  for (const InsnRange &R : Ranges) {
+    auto *BeginLabel = DD->getLabelBeforeInsn(R.first);
+    auto *EndLabel = DD->getLabelAfterInsn(R.second);
+
+    const auto *BeginMBB = R.first->getParent();
+    const auto *EndMBB = R.second->getParent();
+
+    const auto *MBB = BeginMBB;
+    // Basic block sections allows basic block subsets to be placed in unique
+    // sections. For each section, the begin and end label must be added to the
+    // list. If there is more than one range, debug ranges must be used.
+    // Otherwise, low/high PC can be used.
+    // FIXME: Debug Info Emission depends on block order and this assumes that
+    // the order of blocks will be frozen beyond this point.
+    do {
+      if (MBB->sameSection(EndMBB) || MBB->isEndSection()) {
+        auto MBBSectionRange = Asm->MBBSectionRanges[MBB->getSectionIDNum()];
+        List.push_back(
+            {MBB->sameSection(BeginMBB) ? BeginLabel
+                                        : MBBSectionRange.BeginLabel,
+             MBB->sameSection(EndMBB) ? EndLabel : MBBSectionRange.EndLabel});
+      }
+      if (MBB->sameSection(EndMBB))
+        break;
+      MBB = MBB->getNextNode();
+    } while (true);
+  }
   attachRangesOrLowHighPC(Die, std::move(List));
 }
 
index 870b848..80935f8 100644 (file)
@@ -1664,7 +1664,8 @@ bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
 
     const MCSymbol *EndLabel;
     if (std::next(EI) == Entries.end()) {
-      EndLabel = Asm->getFunctionEnd();
+      const MachineBasicBlock &EndMBB = Asm->MF->back();
+      EndLabel = Asm->MBBSectionRanges[EndMBB.getSectionIDNum()].EndLabel;
       if (EI->isClobber())
         EndMI = EI->getInstr();
     }
@@ -2115,7 +2116,9 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
   collectEntityInfo(TheCU, SP, Processed);
 
   // Add the range of this function to the list of ranges for the CU.
-  TheCU.addRange({Asm->getFunctionBegin(), Asm->getFunctionEnd()});
+  // With basic block sections, add ranges for all basic block sections.
+  for (const auto &R : Asm->MBBSectionRanges)
+    TheCU.addRange({R.second.BeginLabel, R.second.EndLabel});
 
   // Under -gmlt, skip building the subprogram if there are no inlined
   // subroutines inside it. But with -fdebug-info-for-profiling, the subprogram
diff --git a/llvm/test/DebugInfo/X86/basicblock-sections_1.ll b/llvm/test/DebugInfo/X86/basicblock-sections_1.ll
new file mode 100644 (file)
index 0000000..f3bedd9
--- /dev/null
@@ -0,0 +1,97 @@
+; RUN: llc -O0 %s -mtriple=x86_64-* -filetype=obj -o %t && llvm-dwarfdump  -debug-info -v %t | FileCheck --check-prefix=NO-SECTIONS %s
+; RUN: llc -O0 %s --basicblock-sections=all --unique-bb-section-names -mtriple=x86_64-* -filetype=obj -o %t && llvm-dwarfdump  -debug-info -v %t | FileCheck --check-prefix=BB-SECTIONS %s
+; RUN: llc -O0 %s --basicblock-sections=all --unique-bb-section-names -mtriple=x86_64-* -filetype=obj -split-dwarf-file=%t.dwo -o %t && llvm-dwarfdump  -debug-info -v %t | FileCheck --check-prefix=BB-SECTIONS %s
+; RUN: llc -O0 %s --basicblock-sections=all -mtriple=x86_64-* -filetype=asm -o - | FileCheck --check-prefix=BB-SECTIONS-ASM %s
+
+; From:
+; int foo(int a) {
+;   if (a > 20)
+;     return 2;
+;   else
+;     return 0;
+; }
+
+; NO-SECTIONS: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000 ".text")
+; NO-SECTIONS: DW_AT_high_pc [DW_FORM_data4] ({{.*}})
+; BB-SECTIONS: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
+; BB-SECTIONS-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
+; BB-SECTIONS-NEXT: [{{.*}}) ".text._Z3fooi.1"
+; BB-SECTIONS-NEXT: [{{.*}}) ".text._Z3fooi.2"
+; BB-SECTIONS-NEXT: [{{.*}}) ".text._Z3fooi.3"
+; BB-SECTIONS-NEXT: [{{.*}}) ".text"
+; BB-SECTIONS-ASM: _Z3fooi:
+; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
+; BB-SECTIONS-ASM-NEXT: .loc 1 2 9 prologue_end
+; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
+; BB-SECTIONS-ASM-NEXT: .loc 1 2 7 is_stmt
+; BB-SECTIONS-ASM: _Z3fooi.1:
+; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
+; BB-SECTIONS-ASM: .size       _Z3fooi.1, .Ltmp{{[0-9]+}}-_Z3fooi.1
+; BB-SECTIONS-ASM: _Z3fooi.2:
+; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
+; BB-SECTIONS-ASM-NEXT: .Ltmp{{[0-9]+}}:
+; BB-SECTIONS-ASM: .size       _Z3fooi.2, .Ltmp{{[0-9]+}}-_Z3fooi.2
+; BB-SECTIONS-ASM: _Z3fooi.3:
+; BB-SECTIONS-ASM: .Ltmp{{[0-9]+}}:
+; BB-SECTIONS-ASM-NEXT: .Ltmp{{[0-9]+}}:
+; BB-SECTIONS-ASM: .size       _Z3fooi.3, .Ltmp{{[0-9]+}}-_Z3fooi.3
+; BB-SECTIONS-ASM: .Lfunc_end0:
+; BB-SECTIONS-ASM: .Ldebug_ranges0:
+; BB-SECTIONS-ASM-NEXT:        .quad   _Z3fooi.1
+; BB-SECTIONS-ASM-NEXT:        .quad   .Ltmp{{[0-9]+}}
+; BB-SECTIONS-ASM-NEXT:        .quad   _Z3fooi.2
+; BB-SECTIONS-ASM-NEXT:        .quad   .Ltmp{{[0-9]+}}
+; BB-SECTIONS-ASM-NEXT:        .quad   _Z3fooi.3
+; BB-SECTIONS-ASM-NEXT:        .quad   .Ltmp{{[0-9]+}}
+; BB-SECTIONS-ASM-NEXT:        .quad   .Lfunc_begin0
+; BB-SECTIONS-ASM-NEXT:        .quad   .Lfunc_end0
+; BB-SECTIONS-ASM-NEXT:        .quad   0
+; BB-SECTIONS-ASM-NEXT:        .quad   0
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local i32 @_Z3fooi(i32 %0) !dbg !7 {
+  %2 = alloca i32, align 4
+  %3 = alloca i32, align 4
+  store i32 %0, i32* %3, align 4
+  call void @llvm.dbg.declare(metadata i32* %3, metadata !11, metadata !DIExpression()), !dbg !12
+  %4 = load i32, i32* %3, align 4, !dbg !13
+  %5 = icmp sgt i32 %4, 20, !dbg !15
+  br i1 %5, label %6, label %7, !dbg !16
+
+6:                                                ; preds = %1
+  store i32 2, i32* %2, align 4, !dbg !17
+  br label %8, !dbg !17
+
+7:                                                ; preds = %1
+  store i32 0, i32* %2, align 4, !dbg !18
+  br label %8, !dbg !18
+
+8:                                                ; preds = %7, %6
+  %9 = load i32, i32* %2, align 4, !dbg !19
+  ret i32 %9, !dbg !19
+}
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 10.0.0 (git@github.com:google/llvm-propeller.git f9421ebf4b3d8b64678bf6c49d1607fdce3f50c5)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "debuginfo.cc", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 1, type: !10)
+!12 = !DILocation(line: 1, column: 13, scope: !7)
+!13 = !DILocation(line: 2, column: 7, scope: !14)
+!14 = distinct !DILexicalBlock(scope: !7, file: !1, line: 2, column: 7)
+!15 = !DILocation(line: 2, column: 9, scope: !14)
+!16 = !DILocation(line: 2, column: 7, scope: !7)
+!17 = !DILocation(line: 3, column: 5, scope: !14)
+!18 = !DILocation(line: 5, column: 5, scope: !14)
+!19 = !DILocation(line: 6, column: 1, scope: !7)