OSDN Git Service

2012-01-09 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / libcpp / line-map.c
index 3dbaeab..d7752bb 100644 (file)
@@ -46,6 +46,10 @@ static source_location linemap_macro_loc_to_exp_point (struct line_maps *,
                                                       source_location,
                                                       const struct line_map **);
 
+/* Counters defined in macro.c.  */
+extern unsigned num_expanded_macros_counter;
+extern unsigned num_macro_tokens_counter;
+
 /* Initialize a line map set.  */
 
 void
@@ -88,16 +92,43 @@ new_linemap (struct line_maps *set,
   if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p))
     {
       /* We ran out of allocated line maps. Let's allocate more.  */
+      unsigned alloc_size;
 
       line_map_realloc reallocator
        = set->reallocator ? set->reallocator : xrealloc;
+      line_map_round_alloc_size_func round_alloc_size =
+       set->round_alloc_size;
+
+      /* We are going to execute some dance to try to reduce the
+        overhead of the memory allocator, in case we are using the
+        ggc-page.c one.
+        
+        The actual size of memory we are going to get back from the
+        allocator is the smallest power of 2 that is greater than the
+        size we requested.  So let's consider that size then.  */
+
+      alloc_size =
+       (2 * LINEMAPS_ALLOCATED (set, macro_map_p) +  256)
+       * sizeof (struct line_map);
+
+      /* Get the actual size of memory that is going to be allocated
+        by the allocator.  */
+      alloc_size = round_alloc_size (alloc_size);
+
+      /* Now alloc_size contains the exact memory size we would get if
+        we have asked for the initial alloc_size amount of memory.
+        Let's get back to the number of macro map that amounts
+        to.  */
       LINEMAPS_ALLOCATED (set, macro_map_p) =
-       2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256;
-      LINEMAPS_MAPS (set, macro_map_p)
-       = (struct line_map *) (*reallocator) (LINEMAPS_MAPS (set, macro_map_p),
-                                             LINEMAPS_ALLOCATED (set,
-                                                                 macro_map_p)
-                                             * sizeof (struct line_map));
+       alloc_size / (sizeof (struct line_map));
+
+      /* And now let's really do the re-allocation.  */
+      LINEMAPS_MAPS (set, macro_map_p) =
+       (struct line_map *) (*reallocator)
+       (LINEMAPS_MAPS (set, macro_map_p),
+        (LINEMAPS_ALLOCATED (set, macro_map_p)
+         * sizeof (struct line_map)));
+
       result =
        &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
       memset (result, 0,
@@ -557,14 +588,14 @@ linemap_macro_map_lookup (struct line_maps *set, source_location line)
       mn = 0;
     }
 
-  do 
+  while (mn < mx)
     {
       md = (mx + mn) / 2;
       if (MAP_START_LOCATION (LINEMAPS_MACRO_MAP_AT (set, md)) > line)
-       mn = md;
+       mn = md + 1;
       else
        mx = md;
-    } while (mx - mn > 1);
+    }
 
   LINEMAPS_MACRO_CACHE (set) = mx;
   result = LINEMAPS_MACRO_MAP_AT (set, LINEMAPS_MACRO_CACHE (set));
@@ -590,18 +621,16 @@ linemap_macro_expansion_map_p (const struct line_map *map)
    Read the comments of struct line_map and struct line_map_macro in
    line-map.h to understand what a macro expansion point is.  */
 
-source_location
+static source_location
 linemap_macro_map_loc_to_exp_point (const struct line_map *map,
-                                   source_location location)
+                                   source_location location ATTRIBUTE_UNUSED)
 {
-  unsigned token_no;
-
   linemap_assert (linemap_macro_expansion_map_p (map)
                  && location >= MAP_START_LOCATION (map));
 
   /* Make sure LOCATION is correct.  */
-  token_no = location - MAP_START_LOCATION (map);
-  linemap_assert (token_no <  MACRO_MAP_NUM_MACRO_TOKENS (map));
+  linemap_assert ((location - MAP_START_LOCATION (map))
+                 <  MACRO_MAP_NUM_MACRO_TOKENS (map));
 
   return MACRO_MAP_EXPANSION_POINT_LOCATION (map);
 }
@@ -726,12 +755,12 @@ linemap_location_in_system_header_p (struct line_maps *set,
 {
   const struct line_map *map = NULL;
 
-  if (location < RESERVED_LOCATION_COUNT)
-    return false;
-
   location =
     linemap_resolve_location (set, location, LRK_SPELLING_LOCATION, &map);
 
+  if (location < RESERVED_LOCATION_COUNT)
+    return false;
+
   return LINEMAP_SYSP (map);
 }
 
@@ -1010,7 +1039,10 @@ linemap_macro_loc_to_exp_point (struct line_maps *set,
    LRK_SPELLING_LOCATION.
 
    If MAP is non-NULL, *MAP is set to the map of the resolved
-   location.  */
+   location.  Note that if the resturned location wasn't originally
+   encoded by a map, the *MAP is set to NULL.  This can happen if LOC
+   resolves to a location reserved for the client code, like
+   UNKNOWN_LOCATION or BUILTINS_LOCATION in GCC.  */
 
 source_location
 linemap_resolve_location (struct line_maps *set,
@@ -1018,7 +1050,15 @@ linemap_resolve_location (struct line_maps *set,
                          enum location_resolution_kind lrk,
                          const struct line_map **map)
 {
-  linemap_assert (set && loc >= RESERVED_LOCATION_COUNT);
+  if (loc < RESERVED_LOCATION_COUNT)
+    {
+      /* A reserved location wasn't encoded in a map.  Let's return a
+        NULL map here, just like what linemap_ordinary_map_lookup
+        does.  */
+      if (map)
+       *map = NULL;
+      return loc;
+    }
 
   switch (lrk)
     {
@@ -1072,40 +1112,98 @@ linemap_unwind_toward_expansion (struct line_maps *set,
 }
 
 /* Expand source code location LOC and return a user readable source
-   code location.  LOC must be a spelling (non-virtual) location.  */
+   code location.  LOC must be a spelling (non-virtual) location.  If
+   it's a location < RESERVED_LOCATION_COUNT a zeroed expanded source
+   location is returned.  */
 
 expanded_location
-linemap_expand_location (const struct line_map *map,
+linemap_expand_location (struct line_maps *set,
+                        const struct line_map *map,
                         source_location loc)
 
 {
   expanded_location xloc;
 
-  xloc.file = LINEMAP_FILE (map);
-  xloc.line = SOURCE_LINE (map, loc);
-  xloc.column = SOURCE_COLUMN (map, loc);
-  xloc.sysp = LINEMAP_SYSP (map) != 0;
+  memset (&xloc, 0, sizeof (xloc));
+
+  if (loc < RESERVED_LOCATION_COUNT)
+    /* The location for this token wasn't generated from a line map.
+       It was probably a location for a builtin token, chosen by some
+       client code.  Let's not try to expand the location in that
+       case.  */;
+  else if (map == NULL)
+    /* We shouldn't be getting a NULL map with a location that is not
+       reserved by the client code.  */
+    abort ();
+  else
+    {
+      /* MAP must be an ordinary map and LOC must be non-virtual,
+        encoded into this map, obviously; the accessors used on MAP
+        below ensure it is ordinary.  Let's just assert the
+        non-virtualness of LOC here.  */
+      if (linemap_location_from_macro_expansion_p (set, loc))
+       abort ();
+
+      xloc.file = LINEMAP_FILE (map);
+      xloc.line = SOURCE_LINE (map, loc);
+      xloc.column = SOURCE_COLUMN (map, loc);
+      xloc.sysp = LINEMAP_SYSP (map) != 0;
+    }
 
   return xloc;
 }
 
-/* Expand source code location LOC and return a user readable source
-   code location.  LOC can be a virtual location.  The LRK parameter
-   is the same as for linemap_resolve_location.  */
 
-expanded_location
-linemap_expand_location_full (struct line_maps *set,
-                             source_location loc,
-                             enum location_resolution_kind lrk)
+/* Dump line map at index IX in line table SET to STREAM.  If STREAM
+   is NULL, use stderr.  IS_MACRO is true if the caller wants to
+   dump a macro map, false otherwise.  */
+
+void
+linemap_dump (FILE *stream, struct line_maps *set, unsigned ix, bool is_macro)
 {
-  const struct line_map *map;
-  expanded_location xloc;
+  const char *lc_reasons_v[LC_ENTER_MACRO + 1]
+      = { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
+         "LC_ENTER_MACRO" };
+  const char *reason;
+  struct line_map *map;
 
-  loc = linemap_resolve_location (set, loc, lrk, &map);
-  xloc = linemap_expand_location (map, loc);
-  return xloc;
+  if (stream == NULL)
+    stream = stderr;
+
+  if (!is_macro)
+    map = LINEMAPS_ORDINARY_MAP_AT (set, ix);
+  else
+    map = LINEMAPS_MACRO_MAP_AT (set, ix);
+
+  reason = (map->reason <= LC_ENTER_MACRO) ? lc_reasons_v[map->reason] : "???";
+
+  fprintf (stream, "Map #%u [%p] - LOC: %u - REASON: %s - SYSP: %s\n",
+          ix, (void *) map, map->start_location, reason,
+          (!is_macro && ORDINARY_MAP_IN_SYSTEM_HEADER_P (map)) ? "yes" : "no");
+  if (!is_macro)
+    {
+      unsigned includer_ix;
+      struct line_map *includer_map;
+
+      includer_ix = ORDINARY_MAP_INCLUDER_FILE_INDEX (map);
+      includer_map = includer_ix < LINEMAPS_ORDINARY_USED (set)
+                    ? LINEMAPS_ORDINARY_MAP_AT (set, includer_ix)
+                    : NULL;
+
+      fprintf (stream, "File: %s:%d\n", ORDINARY_MAP_FILE_NAME (map),
+              ORDINARY_MAP_STARTING_LINE_NUMBER (map));
+      fprintf (stream, "Included from: [%d] %s\n", includer_ix,
+              includer_map ? ORDINARY_MAP_FILE_NAME (includer_map) : "None");
+    }
+  else
+    fprintf (stream, "Macro: %s (%u tokens)\n",
+            linemap_map_get_macro_name (map),
+            MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+  fprintf (stream, "\n");
 }
 
+
 /* Dump debugging information about source location LOC into the file
    stream STREAM. SET is the line map set LOC comes from.  */
 
@@ -1116,30 +1214,133 @@ linemap_dump_location (struct line_maps *set,
 {
   const struct line_map *map;
   source_location location;
-  const char *path, *from;
-  int l,c,s,e;
+  const char *path = "", *from = "";
+  int l = -1, c = -1, s = -1, e = -1;
 
   if (loc == 0)
     return;
 
   location =
     linemap_resolve_location (set, loc, LRK_MACRO_DEFINITION_LOCATION, &map);
-  path = LINEMAP_FILE (map);
-
-  l = SOURCE_LINE (map, location);
-  c = SOURCE_COLUMN (map, location);
-  s = LINEMAP_SYSP (map) != 0;
-  e = location != loc;
 
-  if (e)
-    from = "N/A";
+  if (map == NULL)
+    /* Only reserved locations can be tolerated in this case.  */
+    linemap_assert (location < RESERVED_LOCATION_COUNT);
   else
-    from = (INCLUDED_FROM (set, map))
-      ? LINEMAP_FILE (INCLUDED_FROM (set, map))
-      : "<NULL>";
+    {
+      path = LINEMAP_FILE (map);
+      l = SOURCE_LINE (map, location);
+      c = SOURCE_COLUMN (map, location);
+      s = LINEMAP_SYSP (map) != 0;
+      e = location != loc;
+      if (e)
+       from = "N/A";
+      else
+       from = (INCLUDED_FROM (set, map))
+         ? LINEMAP_FILE (INCLUDED_FROM (set, map))
+         : "<NULL>";
+    }
 
   /* P: path, L: line, C: column, S: in-system-header, M: map address,
-     E: macro expansion?.   */
-  fprintf (stream, "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%d}",
-          path, from, l, c, s, (void*)map, e, loc);
+     E: macro expansion?, LOC: original location, R: resolved location   */
+  fprintf (stream, "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%d,R:%d}",
+          path, from, l, c, s, (void*)map, e, loc, location);
+}
+
+/* Compute and return statistics about the memory consumption of some
+   parts of the line table SET.  */
+
+void
+linemap_get_statistics (struct line_maps *set,
+                       struct linemap_stats *s)
+{
+  long ordinary_maps_allocated_size, ordinary_maps_used_size,
+    macro_maps_allocated_size, macro_maps_used_size,
+    macro_maps_locations_size = 0, duplicated_macro_maps_locations_size = 0;
+
+  struct line_map *cur_map;
+
+  ordinary_maps_allocated_size =
+    LINEMAPS_ORDINARY_ALLOCATED (set) * sizeof (struct line_map);
+
+  ordinary_maps_used_size =
+    LINEMAPS_ORDINARY_USED (set) * sizeof (struct line_map);
+
+  macro_maps_allocated_size =
+    LINEMAPS_MACRO_ALLOCATED (set) * sizeof (struct line_map);
+
+  for (cur_map = LINEMAPS_MACRO_MAPS (set);
+       cur_map && cur_map <= LINEMAPS_LAST_MACRO_MAP (set);
+       ++cur_map)
+    {
+      unsigned i;
+
+      linemap_assert (linemap_macro_expansion_map_p (cur_map));
+
+      macro_maps_locations_size +=
+       2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map) * sizeof (source_location);
+
+      for (i = 0; i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map); i += 2)
+       {
+         if (MACRO_MAP_LOCATIONS (cur_map)[i] ==
+             MACRO_MAP_LOCATIONS (cur_map)[i + 1])
+           duplicated_macro_maps_locations_size +=
+             sizeof (source_location);
+       }
+    }
+
+  macro_maps_used_size =
+    LINEMAPS_MACRO_USED (set) * sizeof (struct line_map);
+
+  s->num_ordinary_maps_allocated = LINEMAPS_ORDINARY_ALLOCATED (set);
+  s->num_ordinary_maps_used = LINEMAPS_ORDINARY_USED (set);
+  s->ordinary_maps_allocated_size = ordinary_maps_allocated_size;
+  s->ordinary_maps_used_size = ordinary_maps_used_size;
+  s->num_expanded_macros = num_expanded_macros_counter;
+  s->num_macro_tokens = num_macro_tokens_counter;
+  s->num_macro_maps_used = LINEMAPS_MACRO_USED (set);
+  s->macro_maps_allocated_size = macro_maps_allocated_size;
+  s->macro_maps_locations_size = macro_maps_locations_size;
+  s->macro_maps_used_size = macro_maps_used_size;
+  s->duplicated_macro_maps_locations_size =
+    duplicated_macro_maps_locations_size;
+}
+
+
+/* Dump line table SET to STREAM.  If STREAM is NULL, stderr is used.
+   NUM_ORDINARY specifies how many ordinary maps to dump.  NUM_MACRO
+   specifies how many macro maps to dump.  */
+
+void
+line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary,
+                unsigned int num_macro)
+{
+  unsigned int i;
+
+  if (set == NULL)
+    return;
+
+  if (stream == NULL)
+    stream = stderr;
+
+  fprintf (stream, "# of ordinary maps:  %d\n", LINEMAPS_ORDINARY_USED (set));
+  fprintf (stream, "# of macro maps:     %d\n", LINEMAPS_MACRO_USED (set));
+  fprintf (stream, "Include stack depth: %d\n", set->depth);
+  fprintf (stream, "Highest location:    %u\n", set->highest_location);
+
+  if (num_ordinary)
+    {
+      fprintf (stream, "\nOrdinary line maps\n");
+      for (i = 0; i < num_ordinary && i < LINEMAPS_ORDINARY_USED (set); i++)
+       linemap_dump (stream, set, i, false);
+      fprintf (stream, "\n");
+    }
+
+  if (num_macro)
+    {
+      fprintf (stream, "\nMacro line maps\n");
+      for (i = 0; i < num_macro && i < LINEMAPS_MACRO_USED (set); i++)
+       linemap_dump (stream, set, i, true);
+      fprintf (stream, "\n");
+    }
 }