Emit relocations for DW_AT_location entries on systems which need it. This is
authorNick Lewycky <nicholas@mxc.ca>
Fri, 22 Jun 2012 01:25:12 +0000 (01:25 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Fri, 22 Jun 2012 01:25:12 +0000 (01:25 +0000)
a recommit of r127757. Fixes PR9493. Patch by Paul Robinson!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158957 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/AsmPrinter.h
include/llvm/MC/MCAsmInfo.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/MC/MCAsmInfo.cpp
lib/MC/MCAsmInfoDarwin.cpp
test/DebugInfo/X86/DW_AT_location-reference.ll [new file with mode: 0644]

index 56a87f139a21404b202575423758cf83d4bb4104..170a528a5a22bd86a1d2c23dad4de75b1afe8240 100644 (file)
@@ -354,6 +354,13 @@ namespace llvm {
     void EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset,
                                    unsigned Size) const;
 
+    /// EmitLabelReference - Emit something like ".long Label"
+    /// where the size in bytes of the directive is specified by Size and Label
+    /// specifies the label.
+    void EmitLabelReference(const MCSymbol *Label, unsigned Size) const {
+      EmitLabelPlusOffset(Label, 0, Size);
+    }
+
     //===------------------------------------------------------------------===//
     // Dwarf Emission Helper Routines
     //===------------------------------------------------------------------===//
index ae0dad2fd1c0578f2673e4d52b9b8bdb25dcddc8..21b484c1c0fd116bbacf4c00b9d2052bda2b6cae 100644 (file)
@@ -319,9 +319,11 @@ namespace llvm {
     /// relocation when we want a section offset in dwarf.
     bool DwarfRequiresRelocationForSectionOffset;  // Defaults to true;
 
-    /// DwarfUsesLabelOffsetDifference - True if Dwarf2 output can
-    /// use EmitLabelOffsetDifference.
-    bool DwarfUsesLabelOffsetForRanges;
+    /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally
+    /// uses relocations for references to other .debug_* sections.
+    // FIXME: Can we replace DwarfRequiresRelocationForSectionOffset
+    // with this?
+    bool DwarfUsesRelocationsAcrossSections;
 
     /// DwarfUsesRelocationsForStringPool - True if this Dwarf output must use
     /// relocations to refer to entries in the string pool.
@@ -552,8 +554,8 @@ namespace llvm {
     bool doesDwarfRequireRelocationForSectionOffset() const {
       return DwarfRequiresRelocationForSectionOffset;
     }
-    bool doesDwarfUseLabelOffsetForRanges() const {
-      return DwarfUsesLabelOffsetForRanges;
+    bool doesDwarfUseRelocationsAcrossSections() const {
+      return DwarfUsesRelocationsAcrossSections;
     }
     bool doesDwarfUseRelocationsForStringPool() const {
       return DwarfUsesRelocationsForStringPool;
index eeacc43c0972258c40c65f968ad92787e0d1c85c..2d6dc804635a8f817b5ad9b00e1424fed2bad2e8 100644 (file)
@@ -1388,13 +1388,14 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset,
                                       unsigned Size)
   const {
 
-  // Emit Label+Offset
-  const MCExpr *Plus =
-    MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Label, OutContext),
-                            MCConstantExpr::Create(Offset, OutContext),
-                            OutContext);
-
-  OutStreamer.EmitValue(Plus, 4, 0/*AddrSpace*/);
+  // Emit Label+Offset (or just Label if Offset is zero)
+  const MCExpr *Expr = MCSymbolRefExpr::Create(Label, OutContext);
+  if (Offset)
+    Expr = MCBinaryExpr::CreateAdd(Expr,
+                                   MCConstantExpr::Create(Offset, OutContext),
+                                   OutContext);
+
+  OutStreamer.EmitValue(Expr, Size, 0/*AddrSpace*/);
 }
 
 
index 2e24977ef24f32e0164e189e443078291bab3e91..1e4ef5fbdbb8a881e5b67645a173b5a36acd9872 100644 (file)
@@ -1624,7 +1624,7 @@ void DwarfDebug::emitDIE(DIE *Die) {
       // DW_AT_range Value encodes offset in debug_range section.
       DIEInteger *V = cast<DIEInteger>(Values[i]);
 
-      if (Asm->MAI->doesDwarfUseLabelOffsetForRanges()) {
+      if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) {
         Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym,
                                  V->getValue(),
                                  4);
@@ -1637,10 +1637,14 @@ void DwarfDebug::emitDIE(DIE *Die) {
       break;
     }
     case dwarf::DW_AT_location: {
-      if (DIELabel *L = dyn_cast<DIELabel>(Values[i]))
-        Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4);
-      else
+      if (DIELabel *L = dyn_cast<DIELabel>(Values[i])) {
+        if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+          Asm->EmitLabelReference(L->getValue(), 4);
+        else
+          Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4);
+      } else {
         Values[i]->EmitValue(Asm, Form);
+      }
       break;
     }
     case dwarf::DW_AT_accessibility: {
index d9c1d51d185fbc451ee11da5aa2abd95df1c116f..beb20e8f15987241900bbec93de024fed600d561 100644 (file)
@@ -86,7 +86,7 @@ MCAsmInfo::MCAsmInfo() {
   DwarfUsesInlineInfoSection = false;
   DwarfRequiresRelocationForSectionOffset = true;
   DwarfSectionOffsetDirective = 0;
-  DwarfUsesLabelOffsetForRanges = true;
+  DwarfUsesRelocationsAcrossSections = true;
   DwarfUsesRelocationsForStringPool = true;
   DwarfRegNumForCFI = false;
   HasMicrosoftFastStdCallMangling = false;
index 73ef7ba0604a0cfd014518363809c43fad28c8f8..7c271a9e824b910e2900062a126f11b5a6239561 100644 (file)
@@ -60,6 +60,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
   HasSymbolResolver = true;
 
   DwarfRequiresRelocationForSectionOffset = false;
-  DwarfUsesLabelOffsetForRanges = false;
+  DwarfUsesRelocationsAcrossSections = false;
   DwarfUsesRelocationsForStringPool = false;
 }
diff --git a/test/DebugInfo/X86/DW_AT_location-reference.ll b/test/DebugInfo/X86/DW_AT_location-reference.ll
new file mode 100644 (file)
index 0000000..3be9aba
--- /dev/null
@@ -0,0 +1,111 @@
+; RUN: llc -O1 -mtriple=x86_64-apple-darwin < %s | FileCheck -check-prefix=DARWIN %s
+; RUN: llc -O1 -mtriple=x86_64-pc-linux-gnu < %s | FileCheck -check-prefix=LINUX %s
+; PR9493
+; Adapted from the original test case in r127757.
+; We use 'llc -O1' to induce variable 'x' to live in different locations.
+; We don't actually care where 'x' lives, or what exact optimizations get
+; used, as long as 'x' moves around we're fine.
+
+; // The variable 'x' lives in different locations, so it needs an entry in
+; // the .debug_loc table section, referenced by DW_AT_location.
+; // This ref is not relocatable on Darwin, and is relocatable elsewhere.
+; extern int g(int, int);
+; extern int a;
+; 
+; void f(void) {
+;   int x;
+;   a = g(0, 0);
+;   x = 1;
+;   while (x & 1) { x *= a; }
+;   a = g(x, 0);
+;   x = 2;
+;   while (x & 2) { x *= a; }
+;   a = g(0, x);
+; }
+
+; // The 'x' variable and its symbol reference location
+; DARWIN:      DW_TAG_variable
+; DARWIN-NEXT: ## DW_AT_name
+; DARWIN-NEXT: .long Lset{{[0-9]+}}
+; DARWIN-NEXT: ## DW_AT_decl_file
+; DARWIN-NEXT: ## DW_AT_decl_line
+; DARWIN-NEXT: ## DW_AT_type
+; DARWIN-NEXT: Lset{{[0-9]+}} = Ldebug_loc{{[0-9]+}}-Lsection_debug_loc ## DW_AT_location
+; DARWIN-NEXT: .long Lset{{[0-9]+}}
+
+; LINUX:      DW_TAG_variable
+; LINUX-NEXT: # DW_AT_name
+; LINUX-NEXT: # DW_AT_decl_file
+; LINUX-NEXT: # DW_AT_decl_line
+; LINUX-NEXT: # DW_AT_type
+; LINUX-NEXT: .long .Ldebug_loc{{[0-9]+}} # DW_AT_location
+
+
+; ModuleID = 'simple.c'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32"
+
+@a = external global i32
+
+define void @f() nounwind {
+entry:
+  %call = tail call i32 @g(i32 0, i32 0) nounwind, !dbg !8
+  store i32 %call, i32* @a, align 4, !dbg !8, !tbaa !9
+  tail call void @llvm.dbg.value(metadata !12, i64 0, metadata !5), !dbg !13
+  br label %while.body
+
+while.body:                                       ; preds = %entry, %while.body
+  %x.017 = phi i32 [ 1, %entry ], [ %mul, %while.body ]
+  %mul = mul nsw i32 %call, %x.017, !dbg !14
+  %and = and i32 %mul, 1, !dbg !14
+  %tobool = icmp eq i32 %and, 0, !dbg !14
+  br i1 %tobool, label %while.end, label %while.body, !dbg !14
+
+while.end:                                        ; preds = %while.body
+  tail call void @llvm.dbg.value(metadata !{i32 %mul}, i64 0, metadata !5), !dbg !14
+  %call4 = tail call i32 @g(i32 %mul, i32 0) nounwind, !dbg !15
+  store i32 %call4, i32* @a, align 4, !dbg !15, !tbaa !9
+  tail call void @llvm.dbg.value(metadata !16, i64 0, metadata !5), !dbg !17
+  br label %while.body9
+
+while.body9:                                      ; preds = %while.end, %while.body9
+  %x.116 = phi i32 [ 2, %while.end ], [ %mul12, %while.body9 ]
+  %mul12 = mul nsw i32 %call4, %x.116, !dbg !18
+  %and7 = and i32 %mul12, 2, !dbg !18
+  %tobool8 = icmp eq i32 %and7, 0, !dbg !18
+  br i1 %tobool8, label %while.end13, label %while.body9, !dbg !18
+
+while.end13:                                      ; preds = %while.body9
+  tail call void @llvm.dbg.value(metadata !{i32 %mul12}, i64 0, metadata !5), !dbg !18
+  %call15 = tail call i32 @g(i32 0, i32 %mul12) nounwind, !dbg !19
+  store i32 %call15, i32* @a, align 4, !dbg !19, !tbaa !9
+  ret void, !dbg !20
+}
+
+declare i32 @g(i32, i32)
+
+declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone
+
+!llvm.dbg.sp = !{!0}
+!llvm.dbg.lv.f = !{!5}
+
+!0 = metadata !{i32 589870, i32 0, metadata !1, metadata !"f", metadata !"f", metadata !"", metadata !1, i32 4, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, void ()* @f} ; [ DW_TAG_subprogram ]
+!1 = metadata !{i32 589865, metadata !"simple.c", metadata !"/home/rengol01/temp/tests/dwarf/relocation", metadata !2} ; [ DW_TAG_file_type ]
+!2 = metadata !{i32 589841, i32 0, i32 12, metadata !"simple.c", metadata !"/home/rengol01/temp/tests/dwarf/relocation", metadata !"clang version 3.0 (trunk)", i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
+!3 = metadata !{i32 589845, metadata !1, metadata !"", metadata !1, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
+!4 = metadata !{null}
+!5 = metadata !{i32 590080, metadata !6, metadata !"x", metadata !1, i32 5, metadata !7, i32 0} ; [ DW_TAG_auto_variable ]
+!6 = metadata !{i32 589835, metadata !0, i32 4, i32 14, metadata !1, i32 0} ; [ DW_TAG_lexical_block ]
+!7 = metadata !{i32 589860, metadata !2, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
+!8 = metadata !{i32 6, i32 3, metadata !6, null}
+!9 = metadata !{metadata !"int", metadata !10}
+!10 = metadata !{metadata !"omnipotent char", metadata !11}
+!11 = metadata !{metadata !"Simple C/C++ TBAA", null}
+!12 = metadata !{i32 1}
+!13 = metadata !{i32 7, i32 3, metadata !6, null}
+!14 = metadata !{i32 8, i32 3, metadata !6, null}
+!15 = metadata !{i32 9, i32 3, metadata !6, null}
+!16 = metadata !{i32 2}
+!17 = metadata !{i32 10, i32 3, metadata !6, null}
+!18 = metadata !{i32 11, i32 3, metadata !6, null}
+!19 = metadata !{i32 12, i32 3, metadata !6, null}
+!20 = metadata !{i32 13, i32 1, metadata !6, null}