xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/coverage.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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   /* We don't need to output .gcno file unless we're under -ftest-coverage
620      (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
621   if (no_coverage || !bbg_file_name)
622     return 0;
623 
624   expanded_location startloc
625     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
626 
627   /* Announce function */
628   unsigned long offset = gcov_write_tag (GCOV_TAG_FUNCTION);
629   if (param_profile_func_internal_id)
630     gcov_write_unsigned (current_function_funcdef_no + 1);
631   else
632     {
633       gcc_assert (coverage_node_map_initialized_p ());
634       gcov_write_unsigned (
635         cgraph_node::get (current_function_decl)->profile_id);
636     }
637 
638   gcov_write_unsigned (lineno_checksum);
639   gcov_write_unsigned (cfg_checksum);
640   gcov_write_string (IDENTIFIER_POINTER
641 		     (DECL_ASSEMBLER_NAME (current_function_decl)));
642   gcov_write_unsigned (DECL_ARTIFICIAL (current_function_decl)
643 		       && !DECL_FUNCTION_VERSIONED (current_function_decl)
644 		       && !DECL_LAMBDA_FUNCTION_P (current_function_decl));
645   gcov_write_filename (startloc.file);
646   gcov_write_unsigned (startloc.line);
647   gcov_write_unsigned (startloc.column);
648 
649   expanded_location endloc = expand_location (cfun->function_end_locus);
650 
651   /* Function can start in a single file and end in another one.  */
652   int end_line
653     = endloc.file == startloc.file ? endloc.line : startloc.line;
654   int end_column
655     = endloc.file == startloc.file ? endloc.column: startloc.column;
656 
657   if (startloc.line > end_line)
658     {
659       end_line = startloc.line;
660       end_column = startloc.column;
661     }
662 
663   gcov_write_unsigned (end_line);
664   gcov_write_unsigned (end_column);
665   gcov_write_length (offset);
666 
667   return !gcov_is_error ();
668 }
669 
670 /* Finish coverage data for the current function. Verify no output
671    error has occurred.  Save function coverage counts.  */
672 
673 void
coverage_end_function(unsigned lineno_checksum,unsigned cfg_checksum)674 coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
675 {
676   unsigned i;
677 
678   if (bbg_file_name && gcov_is_error ())
679     {
680       warning (0, "error writing %qs", bbg_file_name);
681       unlink (bbg_file_name);
682       bbg_file_name = NULL;
683     }
684 
685   if (fn_ctr_mask)
686     {
687       struct coverage_data *item = 0;
688 
689       item = ggc_alloc<coverage_data> ();
690 
691       if (param_profile_func_internal_id)
692 	item->ident = current_function_funcdef_no + 1;
693       else
694 	{
695 	  gcc_assert (coverage_node_map_initialized_p ());
696 	  item->ident = cgraph_node::get (cfun->decl)->profile_id;
697 	}
698 
699       item->lineno_checksum = lineno_checksum;
700       item->cfg_checksum = cfg_checksum;
701 
702       item->fn_decl = current_function_decl;
703       item->next = 0;
704       *functions_tail = item;
705       functions_tail = &item->next;
706 
707       for (i = 0; i != GCOV_COUNTERS; i++)
708 	{
709 	  tree var = fn_v_ctrs[i];
710 
711 	  if (item)
712 	    item->ctr_vars[i] = var;
713 	  if (var)
714 	    {
715 	      tree array_type = build_index_type (size_int (fn_n_ctrs[i] - 1));
716 	      array_type = build_array_type (get_gcov_type (), array_type);
717 	      TREE_TYPE (var) = array_type;
718 	      DECL_SIZE (var) = TYPE_SIZE (array_type);
719 	      DECL_SIZE_UNIT (var) = TYPE_SIZE_UNIT (array_type);
720 	      varpool_node::finalize_decl (var);
721 	    }
722 
723 	  fn_b_ctrs[i] = fn_n_ctrs[i] = 0;
724 	  fn_v_ctrs[i] = NULL_TREE;
725 	}
726       prg_ctr_mask |= fn_ctr_mask;
727       fn_ctr_mask = 0;
728     }
729 }
730 
731 /* Remove coverage file if opened.  */
732 
733 void
coverage_remove_note_file(void)734 coverage_remove_note_file (void)
735 {
736   if (bbg_file_name)
737     {
738       gcov_close ();
739       unlink (bbg_file_name);
740     }
741 }
742 
743 /* Build a coverage variable of TYPE for function FN_DECL.  If COUNTER
744    >= 0 it is a counter array, otherwise it is the function structure.  */
745 
746 static tree
build_var(tree fn_decl,tree type,int counter)747 build_var (tree fn_decl, tree type, int counter)
748 {
749   tree var = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE, type);
750   const char *fn_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn_decl));
751   char *buf;
752   size_t fn_name_len, len;
753 
754   fn_name = targetm.strip_name_encoding (fn_name);
755   fn_name_len = strlen (fn_name);
756   buf = XALLOCAVEC (char, fn_name_len + 8 + sizeof (int) * 3);
757 
758   if (counter < 0)
759     strcpy (buf, "__gcov__");
760   else
761     sprintf (buf, "__gcov%u_", counter);
762   len = strlen (buf);
763   buf[len - 1] = symbol_table::symbol_suffix_separator ();
764   memcpy (buf + len, fn_name, fn_name_len + 1);
765   DECL_NAME (var) = get_identifier (buf);
766   TREE_STATIC (var) = 1;
767   TREE_ADDRESSABLE (var) = 1;
768   DECL_NONALIASED (var) = 1;
769   SET_DECL_ALIGN (var, TYPE_ALIGN (type));
770 
771   return var;
772 }
773 
774 /* Creates the gcov_fn_info RECORD_TYPE.  */
775 
776 static void
build_fn_info_type(tree type,unsigned counters,tree gcov_info_type)777 build_fn_info_type (tree type, unsigned counters, tree gcov_info_type)
778 {
779   tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE);
780   tree field, fields;
781   tree array_type;
782 
783   gcc_assert (counters);
784 
785   /* ctr_info::num */
786   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
787 		      get_gcov_unsigned_t ());
788   fields = field;
789 
790   /* ctr_info::values */
791   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
792 		      build_pointer_type (get_gcov_type ()));
793   DECL_CHAIN (field) = fields;
794   fields = field;
795 
796   finish_builtin_struct (ctr_info, "__gcov_ctr_info", fields, NULL_TREE);
797 
798   /* key */
799   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
800 		      build_pointer_type (build_qualified_type
801 					  (gcov_info_type, TYPE_QUAL_CONST)));
802   fields = field;
803 
804   /* ident */
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   /* lineno_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   /* cfg checksum */
817   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
818 		      get_gcov_unsigned_t ());
819   DECL_CHAIN (field) = fields;
820   fields = field;
821 
822   array_type = build_index_type (size_int (counters - 1));
823   array_type = build_array_type (ctr_info, array_type);
824 
825   /* counters */
826   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type);
827   DECL_CHAIN (field) = fields;
828   fields = field;
829 
830   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
831 }
832 
833 /* Returns a CONSTRUCTOR for a gcov_fn_info.  DATA is
834    the coverage data for the function and TYPE is the gcov_fn_info
835    RECORD_TYPE.  KEY is the object file key.  */
836 
837 static tree
build_fn_info(const struct coverage_data * data,tree type,tree key)838 build_fn_info (const struct coverage_data *data, tree type, tree key)
839 {
840   tree fields = TYPE_FIELDS (type);
841   tree ctr_type;
842   unsigned ix;
843   vec<constructor_elt, va_gc> *v1 = NULL;
844   vec<constructor_elt, va_gc> *v2 = NULL;
845 
846   /* key */
847   CONSTRUCTOR_APPEND_ELT (v1, fields,
848 			  build1 (ADDR_EXPR, TREE_TYPE (fields), key));
849   fields = DECL_CHAIN (fields);
850 
851   /* ident */
852   CONSTRUCTOR_APPEND_ELT (v1, fields,
853 			  build_int_cstu (get_gcov_unsigned_t (),
854 					  data->ident));
855   fields = DECL_CHAIN (fields);
856 
857   /* lineno_checksum */
858   CONSTRUCTOR_APPEND_ELT (v1, fields,
859 			  build_int_cstu (get_gcov_unsigned_t (),
860 					  data->lineno_checksum));
861   fields = DECL_CHAIN (fields);
862 
863   /* cfg_checksum */
864   CONSTRUCTOR_APPEND_ELT (v1, fields,
865 			  build_int_cstu (get_gcov_unsigned_t (),
866 					  data->cfg_checksum));
867   fields = DECL_CHAIN (fields);
868 
869   /* counters */
870   ctr_type = TREE_TYPE (TREE_TYPE (fields));
871   for (ix = 0; ix != GCOV_COUNTERS; ix++)
872     if (prg_ctr_mask & (1 << ix))
873       {
874 	vec<constructor_elt, va_gc> *ctr = NULL;
875 	tree var = data->ctr_vars[ix];
876 	unsigned count = 0;
877 
878 	if (var)
879 	  count
880 	    = tree_to_shwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))))
881 	    + 1;
882 
883 	CONSTRUCTOR_APPEND_ELT (ctr, TYPE_FIELDS (ctr_type),
884 				build_int_cstu (get_gcov_unsigned_t (),
885 						count));
886 
887 	if (var)
888 	  CONSTRUCTOR_APPEND_ELT (ctr, DECL_CHAIN (TYPE_FIELDS (ctr_type)),
889 				  build_fold_addr_expr (var));
890 
891 	CONSTRUCTOR_APPEND_ELT (v2, NULL, build_constructor (ctr_type, ctr));
892       }
893 
894   CONSTRUCTOR_APPEND_ELT (v1, fields,
895 			  build_constructor (TREE_TYPE (fields), v2));
896 
897   return build_constructor (type, v1);
898 }
899 
900 /* Create gcov_info struct.  TYPE is the incomplete RECORD_TYPE to be
901    completed, and FN_INFO_PTR_TYPE is a pointer to the function info type.  */
902 
903 static void
build_info_type(tree type,tree fn_info_ptr_type)904 build_info_type (tree type, tree fn_info_ptr_type)
905 {
906   tree field, fields = NULL_TREE;
907   tree merge_fn_type;
908 
909   /* Version ident */
910   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
911 		      get_gcov_unsigned_t ());
912   DECL_CHAIN (field) = fields;
913   fields = field;
914 
915   /* next pointer */
916   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
917 		      build_pointer_type (build_qualified_type
918 					  (type, TYPE_QUAL_CONST)));
919   DECL_CHAIN (field) = fields;
920   fields = field;
921 
922   /* stamp */
923   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
924 		      get_gcov_unsigned_t ());
925   DECL_CHAIN (field) = fields;
926   fields = field;
927 
928   /* Filename */
929   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
930 		      build_pointer_type (build_qualified_type
931 					  (char_type_node, TYPE_QUAL_CONST)));
932   DECL_CHAIN (field) = fields;
933   fields = field;
934 
935   /* merge fn array */
936   merge_fn_type
937     = build_function_type_list (void_type_node,
938 				build_pointer_type (get_gcov_type ()),
939 				get_gcov_unsigned_t (), NULL_TREE);
940   merge_fn_type
941     = build_array_type (build_pointer_type (merge_fn_type),
942 			build_index_type (size_int (GCOV_COUNTERS - 1)));
943   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
944 		      merge_fn_type);
945   DECL_CHAIN (field) = fields;
946   fields = field;
947 
948   /* n_functions */
949   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
950 		      get_gcov_unsigned_t ());
951   DECL_CHAIN (field) = fields;
952   fields = field;
953 
954   /* function_info pointer pointer */
955   fn_info_ptr_type = build_pointer_type
956     (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST));
957   field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
958 		      fn_info_ptr_type);
959   DECL_CHAIN (field) = fields;
960   fields = field;
961 
962   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
963 }
964 
965 /* Returns a CONSTRUCTOR for the gcov_info object.  INFO_TYPE is the
966    gcov_info structure type, FN_ARY is the array of pointers to
967    function info objects.  */
968 
969 static tree
build_info(tree info_type,tree fn_ary)970 build_info (tree info_type, tree fn_ary)
971 {
972   tree info_fields = TYPE_FIELDS (info_type);
973   tree merge_fn_type, n_funcs;
974   unsigned ix;
975   tree filename_string;
976   int da_file_name_len;
977   vec<constructor_elt, va_gc> *v1 = NULL;
978   vec<constructor_elt, va_gc> *v2 = NULL;
979 
980   /* Version ident */
981   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
982 			  build_int_cstu (TREE_TYPE (info_fields),
983 					  GCOV_VERSION));
984   info_fields = DECL_CHAIN (info_fields);
985 
986   /* next -- NULL */
987   CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
988   info_fields = DECL_CHAIN (info_fields);
989 
990   /* stamp */
991   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
992 			  build_int_cstu (TREE_TYPE (info_fields),
993 					  bbg_file_stamp));
994   info_fields = DECL_CHAIN (info_fields);
995 
996   /* Filename */
997   da_file_name_len = strlen (da_file_name);
998   filename_string = build_string (da_file_name_len + 1, da_file_name);
999   TREE_TYPE (filename_string) = build_array_type
1000     (char_type_node, build_index_type (size_int (da_file_name_len)));
1001   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
1002 			  build1 (ADDR_EXPR, TREE_TYPE (info_fields),
1003 				  filename_string));
1004   info_fields = DECL_CHAIN (info_fields);
1005 
1006   /* merge fn array -- NULL slots indicate unmeasured counters */
1007   merge_fn_type = TREE_TYPE (TREE_TYPE (info_fields));
1008   for (ix = 0; ix != GCOV_COUNTERS; ix++)
1009     {
1010       tree ptr = null_pointer_node;
1011 
1012       if ((1u << ix) & prg_ctr_mask)
1013 	{
1014 	  tree merge_fn = build_decl (BUILTINS_LOCATION,
1015 				      FUNCTION_DECL,
1016 				      get_identifier (ctr_merge_functions[ix]),
1017 				      TREE_TYPE (merge_fn_type));
1018 	  DECL_EXTERNAL (merge_fn) = 1;
1019 	  TREE_PUBLIC (merge_fn) = 1;
1020 	  DECL_ARTIFICIAL (merge_fn) = 1;
1021 	  TREE_NOTHROW (merge_fn) = 1;
1022 	  /* Initialize assembler name so we can stream out. */
1023 	  DECL_ASSEMBLER_NAME (merge_fn);
1024 	  ptr = build1 (ADDR_EXPR, merge_fn_type, merge_fn);
1025 	}
1026       CONSTRUCTOR_APPEND_ELT (v2, NULL, ptr);
1027     }
1028   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
1029 			  build_constructor (TREE_TYPE (info_fields), v2));
1030   info_fields = DECL_CHAIN (info_fields);
1031 
1032   /* n_functions */
1033   n_funcs = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (fn_ary)));
1034   n_funcs = fold_build2 (PLUS_EXPR, TREE_TYPE (info_fields),
1035 			 n_funcs, size_one_node);
1036   CONSTRUCTOR_APPEND_ELT (v1, info_fields, n_funcs);
1037   info_fields = DECL_CHAIN (info_fields);
1038 
1039   /* functions */
1040   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
1041 			  build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary));
1042   info_fields = DECL_CHAIN (info_fields);
1043 
1044   gcc_assert (!info_fields);
1045   return build_constructor (info_type, v1);
1046 }
1047 
1048 /* Generate the constructor function to call __gcov_init.  */
1049 
1050 static void
build_init_ctor(tree gcov_info_type)1051 build_init_ctor (tree gcov_info_type)
1052 {
1053   tree ctor, stmt, init_fn;
1054 
1055   /* Build a decl for __gcov_init.  */
1056   init_fn = build_pointer_type (gcov_info_type);
1057   init_fn = build_function_type_list (void_type_node, init_fn, NULL);
1058   init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1059 			get_identifier ("__gcov_init"), init_fn);
1060   TREE_PUBLIC (init_fn) = 1;
1061   DECL_EXTERNAL (init_fn) = 1;
1062   DECL_ASSEMBLER_NAME (init_fn);
1063 
1064   /* Generate a call to __gcov_init(&gcov_info).  */
1065   ctor = NULL;
1066   stmt = build_fold_addr_expr (gcov_info_var);
1067   stmt = build_call_expr (init_fn, 1, stmt);
1068   append_to_statement_list (stmt, &ctor);
1069 
1070   /* Generate a constructor to run it.  */
1071   int priority = SUPPORTS_INIT_PRIORITY
1072     ? MAX_RESERVED_INIT_PRIORITY: DEFAULT_INIT_PRIORITY;
1073   cgraph_build_static_cdtor ('I', ctor, priority);
1074 }
1075 
1076 /* Generate the destructor function to call __gcov_exit.  */
1077 
1078 static void
build_gcov_exit_decl(void)1079 build_gcov_exit_decl (void)
1080 {
1081   tree init_fn = build_function_type_list (void_type_node, NULL);
1082   init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1083 			get_identifier ("__gcov_exit"), init_fn);
1084   TREE_PUBLIC (init_fn) = 1;
1085   DECL_EXTERNAL (init_fn) = 1;
1086   DECL_ASSEMBLER_NAME (init_fn);
1087 
1088   /* Generate a call to __gcov_exit ().  */
1089   tree dtor = NULL;
1090   tree stmt = build_call_expr (init_fn, 0);
1091   append_to_statement_list (stmt, &dtor);
1092 
1093   /* Generate a destructor to run it.  */
1094   int priority = SUPPORTS_INIT_PRIORITY
1095     ? MAX_RESERVED_INIT_PRIORITY: DEFAULT_INIT_PRIORITY;
1096 
1097   cgraph_build_static_cdtor ('D', dtor, priority);
1098 }
1099 
1100 /* Create the gcov_info types and object.  Generate the constructor
1101    function to call __gcov_init.  Does not generate the initializer
1102    for the object.  Returns TRUE if coverage data is being emitted.  */
1103 
1104 static bool
coverage_obj_init(void)1105 coverage_obj_init (void)
1106 {
1107   tree gcov_info_type;
1108   unsigned n_counters = 0;
1109   unsigned ix;
1110   struct coverage_data *fn;
1111   struct coverage_data **fn_prev;
1112   char name_buf[32];
1113 
1114   no_coverage = 1; /* Disable any further coverage.  */
1115 
1116   if (!prg_ctr_mask)
1117     return false;
1118 
1119   if (symtab->dump_file)
1120     fprintf (symtab->dump_file, "Using data file %s\n", da_file_name);
1121 
1122   /* Prune functions.  */
1123   for (fn_prev = &functions_head; (fn = *fn_prev);)
1124     if (DECL_STRUCT_FUNCTION (fn->fn_decl))
1125       fn_prev = &fn->next;
1126     else
1127       /* The function is not being emitted, remove from list.  */
1128       *fn_prev = fn->next;
1129 
1130   if (functions_head == NULL)
1131     return false;
1132 
1133   for (ix = 0; ix != GCOV_COUNTERS; ix++)
1134     if ((1u << ix) & prg_ctr_mask)
1135       n_counters++;
1136 
1137   /* Build the info and fn_info types.  These are mutually recursive.  */
1138   gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
1139   gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
1140   build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
1141   gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
1142   gcov_fn_info_ptr_type = build_pointer_type
1143     (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
1144   build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
1145 
1146   /* Build the gcov info var, this is referred to in its own
1147      initializer.  */
1148   gcov_info_var = build_decl (BUILTINS_LOCATION,
1149 			      VAR_DECL, NULL_TREE, gcov_info_type);
1150   TREE_STATIC (gcov_info_var) = 1;
1151   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
1152   DECL_NAME (gcov_info_var) = get_identifier (name_buf);
1153 
1154   build_init_ctor (gcov_info_type);
1155   build_gcov_exit_decl ();
1156 
1157   return true;
1158 }
1159 
1160 /* Generate the coverage function info for FN and DATA.  Append a
1161    pointer to that object to CTOR and return the appended CTOR.  */
1162 
1163 static vec<constructor_elt, va_gc> *
coverage_obj_fn(vec<constructor_elt,va_gc> * ctor,tree fn,struct coverage_data const * data)1164 coverage_obj_fn (vec<constructor_elt, va_gc> *ctor, tree fn,
1165 		 struct coverage_data const *data)
1166 {
1167   tree init = build_fn_info (data, gcov_fn_info_type, gcov_info_var);
1168   tree var = build_var (fn, gcov_fn_info_type, -1);
1169 
1170   DECL_INITIAL (var) = init;
1171   varpool_node::finalize_decl (var);
1172 
1173   CONSTRUCTOR_APPEND_ELT (ctor, NULL,
1174 			  build1 (ADDR_EXPR, gcov_fn_info_ptr_type, var));
1175   return ctor;
1176 }
1177 
1178 /* Finalize the coverage data.  Generates the array of pointers to
1179    function objects from CTOR.  Generate the gcov_info initializer.  */
1180 
1181 static void
coverage_obj_finish(vec<constructor_elt,va_gc> * ctor)1182 coverage_obj_finish (vec<constructor_elt, va_gc> *ctor)
1183 {
1184   unsigned n_functions = vec_safe_length (ctor);
1185   tree fn_info_ary_type = build_array_type
1186     (build_qualified_type (gcov_fn_info_ptr_type, TYPE_QUAL_CONST),
1187      build_index_type (size_int (n_functions - 1)));
1188   tree fn_info_ary = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE,
1189 				 fn_info_ary_type);
1190   char name_buf[32];
1191 
1192   TREE_STATIC (fn_info_ary) = 1;
1193   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 1);
1194   DECL_NAME (fn_info_ary) = get_identifier (name_buf);
1195   DECL_INITIAL (fn_info_ary) = build_constructor (fn_info_ary_type, ctor);
1196   varpool_node::finalize_decl (fn_info_ary);
1197 
1198   DECL_INITIAL (gcov_info_var)
1199     = build_info (TREE_TYPE (gcov_info_var), fn_info_ary);
1200   varpool_node::finalize_decl (gcov_info_var);
1201 }
1202 
1203 /* Perform file-level initialization. Read in data file, generate name
1204    of notes file.  */
1205 
1206 void
coverage_init(const char * filename)1207 coverage_init (const char *filename)
1208 {
1209   const char *original_filename = filename;
1210   int original_len = strlen (original_filename);
1211 #if HAVE_DOS_BASED_FILE_SYSTEM
1212   const char *separator = "\\";
1213 #else
1214   const char *separator = "/";
1215 #endif
1216   int len = strlen (filename);
1217   int prefix_len = 0;
1218 
1219   /* Since coverage_init is invoked very early, before the pass
1220      manager, we need to set up the dumping explicitly. This is
1221      similar to the handling in finish_optimization_passes.  */
1222   int profile_pass_num =
1223     g->get_passes ()->get_pass_profile ()->static_pass_number;
1224   g->get_dumps ()->dump_start (profile_pass_num, NULL);
1225 
1226   if (!IS_ABSOLUTE_PATH (filename))
1227     {
1228       /* When a profile_data_prefix is provided, then mangle full path
1229 	 of filename in order to prevent file path clashing.  */
1230       if (profile_data_prefix)
1231 	{
1232 	  filename = concat (getpwd (), separator, filename, NULL);
1233 	  if (profile_prefix_path)
1234 	    {
1235 	      if (!strncmp (filename, profile_prefix_path,
1236 			    strlen (profile_prefix_path)))
1237 		{
1238 		  filename += strlen (profile_prefix_path);
1239 		  while (*filename == *separator)
1240 		    filename++;
1241 		}
1242 	      else
1243 		warning (0, "filename %qs does not start with profile "
1244 			 "prefix %qs", filename, profile_prefix_path);
1245 	    }
1246 	  filename = mangle_path (filename);
1247 	  len = strlen (filename);
1248 	}
1249       else
1250 	profile_data_prefix = getpwd ();
1251     }
1252 
1253   if (profile_data_prefix)
1254     prefix_len = strlen (profile_data_prefix);
1255 
1256   /* Name of da file.  */
1257   da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
1258 			  + prefix_len + 2);
1259 
1260   if (profile_data_prefix)
1261     {
1262       memcpy (da_file_name, profile_data_prefix, prefix_len);
1263       da_file_name[prefix_len++] = *separator;
1264     }
1265   memcpy (da_file_name + prefix_len, filename, len);
1266   strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
1267 
1268   bbg_file_stamp = local_tick;
1269 
1270   if (flag_auto_profile)
1271     read_autofdo_file ();
1272   else if (flag_branch_probabilities)
1273     read_counts_file ();
1274 
1275   /* Name of bbg file.  */
1276   if (flag_test_coverage && !flag_compare_debug)
1277     {
1278       if (profile_note_location)
1279 	bbg_file_name = xstrdup (profile_note_location);
1280       else
1281 	{
1282 	  bbg_file_name = XNEWVEC (char, original_len + strlen (GCOV_NOTE_SUFFIX) + 1);
1283 	  memcpy (bbg_file_name, original_filename, original_len);
1284 	  strcpy (bbg_file_name + original_len, GCOV_NOTE_SUFFIX);
1285 	}
1286 
1287       if (!gcov_open (bbg_file_name, -1))
1288 	{
1289 	  error ("cannot open %s", bbg_file_name);
1290 	  bbg_file_name = NULL;
1291 	}
1292       else
1293 	{
1294 	  gcov_write_unsigned (GCOV_NOTE_MAGIC);
1295 	  gcov_write_unsigned (GCOV_VERSION);
1296 	  gcov_write_unsigned (bbg_file_stamp);
1297 	  gcov_write_string (getpwd ());
1298 
1299 	  /* Do not support has_unexecuted_blocks for Ada.  */
1300 	  gcov_write_unsigned (strcmp (lang_hooks.name, "GNU Ada") != 0);
1301 	}
1302     }
1303 
1304   g->get_dumps ()->dump_finish (profile_pass_num);
1305 }
1306 
1307 /* Performs file-level cleanup.  Close notes file, generate coverage
1308    variables and constructor.  */
1309 
1310 void
coverage_finish(void)1311 coverage_finish (void)
1312 {
1313   if (bbg_file_name && gcov_close ())
1314     unlink (bbg_file_name);
1315 
1316   if (!flag_branch_probabilities && flag_test_coverage
1317       && (!local_tick || local_tick == (unsigned)-1))
1318     /* Only remove the da file, if we're emitting coverage code and
1319        cannot uniquely stamp it.  If we can stamp it, libgcov will DTRT.  */
1320     unlink (da_file_name);
1321 
1322   if (coverage_obj_init ())
1323     {
1324       vec<constructor_elt, va_gc> *fn_ctor = NULL;
1325       struct coverage_data *fn;
1326 
1327       for (fn = functions_head; fn; fn = fn->next)
1328 	fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
1329       coverage_obj_finish (fn_ctor);
1330     }
1331 
1332   XDELETEVEC (da_file_name);
1333   da_file_name = NULL;
1334 }
1335 
1336 #include "gt-coverage.h"
1337