Add a DW_AT_high_pc for CUs that are a single address range. Update
all tests accordingly.

Fixes PR13351.

Patch by shinichiro hamaji!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160899 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 649684a..1a8db3c 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -127,7 +127,8 @@
   : Asm(A), MMI(Asm->MMI), FirstCU(0),
     AbbreviationsSet(InitAbbreviationsSetSize),
     SourceIdMap(DIEValueAllocator), StringPool(DIEValueAllocator),
-    PrevLabel(NULL) {
+    PrevLabel(NULL),
+    HasNonTextSection(false) {
   NextStringPoolNumber = 0;
 
   DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
@@ -561,9 +562,6 @@
   NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
                  DIUnit.getLanguage());
   NewCU->addString(Die, dwarf::DW_AT_name, FN);
-  // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
-  // into an entity.
-  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.
   if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
@@ -787,12 +785,25 @@
     FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
   }
 
-  // Emit DW_AT_containing_type attribute to connect types with their
-  // vtable holding type.
   for (DenseMap<const MDNode *, CompileUnit *>::iterator CUI = CUMap.begin(),
          CUE = CUMap.end(); CUI != CUE; ++CUI) {
+    // Emit DW_AT_containing_type attribute to connect types with their
+    // vtable holding type.
     CompileUnit *TheCU = CUI->second;
     TheCU->constructContainingTypeDIEs();
+
+    // Emit low_pc and high_pc for CU.
+    DIE *Die = TheCU->getCUDie();
+    if (HasNonTextSection) {
+      // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
+      // into an entity.
+      TheCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
+    } else {
+      TheCU->addLabel(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+                      Asm->GetTempSymbol("text_begin"));
+      TheCU->addLabel(Die, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
+                      Asm->GetTempSymbol("text_end"));
+    }
   }
 
   // Standard sections final addresses.
@@ -852,6 +863,7 @@
          E = CUMap.end(); I != E; ++I)
     delete I->second;
   FirstCU = NULL;  // Reset for the next Module, if any.
+  HasNonTextSection = false;
 }
 
 /// findAbstractVariable - Find abstract variable, if any, associated with Var.
@@ -1220,6 +1232,9 @@
   if (LScopes.empty()) return;
   identifyScopeMarkers();
 
+  if (!Asm->getCurrentSection()->getKind().isText())
+    HasNonTextSection = true;
+
   FunctionBeginSym = Asm->GetTempSymbol("func_begin",
                                         Asm->getFunctionNumber());
   // Assumes in correct section after the entry point.
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index d1d6512..5b8f61c 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -307,6 +307,9 @@
   // table for the same directory as DW_at_comp_dir.
   StringRef CompilationDir;
 
+  // True if the current module has non text section.
+  bool HasNonTextSection;
+
 private:
 
   /// assignAbbrevNumber - Define a unique number for the abbreviation.
diff --git a/test/DebugInfo/X86/DW_AT_specification.ll b/test/DebugInfo/X86/DW_AT_specification.ll
index 078b740..5df4f2a 100644
--- a/test/DebugInfo/X86/DW_AT_specification.ll
+++ b/test/DebugInfo/X86/DW_AT_specification.ll
@@ -3,8 +3,8 @@
 
 ; test that the DW_AT_specification is a back edge in the file.
 
-; CHECK: 0x0000003a: DW_TAG_subprogram [5] *
-; CHECK: 0x00000060: DW_AT_specification [DW_FORM_ref4]      (cu + 0x003a => {0x0000003a})
+; CHECK: 0x00000042: DW_TAG_subprogram [5] *
+; CHECK: 0x00000068: DW_AT_specification [DW_FORM_ref4]      (cu + 0x0042 => {0x00000042})
 
 
 @_ZZN3foo3barEvE1x = constant i32 0, align 4
diff --git a/test/DebugInfo/X86/DW_TAG_friend.ll b/test/DebugInfo/X86/DW_TAG_friend.ll
index a0dcec3..c35dcd2 100644
--- a/test/DebugInfo/X86/DW_TAG_friend.ll
+++ b/test/DebugInfo/X86/DW_TAG_friend.ll
@@ -3,10 +3,10 @@
 
 ; Check that the friend tag is there and is followed by a DW_AT_friend that has a reference back.
 
-; CHECK: 0x00000032:   DW_TAG_class_type [4]
-; CHECK: 0x00000077:   DW_TAG_class_type [4]
-; CHECK: 0x000000a0:     DW_TAG_friend [9]  
-; CHECK: 0x000000a1:       DW_AT_friend [DW_FORM_ref4]   (cu + 0x0032 => {0x00000032})
+; CHECK: 0x0000003a:   DW_TAG_class_type [4]
+; CHECK: 0x0000007f:   DW_TAG_class_type [4]
+; CHECK: 0x000000a8:     DW_TAG_friend [9]
+; CHECK: 0x000000a9:       DW_AT_friend [DW_FORM_ref4]   (cu + 0x003a => {0x0000003a})
 
 
 %class.A = type { i32 }
diff --git a/test/DebugInfo/X86/block-capture.ll b/test/DebugInfo/X86/block-capture.ll
index 4953c42..432afe0 100644
--- a/test/DebugInfo/X86/block-capture.ll
+++ b/test/DebugInfo/X86/block-capture.ll
@@ -2,10 +2,10 @@
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 
 ; Checks that we emit debug info for the block variable declare.
-; CHECK: 0x00000030:   DW_TAG_subprogram [3]
-; CHECK: 0x0000005b:     DW_TAG_variable [5]
-; CHECK: 0x0000005c:       DW_AT_name [DW_FORM_strp]     ( .debug_str[0x000000e6] = "block")
-; CHECK: 0x00000066:       DW_AT_location [DW_FORM_data4]        (0x00000023)
+; CHECK: 0x00000038:   DW_TAG_subprogram [3]
+; CHECK: 0x00000063:     DW_TAG_variable [5]
+; CHECK: 0x00000064:       DW_AT_name [DW_FORM_strp]     ( .debug_str[0x000000e6] = "block")
+; CHECK: 0x0000006e:       DW_AT_location [DW_FORM_data4]        (0x00000023)
 
 %struct.__block_descriptor = type { i64, i64 }
 %struct.__block_literal_generic = type { i8*, i32, i32, i8*, %struct.__block_descriptor* }
diff --git a/test/DebugInfo/X86/concrete_out_of_line.ll b/test/DebugInfo/X86/concrete_out_of_line.ll
index a227071..36a6653 100644
--- a/test/DebugInfo/X86/concrete_out_of_line.ll
+++ b/test/DebugInfo/X86/concrete_out_of_line.ll
@@ -7,7 +7,7 @@
 ; first check that we have a TAG_subprogram at a given offset and it has
 ; AT_inline.
 
-; CHECK: 0x00000134:   DW_TAG_subprogram [18]
+; CHECK: 0x0000013c:   DW_TAG_subprogram [18]
 ; CHECK-NEXT:     DW_AT_MIPS_linkage_name
 ; CHECK-NEXT:     DW_AT_specification
 ; CHECK-NEXT:     DW_AT_inline
@@ -15,8 +15,8 @@
 
 ; and then that a TAG_subprogram refers to it with AT_abstract_origin.
 
-; CHECK: 0x00000184:   DW_TAG_subprogram [20]
-; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4]    (cu + 0x0134 => {0x00000134})
+; CHECK: 0x0000018c:   DW_TAG_subprogram [20]
+; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4]    (cu + 0x013c => {0x0000013c})
 
 define i32 @_ZN17nsAutoRefCnt7ReleaseEv() {
 entry:
diff --git a/test/DebugInfo/X86/enum-class.ll b/test/DebugInfo/X86/enum-class.ll
index 6eb715d..aa0b2d0 100644
--- a/test/DebugInfo/X86/enum-class.ll
+++ b/test/DebugInfo/X86/enum-class.ll
@@ -31,12 +31,12 @@
 !21 = metadata !{i32 786484, i32 0, null, metadata !"c", metadata !"c", metadata !"", metadata !4, i32 6, metadata !12, i32 0, i32 1, i32* @c} ; [ DW_TAG_variable ]
 
 ; CHECK: DW_TAG_enumeration_type [3]
-; CHECK: DW_AT_type [DW_FORM_ref4]      (cu + 0x0026 => {0x00000026})
+; CHECK: DW_AT_type [DW_FORM_ref4]      (cu + 0x002e => {0x0000002e})
 ; CHECK: DW_AT_enum_class [DW_FORM_flag]    (0x01)
 ; CHECK: DW_AT_name [DW_FORM_strp]      ( .debug_str[{{.*}}] = "A")
 
 ; CHECK: DW_TAG_enumeration_type [3] *
-; CHECK: DW_AT_type [DW_FORM_ref4]      (cu + 0x0057 => {0x00000057})
+; CHECK: DW_AT_type [DW_FORM_ref4]      (cu + 0x005f => {0x0000005f})
 ; CHECK: DW_AT_enum_class [DW_FORM_flag]    (0x01)
 ; CHECK: DW_AT_name [DW_FORM_strp]          ( .debug_str[{{.*}}] = "B")
 
diff --git a/test/DebugInfo/X86/low-pc-cu.ll b/test/DebugInfo/X86/low-high-pc-cu.ll
similarity index 94%
rename from test/DebugInfo/X86/low-pc-cu.ll
rename to test/DebugInfo/X86/low-high-pc-cu.ll
index f9d9b91..53fc46d 100644
--- a/test/DebugInfo/X86/low-pc-cu.ll
+++ b/test/DebugInfo/X86/low-high-pc-cu.ll
@@ -1,10 +1,11 @@
 ; RUN: llc -mtriple=x86_64-apple-darwin %s -o %t -filetype=obj
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 
-; Check that we use DW_AT_low_pc
+; Check that we use DW_AT_low_pc and DW_AT_high_pc
 
 ; CHECK: DW_TAG_compile_unit [1]
 ; CHECK: DW_AT_low_pc [DW_FORM_addr]       (0x0000000000000000)
+; CHECK: DW_AT_high_pc [DW_FORM_addr]      (0x0000000000000001)
 ; CHECK: DW_TAG_subprogram [2]
 
 define i32 @_Z1qv() nounwind uwtable readnone ssp {
diff --git a/test/DebugInfo/X86/non-text-cu.ll b/test/DebugInfo/X86/non-text-cu.ll
new file mode 100644
index 0000000..858812b
--- /dev/null
+++ b/test/DebugInfo/X86/non-text-cu.ll
@@ -0,0 +1,23 @@
+; RUN: llc -mtriple=x86_64-redhat-linux-gnu %s -o %t -filetype=obj
+; RUN: llvm-dwarfdump %t | FileCheck %s
+
+; Check that we only use DW_AT_low_pc for CU which has non text sections
+
+; CHECK: DW_TAG_compile_unit [1]
+; CHECK: DW_AT_low_pc [DW_FORM_addr]       (0x0000000000000000)
+; CHECK-NOT: DW_AT_high_pc [DW_FORM_addr]
+; CHECK: DW_TAG_subprogram [2]
+
+define void @in_data() nounwind section ".data" {
+  ret void, !dbg !5
+}
+
+!llvm.dbg.sp = !{!0}
+
+!0 = metadata !{i32 589870, i32 0, metadata !1, metadata !"in_data", metadata !"in_data", metadata !"", metadata !1, i32 1, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 0, i1 false, void ()* @in_data} ; [ DW_TAG_subprogram ]
+!1 = metadata !{i32 589865, metadata !"in_data.c", metadata !"/home/i/test", metadata !2} ; [ DW_TAG_file_type ]
+!2 = metadata !{i32 589841, i32 0, i32 12, metadata !"in_data.c", metadata !"/home/i/test", metadata !"clang version 2.9 (tags/RELEASE_29/final)", i1 true, i1 false, 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 1, i32 51, metadata !6, null}
+!6 = metadata !{i32 589835, metadata !0, i32 1, i32 50, metadata !1, i32 0} ; [ DW_TAG_lexical_block ]
diff --git a/test/DebugInfo/X86/objc-fwd-decl.ll b/test/DebugInfo/X86/objc-fwd-decl.ll
index 1a815f9..f40770c 100644
--- a/test/DebugInfo/X86/objc-fwd-decl.ll
+++ b/test/DebugInfo/X86/objc-fwd-decl.ll
@@ -1,9 +1,9 @@
 ; RUN: llc -mtriple=x86_64-macosx %s -o %t -filetype=obj
 ; RUN: llvm-dwarfdump %t | FileCheck %s
 
-; CHECK: 0x00000027:   DW_TAG_structure_type
-; CHECK: 0x0000002c:     DW_AT_declaration
-; CHECK: 0x0000002d:     DW_AT_APPLE_runtime_class
+; CHECK: 0x0000002f:   DW_TAG_structure_type
+; CHECK: 0x00000034:     DW_AT_declaration
+; CHECK: 0x00000035:     DW_AT_APPLE_runtime_class
 
 %0 = type opaque
 
diff --git a/test/DebugInfo/X86/pr11300.ll b/test/DebugInfo/X86/pr11300.ll
index 5a001ee..f3998c5 100644
--- a/test/DebugInfo/X86/pr11300.ll
+++ b/test/DebugInfo/X86/pr11300.ll
@@ -3,8 +3,8 @@
 
 ; test that the DW_AT_specification is a back edge in the file.
 
-; CHECK: 0x0000005c:     DW_TAG_subprogram [5]
-; CHECK: 0x0000007c:     DW_AT_specification [DW_FORM_ref4]      (cu + 0x005c => {0x0000005c})
+; CHECK: 0x00000064:     DW_TAG_subprogram [5]
+; CHECK: 0x00000084:     DW_AT_specification [DW_FORM_ref4]      (cu + 0x0064 => {0x00000064})
 
 %struct.foo = type { i8 }
 
diff --git a/test/DebugInfo/X86/stringpool.ll b/test/DebugInfo/X86/stringpool.ll
index 2cd1001..af47540 100644
--- a/test/DebugInfo/X86/stringpool.ll
+++ b/test/DebugInfo/X86/stringpool.ll
@@ -16,7 +16,7 @@
 
 ; Verify that we refer to 'yyyy' with a relocation.
 ; LINUX:      .long   .Lstring3               # DW_AT_name
-; LINUX-NEXT: .long   39                      # DW_AT_type
+; LINUX-NEXT: .long   47                      # DW_AT_type
 ; LINUX-NEXT: .byte   1                       # DW_AT_external
 ; LINUX-NEXT: .byte   1                       # DW_AT_decl_file
 ; LINUX-NEXT: .byte   1                       # DW_AT_decl_line
@@ -27,7 +27,7 @@
 ; Verify that we refer to 'yyyy' without a relocation.
 ; DARWIN: Lset5 = Lstring3-Lsection_str               ## DW_AT_name
 ; DARWIN-NEXT:        .long   Lset5
-; DARWIN-NEXT:        .long   39                      ## DW_AT_type
+; DARWIN-NEXT:        .long   47                      ## DW_AT_type
 ; DARWIN-NEXT:        .byte   1                       ## DW_AT_external
 ; DARWIN-NEXT:        .byte   1                       ## DW_AT_decl_file
 ; DARWIN-NEXT:        .byte   1                       ## DW_AT_decl_line