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

Subversion Repositories openrisc_me

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

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

Line No. Rev Author Line
1 38 julius
/* 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 Free Software Foundation, Inc.
4
   Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
5
   based on some ideas from Dain Samples of UC Berkeley.
6
   Further mangling by Bob Manson, Cygnus Support.
7
   Further mangled by Nathan Sidwell, CodeSourcery
8
 
9
This file is part of GCC.
10
 
11
GCC is free software; you can redistribute it and/or modify it under
12
the terms of the GNU General Public License as published by the Free
13
Software Foundation; either version 3, or (at your option) any later
14
version.
15
 
16
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17
WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19
for more details.
20
 
21
You should have received a copy of the GNU General Public License
22
along with GCC; see the file COPYING3.  If not see
23
<http://www.gnu.org/licenses/>.  */
24
 
25
 
26
#define GCOV_LINKAGE
27
 
28
#include "config.h"
29
#include "system.h"
30
#include "coretypes.h"
31
#include "tm.h"
32
#include "rtl.h"
33
#include "tree.h"
34
#include "flags.h"
35
#include "output.h"
36
#include "regs.h"
37
#include "expr.h"
38
#include "function.h"
39
#include "toplev.h"
40
#include "ggc.h"
41
#include "coverage.h"
42
#include "langhooks.h"
43
#include "hashtab.h"
44
#include "tree-iterator.h"
45
#include "cgraph.h"
46
 
47
#include "gcov-io.c"
48
 
49
struct function_list
50
{
51
  struct function_list *next;    /* next function */
52
  unsigned ident;                /* function ident */
53
  unsigned checksum;             /* function checksum */
54
  unsigned n_ctrs[GCOV_COUNTERS];/* number of counters.  */
55
};
56
 
57
/* Counts information for a function.  */
58
typedef struct counts_entry
59
{
60
  /* We hash by  */
61
  unsigned ident;
62
  unsigned ctr;
63
 
64
  /* Store  */
65
  unsigned checksum;
66
  gcov_type *counts;
67
  struct gcov_ctr_summary summary;
68
 
69
  /* Workspace */
70
  struct counts_entry *chain;
71
 
72
} counts_entry_t;
73
 
74
static struct function_list *functions_head = 0;
75
static struct function_list **functions_tail = &functions_head;
76
static unsigned no_coverage = 0;
77
 
78
/* Cumulative counter information for whole program.  */
79
static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
80
static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated.  */
81
 
82
/* Counter information for current function.  */
83
static unsigned fn_ctr_mask; /* Mask of counters used.  */
84
static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
85
static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
86
 
87
/* Name of the output file for coverage output file.  */
88
static char *bbg_file_name;
89
static unsigned bbg_file_opened;
90
static int bbg_function_announced;
91
 
92
/* Name of the count data file.  */
93
static char *da_file_name;
94
 
95
/* Hash table of count data.  */
96
static htab_t counts_hash = NULL;
97
 
98
/* Trees representing the counter table arrays.  */
99
static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
100
 
101
/* The names of the counter tables.  Not used if we're
102
   generating counters at tree level.  */
103
static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
104
 
105
/* The names of merge functions for counters.  */
106
static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
107
static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
108
 
109
/* Forward declarations.  */
110
static hashval_t htab_counts_entry_hash (const void *);
111
static int htab_counts_entry_eq (const void *, const void *);
112
static void htab_counts_entry_del (void *);
113
static void read_counts_file (void);
114
static unsigned compute_checksum (void);
115
static unsigned coverage_checksum_string (unsigned, const char *);
116
static tree build_fn_info_type (unsigned);
117
static tree build_fn_info_value (const struct function_list *, tree);
118
static tree build_ctr_info_type (void);
119
static tree build_ctr_info_value (unsigned, tree);
120
static tree build_gcov_info (void);
121
static void create_coverage (void);
122
 
123
/* Return the type node for gcov_type.  */
124
 
125
tree
126
get_gcov_type (void)
127
{
128
  return lang_hooks.types.type_for_size (GCOV_TYPE_SIZE, false);
129
}
130
 
131
/* Return the type node for gcov_unsigned_t.  */
132
 
133
static tree
134
get_gcov_unsigned_t (void)
135
{
136
  return lang_hooks.types.type_for_size (32, true);
137
}
138
 
139
static hashval_t
140
htab_counts_entry_hash (const void *of)
141
{
142
  const counts_entry_t *entry = of;
143
 
144
  return entry->ident * GCOV_COUNTERS + entry->ctr;
145
}
146
 
147
static int
148
htab_counts_entry_eq (const void *of1, const void *of2)
149
{
150
  const counts_entry_t *entry1 = of1;
151
  const counts_entry_t *entry2 = of2;
152
 
153
  return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
154
}
155
 
156
static void
157
htab_counts_entry_del (void *of)
158
{
159
  counts_entry_t *entry = of;
160
 
161
  free (entry->counts);
162
  free (entry);
163
}
164
 
165
/* Read in the counts file, if available.  */
166
 
167
static void
168
read_counts_file (void)
169
{
170
  gcov_unsigned_t fn_ident = 0;
171
  gcov_unsigned_t checksum = -1;
172
  counts_entry_t *summaried = NULL;
173
  unsigned seen_summary = 0;
174
  gcov_unsigned_t tag;
175
  int is_error = 0;
176
 
177
  if (!gcov_open (da_file_name, 1))
178
    return;
179
 
180
  if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
181
    {
182
      warning (0, "%qs is not a gcov data file", da_file_name);
183
      gcov_close ();
184
      return;
185
    }
186
  else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
187
    {
188
      char v[4], e[4];
189
 
190
      GCOV_UNSIGNED2STRING (v, tag);
191
      GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
192
 
193
      warning (0, "%qs is version %q.*s, expected version %q.*s",
194
               da_file_name, 4, v, 4, e);
195
      gcov_close ();
196
      return;
197
    }
198
 
199
  /* Read and discard the stamp.  */
200
  gcov_read_unsigned ();
201
 
202
  counts_hash = htab_create (10,
203
                             htab_counts_entry_hash, htab_counts_entry_eq,
204
                             htab_counts_entry_del);
205
  while ((tag = gcov_read_unsigned ()))
206
    {
207
      gcov_unsigned_t length;
208
      gcov_position_t offset;
209
 
210
      length = gcov_read_unsigned ();
211
      offset = gcov_position ();
212
      if (tag == GCOV_TAG_FUNCTION)
213
        {
214
          fn_ident = gcov_read_unsigned ();
215
          checksum = gcov_read_unsigned ();
216
          if (seen_summary)
217
            {
218
              /* We have already seen a summary, this means that this
219
                 new function begins a new set of program runs. We
220
                 must unlink the summaried chain.  */
221
              counts_entry_t *entry, *chain;
222
 
223
              for (entry = summaried; entry; entry = chain)
224
                {
225
                  chain = entry->chain;
226
                  entry->chain = NULL;
227
                }
228
              summaried = NULL;
229
              seen_summary = 0;
230
            }
231
        }
232
      else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
233
        {
234
          counts_entry_t *entry;
235
          struct gcov_summary summary;
236
 
237
          gcov_read_summary (&summary);
238
          seen_summary = 1;
239
          for (entry = summaried; entry; entry = entry->chain)
240
            {
241
              struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
242
 
243
              entry->summary.runs += csum->runs;
244
              entry->summary.sum_all += csum->sum_all;
245
              if (entry->summary.run_max < csum->run_max)
246
                entry->summary.run_max = csum->run_max;
247
              entry->summary.sum_max += csum->sum_max;
248
            }
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 = elt.ident;
266
              entry->ctr = elt.ctr;
267
              entry->checksum = checksum;
268
              entry->summary.num = n_counts;
269
              entry->counts = XCNEWVEC (gcov_type, n_counts);
270
            }
271
          else if (entry->checksum != checksum)
272
            {
273
              error ("coverage mismatch for function %u while reading execution counters",
274
                     fn_ident);
275
              error ("checksum is %x instead of %x", entry->checksum, checksum);
276
              htab_delete (counts_hash);
277
              break;
278
            }
279
          else if (entry->summary.num != n_counts)
280
            {
281
              error ("coverage mismatch for function %u while reading execution counters",
282
                     fn_ident);
283
              error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
284
              htab_delete (counts_hash);
285
              break;
286
            }
287
          else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
288
            {
289
              error ("cannot merge separate %s counters for function %u",
290
                     ctr_names[elt.ctr], fn_ident);
291
              goto skip_merge;
292
            }
293
 
294
          if (elt.ctr < GCOV_COUNTERS_SUMMABLE
295
              /* This should always be true for a just allocated entry,
296
                 and always false for an existing one. Check this way, in
297
                 case the gcov file is corrupt.  */
298
              && (!entry->chain || summaried != entry))
299
            {
300
              entry->chain = summaried;
301
              summaried = entry;
302
            }
303
          for (ix = 0; ix != n_counts; ix++)
304
            entry->counts[ix] += gcov_read_counter ();
305
        skip_merge:;
306
        }
307
      gcov_sync (offset, length);
308
      if ((is_error = gcov_is_error ()))
309
        {
310
          error (is_error < 0 ? "%qs has overflowed" : "%qs is corrupted",
311
                 da_file_name);
312
          htab_delete (counts_hash);
313
          break;
314
        }
315
    }
316
 
317
  gcov_close ();
318
}
319
 
320
/* Returns the counters for a particular tag.  */
321
 
322
gcov_type *
323
get_coverage_counts (unsigned counter, unsigned expected,
324
                     const struct gcov_ctr_summary **summary)
325
{
326
  counts_entry_t *entry, elt;
327
  gcov_unsigned_t checksum = -1;
328
 
329
  /* No hash table, no counts.  */
330
  if (!counts_hash)
331
    {
332
      static int warned = 0;
333
 
334
      if (!warned++)
335
        inform ((flag_guess_branch_prob
336
                 ? "file %s not found, execution counts estimated"
337
                 : "file %s not found, execution counts assumed to be zero"),
338
                da_file_name);
339
      return NULL;
340
    }
341
 
342
  elt.ident = current_function_funcdef_no + 1;
343
  elt.ctr = counter;
344
  entry = htab_find (counts_hash, &elt);
345
  if (!entry)
346
    {
347
      warning (0, "no coverage for function %qs found", IDENTIFIER_POINTER
348
               (DECL_ASSEMBLER_NAME (current_function_decl)));
349
      return 0;
350
    }
351
 
352
  checksum = compute_checksum ();
353
  if (entry->checksum != checksum)
354
    {
355
      error ("coverage mismatch for function %qs while reading counter %qs",
356
             IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
357
             ctr_names[counter]);
358
      error ("checksum is %x instead of %x", entry->checksum, checksum);
359
      return 0;
360
    }
361
  else if (entry->summary.num != expected)
362
    {
363
      error ("coverage mismatch for function %qs while reading counter %qs",
364
             IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
365
             ctr_names[counter]);
366
      error ("number of counters is %d instead of %d", entry->summary.num, expected);
367
      return 0;
368
    }
369
 
370
  if (summary)
371
    *summary = &entry->summary;
372
 
373
  return entry->counts;
374
}
375
 
376
/* Allocate NUM counters of type COUNTER. Returns nonzero if the
377
   allocation succeeded.  */
378
 
379
int
380
coverage_counter_alloc (unsigned counter, unsigned num)
381
{
382
  if (no_coverage)
383
    return 0;
384
 
385
  if (!num)
386
    return 1;
387
 
388
  if (!tree_ctr_tables[counter])
389
    {
390
      /* Generate and save a copy of this so it can be shared.  Leave
391
         the index type unspecified for now; it will be set after all
392
         functions have been compiled.  */
393
      char buf[20];
394
      tree gcov_type_node = get_gcov_type ();
395
      tree gcov_type_array_type
396
        = build_array_type (gcov_type_node, NULL_TREE);
397
      tree_ctr_tables[counter]
398
        = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
399
      TREE_STATIC (tree_ctr_tables[counter]) = 1;
400
      ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
401
      DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
402
      DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (gcov_type_node);
403
    }
404
  fn_b_ctrs[counter] = fn_n_ctrs[counter];
405
  fn_n_ctrs[counter] += num;
406
  fn_ctr_mask |= 1 << counter;
407
  return 1;
408
}
409
 
410
/* Generate a tree to access COUNTER NO.  */
411
 
412
tree
413
tree_coverage_counter_ref (unsigned counter, unsigned no)
414
{
415
  tree gcov_type_node = get_gcov_type ();
416
 
417
  gcc_assert (no < fn_n_ctrs[counter] - fn_b_ctrs[counter]);
418
  no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
419
 
420
  /* "no" here is an array index, scaled to bytes later.  */
421
  return build4 (ARRAY_REF, gcov_type_node, tree_ctr_tables[counter],
422
                 build_int_cst (NULL_TREE, no), NULL, NULL);
423
}
424
 
425
/* Generate a checksum for a string.  CHKSUM is the current
426
   checksum.  */
427
 
428
static unsigned
429
coverage_checksum_string (unsigned chksum, const char *string)
430
{
431
  int i;
432
  char *dup = NULL;
433
 
434
  /* Look for everything that looks if it were produced by
435
     get_file_function_name_long and zero out the second part
436
     that may result from flag_random_seed.  This is not critical
437
     as the checksums are used only for sanity checking.  */
438
  for (i = 0; string[i]; i++)
439
    {
440
      int offset = 0;
441
      if (!strncmp (string + i, "_GLOBAL__N_", 11))
442
      offset = 11;
443
      if (!strncmp (string + i, "_GLOBAL__", 9))
444
      offset = 9;
445
 
446
      /* C++ namespaces do have scheme:
447
         _GLOBAL__N_<filename>_<wrongmagicnumber>_<magicnumber>functionname
448
       since filename might contain extra underscores there seems
449
       to be no better chance then walk all possible offsets looking
450
       for magicnuber.  */
451
      if (offset)
452
        {
453
          for (i = i + offset; string[i]; i++)
454
            if (string[i]=='_')
455
              {
456
                int y;
457
 
458
                for (y = 1; y < 9; y++)
459
                  if (!(string[i + y] >= '0' && string[i + y] <= '9')
460
                      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
461
                    break;
462
                if (y != 9 || string[i + 9] != '_')
463
                  continue;
464
                for (y = 10; y < 18; y++)
465
                  if (!(string[i + y] >= '0' && string[i + y] <= '9')
466
                      && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
467
                    break;
468
                if (y != 18)
469
                  continue;
470
                if (!dup)
471
                  string = dup = xstrdup (string);
472
                for (y = 10; y < 18; y++)
473
                  dup[i + y] = '0';
474
              }
475
          break;
476
        }
477
    }
478
 
479
  chksum = crc32_string (chksum, string);
480
  if (dup)
481
    free (dup);
482
 
483
  return chksum;
484
}
485
 
486
/* Compute checksum for the current function.  We generate a CRC32.  */
487
 
488
static unsigned
489
compute_checksum (void)
490
{
491
  expanded_location xloc
492
    = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
493
  unsigned chksum = xloc.line;
494
 
495
  chksum = coverage_checksum_string (chksum, xloc.file);
496
  chksum = coverage_checksum_string
497
    (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
498
 
499
  return chksum;
500
}
501
 
502
/* Begin output to the graph file for the current function.
503
   Opens the output file, if not already done. Writes the
504
   function header, if not already done. Returns nonzero if data
505
   should be output.  */
506
 
507
int
508
coverage_begin_output (void)
509
{
510
  if (no_coverage)
511
    return 0;
512
 
513
  if (!bbg_function_announced)
514
    {
515
      expanded_location xloc
516
        = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
517
      unsigned long offset;
518
 
519
      if (!bbg_file_opened)
520
        {
521
          if (!gcov_open (bbg_file_name, -1))
522
            error ("cannot open %s", bbg_file_name);
523
          else
524
            {
525
              gcov_write_unsigned (GCOV_NOTE_MAGIC);
526
              gcov_write_unsigned (GCOV_VERSION);
527
              gcov_write_unsigned (local_tick);
528
            }
529
          bbg_file_opened = 1;
530
        }
531
 
532
      /* Announce function */
533
      offset = gcov_write_tag (GCOV_TAG_FUNCTION);
534
      gcov_write_unsigned (current_function_funcdef_no + 1);
535
      gcov_write_unsigned (compute_checksum ());
536
      gcov_write_string (IDENTIFIER_POINTER
537
                         (DECL_ASSEMBLER_NAME (current_function_decl)));
538
      gcov_write_string (xloc.file);
539
      gcov_write_unsigned (xloc.line);
540
      gcov_write_length (offset);
541
 
542
      bbg_function_announced = 1;
543
    }
544
  return !gcov_is_error ();
545
}
546
 
547
/* Finish coverage data for the current function. Verify no output
548
   error has occurred.  Save function coverage counts.  */
549
 
550
void
551
coverage_end_function (void)
552
{
553
  unsigned i;
554
 
555
  if (bbg_file_opened > 1 && gcov_is_error ())
556
    {
557
      warning (0, "error writing %qs", bbg_file_name);
558
      bbg_file_opened = -1;
559
    }
560
 
561
  if (fn_ctr_mask)
562
    {
563
      struct function_list *item;
564
 
565
      item = XNEW (struct function_list);
566
 
567
      *functions_tail = item;
568
      functions_tail = &item->next;
569
 
570
      item->next = 0;
571
      item->ident = current_function_funcdef_no + 1;
572
      item->checksum = compute_checksum ();
573
      for (i = 0; i != GCOV_COUNTERS; i++)
574
        {
575
          item->n_ctrs[i] = fn_n_ctrs[i];
576
          prg_n_ctrs[i] += fn_n_ctrs[i];
577
          fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
578
        }
579
      prg_ctr_mask |= fn_ctr_mask;
580
      fn_ctr_mask = 0;
581
    }
582
  bbg_function_announced = 0;
583
}
584
 
585
/* Creates the gcov_fn_info RECORD_TYPE.  */
586
 
587
static tree
588
build_fn_info_type (unsigned int counters)
589
{
590
  tree type = lang_hooks.types.make_type (RECORD_TYPE);
591
  tree field, fields;
592
  tree array_type;
593
 
594
  /* ident */
595
  fields = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
596
 
597
  /* checksum */
598
  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
599
  TREE_CHAIN (field) = fields;
600
  fields = field;
601
 
602
  array_type = build_int_cst (NULL_TREE, counters - 1);
603
  array_type = build_index_type (array_type);
604
  array_type = build_array_type (get_gcov_unsigned_t (), array_type);
605
 
606
  /* counters */
607
  field = build_decl (FIELD_DECL, NULL_TREE, array_type);
608
  TREE_CHAIN (field) = fields;
609
  fields = field;
610
 
611
  finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
612
 
613
  return type;
614
}
615
 
616
/* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
617
   the function being processed and TYPE is the gcov_fn_info
618
   RECORD_TYPE.  */
619
 
620
static tree
621
build_fn_info_value (const struct function_list *function, tree type)
622
{
623
  tree value = NULL_TREE;
624
  tree fields = TYPE_FIELDS (type);
625
  unsigned ix;
626
  tree array_value = NULL_TREE;
627
 
628
  /* ident */
629
  value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
630
                                             function->ident), value);
631
  fields = TREE_CHAIN (fields);
632
 
633
  /* checksum */
634
  value = tree_cons (fields, build_int_cstu (get_gcov_unsigned_t (),
635
                                             function->checksum), value);
636
  fields = TREE_CHAIN (fields);
637
 
638
  /* counters */
639
  for (ix = 0; ix != GCOV_COUNTERS; ix++)
640
    if (prg_ctr_mask & (1 << ix))
641
      {
642
        tree counters = build_int_cstu (get_gcov_unsigned_t (),
643
                                        function->n_ctrs[ix]);
644
 
645
        array_value = tree_cons (NULL_TREE, counters, array_value);
646
      }
647
 
648
  /* FIXME: use build_constructor directly.  */
649
  array_value = build_constructor_from_list (TREE_TYPE (fields),
650
                                             nreverse (array_value));
651
  value = tree_cons (fields, array_value, value);
652
 
653
  /* FIXME: use build_constructor directly.  */
654
  value = build_constructor_from_list (type, nreverse (value));
655
 
656
  return value;
657
}
658
 
659
/* Creates the gcov_ctr_info RECORD_TYPE.  */
660
 
661
static tree
662
build_ctr_info_type (void)
663
{
664
  tree type = lang_hooks.types.make_type (RECORD_TYPE);
665
  tree field, fields = NULL_TREE;
666
  tree gcov_ptr_type = build_pointer_type (get_gcov_type ());
667
  tree gcov_merge_fn_type;
668
 
669
  /* counters */
670
  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
671
  TREE_CHAIN (field) = fields;
672
  fields = field;
673
 
674
  /* values */
675
  field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
676
  TREE_CHAIN (field) = fields;
677
  fields = field;
678
 
679
  /* merge */
680
  gcov_merge_fn_type =
681
    build_function_type_list (void_type_node,
682
                              gcov_ptr_type, get_gcov_unsigned_t (),
683
                              NULL_TREE);
684
  field = build_decl (FIELD_DECL, NULL_TREE,
685
                      build_pointer_type (gcov_merge_fn_type));
686
  TREE_CHAIN (field) = fields;
687
  fields = field;
688
 
689
  finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
690
 
691
  return type;
692
}
693
 
694
/* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
695
   the counter being processed and TYPE is the gcov_ctr_info
696
   RECORD_TYPE.  */
697
 
698
static tree
699
build_ctr_info_value (unsigned int counter, tree type)
700
{
701
  tree value = NULL_TREE;
702
  tree fields = TYPE_FIELDS (type);
703
  tree fn;
704
 
705
  /* counters */
706
  value = tree_cons (fields,
707
                     build_int_cstu (get_gcov_unsigned_t (),
708
                                     prg_n_ctrs[counter]),
709
                     value);
710
  fields = TREE_CHAIN (fields);
711
 
712
  if (prg_n_ctrs[counter])
713
    {
714
      tree array_type;
715
 
716
      array_type = build_int_cstu (get_gcov_unsigned_t (),
717
                                   prg_n_ctrs[counter] - 1);
718
      array_type = build_index_type (array_type);
719
      array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
720
                                     array_type);
721
 
722
      TREE_TYPE (tree_ctr_tables[counter]) = array_type;
723
      DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
724
      DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
725
      assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
726
 
727
      value = tree_cons (fields,
728
                         build1 (ADDR_EXPR, TREE_TYPE (fields),
729
                                            tree_ctr_tables[counter]),
730
                         value);
731
    }
732
  else
733
    value = tree_cons (fields, null_pointer_node, value);
734
  fields = TREE_CHAIN (fields);
735
 
736
  fn = build_decl (FUNCTION_DECL,
737
                   get_identifier (ctr_merge_functions[counter]),
738
                   TREE_TYPE (TREE_TYPE (fields)));
739
  DECL_EXTERNAL (fn) = 1;
740
  TREE_PUBLIC (fn) = 1;
741
  DECL_ARTIFICIAL (fn) = 1;
742
  TREE_NOTHROW (fn) = 1;
743
  value = tree_cons (fields,
744
                     build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
745
                     value);
746
 
747
  /* FIXME: use build_constructor directly.  */
748
  value = build_constructor_from_list (type, nreverse (value));
749
 
750
  return value;
751
}
752
 
753
/* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
754
   CONSTRUCTOR.  */
755
 
756
static tree
757
build_gcov_info (void)
758
{
759
  unsigned n_ctr_types, ix;
760
  tree type, const_type;
761
  tree fn_info_type, fn_info_value = NULL_TREE;
762
  tree fn_info_ptr_type;
763
  tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
764
  tree field, fields = NULL_TREE;
765
  tree value = NULL_TREE;
766
  tree filename_string;
767
  char *filename;
768
  int filename_len;
769
  unsigned n_fns;
770
  const struct function_list *fn;
771
  tree string_type;
772
 
773
  /* Count the number of active counters.  */
774
  for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
775
    if (prg_ctr_mask & (1 << ix))
776
      n_ctr_types++;
777
 
778
  type = lang_hooks.types.make_type (RECORD_TYPE);
779
  const_type = build_qualified_type (type, TYPE_QUAL_CONST);
780
 
781
  /* Version ident */
782
  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
783
  TREE_CHAIN (field) = fields;
784
  fields = field;
785
  value = tree_cons (field, build_int_cstu (TREE_TYPE (field), GCOV_VERSION),
786
                     value);
787
 
788
  /* next -- NULL */
789
  field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
790
  TREE_CHAIN (field) = fields;
791
  fields = field;
792
  value = tree_cons (field, null_pointer_node, value);
793
 
794
  /* stamp */
795
  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
796
  TREE_CHAIN (field) = fields;
797
  fields = field;
798
  value = tree_cons (field, build_int_cstu (TREE_TYPE (field), local_tick),
799
                     value);
800
 
801
  /* Filename */
802
  string_type = build_pointer_type (build_qualified_type (char_type_node,
803
                                                    TYPE_QUAL_CONST));
804
  field = build_decl (FIELD_DECL, NULL_TREE, string_type);
805
  TREE_CHAIN (field) = fields;
806
  fields = field;
807
  filename = getpwd ();
808
  filename = (filename && da_file_name[0] != '/'
809
              ? concat (filename, "/", da_file_name, NULL)
810
              : da_file_name);
811
  filename_len = strlen (filename);
812
  filename_string = build_string (filename_len + 1, filename);
813
  if (filename != da_file_name)
814
    free (filename);
815
  TREE_TYPE (filename_string) = build_array_type
816
    (char_type_node, build_index_type
817
     (build_int_cst (NULL_TREE, filename_len)));
818
  value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
819
                     value);
820
 
821
  /* Build the fn_info type and initializer.  */
822
  fn_info_type = build_fn_info_type (n_ctr_types);
823
  fn_info_ptr_type = build_pointer_type (build_qualified_type
824
                                         (fn_info_type, TYPE_QUAL_CONST));
825
  for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
826
    fn_info_value = tree_cons (NULL_TREE,
827
                               build_fn_info_value (fn, fn_info_type),
828
                               fn_info_value);
829
  if (n_fns)
830
    {
831
      tree array_type;
832
 
833
      array_type = build_index_type (build_int_cst (NULL_TREE, n_fns - 1));
834
      array_type = build_array_type (fn_info_type, array_type);
835
 
836
      /* FIXME: use build_constructor directly.  */
837
      fn_info_value = build_constructor_from_list (array_type,
838
                                                   nreverse (fn_info_value));
839
      fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
840
    }
841
  else
842
    fn_info_value = null_pointer_node;
843
 
844
  /* number of functions */
845
  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
846
  TREE_CHAIN (field) = fields;
847
  fields = field;
848
  value = tree_cons (field,
849
                     build_int_cstu (get_gcov_unsigned_t (), n_fns),
850
                     value);
851
 
852
  /* fn_info table */
853
  field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
854
  TREE_CHAIN (field) = fields;
855
  fields = field;
856
  value = tree_cons (field, fn_info_value, value);
857
 
858
  /* counter_mask */
859
  field = build_decl (FIELD_DECL, NULL_TREE, get_gcov_unsigned_t ());
860
  TREE_CHAIN (field) = fields;
861
  fields = field;
862
  value = tree_cons (field,
863
                     build_int_cstu (get_gcov_unsigned_t (), prg_ctr_mask),
864
                     value);
865
 
866
  /* counters */
867
  ctr_info_type = build_ctr_info_type ();
868
  ctr_info_ary_type = build_index_type (build_int_cst (NULL_TREE,
869
                                                       n_ctr_types));
870
  ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
871
  for (ix = 0; ix != GCOV_COUNTERS; ix++)
872
    if (prg_ctr_mask & (1 << ix))
873
      ctr_info_value = tree_cons (NULL_TREE,
874
                                  build_ctr_info_value (ix, ctr_info_type),
875
                                  ctr_info_value);
876
  /* FIXME: use build_constructor directly.  */
877
  ctr_info_value = build_constructor_from_list (ctr_info_ary_type,
878
                                                nreverse (ctr_info_value));
879
 
880
  field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
881
  TREE_CHAIN (field) = fields;
882
  fields = field;
883
  value = tree_cons (field, ctr_info_value, value);
884
 
885
  finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
886
 
887
  /* FIXME: use build_constructor directly.  */
888
  value = build_constructor_from_list (type, nreverse (value));
889
 
890
  return value;
891
}
892
 
893
/* Write out the structure which libgcov uses to locate all the
894
   counters.  The structures used here must match those defined in
895
   gcov-io.h.  Write out the constructor to call __gcov_init.  */
896
 
897
static void
898
create_coverage (void)
899
{
900
  tree gcov_info, gcov_init, body, t;
901
  char name_buf[32];
902
 
903
  no_coverage = 1; /* Disable any further coverage.  */
904
 
905
  if (!prg_ctr_mask)
906
    return;
907
 
908
  t = build_gcov_info ();
909
 
910
  gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (t));
911
  TREE_STATIC (gcov_info) = 1;
912
  ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
913
  DECL_NAME (gcov_info) = get_identifier (name_buf);
914
  DECL_INITIAL (gcov_info) = t;
915
 
916
  /* Build structure.  */
917
  assemble_variable (gcov_info, 0, 0, 0);
918
 
919
  /* Build a decl for __gcov_init.  */
920
  t = build_pointer_type (TREE_TYPE (gcov_info));
921
  t = build_function_type_list (void_type_node, t, NULL);
922
  t = build_decl (FUNCTION_DECL, get_identifier ("__gcov_init"), t);
923
  TREE_PUBLIC (t) = 1;
924
  DECL_EXTERNAL (t) = 1;
925
  gcov_init = t;
926
 
927
  /* Generate a call to __gcov_init(&gcov_info).  */
928
  body = NULL;
929
  t = build_fold_addr_expr (gcov_info);
930
  t = tree_cons (NULL, t, NULL);
931
  t = build_function_call_expr (gcov_init, t);
932
  append_to_statement_list (t, &body);
933
 
934
  /* Generate a constructor to run it.  */
935
  cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
936
}
937
 
938
/* Perform file-level initialization. Read in data file, generate name
939
   of graph file.  */
940
 
941
void
942
coverage_init (const char *filename)
943
{
944
  int len = strlen (filename);
945
 
946
  /* Name of da file.  */
947
  da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) + 1);
948
  strcpy (da_file_name, filename);
949
  strcat (da_file_name, GCOV_DATA_SUFFIX);
950
 
951
  /* Name of bbg file.  */
952
  bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
953
  strcpy (bbg_file_name, filename);
954
  strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
955
 
956
  read_counts_file ();
957
}
958
 
959
/* Performs file-level cleanup.  Close graph file, generate coverage
960
   variables and constructor.  */
961
 
962
void
963
coverage_finish (void)
964
{
965
  create_coverage ();
966
  if (bbg_file_opened)
967
    {
968
      int error = gcov_close ();
969
 
970
      if (error)
971
        unlink (bbg_file_name);
972
      if (!local_tick)
973
        /* Only remove the da file, if we cannot stamp it. If we can
974
           stamp it, libgcov will DTRT.  */
975
        unlink (da_file_name);
976
    }
977
}
978
 
979
#include "gt-coverage.h"

powered by: WebSVN 2.1.0

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