OSDN Git Service

Formatting fixes.
[pf3gnuchains/gcc-fork.git] / gcc / coverage.c
1 /* 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 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 2, 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 COPYING.  If not, write to the Free
23 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 02111-1307, USA.  */
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 "ggc.h"
42 #include "target.h"
43 #include "coverage.h"
44 #include "libfuncs.h"
45 #include "langhooks.h"
46 #include "hashtab.h"
47
48 #include "gcov-io.c"
49
50 struct function_list
51 {
52   struct function_list *next;    /* next function */
53   unsigned ident;                /* function ident */
54   unsigned checksum;             /* function checksum */
55   unsigned n_ctrs[GCOV_COUNTERS];/* number of counters.  */
56 };
57
58 /* Counts information for a function.  */
59 typedef struct counts_entry
60 {
61   /* We hash by  */
62   unsigned ident;
63   unsigned ctr;
64
65   /* Store  */
66   unsigned checksum;
67   gcov_type *counts;
68   struct gcov_ctr_summary summary;
69
70   /* Workspace */
71   struct counts_entry *chain;
72
73 } counts_entry_t;
74
75 static struct function_list *functions_head = 0;
76 static struct function_list **functions_tail = &functions_head;
77 static unsigned no_coverage = 0;
78
79 /* Cumulative counter information for whole program.  */
80 static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
81 static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated.  */
82
83 /* Counter information for current function.  */
84 static unsigned fn_ctr_mask; /* Mask of counters used.  */
85 static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated.  */
86 static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base.  */
87
88 /* Name of the output file for coverage output file.  */
89 static char *bbg_file_name;
90 static unsigned bbg_file_opened;
91 static int bbg_function_announced;
92
93 /* Name of the count data file.  */
94 static char *da_file_name;
95
96 /* Hash table of count data.  */
97 static htab_t counts_hash = NULL;
98
99 /* Trees representing the counter table arrays.  */
100 static GTY(()) tree tree_ctr_tables[GCOV_COUNTERS];
101
102 /* The names of the counter tables.  Not used if we're
103    generating counters at tree level.  */
104 static GTY(()) rtx ctr_labels[GCOV_COUNTERS];
105
106 /* The names of merge functions for counters.  */
107 static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIONS;
108 static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES;
109
110 /* Forward declarations.  */
111 static hashval_t htab_counts_entry_hash (const void *);
112 static int htab_counts_entry_eq (const void *, const void *);
113 static void htab_counts_entry_del (void *);
114 static void read_counts_file (void);
115 static unsigned compute_checksum (void);
116 static unsigned coverage_checksum_string (unsigned, const char *);
117 static tree build_fn_info_type (unsigned);
118 static tree build_fn_info_value (const struct function_list *, tree);
119 static tree build_ctr_info_type (void);
120 static tree build_ctr_info_value (unsigned, tree);
121 static tree build_gcov_info (void);
122 static void create_coverage (void);
123
124 \f
125 static hashval_t
126 htab_counts_entry_hash (const void *of)
127 {
128   const counts_entry_t *entry = of;
129
130   return entry->ident * GCOV_COUNTERS + entry->ctr;
131 }
132
133 static int
134 htab_counts_entry_eq (const void *of1, const void *of2)
135 {
136   const counts_entry_t *entry1 = of1;
137   const counts_entry_t *entry2 = of2;
138
139   return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
140 }
141
142 static void
143 htab_counts_entry_del (void *of)
144 {
145   counts_entry_t *entry = of;
146
147   free (entry->counts);
148   free (entry);
149 }
150
151 /* Read in the counts file, if available.  */
152
153 static void
154 read_counts_file (void)
155 {
156   gcov_unsigned_t fn_ident = 0;
157   gcov_unsigned_t checksum = -1;
158   counts_entry_t *summaried = NULL;
159   unsigned seen_summary = 0;
160   gcov_unsigned_t tag;
161   int is_error = 0;
162
163   if (!gcov_open (da_file_name, 1))
164     return;
165
166   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
167     {
168       warning ("`%s' is not a gcov data file", da_file_name);
169       gcov_close ();
170       return;
171     }
172   else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
173     {
174       char v[4], e[4];
175
176       GCOV_UNSIGNED2STRING (v, tag);
177       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
178
179       warning ("`%s' is version `%.*s', expected version `%.*s'",
180                da_file_name, 4, v, 4, e);
181       gcov_close ();
182       return;
183     }
184
185   /* Read and discard the stamp.  */
186   gcov_read_unsigned ();
187   
188   counts_hash = htab_create (10,
189                              htab_counts_entry_hash, htab_counts_entry_eq,
190                              htab_counts_entry_del);
191   while ((tag = gcov_read_unsigned ()))
192     {
193       gcov_unsigned_t length;
194       gcov_position_t offset;
195
196       length = gcov_read_unsigned ();
197       offset = gcov_position ();
198       if (tag == GCOV_TAG_FUNCTION)
199         {
200           fn_ident = gcov_read_unsigned ();
201           checksum = gcov_read_unsigned ();
202           if (seen_summary)
203             {
204               /* We have already seen a summary, this means that this
205                  new function begins a new set of program runs. We
206                  must unlink the summaried chain.  */
207               counts_entry_t *entry, *chain;
208
209               for (entry = summaried; entry; entry = chain)
210                 {
211                   chain = entry->chain;
212                   entry->chain = NULL;
213                 }
214               summaried = NULL;
215               seen_summary = 0;
216             }
217         }
218       else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
219         {
220           counts_entry_t *entry;
221           struct gcov_summary summary;
222
223           gcov_read_summary (&summary);
224           seen_summary = 1;
225           for (entry = summaried; entry; entry = entry->chain)
226             {
227               struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr];
228
229               entry->summary.runs += csum->runs;
230               entry->summary.sum_all += csum->sum_all;
231               if (entry->summary.run_max < csum->run_max)
232                 entry->summary.run_max = csum->run_max;
233               entry->summary.sum_max += csum->sum_max;
234             }
235         }
236       else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
237         {
238           counts_entry_t **slot, *entry, elt;
239           unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
240           unsigned ix;
241
242           elt.ident = fn_ident;
243           elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
244
245           slot = (counts_entry_t **) htab_find_slot
246             (counts_hash, &elt, INSERT);
247           entry = *slot;
248           if (!entry)
249             {
250               *slot = entry = xcalloc (1, sizeof (counts_entry_t));
251               entry->ident = elt.ident;
252               entry->ctr = elt.ctr;
253               entry->checksum = checksum;
254               entry->summary.num = n_counts;
255               entry->counts = xcalloc (n_counts, sizeof (gcov_type));
256             }
257           else if (entry->checksum != checksum)
258             {
259               error ("coverage mismatch for function %u while reading execution counters.",
260                      fn_ident);
261               error ("checksum is %x instead of %x", entry->checksum, checksum);
262               htab_delete (counts_hash);
263               break;
264             }
265           else if (entry->summary.num != n_counts)
266             {
267               error ("coverage mismatch for function %u while reading execution counters.",
268                      fn_ident);
269               error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
270               htab_delete (counts_hash);
271               break;
272             }
273           else if (elt.ctr >= GCOV_COUNTERS_SUMMABLE)
274             {
275               error ("cannot merge separate %s counters for function %u",
276                      ctr_names[elt.ctr], fn_ident);
277               goto skip_merge;
278             }
279
280           if (elt.ctr < GCOV_COUNTERS_SUMMABLE
281               /* This should always be true for a just allocated entry,
282                  and always false for an existing one. Check this way, in
283                  case the gcov file is corrupt.  */
284               && (!entry->chain || summaried != entry))
285             {
286               entry->chain = summaried;
287               summaried = entry;
288             }
289           for (ix = 0; ix != n_counts; ix++)
290             entry->counts[ix] += gcov_read_counter ();
291         skip_merge:;
292         }
293       gcov_sync (offset, length);
294       if ((is_error = gcov_is_error ()))
295         break;
296     }
297
298   if (!gcov_is_eof ())
299     {
300       error (is_error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
301              da_file_name);
302       htab_delete (counts_hash);
303     }
304
305   gcov_close ();
306 }
307
308 /* Returns the counters for a particular tag.  */
309
310 gcov_type *
311 get_coverage_counts (unsigned counter, unsigned expected,
312                      const struct gcov_ctr_summary **summary)
313 {
314   counts_entry_t *entry, elt;
315   gcov_unsigned_t checksum = -1;
316
317   /* No hash table, no counts.  */
318   if (!counts_hash)
319     {
320       static int warned = 0;
321
322       if (!warned++)
323         inform ((flag_guess_branch_prob
324                  ? "file %s not found, execution counts estimated"
325                  : "file %s not found, execution counts assumed to be zero"),
326                 da_file_name);
327       return NULL;
328     }
329
330   elt.ident = current_function_funcdef_no + 1;
331   elt.ctr = counter;
332   entry = htab_find (counts_hash, &elt);
333   if (!entry)
334     {
335       warning ("no coverage for function '%s' found.", IDENTIFIER_POINTER
336                (DECL_ASSEMBLER_NAME (current_function_decl)));
337       return 0;
338     }
339
340   checksum = compute_checksum ();
341   if (entry->checksum != checksum)
342     {
343       error ("coverage mismatch for function '%s' while reading counter '%s'.",
344              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
345              ctr_names[counter]);
346       error ("checksum is %x instead of %x", entry->checksum, checksum);
347       return 0;
348     }
349   else if (entry->summary.num != expected)
350     {
351       error ("coverage mismatch for function '%s' while reading counter '%s'.",
352              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),
353              ctr_names[counter]);
354       error ("number of counters is %d instead of %d", entry->summary.num, expected);
355       return 0;
356     }
357
358   if (summary)
359     *summary = &entry->summary;
360
361   return entry->counts;
362 }
363
364 /* Allocate NUM counters of type COUNTER. Returns nonzero if the
365    allocation succeeded.  */
366
367 int
368 coverage_counter_alloc (unsigned counter, unsigned num)
369 {
370   if (no_coverage)
371     return 0;
372
373   if (!num)
374     return 1;
375
376   if (!tree_ctr_tables[counter])
377     {
378       /* Generate and save a copy of this so it can be shared.  */
379       /* We don't know the size yet; make it big enough that nobody
380          will make any clever transformation on it.  */
381       char buf[20];
382       tree domain_tree
383         = build_index_type (build_int_2 (1000, 0)); /* replaced later */
384       tree gcov_type_array_type
385         = build_array_type (GCOV_TYPE_NODE, domain_tree);
386       tree_ctr_tables[counter]
387         = build_decl (VAR_DECL, NULL_TREE, gcov_type_array_type);
388       TREE_STATIC (tree_ctr_tables[counter]) = 1;
389       ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1);
390       DECL_NAME (tree_ctr_tables[counter]) = get_identifier (buf);
391       DECL_ALIGN (tree_ctr_tables[counter]) = TYPE_ALIGN (GCOV_TYPE_NODE);
392     }
393   fn_b_ctrs[counter] = fn_n_ctrs[counter];
394   fn_n_ctrs[counter] += num;
395   fn_ctr_mask |= 1 << counter;
396   return 1;
397 }
398
399 /* Generate a MEM rtl to access COUNTER NO.  */
400
401 rtx
402 rtl_coverage_counter_ref (unsigned counter, unsigned no)
403 {
404   unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
405   enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
406   rtx ref;
407
408   if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
409     abort ();
410   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
411   if (!ctr_labels[counter])
412       {
413         ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode,
414                                ggc_strdup (IDENTIFIER_POINTER (DECL_NAME
415                                (tree_ctr_tables[counter]))));
416         SYMBOL_REF_FLAGS (ctr_labels[counter]) = SYMBOL_FLAG_LOCAL;
417       }
418   ref = plus_constant (ctr_labels[counter], gcov_size / BITS_PER_UNIT * no);
419   ref = gen_rtx_MEM (mode, ref);
420   set_mem_alias_set (ref, new_alias_set ());
421   MEM_NOTRAP_P (ref) = 1;
422
423   return ref;
424 }
425
426 /* Generate a tree to access COUNTER NO.  */
427
428 tree
429 tree_coverage_counter_ref (unsigned counter, unsigned no)
430 {
431   tree domain_type = TYPE_DOMAIN (TREE_TYPE (tree_ctr_tables[counter]));
432
433   if (no >= fn_n_ctrs[counter] - fn_b_ctrs[counter])
434     abort ();
435   no += prg_n_ctrs[counter] + fn_b_ctrs[counter];
436
437   /* "no" here is an array index, scaled to bytes later.  */
438   return build (ARRAY_REF, GCOV_TYPE_NODE, tree_ctr_tables[counter],
439                 fold_convert (domain_type, build_int_2 (no, 0)),
440                 TYPE_MIN_VALUE (domain_type),
441                 size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (GCOV_TYPE_NODE),
442                             size_int (TYPE_ALIGN (GCOV_TYPE_NODE))));
443 }
444 \f
445 /* Generate a checksum for a string.  CHKSUM is the current
446    checksum.  */
447
448 static unsigned
449 coverage_checksum_string (unsigned chksum, const char *string)
450 {
451   int i;
452   char *dup = NULL;
453
454   /* Look for everything that looks if it were produced by
455      get_file_function_name_long and zero out the second part
456      that may result from flag_random_seed.  This is not critical
457      as the checksums are used only for sanity checking.  */
458   for (i = 0; string[i]; i++)
459     {
460       if (!strncmp (string + i, "_GLOBAL__", 9))
461         for (i = i + 9; string[i]; i++)
462           if (string[i]=='_')
463             {
464               int y;
465               unsigned seed;
466
467               for (y = 1; y < 9; y++)
468                 if (!(string[i + y] >= '0' && string[i + y] <= '9')
469                     && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
470                   break;
471               if (y != 9 || string[i + 9] != '_')
472                 continue;
473               for (y = 10; y < 18; y++)
474                 if (!(string[i + y] >= '0' && string[i + y] <= '9')
475                     && !(string[i + y] >= 'A' && string[i + y] <= 'F'))
476                   break;
477               if (y != 18)
478                 continue;
479               if (!sscanf (string + i + 10, "%X", &seed))
480                 abort ();
481               if (seed != crc32_string (0, flag_random_seed))
482                 continue;
483               string = dup = xstrdup (string);
484               for (y = 10; y < 18; y++)
485                 dup[i + y] = '0';
486               break;
487             }
488       break;
489     }
490
491   chksum = crc32_string (chksum, string);
492   if (dup)
493     free (dup);
494
495   return chksum;
496 }
497
498 /* Compute checksum for the current function.  We generate a CRC32.  */
499
500 static unsigned
501 compute_checksum (void)
502 {
503   unsigned chksum = DECL_SOURCE_LINE (current_function_decl);
504
505   chksum = coverage_checksum_string (chksum,
506                                      DECL_SOURCE_FILE (current_function_decl));
507   chksum = coverage_checksum_string
508     (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
509
510   return chksum;
511 }
512 \f
513 /* Begin output to the graph file for the current function.
514    Opens the output file, if not already done. Writes the
515    function header, if not already done. Returns nonzero if data
516    should be output.  */
517
518 int
519 coverage_begin_output (void)
520 {
521   if (no_coverage)
522     return 0;
523
524   if (!bbg_function_announced)
525     {
526       const char *file = DECL_SOURCE_FILE (current_function_decl);
527       unsigned line = DECL_SOURCE_LINE (current_function_decl);
528       unsigned long offset;
529
530       if (!bbg_file_opened)
531         {
532           if (!gcov_open (bbg_file_name, -1))
533             error ("cannot open %s", bbg_file_name);
534           else
535             {
536               gcov_write_unsigned (GCOV_NOTE_MAGIC);
537               gcov_write_unsigned (GCOV_VERSION);
538               gcov_write_unsigned (local_tick);
539             }
540           bbg_file_opened = 1;
541         }
542
543       /* Announce function */
544       offset = gcov_write_tag (GCOV_TAG_FUNCTION);
545       gcov_write_unsigned (current_function_funcdef_no + 1);
546       gcov_write_unsigned (compute_checksum ());
547       gcov_write_string (IDENTIFIER_POINTER
548                          (DECL_ASSEMBLER_NAME (current_function_decl)));
549       gcov_write_string (file);
550       gcov_write_unsigned (line);
551       gcov_write_length (offset);
552
553       bbg_function_announced = 1;
554     }
555   return !gcov_is_error ();
556 }
557
558 /* Finish coverage data for the current function. Verify no output
559    error has occurred.  Save function coverage counts.  */
560
561 void
562 coverage_end_function (void)
563 {
564   unsigned i;
565
566   if (bbg_file_opened > 1 && gcov_is_error ())
567     {
568       warning ("error writing `%s'", bbg_file_name);
569       bbg_file_opened = -1;
570     }
571
572   if (fn_ctr_mask)
573     {
574       struct function_list *item;
575
576       item = xmalloc (sizeof (struct function_list));
577
578       *functions_tail = item;
579       functions_tail = &item->next;
580
581       item->next = 0;
582       item->ident = current_function_funcdef_no + 1;
583       item->checksum = compute_checksum ();
584       for (i = 0; i != GCOV_COUNTERS; i++)
585         {
586           item->n_ctrs[i] = fn_n_ctrs[i];
587           prg_n_ctrs[i] += fn_n_ctrs[i];
588           fn_n_ctrs[i] = fn_b_ctrs[i] = 0;
589         }
590       prg_ctr_mask |= fn_ctr_mask;
591       fn_ctr_mask = 0;
592     }
593   bbg_function_announced = 0;
594 }
595
596 /* Creates the gcov_fn_info RECORD_TYPE.  */
597
598 static tree
599 build_fn_info_type (unsigned int counters)
600 {
601   tree type = lang_hooks.types.make_type (RECORD_TYPE);
602   tree field, fields;
603   tree array_type;
604
605   /* ident */
606   fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
607
608   /* checksum */
609   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
610   TREE_CHAIN (field) = fields;
611   fields = field;
612
613   array_type = build_index_type (build_int_2 (counters - 1, 0));
614   array_type = build_array_type (unsigned_type_node, array_type);
615
616   /* counters */
617   field = build_decl (FIELD_DECL, NULL_TREE, array_type);
618   TREE_CHAIN (field) = fields;
619   fields = field;
620
621   finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
622
623   return type;
624 }
625
626 /* Creates a CONSTRUCTOR for a gcov_fn_info. FUNCTION is
627    the function being processed and TYPE is the gcov_fn_info
628    RECORD_TYPE.  */
629
630 static tree
631 build_fn_info_value (const struct function_list *function, tree type)
632 {
633   tree value = NULL_TREE;
634   tree fields = TYPE_FIELDS (type);
635   unsigned ix;
636   tree array_value = NULL_TREE;
637
638   /* ident */
639   value = tree_cons (fields,
640                      convert (unsigned_intSI_type_node,
641                               build_int_2 (function->ident, 0)),
642                      value);
643   fields = TREE_CHAIN (fields);
644
645   /* checksum */
646   value = tree_cons (fields,
647                      convert (unsigned_intSI_type_node,
648                               build_int_2 (function->checksum, 0)),
649                      value);
650   fields = TREE_CHAIN (fields);
651
652   /* counters */
653   for (ix = 0; ix != GCOV_COUNTERS; ix++)
654     if (prg_ctr_mask & (1 << ix))
655       {
656         tree counters = convert (unsigned_type_node,
657                                  build_int_2 (function->n_ctrs[ix], 0));
658
659         array_value = tree_cons (NULL_TREE, counters, array_value);
660       }
661
662   array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value));
663   value = tree_cons (fields, array_value, value);
664
665   value = build_constructor (type, nreverse (value));
666
667   return value;
668 }
669
670 /* Creates the gcov_ctr_info RECORD_TYPE.  */
671
672 static tree
673 build_ctr_info_type (void)
674 {
675   tree type = lang_hooks.types.make_type (RECORD_TYPE);
676   tree field, fields = NULL_TREE;
677   tree gcov_ptr_type = build_pointer_type (GCOV_TYPE_NODE);
678   tree gcov_merge_fn_type;
679
680   /* counters */
681   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
682   TREE_CHAIN (field) = fields;
683   fields = field;
684
685   /* values */
686   field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
687   TREE_CHAIN (field) = fields;
688   fields = field;
689
690   /* merge */
691   gcov_merge_fn_type =
692     build_function_type_list (void_type_node,
693                               gcov_ptr_type, unsigned_type_node,
694                               NULL_TREE);
695   field = build_decl (FIELD_DECL, NULL_TREE,
696                       build_pointer_type (gcov_merge_fn_type));
697   TREE_CHAIN (field) = fields;
698   fields = field;
699
700   finish_builtin_struct (type, "__gcov_ctr_info", fields, NULL_TREE);
701
702   return type;
703 }
704
705 /* Creates a CONSTRUCTOR for a gcov_ctr_info. COUNTER is
706    the counter being processed and TYPE is the gcov_ctr_info
707    RECORD_TYPE.  */
708
709 static tree
710 build_ctr_info_value (unsigned int counter, tree type)
711 {
712   tree value = NULL_TREE;
713   tree fields = TYPE_FIELDS (type);
714   tree fn;
715
716   /* counters */
717   value = tree_cons (fields,
718                      convert (unsigned_intSI_type_node,
719                               build_int_2 (prg_n_ctrs[counter], 0)),
720                      value);
721   fields = TREE_CHAIN (fields);
722
723   if (prg_n_ctrs[counter])
724     {
725       tree array_type;
726
727       array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0));
728       array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)),
729                                      array_type);
730
731       TREE_TYPE (tree_ctr_tables[counter]) = array_type;
732       DECL_SIZE (tree_ctr_tables[counter]) = TYPE_SIZE (array_type);
733       DECL_SIZE_UNIT (tree_ctr_tables[counter]) = TYPE_SIZE_UNIT (array_type);
734       assemble_variable (tree_ctr_tables[counter], 0, 0, 0);
735
736       value = tree_cons (fields,
737                          build1 (ADDR_EXPR, TREE_TYPE (fields), 
738                                             tree_ctr_tables[counter]),
739                          value);
740     }
741   else
742     value = tree_cons (fields, null_pointer_node, value);
743   fields = TREE_CHAIN (fields);
744
745   fn = build_decl (FUNCTION_DECL,
746                    get_identifier (ctr_merge_functions[counter]),
747                    TREE_TYPE (TREE_TYPE (fields)));
748   DECL_EXTERNAL (fn) = 1;
749   TREE_PUBLIC (fn) = 1;
750   DECL_ARTIFICIAL (fn) = 1;
751   TREE_NOTHROW (fn) = 1;
752   value = tree_cons (fields,
753                      build1 (ADDR_EXPR, TREE_TYPE (fields), fn),
754                      value);
755
756   value = build_constructor (type, nreverse (value));
757
758   return value;
759 }
760
761 /* Creates the gcov_info RECORD_TYPE and initializer for it. Returns a
762    CONSTRUCTOR.  */
763
764 static tree
765 build_gcov_info (void)
766 {
767   unsigned n_ctr_types, ix;
768   tree type, const_type;
769   tree fn_info_type, fn_info_value = NULL_TREE;
770   tree fn_info_ptr_type;
771   tree ctr_info_type, ctr_info_ary_type, ctr_info_value = NULL_TREE;
772   tree field, fields = NULL_TREE;
773   tree value = NULL_TREE;
774   tree filename_string;
775   char *filename;
776   int filename_len;
777   unsigned n_fns;
778   const struct function_list *fn;
779   tree string_type;
780
781   /* Count the number of active counters.  */
782   for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++)
783     if (prg_ctr_mask & (1 << ix))
784       n_ctr_types++;
785
786   type = lang_hooks.types.make_type (RECORD_TYPE);
787   const_type = build_qualified_type (type, TYPE_QUAL_CONST);
788
789   /* Version ident */
790   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
791   TREE_CHAIN (field) = fields;
792   fields = field;
793   value = tree_cons (field, convert (unsigned_intSI_type_node,
794                                      build_int_2 (GCOV_VERSION, 0)),
795                      value);
796
797   /* next -- NULL */
798   field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type));
799   TREE_CHAIN (field) = fields;
800   fields = field;
801   value = tree_cons (field, null_pointer_node, value);
802
803   /* stamp */
804   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
805   TREE_CHAIN (field) = fields;
806   fields = field;
807   value = tree_cons (field, convert (unsigned_intSI_type_node,
808                                      build_int_2 (local_tick, 0)),
809                      value);
810
811   /* Filename */
812   string_type = build_pointer_type (build_qualified_type (char_type_node,
813                                                     TYPE_QUAL_CONST));
814   field = build_decl (FIELD_DECL, NULL_TREE, string_type);
815   TREE_CHAIN (field) = fields;
816   fields = field;
817   filename = getpwd ();
818   filename = (filename && da_file_name[0] != '/'
819               ? concat (filename, "/", da_file_name, NULL)
820               : da_file_name);
821   filename_len = strlen (filename);
822   filename_string = build_string (filename_len + 1, filename);
823   if (filename != da_file_name)
824     free (filename);
825   TREE_TYPE (filename_string) =
826           build_array_type (char_type_node,
827                             build_index_type (build_int_2 (filename_len, 0)));
828   value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string),
829                      value);
830
831   /* Build the fn_info type and initializer.  */
832   fn_info_type = build_fn_info_type (n_ctr_types);
833   fn_info_ptr_type = build_pointer_type (build_qualified_type
834                                          (fn_info_type, TYPE_QUAL_CONST));
835   for (fn = functions_head, n_fns = 0; fn; fn = fn->next, n_fns++)
836     fn_info_value = tree_cons (NULL_TREE,
837                                build_fn_info_value (fn, fn_info_type),
838                                fn_info_value);
839   if (n_fns)
840     {
841       tree array_type;
842
843       array_type = build_index_type (build_int_2 (n_fns - 1, 0));
844       array_type = build_array_type (fn_info_type, array_type);
845
846       fn_info_value = build_constructor (array_type, nreverse (fn_info_value));
847       fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value);
848     }
849   else
850     fn_info_value = null_pointer_node;
851
852   /* number of functions */
853   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
854   TREE_CHAIN (field) = fields;
855   fields = field;
856   value = tree_cons (field,
857                      convert (unsigned_type_node, build_int_2 (n_fns, 0)),
858                      value);
859
860   /* fn_info table */
861   field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type);
862   TREE_CHAIN (field) = fields;
863   fields = field;
864   value = tree_cons (field, fn_info_value, value);
865
866   /* counter_mask */
867   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
868   TREE_CHAIN (field) = fields;
869   fields = field;
870   value = tree_cons (field,
871                      convert (unsigned_type_node,
872                               build_int_2 (prg_ctr_mask, 0)),
873                      value);
874
875   /* counters */
876   ctr_info_type = build_ctr_info_type ();
877   ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0));
878   ctr_info_ary_type = build_array_type (ctr_info_type, ctr_info_ary_type);
879   for (ix = 0; ix != GCOV_COUNTERS; ix++)
880     if (prg_ctr_mask & (1 << ix))
881       ctr_info_value = tree_cons (NULL_TREE,
882                                   build_ctr_info_value (ix, ctr_info_type),
883                                   ctr_info_value);
884   ctr_info_value = build_constructor (ctr_info_ary_type,
885                                       nreverse (ctr_info_value));
886
887   field = build_decl (FIELD_DECL, NULL_TREE, ctr_info_ary_type);
888   TREE_CHAIN (field) = fields;
889   fields = field;
890   value = tree_cons (field, ctr_info_value, value);
891
892   finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
893
894   value = build_constructor (type, nreverse (value));
895
896   return value;
897 }
898
899 /* Write out the structure which libgcov uses to locate all the
900    counters.  The structures used here must match those defined in
901    gcov-io.h.  Write out the constructor to call __gcov_init.  */
902
903 static void
904 create_coverage (void)
905 {
906   tree gcov_info, gcov_info_value;
907   char name[20];
908   char *ctor_name;
909   tree ctor;
910   rtx gcov_info_address;
911
912   no_coverage = 1; /* Disable any further coverage.  */
913
914   if (!prg_ctr_mask)
915     return;
916
917   gcov_info_value = build_gcov_info ();
918
919   gcov_info = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (gcov_info_value));
920   DECL_INITIAL (gcov_info) = gcov_info_value;
921
922   TREE_STATIC (gcov_info) = 1;
923   ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
924   DECL_NAME (gcov_info) = get_identifier (name);
925
926   /* Build structure.  */
927   assemble_variable (gcov_info, 0, 0, 0);
928
929   /* Build the constructor function to invoke __gcov_init.  */
930   ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
931                       "_GCOV", NULL);
932   ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
933                      build_function_type (void_type_node, NULL_TREE));
934   free (ctor_name);
935   DECL_EXTERNAL (ctor) = 0;
936
937   /* It can be a static function as long as collect2 does not have
938      to scan the object file to find its ctor/dtor routine.  */
939   TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
940   TREE_USED (ctor) = 1;
941   DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
942   DECL_UNINLINABLE (ctor) = 1;
943
944   rest_of_decl_compilation (ctor, 0, 1, 0);
945   announce_function (ctor);
946   current_function_decl = ctor;
947   make_decl_rtl (ctor, NULL);
948   init_function_start (ctor);
949   expand_function_start (ctor, 0);
950   /* Actually generate the code to call __gcov_init.  */
951   gcov_info_address = force_reg (Pmode, XEXP (DECL_RTL (gcov_info), 0));
952   emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1,
953                      gcov_info_address, Pmode);
954
955   expand_function_end ();
956   /* Create a dummy BLOCK.  */
957   DECL_INITIAL (ctor) = make_node (BLOCK);
958   TREE_USED (DECL_INITIAL (ctor)) = 1;
959
960   rest_of_compilation ();
961
962   if (! quiet_flag)
963     fflush (asm_out_file);
964   current_function_decl = NULL_TREE;
965
966   if (targetm.have_ctors_dtors)
967     targetm.asm_out.constructor (XEXP (DECL_RTL (ctor), 0),
968                                  DEFAULT_INIT_PRIORITY);
969 }
970 \f
971 /* Perform file-level initialization. Read in data file, generate name
972    of graph file.  */
973
974 void
975 coverage_init (const char *filename)
976 {
977   int len = strlen (filename);
978
979   /* Name of da file.  */
980   da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
981   strcpy (da_file_name, filename);
982   strcat (da_file_name, GCOV_DATA_SUFFIX);
983
984   /* Name of bbg file.  */
985   bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
986   strcpy (bbg_file_name, filename);
987   strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
988
989   read_counts_file ();
990 }
991
992 /* Performs file-level cleanup.  Close graph file, generate coverage
993    variables and constructor.  */
994
995 void
996 coverage_finish (void)
997 {
998   create_coverage ();
999   if (bbg_file_opened)
1000     {
1001       int error = gcov_close ();
1002
1003       if (error)
1004         unlink (bbg_file_name);
1005       if (!local_tick)
1006         /* Only remove the da file, if we cannot stamp it. If we can
1007            stamp it, libgcov will DTRT.  */
1008         unlink (da_file_name);
1009     }
1010 }
1011
1012 #include "gt-coverage.h"