This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] DWARF5 .debug_rnglists support


Hi!

This is another section that changed completely in DWARF5.
In order to decrease the size of the section, when using num > 0
entries (i.e. .LBBnn/.LBEnn labels), the patch is using DW_RLE_base_address
followed by DW_RLE_offset_pair, but needs to add another DW_RLE_base_address
if there is hot/cold (or vice versa) section switch in between (for that
I had to add the BLOCK_IN_COLD_SECTION_P flag and initialize it in final.c).

The -gsplit-dwarf support here is only partial, DWARF5 says that there
should be .debug_rnglists.dwo, and then obviously can't use
DW_RLE_base_address or DW_RLE_start_length or DW_RLE_start_end encodings,
but needs entries in .debug_addr etc.  All the patch does for it is it uses
DW_FORM_rnglistx encodings for (most of) DW_AT_ranges attributes.
For -gno-split-dwarf the offset table in .debug_rnglists section is at least
on the testcases I've tried larger than what we can safe in .debug_info size
through using DW_FORM_rnglistx instead of DW_FORM_sec_offset.

Bootstrapped/regtested on x86_64-linux and i686-linux on top of the
other 10 previously posted dwarf2out* patches, ok for trunk?

FYI, with -gno-split-dwarf, the new .debug_loclists and .debug_rnglists
section are much more compact than .debug_loc and .debug_ranges in DWARF4:
dwarf2out.o with -O2 -gdwarf-4:
   [251] .debug_loc        PROGBITS        0000000000000000 15b225 103dc4 00      0   0  1
   [255] .debug_ranges     PROGBITS        0000000000000000 25f5c9 039e40 00      0   0  1
dwarf2out.o with -O2 -gdwarf-5:
   [251] .debug_loclists   PROGBITS        0000000000000000 158202 078ad2 00      0   0  1
   [255] .debug_rnglists   PROGBITS        0000000000000000 1d12b4 0179da 00      0   0  1
Both sections shorter than 50% of the corresponding DWARF4 ones.

2016-10-20  Jakub Jelinek  <jakub@redhat.com>

	* tree.h (BLOCK_IN_COLD_SECTION_P): Define.
	* final.c (final_scan_insn): Set BLOCK_IN_COLD_SECTION_P.
	* dwarf2out.c (rnglist_idx): New variable.
	(struct dw_rnglist): New type.
	(rnglist_table): New variable.
	(DEBUG_RNGLISTS_SECTION): Define.
	(ranges_base_label): New variable.
	(size_of_die) <case dw_val_class_range_list>: For
	-gdwarf-5 -gsplit-dwarf count size of uleb128 of
	range list index.
	(value_format) <case dw_val_class_range_list>: For
	-gdwarf-5 -gsplit-dwarf return DW_FORM_rnglistx.
	(output_range_list_offset): Handle -gdwarf-5 .debug_rnglists
	offsets.  Multiply dwarf < 5 offsets by 2 * DWARF_ADDR_SIZE.
	(add_ranges_num): Don't multiply by 2 * DWARF2_ADDR_SIZE.
	(add_rnglist_num): New function.
	(add_ranges): For -gdwarf-5 call add_rnglist_num instead of
	add_ranges_num.  Add maybe_new_sec argument and pass it
	through to add_rnglist_num.
	(note_rnglist_head): New function.
	(add_ranges_by_labels): For -gdwarf-5 call add_rnglist_num
	instead of add_ranges_num and call note_rnglist_head on
	the head of the list.
	(output_ranges): Add function comment.  Switch to
	.debug_ranges section here and emit .Ldebug_ranges0 label.
	(index_rnglists, output_rnglists): New functions.
	(gen_subprogram_die): Formatting fixes.
	(add_high_low_attributes): For -gdwarf-5 look through
	rnglist_table instead of ranges_table.  Don't divide offsets
	by 2 * DWARF2_ADDR_SIZE.  Call note_rnglist_head on the
	first list element or when pointing into the middle of
	a list.  Pass true as second argument to add_ranges on the
	first block fragment after cold/hot section switch.
	(init_sections_and_labels): For -gdwarf-5 use .debug_rnglists
	section instead of .debug_ranges.  Initialize
	ranges_base_label if -gdwarf-5 -gsplit-dwarf.
	(dwarf2out_finish): For -gdwarf-5 -gsplit-dwarf call
	index_rnglists and add DW_AT_rnglists_base attr.  Don't switch
	to dwarf_ranges_section here or emit .Ldebug_ranges0 label.
	Call output_rnglists for -gdwarf-5.
	(dwarf2out_c_finalize): Clear rnglist_table and rnglist_idx.

--- gcc/tree.h.jj	2016-10-17 08:42:34.000000000 +0200
+++ gcc/tree.h	2016-10-20 13:43:34.002774460 +0200
@@ -1757,6 +1757,10 @@ extern void protected_set_expr_location
 /* True if BLOCK has the same ranges as its BLOCK_SUPERCONTEXT.  */
 #define BLOCK_SAME_RANGE(NODE) (BLOCK_CHECK (NODE)->base.u.bits.nameless_flag)
 
+/* True if BLOCK appears in cold section.  */
+#define BLOCK_IN_COLD_SECTION_P(NODE) \
+  (BLOCK_CHECK (NODE)->base.u.bits.atomic_flag)
+
 /* An index number for this block.  These values are not guaranteed to
    be unique across functions -- whether or not they are depends on
    the debugging output format in use.  */
--- gcc/final.c.jj	2016-10-14 12:31:49.000000000 +0200
+++ gcc/final.c	2016-10-20 13:45:26.281357597 +0200
@@ -2323,6 +2323,7 @@ final_scan_insn (rtx_insn *insn, FILE *f
 
 	      /* Mark this block as output.  */
 	      TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
+	      BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn)) = in_cold_section_p;
 	    }
 	  if (write_symbols == DBX_DEBUG
 	      || write_symbols == SDB_DEBUG)
@@ -2355,6 +2356,8 @@ final_scan_insn (rtx_insn *insn, FILE *f
 
 	      if (!DECL_IGNORED_P (current_function_decl))
 		debug_hooks->end_block (high_block_linenum, n);
+	      gcc_assert (BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn))
+			  == in_cold_section_p);
 	    }
 	  if (write_symbols == DBX_DEBUG
 	      || write_symbols == SDB_DEBUG)
--- gcc/dwarf2out.c.jj	2016-10-20 15:12:19.687437410 +0200
+++ gcc/dwarf2out.c	2016-10-20 17:37:08.645170742 +0200
@@ -277,6 +277,9 @@ static void dwarf2out_note_section_used
    personality CFI.  */
 static GTY(()) rtx current_unit_personality;
 
+/* .debug_rnglists next index.  */
+static unsigned int rnglist_idx;
+
 /* Data and reference forms for relocatable data.  */
 #define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
 #define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
@@ -2744,6 +2747,18 @@ struct GTY(()) dw_ranges {
   int num;
 };
 
+struct GTY(()) dw_rnglist {
+  const char *label;
+  /* If this is positive, it's a block number, otherwise it's a
+     bitwise-negated index into dw_ranges_by_label.  */
+  int num;
+  /* Index for the range list for DW_FORM_rnglistx.  */
+  unsigned int idx : 31;
+  /* True if this range might be possibly in a different section
+     from previous entry.  */
+  unsigned int maybe_new_sec : 1;
+};
+
 /* A structure to hold a macinfo entry.  */
 
 typedef struct GTY(()) macinfo_struct {
@@ -3082,6 +3097,9 @@ static GTY (()) vec<dw_ranges, va_gc> *r
 /* Vector of pairs of labels referenced in ranges_table.  */
 static GTY (()) vec<dw_ranges_by_label, va_gc> *ranges_by_label;
 
+/* Vector of dies for which we should generate .debug_rnglists info.  */
+static GTY (()) vec<dw_rnglist, va_gc> *rnglist_table;
+
 /* Whether we have location lists that need outputting */
 static GTY(()) bool have_location_lists;
 
@@ -3271,7 +3289,7 @@ static void add_pubtype (tree, dw_die_re
 static void output_pubnames (vec<pubname_entry, va_gc> *);
 static void output_aranges (void);
 static unsigned int add_ranges_num (int);
-static unsigned int add_ranges (const_tree);
+static unsigned int add_ranges (const_tree, bool = false);
 static void add_ranges_by_labels (dw_die_ref, const char *, const char *,
                                   bool *, bool);
 static void output_ranges (void);
@@ -3555,6 +3573,9 @@ new_addr_loc_descr (rtx addr, enum dtpre
 #ifndef DEBUG_RANGES_SECTION
 #define DEBUG_RANGES_SECTION	".debug_ranges"
 #endif
+#ifndef DEBUG_RNGLISTS_SECTION
+#define DEBUG_RNGLISTS_SECTION	".debug_rnglists"
+#endif
 #ifndef DEBUG_LINE_STR_SECTION
 #define DEBUG_LINE_STR_SECTION  ".debug_line_str"
 #endif
@@ -3638,6 +3659,7 @@ static char debug_skeleton_line_section_
 static char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
+static char ranges_base_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
 
 #ifndef TEXT_END_LABEL
 #define TEXT_END_LABEL		"Letext"
@@ -8476,7 +8498,16 @@ size_of_die (dw_die_ref die)
             size += DWARF_OFFSET_SIZE;
 	  break;
 	case dw_val_class_range_list:
-          size += DWARF_OFFSET_SIZE;
+	  if (dwarf_split_debug_info
+	      && dwarf_version >= 5
+	      && a->dw_attr_val.val_entry != RELOCATED_OFFSET)
+	    {
+	      gcc_assert (rnglist_idx);
+	      dw_rnglist *r = &(*rnglist_table)[a->dw_attr_val.v.val_offset];
+	      size += size_of_uleb128 (r->idx);
+	    }
+	  else
+	    size += DWARF_OFFSET_SIZE;
 	  break;
 	case dw_val_class_const:
 	  size += size_of_sleb128 (AT_int (a));
@@ -8826,6 +8857,12 @@ value_format (dw_attr_node *a)
 	return DW_FORM_loclistx;
       /* FALLTHRU */
     case dw_val_class_range_list:
+      if (dwarf_split_debug_info
+	  && dwarf_version >= 5
+	  && AT_class (a) == dw_val_class_range_list
+	  && rnglist_idx
+	  && a->dw_attr_val.val_entry != RELOCATED_OFFSET)
+	return DW_FORM_rnglistx;
       if (dwarf_version >= 4)
 	return DW_FORM_sec_offset;
       /* FALLTHRU */
@@ -9292,9 +9329,9 @@ output_loc_list (dw_loc_list_ref list_he
     }
 }
 
-/* Output a range_list offset into the debug_range section.  Emit a
-   relocated reference if val_entry is NULL, otherwise, emit an
-   indirect reference.  */
+/* Output a range_list offset into the .debug_ranges or .debug_rnglists
+   section.  Emit a relocated reference if val_entry is NULL, otherwise,
+   emit an indirect reference.  */
 
 static void
 output_range_list_offset (dw_attr_node *a)
@@ -9303,14 +9340,31 @@ output_range_list_offset (dw_attr_node *
 
   if (a->dw_attr_val.val_entry == RELOCATED_OFFSET)
     {
-      char *p = strchr (ranges_section_label, '\0');
-      sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX, a->dw_attr_val.v.val_offset);
-      dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
-                             debug_ranges_section, "%s", name);
-      *p = '\0';
+      if (dwarf_version >= 5)
+	{
+	  dw_rnglist *r = &(*rnglist_table)[a->dw_attr_val.v.val_offset];
+	  dw2_asm_output_offset (DWARF_OFFSET_SIZE, r->label,
+				 debug_ranges_section, "%s", name);
+	}
+      else
+	{
+	  char *p = strchr (ranges_section_label, '\0');
+	  sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX,
+		   a->dw_attr_val.v.val_offset * 2 * DWARF2_ADDR_SIZE);
+	  dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
+				 debug_ranges_section, "%s", name);
+	  *p = '\0';
+	}
+    }
+  else if (dwarf_version >= 5)
+    {
+      dw_rnglist *r = &(*rnglist_table)[a->dw_attr_val.v.val_offset];
+      gcc_assert (rnglist_idx);
+      dw2_asm_output_data_uleb128 (r->idx, "%s", name);
     }
   else
-    dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset,
+    dw2_asm_output_data (DWARF_OFFSET_SIZE,
+			 a->dw_attr_val.v.val_offset * 2 * DWARF2_ADDR_SIZE,
                          "%s (offset from %s)", name, ranges_section_label);
 }
 
@@ -10331,26 +10385,51 @@ output_aranges (void)
   dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
 }
 
-/* Add a new entry to .debug_ranges.  Return the offset at which it
-   was placed.  */
+/* Add a new entry to .debug_ranges.  Return its index into
+   ranges_table vector.  */
 
 static unsigned int
 add_ranges_num (int num)
 {
   dw_ranges r = { num };
   vec_safe_push (ranges_table, r);
-  return (vec_safe_length (ranges_table) - 1) * 2 * DWARF2_ADDR_SIZE;
+  return vec_safe_length (ranges_table) - 1;
+}
+
+/* Add a new entry to .debug_rnglists.  Return its index into
+   rnglist_table vector.  */
+
+static unsigned int
+add_rnglist_num (int num, bool maybe_new_sec)
+{
+  dw_rnglist r = { NULL, num, 0, maybe_new_sec };
+  vec_safe_push (rnglist_table, r);
+  return vec_safe_length (rnglist_table) - 1;
 }
 
 /* Add a new entry to .debug_ranges corresponding to a block, or a
-   range terminator if BLOCK is NULL.  */
+   range terminator if BLOCK is NULL.  MAYBE_NEW_SEC is true if
+   this entry might be in a different section from previous range.  */
 
 static unsigned int
-add_ranges (const_tree block)
+add_ranges (const_tree block, bool maybe_new_sec)
 {
+  if (dwarf_version >= 5)
+    return add_rnglist_num (block ? BLOCK_NUMBER (block) : 0, maybe_new_sec);
   return add_ranges_num (block ? BLOCK_NUMBER (block) : 0);
 }
 
+/* Note that (*rnglist_table)[offset] is either a head of a rnglist
+   chain, or middle entry of a chain that will be directly referred to.  */
+
+static void
+note_rnglist_head (unsigned int offset)
+{
+  if (dwarf_version < 5 || (*rnglist_table)[offset].label)
+    return;
+  (*rnglist_table)[offset].label = gen_internal_sym ("LLRL");
+}
+
 /* Add a new entry to .debug_ranges corresponding to a pair of labels.
    When using dwarf_split_debug_info, address attributes in dies destined
    for the final executable should be direct references--setting the
@@ -10364,14 +10443,20 @@ add_ranges_by_labels (dw_die_ref die, co
   unsigned int offset;
   dw_ranges_by_label rbl = { begin, end };
   vec_safe_push (ranges_by_label, rbl);
-  offset = add_ranges_num (-(int)in_use - 1);
+  if (dwarf_version >= 5)
+    offset = add_rnglist_num (-(int)in_use - 1, true);
+  else
+    offset = add_ranges_num (-(int)in_use - 1);
   if (!*added)
     {
       add_AT_range_list (die, DW_AT_ranges, offset, force_direct);
       *added = true;
+      note_rnglist_head (offset);
     }
 }
 
+/* Emit .debug_ranges section.  */
+
 static void
 output_ranges (void)
 {
@@ -10380,6 +10465,8 @@ output_ranges (void)
   const char *fmt = start_fmt;
   dw_ranges *r;
 
+  switch_to_section (debug_ranges_section);
+  ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label);
   FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r)
     {
       int block_num = r->num;
@@ -10458,6 +10545,171 @@ output_ranges (void)
     }
 }
 
+/* Assign .debug_rnglists indexes.  */
+
+static void
+index_rnglists (void)
+{
+  unsigned i;
+  dw_rnglist *r;
+
+  FOR_EACH_VEC_SAFE_ELT (rnglist_table, i, r)
+    if (r->label)
+      r->idx = rnglist_idx++;
+}
+
+/* Emit .debug_rnglists section.  */
+
+static void
+output_rnglists (void)
+{
+  unsigned i;
+  dw_rnglist *r;
+  char l1[MAX_ARTIFICIAL_LABEL_BYTES];
+  char l2[MAX_ARTIFICIAL_LABEL_BYTES];
+  char basebuf[MAX_ARTIFICIAL_LABEL_BYTES];
+
+  switch_to_section (debug_ranges_section);
+  ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label);
+  ASM_GENERATE_INTERNAL_LABEL (l1, DEBUG_RANGES_SECTION_LABEL, 2);
+  ASM_GENERATE_INTERNAL_LABEL (l2, DEBUG_RANGES_SECTION_LABEL, 3);
+  if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+    dw2_asm_output_data (4, 0xffffffff,
+			 "Initial length escape value indicating "
+			 "64-bit DWARF extension");
+  dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+			"Length of Range Lists");
+  ASM_OUTPUT_LABEL (asm_out_file, l1);
+  dw2_asm_output_data (2, dwarf_version, "DWARF Version");
+  dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size");
+  dw2_asm_output_data (1, 0, "Segment Size");
+  dw2_asm_output_data (4, dwarf_split_debug_info ? rnglist_idx : 0,
+		       "Offset Entry Count");
+  if (dwarf_split_debug_info)
+    {
+      ASM_OUTPUT_LABEL (asm_out_file, ranges_base_label);
+      FOR_EACH_VEC_SAFE_ELT (rnglist_table, i, r)
+	if (r->label)
+	  dw2_asm_output_delta (DWARF_OFFSET_SIZE, r->label,
+				ranges_base_label, NULL);
+    }
+
+  unsigned int len = vec_safe_length (rnglist_table);
+  const char *lab = "";
+#ifdef HAVE_AS_LEB128
+  const char *base = NULL;
+#endif
+  FOR_EACH_VEC_SAFE_ELT (rnglist_table, i, r)
+    {
+      int block_num = r->num;
+
+      if (r->label)
+	{
+	  ASM_OUTPUT_LABEL (asm_out_file, r->label);
+	  lab = r->label;
+	}
+#ifdef HAVE_AS_LEB128
+      if (r->label || r->maybe_new_sec)
+	base = NULL;
+#endif
+      if (block_num > 0)
+	{
+	  char blabel[MAX_ARTIFICIAL_LABEL_BYTES];
+	  char elabel[MAX_ARTIFICIAL_LABEL_BYTES];
+
+	  ASM_GENERATE_INTERNAL_LABEL (blabel, BLOCK_BEGIN_LABEL, block_num);
+	  ASM_GENERATE_INTERNAL_LABEL (elabel, BLOCK_END_LABEL, block_num);
+
+#ifdef HAVE_AS_LEB128
+	  /* If all code is in the text section, then the compilation
+	     unit base address defaults to DW_AT_low_pc, which is the
+	     base of the text section.  */
+	  if (!have_multiple_function_sections)
+	    {
+	      dw2_asm_output_data (1, DW_RLE_offset_pair,
+				   "DW_RLE_offset_pair (%s)", lab);
+	      dw2_asm_output_delta_uleb128 (blabel, text_section_label,
+					    "Range begin address (%s)", lab);
+	      dw2_asm_output_delta_uleb128 (elabel, text_section_label,
+					    "Range end address (%s)", lab);
+	      continue;
+	    }
+	  if (base == NULL)
+	    {
+	      dw_rnglist *r2 = NULL;
+	      if (i < len - 1)
+		r2 = &(*rnglist_table)[i + 1];
+	      if (r2
+		  && r2->num != 0
+		  && r2->label == NULL
+		  && !r2->maybe_new_sec)
+		{
+		  dw2_asm_output_data (1, DW_RLE_base_address,
+				       "DW_RLE_base_address (%s)", lab);
+		  dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+				       "Base address (%s)", lab);
+		  strcpy (basebuf, blabel);
+		  base = basebuf;
+		}
+	    }
+	  if (base)
+	    {
+	      dw2_asm_output_data (1, DW_RLE_offset_pair,
+				   "DW_RLE_offset_pair (%s)", lab);
+	      dw2_asm_output_delta_uleb128 (blabel, base,
+					    "Range begin address (%s)", lab);
+	      dw2_asm_output_delta_uleb128 (elabel, base,
+					    "Range end address (%s)", lab);
+	      continue;
+	    }
+	  dw2_asm_output_data (1, DW_RLE_start_length,
+			       "DW_RLE_start_length (%s)", lab);
+	  dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+			       "Range begin address (%s)", lab);
+	  dw2_asm_output_delta_uleb128 (elabel, blabel,
+					"Range length (%s)", lab);
+#else
+	  dw2_asm_output_data (1, DW_RLE_start_end,
+			       "DW_RLE_start_end (%s)", lab);
+	  dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+			       "Range begin address (%s)", lab);
+	  dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel,
+			       "Range end address (%s)", lab);
+#endif
+	}
+
+      /* Negative block_num stands for an index into ranges_by_label.  */
+      else if (block_num < 0)
+	{
+	  int lab_idx = - block_num - 1;
+	  const char *blabel = (*ranges_by_label)[lab_idx].begin;
+	  const char *elabel = (*ranges_by_label)[lab_idx].end;
+
+	  if (!have_multiple_function_sections)
+	    gcc_unreachable ();
+#ifdef HAVE_AS_LEB128
+	  dw2_asm_output_data (1, DW_RLE_start_length,
+			       "DW_RLE_start_length (%s)", lab);
+	  dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+			       "Range begin address (%s)", lab);
+	  dw2_asm_output_delta_uleb128 (elabel, blabel,
+					"Range length (%s)", lab);
+#else
+	  dw2_asm_output_data (1, DW_RLE_start_end,
+			       "DW_RLE_start_end (%s)", lab);
+	  dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+			       "Range begin address (%s)", lab);
+	  dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel,
+			       "Range end address (%s)", lab);
+#endif
+	}
+      else
+	dw2_asm_output_data (1, DW_RLE_end_of_list,
+			     "DW_RLE_end_of_list (%s)", lab);
+    }
+  ASM_OUTPUT_LABEL (asm_out_file, l2);
+}
+
 /* Data structure containing information about input files.  */
 struct file_info
 {
@@ -21124,11 +21376,11 @@ gen_subprogram_die (tree decl, dw_die_re
 		     alignment offset.  */
 		  bool range_list_added = false;
 		  add_ranges_by_labels (subr_die, fde->dw_fde_begin,
-                                        fde->dw_fde_end, &range_list_added,
-                                        false);
+					fde->dw_fde_end, &range_list_added,
+					false);
 		  add_ranges_by_labels (subr_die, fde->dw_fde_second_begin,
 					fde->dw_fde_second_end,
-                                       &range_list_added, false);
+					&range_list_added, false);
 		  if (range_list_added)
 		    add_ranges (NULL);
 		}
@@ -21985,13 +22237,37 @@ add_high_low_attributes (tree stmt, dw_d
 	  superblock = BLOCK_SUPERCONTEXT (chain);
 	}
       if (attr != NULL
-	  && ((*ranges_table)[attr->dw_attr_val.v.val_offset
-			      / 2 / DWARF2_ADDR_SIZE].num
+	  && dwarf_version >= 5
+	  && ((*rnglist_table)[attr->dw_attr_val.v.val_offset].num
+	      == BLOCK_NUMBER (superblock))
+	  && BLOCK_FRAGMENT_CHAIN (superblock))
+	{
+	  unsigned long off = attr->dw_attr_val.v.val_offset;
+	  unsigned long supercnt = 0, thiscnt = 0;
+	  for (chain = BLOCK_FRAGMENT_CHAIN (superblock);
+	       chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
+	    {
+	      ++supercnt;
+	      gcc_checking_assert ((*rnglist_table)[off + supercnt].num
+				   == BLOCK_NUMBER (chain));
+	    }
+	  gcc_checking_assert ((*rnglist_table)[off + supercnt + 1].num == 0);
+	  for (chain = BLOCK_FRAGMENT_CHAIN (stmt);
+	       chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
+	    ++thiscnt;
+	  gcc_assert (supercnt >= thiscnt);
+	  add_AT_range_list (die, DW_AT_ranges, off + supercnt - thiscnt,
+			     false);
+	  note_rnglist_head (off + supercnt - thiscnt);
+	  return;
+	}
+      if (attr != NULL
+	  && dwarf_version < 5
+	  && ((*ranges_table)[attr->dw_attr_val.v.val_offset].num
 	      == BLOCK_NUMBER (superblock))
 	  && BLOCK_FRAGMENT_CHAIN (superblock))
 	{
-	  unsigned long off = attr->dw_attr_val.v.val_offset
-			      / 2 / DWARF2_ADDR_SIZE;
+	  unsigned long off = attr->dw_attr_val.v.val_offset;
 	  unsigned long supercnt = 0, thiscnt = 0;
 	  for (chain = BLOCK_FRAGMENT_CHAIN (superblock);
 	       chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
@@ -22005,19 +22281,21 @@ add_high_low_attributes (tree stmt, dw_d
 	       chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
 	    ++thiscnt;
 	  gcc_assert (supercnt >= thiscnt);
-	  add_AT_range_list (die, DW_AT_ranges,
-                             ((off + supercnt - thiscnt)
-                              * 2 * DWARF2_ADDR_SIZE),
-                             false);
+	  add_AT_range_list (die, DW_AT_ranges, off + supercnt - thiscnt,
+			     false);
 	  return;
 	}
 
-      add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt), false);
+      unsigned int offset = add_ranges (stmt, true);
+      add_AT_range_list (die, DW_AT_ranges, offset, false);
+      note_rnglist_head (offset);
 
+      bool prev_in_cold = BLOCK_IN_COLD_SECTION_P (stmt);
       chain = BLOCK_FRAGMENT_CHAIN (stmt);
       do
 	{
-	  add_ranges (chain);
+	  add_ranges (chain, prev_in_cold != BLOCK_IN_COLD_SECTION_P (chain));
+	  prev_in_cold = BLOCK_IN_COLD_SECTION_P (chain);
 	  chain = BLOCK_FRAGMENT_CHAIN (chain);
 	}
       while (chain);
@@ -26022,7 +26300,9 @@ init_sections_and_labels (void)
     debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
 					  DEBUG_STR_SECTION_FLAGS, NULL);
 
-  debug_ranges_section = get_section (DEBUG_RANGES_SECTION,
+  debug_ranges_section = get_section (dwarf_version >= 5
+				      ? DEBUG_RNGLISTS_SECTION
+				      : DEBUG_RANGES_SECTION,
 				      SECTION_DEBUG, NULL);
   debug_frame_section = get_section (DEBUG_FRAME_SECTION,
 				     SECTION_DEBUG, NULL);
@@ -26035,6 +26315,9 @@ init_sections_and_labels (void)
 			       DEBUG_LINE_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
 			       DEBUG_RANGES_SECTION_LABEL, 0);
+  if (dwarf_version >= 5 && dwarf_split_debug_info)
+    ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
+				 DEBUG_RANGES_SECTION_LABEL, 1);
   ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
                                DEBUG_ADDR_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
@@ -28483,6 +28766,9 @@ dwarf2out_finish (const char *)
       unsigned char checksum[16];
       struct md5_ctx ctx;
 
+      if (!vec_safe_is_empty (rnglist_table))
+	index_rnglists ();
+
       /* Compute a checksum of the comp_unit to use as the dwo_id.  */
       md5_init_ctx (&ctx);
       mark = 0;
@@ -28500,6 +28786,9 @@ dwarf2out_finish (const char *)
       if (!vec_safe_is_empty (ranges_table))
         add_AT_lineptr (main_comp_unit_die, DW_AT_GNU_ranges_base,
                         ranges_section_label);
+      else if (!vec_safe_is_empty (rnglist_table))
+	add_AT_lineptr (main_comp_unit_die, DW_AT_rnglists_base,
+			ranges_base_label);
 
       switch_to_section (debug_addr_section);
       ASM_OUTPUT_LABEL (asm_out_file, debug_addr_section_label);
@@ -28573,11 +28862,9 @@ dwarf2out_finish (const char *)
 
   /* Output ranges section if necessary.  */
   if (!vec_safe_is_empty (ranges_table))
-    {
-      switch_to_section (debug_ranges_section);
-      ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label);
-      output_ranges ();
-    }
+    output_ranges ();
+  else if (!vec_safe_is_empty (rnglist_table))
+    output_rnglists ();
 
   /* Have to end the macro section.  */
   if (have_macinfo)
@@ -28828,6 +29115,8 @@ dwarf2out_c_finalize (void)
   macinfo_table = NULL;
   ranges_table = NULL;
   ranges_by_label = NULL;
+  rnglist_table = NULL;
+  rnglist_idx = 0;
   have_location_lists = false;
   loclabel_num = 0;
   poc_label_num = 0;

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]