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