[llvm] r338477 - [DebugInfo] Generate fixups as emitting DWARF .debug_line.

Hsiangkai Wang via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 31 19:18:06 PDT 2018


Author: hsiangkai
Date: Tue Jul 31 19:18:06 2018
New Revision: 338477

URL: http://llvm.org/viewvc/llvm-project?rev=338477&view=rev
Log:
[DebugInfo] Generate fixups as emitting DWARF .debug_line.

It is necessary to generate fixups in .debug_line as relaxation is
enabled due to the address delta may be changed after relaxation.

DWARF will record the mappings of lines and addresses in
.debug_line section. It will encode the information using special
opcodes, standard opcodes and extended opcodes in Line Number
Program. I use DW_LNS_fixed_advance_pc to encode fixed length
address delta and DW_LNE_set_address to encode absolute address
to make it possible to generate fixups in .debug_line section.

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

Added:
    llvm/trunk/test/DebugInfo/RISCV/
    llvm/trunk/test/DebugInfo/RISCV/lit.local.cfg
    llvm/trunk/test/DebugInfo/RISCV/relax-debug-line.ll
Modified:
    llvm/trunk/include/llvm/MC/MCDwarf.h
    llvm/trunk/include/llvm/MC/MCFragment.h
    llvm/trunk/lib/MC/MCAssembler.cpp
    llvm/trunk/lib/MC/MCDwarf.cpp

Modified: llvm/trunk/include/llvm/MC/MCDwarf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCDwarf.h?rev=338477&r1=338476&r2=338477&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCDwarf.h (original)
+++ llvm/trunk/include/llvm/MC/MCDwarf.h Tue Jul 31 19:18:06 2018
@@ -362,6 +362,13 @@ public:
   static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
                      int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
 
+  /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas using
+  /// fixed length operands.
+  static bool FixedEncode(MCContext &Context,
+                          MCDwarfLineTableParams Params,
+                          int64_t LineDelta, uint64_t AddrDelta,
+                          raw_ostream &OS, uint32_t *Offset, uint32_t *Size);
+
   /// Utility function to emit the encoding to a streamer.
   static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
                    int64_t LineDelta, uint64_t AddrDelta);

Modified: llvm/trunk/include/llvm/MC/MCFragment.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCFragment.h?rev=338477&r1=338476&r2=338477&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCFragment.h (original)
+++ llvm/trunk/include/llvm/MC/MCFragment.h Tue Jul 31 19:18:06 2018
@@ -149,6 +149,7 @@ public:
     case MCFragment::FT_Relaxable:
     case MCFragment::FT_CompactEncodedInst:
     case MCFragment::FT_Data:
+    case MCFragment::FT_Dwarf:
       return true;
     }
   }
@@ -232,7 +233,7 @@ public:
   static bool classof(const MCFragment *F) {
     MCFragment::FragmentType Kind = F->getKind();
     return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
-           Kind == MCFragment::FT_CVDefRange;
+           Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf;;
   }
 };
 
@@ -514,7 +515,7 @@ public:
   }
 };
 
-class MCDwarfLineAddrFragment : public MCFragment {
+class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
   /// LineDelta - the value of the difference between the two line numbers
   /// between two .loc dwarf directives.
   int64_t LineDelta;
@@ -523,15 +524,11 @@ class MCDwarfLineAddrFragment : public M
   /// make up the address delta between two .loc dwarf directives.
   const MCExpr *AddrDelta;
 
-  SmallString<8> Contents;
-
 public:
   MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
                           MCSection *Sec = nullptr)
-      : MCFragment(FT_Dwarf, false, Sec), LineDelta(LineDelta),
-        AddrDelta(&AddrDelta) {
-    Contents.push_back(0);
-  }
+      : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
+        LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
 
   /// \name Accessors
   /// @{
@@ -540,9 +537,6 @@ public:
 
   const MCExpr &getAddrDelta() const { return *AddrDelta; }
 
-  SmallString<8> &getContents() { return Contents; }
-  const SmallString<8> &getContents() const { return Contents; }
-
   /// @}
 
   static bool classof(const MCFragment *F) {

Modified: llvm/trunk/lib/MC/MCAssembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAssembler.cpp?rev=338477&r1=338476&r2=338477&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAssembler.cpp (original)
+++ llvm/trunk/lib/MC/MCAssembler.cpp Tue Jul 31 19:18:06 2018
@@ -822,6 +822,9 @@ void MCAssembler::layout(MCAsmLayout &La
       } else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
         Fixups = FragWithFixups->getFixups();
         Contents = FragWithFixups->getContents();
+      } else if (auto *FragWithFixups = dyn_cast<MCDwarfLineAddrFragment>(&Frag)) {
+        Fixups = FragWithFixups->getFixups();
+        Contents = FragWithFixups->getContents();
       } else
         llvm_unreachable("Unknown fragment with fixups!");
       for (const MCFixup &Fixup : Fixups) {
@@ -951,16 +954,37 @@ bool MCAssembler::relaxDwarfLineAddr(MCA
   MCContext &Context = Layout.getAssembler().getContext();
   uint64_t OldSize = DF.getContents().size();
   int64_t AddrDelta;
-  bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
-  assert(Abs && "We created a line delta with an invalid expression");
-  (void) Abs;
+  bool Abs = DF.getAddrDelta().evaluateAsAbsolute(AddrDelta, Layout);
   int64_t LineDelta;
   LineDelta = DF.getLineDelta();
-  SmallString<8> &Data = DF.getContents();
+  SmallVectorImpl<char> &Data = DF.getContents();
   Data.clear();
   raw_svector_ostream OSE(Data);
-  MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
-                          AddrDelta, OSE);
+  DF.getFixups().clear();
+
+  if (Abs) {
+    MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
+                            AddrDelta, OSE);
+  } else {
+    uint32_t Offset;
+    uint32_t Size;
+    bool SetDelta = MCDwarfLineAddr::FixedEncode(Context,
+                                                 getDWARFLinetableParams(),
+                                                 LineDelta, AddrDelta,
+                                                 OSE, &Offset, &Size);
+    // Add Fixups for address delta or new address.
+    const MCExpr *FixupExpr;
+    if (SetDelta) {
+      FixupExpr = &DF.getAddrDelta();
+    } else {
+      const MCBinaryExpr *ABE = cast<MCBinaryExpr>(&DF.getAddrDelta());
+      FixupExpr = ABE->getLHS();
+    }
+    DF.getFixups().push_back(
+        MCFixup::create(Offset, FixupExpr,
+                        MCFixup::getKindForSize(Size, false /*isPCRel*/)));
+  }
+
   return OldSize != Data.size();
 }
 

Modified: llvm/trunk/lib/MC/MCDwarf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDwarf.cpp?rev=338477&r1=338476&r2=338477&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCDwarf.cpp (original)
+++ llvm/trunk/lib/MC/MCDwarf.cpp Tue Jul 31 19:18:06 2018
@@ -731,6 +731,57 @@ void MCDwarfLineAddr::Encode(MCContext &
   }
 }
 
+bool MCDwarfLineAddr::FixedEncode(MCContext &Context,
+                                  MCDwarfLineTableParams Params,
+                                  int64_t LineDelta, uint64_t AddrDelta,
+                                  raw_ostream &OS,
+                                  uint32_t *Offset, uint32_t *Size) {
+  if (LineDelta != INT64_MAX) {
+    OS << char(dwarf::DW_LNS_advance_line);
+    encodeSLEB128(LineDelta, OS);
+  }
+
+  // Use address delta to adjust address or use absolute address to adjust
+  // address.
+  bool SetDelta;
+  // According to DWARF spec., the DW_LNS_fixed_advance_pc opcode takes a
+  // single uhalf (unencoded) operand. So, the maximum value of AddrDelta
+  // is 65535. We set a conservative upper bound for it for relaxation.
+  if (AddrDelta > 60000) {
+    const MCAsmInfo *asmInfo = Context.getAsmInfo();
+    unsigned AddrSize = asmInfo->getCodePointerSize();
+
+    OS << char(dwarf::DW_LNS_extended_op);
+    encodeULEB128(1 + AddrSize, OS);
+    OS << char(dwarf::DW_LNE_set_address);
+    // Generate fixup for the address.
+    *Offset = OS.tell();
+    *Size = AddrSize;
+    SetDelta = false;
+    std::vector<uint8_t> FillData;
+    FillData.insert(FillData.begin(), AddrSize, 0);
+    OS.write(reinterpret_cast<char *>(FillData.data()), AddrSize);
+  } else {
+    OS << char(dwarf::DW_LNS_fixed_advance_pc);
+    // Generate fixup for 2-bytes address delta.
+    *Offset = OS.tell();
+    *Size = 2;
+    SetDelta = true;
+    OS << char(0);
+    OS << char(0);
+  }
+
+  if (LineDelta == INT64_MAX) {
+    OS << char(dwarf::DW_LNS_extended_op);
+    OS << char(1);
+    OS << char(dwarf::DW_LNE_end_sequence);
+  } else {
+    OS << char(dwarf::DW_LNS_copy);
+  }
+
+  return SetDelta;
+}
+
 // Utility function to write a tuple for .debug_abbrev.
 static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
   MCOS->EmitULEB128IntValue(Name);

Added: llvm/trunk/test/DebugInfo/RISCV/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/RISCV/lit.local.cfg?rev=338477&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/RISCV/lit.local.cfg (added)
+++ llvm/trunk/test/DebugInfo/RISCV/lit.local.cfg Tue Jul 31 19:18:06 2018
@@ -0,0 +1,2 @@
+if not 'RISCV' in config.root.targets:
+    config.unsupported = True

Added: llvm/trunk/test/DebugInfo/RISCV/relax-debug-line.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/RISCV/relax-debug-line.ll?rev=338477&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/RISCV/relax-debug-line.ll (added)
+++ llvm/trunk/test/DebugInfo/RISCV/relax-debug-line.ll Tue Jul 31 19:18:06 2018
@@ -0,0 +1,75 @@
+; RUN: llc -filetype=obj -mtriple=riscv32 -mattr=+relax %s -o - \
+; RUN:     | llvm-readobj -r | FileCheck -check-prefix=RELAX %s
+;
+; RELAX: .rela.debug_line {
+; RELAX: R_RISCV_ADD16
+; RELAX: R_RISCV_SUB16
+source_filename = "line.c"
+
+; Function Attrs: noinline nounwind optnone
+define i32 @init() !dbg !7 {
+entry:
+  ret i32 0, !dbg !11
+}
+
+; Function Attrs: noinline nounwind optnone
+define i32 @foo(i32 signext %value) !dbg !12 {
+entry:
+  %value.addr = alloca i32, align 4
+  store i32 %value, i32* %value.addr, align 4
+  call void @llvm.dbg.declare(metadata i32* %value.addr, metadata !15, metadata !DIExpression()), !dbg !16
+  %0 = load i32, i32* %value.addr, align 4, !dbg !17
+  ret i32 %0, !dbg !18
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+; Function Attrs: noinline nounwind optnone
+define i32 @bar() !dbg !19 {
+entry:
+  %result = alloca i32, align 4
+  %v = alloca i32, align 4
+  call void @llvm.dbg.declare(metadata i32* %result, metadata !20, metadata !DIExpression()), !dbg !21
+  call void @llvm.dbg.declare(metadata i32* %v, metadata !22, metadata !DIExpression()), !dbg !23
+  %call = call i32 @init(), !dbg !24
+  store i32 %call, i32* %v, align 4, !dbg !23
+  %0 = load i32, i32* %v, align 4, !dbg !25
+  %call1 = call i32 @foo(i32 signext %0), !dbg !26
+  store i32 %call1, i32* %result, align 4, !dbg !27
+  %1 = load i32, i32* %result, align 4, !dbg !28
+  ret i32 %1, !dbg !29
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "line.c", directory: "./")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!7 = distinct !DISubprogram(name: "init", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DILocation(line: 3, column: 3, scope: !7)
+!12 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 6, type: !13, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!13 = !DISubroutineType(types: !14)
+!14 = !{!10, !10}
+!15 = !DILocalVariable(name: "value", arg: 1, scope: !12, file: !1, line: 6, type: !10)
+!16 = !DILocation(line: 6, column: 13, scope: !12)
+!17 = !DILocation(line: 8, column: 10, scope: !12)
+!18 = !DILocation(line: 8, column: 3, scope: !12)
+!19 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 11, type: !8, isLocal: false, isDefinition: true, scopeLine: 12, isOptimized: false, unit: !0, retainedNodes: !2)
+!20 = !DILocalVariable(name: "result", scope: !19, file: !1, line: 13, type: !10)
+!21 = !DILocation(line: 13, column: 7, scope: !19)
+!22 = !DILocalVariable(name: "v", scope: !19, file: !1, line: 14, type: !10)
+!23 = !DILocation(line: 14, column: 7, scope: !19)
+!24 = !DILocation(line: 14, column: 11, scope: !19)
+!25 = !DILocation(line: 16, column: 16, scope: !19)
+!26 = !DILocation(line: 16, column: 12, scope: !19)
+!27 = !DILocation(line: 16, column: 10, scope: !19)
+!28 = !DILocation(line: 18, column: 10, scope: !19)
+!29 = !DILocation(line: 18, column: 3, scope: !19)




More information about the llvm-commits mailing list