OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [coverage.c] - Blame information for rev 715

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 684 jeremybenn
/* Read and write coverage files, and associated functionality.
2
   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3
   2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
4
   Free Software Foundation, Inc.
5
   Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
6
   based on some ideas from Dain Samples of UC Berkeley.
7
   Further mangling by Bob Manson, Cygnus Support.
8
   Further mangled by Nathan Sidwell, CodeSourcery
9
 
10
This file is part of GCC.
11
 
12
GCC is free software; you can redistribute it and/or modify it under
13
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
version.
16
 
17
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18
WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
for more details.
21
 
22
You should have received a copy of the GNU General Public License
23
along with GCC; see the file COPYING3.  If not see
24
<http://www.gnu.org/licenses/>.  */
25
 
26
 
27
#define GCOV_LINKAGE
28
 
29
#include "config.h"
30
#include "system.h"
31
#include "coretypes.h"
32
#include "tm.h"
33
#include "rtl.h"
34
#include "tree.h"
35
#include "flags.h"
36
#include "output.h"
37
#include "regs.h"
38
#include "expr.h"
39
#include "function.h"
40
#include "basic-block.h"
41
#include "toplev.h"
42
#include "tm_p.h"
43
#include "ggc.h"
44
#include "coverage.h"
45
#include "langhooks.h"
46
#include "hashtab.h"
47
#include "tree-iterator.h"
48
#include "cgraph.h"
49
#include "tree-pass.h"
50
#include "diagnostic-core.h"
51
#include "intl.h"
52
#include "filenames.h"
53
#include "target.h"
54
 
55
#include "gcov-io.h"
56
#include "gcov-io.c"
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
typedef struct 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
  struct gcov_ctr_summary summary;
80
} counts_entry_t;
81
 
82
static GTY(()) struct coverage_data *functions_head = 0;
83
static struct coverage_data **functions_tail = &functions_head;
84
static unsigned no_coverage = 0;
85
 
86
/* Cumulative counter information for whole program.  */
87
static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
88
 
89
/* Counter information for current function.  */
90
static unsigned fn_ctr_mask; /* Mask of counters used.  */
91
static GTY(()) tree fn_v_ctrs[GCOV_COUNTERS];   /* counter variables.  */
92
static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
93
static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
94
 
95
/* Coverage info VAR_DECL and function info type nodes.  */
96
static GTY(()) tree gcov_info_var;
97
static GTY(()) tree gcov_fn_info_type;
98
static GTY(()) tree gcov_fn_info_ptr_type;
99
 
100
/* Name of the output file for coverage output file.  If this is NULL
101
   we're not writing to the notes file.  */
102
static char *bbg_file_name;
103
 
104
/* Name of the count data file.  */
105
static char *da_file_name;
106
 
107
/* Hash table of count data.  */
108
static htab_t counts_hash = NULL;
109
 
110
/* The names of merge functions for counters.  */
111
static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
112
static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
113
 
114
/* Forward declarations.  */
115
static hashval_t htab_counts_entry_hash (const void *);
116
static int htab_counts_entry_eq (const void *, const void *);
117
static void htab_counts_entry_del (void *);
118
static void read_counts_file (void);
119
static tree build_var (tree, tree, int);
120
static void build_fn_info_type (tree, unsigned, tree);
121
static void build_info_type (tree, tree);
122
static tree build_fn_info (const struct coverage_data *, tree, tree);
123
static tree build_info (tree, tree);
124
static bool coverage_obj_init (void);
125
static VEC(constructor_elt,gc) *coverage_obj_fn
126
(VEC(constructor_elt,gc) *, tree, struct coverage_data const *);
127
static void coverage_obj_finish (VEC(constructor_elt,gc) *);
128
 
129
/* Return the type node for gcov_type.  */
130
 
131
tree
132
get_gcov_type (void)
133
{
134
  return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
135
}
136
 
137
/* Return the type node for gcov_unsigned_t.  */
138
 
139
static tree
140
get_gcov_unsigned_t (void)
141
{
142
  return lang_hooks.types.type_for_size (32, true);
143
}
144
 
145
static hashval_t
146
htab_counts_entry_hash (const void *of)
147
{
148
  const counts_entry_t *const entry = (const counts_entry_t *) of;
149
 
150
  return entry->ident * GCOV_COUNTERS + entry->ctr;
151
}
152
 
153
static int
154
htab_counts_entry_eq (const void *of1, const void *of2)
155
{
156
  const counts_entry_t *const entry1 = (const counts_entry_t *) of1;
157
  const counts_entry_t *const entry2 = (const counts_entry_t *) of2;
158
 
159
  return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
160
}
161
 
162
static void
163
htab_counts_entry_del (void *of)
164
{
165
  counts_entry_t *const entry = (counts_entry_t *) of;
166
 
167
  free (entry->counts);
168
  free (entry);
169
}
170
 
171
/* Read in the counts file, if available.  */
172
 
173
static void
174
read_counts_file (void)
175
{
176
  gcov_unsigned_t fn_ident = 0;
177
  struct gcov_summary summary;
178
  unsigned new_summary = 1;
179
  gcov_unsigned_t tag;
180
  int is_error = 0;
181
  unsigned lineno_checksum = 0;
182
  unsigned cfg_checksum = 0;
183
 
184
  if (!gcov_open (da_file_name, 1))
185
    return;
186
 
187
  if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
188
    {
189
      warning (0, "%qs is not a gcov data file", da_file_name);
190
      gcov_close ();
191
      return;
192
    }
193
  else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
194
    {
195
      char v[4], e[4];
196
 
197
      GCOV_UNSIGNED2STRING (v, tag);
198
      GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
199
 
200
      warning (0, "%qs is version %q.*s, expected version %q.*s",
201
               da_file_name, 4, v, 4, e);
202
      gcov_close ();
203
      return;
204
    }
205
 
206
  /* Read and discard the stamp.  */
207
  gcov_read_unsigned ();
208
 
209
  counts_hash = htab_create (10,
210
                             htab_counts_entry_hash, htab_counts_entry_eq,
211
                             htab_counts_entry_del);
212
  while ((tag = gcov_read_unsigned ()))
213
    {
214
      gcov_unsigned_t length;
215
      gcov_position_t offset;
216
 
217
      length = gcov_read_unsigned ();
218
      offset = gcov_position ();
219
      if (tag == GCOV_TAG_FUNCTION)
220
        {
221
          if (length)
222
            {
223
              fn_ident = gcov_read_unsigned ();
224
              lineno_checksum = gcov_read_unsigned ();
225
              cfg_checksum = gcov_read_unsigned ();
226
            }
227
          else
228
            fn_ident = lineno_checksum = cfg_checksum = 0;
229
          new_summary = 1;
230
        }
231
      else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
232
        {
233
          struct gcov_summary sum;
234
          unsigned ix;
235
 
236
          if (new_summary)
237
            memset (&summary, 0, sizeof (summary));
238
 
239
          gcov_read_summary (&sum);
240
          for (ix = 0; ix != GCOV_COUNTERS_SUMMABLE; ix++)
241
            {
242
              summary.ctrs[ix].runs += sum.ctrs[ix].runs;
243
              summary.ctrs[ix].sum_all += sum.ctrs[ix].sum_all;
244
              if (summary.ctrs[ix].run_max < sum.ctrs[ix].run_max)
245
                summary.ctrs[ix].run_max = sum.ctrs[ix].run_max;
246
              summary.ctrs[ix].sum_max += sum.ctrs[ix].sum_max;
247
            }
248
          new_summary = 0;
249
        }
250
      else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
251
        {
252
          counts_entry_t **slot, *entry, elt;
253
          unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
254
          unsigned ix;
255
 
256
          elt.ident = fn_ident;
257
          elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
258
 
259
          slot = (counts_entry_t **) htab_find_slot
260
            (counts_hash, &elt, INSERT);
261
          entry = *slot;
262
          if (!entry)
263
            {
264
              *slot = entry = XCNEW (counts_entry_t);
265
              entry->ident = fn_ident;
266
              entry->ctr = elt.ctr;
267
              entry->lineno_checksum = lineno_checksum;
268
              entry->cfg_checksum = cfg_checksum;
269
              entry->summary = summary.ctrs[elt.ctr];
270
              entry->summary.num = n_counts;
271
              entry->counts = XCNEWVEC (gcov_type, n_counts);
272
            }
273
          else if (entry->lineno_checksum != lineno_checksum
274
                   || entry->cfg_checksum != cfg_checksum)
275
            {
276
              error ("Profile data for function %u is corrupted", fn_ident);
277
              error ("checksum is (%x,%x) instead of (%x,%x)",
278
                     entry->lineno_checksum, entry->cfg_checksum,
279
                     lineno_checksum, cfg_checksum);
280
              htab_delete (counts_hash);
281
              break;
282
            }
283
          else if (entry->summary.num != n_counts)
284
            {
285
              error ("Profile data for function %u is corrupted", fn_ident);
286
              error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
287
              htab_delete (counts_hash);
288
              break;
289
            }
290
          else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
291
            {
292
              error ("cannot merge separate %s counters for function %u",
293
                     ctr_names[elt.ctr], fn_ident);
294
              goto skip_merge;
295
            }
296
          else
297
            {
298
              entry->summary.runs += summary.ctrs[elt.ctr].runs;
299
              entry->summary.sum_all += summary.ctrs[elt.ctr].sum_all;
300
              if (entry->summary.run_max < summary.ctrs[elt.ctr].run_max)
301
                entry->summary.run_max = summary.ctrs[elt.ctr].run_max;
302
              entry->summary.sum_max += summary.ctrs[elt.ctr].sum_max;
303
            }
304
          for (ix = 0; ix != n_counts; ix++)
305
            entry->counts[ix] += gcov_read_counter ();
306
        skip_merge:;
307
        }
308
      gcov_sync (offset, length);
309
      if ((is_error = gcov_is_error ()))
310
        {
311
          error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
312
                 da_file_name);
313
          htab_delete (counts_hash);
314
          break;
315
        }
316
    }
317
 
318
  gcov_close ();
319
}
320
 
321
/* Returns the counters for a particular tag.  */
322
 
323
gcov_type *
324
get_coverage_counts (unsigned counter, unsigned expected,
325
                     unsigned cfg_checksum, unsigned lineno_checksum,
326
                     const struct gcov_ctr_summary **summary)
327
{
328
  counts_entry_t *entry, elt;
329
 
330
  /* No hash table, no counts.  */
331
  if (!counts_hash)
332
    {
333
      static int warned = 0;
334
 
335
      if (!warned++)
336
        inform (input_location, (flag_guess_branch_prob
337
                 ? "file %s not found, execution counts estimated"
338
                 : "file %s not found, execution counts assumed to be zero"),
339
                da_file_name);
340
      return NULL;
341
    }
342
 
343
  elt.ident = current_function_funcdef_no + 1;
344
  elt.ctr = counter;
345
  entry = (counts_entry_t *) htab_find (counts_hash, &elt);
346
  if (!entry || !entry->summary.num)
347
    /* The function was not emitted, or is weak and not chosen in the
348
       final executable.  Silently fail, because there's nothing we
349
       can do about it.  */
350
    return NULL;
351
 
352
  if (entry->cfg_checksum != cfg_checksum
353
      || entry->summary.num != expected)
354
    {
355
      static int warned = 0;
356
      bool warning_printed = false;
357
      tree id = DECL_ASSEMBLER_NAME (current_function_decl);
358
 
359
      warning_printed =
360
        warning_at (input_location, OPT_Wcoverage_mismatch,
361
                    "the control flow of function %qE does not match "
362
                    "its profile data (counter %qs)", id, ctr_names[counter]);
363
      if (warning_printed)
364
        {
365
         inform (input_location, "use -Wno-error=coverage-mismatch to tolerate "
366
                 "the mismatch but performance may drop if the function is hot");
367
 
368
          if (!seen_error ()
369
              && !warned++)
370
            {
371
              inform (input_location, "coverage mismatch ignored");
372
              inform (input_location, flag_guess_branch_prob
373
                      ? G_("execution counts estimated")
374
                      : G_("execution counts assumed to be zero"));
375
              if (!flag_guess_branch_prob)
376
                inform (input_location,
377
                        "this can result in poorly optimized code");
378
            }
379
        }
380
 
381
      return NULL;
382
    }
383
  else if (entry->lineno_checksum != lineno_checksum)
384
    {
385
      warning (0, "source locations for function %qE have changed,"
386
               " the profile data may be out of date",
387
               DECL_ASSEMBLER_NAME (current_function_decl));
388
    }
389
 
390
  if (summary)
391
    *summary = &entry->summary;
392
 
393
  return entry->counts;
394
}
395
 
396
/* Allocate NUM counters of type COUNTER. Returns nonzero if the
397
   allocation succeeded.  */
398
 
399
int
400
coverage_counter_alloc (unsigned counter, unsigned num)
401
{
402
  if (no_coverage)
403
    return 0;
404
 
405
  if (!num)
406
    return 1;
407
 
408
  if (!fn_v_ctrs[counter])
409
    {
410
      tree array_type = build_array_type (get_gcov_type (), NULL_TREE);
411
 
412
      fn_v_ctrs[counter]
413
        = build_var (current_function_decl, array_type, counter);
414
    }
415
 
416
  fn_b_ctrs[counter] = fn_n_ctrs[counter];
417
  fn_n_ctrs[counter] += num;
418
 
419
  fn_ctr_mask |= 1 << counter;
420
  return 1;
421
}
422
 
423
/* Generate a tree to access COUNTER NO.  */
424
 
425
tree
426
tree_coverage_counter_ref (unsigned counter, unsigned no)
427
{
428
  tree gcov_type_node = get_gcov_type ();
429
 
430
  gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
431
 
432
  no += fn_b_ctrs[counter];
433
 
434
  /* "no" here is an array index, scaled to bytes later.  */
435
  return build4 (ARRAY_REF, gcov_type_node, fn_v_ctrs[counter],
436
                 build_int_cst (integer_type_node, no), NULL, NULL);
437
}
438
 
439
/* Generate a tree to access the address of COUNTER NO.  */
440
 
441
tree
442
tree_coverage_counter_addr (unsigned counter, unsigned no)
443
{
444
  tree gcov_type_node = get_gcov_type ();
445
 
446
  gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
447
  no += fn_b_ctrs[counter];
448
 
449
  /* "no" here is an array index, scaled to bytes later.  */
450
  return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
451
                                       fn_v_ctrs[counter],
452
                                       build_int_cst (integer_type_node, no),
453
                                       NULL, NULL));
454
}
455
 
456
 
457
/* Generate a checksum for a string.  CHKSUM is the current
458
   checksum.  */
459
 
460
static unsigned
461
coverage_checksum_string (unsigned chksum, const char *string)
462
{
463
  int i;
464
  char *dup = NULL;
465
 
466
  /* Look for everything that looks if it were produced by
467
     get_file_function_name and zero out the second part
468
     that may result from flag_random_seed.  This is not critical
469
     as the checksums are used only for sanity checking.  */
470
  for (i = 0; string[i]; i++)
471
    {
472
      int offset = 0;
473
      if (!strncmp (string + i, "_GLOBAL__N_", 11))
474
      offset = 11;
475
      if (!strncmp (string + i, "_GLOBAL__", 9))
476
      offset = 9;
477
 
478
      /* C++ namespaces do have scheme:
479
         _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
480
       since filename might contain extra underscores there seems
481
       to be no better chance then walk all possible offsets looking
482
       for magicnumber.  */
483
      if (offset)
484
        {
485
          for (i = i + offset; string[i]; i++)
486
            if (string[i]=='_')
487
              {
488
                int y;
489
 
490
                for (y = 1; y < 9; y++)
491
                  if (!(string[i + y] >= '0' && string[i + y] <= '9')
492
                      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
493
                    break;
494
                if (y != 9 || string[i + 9] != '_')
495
                  continue;
496
                for (y = 10; y < 18; y++)
497
                  if (!(string[i + y] >= '0' && string[i + y] <= '9')
498
                      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
499
                    break;
500
                if (y != 18)
501
                  continue;
502
                if (!dup)
503
                  string = dup = xstrdup (string);
504
                for (y = 10; y < 18; y++)
505
                  dup[i + y] = '0';
506
              }
507
          break;
508
        }
509
    }
510
 
511
  chksum = crc32_string (chksum, string);
512
  free (dup);
513
 
514
  return chksum;
515
}
516
 
517
/* Compute checksum for the current function.  We generate a CRC32.  */
518
 
519
unsigned
520
coverage_compute_lineno_checksum (void)
521
{
522
  expanded_location xloc
523
    = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
524
  unsigned chksum = xloc.line;
525
 
526
  chksum = coverage_checksum_string (chksum, xloc.file);
527
  chksum = coverage_checksum_string
528
    (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
529
 
530
  return chksum;
531
}
532
 
533
/* Compute cfg checksum for the current function.
534
   The checksum is calculated carefully so that
535
   source code changes that doesn't affect the control flow graph
536
   won't change the checksum.
537
   This is to make the profile data useable across source code change.
538
   The downside of this is that the compiler may use potentially
539
   wrong profile data - that the source code change has non-trivial impact
540
   on the validity of profile data (e.g. the reversed condition)
541
   but the compiler won't detect the change and use the wrong profile data.  */
542
 
543
unsigned
544
coverage_compute_cfg_checksum (void)
545
{
546
  basic_block bb;
547
  unsigned chksum = n_basic_blocks;
548
 
549
  FOR_EACH_BB (bb)
550
    {
551
      edge e;
552
      edge_iterator ei;
553
      chksum = crc32_byte (chksum, bb->index);
554
      FOR_EACH_EDGE (e, ei, bb->succs)
555
        {
556
          chksum = crc32_byte (chksum, e->dest->index);
557
        }
558
    }
559
 
560
  return chksum;
561
}
562
 
563
/* Begin output to the graph file for the current function.
564
   Writes the function header. Returns nonzero if data should be output.  */
565
 
566
int
567
coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
568
{
569
  expanded_location xloc;
570
  unsigned long offset;
571
 
572
  /* We don't need to output .gcno file unless we're under -ftest-coverage
573
     (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
574
  if (no_coverage || !bbg_file_name)
575
    return 0;
576
 
577
  xloc = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
578
 
579
  /* Announce function */
580
  offset = gcov_write_tag (GCOV_TAG_FUNCTION);
581
  gcov_write_unsigned (current_function_funcdef_no + 1);
582
  gcov_write_unsigned (lineno_checksum);
583
  gcov_write_unsigned (cfg_checksum);
584
  gcov_write_string (IDENTIFIER_POINTER
585
                     (DECL_ASSEMBLER_NAME (current_function_decl)));
586
  gcov_write_string (xloc.file);
587
  gcov_write_unsigned (xloc.line);
588
  gcov_write_length (offset);
589
 
590
  return !gcov_is_error ();
591
}
592
 
593
/* Finish coverage data for the current function. Verify no output
594
   error has occurred.  Save function coverage counts.  */
595
 
596
void
597
coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
598
{
599
  unsigned i;
600
 
601
  if (bbg_file_name && gcov_is_error ())
602
    {
603
      warning (0, "error writing %qs", bbg_file_name);
604
      unlink (bbg_file_name);
605
      bbg_file_name = NULL;
606
    }
607
 
608
  if (fn_ctr_mask)
609
    {
610
      struct coverage_data *item = 0;
611
 
612
      /* If the function is extern (i.e. extern inline), then we won't
613
         be outputting it, so don't chain it onto the function
614
         list.  */
615
      if (!DECL_EXTERNAL (current_function_decl))
616
        {
617
          item = ggc_alloc_coverage_data ();
618
 
619
          item->ident = current_function_funcdef_no + 1;
620
          item->lineno_checksum = lineno_checksum;
621
          item->cfg_checksum = cfg_checksum;
622
 
623
          item->fn_decl = current_function_decl;
624
          item->next = 0;
625
          *functions_tail = item;
626
          functions_tail = &item->next;
627
        }
628
 
629
      for (i = 0; i != GCOV_COUNTERS; i++)
630
        {
631
          tree var = fn_v_ctrs[i];
632
 
633
          if (item)
634
            item->ctr_vars[i] = var;
635
          if (var)
636
            {
637
              tree array_type = build_index_type (size_int (fn_n_ctrs[i] - 1));
638
              array_type = build_array_type (get_gcov_type (), array_type);
639
              TREE_TYPE (var) = array_type;
640
              DECL_SIZE (var) = TYPE_SIZE (array_type);
641
              DECL_SIZE_UNIT (var) = TYPE_SIZE_UNIT (array_type);
642
              varpool_finalize_decl (var);
643
            }
644
 
645
          fn_b_ctrs[i] = fn_n_ctrs[i] = 0;
646
          fn_v_ctrs[i] = NULL_TREE;
647
        }
648
      prg_ctr_mask |= fn_ctr_mask;
649
      fn_ctr_mask = 0;
650
    }
651
}
652
 
653
/* Build a coverage variable of TYPE for function FN_DECL.  If COUNTER
654
   >= 0 it is a counter array, otherwise it is the function structure.  */
655
 
656
static tree
657
build_var (tree fn_decl, tree type, int counter)
658
{
659
  tree var = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE, type);
660
  const char *fn_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn_decl));
661
  char *buf;
662
  size_t fn_name_len, len;
663
 
664
  fn_name = targetm.strip_name_encoding (fn_name);
665
  fn_name_len = strlen (fn_name);
666
  buf = XALLOCAVEC (char, fn_name_len + 8 + sizeof (int) * 3);
667
 
668
  if (counter < 0)
669
    strcpy (buf, "__gcov__");
670
  else
671
    sprintf (buf, "__gcov%u_", counter);
672
  len = strlen (buf);
673
#ifndef NO_DOT_IN_LABEL
674
  buf[len - 1] = '.';
675
#elif !defined NO_DOLLAR_IN_LABEL
676
  buf[len - 1] = '$';
677
#endif
678
  memcpy (buf + len, fn_name, fn_name_len + 1);
679
  DECL_NAME (var) = get_identifier (buf);
680
  TREE_STATIC (var) = 1;
681
  TREE_ADDRESSABLE (var) = 1;
682
  DECL_ALIGN (var) = TYPE_ALIGN (type);
683
 
684
  return var;
685
}
686
 
687
/* Creates the gcov_fn_info RECORD_TYPE.  */
688
 
689
static void
690
build_fn_info_type (tree type, unsigned counters, tree gcov_info_type)
691
{
692
  tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE);
693
  tree field, fields;
694
  tree array_type;
695
 
696
  gcc_assert (counters);
697
 
698
  /* ctr_info::num */
699
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
700
                      get_gcov_unsigned_t ());
701
  fields = field;
702
 
703
  /* ctr_info::values */
704
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
705
                      build_pointer_type (get_gcov_type ()));
706
  DECL_CHAIN (field) = fields;
707
  fields = field;
708
 
709
  finish_builtin_struct (ctr_info, "__gcov_ctr_info", fields, NULL_TREE);
710
 
711
  /* key */
712
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
713
                      build_pointer_type (build_qualified_type
714
                                          (gcov_info_type, TYPE_QUAL_CONST)));
715
  fields = field;
716
 
717
  /* ident */
718
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
719
                      get_gcov_unsigned_t ());
720
  DECL_CHAIN (field) = fields;
721
  fields = field;
722
 
723
  /* lineno_checksum */
724
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
725
                      get_gcov_unsigned_t ());
726
  DECL_CHAIN (field) = fields;
727
  fields = field;
728
 
729
  /* cfg checksum */
730
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
731
                      get_gcov_unsigned_t ());
732
  DECL_CHAIN (field) = fields;
733
  fields = field;
734
 
735
  array_type = build_index_type (size_int (counters - 1));
736
  array_type = build_array_type (ctr_info, array_type);
737
 
738
  /* counters */
739
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type);
740
  DECL_CHAIN (field) = fields;
741
  fields = field;
742
 
743
  finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
744
}
745
 
746
/* Returns a CONSTRUCTOR for a gcov_fn_info.  DATA is
747
   the coverage data for the function and TYPE is the gcov_fn_info
748
   RECORD_TYPE.  KEY is the object file key.  */
749
 
750
static tree
751
build_fn_info (const struct coverage_data *data, tree type, tree key)
752
{
753
  tree fields = TYPE_FIELDS (type);
754
  tree ctr_type;
755
  unsigned ix;
756
  VEC(constructor_elt,gc) *v1 = NULL;
757
  VEC(constructor_elt,gc) *v2 = NULL;
758
 
759
  /* key */
760
  CONSTRUCTOR_APPEND_ELT (v1, fields,
761
                          build1 (ADDR_EXPR, TREE_TYPE (fields), key));
762
  fields = DECL_CHAIN (fields);
763
 
764
  /* ident */
765
  CONSTRUCTOR_APPEND_ELT (v1, fields,
766
                          build_int_cstu (get_gcov_unsigned_t (),
767
                                          data->ident));
768
  fields = DECL_CHAIN (fields);
769
 
770
  /* lineno_checksum */
771
  CONSTRUCTOR_APPEND_ELT (v1, fields,
772
                          build_int_cstu (get_gcov_unsigned_t (),
773
                                          data->lineno_checksum));
774
  fields = DECL_CHAIN (fields);
775
 
776
  /* cfg_checksum */
777
  CONSTRUCTOR_APPEND_ELT (v1, fields,
778
                          build_int_cstu (get_gcov_unsigned_t (),
779
                                          data->cfg_checksum));
780
  fields = DECL_CHAIN (fields);
781
 
782
  /* counters */
783
  ctr_type = TREE_TYPE (TREE_TYPE (fields));
784
  for (ix = 0; ix != GCOV_COUNTERS; ix++)
785
    if (prg_ctr_mask & (1 << ix))
786
      {
787
        VEC(constructor_elt,gc) *ctr = NULL;
788
        tree var = data->ctr_vars[ix];
789
        unsigned count = 0;
790
 
791
        if (var)
792
          count
793
            = tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (var))), 0)
794
            + 1;
795
 
796
        CONSTRUCTOR_APPEND_ELT (ctr, TYPE_FIELDS (ctr_type),
797
                                build_int_cstu (get_gcov_unsigned_t (),
798
                                                count));
799
 
800
        if (var)
801
          CONSTRUCTOR_APPEND_ELT (ctr, DECL_CHAIN (TYPE_FIELDS (ctr_type)),
802
                                  build_fold_addr_expr (var));
803
 
804
        CONSTRUCTOR_APPEND_ELT (v2, NULL, build_constructor (ctr_type, ctr));
805
      }
806
 
807
  CONSTRUCTOR_APPEND_ELT (v1, fields,
808
                          build_constructor (TREE_TYPE (fields), v2));
809
 
810
  return build_constructor (type, v1);
811
}
812
 
813
/* Create gcov_info struct.  TYPE is the incomplete RECORD_TYPE to be
814
   completed, and FN_INFO_PTR_TYPE is a pointer to the function info type.  */
815
 
816
static void
817
build_info_type (tree type, tree fn_info_ptr_type)
818
{
819
  tree field, fields = NULL_TREE;
820
  tree merge_fn_type;
821
 
822
  /* Version ident */
823
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
824
                      get_gcov_unsigned_t ());
825
  DECL_CHAIN (field) = fields;
826
  fields = field;
827
 
828
  /* next pointer */
829
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
830
                      build_pointer_type (build_qualified_type
831
                                          (type, TYPE_QUAL_CONST)));
832
  DECL_CHAIN (field) = fields;
833
  fields = field;
834
 
835
  /* stamp */
836
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
837
                      get_gcov_unsigned_t ());
838
  DECL_CHAIN (field) = fields;
839
  fields = field;
840
 
841
  /* Filename */
842
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
843
                      build_pointer_type (build_qualified_type
844
                                          (char_type_node, TYPE_QUAL_CONST)));
845
  DECL_CHAIN (field) = fields;
846
  fields = field;
847
 
848
  /* merge fn array */
849
  merge_fn_type
850
    = build_function_type_list (void_type_node,
851
                                build_pointer_type (get_gcov_type ()),
852
                                get_gcov_unsigned_t (), NULL_TREE);
853
  merge_fn_type
854
    = build_array_type (build_pointer_type (merge_fn_type),
855
                        build_index_type (size_int (GCOV_COUNTERS - 1)));
856
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
857
                      merge_fn_type);
858
  DECL_CHAIN (field) = fields;
859
  fields = field;
860
 
861
  /* n_functions */
862
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
863
                      get_gcov_unsigned_t ());
864
  DECL_CHAIN (field) = fields;
865
  fields = field;
866
 
867
  /* function_info pointer pointer */
868
  fn_info_ptr_type = build_pointer_type
869
    (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST));
870
  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
871
                      fn_info_ptr_type);
872
  DECL_CHAIN (field) = fields;
873
  fields = field;
874
 
875
  finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
876
}
877
 
878
/* Returns a CONSTRUCTOR for the gcov_info object.  INFO_TYPE is the
879
   gcov_info structure type, FN_ARY is the array of pointers to
880
   function info objects.  */
881
 
882
static tree
883
build_info (tree info_type, tree fn_ary)
884
{
885
  tree info_fields = TYPE_FIELDS (info_type);
886
  tree merge_fn_type, n_funcs;
887
  unsigned ix;
888
  tree filename_string;
889
  int da_file_name_len;
890
  VEC(constructor_elt,gc) *v1 = NULL;
891
  VEC(constructor_elt,gc) *v2 = NULL;
892
 
893
  /* Version ident */
894
  CONSTRUCTOR_APPEND_ELT (v1, info_fields,
895
                          build_int_cstu (TREE_TYPE (info_fields),
896
                                          GCOV_VERSION));
897
  info_fields = DECL_CHAIN (info_fields);
898
 
899
  /* next -- NULL */
900
  CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
901
  info_fields = DECL_CHAIN (info_fields);
902
 
903
  /* stamp */
904
  CONSTRUCTOR_APPEND_ELT (v1, info_fields,
905
                          build_int_cstu (TREE_TYPE (info_fields),
906
                                          local_tick));
907
  info_fields = DECL_CHAIN (info_fields);
908
 
909
  /* Filename */
910
  da_file_name_len = strlen (da_file_name);
911
  filename_string = build_string (da_file_name_len + 1, da_file_name);
912
  TREE_TYPE (filename_string) = build_array_type
913
    (char_type_node, build_index_type (size_int (da_file_name_len)));
914
  CONSTRUCTOR_APPEND_ELT (v1, info_fields,
915
                          build1 (ADDR_EXPR, TREE_TYPE (info_fields),
916
                                  filename_string));
917
  info_fields = DECL_CHAIN (info_fields);
918
 
919
  /* merge fn array -- NULL slots indicate unmeasured counters */
920
  merge_fn_type = TREE_TYPE (TREE_TYPE (info_fields));
921
  for (ix = 0; ix != GCOV_COUNTERS; ix++)
922
    {
923
      tree ptr = null_pointer_node;
924
 
925
      if ((1u << ix) & prg_ctr_mask)
926
        {
927
          tree merge_fn = build_decl (BUILTINS_LOCATION,
928
                                      FUNCTION_DECL,
929
                                      get_identifier (ctr_merge_functions[ix]),
930
                                      TREE_TYPE (merge_fn_type));
931
          DECL_EXTERNAL (merge_fn) = 1;
932
          TREE_PUBLIC (merge_fn) = 1;
933
          DECL_ARTIFICIAL (merge_fn) = 1;
934
          TREE_NOTHROW (merge_fn) = 1;
935
          /* Initialize assembler name so we can stream out. */
936
          DECL_ASSEMBLER_NAME (merge_fn);
937
          ptr = build1 (ADDR_EXPR, merge_fn_type, merge_fn);
938
        }
939
      CONSTRUCTOR_APPEND_ELT (v2, NULL, ptr);
940
    }
941
  CONSTRUCTOR_APPEND_ELT (v1, info_fields,
942
                          build_constructor (TREE_TYPE (info_fields), v2));
943
  info_fields = DECL_CHAIN (info_fields);
944
 
945
  /* n_functions */
946
  n_funcs = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (fn_ary)));
947
  n_funcs = fold_build2 (PLUS_EXPR, TREE_TYPE (info_fields),
948
                         n_funcs, size_one_node);
949
  CONSTRUCTOR_APPEND_ELT (v1, info_fields, n_funcs);
950
  info_fields = DECL_CHAIN (info_fields);
951
 
952
  /* functions */
953
  CONSTRUCTOR_APPEND_ELT (v1, info_fields,
954
                          build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary));
955
  info_fields = DECL_CHAIN (info_fields);
956
 
957
  gcc_assert (!info_fields);
958
  return build_constructor (info_type, v1);
959
}
960
 
961
/* Create the gcov_info types and object.  Generate the constructor
962
   function to call __gcov_init.  Does not generate the initializer
963
   for the object.  Returns TRUE if coverage data is being emitted.  */
964
 
965
static bool
966
coverage_obj_init (void)
967
{
968
  tree gcov_info_type, ctor, stmt, init_fn;
969
  unsigned n_counters = 0;
970
  unsigned ix;
971
  struct coverage_data *fn;
972
  struct coverage_data **fn_prev;
973
  char name_buf[32];
974
 
975
  no_coverage = 1; /* Disable any further coverage.  */
976
 
977
  if (!prg_ctr_mask)
978
    return false;
979
 
980
  if (cgraph_dump_file)
981
    fprintf (cgraph_dump_file, "Using data file %s\n", da_file_name);
982
 
983
  /* Prune functions.  */
984
  for (fn_prev = &functions_head; (fn = *fn_prev);)
985
    if (DECL_STRUCT_FUNCTION (fn->fn_decl))
986
      fn_prev = &fn->next;
987
    else
988
      /* The function is not being emitted, remove from list.  */
989
      *fn_prev = fn->next;
990
 
991
  for (ix = 0; ix != GCOV_COUNTERS; ix++)
992
    if ((1u << ix) & prg_ctr_mask)
993
      n_counters++;
994
 
995
  /* Build the info and fn_info types.  These are mutually recursive.  */
996
  gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
997
  gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
998
  gcov_fn_info_ptr_type = build_pointer_type
999
    (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
1000
  build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
1001
  build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
1002
 
1003
  /* Build the gcov info var, this is referred to in its own
1004
     initializer.  */
1005
  gcov_info_var = build_decl (BUILTINS_LOCATION,
1006
                              VAR_DECL, NULL_TREE, gcov_info_type);
1007
  TREE_STATIC (gcov_info_var) = 1;
1008
  ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
1009
  DECL_NAME (gcov_info_var) = get_identifier (name_buf);
1010
 
1011
  /* Build a decl for __gcov_init.  */
1012
  init_fn = build_pointer_type (gcov_info_type);
1013
  init_fn = build_function_type_list (void_type_node, init_fn, NULL);
1014
  init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1015
                        get_identifier ("__gcov_init"), init_fn);
1016
  TREE_PUBLIC (init_fn) = 1;
1017
  DECL_EXTERNAL (init_fn) = 1;
1018
  DECL_ASSEMBLER_NAME (init_fn);
1019
 
1020
  /* Generate a call to __gcov_init(&gcov_info).  */
1021
  ctor = NULL;
1022
  stmt = build_fold_addr_expr (gcov_info_var);
1023
  stmt = build_call_expr (init_fn, 1, stmt);
1024
  append_to_statement_list (stmt, &ctor);
1025
 
1026
  /* Generate a constructor to run it.  */
1027
  cgraph_build_static_cdtor ('I', ctor, DEFAULT_INIT_PRIORITY);
1028
 
1029
  return true;
1030
}
1031
 
1032
/* Generate the coverage function info for FN and DATA.  Append a
1033
   pointer to that object to CTOR and return the appended CTOR.  */
1034
 
1035
static VEC(constructor_elt,gc) *
1036
coverage_obj_fn (VEC(constructor_elt,gc) *ctor, tree fn,
1037
                 struct coverage_data const *data)
1038
{
1039
  tree init = build_fn_info (data, gcov_fn_info_type, gcov_info_var);
1040
  tree var = build_var (fn, gcov_fn_info_type, -1);
1041
 
1042
  DECL_INITIAL (var) = init;
1043
  varpool_finalize_decl (var);
1044
 
1045
  CONSTRUCTOR_APPEND_ELT (ctor, NULL,
1046
                          build1 (ADDR_EXPR, gcov_fn_info_ptr_type, var));
1047
  return ctor;
1048
}
1049
 
1050
/* Finalize the coverage data.  Generates the array of pointers to
1051
   function objects from CTOR.  Generate the gcov_info initializer.  */
1052
 
1053
static void
1054
coverage_obj_finish (VEC(constructor_elt,gc) *ctor)
1055
{
1056
  unsigned n_functions = VEC_length(constructor_elt, ctor);
1057
  tree fn_info_ary_type = build_array_type
1058
    (build_qualified_type (gcov_fn_info_ptr_type, TYPE_QUAL_CONST),
1059
     build_index_type (size_int (n_functions - 1)));
1060
  tree fn_info_ary = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL_TREE,
1061
                                 fn_info_ary_type);
1062
  char name_buf[32];
1063
 
1064
  TREE_STATIC (fn_info_ary) = 1;
1065
  ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 1);
1066
  DECL_NAME (fn_info_ary) = get_identifier (name_buf);
1067
  DECL_INITIAL (fn_info_ary) = build_constructor (fn_info_ary_type, ctor);
1068
  varpool_finalize_decl (fn_info_ary);
1069
 
1070
  DECL_INITIAL (gcov_info_var)
1071
    = build_info (TREE_TYPE (gcov_info_var), fn_info_ary);
1072
  varpool_finalize_decl (gcov_info_var);
1073
}
1074
 
1075
/* Perform file-level initialization. Read in data file, generate name
1076
   of graph file.  */
1077
 
1078
void
1079
coverage_init (const char *filename)
1080
{
1081
  int len = strlen (filename);
1082
  int prefix_len = 0;
1083
 
1084
  if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename))
1085
    profile_data_prefix = getpwd ();
1086
 
1087
  if (profile_data_prefix)
1088
    prefix_len = strlen (profile_data_prefix);
1089
 
1090
  /* Name of da file.  */
1091
  da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
1092
                          + prefix_len + 2);
1093
 
1094
  if (profile_data_prefix)
1095
    {
1096
      memcpy (da_file_name, profile_data_prefix, prefix_len);
1097
      da_file_name[prefix_len++] = '/';
1098
    }
1099
  memcpy (da_file_name + prefix_len, filename, len);
1100
  strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
1101
 
1102
  /* Name of bbg file.  */
1103
  if (flag_test_coverage && !flag_compare_debug)
1104
    {
1105
      bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1106
      memcpy (bbg_file_name, filename, len);
1107
      strcpy (bbg_file_name + len, GCOV_NOTE_SUFFIX);
1108
 
1109
      if (!gcov_open (bbg_file_name, -1))
1110
        {
1111
          error ("cannot open %s", bbg_file_name);
1112
          bbg_file_name = NULL;
1113
        }
1114
      else
1115
        {
1116
          gcov_write_unsigned (GCOV_NOTE_MAGIC);
1117
          gcov_write_unsigned (GCOV_VERSION);
1118
          gcov_write_unsigned (local_tick);
1119
        }
1120
    }
1121
 
1122
  if (flag_branch_probabilities)
1123
    read_counts_file ();
1124
}
1125
 
1126
/* Performs file-level cleanup.  Close graph file, generate coverage
1127
   variables and constructor.  */
1128
 
1129
void
1130
coverage_finish (void)
1131
{
1132
  if (bbg_file_name && gcov_close ())
1133
    unlink (bbg_file_name);
1134
 
1135
  if (!local_tick || local_tick == (unsigned)-1)
1136
    /* Only remove the da file, if we cannot stamp it.  If we can
1137
       stamp it, libgcov will DTRT.  */
1138
    unlink (da_file_name);
1139
 
1140
  if (coverage_obj_init ())
1141
    {
1142
      VEC(constructor_elt,gc) *fn_ctor = NULL;
1143
      struct coverage_data *fn;
1144
 
1145
      for (fn = functions_head; fn; fn = fn->next)
1146
        fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
1147
      coverage_obj_finish (fn_ctor);
1148
    }
1149
}
1150
 
1151
#include "gt-coverage.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.