From e1616f40a28097eb9720c7b158b96b114c931429 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 20 Oct 2015 17:11:50 -0400
Subject: [PATCH 20/29] FIXME: Make range_bits be properly per-map

---
 gcc/input.c               | 15 +++++----
 gcc/tree.c                |  5 ++-
 libcpp/include/line-map.h | 15 ++-------
 libcpp/line-map.c         | 80 ++++++++++++++++++++++++++++++++++-------------
 4 files changed, 74 insertions(+), 41 deletions(-)

diff --git a/gcc/input.c b/gcc/input.c
index 5549872..9793468 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -902,13 +902,14 @@ write_digit (FILE *stream, int digit)
 
 static void
 write_digit_row (FILE *stream, int indent,
+		 const line_map_ordinary *map,
 		 source_location loc, int max_col, int divisor)
 {
   fprintf (stream, "%*c", indent, ' ');
   fprintf (stream, "|");
   for (int column = 1; column < max_col; column++)
     {
-      source_location column_loc = loc + (column << line_table->range_bits);
+      source_location column_loc = loc + (column << map->range_bits);
       write_digit (stream, column_loc / divisor);
     }
   fprintf (stream, "\n");
@@ -964,11 +965,13 @@ dump_location_info (FILE *stream)
 	       ORDINARY_MAP_STARTING_LINE_NUMBER (map));
       fprintf (stream, "  column bits: %i\n",
 	       ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map));
+      fprintf (stream, "  range bits: %i\n",
+	       map->range_bits);
 
       /* Render the span of source lines that this "map" covers.  */
       for (source_location loc = MAP_START_LOCATION (map);
 	   loc < end_location;
-	   loc += (1 << line_table->range_bits) )
+	   loc += (1 << map->range_bits) )
 	{
 	  gcc_assert (pure_location_p (line_table, loc) );
 
@@ -1004,17 +1007,17 @@ dump_location_info (FILE *stream)
 
 	      /* Thousands.  */
 	      if (end_location > 999)
-		write_digit_row (stream, indent, loc, max_col, 1000);
+		write_digit_row (stream, indent, map, loc, max_col, 1000);
 
 	      /* Hundreds.  */
 	      if (end_location > 99)
-		write_digit_row (stream, indent, loc, max_col, 100);
+		write_digit_row (stream, indent, map, loc, max_col, 100);
 
 	      /* Tens.  */
-	      write_digit_row (stream, indent, loc, max_col, 10);
+	      write_digit_row (stream, indent, map, loc, max_col, 10);
 
 	      /* Units.  */
-	      write_digit_row (stream, indent, loc, max_col, 1);
+	      write_digit_row (stream, indent, map, loc, max_col, 1);
 	    }
 	}
       fprintf (stream, "\n");
diff --git a/gcc/tree.c b/gcc/tree.c
index d25e353..9cd978c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13675,7 +13675,10 @@ get_pure_location (location_t loc)
   if (loc < RESERVED_LOCATION_COUNT)
     return loc;
 
-  return loc & ~((1 << line_table->range_bits) - 1);
+  const line_map *map = linemap_lookup (line_table, loc);
+  const line_map_ordinary *ordmap = linemap_check_ordinary (map);
+
+  return loc & ~((1 << ordmap->range_bits) - 1);
 }
 
 void
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 7d48855..1d3b152 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -571,7 +571,7 @@ struct GTY(()) line_maps {
   bool seen_line_directive;
 
   /* FIXME.  */
-  unsigned int range_bits;
+  unsigned int default_range_bits;
 
   unsigned int num_optimized_ranges;
   unsigned int num_unoptimized_ranges;
@@ -834,17 +834,8 @@ IS_ADHOC_LOC (source_location loc)
 /* Get whether location LOC is a "pure" location, or
    whether it is an ad-hoc location, or embeds range information.  */
 
-inline bool
-pure_location_p (line_maps *set, source_location loc)
-{
-  if (IS_ADHOC_LOC (loc))
-    return false;
-
-  if (loc & ((1U << set->range_bits) - 1))
-    return false;
-
-  return true;
-}
+bool
+pure_location_p (line_maps *set, source_location loc);
 
 /* Combine LOC and BLOCK, giving a combined adhoc location.  */
 
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 8d3c3c8..676beb8 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -191,9 +191,11 @@ get_combined_adhoc_loc (struct line_maps *set,
     {
       /* The low bits ought to be clear.  */
       linemap_assert (pure_location_p (set, locus));
+      const line_map *map = linemap_lookup (set, locus);
+      const line_map_ordinary *ordmap = linemap_check_ordinary (map);
       unsigned int int_diff = src_range.m_finish - src_range.m_start;
-      unsigned int col_diff = (int_diff >> set->range_bits);
-      if (col_diff < (1U << set->range_bits))
+      unsigned int col_diff = (int_diff >> ordmap->range_bits);
+      if (col_diff < (1U << ordmap->range_bits))
 	{
 	  source_location packed = locus | col_diff;
 	  set->num_optimized_ranges++;
@@ -301,16 +303,37 @@ get_range_from_loc (struct line_maps *set,
       && loc < LINEMAPS_MACRO_LOWEST_LOCATION (set)
       && loc <= LINE_MAP_MAX_LOCATION_WITH_COLS)
     {
+      const line_map *map = linemap_lookup (set, loc);
+      const line_map_ordinary *ordmap = linemap_check_ordinary (map);
       source_range result;
-      int offset = loc & ((1 << set->range_bits) - 1);
+      int offset = loc & ((1 << ordmap->range_bits) - 1);
       result.m_start = loc - offset;
-      result.m_finish = result.m_start + (offset << set->range_bits);
+      result.m_finish = result.m_start + (offset << ordmap->range_bits);
       return result;
     }
 
   return source_range::from_location (loc);
 }
 
+/* Get whether location LOC is a "pure" location, or
+   whether it is an ad-hoc location, or embeds range information.  */
+
+bool
+pure_location_p (line_maps *set, source_location loc)
+{
+  if (IS_ADHOC_LOC (loc))
+    return false;
+
+  const line_map *map = linemap_lookup (set, loc);
+  const line_map_ordinary *ordmap = linemap_check_ordinary (map);
+  // FIXME: what about macro maps?
+
+  if (loc & ((1U << ordmap->range_bits) - 1))
+    return false;
+
+  return true;
+}
+
 /* Finalize the location_adhoc_data structure.  */
 void
 location_adhoc_data_fini (struct line_maps *set)
@@ -453,12 +476,19 @@ const struct line_map *
 linemap_add (struct line_maps *set, enum lc_reason reason,
 	     unsigned int sysp, const char *to_file, linenum_type to_line)
 {
-  source_location start_location =
-    set->highest_location + (1 << set->range_bits);
-
-  if (set->range_bits)
-    start_location &= ~((1 << set->range_bits) - 1);
-  linemap_assert (0 == (start_location & ((1 << set->range_bits) - 1)));
+  source_location start_location;
+  if (set->highest_location < LINE_MAP_MAX_LOCATION_WITH_COLS)
+    {
+      start_location = set->highest_location + (1 << set->default_range_bits);
+      if (set->default_range_bits)
+	start_location &= ~((1 << set->default_range_bits) - 1);
+      linemap_assert (0 == (start_location
+			    & ((1 << set->default_range_bits) - 1)));
+    }
+  else
+    {
+      start_location = set->highest_location + 1;
+    }
 
   linemap_assert (!(LINEMAPS_ORDINARY_USED (set)
 		    && (start_location
@@ -533,15 +563,15 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
     }
 
   map->sysp = sysp;
+  set->highest_location = start_location;
+  set->highest_line = start_location;
   linemap_assert (pure_location_p (set, start_location));
   map->start_location = start_location;
   map->to_file = to_file;
   map->to_line = to_line;
   LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1;
   map->column_bits = 0;
-  map->range_bits = set->range_bits;
-  set->highest_location = start_location;
-  set->highest_line = start_location;
+  map->range_bits = 0;
   set->max_column_hint = 0;
 
   if (reason == LC_ENTER)
@@ -690,9 +720,9 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
     SOURCE_LINE (map, set->highest_line);
   int line_delta = to_line - last_line;
   bool add_map = false;
-  int effective_column_bits = ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map);
-  if (effective_column_bits)
-    effective_column_bits -= set->range_bits;
+  linemap_assert (ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= map->range_bits);
+  int effective_column_bits
+    = ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) - map->range_bits;
 
   if (line_delta < 0
       || (line_delta > 10
@@ -707,6 +737,7 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
   if (add_map)
     {
       int column_bits;
+      int range_bits;
       if (max_column_hint > LINE_MAP_MAX_COLUMN_NUMBER
 	  || highest > LINE_MAP_MAX_LOCATION_WITH_COLS)
 	{
@@ -714,16 +745,18 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
 	     number of source_locations, give up on column numbers. */
 	  max_column_hint = 0;
 	  column_bits = 0;
+	  range_bits = 0;
 	  if (highest > LINE_MAP_MAX_SOURCE_LOCATION)
 	    return 0;
 	}
       else
 	{
 	  column_bits = 7;
+	  range_bits = set->default_range_bits;
 	  while (max_column_hint >= (1U << column_bits))
 	    column_bits++;
 	  max_column_hint = 1U << column_bits;
-	  column_bits += set->range_bits;
+	  column_bits += range_bits;
 	}
       /* Allocate the new line_map.  However, if the current map only has a
 	 single line we can sometimes just increase its column_bits instead. */
@@ -737,6 +770,7 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
 				ORDINARY_MAP_FILE_NAME (map),
 				to_line)));
       map->column_bits = column_bits;
+      map->range_bits = range_bits;
       r = (MAP_START_LOCATION (map)
 	   + ((to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
 	      << column_bits));
@@ -750,6 +784,11 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
   if (r >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
     return 0;
 
+  set->highest_line = r;
+  if (r > set->highest_location)
+    set->highest_location = r;
+  set->max_column_hint = max_column_hint;
+
   /* At this point, we expect one of:
      (a) the normal case: a "pure" location with 0 range bits, or
      (b) we've gone past LINE_MAP_MAX_LOCATION_WITH_COLS so can't track
@@ -760,10 +799,6 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
   linemap_assert (pure_location_p (set, r)
 		  || r >= LINE_MAP_MAX_LOCATION_WITH_COLS
 		  || map->column_bits == 0);
-  set->highest_line = r;
-  if (r > set->highest_location)
-    set->highest_location = r;
-  set->max_column_hint = max_column_hint;
   linemap_assert (SOURCE_LINE (map, r) == to_line);
   return r;
 }
@@ -795,7 +830,8 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column)
 	  r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
 	}
     }
-  r = r + (to_column << set->range_bits);
+  line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
+  r = r + (to_column << map->range_bits);
   if (r >= set->highest_location)
     set->highest_location = r;
   return r;
-- 
1.8.5.3

