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