Merge aosp-toolchain/gcc/gcc-4_9 changes.
[official-gcc.git] / gcc-4_9-mobile / gcc / input.c
blobc819303b5e19841a83f37f0b56a0810a65ac8ed1
1 /* Data and functions related to line maps and input files.
2 Copyright (C) 2004-2014 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "intl.h"
24 #include "input.h"
25 #include "vec.h"
27 /* This is a cache used by get_next_line to store the content of a
28 file to be searched for file lines. */
29 struct fcache
31 /* These are information used to store a line boundary. */
32 struct line_info
34 /* The line number. It starts from 1. */
35 size_t line_num;
37 /* The position (byte count) of the beginning of the line,
38 relative to the file data pointer. This starts at zero. */
39 size_t start_pos;
41 /* The position (byte count) of the last byte of the line. This
42 normally points to the '\n' character, or to one byte after the
43 last byte of the file, if the file doesn't contain a '\n'
44 character. */
45 size_t end_pos;
47 line_info (size_t l, size_t s, size_t e)
48 : line_num (l), start_pos (s), end_pos (e)
51 line_info ()
52 :line_num (0), start_pos (0), end_pos (0)
56 /* The number of time this file has been accessed. This is used
57 to designate which file cache to evict from the cache
58 array. */
59 unsigned use_count;
61 const char *file_path;
63 FILE *fp;
65 /* This points to the content of the file that we've read so
66 far. */
67 char *data;
69 /* The size of the DATA array above.*/
70 size_t size;
72 /* The number of bytes read from the underlying file so far. This
73 must be less (or equal) than SIZE above. */
74 size_t nb_read;
76 /* The index of the beginning of the current line. */
77 size_t line_start_idx;
79 /* The number of the previous line read. This starts at 1. Zero
80 means we've read no line so far. */
81 size_t line_num;
83 /* This is the total number of lines of the current file. At the
84 moment, we try to get this information from the line map
85 subsystem. Note that this is just a hint. When using the C++
86 front-end, this hint is correct because the input file is then
87 completely tokenized before parsing starts; so the line map knows
88 the number of lines before compilation really starts. For e.g,
89 the C front-end, it can happen that we start emitting diagnostics
90 before the line map has seen the end of the file. */
91 size_t total_lines;
93 /* This is a record of the beginning and end of the lines we've seen
94 while reading the file. This is useful to avoid walking the data
95 from the beginning when we are asked to read a line that is
96 before LINE_START_IDX above. Note that the maximum size of this
97 record is fcache_line_record_size, so that the memory consumption
98 doesn't explode. We thus scale total_lines down to
99 fcache_line_record_size. */
100 vec<line_info, va_heap> line_record;
102 fcache ();
103 ~fcache ();
106 /* Current position in real source file. */
108 location_t input_location;
110 struct line_maps *line_table;
112 static vec<location_t> discriminator_location_locations;
113 static vec<int> discriminator_location_discriminators;
114 static location_t next_discriminator_location = UNKNOWN_LOCATION;
115 static location_t min_discriminator_location = UNKNOWN_LOCATION;
117 static fcache *fcache_tab;
118 static const size_t fcache_tab_size = 16;
119 static const size_t fcache_buffer_size = 4 * 1024;
120 static const size_t fcache_line_record_size = 100;
122 /* Expand the source location LOC into a human readable location. If
123 LOC resolves to a builtin location, the file name of the readable
124 location is set to the string "<built-in>". If EXPANSION_POINT_P is
125 TRUE and LOC is virtual, then it is resolved to the expansion
126 point of the involved macro. Otherwise, it is resolved to the
127 spelling location of the token.
129 When resolving to the spelling location of the token, if the
130 resulting location is for a built-in location (that is, it has no
131 associated line/column) in the context of a macro expansion, the
132 returned location is the first one (while unwinding the macro
133 location towards its expansion point) that is in real source
134 code. */
136 static expanded_location
137 expand_location_1 (source_location loc,
138 bool expansion_point_p)
140 expanded_location xloc;
141 const struct line_map *map;
142 enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
143 tree block = NULL;
145 if (IS_ADHOC_LOC (loc))
147 block = LOCATION_BLOCK (loc);
148 loc = LOCATION_LOCUS (loc);
151 /* If LOC describes a location with a discriminator, extract the
152 discriminator and map it to the real location. */
153 if (min_discriminator_location != UNKNOWN_LOCATION
154 && loc >= min_discriminator_location
155 && loc < next_discriminator_location)
156 loc = map_discriminator_location (loc);
158 memset (&xloc, 0, sizeof (xloc));
160 if (loc >= RESERVED_LOCATION_COUNT)
162 if (!expansion_point_p)
164 /* We want to resolve LOC to its spelling location.
166 But if that spelling location is a reserved location that
167 appears in the context of a macro expansion (like for a
168 location for a built-in token), let's consider the first
169 location (toward the expansion point) that is not reserved;
170 that is, the first location that is in real source code. */
171 loc = linemap_unwind_to_first_non_reserved_loc (line_table,
172 loc, &map);
173 lrk = LRK_SPELLING_LOCATION;
175 loc = linemap_resolve_location (line_table, loc,
176 lrk, &map);
177 xloc = linemap_expand_location (line_table, map, loc);
180 xloc.data = block;
181 if (loc <= BUILTINS_LOCATION)
182 xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
184 return xloc;
187 /* Initialize the set of cache used for files accessed by caret
188 diagnostic. */
190 static void
191 diagnostic_file_cache_init (void)
193 if (fcache_tab == NULL)
194 fcache_tab = new fcache[fcache_tab_size];
197 /* Free the ressources used by the set of cache used for files accessed
198 by caret diagnostic. */
200 void
201 diagnostic_file_cache_fini (void)
203 if (fcache_tab)
205 delete [] (fcache_tab);
206 fcache_tab = NULL;
210 /* Return the total lines number that have been read so far by the
211 line map (in the preprocessor) so far. For languages like C++ that
212 entirely preprocess the input file before starting to parse, this
213 equals the actual number of lines of the file. */
215 static size_t
216 total_lines_num (const char *file_path)
218 size_t r = 0;
219 source_location l = 0;
220 if (linemap_get_file_highest_location (line_table, file_path, &l))
222 gcc_assert (l >= RESERVED_LOCATION_COUNT);
223 expanded_location xloc = expand_location (l);
224 r = xloc.line;
226 return r;
229 /* Lookup the cache used for the content of a given file accessed by
230 caret diagnostic. Return the found cached file, or NULL if no
231 cached file was found. */
233 static fcache*
234 lookup_file_in_cache_tab (const char *file_path)
236 if (file_path == NULL)
237 return NULL;
239 diagnostic_file_cache_init ();
241 /* This will contain the found cached file. */
242 fcache *r = NULL;
243 for (unsigned i = 0; i < fcache_tab_size; ++i)
245 fcache *c = &fcache_tab[i];
246 if (c->file_path && !strcmp (c->file_path, file_path))
248 ++c->use_count;
249 r = c;
253 if (r)
254 ++r->use_count;
256 return r;
259 /* Return the file cache that has been less used, recently, or the
260 first empty one. If HIGHEST_USE_COUNT is non-null,
261 *HIGHEST_USE_COUNT is set to the highest use count of the entries
262 in the cache table. */
264 static fcache*
265 evicted_cache_tab_entry (unsigned *highest_use_count)
267 diagnostic_file_cache_init ();
269 fcache *to_evict = &fcache_tab[0];
270 unsigned huc = to_evict->use_count;
271 for (unsigned i = 1; i < fcache_tab_size; ++i)
273 fcache *c = &fcache_tab[i];
274 bool c_is_empty = (c->file_path == NULL);
276 if (c->use_count < to_evict->use_count
277 || (to_evict->file_path && c_is_empty))
278 /* We evict C because it's either an entry with a lower use
279 count or one that is empty. */
280 to_evict = c;
282 if (huc < c->use_count)
283 huc = c->use_count;
285 if (c_is_empty)
286 /* We've reached the end of the cache; subsequent elements are
287 all empty. */
288 break;
291 if (highest_use_count)
292 *highest_use_count = huc;
294 return to_evict;
297 /* Create the cache used for the content of a given file to be
298 accessed by caret diagnostic. This cache is added to an array of
299 cache and can be retrieved by lookup_file_in_cache_tab. This
300 function returns the created cache. Note that only the last
301 fcache_tab_size files are cached. */
303 static fcache*
304 add_file_to_cache_tab (const char *file_path)
307 FILE *fp = fopen (file_path, "r");
308 if (fp == NULL)
309 return NULL;
311 unsigned highest_use_count = 0;
312 fcache *r = evicted_cache_tab_entry (&highest_use_count);
313 r->file_path = file_path;
314 if (r->fp)
315 fclose (r->fp);
316 r->fp = fp;
317 r->nb_read = 0;
318 r->line_start_idx = 0;
319 r->line_num = 0;
320 r->line_record.truncate (0);
321 /* Ensure that this cache entry doesn't get evicted next time
322 add_file_to_cache_tab is called. */
323 r->use_count = ++highest_use_count;
324 r->total_lines = total_lines_num (file_path);
326 return r;
329 /* Lookup the cache used for the content of a given file accessed by
330 caret diagnostic. If no cached file was found, create a new cache
331 for this file, add it to the array of cached file and return
332 it. */
334 static fcache*
335 lookup_or_add_file_to_cache_tab (const char *file_path)
337 fcache *r = lookup_file_in_cache_tab (file_path);
338 if (r == NULL)
339 r = add_file_to_cache_tab (file_path);
340 return r;
343 /* Default constructor for a cache of file used by caret
344 diagnostic. */
346 fcache::fcache ()
347 : use_count (0), file_path (NULL), fp (NULL), data (0),
348 size (0), nb_read (0), line_start_idx (0), line_num (0),
349 total_lines (0)
351 line_record.create (0);
354 /* Destructor for a cache of file used by caret diagnostic. */
356 fcache::~fcache ()
358 if (fp)
360 fclose (fp);
361 fp = NULL;
363 if (data)
365 XDELETEVEC (data);
366 data = 0;
368 line_record.release ();
371 /* Returns TRUE iff the cache would need to be filled with data coming
372 from the file. That is, either the cache is empty or full or the
373 current line is empty. Note that if the cache is full, it would
374 need to be extended and filled again. */
376 static bool
377 needs_read (fcache *c)
379 return (c->nb_read == 0
380 || c->nb_read == c->size
381 || (c->line_start_idx >= c->nb_read - 1));
384 /* Return TRUE iff the cache is full and thus needs to be
385 extended. */
387 static bool
388 needs_grow (fcache *c)
390 return c->nb_read == c->size;
393 /* Grow the cache if it needs to be extended. */
395 static void
396 maybe_grow (fcache *c)
398 if (!needs_grow (c))
399 return;
401 size_t size = c->size == 0 ? fcache_buffer_size : c->size * 2;
402 c->data = XRESIZEVEC (char, c->data, size + 1);
403 c->size = size;
406 /* Read more data into the cache. Extends the cache if need be.
407 Returns TRUE iff new data could be read. */
409 static bool
410 read_data (fcache *c)
412 if (feof (c->fp) || ferror (c->fp))
413 return false;
415 maybe_grow (c);
417 char * from = c->data + c->nb_read;
418 size_t to_read = c->size - c->nb_read;
419 size_t nb_read = fread (from, 1, to_read, c->fp);
421 if (ferror (c->fp))
422 return false;
424 c->nb_read += nb_read;
425 return !!nb_read;
428 /* Read new data iff the cache needs to be filled with more data
429 coming from the file FP. Return TRUE iff the cache was filled with
430 mode data. */
432 static bool
433 maybe_read_data (fcache *c)
435 if (!needs_read (c))
436 return false;
437 return read_data (c);
440 /* Read a new line from file FP, using C as a cache for the data
441 coming from the file. Upon successful completion, *LINE is set to
442 the beginning of the line found. Space for that line has been
443 allocated in the cache thus *LINE has the same life time as C.
444 *LINE_LEN is set to the length of the line. Note that the line
445 does not contain any terminal delimiter. This function returns
446 true if some data was read or process from the cache, false
447 otherwise. Note that subsequent calls to get_next_line return the
448 next lines of the file and might overwrite the content of
449 *LINE. */
451 static bool
452 get_next_line (fcache *c, char **line, ssize_t *line_len)
454 /* Fill the cache with data to process. */
455 maybe_read_data (c);
457 size_t remaining_size = c->nb_read - c->line_start_idx;
458 if (remaining_size == 0)
459 /* There is no more data to process. */
460 return false;
462 char *line_start = c->data + c->line_start_idx;
464 char *next_line_start = NULL;
465 size_t len = 0;
466 char *line_end = (char *) memchr (line_start, '\n', remaining_size);
467 if (line_end == NULL)
469 /* We haven't found the end-of-line delimiter in the cache.
470 Fill the cache with more data from the file and look for the
471 '\n'. */
472 while (maybe_read_data (c))
474 line_start = c->data + c->line_start_idx;
475 remaining_size = c->nb_read - c->line_start_idx;
476 line_end = (char *) memchr (line_start, '\n', remaining_size);
477 if (line_end != NULL)
479 next_line_start = line_end + 1;
480 break;
483 if (line_end == NULL)
484 /* We've loadded all the file into the cache and still no
485 '\n'. Let's say the line ends up at one byte passed the
486 end of the file. This is to stay consistent with the case
487 of when the line ends up with a '\n' and line_end points to
488 that terminal '\n'. That consistency is useful below in
489 the len calculation. */
490 line_end = c->data + c->nb_read ;
492 else
493 next_line_start = line_end + 1;
495 if (ferror (c->fp))
496 return -1;
498 /* At this point, we've found the end of the of line. It either
499 points to the '\n' or to one byte after the last byte of the
500 file. */
501 gcc_assert (line_end != NULL);
503 len = line_end - line_start;
505 if (c->line_start_idx < c->nb_read)
506 *line = line_start;
508 ++c->line_num;
510 /* Before we update our line record, make sure the hint about the
511 total number of lines of the file is correct. If it's not, then
512 we give up recording line boundaries from now on. */
513 bool update_line_record = true;
514 if (c->line_num > c->total_lines)
515 update_line_record = false;
517 /* Now update our line record so that re-reading lines from the
518 before c->line_start_idx is faster. */
519 if (update_line_record
520 && c->line_record.length () < fcache_line_record_size)
522 /* If the file lines fits in the line record, we just record all
523 its lines ...*/
524 if (c->total_lines <= fcache_line_record_size
525 && c->line_num > c->line_record.length ())
526 c->line_record.safe_push (fcache::line_info (c->line_num,
527 c->line_start_idx,
528 line_end - c->data));
529 else if (c->total_lines > fcache_line_record_size)
531 /* ... otherwise, we just scale total_lines down to
532 (fcache_line_record_size lines. */
533 size_t n = (c->line_num * fcache_line_record_size) / c->total_lines;
534 if (c->line_record.length () == 0
535 || n >= c->line_record.length ())
536 c->line_record.safe_push (fcache::line_info (c->line_num,
537 c->line_start_idx,
538 line_end - c->data));
542 /* Update c->line_start_idx so that it points to the next line to be
543 read. */
544 if (next_line_start)
545 c->line_start_idx = next_line_start - c->data;
546 else
547 /* We didn't find any terminal '\n'. Let's consider that the end
548 of line is the end of the data in the cache. The next
549 invocation of get_next_line will either read more data from the
550 underlying file or return false early because we've reached the
551 end of the file. */
552 c->line_start_idx = c->nb_read;
554 *line_len = len;
556 return true;
559 /* Reads the next line from FILE into *LINE. If *LINE is too small
560 (or NULL) it is allocated (or extended) to have enough space to
561 containe the line. *LINE_LENGTH must contain the size of the
562 initial*LINE buffer. It's then updated by this function to the
563 actual length of the returned line. Note that the returned line
564 can contain several zero bytes. Also note that the returned string
565 is allocated in static storage that is going to be re-used by
566 subsequent invocations of read_line. */
568 static bool
569 read_next_line (fcache *cache, char ** line, ssize_t *line_len)
571 char *l = NULL;
572 ssize_t len = 0;
574 if (!get_next_line (cache, &l, &len))
575 return false;
577 if (*line == NULL)
578 *line = XNEWVEC (char, len);
579 else
580 if (*line_len < len)
581 *line = XRESIZEVEC (char, *line, len);
583 memcpy (*line, l, len);
584 *line_len = len;
586 return true;
589 /* Consume the next bytes coming from the cache (or from its
590 underlying file if there are remaining unread bytes in the file)
591 until we reach the next end-of-line (or end-of-file). There is no
592 copying from the cache involved. Return TRUE upon successful
593 completion. */
595 static bool
596 goto_next_line (fcache *cache)
598 char *l;
599 ssize_t len;
601 return get_next_line (cache, &l, &len);
604 /* Read an arbitrary line number LINE_NUM from the file cached in C.
605 The line is copied into *LINE. *LINE_LEN must have been set to the
606 length of *LINE. If *LINE is too small (or NULL) it's extended (or
607 allocated) and *LINE_LEN is adjusted accordingly. *LINE ends up
608 with a terminal zero byte and can contain additional zero bytes.
609 This function returns bool if a line was read. */
611 static bool
612 read_line_num (fcache *c, size_t line_num,
613 char ** line, ssize_t *line_len)
615 gcc_assert (line_num > 0);
617 if (line_num <= c->line_num)
619 /* We've been asked to read lines that are before c->line_num.
620 So lets use our line record (if it's not empty) to try to
621 avoid re-reading the file from the beginning again. */
623 if (c->line_record.is_empty ())
625 c->line_start_idx = 0;
626 c->line_num = 0;
628 else
630 fcache::line_info *i = NULL;
631 if (c->total_lines <= fcache_line_record_size)
633 /* In languages where the input file is not totally
634 preprocessed up front, the c->total_lines hint
635 can be smaller than the number of lines of the
636 file. In that case, only the first
637 c->total_lines have been recorded.
639 Otherwise, the first c->total_lines we've read have
640 their start/end recorded here. */
641 i = (line_num <= c->total_lines)
642 ? &c->line_record[line_num - 1]
643 : &c->line_record[c->total_lines - 1];
644 gcc_assert (i->line_num <= line_num);
646 else
648 /* So the file had more lines than our line record
649 size. Thus the number of lines we've recorded has
650 been scaled down to fcache_line_reacord_size. Let's
651 pick the start/end of the recorded line that is
652 closest to line_num. */
653 size_t n = (line_num <= c->total_lines)
654 ? line_num * fcache_line_record_size / c->total_lines
655 : c ->line_record.length () - 1;
656 if (n < c->line_record.length ())
658 i = &c->line_record[n];
659 gcc_assert (i->line_num <= line_num);
663 if (i && i->line_num == line_num)
665 /* We have the start/end of the line. Let's just copy
666 it again and we are done. */
667 ssize_t len = i->end_pos - i->start_pos + 1;
668 if (*line_len < len)
669 *line = XRESIZEVEC (char, *line, len);
670 memmove (*line, c->data + i->start_pos, len);
671 (*line)[len - 1] = '\0';
672 *line_len = --len;
673 return true;
676 if (i)
678 c->line_start_idx = i->start_pos;
679 c->line_num = i->line_num - 1;
681 else
683 c->line_start_idx = 0;
684 c->line_num = 0;
689 /* Let's walk from line c->line_num up to line_num - 1, without
690 copying any line. */
691 while (c->line_num < line_num - 1)
692 if (!goto_next_line (c))
693 return false;
695 /* The line we want is the next one. Let's read and copy it back to
696 the caller. */
697 return read_next_line (c, line, line_len);
700 /* Return the physical source line that corresponds to xloc in a
701 buffer that is statically allocated. The newline is replaced by
702 the null character. Note that the line can contain several null
703 characters, so LINE_LEN, if non-null, points to the actual length
704 of the line. */
706 const char *
707 location_get_source_line (expanded_location xloc,
708 int *line_len)
710 static char *buffer;
711 static ssize_t len;
713 if (xloc.line == 0)
714 return NULL;
716 fcache *c = lookup_or_add_file_to_cache_tab (xloc.file);
717 if (c == NULL)
718 return NULL;
720 bool read = read_line_num (c, xloc.line, &buffer, &len);
722 if (read && line_len)
723 *line_len = len;
725 return read ? buffer : NULL;
728 /* Expand the source location LOC into a human readable location. If
729 LOC is virtual, it resolves to the expansion point of the involved
730 macro. If LOC resolves to a builtin location, the file name of the
731 readable location is set to the string "<built-in>". */
733 expanded_location
734 expand_location (source_location loc)
736 return expand_location_1 (loc, /*expansion_point_p=*/true);
739 /* Expand the source location LOC into a human readable location. If
740 LOC is virtual, it resolves to the expansion location of the
741 relevant macro. If LOC resolves to a builtin location, the file
742 name of the readable location is set to the string
743 "<built-in>". */
745 expanded_location
746 expand_location_to_spelling_point (source_location loc)
748 return expand_location_1 (loc, /*expansion_piont_p=*/false);
751 /* If LOCATION is in a system header and if it's a virtual location for
752 a token coming from the expansion of a macro M, unwind it to the
753 location of the expansion point of M. Otherwise, just return
754 LOCATION.
756 This is used for instance when we want to emit diagnostics about a
757 token that is located in a macro that is itself defined in a system
758 header -- e.g for the NULL macro. In that case, if LOCATION is
759 passed to diagnostics emitting functions like warning_at as is, no
760 diagnostic won't be emitted. */
762 source_location
763 expansion_point_location_if_in_system_header (source_location location)
765 if (in_system_header_at (location))
766 location = linemap_resolve_location (line_table, location,
767 LRK_MACRO_EXPANSION_POINT,
768 NULL);
769 return location;
772 #define ONE_K 1024
773 #define ONE_M (ONE_K * ONE_K)
775 /* Display a number as an integer multiple of either:
776 - 1024, if said integer is >= to 10 K (in base 2)
777 - 1024 * 1024, if said integer is >= 10 M in (base 2)
779 #define SCALE(x) ((unsigned long) ((x) < 10 * ONE_K \
780 ? (x) \
781 : ((x) < 10 * ONE_M \
782 ? (x) / ONE_K \
783 : (x) / ONE_M)))
785 /* For a given integer, display either:
786 - the character 'k', if the number is higher than 10 K (in base 2)
787 but strictly lower than 10 M (in base 2)
788 - the character 'M' if the number is higher than 10 M (in base2)
789 - the charcter ' ' if the number is strictly lower than 10 K */
790 #define STAT_LABEL(x) ((x) < 10 * ONE_K ? ' ' : ((x) < 10 * ONE_M ? 'k' : 'M'))
792 /* Display an integer amount as multiple of 1K or 1M (in base 2).
793 Display the correct unit (either k, M, or ' ') after the amout, as
794 well. */
795 #define FORMAT_AMOUNT(size) SCALE (size), STAT_LABEL (size)
797 /* Dump statistics to stderr about the memory usage of the line_table
798 set of line maps. This also displays some statistics about macro
799 expansion. */
801 void
802 dump_line_table_statistics (void)
804 struct linemap_stats s;
805 long total_used_map_size,
806 macro_maps_size,
807 total_allocated_map_size;
809 memset (&s, 0, sizeof (s));
811 linemap_get_statistics (line_table, &s);
813 macro_maps_size = s.macro_maps_used_size
814 + s.macro_maps_locations_size;
816 total_allocated_map_size = s.ordinary_maps_allocated_size
817 + s.macro_maps_allocated_size
818 + s.macro_maps_locations_size;
820 total_used_map_size = s.ordinary_maps_used_size
821 + s.macro_maps_used_size
822 + s.macro_maps_locations_size;
824 fprintf (stderr, "Number of expanded macros: %5ld\n",
825 s.num_expanded_macros);
826 if (s.num_expanded_macros != 0)
827 fprintf (stderr, "Average number of tokens per macro expansion: %5ld\n",
828 s.num_macro_tokens / s.num_expanded_macros);
829 fprintf (stderr,
830 "\nLine Table allocations during the "
831 "compilation process\n");
832 fprintf (stderr, "Number of ordinary maps used: %5ld%c\n",
833 SCALE (s.num_ordinary_maps_used),
834 STAT_LABEL (s.num_ordinary_maps_used));
835 fprintf (stderr, "Ordinary map used size: %5ld%c\n",
836 SCALE (s.ordinary_maps_used_size),
837 STAT_LABEL (s.ordinary_maps_used_size));
838 fprintf (stderr, "Number of ordinary maps allocated: %5ld%c\n",
839 SCALE (s.num_ordinary_maps_allocated),
840 STAT_LABEL (s.num_ordinary_maps_allocated));
841 fprintf (stderr, "Ordinary maps allocated size: %5ld%c\n",
842 SCALE (s.ordinary_maps_allocated_size),
843 STAT_LABEL (s.ordinary_maps_allocated_size));
844 fprintf (stderr, "Number of macro maps used: %5ld%c\n",
845 SCALE (s.num_macro_maps_used),
846 STAT_LABEL (s.num_macro_maps_used));
847 fprintf (stderr, "Macro maps used size: %5ld%c\n",
848 SCALE (s.macro_maps_used_size),
849 STAT_LABEL (s.macro_maps_used_size));
850 fprintf (stderr, "Macro maps locations size: %5ld%c\n",
851 SCALE (s.macro_maps_locations_size),
852 STAT_LABEL (s.macro_maps_locations_size));
853 fprintf (stderr, "Macro maps size: %5ld%c\n",
854 SCALE (macro_maps_size),
855 STAT_LABEL (macro_maps_size));
856 fprintf (stderr, "Duplicated maps locations size: %5ld%c\n",
857 SCALE (s.duplicated_macro_maps_locations_size),
858 STAT_LABEL (s.duplicated_macro_maps_locations_size));
859 fprintf (stderr, "Total allocated maps size: %5ld%c\n",
860 SCALE (total_allocated_map_size),
861 STAT_LABEL (total_allocated_map_size));
862 fprintf (stderr, "Total used maps size: %5ld%c\n",
863 SCALE (total_used_map_size),
864 STAT_LABEL (total_used_map_size));
865 fprintf (stderr, "\n");
868 /* Associate the DISCRIMINATOR with LOCUS, and return a new locus.
869 We associate discriminators with a locus by allocating location_t
870 values beyond those assigned by libcpp. Each new value is mapped
871 directly to a real location_t value, and separately to the
872 discriminator. */
874 location_t
875 location_with_discriminator (location_t locus, int discriminator)
877 tree block = LOCATION_BLOCK (locus);
878 location_t ret;
879 int i;
880 locus = map_discriminator_location (locus);
882 if (locus == UNKNOWN_LOCATION)
883 return block ? COMBINE_LOCATION_DATA (line_table, locus, block)
884 : locus;
886 if (min_discriminator_location == UNKNOWN_LOCATION)
888 min_discriminator_location = line_table->highest_location + 1;
889 next_discriminator_location = min_discriminator_location;
892 /* Traverse the last few discriminator_locations to see if we can reuse
893 the entry. */
894 for (i = next_discriminator_location - min_discriminator_location - 1;
895 (i >= 0 && LOCATION_LINE (discriminator_location_locations[i]) ==
896 LOCATION_LINE (locus)
897 && discriminator_location_discriminators[i] == discriminator);
898 i--)
899 if (discriminator_location_locations[i] == locus)
900 return (block
901 ? COMBINE_LOCATION_DATA (line_table, min_discriminator_location + i,
902 block)
903 : min_discriminator_location + i);
905 discriminator_location_locations.safe_push(locus);
906 discriminator_location_discriminators.safe_push(discriminator);
908 ret = (block
909 ? COMBINE_LOCATION_DATA (line_table, next_discriminator_location, block)
910 : next_discriminator_location);
912 next_discriminator_location++;
913 return ret;
916 /* Return TRUE if LOCUS represents a location with a discriminator. */
918 bool
919 has_discriminator (location_t locus)
921 locus = LOCATION_LOCUS (locus);
922 return (min_discriminator_location != UNKNOWN_LOCATION
923 && locus >= min_discriminator_location
924 && locus < next_discriminator_location);
927 /* Return the real location_t value for LOCUS. */
929 location_t
930 map_discriminator_location (location_t locus)
932 locus = LOCATION_LOCUS (locus);
933 if (! has_discriminator (locus))
934 return locus;
935 return (location_t) discriminator_location_locations[locus - min_discriminator_location];
938 /* Return the discriminator for LOCUS. */
941 get_discriminator_from_locus (location_t locus)
943 locus = LOCATION_LOCUS (locus);
944 if (! has_discriminator (locus))
945 return 0;
946 return discriminator_location_discriminators[locus - min_discriminator_location];