1 /* Read and write coverage files, and associated functionality.
2    Copyright (C) 1990-2020 Free Software Foundation, Inc.
3    Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
4    based on some ideas from Dain Samples of UC Berkeley.
5    Further mangling by Bob Manson, Cygnus Support.
6    Further mangled by Nathan Sidwell, CodeSourcery
7 
8 This file is part of GCC.
9 
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
14 
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3.  If not see
22 <http://www.gnu.org/licenses/>.  */
23 
24 
25 #define GCOV_LINKAGE
26 
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "backend.h"
31 #include "target.h"
32 #include "rtl.h"
33 #include "tree.h"
34 #include "tree-pass.h"
35 #include "memmodel.h"
36 #include "tm_p.h"
37 #include "stringpool.h"
38 #include "cgraph.h"
39 #include "coverage.h"
40 #include "diagnostic-core.h"
41 #include "fold-const.h"
42 #include "stor-layout.h"
43 #include "output.h"
44 #include "toplev.h"
45 #include "langhooks.h"
46 #include "tree-iterator.h"
47 #include "context.h"
48 #include "pass_manager.h"
49 #include "intl.h"
50 #include "auto-profile.h"
51 #include "profile.h"
52 #include "diagnostic.h"
53 
54 #include "gcov-io.c"
55 
56 struct GTY((chain_next ("%h.next"))) coverage_data
57 {
58   struct coverage_data *next;	 /* next function */
59   unsigned ident;		 /* function ident */
60   unsigned lineno_checksum;	 /* function lineno checksum */
61   unsigned cfg_checksum;	 /* function cfg checksum */
62   tree fn_decl;			 /* the function decl */
63   tree ctr_vars[GCOV_COUNTERS];	 /* counter variables.  */
64 };
65 
66 /* Counts information for a function.  */
67 struct counts_entry : pointer_hash <counts_entry>
68 {
69   /* We hash by  */
70   unsigned ident;
71   unsigned ctr;
72 
73   /* Store  */
74   unsigned lineno_checksum;
75   unsigned cfg_checksum;
76   gcov_type *counts;
77   unsigned n_counts;
78 
79   /* hash_table support.  */
80   static inline hashval_t hash (const counts_entry *);
81   static int equal (const counts_entry *, const counts_entry *);
82   static void remove (counts_entry *);
83 };
84 
85 static GTY(()) struct coverage_data *functions_head = 0;
86 static struct coverage_data **functions_tail = &functions_head;
87 static unsigned no_coverage = 0;
88 
89 /* Cumulative counter information for whole program.  */
90 static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
91 
92 /* Counter information for current function.  */
93 static unsigned fn_ctr_mask; /* Mask of counters used.  */
94 static GTY(()) tree fn_v_ctrs[GCOV_COUNTERS];   /* counter variables.  */
95 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
96 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
97 
98 /* Coverage info VAR_DECL and function info type nodes.  */
99 static GTY(()) tree gcov_info_var;
100 static GTY(()) tree gcov_fn_info_type;
101 static GTY(()) tree gcov_fn_info_ptr_type;
102 
103 /* Name of the notes (gcno) output file.  The "bbg" prefix is for
104    historical reasons, when the notes file contained only the
105    basic block graph notes.
106    If this is NULL we're not writing to the notes file.  */
107 static char *bbg_file_name;
108 
109 /* File stamp for notes file.  */
110 static unsigned bbg_file_stamp;
111 
112 /* Name of the count data (gcda) file.  */
113 static char *da_file_name;
114 
115 /* The names of merge functions for counters.  */
116 #define STR(str) #str
117 #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) STR(__gcov_merge ## FN_TYPE),
118 static const char *const ctr_merge_functions[GCOV_COUNTERS] = {
119 #include "gcov-counter.def"
120 };
121 #undef DEF_GCOV_COUNTER
122 #undef STR
123 
124 #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) NAME,
125 static const char *const ctr_names[GCOV_COUNTERS] = {
126 #include "gcov-counter.def"
127 };
128 #undef DEF_GCOV_COUNTER
129 
130 /* Forward declarations.  */
131 static void read_counts_file (void);
132 static tree build_var (tree, tree, int);
133 static void build_fn_info_type (tree, unsigned, tree);
134 static void build_info_type (tree, tree);
135 static tree build_fn_info (const struct coverage_data *, tree, tree);
136 static tree build_info (tree, tree);
137 static bool coverage_obj_init (void);
138 static vec<constructor_elt, va_gc> *coverage_obj_fn
139 (vec<constructor_elt, va_gc> *, tree, struct coverage_data const *);
140 static void coverage_obj_finish (vec<constructor_elt, va_gc> *);
141 
142 /* Return the type node for gcov_type.  */
143 
144 tree
get_gcov_type(void)145 get_gcov_type (void)
146 {
147   scalar_int_mode mode
148     = smallest_int_mode_for_size (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32);
149   return lang_hooks.types.type_for_mode (mode, false);
150 }
151 
152 /* Return the type node for gcov_unsigned_t.  */
153 
154 static tree
get_gcov_unsigned_t(void)155 get_gcov_unsigned_t (void)
156 {
157   scalar_int_mode mode = smallest_int_mode_for_size (32);
158   return lang_hooks.types.type_for_mode (mode, true);
159 }
160 
161 inline hashval_t
hash(const counts_entry * entry)162 counts_entry::hash (const counts_entry *entry)
163 {
164   return entry->ident * GCOV_COUNTERS + entry->ctr;
165 }
166 
167 inline int
equal(const counts_entry * entry1,const counts_entry * entry2)168 counts_entry::equal (const counts_entry *entry1, const counts_entry *entry2)
169 {
170   return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
171 }
172 
173 inline void
remove(counts_entry * entry)174 counts_entry::remove (counts_entry *entry)
175 {
176   free (entry->counts);
177   free (entry);
178 }
179 
180 /* Hash table of count data.  */
181 static hash_table<counts_entry> *counts_hash;
182 
183 /* Read in the counts file, if available.  */
184 
185 static void
read_counts_file(void)186 read_counts_file (void)
187 {
188   gcov_unsigned_t fn_ident = 0;
189   gcov_unsigned_t tag;
190   int is_error = 0;
191   unsigned lineno_checksum = 0;
192   unsigned cfg_checksum = 0;
193 
194   if (!gcov_open (da_file_name, 1))
195     return;
196 
197   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
198     {
199       warning (0, "%qs is not a gcov data file", da_file_name);
200       gcov_close ();
201       return;
202     }
203   else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
204     {
205       char v[4], e[4];
206 
207       GCOV_UNSIGNED2STRING (v, tag);
208       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
209 
210       warning (0, "%qs is version %q.*s, expected version %q.*s",
211  	       da_file_name, 4, v, 4, e);
212       gcov_close ();
213       return;
214     }
215 
216   /* Read the stamp, used for creating a generation count.  */
217   tag = gcov_read_unsigned ();
218   bbg_file_stamp = crc32_unsigned (bbg_file_stamp, tag);
219 
220   counts_hash = new hash_table<counts_entry> (10);
221   while ((tag = gcov_read_unsigned ()))
222     {
223       gcov_unsigned_t length;
224       gcov_position_t offset;
225 
226       length = gcov_read_unsigned ();
227       offset = gcov_position ();
228       if (tag == GCOV_TAG_FUNCTION)
229 	{
230 	  if (length)
231 	    {
232 	      fn_ident = gcov_read_unsigned ();
233 	      lineno_checksum = gcov_read_unsigned ();
234 	      cfg_checksum = gcov_read_unsigned ();
235 	    }
236 	  else
237 	    fn_ident = lineno_checksum = cfg_checksum = 0;
238 	}
239       else if (tag == GCOV_TAG_OBJECT_SUMMARY)
240 	{
241 	  profile_info = XCNEW (gcov_summary);
242 	  profile_info->runs = gcov_read_unsigned ();
243 	  profile_info->sum_max = gcov_read_unsigned ();
244 	}
245       else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
246 	{
247 	  counts_entry **slot, *entry, elt;
248 	  unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
249 	  unsigned ix;
250 
251 	  elt.ident = fn_ident;
252 	  elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
253 
254 	  slot = counts_hash->find_slot (&elt, INSERT);
255 	  entry = *slot;
256 	  if (!entry)
257 	    {
258 	      *slot = entry = XCNEW (counts_entry);
259 	      entry->ident = fn_ident;
260 	      entry->ctr = elt.ctr;
261 	      entry->lineno_checksum = lineno_checksum;
262 	      entry->cfg_checksum = cfg_checksum;
263 	      entry->counts = XCNEWVEC (gcov_type, n_counts);
264 	      entry->n_counts = n_counts;
265 	    }
266 	  else if (entry->lineno_checksum != lineno_checksum
267 		   || entry->cfg_checksum != cfg_checksum)
268 	    {
269 	      error ("profile data for function %u is corrupted", fn_ident);
270 	      error ("checksum is (%x,%x) instead of (%x,%x)",
271 		     entry->lineno_checksum, entry->cfg_checksum,
272 		     lineno_checksum, cfg_checksum);
273 	      delete counts_hash;
274 	      counts_hash = NULL;
275 	      break;
276 	    }
277 	  for (ix = 0; ix != n_counts; ix++)
278 	    entry->counts[ix] += gcov_read_counter ();
279 	}
280       gcov_sync (offset, length);
281       if ((is_error = gcov_is_error ()))
282 	{
283 	  error (is_error < 0
284 		 ? G_("%qs has overflowed")
285 		 : G_("%qs is corrupted"),
286 		 da_file_name);
287 	  delete counts_hash;
288 	  counts_hash = NULL;
289 	  break;
290 	}
291     }
292 
293   gcov_close ();
294 }
295 
296 /* Returns the counters for a particular tag.  */
297 
298 gcov_type *
get_coverage_counts(unsigned counter,unsigned cfg_checksum,unsigned lineno_checksum,unsigned int n_counts)299 get_coverage_counts (unsigned counter, unsigned cfg_checksum,
300 		     unsigned lineno_checksum, unsigned int n_counts)
301 {
302   counts_entry *entry, elt;
303 
304   /* No hash table, no counts.  */
305   if (!counts_hash)
306     {
307       static int warned = 0;
308 
309       if (!warned++)
310 	{
311 	  warning (OPT_Wmissing_profile,
312 		   "%qs profile count data file not found",
313 		   da_file_name);
314 	  if (dump_enabled_p ())
315 	    {
316 	      dump_user_location_t loc
317 		= dump_user_location_t::from_location_t (input_location);
318 	      dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
319 			       "file %s not found, %s\n", da_file_name,
320 			       (flag_guess_branch_prob
321 				? "execution counts estimated"
322 				: "execution counts assumed to be zero"));
323 	    }
324 	}
325       return NULL;
326     }
327   if (param_profile_func_internal_id)
328     elt.ident = current_function_funcdef_no + 1;
329   else
330     {
331       gcc_assert (coverage_node_map_initialized_p ());
332       elt.ident = cgraph_node::get (current_function_decl)->profile_id;
333     }
334   elt.ctr = counter;
335   entry = counts_hash->find (&elt);
336   if (!entry)
337     {
338       if (counter == GCOV_COUNTER_ARCS)
339 	warning_at (DECL_SOURCE_LOCATION (current_function_decl),
340 		    OPT_Wmissing_profile,
341 		    "profile for function %qD not found in profile data",
342 		    current_function_decl);
343       /* The function was not emitted, or is weak and not chosen in the
344 	 final executable.  Silently fail, because there's nothing we
345 	 can do about it.  */
346       return NULL;
347     }
348 
349   if (entry->cfg_checksum != cfg_checksum || entry->n_counts != n_counts)
350     {
351       static int warned = 0;
352       bool warning_printed = false;
353 
354       if (entry->n_counts != n_counts)
355 	warning_printed =
356 	  warning_at (DECL_SOURCE_LOCATION (current_function_decl),
357 		      OPT_Wcoverage_mismatch,
358 		      "number of counters in profile data for function %qD "
359 		      "does not match "
360 		      "its profile data (counter %qs, expected %i and have %i)",
361 		      current_function_decl,
362 		      ctr_names[counter], entry->n_counts, n_counts);
363       else
364 	warning_printed =
365 	  warning_at (DECL_SOURCE_LOCATION (current_function_decl),
366 		      OPT_Wcoverage_mismatch,
367 		      "the control flow of function %qD does not match "
368 		      "its profile data (counter %qs)", current_function_decl,
369 		      ctr_names[counter]);
370       if (warning_printed && dump_enabled_p ())
371 	{
372 	  dump_user_location_t loc
373 	    = dump_user_location_t::from_function_decl (current_function_decl);
374           dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
375                            "use -Wno-error=coverage-mismatch to tolerate "
376                            "the mismatch but performance may drop if the "
377                            "function is hot\n");
378 
379 	  if (!seen_error ()
380 	      && !warned++)
381 	    {
382 	      dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
383                                "coverage mismatch ignored\n");
384 	      dump_printf (MSG_MISSED_OPTIMIZATION,
385                            flag_guess_branch_prob
386                            ? G_("execution counts estimated\n")
387                            : G_("execution counts assumed to be zero\n"));
388 	      if (!flag_guess_branch_prob)
389 		dump_printf (MSG_MISSED_OPTIMIZATION,
390                              "this can result in poorly optimized code\n");
391 	    }
392 	}
393 
394       return NULL;
395     }
396   else if (entry->lineno_checksum != lineno_checksum)
397     {
398       warning_at (DECL_SOURCE_LOCATION (current_function_decl),
399 		  OPT_Wcoverage_mismatch,
400 		  "source locations for function %qD have changed,"
401 		  " the profile data may be out of date",
402 		  current_function_decl);
403     }
404 
405   return entry->counts;
406 }
407 
408 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
409    allocation succeeded.  */
410 
411 int
coverage_counter_alloc(unsigned counter,unsigned num)412 coverage_counter_alloc (unsigned counter, unsigned num)
413 {
414   if (no_coverage)
415     return 0;
416 
417   if (!num)
418     return 1;
419 
420   if (!fn_v_ctrs[counter])
421     {
422       tree array_type = build_array_type (get_gcov_type (), NULL_TREE);
423 
424       fn_v_ctrs[counter]
425 	= build_var (current_function_decl, array_type, counter);
426     }
427 
428   fn_b_ctrs[counter] = fn_n_ctrs[counter];
429   fn_n_ctrs[counter] += num;
430 
431   fn_ctr_mask |= 1 << counter;
432   return 1;
433 }
434 
435 /* Generate a tree to access COUNTER NO.  */
436 
437 tree
tree_coverage_counter_ref(unsigned counter,unsigned no)438 tree_coverage_counter_ref (unsigned counter, unsigned no)
439 {
440   tree gcov_type_node = get_gcov_type ();
441 
442   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
443 
444   no += fn_b_ctrs[counter];
445 
446   /* "no" here is an array index, scaled to bytes later.  */
447   return build4 (ARRAY_REF, gcov_type_node, fn_v_ctrs[counter],
448 		 build_int_cst (integer_type_node, no), NULL, NULL);
449 }
450 
451 /* Generate a tree to access the address of COUNTER NO.  */
452 
453 tree
tree_coverage_counter_addr(unsigned counter,unsigned no)454 tree_coverage_counter_addr (unsigned counter, unsigned no)
455 {
456   tree gcov_type_node = get_gcov_type ();
457 
458   gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
459   no += fn_b_ctrs[counter];
460 
461   /* "no" here is an array index, scaled to bytes later.  */
462   return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
463 				       fn_v_ctrs[counter],
464 				       build_int_cst (integer_type_node, no),
465 				       NULL, NULL));
466 }
467 
468 
469 /* Generate a checksum for a string.  CHKSUM is the current
470    checksum.  */
471 
472 static unsigned
coverage_checksum_string(unsigned chksum,const char * string)473 coverage_checksum_string (unsigned chksum, const char *string)
474 {
475   int i;
476   char *dup = NULL;
477 
478   /* Look for everything that looks if it were produced by
479      get_file_function_name and zero out the second part
480      that may result from flag_random_seed.  This is not critical
481      as the checksums are used only for sanity checking.  */
482   for (i = 0; string[i]; i++)
483     {
484       int offset = 0;
485       if (!strncmp (string + i, "_GLOBAL__N_", 11))
486       offset = 11;
487       if (!strncmp (string + i, "_GLOBAL__", 9))
488       offset = 9;
489 
490       /* C++ namespaces do have scheme:
491          _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
492        since filename might contain extra underscores there seems
493        to be no better chance then walk all possible offsets looking
494        for magicnumber.  */
495       if (offset)
496 	{
497 	  for (i = i + offset; string[i]; i++)
498 	    if (string[i]=='_')
499 	      {
500 		int y;
501 
502 		for (y = 1; y < 9; y++)
503 		  if (!(string[i + y] >= '0' && string[i + y] <= '9')
504 		      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
505 		    break;
506 		if (y != 9 || string[i + 9] != '_')
507 		  continue;
508 		for (y = 10; y < 18; y++)
509 		  if (!(string[i + y] >= '0' && string[i + y] <= '9')
510 		      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
511 		    break;
512 		if (y != 18)
513 		  continue;
514 		if (!dup)
515 		  string = dup = xstrdup (string);
516 		for (y = 10; y < 18; y++)
517 		  dup[i + y] = '0';
518 	      }
519 	  break;
520 	}
521     }
522 
523   chksum = crc32_string (chksum, string);
524   free (dup);
525 
526   return chksum;
527 }
528 
529 /* Compute checksum for the current function.  We generate a CRC32.  */
530 
531 unsigned
coverage_compute_lineno_checksum(void)532 coverage_compute_lineno_checksum (void)
533 {
534   expanded_location xloc
535     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
536   unsigned chksum = xloc.line;
537 
538   if (xloc.file)
539     chksum = coverage_checksum_string (chksum, xloc.file);
540   chksum = coverage_checksum_string
541     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
542 
543   return chksum;
544 }
545 
546 /* Compute profile ID.  This is better to be unique in whole program.  */
547 
548 unsigned
coverage_compute_profile_id(struct cgraph_node * n)549 coverage_compute_profile_id (struct cgraph_node *n)
550 {
551   unsigned chksum;
552 
553   /* Externally visible symbols have unique name.  */
554   if (TREE_PUBLIC (n->decl) || DECL_EXTERNAL (n->decl) || n->unique_name)
555     {
556       chksum = coverage_checksum_string
557 	(0, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
558     }
559   else
560     {
561       expanded_location xloc
562 	= expand_location (DECL_SOURCE_LOCATION (n->decl));
563       bool use_name_only = (param_profile_func_internal_id == 0);
564 
565       chksum = (use_name_only ? 0 : xloc.line);
566       if (xloc.file)
567 	chksum = coverage_checksum_string (chksum, xloc.file);
568       chksum = coverage_checksum_string
569 	(chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
570       if (!use_name_only && first_global_object_name)
571 	chksum = coverage_checksum_string
572 	  (chksum, first_global_object_name);
573       chksum = coverage_checksum_string
574 	(chksum, aux_base_name);
575     }
576 
577   /* Non-negative integers are hopefully small enough to fit in all targets.
578      Gcov file formats wants non-zero function IDs.  */
579   chksum = chksum & 0x7fffffff;
580   return chksum + (!chksum);
581 }
582 
583 /* Compute cfg checksum for the function FN given as argument.
584    The checksum is calculated carefully so that
585    source code changes that doesn't affect the control flow graph
586    won't change the checksum.
587    This is to make the profile data useable across source code change.
588    The downside of this is that the compiler may use potentially
589    wrong profile data - that the source code change has non-trivial impact
590    on the validity of profile data (e.g. the reversed condition)
591    but the compiler won't detect the change and use the wrong profile data.  */
592 
593 unsigned
coverage_compute_cfg_checksum(struct function * fn)594 coverage_compute_cfg_checksum (struct function *fn)
595 {
596   basic_block bb;
597   unsigned chksum = n_basic_blocks_for_fn (fn);
598 
599   FOR_EACH_BB_FN (bb, fn)
600     {
601       edge e;
602       edge_iterator ei;
603       chksum = crc32_byte (chksum, bb->index);
604       FOR_EACH_EDGE (e, ei, bb->succs)
605         {
606           chksum = crc32_byte (chksum, e->dest->index);
607         }
608     }
609 
610   return chksum;
611 }
612 
613 /* Begin output to the notes file for the current function.
614    Writes the function header. Returns nonzero if data should be output.  */
615 
616 int
coverage_begin_function(unsigned lineno_checksum,unsigned cfg_checksum)617 coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
618 {
619   expanded_location xloc;
620   unsigned long offset;
621 
622   /* We don't need to output .gcno file unless we're under -ftest-coverage
623      (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
624   if (no_coverage || !bbg_file_name)
625     return 0;
626 
627   xloc = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
628 
629   /* Announce function */
630   offset = gcov_write_tag (GCOV_TAG_FUNCTION);
631   if (param_profile_func_internal_id)
632     gcov_write_unsigned (current_function_funcdef_no + 1);
633   else
634     {
635       gcc_assert (coverage_node_map_initialized_p ());
636       gcov_write_unsigned (
637         cgraph_node::get (current_function_decl)->profile_id);
638     }
639 
640   gcov_write_unsigned (lineno_checksum);
641   gcov_write_unsigned (cfg_checksum);
642   gcov_write_string (IDENTIFIER_POINTER
643 		     (DECL_ASSEMBLER_NAME (current_function_decl)));
644   gcov_write_unsigned (DECL_ARTIFICIAL (current_function_decl)
645 		       && !DECL_FUNCTION_VERSIONED (current_function_decl)
646 		       && !DECL_LAMBDA_FUNCTION_P (current_function_decl));
647   gcov_write_filename (xloc.file);
648   gcov_write_unsigned (xloc.line);
649   gcov_write_unsigned (xloc.column);
650 
651   expanded_location endloc = expand_location (cfun->function_end_locus);
652 
653   /* Function can start in a single file and end in another one.  */
654   int end_line = endloc.file == xloc.file ? endloc.line : xloc.line;
655   int end_column = endloc.file == xloc.file ? endloc.column: xloc.column;
656   gcc_assert (xloc.line <= end_line);
657   gcov_write_unsigned (end_line);
658   gcov_write_unsigned (end_column);
659   gcov_write_length (offset);
660 
661   return !gcov_is_error ();
662 }
663 
664 /* Finish coverage data for the current function. Verify no output
665    error has occurred.  Save function coverage counts.  */
666 
667 void
coverage_end_function(unsigned lineno_checksum,unsigned cfg_checksum)668 coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
669 {
670   unsigned i;
671 
672   if (bbg_file_name && gcov_is_error ())
673     {
674       warning (0, "error writing %qs", bbg_file_name);
675       unlink (bbg_file_name);
676       bbg_file_name = NULL;
677     }
678 
679   if (fn_ctr_mask)
680     {
681       struct coverage_data *item = 0;
682 
683       item = ggc_alloc<coverage_data> ();
684 
685       if (param_profile_func_internal_id)
686 	item->ident = current_function_funcdef_no + 1;
687       else
688 	{
689 	  gcc_assert (coverage_node_map_initialized_p ());
690 	  item->ident = cgraph_node::get (cfun->decl)->profile_id;
691 	}
692 
693       item->lineno_checksum = lineno_checksum;
694       item->cfg_checksum = cfg_checksum;
695 
696       item->fn_decl = current_function_decl;
697       item->next = 0;
698       *functions_tail = item;
699       functions_tail = &item->next;
700 
701       for (i = 0; i != GCOV_COUNTERS; i++)
702 	{
703 	  tree var = fn_v_ctrs[i];
704 
705 	  if (item)
706 	    item->ctr_vars[i] = var;
707 	  if (var)
708 	    {
709 	      tree array_type = build_index_type (size_int (fn_n_ctrs[i] - 1));
710 	      array_type = build_array_type (get_gcov_type (), array_type);
711 	      TREE_TYPE (var) = array_type;
712 	      DECL_SIZE (var) = TYPE_SIZE (array_type);
713 	      DECL_SIZE_UNIT (var) = TYPE_SIZE_UNIT (array_type);
714 	      varpool_node::finalize_decl (var);
715 	    }
716 
717 	  fn_b_ctrs[i] = fn_n_ctrs[i] = 0;
718 	  fn_v_ctrs[i] = NULL_TREE;
719 	}
720       prg_ctr_mask |= fn_ctr_mask;
721       fn_ctr_mask = 0;
722     }
723 }
724 
725 /* Remove coverage file if opened.  */
726 
727 void
coverage_remove_note_file(void)728 coverage_remove_note_file (void)
729 {
730   if (bbg_file_name)
731     {
732       gcov_close ();
733       unlink (bbg_file_name);
734     }
735 }
736 
737 /* Build a coverage variable of TYPE for function FN_DECL.  If COUNTER
738    >= 0 it is a counter array, otherwise it is the function structure.  */
739 
740 static tree
build_var(tree fn_decl,tree type,int counter)741 build_var (tree fn_decl, tree type, int counter)
742 {
743   tree var = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE, type);
744   const char *fn_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn_decl));
745   char *buf;
746   size_t fn_name_len, len;
747 
748   fn_name = targetm.strip_name_encoding (fn_name);
749   fn_name_len = strlen (fn_name);
750   buf = XALLOCAVEC (char, fn_name_len + 8 + sizeof (int) * 3);
751 
752   if (counter < 0)
753     strcpy (buf, "__gcov__");
754   else
755     sprintf (buf, "__gcov%u_", counter);
756   len = strlen (buf);
757   buf[len - 1] = symbol_table::symbol_suffix_separator ();
758   memcpy (buf + len, fn_name, fn_name_len + 1);
759   DECL_NAME (var) = get_identifier (buf);
760   TREE_STATIC (var) = 1;
761   TREE_ADDRESSABLE (var) = 1;
762   DECL_NONALIASED (var) = 1;
763   SET_DECL_ALIGN (var, TYPE_ALIGN (type));
764 
765   return var;
766 }
767 
768 /* Creates the gcov_fn_info RECORD_TYPE.  */
769 
770 static void
build_fn_info_type(tree type,unsigned counters,tree gcov_info_type)771 build_fn_info_type (tree type, unsigned counters, tree gcov_info_type)
772 {
773   tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE);
774   tree field, fields;
775   tree array_type;
776 
777   gcc_assert (counters);
778 
779   /* ctr_info::num */
780   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
781 		      get_gcov_unsigned_t ());
782   fields = field;
783 
784   /* ctr_info::values */
785   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
786 		      build_pointer_type (get_gcov_type ()));
787   DECL_CHAIN (field) = fields;
788   fields = field;
789 
790   finish_builtin_struct (ctr_info, "__gcov_ctr_info", fields, NULL_TREE);
791 
792   /* key */
793   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
794 		      build_pointer_type (build_qualified_type
795 					  (gcov_info_type, TYPE_QUAL_CONST)));
796   fields = field;
797 
798   /* ident */
799   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
800 		      get_gcov_unsigned_t ());
801   DECL_CHAIN (field) = fields;
802   fields = field;
803 
804   /* lineno_checksum */
805   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
806 		      get_gcov_unsigned_t ());
807   DECL_CHAIN (field) = fields;
808   fields = field;
809 
810   /* cfg checksum */
811   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
812 		      get_gcov_unsigned_t ());
813   DECL_CHAIN (field) = fields;
814   fields = field;
815 
816   array_type = build_index_type (size_int (counters - 1));
817   array_type = build_array_type (ctr_info, array_type);
818 
819   /* counters */
820   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type);
821   DECL_CHAIN (field) = fields;
822   fields = field;
823 
824   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
825 }
826 
827 /* Returns a CONSTRUCTOR for a gcov_fn_info.  DATA is
828    the coverage data for the function and TYPE is the gcov_fn_info
829    RECORD_TYPE.  KEY is the object file key.  */
830 
831 static tree
build_fn_info(const struct coverage_data * data,tree type,tree key)832 build_fn_info (const struct coverage_data *data, tree type, tree key)
833 {
834   tree fields = TYPE_FIELDS (type);
835   tree ctr_type;
836   unsigned ix;
837   vec<constructor_elt, va_gc> *v1 = NULL;
838   vec<constructor_elt, va_gc> *v2 = NULL;
839 
840   /* key */
841   CONSTRUCTOR_APPEND_ELT (v1, fields,
842 			  build1 (ADDR_EXPR, TREE_TYPE (fields), key));
843   fields = DECL_CHAIN (fields);
844 
845   /* ident */
846   CONSTRUCTOR_APPEND_ELT (v1, fields,
847 			  build_int_cstu (get_gcov_unsigned_t (),
848 					  data->ident));
849   fields = DECL_CHAIN (fields);
850 
851   /* lineno_checksum */
852   CONSTRUCTOR_APPEND_ELT (v1, fields,
853 			  build_int_cstu (get_gcov_unsigned_t (),
854 					  data->lineno_checksum));
855   fields = DECL_CHAIN (fields);
856 
857   /* cfg_checksum */
858   CONSTRUCTOR_APPEND_ELT (v1, fields,
859 			  build_int_cstu (get_gcov_unsigned_t (),
860 					  data->cfg_checksum));
861   fields = DECL_CHAIN (fields);
862 
863   /* counters */
864   ctr_type = TREE_TYPE (TREE_TYPE (fields));
865   for (ix = 0; ix != GCOV_COUNTERS; ix++)
866     if (prg_ctr_mask & (1 << ix))
867       {
868 	vec<constructor_elt, va_gc> *ctr = NULL;
869 	tree var = data->ctr_vars[ix];
870 	unsigned count = 0;
871 
872 	if (var)
873 	  count
874 	    = tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))))
875 	    + 1;
876 
877 	CONSTRUCTOR_APPEND_ELT (ctr, TYPE_FIELDS (ctr_type),
878 				build_int_cstu (get_gcov_unsigned_t (),
879 						count));
880 
881 	if (var)
882 	  CONSTRUCTOR_APPEND_ELT (ctr, DECL_CHAIN (TYPE_FIELDS (ctr_type)),
883 				  build_fold_addr_expr (var));
884 
885 	CONSTRUCTOR_APPEND_ELT (v2, NULL, build_constructor (ctr_type, ctr));
886       }
887 
888   CONSTRUCTOR_APPEND_ELT (v1, fields,
889 			  build_constructor (TREE_TYPE (fields), v2));
890 
891   return build_constructor (type, v1);
892 }
893 
894 /* Create gcov_info struct.  TYPE is the incomplete RECORD_TYPE to be
895    completed, and FN_INFO_PTR_TYPE is a pointer to the function info type.  */
896 
897 static void
build_info_type(tree type,tree fn_info_ptr_type)898 build_info_type (tree type, tree fn_info_ptr_type)
899 {
900   tree field, fields = NULL_TREE;
901   tree merge_fn_type;
902 
903   /* Version ident */
904   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
905 		      get_gcov_unsigned_t ());
906   DECL_CHAIN (field) = fields;
907   fields = field;
908 
909   /* next pointer */
910   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
911 		      build_pointer_type (build_qualified_type
912 					  (type, TYPE_QUAL_CONST)));
913   DECL_CHAIN (field) = fields;
914   fields = field;
915 
916   /* stamp */
917   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
918 		      get_gcov_unsigned_t ());
919   DECL_CHAIN (field) = fields;
920   fields = field;
921 
922   /* Filename */
923   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
924 		      build_pointer_type (build_qualified_type
925 					  (char_type_node, TYPE_QUAL_CONST)));
926   DECL_CHAIN (field) = fields;
927   fields = field;
928 
929   /* merge fn array */
930   merge_fn_type
931     = build_function_type_list (void_type_node,
932 				build_pointer_type (get_gcov_type ()),
933 				get_gcov_unsigned_t (), NULL_TREE);
934   merge_fn_type
935     = build_array_type (build_pointer_type (merge_fn_type),
936 			build_index_type (size_int (GCOV_COUNTERS - 1)));
937   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
938 		      merge_fn_type);
939   DECL_CHAIN (field) = fields;
940   fields = field;
941 
942   /* n_functions */
943   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
944 		      get_gcov_unsigned_t ());
945   DECL_CHAIN (field) = fields;
946   fields = field;
947 
948   /* function_info pointer pointer */
949   fn_info_ptr_type = build_pointer_type
950     (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST));
951   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
952 		      fn_info_ptr_type);
953   DECL_CHAIN (field) = fields;
954   fields = field;
955 
956   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
957 }
958 
959 /* Returns a CONSTRUCTOR for the gcov_info object.  INFO_TYPE is the
960    gcov_info structure type, FN_ARY is the array of pointers to
961    function info objects.  */
962 
963 static tree
build_info(tree info_type,tree fn_ary)964 build_info (tree info_type, tree fn_ary)
965 {
966   tree info_fields = TYPE_FIELDS (info_type);
967   tree merge_fn_type, n_funcs;
968   unsigned ix;
969   tree filename_string;
970   int da_file_name_len;
971   vec<constructor_elt, va_gc> *v1 = NULL;
972   vec<constructor_elt, va_gc> *v2 = NULL;
973 
974   /* Version ident */
975   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
976 			  build_int_cstu (TREE_TYPE (info_fields),
977 					  GCOV_VERSION));
978   info_fields = DECL_CHAIN (info_fields);
979 
980   /* next -- NULL */
981   CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
982   info_fields = DECL_CHAIN (info_fields);
983 
984   /* stamp */
985   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
986 			  build_int_cstu (TREE_TYPE (info_fields),
987 					  bbg_file_stamp));
988   info_fields = DECL_CHAIN (info_fields);
989 
990   /* Filename */
991   da_file_name_len = strlen (da_file_name);
992   filename_string = build_string (da_file_name_len + 1, da_file_name);
993   TREE_TYPE (filename_string) = build_array_type
994     (char_type_node, build_index_type (size_int (da_file_name_len)));
995   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
996 			  build1 (ADDR_EXPR, TREE_TYPE (info_fields),
997 				  filename_string));
998   info_fields = DECL_CHAIN (info_fields);
999 
1000   /* merge fn array -- NULL slots indicate unmeasured counters */
1001   merge_fn_type = TREE_TYPE (TREE_TYPE (info_fields));
1002   for (ix = 0; ix != GCOV_COUNTERS; ix++)
1003     {
1004       tree ptr = null_pointer_node;
1005 
1006       if ((1u << ix) & prg_ctr_mask)
1007 	{
1008 	  tree merge_fn = build_decl (BUILTINS_LOCATION,
1009 				      FUNCTION_DECL,
1010 				      get_identifier (ctr_merge_functions[ix]),
1011 				      TREE_TYPE (merge_fn_type));
1012 	  DECL_EXTERNAL (merge_fn) = 1;
1013 	  TREE_PUBLIC (merge_fn) = 1;
1014 	  DECL_ARTIFICIAL (merge_fn) = 1;
1015 	  TREE_NOTHROW (merge_fn) = 1;
1016 	  /* Initialize assembler name so we can stream out. */
1017 	  DECL_ASSEMBLER_NAME (merge_fn);
1018 	  ptr = build1 (ADDR_EXPR, merge_fn_type, merge_fn);
1019 	}
1020       CONSTRUCTOR_APPEND_ELT (v2, NULL, ptr);
1021     }
1022   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
1023 			  build_constructor (TREE_TYPE (info_fields), v2));
1024   info_fields = DECL_CHAIN (info_fields);
1025 
1026   /* n_functions */
1027   n_funcs = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (fn_ary)));
1028   n_funcs = fold_build2 (PLUS_EXPR, TREE_TYPE (info_fields),
1029 			 n_funcs, size_one_node);
1030   CONSTRUCTOR_APPEND_ELT (v1, info_fields, n_funcs);
1031   info_fields = DECL_CHAIN (info_fields);
1032 
1033   /* functions */
1034   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
1035 			  build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary));
1036   info_fields = DECL_CHAIN (info_fields);
1037 
1038   gcc_assert (!info_fields);
1039   return build_constructor (info_type, v1);
1040 }
1041 
1042 /* Generate the constructor function to call __gcov_init.  */
1043 
1044 static void
build_init_ctor(tree gcov_info_type)1045 build_init_ctor (tree gcov_info_type)
1046 {
1047   tree ctor, stmt, init_fn;
1048 
1049   /* Build a decl for __gcov_init.  */
1050   init_fn = build_pointer_type (gcov_info_type);
1051   init_fn = build_function_type_list (void_type_node, init_fn, NULL);
1052   init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1053 			get_identifier ("__gcov_init"), init_fn);
1054   TREE_PUBLIC (init_fn) = 1;
1055   DECL_EXTERNAL (init_fn) = 1;
1056   DECL_ASSEMBLER_NAME (init_fn);
1057 
1058   /* Generate a call to __gcov_init(&gcov_info).  */
1059   ctor = NULL;
1060   stmt = build_fold_addr_expr (gcov_info_var);
1061   stmt = build_call_expr (init_fn, 1, stmt);
1062   append_to_statement_list (stmt, &ctor);
1063 
1064   /* Generate a constructor to run it.  */
1065   int priority = SUPPORTS_INIT_PRIORITY
1066     ? MAX_RESERVED_INIT_PRIORITY: DEFAULT_INIT_PRIORITY;
1067   cgraph_build_static_cdtor ('I', ctor, priority);
1068 }
1069 
1070 /* Generate the destructor function to call __gcov_exit.  */
1071 
1072 static void
build_gcov_exit_decl(void)1073 build_gcov_exit_decl (void)
1074 {
1075   tree init_fn = build_function_type_list (void_type_node, NULL);
1076   init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1077 			get_identifier ("__gcov_exit"), init_fn);
1078   TREE_PUBLIC (init_fn) = 1;
1079   DECL_EXTERNAL (init_fn) = 1;
1080   DECL_ASSEMBLER_NAME (init_fn);
1081 
1082   /* Generate a call to __gcov_exit ().  */
1083   tree dtor = NULL;
1084   tree stmt = build_call_expr (init_fn, 0);
1085   append_to_statement_list (stmt, &dtor);
1086 
1087   /* Generate a destructor to run it.  */
1088   int priority = SUPPORTS_INIT_PRIORITY
1089     ? MAX_RESERVED_INIT_PRIORITY: DEFAULT_INIT_PRIORITY;
1090 
1091   cgraph_build_static_cdtor ('D', dtor, priority);
1092 }
1093 
1094 /* Create the gcov_info types and object.  Generate the constructor
1095    function to call __gcov_init.  Does not generate the initializer
1096    for the object.  Returns TRUE if coverage data is being emitted.  */
1097 
1098 static bool
coverage_obj_init(void)1099 coverage_obj_init (void)
1100 {
1101   tree gcov_info_type;
1102   unsigned n_counters = 0;
1103   unsigned ix;
1104   struct coverage_data *fn;
1105   struct coverage_data **fn_prev;
1106   char name_buf[32];
1107 
1108   no_coverage = 1; /* Disable any further coverage.  */
1109 
1110   if (!prg_ctr_mask)
1111     return false;
1112 
1113   if (symtab->dump_file)
1114     fprintf (symtab->dump_file, "Using data file %s\n", da_file_name);
1115 
1116   /* Prune functions.  */
1117   for (fn_prev = &functions_head; (fn = *fn_prev);)
1118     if (DECL_STRUCT_FUNCTION (fn->fn_decl))
1119       fn_prev = &fn->next;
1120     else
1121       /* The function is not being emitted, remove from list.  */
1122       *fn_prev = fn->next;
1123 
1124   if (functions_head == NULL)
1125     return false;
1126 
1127   for (ix = 0; ix != GCOV_COUNTERS; ix++)
1128     if ((1u << ix) & prg_ctr_mask)
1129       n_counters++;
1130 
1131   /* Build the info and fn_info types.  These are mutually recursive.  */
1132   gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
1133   gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
1134   build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
1135   gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
1136   gcov_fn_info_ptr_type = build_pointer_type
1137     (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
1138   build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
1139 
1140   /* Build the gcov info var, this is referred to in its own
1141      initializer.  */
1142   gcov_info_var = build_decl (BUILTINS_LOCATION,
1143 			      VAR_DECL, NULL_TREE, gcov_info_type);
1144   TREE_STATIC (gcov_info_var) = 1;
1145   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
1146   DECL_NAME (gcov_info_var) = get_identifier (name_buf);
1147 
1148   build_init_ctor (gcov_info_type);
1149   build_gcov_exit_decl ();
1150 
1151   return true;
1152 }
1153 
1154 /* Generate the coverage function info for FN and DATA.  Append a
1155    pointer to that object to CTOR and return the appended CTOR.  */
1156 
1157 static vec<constructor_elt, va_gc> *
coverage_obj_fn(vec<constructor_elt,va_gc> * ctor,tree fn,struct coverage_data const * data)1158 coverage_obj_fn (vec<constructor_elt, va_gc> *ctor, tree fn,
1159 		 struct coverage_data const *data)
1160 {
1161   tree init = build_fn_info (data, gcov_fn_info_type, gcov_info_var);
1162   tree var = build_var (fn, gcov_fn_info_type, -1);
1163 
1164   DECL_INITIAL (var) = init;
1165   varpool_node::finalize_decl (var);
1166 
1167   CONSTRUCTOR_APPEND_ELT (ctor, NULL,
1168 			  build1 (ADDR_EXPR, gcov_fn_info_ptr_type, var));
1169   return ctor;
1170 }
1171 
1172 /* Finalize the coverage data.  Generates the array of pointers to
1173    function objects from CTOR.  Generate the gcov_info initializer.  */
1174 
1175 static void
coverage_obj_finish(vec<constructor_elt,va_gc> * ctor)1176 coverage_obj_finish (vec<constructor_elt, va_gc> *ctor)
1177 {
1178   unsigned n_functions = vec_safe_length (ctor);
1179   tree fn_info_ary_type = build_array_type
1180     (build_qualified_type (gcov_fn_info_ptr_type, TYPE_QUAL_CONST),
1181      build_index_type (size_int (n_functions - 1)));
1182   tree fn_info_ary = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE,
1183 				 fn_info_ary_type);
1184   char name_buf[32];
1185 
1186   TREE_STATIC (fn_info_ary) = 1;
1187   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 1);
1188   DECL_NAME (fn_info_ary) = get_identifier (name_buf);
1189   DECL_INITIAL (fn_info_ary) = build_constructor (fn_info_ary_type, ctor);
1190   varpool_node::finalize_decl (fn_info_ary);
1191 
1192   DECL_INITIAL (gcov_info_var)
1193     = build_info (TREE_TYPE (gcov_info_var), fn_info_ary);
1194   varpool_node::finalize_decl (gcov_info_var);
1195 }
1196 
1197 /* Perform file-level initialization. Read in data file, generate name
1198    of notes file.  */
1199 
1200 void
coverage_init(const char * filename)1201 coverage_init (const char *filename)
1202 {
1203   const char *original_filename = filename;
1204   int original_len = strlen (original_filename);
1205 #if HAVE_DOS_BASED_FILE_SYSTEM
1206   const char *separator = "\\";
1207 #else
1208   const char *separator = "/";
1209 #endif
1210   int len = strlen (filename);
1211   int prefix_len = 0;
1212 
1213   /* Since coverage_init is invoked very early, before the pass
1214      manager, we need to set up the dumping explicitly. This is
1215      similar to the handling in finish_optimization_passes.  */
1216   int profile_pass_num =
1217     g->get_passes ()->get_pass_profile ()->static_pass_number;
1218   g->get_dumps ()->dump_start (profile_pass_num, NULL);
1219 
1220   if (!IS_ABSOLUTE_PATH (filename))
1221     {
1222       /* When a profile_data_prefix is provided, then mangle full path
1223 	 of filename in order to prevent file path clashing.  */
1224       if (profile_data_prefix)
1225 	{
1226 	  filename = concat (getpwd (), separator, filename, NULL);
1227 	  if (profile_prefix_path)
1228 	    {
1229 	      if (!strncmp (filename, profile_prefix_path,
1230 			    strlen (profile_prefix_path)))
1231 		{
1232 		  filename += strlen (profile_prefix_path);
1233 		  while (*filename == *separator)
1234 		    filename++;
1235 		}
1236 	      else
1237 		warning (0, "filename %qs does not start with profile "
1238 			 "prefix %qs", filename, profile_prefix_path);
1239 	    }
1240 	  filename = mangle_path (filename);
1241 	  len = strlen (filename);
1242 	}
1243       else
1244 	profile_data_prefix = getpwd ();
1245     }
1246 
1247   if (profile_data_prefix)
1248     prefix_len = strlen (profile_data_prefix);
1249 
1250   /* Name of da file.  */
1251   da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
1252 			  + prefix_len + 2);
1253 
1254   if (profile_data_prefix)
1255     {
1256       memcpy (da_file_name, profile_data_prefix, prefix_len);
1257       da_file_name[prefix_len++] = *separator;
1258     }
1259   memcpy (da_file_name + prefix_len, filename, len);
1260   strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
1261 
1262   bbg_file_stamp = local_tick;
1263 
1264   if (flag_auto_profile)
1265     read_autofdo_file ();
1266   else if (flag_branch_probabilities)
1267     read_counts_file ();
1268 
1269   /* Name of bbg file.  */
1270   if (flag_test_coverage && !flag_compare_debug)
1271     {
1272       if (profile_note_location)
1273 	bbg_file_name = xstrdup (profile_note_location);
1274       else
1275 	{
1276 	  bbg_file_name = XNEWVEC (char, original_len + strlen (GCOV_NOTE_SUFFIX) + 1);
1277 	  memcpy (bbg_file_name, original_filename, original_len);
1278 	  strcpy (bbg_file_name + original_len, GCOV_NOTE_SUFFIX);
1279 	}
1280 
1281       if (!gcov_open (bbg_file_name, -1))
1282 	{
1283 	  error ("cannot open %s", bbg_file_name);
1284 	  bbg_file_name = NULL;
1285 	}
1286       else
1287 	{
1288 	  gcov_write_unsigned (GCOV_NOTE_MAGIC);
1289 	  gcov_write_unsigned (GCOV_VERSION);
1290 	  gcov_write_unsigned (bbg_file_stamp);
1291 	  gcov_write_string (getpwd ());
1292 
1293 	  /* Do not support has_unexecuted_blocks for Ada.  */
1294 	  gcov_write_unsigned (strcmp (lang_hooks.name, "GNU Ada") != 0);
1295 	}
1296     }
1297 
1298   g->get_dumps ()->dump_finish (profile_pass_num);
1299 }
1300 
1301 /* Performs file-level cleanup.  Close notes file, generate coverage
1302    variables and constructor.  */
1303 
1304 void
coverage_finish(void)1305 coverage_finish (void)
1306 {
1307   if (bbg_file_name && gcov_close ())
1308     unlink (bbg_file_name);
1309 
1310   if (!flag_branch_probabilities && flag_test_coverage
1311       && (!local_tick || local_tick == (unsigned)-1))
1312     /* Only remove the da file, if we're emitting coverage code and
1313        cannot uniquely stamp it.  If we can stamp it, libgcov will DTRT.  */
1314     unlink (da_file_name);
1315 
1316   if (coverage_obj_init ())
1317     {
1318       vec<constructor_elt, va_gc> *fn_ctor = NULL;
1319       struct coverage_data *fn;
1320 
1321       for (fn = functions_head; fn; fn = fn->next)
1322 	fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
1323       coverage_obj_finish (fn_ctor);
1324     }
1325 
1326   XDELETEVEC (da_file_name);
1327   da_file_name = NULL;
1328 }
1329 
1330 #include "gt-coverage.h"
1331