Mercurial > hg > CbC > CbC_gcc
comparison gcc/libgcov.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
86 | 86 |
87 /* Size of the longest file name. */ | 87 /* Size of the longest file name. */ |
88 static size_t gcov_max_filename = 0; | 88 static size_t gcov_max_filename = 0; |
89 | 89 |
90 #ifdef TARGET_POSIX_IO | 90 #ifdef TARGET_POSIX_IO |
91 /* Make sure path component of the given FILENAME exists, create | 91 /* Make sure path component of the given FILENAME exists, create |
92 missing directories. FILENAME must be writable. | 92 missing directories. FILENAME must be writable. |
93 Returns zero on success, or -1 if an error occurred. */ | 93 Returns zero on success, or -1 if an error occurred. */ |
94 | 94 |
95 static int | 95 static int |
96 create_file_directory (char *filename) | 96 create_file_directory (char *filename) |
97 { | 97 { |
112 fprintf (stderr, "profiling:%s:Cannot create directory\n", | 112 fprintf (stderr, "profiling:%s:Cannot create directory\n", |
113 filename); | 113 filename); |
114 *s = sep; | 114 *s = sep; |
115 return -1; | 115 return -1; |
116 }; | 116 }; |
117 | 117 |
118 *s = sep; | 118 *s = sep; |
119 }; | 119 }; |
120 return 0; | 120 return 0; |
121 } | 121 } |
122 #endif | 122 #endif |
123 | 123 |
124 /* Check if VERSION of the info block PTR matches libgcov one. | 124 /* Check if VERSION of the info block PTR matches libgcov one. |
125 Return 1 on success, or zero in case of versions mismatch. | 125 Return 1 on success, or zero in case of versions mismatch. |
126 If FILENAME is not NULL, its value used for reporting purposes | 126 If FILENAME is not NULL, its value used for reporting purposes |
127 instead of value from the info block. */ | 127 instead of value from the info block. */ |
128 | 128 |
129 static int | 129 static int |
130 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, | 130 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, |
131 const char *filename) | 131 const char *filename) |
132 { | 132 { |
133 if (version != GCOV_VERSION) | 133 if (version != GCOV_VERSION) |
134 { | 134 { |
135 char v[4], e[4]; | 135 char v[4], e[4]; |
136 | 136 |
137 GCOV_UNSIGNED2STRING (v, version); | 137 GCOV_UNSIGNED2STRING (v, version); |
138 GCOV_UNSIGNED2STRING (e, GCOV_VERSION); | 138 GCOV_UNSIGNED2STRING (e, GCOV_VERSION); |
139 | 139 |
140 fprintf (stderr, | 140 fprintf (stderr, |
141 "profiling:%s:Version mismatch - expected %.4s got %.4s\n", | 141 "profiling:%s:Version mismatch - expected %.4s got %.4s\n", |
142 filename? filename : ptr->filename, e, v); | 142 filename? filename : ptr->filename, e, v); |
143 return 0; | 143 return 0; |
144 } | 144 } |
201 gcov_prefix_strip = atoi (tmp); | 201 gcov_prefix_strip = atoi (tmp); |
202 /* Do not consider negative values. */ | 202 /* Do not consider negative values. */ |
203 if (gcov_prefix_strip < 0) | 203 if (gcov_prefix_strip < 0) |
204 gcov_prefix_strip = 0; | 204 gcov_prefix_strip = 0; |
205 } | 205 } |
206 | 206 |
207 prefix_length = strlen(gcov_prefix); | 207 prefix_length = strlen(gcov_prefix); |
208 | 208 |
209 /* Remove an unnecessary trailing '/' */ | 209 /* Remove an unnecessary trailing '/' */ |
210 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) | 210 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) |
211 prefix_length--; | 211 prefix_length--; |
212 } | 212 } |
213 else | 213 else |
214 prefix_length = 0; | 214 prefix_length = 0; |
215 | 215 |
216 /* Allocate and initialize the filename scratch space. */ | 216 /* Allocate and initialize the filename scratch space. */ |
217 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 1); | 217 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 1); |
218 if (prefix_length) | 218 if (prefix_length) |
219 memcpy (gi_filename, gcov_prefix, prefix_length); | 219 memcpy (gi_filename, gcov_prefix, prefix_length); |
220 gi_filename_up = gi_filename + prefix_length; | 220 gi_filename_up = gi_filename + prefix_length; |
221 | 221 |
222 /* Now merge each file. */ | 222 /* Now merge each file. */ |
223 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) | 223 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) |
224 { | 224 { |
225 struct gcov_summary this_object; | 225 struct gcov_summary this_object; |
226 struct gcov_summary object, program; | 226 struct gcov_summary object, program; |
234 gcov_position_t summary_pos = 0; | 234 gcov_position_t summary_pos = 0; |
235 gcov_position_t eof_pos = 0; | 235 gcov_position_t eof_pos = 0; |
236 | 236 |
237 memset (&this_object, 0, sizeof (this_object)); | 237 memset (&this_object, 0, sizeof (this_object)); |
238 memset (&object, 0, sizeof (object)); | 238 memset (&object, 0, sizeof (object)); |
239 | 239 |
240 /* Build relocated filename, stripping off leading | 240 /* Build relocated filename, stripping off leading |
241 directories from the initial filename if requested. */ | 241 directories from the initial filename if requested. */ |
242 if (gcov_prefix_strip > 0) | 242 if (gcov_prefix_strip > 0) |
243 { | 243 { |
244 int level = 0; | 244 int level = 0; |
245 const char *fname = gi_ptr->filename; | 245 const char *fname = gi_ptr->filename; |
292 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned)) | 292 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned)) |
293 { | 293 { |
294 fi_stride += __alignof__ (struct gcov_fn_info) - 1; | 294 fi_stride += __alignof__ (struct gcov_fn_info) - 1; |
295 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1); | 295 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1); |
296 } | 296 } |
297 | 297 |
298 if (!gcov_open (gi_filename)) | 298 if (!gcov_open (gi_filename)) |
299 { | 299 { |
300 #ifdef TARGET_POSIX_IO | 300 #ifdef TARGET_POSIX_IO |
301 /* Open failed likely due to missed directory. | 301 /* Open failed likely due to missed directory. |
302 Create directory and retry to open file. */ | 302 Create directory and retry to open file. */ |
329 | 329 |
330 length = gcov_read_unsigned (); | 330 length = gcov_read_unsigned (); |
331 if (length != gi_ptr->stamp) | 331 if (length != gi_ptr->stamp) |
332 /* Read from a different compilation. Overwrite the file. */ | 332 /* Read from a different compilation. Overwrite the file. */ |
333 goto rewrite; | 333 goto rewrite; |
334 | 334 |
335 /* Merge execution counts for each function. */ | 335 /* Merge execution counts for each function. */ |
336 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) | 336 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) |
337 { | 337 { |
338 fi_ptr = (const struct gcov_fn_info *) | 338 fi_ptr = (const struct gcov_fn_info *) |
339 ((const char *) gi_ptr->functions + f_ix * fi_stride); | 339 ((const char *) gi_ptr->functions + f_ix * fi_stride); |
358 { | 358 { |
359 gcov_merge_fn merge; | 359 gcov_merge_fn merge; |
360 | 360 |
361 if (!((1 << t_ix) & gi_ptr->ctr_mask)) | 361 if (!((1 << t_ix) & gi_ptr->ctr_mask)) |
362 continue; | 362 continue; |
363 | 363 |
364 n_counts = fi_ptr->n_ctrs[c_ix]; | 364 n_counts = fi_ptr->n_ctrs[c_ix]; |
365 merge = gi_ptr->counts[c_ix].merge; | 365 merge = gi_ptr->counts[c_ix].merge; |
366 | 366 |
367 tag = gcov_read_unsigned (); | 367 tag = gcov_read_unsigned (); |
368 length = gcov_read_unsigned (); | 368 length = gcov_read_unsigned (); |
369 if (tag != GCOV_TAG_FOR_COUNTER (t_ix) | 369 if (tag != GCOV_TAG_FOR_COUNTER (t_ix) |
370 || length != GCOV_TAG_COUNTER_LENGTH (n_counts)) | 370 || length != GCOV_TAG_COUNTER_LENGTH (n_counts)) |
371 goto read_mismatch; | 371 goto read_mismatch; |
380 f_ix = ~0u; | 380 f_ix = ~0u; |
381 /* Check program & object summary */ | 381 /* Check program & object summary */ |
382 while (1) | 382 while (1) |
383 { | 383 { |
384 int is_program; | 384 int is_program; |
385 | 385 |
386 eof_pos = gcov_position (); | 386 eof_pos = gcov_position (); |
387 tag = gcov_read_unsigned (); | 387 tag = gcov_read_unsigned (); |
388 if (!tag) | 388 if (!tag) |
389 break; | 389 break; |
390 | 390 |
402 goto rewrite; | 402 goto rewrite; |
403 } | 403 } |
404 } | 404 } |
405 } | 405 } |
406 goto rewrite; | 406 goto rewrite; |
407 | 407 |
408 read_error:; | 408 read_error:; |
409 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n" | 409 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n" |
410 : "profiling:%s:Error merging\n", gi_filename); | 410 : "profiling:%s:Error merging\n", gi_filename); |
411 | 411 |
412 read_fatal:; | 412 read_fatal:; |
413 gcov_close (); | 413 gcov_close (); |
414 continue; | 414 continue; |
415 | 415 |
416 rewrite:; | 416 rewrite:; |
436 goto read_mismatch; | 436 goto read_mismatch; |
437 cs_obj->sum_all += cs_tobj->sum_all; | 437 cs_obj->sum_all += cs_tobj->sum_all; |
438 if (cs_obj->run_max < cs_tobj->run_max) | 438 if (cs_obj->run_max < cs_tobj->run_max) |
439 cs_obj->run_max = cs_tobj->run_max; | 439 cs_obj->run_max = cs_tobj->run_max; |
440 cs_obj->sum_max += cs_tobj->run_max; | 440 cs_obj->sum_max += cs_tobj->run_max; |
441 | 441 |
442 if (!cs_prg->runs++) | 442 if (!cs_prg->runs++) |
443 cs_prg->num = cs_tprg->num; | 443 cs_prg->num = cs_tprg->num; |
444 else if (cs_prg->num != cs_tprg->num) | 444 else if (cs_prg->num != cs_tprg->num) |
445 goto read_mismatch; | 445 goto read_mismatch; |
446 cs_prg->sum_all += cs_tprg->sum_all; | 446 cs_prg->sum_all += cs_tprg->sum_all; |
448 cs_prg->run_max = cs_tprg->run_max; | 448 cs_prg->run_max = cs_tprg->run_max; |
449 cs_prg->sum_max += cs_tprg->run_max; | 449 cs_prg->sum_max += cs_tprg->run_max; |
450 } | 450 } |
451 else if (cs_obj->num || cs_prg->num) | 451 else if (cs_obj->num || cs_prg->num) |
452 goto read_mismatch; | 452 goto read_mismatch; |
453 | 453 |
454 if (!cs_all->runs && cs_prg->runs) | 454 if (!cs_all->runs && cs_prg->runs) |
455 memcpy (cs_all, cs_prg, sizeof (*cs_all)); | 455 memcpy (cs_all, cs_prg, sizeof (*cs_all)); |
456 else if (!all.checksum | 456 else if (!all.checksum |
457 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) | 457 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) |
458 && memcmp (cs_all, cs_prg, sizeof (*cs_all))) | 458 && memcmp (cs_all, cs_prg, sizeof (*cs_all))) |
461 gi_filename, GCOV_LOCKED | 461 gi_filename, GCOV_LOCKED |
462 ? "" : " or concurrent update without locking support"); | 462 ? "" : " or concurrent update without locking support"); |
463 all.checksum = ~0u; | 463 all.checksum = ~0u; |
464 } | 464 } |
465 } | 465 } |
466 | 466 |
467 c_ix = 0; | 467 c_ix = 0; |
468 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) | 468 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) |
469 if ((1 << t_ix) & gi_ptr->ctr_mask) | 469 if ((1 << t_ix) & gi_ptr->ctr_mask) |
470 { | 470 { |
471 values[c_ix] = gi_ptr->counts[c_ix].values; | 471 values[c_ix] = gi_ptr->counts[c_ix].values; |
472 c_ix++; | 472 c_ix++; |
473 } | 473 } |
474 | 474 |
475 program.checksum = gcov_crc32; | 475 program.checksum = gcov_crc32; |
476 | 476 |
477 /* Write out the data. */ | 477 /* Write out the data. */ |
478 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); | 478 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); |
479 gcov_write_unsigned (gi_ptr->stamp); | 479 gcov_write_unsigned (gi_ptr->stamp); |
480 | 480 |
481 /* Write execution counts for each function. */ | 481 /* Write execution counts for each function. */ |
482 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) | 482 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) |
483 { | 483 { |
484 fi_ptr = (const struct gcov_fn_info *) | 484 fi_ptr = (const struct gcov_fn_info *) |
485 ((const char *) gi_ptr->functions + f_ix * fi_stride); | 485 ((const char *) gi_ptr->functions + f_ix * fi_stride); |
496 | 496 |
497 if (!((1 << t_ix) & gi_ptr->ctr_mask)) | 497 if (!((1 << t_ix) & gi_ptr->ctr_mask)) |
498 continue; | 498 continue; |
499 | 499 |
500 n_counts = fi_ptr->n_ctrs[c_ix]; | 500 n_counts = fi_ptr->n_ctrs[c_ix]; |
501 | 501 |
502 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), | 502 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), |
503 GCOV_TAG_COUNTER_LENGTH (n_counts)); | 503 GCOV_TAG_COUNTER_LENGTH (n_counts)); |
504 c_ptr = values[c_ix]; | 504 c_ptr = values[c_ix]; |
505 while (n_counts--) | 505 while (n_counts--) |
506 gcov_write_counter (*c_ptr++); | 506 gcov_write_counter (*c_ptr++); |
542 size_t filename_length = strlen(info->filename); | 542 size_t filename_length = strlen(info->filename); |
543 | 543 |
544 /* Refresh the longest file name information */ | 544 /* Refresh the longest file name information */ |
545 if (filename_length > gcov_max_filename) | 545 if (filename_length > gcov_max_filename) |
546 gcov_max_filename = filename_length; | 546 gcov_max_filename = filename_length; |
547 | 547 |
548 do | 548 do |
549 { | 549 { |
550 unsigned ix; | 550 unsigned ix; |
551 gcov_unsigned_t value = *ptr << 24; | 551 gcov_unsigned_t value = *ptr << 24; |
552 | 552 |
558 crc32 <<= 1; | 558 crc32 <<= 1; |
559 crc32 ^= feedback; | 559 crc32 ^= feedback; |
560 } | 560 } |
561 } | 561 } |
562 while (*ptr++); | 562 while (*ptr++); |
563 | 563 |
564 gcov_crc32 = crc32; | 564 gcov_crc32 = crc32; |
565 | 565 |
566 if (!gcov_list) | 566 if (!gcov_list) |
567 atexit (gcov_exit); | 567 atexit (gcov_exit); |
568 | 568 |
569 info->next = gcov_list; | 569 info->next = gcov_list; |
570 gcov_list = info; | 570 gcov_list = info; |
571 } | 571 } |
572 info->version = 0; | 572 info->version = 0; |
573 } | 573 } |
584 gcov_exit (); | 584 gcov_exit (); |
585 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) | 585 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) |
586 { | 586 { |
587 unsigned t_ix; | 587 unsigned t_ix; |
588 const struct gcov_ctr_info *ci_ptr; | 588 const struct gcov_ctr_info *ci_ptr; |
589 | 589 |
590 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++) | 590 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++) |
591 if ((1 << t_ix) & gi_ptr->ctr_mask) | 591 if ((1 << t_ix) & gi_ptr->ctr_mask) |
592 { | 592 { |
593 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); | 593 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); |
594 ci_ptr++; | 594 ci_ptr++; |
626 /* The profile merging function for choosing the most common value. | 626 /* The profile merging function for choosing the most common value. |
627 It is given an array COUNTERS of N_COUNTERS old counters and it | 627 It is given an array COUNTERS of N_COUNTERS old counters and it |
628 reads the same number of counters from the gcov file. The counters | 628 reads the same number of counters from the gcov file. The counters |
629 are split into 3-tuples where the members of the tuple have | 629 are split into 3-tuples where the members of the tuple have |
630 meanings: | 630 meanings: |
631 | 631 |
632 -- the stored candidate on the most common value of the measured entity | 632 -- the stored candidate on the most common value of the measured entity |
633 -- counter | 633 -- counter |
634 -- total number of evaluations of the value */ | 634 -- total number of evaluations of the value */ |
635 void | 635 void |
636 __gcov_merge_single (gcov_type *counters, unsigned n_counters) | 636 __gcov_merge_single (gcov_type *counters, unsigned n_counters) |
664 /* The profile merging function for choosing the most common | 664 /* The profile merging function for choosing the most common |
665 difference between two consecutive evaluations of the value. It is | 665 difference between two consecutive evaluations of the value. It is |
666 given an array COUNTERS of N_COUNTERS old counters and it reads the | 666 given an array COUNTERS of N_COUNTERS old counters and it reads the |
667 same number of counters from the gcov file. The counters are split | 667 same number of counters from the gcov file. The counters are split |
668 into 4-tuples where the members of the tuple have meanings: | 668 into 4-tuples where the members of the tuple have meanings: |
669 | 669 |
670 -- the last value of the measured entity | 670 -- the last value of the measured entity |
671 -- the stored candidate on the most common difference | 671 -- the stored candidate on the most common difference |
672 -- counter | 672 -- counter |
673 -- total number of evaluations of the value */ | 673 -- total number of evaluations of the value */ |
674 void | 674 void |
675 __gcov_merge_delta (gcov_type *counters, unsigned n_counters) | 675 __gcov_merge_delta (gcov_type *counters, unsigned n_counters) |
676 { | 676 { |
677 unsigned i, n_measures; | 677 unsigned i, n_measures; |
678 gcov_type last, value, counter, all; | 678 gcov_type value, counter, all; |
679 | 679 |
680 gcc_assert (!(n_counters % 4)); | 680 gcc_assert (!(n_counters % 4)); |
681 n_measures = n_counters / 4; | 681 n_measures = n_counters / 4; |
682 for (i = 0; i < n_measures; i++, counters += 4) | 682 for (i = 0; i < n_measures; i++, counters += 4) |
683 { | 683 { |
684 last = gcov_read_counter (); | 684 /* last = */ gcov_read_counter (); |
685 value = gcov_read_counter (); | 685 value = gcov_read_counter (); |
686 counter = gcov_read_counter (); | 686 counter = gcov_read_counter (); |
687 all = gcov_read_counter (); | 687 all = gcov_read_counter (); |
688 | 688 |
689 if (counters[1] == value) | 689 if (counters[1] == value) |
768 #endif | 768 #endif |
769 | 769 |
770 #ifdef L_gcov_indirect_call_profiler | 770 #ifdef L_gcov_indirect_call_profiler |
771 /* Tries to determine the most common value among its inputs. */ | 771 /* Tries to determine the most common value among its inputs. */ |
772 void | 772 void |
773 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, | 773 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, |
774 void* cur_func, void* callee_func) | 774 void* cur_func, void* callee_func) |
775 { | 775 { |
776 /* If the C++ virtual tables contain function descriptors then one | 776 /* If the C++ virtual tables contain function descriptors then one |
777 function may have multiple descriptors and we need to dereference | 777 function may have multiple descriptors and we need to dereference |
778 the descriptors to see if they point to the same function. */ | 778 the descriptors to see if they point to the same function. */ |