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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [coverage.c] - Blame information for rev 280

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 280 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 Free Software Foundation,
4
   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 "toplev.h"
41
#include "tm_p.h"
42
#include "ggc.h"
43
#include "coverage.h"
44
#include "langhooks.h"
45
#include "hashtab.h"
46
#include "tree-iterator.h"
47
#include "cgraph.h"
48
#include "tree-pass.h"
49
 
50
#include "gcov-io.c"
51
 
52
struct function_list
53
{
54
  struct function_list *next;    /* next function */
55
  unsigned ident;                /* function ident */
56
  unsigned checksum;             /* function checksum */
57
  unsigned n_ctrs[GCOV_COUNTERS];/* number of counters.  */
58
};
59
 
60
/* Counts information for a function.  */
61
typedef struct counts_entry
62
{
63
  /* We hash by  */
64
  unsigned ident;
65
  unsigned ctr;
66
 
67
  /* Store  */
68
  unsigned checksum;
69
  gcov_type *counts;
70
  struct gcov_ctr_summary summary;
71
 
72
  /* Workspace */
73
  struct counts_entry *chain;
74
 
75
} counts_entry_t;
76
 
77
static struct function_list *functions_head = 0;
78
static struct function_list **functions_tail = &functions_head;
79
static unsigned no_coverage = 0;
80
 
81
/* Cumulative counter information for whole program.  */
82
static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
83
static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated.  */
84
 
85
/* Counter information for current function.  */
86
static unsigned fn_ctr_mask; /* Mask of counters used.  */
87
static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
88
static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
89
 
90
/* Name of the output file for coverage output file.  */
91
static char *bbg_file_name;
92
static unsigned bbg_file_opened;
93
static int bbg_function_announced;
94
 
95
/* Name of the count data file.  */
96
static char *da_file_name;
97
 
98
/* Hash table of count data.  */
99
static htab_t counts_hash = NULL;
100
 
101
/* Trees representing the counter table arrays.  */
102
static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
103
 
104
/* The names of the counter tables.  Not used if we're
105
   generating counters at tree level.  */
106
static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
107
 
108
/* The names of merge functions for counters.  */
109
static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
110
static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
111
 
112
/* Forward declarations.  */
113
static hashval_t htab_counts_entry_hash (const void *);
114
static int htab_counts_entry_eq (const void *, const void *);
115
static void htab_counts_entry_del (void *);
116
static void read_counts_file (void);
117
static unsigned compute_checksum (void);
118
static unsigned coverage_checksum_string (unsigned, const char *);
119
static tree build_fn_info_type (unsigned);
120
static tree build_fn_info_value (const struct function_list *, tree);
121
static tree build_ctr_info_type (void);
122
static tree build_ctr_info_value (unsigned, tree);
123
static tree build_gcov_info (void);
124
static void create_coverage (void);
125
 
126
/* Return the type node for gcov_type.  */
127
 
128
tree
129
get_gcov_type (void)
130
{
131
  return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
132
}
133
 
134
/* Return the type node for gcov_unsigned_t.  */
135
 
136
static tree
137
get_gcov_unsigned_t (void)
138
{
139
  return lang_hooks.types.type_for_size (32, true);
140
}
141
 
142
static hashval_t
143
htab_counts_entry_hash (const void *of)
144
{
145
  const counts_entry_t *const entry = (const counts_entry_t *) of;
146
 
147
  return entry->ident * GCOV_COUNTERS + entry->ctr;
148
}
149
 
150
static int
151
htab_counts_entry_eq (const void *of1, const void *of2)
152
{
153
  const counts_entry_t *const entry1 = (const counts_entry_t *) of1;
154
  const counts_entry_t *const entry2 = (const counts_entry_t *) of2;
155
 
156
  return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
157
}
158
 
159
static void
160
htab_counts_entry_del (void *of)
161
{
162
  counts_entry_t *const entry = (counts_entry_t *) of;
163
 
164
  free (entry->counts);
165
  free (entry);
166
}
167
 
168
/* Read in the counts file, if available.  */
169
 
170
static void
171
read_counts_file (void)
172
{
173
  gcov_unsigned_t fn_ident = 0;
174
  gcov_unsigned_t checksum = -1;
175
  counts_entry_t *summaried = NULL;
176
  unsigned seen_summary = 0;
177
  gcov_unsigned_t tag;
178
  int is_error = 0;
179
 
180
  if (!gcov_open (da_file_name, 1))
181
    return;
182
 
183
  if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
184
    {
185
      warning (0, "%qs is not a gcov data file", da_file_name);
186
      gcov_close ();
187
      return;
188
    }
189
  else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
190
    {
191
      char v[4], e[4];
192
 
193
      GCOV_UNSIGNED2STRING (v, tag);
194
      GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
195
 
196
      warning (0, "%qs is version %q.*s, expected version %q.*s",
197
               da_file_name, 4, v, 4, e);
198
      gcov_close ();
199
      return;
200
    }
201
 
202
  /* Read and discard the stamp.  */
203
  gcov_read_unsigned ();
204
 
205
  counts_hash = htab_create (10,
206
                             htab_counts_entry_hash, htab_counts_entry_eq,
207
                             htab_counts_entry_del);
208
  while ((tag = gcov_read_unsigned ()))
209
    {
210
      gcov_unsigned_t length;
211
      gcov_position_t offset;
212
 
213
      length = gcov_read_unsigned ();
214
      offset = gcov_position ();
215
      if (tag == GCOV_TAG_FUNCTION)
216
        {
217
          fn_ident = gcov_read_unsigned ();
218
          checksum = gcov_read_unsigned ();
219
          if (seen_summary)
220
            {
221
              /* We have already seen a summary, this means that this
222
                 new function begins a new set of program runs. We
223
                 must unlink the summaried chain.  */
224
              counts_entry_t *entry, *chain;
225
 
226
              for (entry = summaried; entry; entry = chain)
227
                {
228
                  chain = entry->chain;
229
                  entry->chain = NULL;
230
                }
231
              summaried = NULL;
232
              seen_summary = 0;
233
            }
234
        }
235
      else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
236
        {
237
          counts_entry_t *entry;
238
          struct gcov_summary summary;
239
 
240
          gcov_read_summary (&summary);
241
          seen_summary = 1;
242
          for (entry = summaried; entry; entry = entry->chain)
243
            {
244
              struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
245
 
246
              entry->summary.runs += csum->runs;
247
              entry->summary.sum_all += csum->sum_all;
248
              if (entry->summary.run_max < csum->run_max)
249
                entry->summary.run_max = csum->run_max;
250
              entry->summary.sum_max += csum->sum_max;
251
            }
252
        }
253
      else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
254
        {
255
          counts_entry_t **slot, *entry, elt;
256
          unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
257
          unsigned ix;
258
 
259
          elt.ident = fn_ident;
260
          elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
261
 
262
          slot = (counts_entry_t **) htab_find_slot
263
            (counts_hash, &elt, INSERT);
264
          entry = *slot;
265
          if (!entry)
266
            {
267
              *slot = entry = XCNEW (counts_entry_t);
268
              entry->ident = elt.ident;
269
              entry->ctr = elt.ctr;
270
              entry->checksum = checksum;
271
              entry->summary.num = n_counts;
272
              entry->counts = XCNEWVEC (gcov_type, n_counts);
273
            }
274
          else if (entry->checksum != checksum)
275
            {
276
              error ("coverage mismatch for function %u while reading execution counters",
277
                     fn_ident);
278
              error ("checksum is %x instead of %x", entry->checksum, checksum);
279
              htab_delete (counts_hash);
280
              break;
281
            }
282
          else if (entry->summary.num != n_counts)
283
            {
284
              error ("coverage mismatch for function %u while reading execution counters",
285
                     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
 
297
          if (elt.ctr < GCOV_COUNTERS_SUMMABLE
298
              /* This should always be true for a just allocated entry,
299
                 and always false for an existing one. Check this way, in
300
                 case the gcov file is corrupt.  */
301
              && (!entry->chain || summaried != entry))
302
            {
303
              entry->chain = summaried;
304
              summaried = entry;
305
            }
306
          for (ix = 0; ix != n_counts; ix++)
307
            entry->counts[ix] += gcov_read_counter ();
308
        skip_merge:;
309
        }
310
      gcov_sync (offset, length);
311
      if ((is_error = gcov_is_error ()))
312
        {
313
          error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
314
                 da_file_name);
315
          htab_delete (counts_hash);
316
          break;
317
        }
318
    }
319
 
320
  gcov_close ();
321
}
322
 
323
/* Returns the counters for a particular tag.  */
324
 
325
gcov_type *
326
get_coverage_counts (unsigned counter, unsigned expected,
327
                     const struct gcov_ctr_summary **summary)
328
{
329
  counts_entry_t *entry, elt;
330
  gcov_unsigned_t checksum = -1;
331
 
332
  /* No hash table, no counts.  */
333
  if (!counts_hash)
334
    {
335
      static int warned = 0;
336
 
337
      if (!warned++)
338
        inform (input_location, (flag_guess_branch_prob
339
                 ? "file %s not found, execution counts estimated"
340
                 : "file %s not found, execution counts assumed to be zero"),
341
                da_file_name);
342
      return NULL;
343
    }
344
 
345
  elt.ident = current_function_funcdef_no + 1;
346
  elt.ctr = counter;
347
  entry = (counts_entry_t *) htab_find (counts_hash, &elt);
348
  if (!entry)
349
    {
350
      warning (0, "no coverage for function %qE found",
351
               DECL_ASSEMBLER_NAME (current_function_decl));
352
      return NULL;
353
    }
354
 
355
  checksum = compute_checksum ();
356
  if (entry->checksum != checksum
357
      || entry->summary.num != expected)
358
    {
359
      static int warned = 0;
360
      tree id = DECL_ASSEMBLER_NAME (current_function_decl);
361
 
362
      if (warn_coverage_mismatch)
363
        warning (OPT_Wcoverage_mismatch, "coverage mismatch for function "
364
                 "%qE while reading counter %qs", id, ctr_names[counter]);
365
      else
366
        error ("coverage mismatch for function %qE while reading counter %qs",
367
               id, ctr_names[counter]);
368
 
369
      if (!inhibit_warnings)
370
        {
371
          if (entry->checksum != checksum)
372
            inform (input_location, "checksum is %x instead of %x", entry->checksum, checksum);
373
          else
374
            inform (input_location, "number of counters is %d instead of %d",
375
                    entry->summary.num, expected);
376
        }
377
 
378
      if (warn_coverage_mismatch
379
          && !inhibit_warnings
380
          && !warned++)
381
        {
382
          inform (input_location, "coverage mismatch ignored due to -Wcoverage-mismatch");
383
          inform (input_location, flag_guess_branch_prob
384
                  ? "execution counts estimated"
385
                  : "execution counts assumed to be zero");
386
          if (!flag_guess_branch_prob)
387
            inform (input_location, "this can result in poorly optimized code");
388
        }
389
 
390
      return NULL;
391
    }
392
 
393
  if (summary)
394
    *summary = &entry->summary;
395
 
396
  return entry->counts;
397
}
398
 
399
/* Allocate NUM counters of type COUNTER. Returns nonzero if the
400
   allocation succeeded.  */
401
 
402
int
403
coverage_counter_alloc (unsigned counter, unsigned num)
404
{
405
  if (no_coverage)
406
    return 0;
407
 
408
  if (!num)
409
    return 1;
410
 
411
  if (!tree_ctr_tables[counter])
412
    {
413
      /* Generate and save a copy of this so it can be shared.  Leave
414
         the index type unspecified for now; it will be set after all
415
         functions have been compiled.  */
416
      char buf[20];
417
      tree gcov_type_node = get_gcov_type ();
418
      tree gcov_type_array_type
419
        = build_array_type (gcov_type_node, NULL_TREE);
420
      tree_ctr_tables[counter]
421
        = build_decl (BUILTINS_LOCATION,
422
                      VAR_DECL, NULL_TREE, gcov_type_array_type);
423
      TREE_STATIC (tree_ctr_tables[counter]) = 1;
424
      ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
425
      DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
426
      DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node);
427
 
428
      if (dump_file)
429
        fprintf (dump_file, "Using data file %s\n", da_file_name);
430
    }
431
  fn_b_ctrs[counter] = fn_n_ctrs[counter];
432
  fn_n_ctrs[counter] += num;
433
  fn_ctr_mask |= 1 << counter;
434
  return 1;
435
}
436
 
437
/* Generate a tree to access COUNTER NO.  */
438
 
439
tree
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
  no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
446
 
447
  /* "no" here is an array index, scaled to bytes later.  */
448
  return build4 (ARRAY_REF, gcov_type_node, tree_ctr_tables[counter],
449
                 build_int_cst (NULL_TREE, no), NULL, NULL);
450
}
451
 
452
/* Generate a tree to access the address of COUNTER NO.  */
453
 
454
tree
455
tree_coverage_counter_addr (unsigned counter, unsigned no)
456
{
457
  tree gcov_type_node = get_gcov_type ();
458
 
459
  gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
460
  no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
461
 
462
  TREE_ADDRESSABLE (tree_ctr_tables[counter]) = 1;
463
 
464
  /* "no" here is an array index, scaled to bytes later.  */
465
  return build_fold_addr_expr (build4 (ARRAY_REF, gcov_type_node,
466
                                       tree_ctr_tables[counter],
467
                                       build_int_cst (NULL_TREE, no),
468
                                       NULL, NULL));
469
}
470
 
471
/* Generate a checksum for a string.  CHKSUM is the current
472
   checksum.  */
473
 
474
static unsigned
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 (!strncmp (string + i, "_GLOBAL__N_", 11))
488
      offset = 11;
489
      if (!strncmp (string + i, "_GLOBAL__", 9))
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
  if (dup)
527
    free (dup);
528
 
529
  return chksum;
530
}
531
 
532
/* Compute checksum for the current function.  We generate a CRC32.  */
533
 
534
static unsigned
535
compute_checksum (void)
536
{
537
  expanded_location xloc
538
    = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
539
  unsigned chksum = xloc.line;
540
 
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
/* Begin output to the graph file for the current function.
549
   Opens the output file, if not already done. Writes the
550
   function header, if not already done. Returns nonzero if data
551
   should be output.  */
552
 
553
int
554
coverage_begin_output (void)
555
{
556
  /* We don't need to output .gcno file unless we're under -ftest-coverage
557
     (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
558
  if (no_coverage || !flag_test_coverage || flag_compare_debug)
559
    return 0;
560
 
561
  if (!bbg_function_announced)
562
    {
563
      expanded_location xloc
564
        = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
565
      unsigned long offset;
566
 
567
      if (!bbg_file_opened)
568
        {
569
          if (!gcov_open (bbg_file_name, -1))
570
            error ("cannot open %s", bbg_file_name);
571
          else
572
            {
573
              gcov_write_unsigned (GCOV_NOTE_MAGIC);
574
              gcov_write_unsigned (GCOV_VERSION);
575
              gcov_write_unsigned (local_tick);
576
            }
577
          bbg_file_opened = 1;
578
        }
579
 
580
      /* Announce function */
581
      offset = gcov_write_tag (GCOV_TAG_FUNCTION);
582
      gcov_write_unsigned (current_function_funcdef_no + 1);
583
      gcov_write_unsigned (compute_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
      bbg_function_announced = 1;
591
    }
592
  return !gcov_is_error ();
593
}
594
 
595
/* Finish coverage data for the current function. Verify no output
596
   error has occurred.  Save function coverage counts.  */
597
 
598
void
599
coverage_end_function (void)
600
{
601
  unsigned i;
602
 
603
  if (bbg_file_opened > 1 && gcov_is_error ())
604
    {
605
      warning (0, "error writing %qs", bbg_file_name);
606
      bbg_file_opened = -1;
607
    }
608
 
609
  if (fn_ctr_mask)
610
    {
611
      struct function_list *item;
612
 
613
      item = XNEW (struct function_list);
614
 
615
      *functions_tail = item;
616
      functions_tail = &item->next;
617
 
618
      item->next = 0;
619
      item->ident = current_function_funcdef_no + 1;
620
      item->checksum = compute_checksum ();
621
      for (i = 0; i != GCOV_COUNTERS; i++)
622
        {
623
          item->n_ctrs[i] = fn_n_ctrs[i];
624
          prg_n_ctrs[i] += fn_n_ctrs[i];
625
          fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
626
        }
627
      prg_ctr_mask |= fn_ctr_mask;
628
      fn_ctr_mask = 0;
629
    }
630
  bbg_function_announced = 0;
631
}
632
 
633
/* Creates the gcov_fn_info RECORD_TYPE.  */
634
 
635
static tree
636
build_fn_info_type (unsigned int counters)
637
{
638
  tree type = lang_hooks.types.make_type (RECORD_TYPE);
639
  tree field, fields;
640
  tree array_type;
641
 
642
  /* ident */
643
  fields = build_decl (BUILTINS_LOCATION,
644
                       FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
645
 
646
  /* checksum */
647
  field = build_decl (BUILTINS_LOCATION,
648
                      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
649
  TREE_CHAIN (field) = fields;
650
  fields = field;
651
 
652
  array_type = build_int_cst (NULL_TREE, counters - 1);
653
  array_type = build_index_type (array_type);
654
  array_type = build_array_type (get_gcov_unsigned_t (), array_type);
655
 
656
  /* counters */
657
  field = build_decl (BUILTINS_LOCATION,
658
                      FIELD_DECL, NULL_TREE, array_type);
659
  TREE_CHAIN (field) = fields;
660
  fields = field;
661
 
662
  finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
663
 
664
  return type;
665
}
666
 
667
/* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
668
   the function being processed and TYPE is the gcov_fn_info
669
   RECORD_TYPE.  */
670
 
671
static tree
672
build_fn_info_value (const struct function_list *function, tree type)
673
{
674
  tree value = NULL_TREE;
675
  tree fields = TYPE_FIELDS (type);
676
  unsigned ix;
677
  tree array_value = NULL_TREE;
678
 
679
  /* ident */
680
  value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
681
                                             function->ident), value);
682
  fields = TREE_CHAIN (fields);
683
 
684
  /* checksum */
685
  value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
686
                                             function->checksum), value);
687
  fields = TREE_CHAIN (fields);
688
 
689
  /* counters */
690
  for (ix = 0; ix != GCOV_COUNTERS; ix++)
691
    if (prg_ctr_mask & (1 << ix))
692
      {
693
        tree counters = build_int_cstu (get_gcov_unsigned_t (),
694
                                        function->n_ctrs[ix]);
695
 
696
        array_value = tree_cons (NULL_TREE, counters, array_value);
697
      }
698
 
699
  /* FIXME: use build_constructor directly.  */
700
  array_value = build_constructor_from_list (TREE_TYPE (fields),
701
                                             nreverse (array_value));
702
  value = tree_cons (fields, array_value, value);
703
 
704
  /* FIXME: use build_constructor directly.  */
705
  value = build_constructor_from_list (type, nreverse (value));
706
 
707
  return value;
708
}
709
 
710
/* Creates the gcov_ctr_info RECORD_TYPE.  */
711
 
712
static tree
713
build_ctr_info_type (void)
714
{
715
  tree type = lang_hooks.types.make_type (RECORD_TYPE);
716
  tree field, fields = NULL_TREE;
717
  tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
718
  tree gcov_merge_fn_type;
719
 
720
  /* counters */
721
  field = build_decl (BUILTINS_LOCATION,
722
                      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
723
  TREE_CHAIN (field) = fields;
724
  fields = field;
725
 
726
  /* values */
727
  field = build_decl (BUILTINS_LOCATION,
728
                      FIELD_DECL, NULL_TREE, gcov_ptr_type);
729
  TREE_CHAIN (field) = fields;
730
  fields = field;
731
 
732
  /* merge */
733
  gcov_merge_fn_type =
734
    build_function_type_list (void_type_node,
735
                              gcov_ptr_type, get_gcov_unsigned_t (),
736
                              NULL_TREE);
737
  field = build_decl (BUILTINS_LOCATION,
738
                      FIELD_DECL, NULL_TREE,
739
                      build_pointer_type (gcov_merge_fn_type));
740
  TREE_CHAIN (field) = fields;
741
  fields = field;
742
 
743
  finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
744
 
745
  return type;
746
}
747
 
748
/* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
749
   the counter being processed and TYPE is the gcov_ctr_info
750
   RECORD_TYPE.  */
751
 
752
static tree
753
build_ctr_info_value (unsigned int counter, tree type)
754
{
755
  tree value = NULL_TREE;
756
  tree fields = TYPE_FIELDS (type);
757
  tree fn;
758
 
759
  /* counters */
760
  value = tree_cons (fields,
761
                     build_int_cstu (get_gcov_unsigned_t (),
762
                                     prg_n_ctrs[counter]),
763
                     value);
764
  fields = TREE_CHAIN (fields);
765
 
766
  if (prg_n_ctrs[counter])
767
    {
768
      tree array_type;
769
 
770
      array_type = build_int_cstu (get_gcov_unsigned_t (),
771
                                   prg_n_ctrs[counter] - 1);
772
      array_type = build_index_type (array_type);
773
      array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
774
                                     array_type);
775
 
776
      TREE_TYPE (tree_ctr_tables[counter]) = array_type;
777
      DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
778
      DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
779
      varpool_finalize_decl (tree_ctr_tables[counter]);
780
 
781
      value = tree_cons (fields,
782
                         build1 (ADDR_EXPR, TREE_TYPE (fields),
783
                                            tree_ctr_tables[counter]),
784
                         value);
785
    }
786
  else
787
    value = tree_cons (fields, null_pointer_node, value);
788
  fields = TREE_CHAIN (fields);
789
 
790
  fn = build_decl (BUILTINS_LOCATION,
791
                   FUNCTION_DECL,
792
                   get_identifier (ctr_merge_functions[counter]),
793
                   TREE_TYPE (TREE_TYPE (fields)));
794
  DECL_EXTERNAL (fn) = 1;
795
  TREE_PUBLIC (fn) = 1;
796
  DECL_ARTIFICIAL (fn) = 1;
797
  TREE_NOTHROW (fn) = 1;
798
  DECL_ASSEMBLER_NAME (fn);  /* Initialize assembler name so we can stream out. */
799
  value = tree_cons (fields,
800
                     build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
801
                     value);
802
 
803
  /* FIXME: use build_constructor directly.  */
804
  value = build_constructor_from_list (type, nreverse (value));
805
 
806
  return value;
807
}
808
 
809
/* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
810
   CONSTRUCTOR.  */
811
 
812
static tree
813
build_gcov_info (void)
814
{
815
  unsigned n_ctr_types, ix;
816
  tree type, const_type;
817
  tree fn_info_type, fn_info_value = NULL_TREE;
818
  tree fn_info_ptr_type;
819
  tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
820
  tree field, fields = NULL_TREE;
821
  tree value = NULL_TREE;
822
  tree filename_string;
823
  int da_file_name_len;
824
  unsigned n_fns;
825
  const struct function_list *fn;
826
  tree string_type;
827
 
828
  /* Count the number of active counters.  */
829
  for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
830
    if (prg_ctr_mask & (1 << ix))
831
      n_ctr_types++;
832
 
833
  type = lang_hooks.types.make_type (RECORD_TYPE);
834
  const_type = build_qualified_type (type, TYPE_QUAL_CONST);
835
 
836
  /* Version ident */
837
  field = build_decl (BUILTINS_LOCATION,
838
                      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
839
  TREE_CHAIN (field) = fields;
840
  fields = field;
841
  value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
842
                     value);
843
 
844
  /* next -- NULL */
845
  field = build_decl (BUILTINS_LOCATION,
846
                      FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
847
  TREE_CHAIN (field) = fields;
848
  fields = field;
849
  value = tree_cons (field, null_pointer_node, value);
850
 
851
  /* stamp */
852
  field = build_decl (BUILTINS_LOCATION,
853
                      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
854
  TREE_CHAIN (field) = fields;
855
  fields = field;
856
  value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
857
                     value);
858
 
859
  /* Filename */
860
  string_type = build_pointer_type (build_qualified_type (char_type_node,
861
                                                    TYPE_QUAL_CONST));
862
  field = build_decl (BUILTINS_LOCATION,
863
                      FIELD_DECL, NULL_TREE, string_type);
864
  TREE_CHAIN (field) = fields;
865
  fields = field;
866
  da_file_name_len = strlen (da_file_name);
867
  filename_string = build_string (da_file_name_len + 1, da_file_name);
868
  TREE_TYPE (filename_string) = build_array_type
869
    (char_type_node, build_index_type
870
     (build_int_cst (NULL_TREE, da_file_name_len)));
871
  value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
872
                     value);
873
 
874
  /* Build the fn_info type and initializer.  */
875
  fn_info_type = build_fn_info_type (n_ctr_types);
876
  fn_info_ptr_type = build_pointer_type (build_qualified_type
877
                                         (fn_info_type, TYPE_QUAL_CONST));
878
  for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
879
    fn_info_value = tree_cons (NULL_TREE,
880
                               build_fn_info_value (fn, fn_info_type),
881
                               fn_info_value);
882
  if (n_fns)
883
    {
884
      tree array_type;
885
 
886
      array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
887
      array_type = build_array_type (fn_info_type, array_type);
888
 
889
      /* FIXME: use build_constructor directly.  */
890
      fn_info_value = build_constructor_from_list (array_type,
891
                                                   nreverse (fn_info_value));
892
      fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
893
    }
894
  else
895
    fn_info_value = null_pointer_node;
896
 
897
  /* number of functions */
898
  field = build_decl (BUILTINS_LOCATION,
899
                      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
900
  TREE_CHAIN (field) = fields;
901
  fields = field;
902
  value = tree_cons (field,
903
                     build_int_cstu (get_gcov_unsigned_t (), n_fns),
904
                     value);
905
 
906
  /* fn_info table */
907
  field = build_decl (BUILTINS_LOCATION,
908
                      FIELD_DECL, NULL_TREE, fn_info_ptr_type);
909
  TREE_CHAIN (field) = fields;
910
  fields = field;
911
  value = tree_cons (field, fn_info_value, value);
912
 
913
  /* counter_mask */
914
  field = build_decl (BUILTINS_LOCATION,
915
                      FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
916
  TREE_CHAIN (field) = fields;
917
  fields = field;
918
  value = tree_cons (field,
919
                     build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask),
920
                     value);
921
 
922
  /* counters */
923
  ctr_info_type = build_ctr_info_type ();
924
  ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
925
                                                       n_ctr_types));
926
  ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
927
  for (ix = 0; ix != GCOV_COUNTERS; ix++)
928
    if (prg_ctr_mask & (1 << ix))
929
      ctr_info_value = tree_cons (NULL_TREE,
930
                                  build_ctr_info_value (ix, ctr_info_type),
931
                                  ctr_info_value);
932
  /* FIXME: use build_constructor directly.  */
933
  ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
934
                                                nreverse (ctr_info_value));
935
 
936
  field = build_decl (BUILTINS_LOCATION,
937
                      FIELD_DECL, NULL_TREE, ctr_info_ary_type);
938
  TREE_CHAIN (field) = fields;
939
  fields = field;
940
  value = tree_cons (field, ctr_info_value, value);
941
 
942
  finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
943
 
944
  /* FIXME: use build_constructor directly.  */
945
  value = build_constructor_from_list (type, nreverse (value));
946
 
947
  return value;
948
}
949
 
950
/* Write out the structure which libgcov uses to locate all the
951
   counters.  The structures used here must match those defined in
952
   gcov-io.h.  Write out the constructor to call __gcov_init.  */
953
 
954
static void
955
create_coverage (void)
956
{
957
  tree gcov_info, gcov_init, body, t;
958
  char name_buf[32];
959
 
960
  no_coverage = 1; /* Disable any further coverage.  */
961
 
962
  if (!prg_ctr_mask)
963
    return;
964
 
965
  t = build_gcov_info ();
966
 
967
  gcov_info = build_decl (BUILTINS_LOCATION,
968
                          VAR_DECL, NULL_TREE, TREE_TYPE (t));
969
  TREE_STATIC (gcov_info) = 1;
970
  ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
971
  DECL_NAME (gcov_info) = get_identifier (name_buf);
972
  DECL_INITIAL (gcov_info) = t;
973
 
974
  /* Build structure.  */
975
  varpool_finalize_decl (gcov_info);
976
 
977
  /* Build a decl for __gcov_init.  */
978
  t = build_pointer_type (TREE_TYPE (gcov_info));
979
  t = build_function_type_list (void_type_node, t, NULL);
980
  t = build_decl (BUILTINS_LOCATION,
981
                  FUNCTION_DECL, get_identifier ("__gcov_init"), t);
982
  TREE_PUBLIC (t) = 1;
983
  DECL_EXTERNAL (t) = 1;
984
  DECL_ASSEMBLER_NAME (t);  /* Initialize assembler name so we can stream out. */
985
  gcov_init = t;
986
 
987
  /* Generate a call to __gcov_init(&gcov_info).  */
988
  body = NULL;
989
  t = build_fold_addr_expr (gcov_info);
990
  t = build_call_expr (gcov_init, 1, t);
991
  append_to_statement_list (t, &body);
992
 
993
  /* Generate a constructor to run it.  */
994
  cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
995
}
996
 
997
/* Perform file-level initialization. Read in data file, generate name
998
   of graph file.  */
999
 
1000
void
1001
coverage_init (const char *filename)
1002
{
1003
  int len = strlen (filename);
1004
  /* + 1 for extra '/', in case prefix doesn't end with /.  */
1005
  int prefix_len;
1006
 
1007
  if (profile_data_prefix == 0 && filename[0] != '/')
1008
    profile_data_prefix = getpwd ();
1009
 
1010
  prefix_len = (profile_data_prefix) ? strlen (profile_data_prefix) + 1 : 0;
1011
 
1012
  /* Name of da file.  */
1013
  da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
1014
                          + prefix_len + 1);
1015
 
1016
  if (profile_data_prefix)
1017
    {
1018
      strcpy (da_file_name, profile_data_prefix);
1019
      da_file_name[prefix_len - 1] = '/';
1020
      da_file_name[prefix_len] = 0;
1021
    }
1022
  else
1023
    da_file_name[0] = 0;
1024
  strcat (da_file_name, filename);
1025
  strcat (da_file_name, GCOV_DATA_SUFFIX);
1026
 
1027
  /* Name of bbg file.  */
1028
  bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
1029
  strcpy (bbg_file_name, filename);
1030
  strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
1031
 
1032
  if (flag_profile_use)
1033
    read_counts_file ();
1034
}
1035
 
1036
/* Performs file-level cleanup.  Close graph file, generate coverage
1037
   variables and constructor.  */
1038
 
1039
void
1040
coverage_finish (void)
1041
{
1042
  create_coverage ();
1043
  if (bbg_file_opened)
1044
    {
1045
      int error = gcov_close ();
1046
 
1047
      if (error)
1048
        unlink (bbg_file_name);
1049
      if (!local_tick)
1050
        /* Only remove the da file, if we cannot stamp it. If we can
1051
           stamp it, libgcov will DTRT.  */
1052
        unlink (da_file_name);
1053
    }
1054
}
1055
 
1056
#include "gt-coverage.h"

powered by: WebSVN 2.1.0

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