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