[llvm] r197776 - Add support for a CU to output a set of ranges for the CU. This is useful

Eric Christopher echristo at gmail.com
Thu Dec 19 20:16:18 PST 2013


Author: echristo
Date: Thu Dec 19 22:16:18 2013
New Revision: 197776

URL: http://llvm.org/viewvc/llvm-project?rev=197776&view=rev
Log:
Add support for a CU to output a set of ranges for the CU. This is useful
when you want to have the full list of addresses for a particular CU or
when you have multiple modules linked together and can't depend upon the
ordering of a single CU for begin/end ranges.

Added:
    llvm/trunk/test/DebugInfo/cu-ranges.ll
Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=197776&r1=197775&r2=197776&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Thu Dec 19 22:16:18 2013
@@ -108,6 +108,11 @@ static cl::opt<unsigned>
 DwarfVersionNumber("dwarf-version", cl::Hidden,
                    cl::desc("Generate DWARF for dwarf version."), cl::init(0));
 
+static cl::opt<bool>
+DwarfCURanges("generate-dwarf-cu-ranges", cl::Hidden,
+              cl::desc("Generate DW_AT_ranges for compile units"),
+              cl::init(false));
+
 static const char *const DWARFGroupName = "DWARF Emission";
 static const char *const DbgTimerName = "DWARF Debug Writer";
 
@@ -426,6 +431,10 @@ DIE *DwarfDebug::updateSubprogramScopeDI
   SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc, FunctionBeginSym);
   SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc, FunctionEndSym);
 
+  // Add this range to the list of ranges for the CU.
+  RangeSpan Span(FunctionBeginSym, FunctionEndSym);
+  SPCU->addRange(llvm_move(Span));
+
   const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
   MachineLocation Location(RI->getFrameRegister(*Asm->MF));
   SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
@@ -1070,24 +1079,32 @@ void DwarfDebug::finalizeModuleInfo() {
     // vtable holding type.
     TheU->constructContainingTypeDIEs();
 
-    // If we're splitting the dwarf out now that we've got the entire
-    // CU then construct a skeleton CU based upon it.
-    if (useSplitDwarf() &&
-        TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) {
-      uint64_t ID = 0;
-      if (GenerateCUHash) {
-        DIEHash CUHash;
-        ID = CUHash.computeCUSignature(*TheU->getUnitDie());
+    // Add CU specific attributes if we need to add any.
+    if (TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) {
+      // If we're splitting the dwarf out now that we've got the entire
+      // CU then construct a skeleton CU based upon it.
+      if (useSplitDwarf()) {
+        // This should be a unique identifier when we want to build .dwp files.
+        uint64_t ID = 0;
+        if (GenerateCUHash) {
+          DIEHash CUHash;
+          ID = CUHash.computeCUSignature(*TheU->getUnitDie());
+        }
+        TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
+                      dwarf::DW_FORM_data8, ID);
+        // Now construct the skeleton CU associated.
+        DwarfCompileUnit *SkCU =
+            constructSkeletonCU(static_cast<DwarfCompileUnit *>(TheU));
+        SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
+                      dwarf::DW_FORM_data8, ID);
+      } else {
+        // Attribute if we've emitted a range list for the compile unit, this
+        // will get constructed for the skeleton CU separately if we have one.
+        if (DwarfCURanges && TheU->getRanges().size())
+          addSectionLabel(Asm, TheU, TheU->getUnitDie(), dwarf::DW_AT_ranges,
+                          Asm->GetTempSymbol("cu_ranges", TheU->getUniqueID()),
+                          DwarfDebugRangeSectionSym);
       }
-      // This should be a unique identifier when we want to build .dwp files.
-      TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
-                    dwarf::DW_FORM_data8, ID);
-      // Now construct the skeleton CU associated.
-      DwarfCompileUnit *SkCU =
-          constructSkeletonCU(static_cast<DwarfCompileUnit *>(TheU));
-      // This should be a unique identifier when we want to build .dwp files.
-      SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
-                    dwarf::DW_FORM_data8, ID);
     }
   }
 
@@ -2935,6 +2952,28 @@ void DwarfDebug::emitDebugRanges() {
       Asm->OutStreamer.EmitIntValue(0, Size);
       Asm->OutStreamer.EmitIntValue(0, Size);
     }
+
+    // Now emit a range for the CU itself.
+    if (DwarfCURanges) {
+      Asm->OutStreamer.EmitLabel(
+          Asm->GetTempSymbol("cu_ranges", TheCU->getUniqueID()));
+      const SmallVectorImpl<RangeSpan> &Ranges = TheCU->getRanges();
+      for (uint32_t i = 0, e = Ranges.size(); i != e; ++i) {
+        RangeSpan Range = Ranges[i];
+
+        // We occasionally have ranges without begin/end labels.
+        // FIXME: Verify and fix.
+        const MCSymbol *Begin = Range.getStart();
+        const MCSymbol *End = Range.getEnd();
+        Begin ? Asm->OutStreamer.EmitSymbolValue(Begin, Size)
+              : Asm->OutStreamer.EmitIntValue(0, Size);
+        End ? Asm->OutStreamer.EmitSymbolValue(End, Size)
+            : Asm->OutStreamer.EmitIntValue(0, Size);
+      }
+      // And terminate the list with two 0 values.
+      Asm->OutStreamer.EmitIntValue(0, Size);
+      Asm->OutStreamer.EmitIntValue(0, Size);
+    }
   }
 }
 
@@ -2963,9 +3002,14 @@ DwarfCompileUnit *DwarfDebug::constructS
   else
     NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0);
 
-  // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
-  // into an entity. We're using 0, or a NULL label for this.
-  NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
+  // Attribute if we've emitted a range list for the compile unit, this
+  // will get constructed for the skeleton CU separately if we have one.
+  if (DwarfCURanges && CU->getRanges().size())
+    addSectionLabel(Asm, NewCU, Die, dwarf::DW_AT_ranges,
+                    Asm->GetTempSymbol("cu_ranges", CU->getUniqueID()),
+                    DwarfDebugRangeSectionSym);
+  else
+    NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
 
   // DW_AT_stmt_list is a offset of line number information for this
   // compile unit in debug_line section.

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h?rev=197776&r1=197775&r2=197776&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h Thu Dec 19 22:16:18 2013
@@ -118,6 +118,9 @@ protected:
   /// corresponds to the MDNode mapped with the subprogram DIE.
   DenseMap<DIE *, const MDNode *> ContainingTypeMap;
 
+  // List of ranges for a given compile unit.
+  SmallVector<RangeSpan, 1> CURanges;
+
   // List of range lists for a given compile unit, separate from the ranges for
   // the CU itself.
   SmallVector<RangeSpanList, 1> CURangeLists;
@@ -216,6 +219,13 @@ public:
   /// hasContent - Return true if this compile unit has something to write out.
   bool hasContent() const { return !UnitDie->getChildren().empty(); }
 
+  /// addRange - Add an address range to the list of ranges for this unit.
+  void addRange(RangeSpan Range) { CURanges.push_back(Range); }
+
+  /// getRanges - Get the list of ranges for this unit.
+  const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; }
+  SmallVectorImpl<RangeSpan> &getRanges() { return CURanges; }
+
   /// addRangeList - Add an address range list to the list of range lists.
   void addRangeList(RangeSpanList Ranges) { CURangeLists.push_back(Ranges); }
 

Added: llvm/trunk/test/DebugInfo/cu-ranges.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/cu-ranges.ll?rev=197776&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/cu-ranges.ll (added)
+++ llvm/trunk/test/DebugInfo/cu-ranges.ll Thu Dec 19 22:16:18 2013
@@ -0,0 +1,50 @@
+; RUN: llc -O0 -filetype=obj -generate-dwarf-cu-ranges %s -o %t
+; RUN: llvm-dwarfdump %t | FileCheck %s
+
+; Check that we emit ranges for this when the -generate-dwarf-cu-ranges flag is passed.
+
+; CHECK: DW_TAG_compile_unit
+; CHECK: DW_AT_ranges
+; CHECK: DW_TAG_subprogram
+
+; CHECK: .debug_ranges contents:
+; FIXME: When we get better dumping facilities we'll want to elaborate here.
+; CHECK: 00000000 <End of list>
+; CHECK: 00000010 <End of list>
+
+; Function Attrs: nounwind uwtable
+define i32 @f(i32 %a) #0 {
+entry:
+  %a.addr = alloca i32, align 4
+  store i32 %a, i32* %a.addr, align 4
+  call void @llvm.dbg.declare(metadata !{i32* %a.addr}, metadata !12), !dbg !13
+  %0 = load i32* %a.addr, align 4, !dbg !14
+  %add = add nsw i32 %0, 4, !dbg !14
+  ret i32 %add, !dbg !14
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata) #1
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !10}
+!llvm.ident = !{!11}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 (trunk 197756) (llvm/trunk 197768)", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/echristo/tmp/foo.c] [DW_LANG_C99]
+!1 = metadata !{metadata !"foo.c", metadata !"/usr/local/google/home/echristo/tmp"}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f", metadata !"f", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @f, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [f]
+!5 = metadata !{i32 786473, metadata !1}          ; [ DW_TAG_file_type ] [/usr/local/google/home/echristo/tmp/foo.c]
+!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = metadata !{metadata !8, metadata !8}
+!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
+!10 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
+!11 = metadata !{metadata !"clang version 3.5 (trunk 197756) (llvm/trunk 197768)"}
+!12 = metadata !{i32 786689, metadata !4, metadata !"a", metadata !5, i32 16777217, metadata !8, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [a] [line 1]
+!13 = metadata !{i32 1, i32 0, metadata !4, null}
+!14 = metadata !{i32 2, i32 0, metadata !4, null}





More information about the llvm-commits mailing list