coverage.c 28.8 KB
Newer Older
1 2
/* Read and write coverage files, and associated functionality.
   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
Joseph Myers committed
3 4
   2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010
   Free Software Foundation, Inc.
5 6 7 8 9 10 11 12 13
   Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
   based on some ideas from Dain Samples of UC Berkeley.
   Further mangling by Bob Manson, Cygnus Support.
   Further mangled by Nathan Sidwell, CodeSourcery

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
14
Software Foundation; either version 3, or (at your option) any later
15 16 17 18 19 20 21 22
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
23 24
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39


#define GCOV_LINKAGE

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
#include "output.h"
#include "regs.h"
#include "expr.h"
#include "function.h"
40
#include "basic-block.h"
41
#include "toplev.h"
42
#include "tm_p.h"
43 44 45 46
#include "ggc.h"
#include "coverage.h"
#include "langhooks.h"
#include "hashtab.h"
47 48
#include "tree-iterator.h"
#include "cgraph.h"
49
#include "tree-pass.h"
Joseph Myers committed
50
#include "diagnostic-core.h"
51
#include "intl.h"
52 53 54 55 56

#include "gcov-io.c"

struct function_list
{
57 58
  struct function_list *next;	 /* next function */
  unsigned ident;		 /* function ident */
59 60
  unsigned checksum;	         /* function checksum */
  unsigned n_ctrs[GCOV_COUNTERS];/* number of counters.  */
61 62 63 64 65 66
};

/* Counts information for a function.  */
typedef struct counts_entry
{
  /* We hash by  */
67
  unsigned ident;
68
  unsigned ctr;
69

70 71 72
  /* Store  */
  unsigned checksum;
  gcov_type *counts;
73
  struct gcov_ctr_summary summary;
74 75 76

  /* Workspace */
  struct counts_entry *chain;
77

78 79 80 81
} counts_entry_t;

static struct function_list *functions_head = 0;
static struct function_list **functions_tail = &functions_head;
82
static unsigned no_coverage = 0;
83

84 85
/* Cumulative counter information for whole program.  */
static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
86
static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated.  */
87

88
/* Counter information for current function.  */
89
static unsigned fn_ctr_mask; /* Mask of counters used.  */
90 91
static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
92 93 94 95 96 97 98 99 100 101 102 103

/* Name of the output file for coverage output file.  */
static char *bbg_file_name;
static unsigned bbg_file_opened;
static int bbg_function_announced;

/* Name of the count data file.  */
static char *da_file_name;

/* Hash table of count data.  */
static htab_t counts_hash = NULL;

104 105 106
/* Trees representing the counter table arrays.  */
static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];

107
/* The names of merge functions for counters.  */
108 109
static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
110

111
/* Forward declarations.  */
112 113 114 115 116
static hashval_t htab_counts_entry_hash (const void *);
static int htab_counts_entry_eq (const void *, const void *);
static void htab_counts_entry_del (void *);
static void read_counts_file (void);
static unsigned compute_checksum (void);
117
static unsigned coverage_checksum_string (unsigned, const char *);
118 119 120 121 122 123
static tree build_fn_info_type (unsigned);
static tree build_fn_info_value (const struct function_list *, tree);
static tree build_ctr_info_type (void);
static tree build_ctr_info_value (unsigned, tree);
static tree build_gcov_info (void);
static void create_coverage (void);
124 125 126 127 128 129 130 131 132 133

/* Return the type node for gcov_type.  */

tree
get_gcov_type (void)
{
  return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
}

/* Return the type node for gcov_unsigned_t.  */
134

135 136 137 138 139
static tree
get_gcov_unsigned_t (void)
{
  return lang_hooks.types.type_for_size (32, true);
}
140 141

static hashval_t
142
htab_counts_entry_hash (const void *of)
143
{
144
  const counts_entry_t *const entry = (const counts_entry_t *) of;
145

146
  return entry->ident * GCOV_COUNTERS + entry->ctr;
147 148 149
}

static int
150
htab_counts_entry_eq (const void *of1, const void *of2)
151
{
152 153
  const counts_entry_t *const entry1 = (const counts_entry_t *) of1;
  const counts_entry_t *const entry2 = (const counts_entry_t *) of2;
154

155
  return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
156 157 158
}

static void
159
htab_counts_entry_del (void *of)
160
{
161
  counts_entry_t *const entry = (counts_entry_t *) of;
162 163 164 165 166 167 168 169

  free (entry->counts);
  free (entry);
}

/* Read in the counts file, if available.  */

static void
170
read_counts_file (void)
171
{
172
  gcov_unsigned_t fn_ident = 0;
173
  gcov_unsigned_t checksum = -1;
174 175
  counts_entry_t *summaried = NULL;
  unsigned seen_summary = 0;
176
  gcov_unsigned_t tag;
177
  int is_error = 0;
178

179 180
  if (!gcov_open (da_file_name, 1))
    return;
181

182
  if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
183
    {
184
      warning (0, "%qs is not a gcov data file", da_file_name);
185 186 187
      gcov_close ();
      return;
    }
188
  else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
189
    {
190 191 192 193
      char v[4], e[4];

      GCOV_UNSIGNED2STRING (v, tag);
      GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
194

195
      warning (0, "%qs is version %q.*s, expected version %q.*s",
196
 	       da_file_name, 4, v, 4, e);
197 198 199
      gcov_close ();
      return;
    }
200

201
  /* Read and discard the stamp.  */
202
  gcov_read_unsigned ();
H.J. Lu committed
203

204 205 206
  counts_hash = htab_create (10,
			     htab_counts_entry_hash, htab_counts_entry_eq,
			     htab_counts_entry_del);
207
  while ((tag = gcov_read_unsigned ()))
208
    {
209
      gcov_unsigned_t length;
210
      gcov_position_t offset;
211

212 213 214 215
      length = gcov_read_unsigned ();
      offset = gcov_position ();
      if (tag == GCOV_TAG_FUNCTION)
	{
216
	  fn_ident = gcov_read_unsigned ();
217 218 219 220 221 222 223
	  checksum = gcov_read_unsigned ();
	  if (seen_summary)
	    {
	      /* We have already seen a summary, this means that this
		 new function begins a new set of program runs. We
		 must unlink the summaried chain.  */
	      counts_entry_t *entry, *chain;
224

225 226 227 228 229 230 231 232 233 234 235 236 237
	      for (entry = summaried; entry; entry = chain)
		{
		  chain = entry->chain;
		  entry->chain = NULL;
		}
	      summaried = NULL;
	      seen_summary = 0;
	    }
	}
      else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
	{
	  counts_entry_t *entry;
	  struct gcov_summary summary;
238

239 240 241 242
	  gcov_read_summary (&summary);
	  seen_summary = 1;
	  for (entry = summaried; entry; entry = entry->chain)
	    {
243
	      struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
244

245 246 247 248 249
	      entry->summary.runs += csum->runs;
	      entry->summary.sum_all += csum->sum_all;
	      if (entry->summary.run_max < csum->run_max)
		entry->summary.run_max = csum->run_max;
	      entry->summary.sum_max += csum->sum_max;
250 251
	    }
	}
252
      else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
253 254
	{
	  counts_entry_t **slot, *entry, elt;
255
	  unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
256 257
	  unsigned ix;

258
	  elt.ident = fn_ident;
259
	  elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
260 261 262 263 264 265

	  slot = (counts_entry_t **) htab_find_slot
	    (counts_hash, &elt, INSERT);
	  entry = *slot;
	  if (!entry)
	    {
266
	      *slot = entry = XCNEW (counts_entry_t);
267
	      entry->ident = elt.ident;
268
	      entry->ctr = elt.ctr;
269
	      entry->checksum = checksum;
270
	      entry->summary.num = n_counts;
271
	      entry->counts = XCNEWVEC (gcov_type, n_counts);
272
	    }
273
	  else if (entry->checksum != checksum)
274
	    {
275
	      error ("coverage mismatch for function %u while reading execution counters",
276 277 278 279 280 281 282
		     fn_ident);
	      error ("checksum is %x instead of %x", entry->checksum, checksum);
	      htab_delete (counts_hash);
	      break;
	    }
	  else if (entry->summary.num != n_counts)
	    {
283
	      error ("coverage mismatch for function %u while reading execution counters",
284 285
		     fn_ident);
	      error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
286 287 288
	      htab_delete (counts_hash);
	      break;
	    }
289 290
	  else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
	    {
291 292
	      error ("cannot merge separate %s counters for function %u",
		     ctr_names[elt.ctr], fn_ident);
293 294 295 296 297
	      goto skip_merge;
	    }

	  if (elt.ctr < GCOV_COUNTERS_SUMMABLE
	      /* This should always be true for a just allocated entry,
298 299
		 and always false for an existing one. Check this way, in
		 case the gcov file is corrupt.  */
300
	      && (!entry->chain || summaried != entry))
301 302 303 304 305 306
	    {
	      entry->chain = summaried;
	      summaried = entry;
	    }
	  for (ix = 0; ix != n_counts; ix++)
	    entry->counts[ix] += gcov_read_counter ();
307
	skip_merge:;
308
	}
309
      gcov_sync (offset, length);
310
      if ((is_error = gcov_is_error ()))
311
	{
312
	  error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
313 314 315 316
		 da_file_name);
	  htab_delete (counts_hash);
	  break;
	}
317
    }
318

319 320 321 322 323 324
  gcov_close ();
}

/* Returns the counters for a particular tag.  */

gcov_type *
325 326
get_coverage_counts (unsigned counter, unsigned expected,
		     const struct gcov_ctr_summary **summary)
327 328
{
  counts_entry_t *entry, elt;
329
  gcov_unsigned_t checksum = -1;
330

331
  /* No hash table, no counts.  */
332 333 334 335 336
  if (!counts_hash)
    {
      static int warned = 0;

      if (!warned++)
337
	inform (input_location, (flag_guess_branch_prob
338 339
		 ? "file %s not found, execution counts estimated"
		 : "file %s not found, execution counts assumed to be zero"),
340
		da_file_name);
341 342 343
      return NULL;
    }

344
  elt.ident = current_function_funcdef_no + 1;
345
  elt.ctr = counter;
346
  entry = (counts_entry_t *) htab_find (counts_hash, &elt);
347 348
  if (!entry)
    {
349 350
      warning (0, "no coverage for function %qE found",
	       DECL_ASSEMBLER_NAME (current_function_decl));
351
      return NULL;
352
    }
353

354
  checksum = compute_checksum ();
355 356
  if (entry->checksum != checksum
      || entry->summary.num != expected)
357
    {
358
      static int warned = 0;
359
      bool warning_printed = false;
360
      tree id = DECL_ASSEMBLER_NAME (current_function_decl);
361

362 363 364 365 366
      warning_printed = 
	warning_at (input_location, OPT_Wcoverage_mismatch, 
		    "coverage mismatch for function "
		    "%qE while reading counter %qs", id, ctr_names[counter]);
      if (warning_printed)
367 368
	{
	  if (entry->checksum != checksum)
369 370
	    inform (input_location, "checksum is %x instead of %x",
		    entry->checksum, checksum);
371
	  else
372
	    inform (input_location, "number of counters is %d instead of %d",
373
		    entry->summary.num, expected);
374
	  
Joseph Myers committed
375
	  if (!seen_error ()
376 377 378 379 380 381 382 383 384 385
	      && !warned++)
	    {
	      inform (input_location, "coverage mismatch ignored");
	      inform (input_location, flag_guess_branch_prob
		      ? G_("execution counts estimated")
		      : G_("execution counts assumed to be zero"));
	      if (!flag_guess_branch_prob)
		inform (input_location,
			"this can result in poorly optimized code");
	    }
386 387 388
	}

      return NULL;
389
    }
390

391 392
  if (summary)
    *summary = &entry->summary;
393 394 395

  return entry->counts;
}
396

397
/* Allocate NUM counters of type COUNTER. Returns nonzero if the
398
   allocation succeeded.  */
399

400 401
int
coverage_counter_alloc (unsigned counter, unsigned num)
402
{
403 404
  if (no_coverage)
    return 0;
405

406 407
  if (!num)
    return 1;
408

409
  if (!tree_ctr_tables[counter])
410
    {
411 412 413
      /* Generate and save a copy of this so it can be shared.  Leave
	 the index type unspecified for now; it will be set after all
	 functions have been compiled.  */
414
      char buf[20];
415
      tree gcov_type_node = get_gcov_type ();
416
      tree gcov_type_array_type
417
        = build_array_type (gcov_type_node, NULL_TREE);
418
      tree_ctr_tables[counter]
419 420
        = build_decl (BUILTINS_LOCATION,
		      VAR_DECL, NULL_TREE, gcov_type_array_type);
421
      TREE_STATIC (tree_ctr_tables[counter]) = 1;
422
      ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
423
      DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
424
      DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node);
425 426 427

      if (dump_file)
	fprintf (dump_file, "Using data file %s\n", da_file_name);
428
    }
429 430 431 432 433
  fn_b_ctrs[counter] = fn_n_ctrs[counter];
  fn_n_ctrs[counter] += num;
  fn_ctr_mask |= 1 << counter;
  return 1;
}
434

435 436 437 438 439
/* Generate a tree to access COUNTER NO.  */

tree
tree_coverage_counter_ref (unsigned counter, unsigned no)
{
440
  tree gcov_type_node = get_gcov_type ();
441

442
  gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
443 444 445
  no += prg_n_ctrs[counter] + fn_b_ctrs[counter];

  /* "no" here is an array index, scaled to bytes later.  */
446
  return build4 (ARRAY_REF, gcov_type_node, tree_ctr_tables[counter],
447
		 build_int_cst (NULL_TREE, no), NULL, NULL);
448
}
449 450 451 452 453 454 455 456 457 458 459

/* Generate a tree to access the address of COUNTER NO.  */

tree
tree_coverage_counter_addr (unsigned counter, unsigned no)
{
  tree gcov_type_node = get_gcov_type ();

  gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
  no += prg_n_ctrs[counter] + fn_b_ctrs[counter];

460 461
  TREE_ADDRESSABLE (tree_ctr_tables[counter]) = 1;

462 463 464 465 466 467
  /* "no" here is an array index, scaled to bytes later.  */
  return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
				       tree_ctr_tables[counter],
				       build_int_cst (NULL_TREE, no),
				       NULL, NULL));
}
468 469

/* Generate a checksum for a string.  CHKSUM is the current
470
   checksum.  */
471 472

static unsigned
473
coverage_checksum_string (unsigned chksum, const char *string)
474
{
475 476 477 478
  int i;
  char *dup = NULL;

  /* Look for everything that looks if it were produced by
Geoffrey Keating committed
479
     get_file_function_name and zero out the second part
480 481 482
     that may result from flag_random_seed.  This is not critical
     as the checksums are used only for sanity checking.  */
  for (i = 0; string[i]; i++)
483
    {
484 485 486
      int offset = 0;
      if (!strncmp (string + i, "_GLOBAL__N_", 11))
      offset = 11;
487
      if (!strncmp (string + i, "_GLOBAL__", 9))
488 489 490 491 492 493
      offset = 9;

      /* C++ namespaces do have scheme:
         _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
       since filename might contain extra underscores there seems
       to be no better chance then walk all possible offsets looking
494
       for magicnumber.  */
495
      if (offset)
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
	{
	  for (i = i + offset; string[i]; i++)
	    if (string[i]=='_')
	      {
		int y;

		for (y = 1; y < 9; y++)
		  if (!(string[i + y] >= '0' && string[i + y] <= '9')
		      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
		    break;
		if (y != 9 || string[i + 9] != '_')
		  continue;
		for (y = 10; y < 18; y++)
		  if (!(string[i + y] >= '0' && string[i + y] <= '9')
		      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
		    break;
		if (y != 18)
		  continue;
		if (!dup)
		  string = dup = xstrdup (string);
		for (y = 10; y < 18; y++)
		  dup[i + y] = '0';
	      }
	  break;
	}
521
    }
522 523 524 525

  chksum = crc32_string (chksum, string);
  if (dup)
    free (dup);
526

527 528 529 530 531 532
  return chksum;
}

/* Compute checksum for the current function.  We generate a CRC32.  */

static unsigned
533
compute_checksum (void)
534
{
535 536 537
  expanded_location xloc
    = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
  unsigned chksum = xloc.line;
538

539
  chksum = coverage_checksum_string (chksum, xloc.file);
540
  chksum = coverage_checksum_string
541 542 543 544 545 546 547
    (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));

  return chksum;
}

/* Begin output to the graph file for the current function.
   Opens the output file, if not already done. Writes the
548
   function header, if not already done. Returns nonzero if data
549 550 551
   should be output.  */

int
552
coverage_begin_output (void)
553
{
554 555
  /* We don't need to output .gcno file unless we're under -ftest-coverage
     (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
556
  if (no_coverage || !flag_test_coverage || flag_compare_debug)
557
    return 0;
558

559 560
  if (!bbg_function_announced)
    {
561 562
      expanded_location xloc
	= expand_location (DECL_SOURCE_LOCATION (current_function_decl));
563
      unsigned long offset;
564

565 566 567 568 569 570
      if (!bbg_file_opened)
	{
	  if (!gcov_open (bbg_file_name, -1))
	    error ("cannot open %s", bbg_file_name);
	  else
	    {
571
	      gcov_write_unsigned (GCOV_NOTE_MAGIC);
572
	      gcov_write_unsigned (GCOV_VERSION);
573
	      gcov_write_unsigned (local_tick);
574 575 576
	    }
	  bbg_file_opened = 1;
	}
577

578 579
      /* Announce function */
      offset = gcov_write_tag (GCOV_TAG_FUNCTION);
580
      gcov_write_unsigned (current_function_funcdef_no + 1);
581
      gcov_write_unsigned (compute_checksum ());
582 583
      gcov_write_string (IDENTIFIER_POINTER
			 (DECL_ASSEMBLER_NAME (current_function_decl)));
584 585
      gcov_write_string (xloc.file);
      gcov_write_unsigned (xloc.line);
586 587 588 589 590 591 592 593 594 595 596
      gcov_write_length (offset);

      bbg_function_announced = 1;
    }
  return !gcov_is_error ();
}

/* Finish coverage data for the current function. Verify no output
   error has occurred.  Save function coverage counts.  */

void
597
coverage_end_function (void)
598 599
{
  unsigned i;
600

601
  if (bbg_file_opened > 1 && gcov_is_error ())
602
    {
603
      warning (0, "error writing %qs", bbg_file_name);
604 605
      bbg_file_opened = -1;
    }
606 607 608 609

  if (fn_ctr_mask)
    {
      struct function_list *item;
610

611
      item = XNEW (struct function_list);
612

613 614
      *functions_tail = item;
      functions_tail = &item->next;
615

616
      item->next = 0;
617
      item->ident = current_function_funcdef_no + 1;
618 619 620 621 622
      item->checksum = compute_checksum ();
      for (i = 0; i != GCOV_COUNTERS; i++)
	{
	  item->n_ctrs[i] = fn_n_ctrs[i];
	  prg_n_ctrs[i] += fn_n_ctrs[i];
623
	  fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
624 625 626 627
	}
      prg_ctr_mask |= fn_ctr_mask;
      fn_ctr_mask = 0;
    }
628 629 630
  bbg_function_announced = 0;
}

631
/* Creates the gcov_fn_info RECORD_TYPE.  */
632 633

static tree
634
build_fn_info_type (unsigned int counters)
635
{
636
  tree type = lang_hooks.types.make_type (RECORD_TYPE);
637
  tree field, fields;
638
  tree array_type;
639

640
  /* ident */
641 642
  fields = build_decl (BUILTINS_LOCATION,
		       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
643

644
  /* checksum */
645 646
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
647
  DECL_CHAIN (field) = fields;
648 649
  fields = field;

650
  array_type = build_int_cst (NULL_TREE, counters - 1);
651
  array_type = build_index_type (array_type);
652
  array_type = build_array_type (get_gcov_unsigned_t (), array_type);
653

654
  /* counters */
655 656
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, array_type);
657
  DECL_CHAIN (field) = fields;
658 659
  fields = field;

660 661 662
  finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);

  return type;
663 664
}

665 666 667 668
/* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
   the function being processed and TYPE is the gcov_fn_info
   RECORD_TYPE.  */

669
static tree
670
build_fn_info_value (const struct function_list *function, tree type)
671
{
672 673
  tree fields = TYPE_FIELDS (type);
  unsigned ix;
674 675
  VEC(constructor_elt,gc) *v1 = NULL;
  VEC(constructor_elt,gc) *v2 = NULL;
676

677
  /* ident */
678 679 680
  CONSTRUCTOR_APPEND_ELT (v1, fields,
			  build_int_cstu (get_gcov_unsigned_t (),
					  function->ident));
681
  fields = DECL_CHAIN (fields);
682

683
  /* checksum */
684 685 686
  CONSTRUCTOR_APPEND_ELT (v1, fields,
			  build_int_cstu (get_gcov_unsigned_t (),
					  function->checksum));
687
  fields = DECL_CHAIN (fields);
688

689
  /* counters */
690 691
  for (ix = 0; ix != GCOV_COUNTERS; ix++)
    if (prg_ctr_mask & (1 << ix))
692 693 694
      CONSTRUCTOR_APPEND_ELT (v2, NULL,
			      build_int_cstu (get_gcov_unsigned_t (),
					      function->n_ctrs[ix]));
695

696 697
  CONSTRUCTOR_APPEND_ELT (v1, fields,
			  build_constructor (TREE_TYPE (fields), v2));
698

699
  return build_constructor (type, v1);
700 701
}

702 703
/* Creates the gcov_ctr_info RECORD_TYPE.  */

704
static tree
705
build_ctr_info_type (void)
706
{
707
  tree type = lang_hooks.types.make_type (RECORD_TYPE);
708
  tree field, fields = NULL_TREE;
709
  tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
710
  tree gcov_merge_fn_type;
711

712
  /* counters */
713 714
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
715
  DECL_CHAIN (field) = fields;
716 717
  fields = field;

718
  /* values */
719 720
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, gcov_ptr_type);
721
  DECL_CHAIN (field) = fields;
722 723
  fields = field;

724 725
  /* merge */
  gcov_merge_fn_type =
726
    build_function_type_list (void_type_node,
727
			      gcov_ptr_type, get_gcov_unsigned_t (),
728
			      NULL_TREE);
729 730
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE,
731
		      build_pointer_type (gcov_merge_fn_type));
732
  DECL_CHAIN (field) = fields;
733 734
  fields = field;

735
  finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
736

737
  return type;
738 739
}

740 741 742 743
/* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
   the counter being processed and TYPE is the gcov_ctr_info
   RECORD_TYPE.  */

744
static tree
745
build_ctr_info_value (unsigned int counter, tree type)
746
{
747
  tree fields = TYPE_FIELDS (type);
748
  tree fn;
749
  VEC(constructor_elt,gc) *v = NULL;
750

751
  /* counters */
752 753 754
  CONSTRUCTOR_APPEND_ELT (v, fields,
			  build_int_cstu (get_gcov_unsigned_t (),
					  prg_n_ctrs[counter]));
755
  fields = DECL_CHAIN (fields);
756

757
  if (prg_n_ctrs[counter])
758
    {
759
      tree array_type;
760

761
      array_type = build_int_cstu (get_gcov_unsigned_t (),
762
				   prg_n_ctrs[counter] - 1);
763
      array_type = build_index_type (array_type);
764 765
      array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
				     array_type);
766

767 768 769
      TREE_TYPE (tree_ctr_tables[counter]) = array_type;
      DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
      DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
770
      varpool_finalize_decl (tree_ctr_tables[counter]);
771

772 773 774
      CONSTRUCTOR_APPEND_ELT (v, fields,
			      build1 (ADDR_EXPR, TREE_TYPE (fields),
				      tree_ctr_tables[counter]));
775 776
    }
  else
777
    CONSTRUCTOR_APPEND_ELT (v, fields, null_pointer_node);
778
  fields = DECL_CHAIN (fields);
779

780 781
  fn = build_decl (BUILTINS_LOCATION,
		   FUNCTION_DECL,
782 783 784 785 786 787
		   get_identifier (ctr_merge_functions[counter]),
		   TREE_TYPE (TREE_TYPE (fields)));
  DECL_EXTERNAL (fn) = 1;
  TREE_PUBLIC (fn) = 1;
  DECL_ARTIFICIAL (fn) = 1;
  TREE_NOTHROW (fn) = 1;
788
  DECL_ASSEMBLER_NAME (fn);  /* Initialize assembler name so we can stream out. */
789
  CONSTRUCTOR_APPEND_ELT (v, fields, build1 (ADDR_EXPR, TREE_TYPE (fields), fn));
790

791
  return build_constructor (type, v);
792 793
}

794 795 796
/* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
   CONSTRUCTOR.  */

797
static tree
798
build_gcov_info (void)
799
{
800 801 802 803 804 805 806
  unsigned n_ctr_types, ix;
  tree type, const_type;
  tree fn_info_type, fn_info_value = NULL_TREE;
  tree fn_info_ptr_type;
  tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
  tree field, fields = NULL_TREE;
  tree filename_string;
807
  int da_file_name_len;
808 809 810
  unsigned n_fns;
  const struct function_list *fn;
  tree string_type;
811 812
  VEC(constructor_elt,gc) *v1 = NULL;
  VEC(constructor_elt,gc) *v2 = NULL;
813

814 815 816 817
  /* Count the number of active counters.  */
  for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
    if (prg_ctr_mask & (1 << ix))
      n_ctr_types++;
818

819
  type = lang_hooks.types.make_type (RECORD_TYPE);
820
  const_type = build_qualified_type (type, TYPE_QUAL_CONST);
821

822
  /* Version ident */
823 824
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
825
  DECL_CHAIN (field) = fields;
826
  fields = field;
827 828
  CONSTRUCTOR_APPEND_ELT (v1, field,
			  build_int_cstu (TREE_TYPE (field), GCOV_VERSION));
829

830
  /* next -- NULL */
831 832
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
833
  DECL_CHAIN (field) = fields;
834
  fields = field;
835
  CONSTRUCTOR_APPEND_ELT (v1, field, null_pointer_node);
836

837
  /* stamp */
838 839
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
840
  DECL_CHAIN (field) = fields;
841
  fields = field;
842 843
  CONSTRUCTOR_APPEND_ELT (v1, field,
			  build_int_cstu (TREE_TYPE (field), local_tick));
844

845
  /* Filename */
846 847
  string_type = build_pointer_type (build_qualified_type (char_type_node,
						    TYPE_QUAL_CONST));
848 849
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, string_type);
850
  DECL_CHAIN (field) = fields;
851
  fields = field;
852 853
  da_file_name_len = strlen (da_file_name);
  filename_string = build_string (da_file_name_len + 1, da_file_name);
854 855
  TREE_TYPE (filename_string) = build_array_type
    (char_type_node, build_index_type
856
     (build_int_cst (NULL_TREE, da_file_name_len)));
857 858
  CONSTRUCTOR_APPEND_ELT (v1, field,
			  build1 (ADDR_EXPR, string_type, filename_string));
859

860 861 862 863 864
  /* Build the fn_info type and initializer.  */
  fn_info_type = build_fn_info_type (n_ctr_types);
  fn_info_ptr_type = build_pointer_type (build_qualified_type
					 (fn_info_type, TYPE_QUAL_CONST));
  for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
865 866 867
    CONSTRUCTOR_APPEND_ELT (v2, NULL_TREE,
			    build_fn_info_value (fn, fn_info_type));

868
  if (n_fns)
869 870 871
    {
      tree array_type;

872
      array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
873
      array_type = build_array_type (fn_info_type, array_type);
874

875
      fn_info_value = build_constructor (array_type, v2);
876
      fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
877 878
    }
  else
879
    fn_info_value = null_pointer_node;
880

881
  /* number of functions */
882 883
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
884
  DECL_CHAIN (field) = fields;
885
  fields = field;
886 887
  CONSTRUCTOR_APPEND_ELT (v1, field,
			  build_int_cstu (get_gcov_unsigned_t (), n_fns));
888

889
  /* fn_info table */
890 891
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, fn_info_ptr_type);
892
  DECL_CHAIN (field) = fields;
893
  fields = field;
894
  CONSTRUCTOR_APPEND_ELT (v1, field, fn_info_value);
895

896
  /* counter_mask */
897 898
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
899
  DECL_CHAIN (field) = fields;
900
  fields = field;
901 902 903
  CONSTRUCTOR_APPEND_ELT (v1, field, 
			  build_int_cstu (get_gcov_unsigned_t (),
					  prg_ctr_mask));
904

905 906
  /* counters */
  ctr_info_type = build_ctr_info_type ();
907
  ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
908
						       n_ctr_types));
909
  ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
910
  v2 = NULL;
911 912
  for (ix = 0; ix != GCOV_COUNTERS; ix++)
    if (prg_ctr_mask & (1 << ix))
913 914 915
      CONSTRUCTOR_APPEND_ELT (v2, NULL_TREE,
			      build_ctr_info_value (ix, ctr_info_type));
  ctr_info_value = build_constructor (ctr_info_ary_type, v2);
916

917 918
  field = build_decl (BUILTINS_LOCATION,
		      FIELD_DECL, NULL_TREE, ctr_info_ary_type);
919
  DECL_CHAIN (field) = fields;
920
  fields = field;
921
  CONSTRUCTOR_APPEND_ELT (v1, field, ctr_info_value);
922

923
  finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
924

925
  return build_constructor (type, v1);
926 927
}

928
/* Write out the structure which libgcov uses to locate all the
929 930 931 932
   counters.  The structures used here must match those defined in
   gcov-io.h.  Write out the constructor to call __gcov_init.  */

static void
933
create_coverage (void)
934
{
935 936
  tree gcov_info, gcov_init, body, t;
  char name_buf[32];
937

938
  no_coverage = 1; /* Disable any further coverage.  */
939

940
  if (!prg_ctr_mask)
941
    return;
942

943
  t = build_gcov_info ();
944

945 946
  gcov_info = build_decl (BUILTINS_LOCATION,
			  VAR_DECL, NULL_TREE, TREE_TYPE (t));
947
  TREE_STATIC (gcov_info) = 1;
948 949 950
  ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
  DECL_NAME (gcov_info) = get_identifier (name_buf);
  DECL_INITIAL (gcov_info) = t;
951

952
  /* Build structure.  */
953
  varpool_finalize_decl (gcov_info);
954

955 956 957
  /* Build a decl for __gcov_init.  */
  t = build_pointer_type (TREE_TYPE (gcov_info));
  t = build_function_type_list (void_type_node, t, NULL);
958 959
  t = build_decl (BUILTINS_LOCATION,
		  FUNCTION_DECL, get_identifier ("__gcov_init"), t);
960 961
  TREE_PUBLIC (t) = 1;
  DECL_EXTERNAL (t) = 1;
962
  DECL_ASSEMBLER_NAME (t);  /* Initialize assembler name so we can stream out. */
963 964 965 966 967
  gcov_init = t;

  /* Generate a call to __gcov_init(&gcov_info).  */
  body = NULL;
  t = build_fold_addr_expr (gcov_info);
968
  t = build_call_expr (gcov_init, 1, t);
969 970 971
  append_to_statement_list (t, &body);

  /* Generate a constructor to run it.  */
Frank Ch. Eigler committed
972
  cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
973 974 975
}

/* Perform file-level initialization. Read in data file, generate name
976
   of graph file.  */
977 978

void
979
coverage_init (const char *filename)
980 981
{
  int len = strlen (filename);
982 983
  /* + 1 for extra '/', in case prefix doesn't end with /.  */
  int prefix_len;
H.J. Lu committed
984

985 986 987 988
  if (profile_data_prefix == 0 && filename[0] != '/')
    profile_data_prefix = getpwd ();

  prefix_len = (profile_data_prefix) ? strlen (profile_data_prefix) + 1 : 0;
989

990
  /* Name of da file.  */
H.J. Lu committed
991
  da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
992 993 994 995 996 997 998 999 1000 1001 1002
			  + prefix_len + 1);

  if (profile_data_prefix)
    {
      strcpy (da_file_name, profile_data_prefix);
      da_file_name[prefix_len - 1] = '/';
      da_file_name[prefix_len] = 0;
    }
  else
    da_file_name[0] = 0;
  strcat (da_file_name, filename);
1003
  strcat (da_file_name, GCOV_DATA_SUFFIX);
1004

1005
  /* Name of bbg file.  */
1006
  bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1007
  strcpy (bbg_file_name, filename);
1008
  strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
1009

1010 1011
  if (flag_profile_use)
    read_counts_file ();
1012 1013 1014 1015 1016 1017
}

/* Performs file-level cleanup.  Close graph file, generate coverage
   variables and constructor.  */

void
1018
coverage_finish (void)
1019 1020 1021 1022 1023
{
  create_coverage ();
  if (bbg_file_opened)
    {
      int error = gcov_close ();
1024

1025 1026
      if (error)
	unlink (bbg_file_name);
1027 1028 1029
      if (!local_tick)
	/* Only remove the da file, if we cannot stamp it. If we can
	   stamp it, libgcov will DTRT.  */
1030 1031 1032 1033 1034
	unlink (da_file_name);
    }
}

#include "gt-coverage.h"