1 /* File format for coverage information 2 Copyright (C) 1996-2013 Free Software Foundation, Inc. 3 Contributed by Bob Manson <manson@cygnus.com>. 4 Completely remangled by Nathan Sidwell <nathan@codesourcery.com>. 5 6 This file is part of GCC. 7 8 GCC is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free 10 Software Foundation; either version 3, or (at your option) any later 11 version. 12 13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 for more details. 17 18 Under Section 7 of GPL version 3, you are granted additional 19 permissions described in the GCC Runtime Library Exception, version 20 3.1, as published by the Free Software Foundation. 21 22 You should have received a copy of the GNU General Public License and 23 a copy of the GCC Runtime Library Exception along with this program; 24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 25 <http://www.gnu.org/licenses/>. */ 26 27 /* Routines declared in gcov-io.h. This file should be #included by 28 another source file, after having #included gcov-io.h. */ 29 30 #if !IN_GCOV 31 static void gcov_write_block (unsigned); 32 static gcov_unsigned_t *gcov_write_words (unsigned); 33 #endif 34 static const gcov_unsigned_t *gcov_read_words (unsigned); 35 #if !IN_LIBGCOV 36 static void gcov_allocate (unsigned); 37 #endif 38 39 static inline gcov_unsigned_t from_file (gcov_unsigned_t value) 40 { 41 #if !IN_LIBGCOV 42 if (gcov_var.endian) 43 { 44 value = (value >> 16) | (value << 16); 45 value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff); 46 } 47 #endif 48 return value; 49 } 50 51 /* Open a gcov file. NAME is the name of the file to open and MODE 52 indicates whether a new file should be created, or an existing file 53 opened. If MODE is >= 0 an existing file will be opened, if 54 possible, and if MODE is <= 0, a new file will be created. Use 55 MODE=0 to attempt to reopen an existing file and then fall back on 56 creating a new one. If MODE < 0, the file will be opened in 57 read-only mode. Otherwise it will be opened for modification. 58 Return zero on failure, >0 on opening an existing file and <0 on 59 creating a new one. */ 60 61 GCOV_LINKAGE int 62 #if IN_LIBGCOV 63 gcov_open (const char *name) 64 #else 65 gcov_open (const char *name, int mode) 66 #endif 67 { 68 #if IN_LIBGCOV 69 const int mode = 0; 70 #endif 71 #if GCOV_LOCKED 72 struct flock s_flock; 73 int fd; 74 75 s_flock.l_whence = SEEK_SET; 76 s_flock.l_start = 0; 77 s_flock.l_len = 0; /* Until EOF. */ 78 s_flock.l_pid = getpid (); 79 #endif 80 81 gcc_assert (!gcov_var.file); 82 gcov_var.start = 0; 83 gcov_var.offset = gcov_var.length = 0; 84 gcov_var.overread = -1u; 85 gcov_var.error = 0; 86 #if !IN_LIBGCOV 87 gcov_var.endian = 0; 88 #endif 89 #if GCOV_LOCKED 90 if (mode > 0) 91 { 92 /* Read-only mode - acquire a read-lock. */ 93 s_flock.l_type = F_RDLCK; 94 /* pass mode (ignored) for compatibility */ 95 fd = open (name, O_RDONLY, S_IRUSR | S_IWUSR); 96 } 97 else 98 { 99 /* Write mode - acquire a write-lock. */ 100 s_flock.l_type = F_WRLCK; 101 fd = open (name, O_RDWR | O_CREAT, 0666); 102 } 103 if (fd < 0) 104 return 0; 105 106 while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) 107 continue; 108 109 gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b"); 110 111 if (!gcov_var.file) 112 { 113 close (fd); 114 return 0; 115 } 116 117 if (mode > 0) 118 gcov_var.mode = 1; 119 else if (mode == 0) 120 { 121 struct stat st; 122 123 if (fstat (fd, &st) < 0) 124 { 125 fclose (gcov_var.file); 126 gcov_var.file = 0; 127 return 0; 128 } 129 if (st.st_size != 0) 130 gcov_var.mode = 1; 131 else 132 gcov_var.mode = mode * 2 + 1; 133 } 134 else 135 gcov_var.mode = mode * 2 + 1; 136 #else 137 if (mode >= 0) 138 gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b"); 139 140 if (gcov_var.file) 141 gcov_var.mode = 1; 142 else if (mode <= 0) 143 { 144 gcov_var.file = fopen (name, "w+b"); 145 if (gcov_var.file) 146 gcov_var.mode = mode * 2 + 1; 147 } 148 if (!gcov_var.file) 149 return 0; 150 #endif 151 152 setbuf (gcov_var.file, (char *)0); 153 154 return 1; 155 } 156 157 /* Close the current gcov file. Flushes data to disk. Returns nonzero 158 on failure or error flag set. */ 159 160 GCOV_LINKAGE int 161 gcov_close (void) 162 { 163 if (gcov_var.file) 164 { 165 #if !IN_GCOV 166 if (gcov_var.offset && gcov_var.mode < 0) 167 gcov_write_block (gcov_var.offset); 168 #endif 169 fclose (gcov_var.file); 170 gcov_var.file = 0; 171 gcov_var.length = 0; 172 } 173 #if !IN_LIBGCOV 174 free (gcov_var.buffer); 175 gcov_var.alloc = 0; 176 gcov_var.buffer = 0; 177 #endif 178 gcov_var.mode = 0; 179 return gcov_var.error; 180 } 181 182 #if !IN_LIBGCOV 183 /* Check if MAGIC is EXPECTED. Use it to determine endianness of the 184 file. Returns +1 for same endian, -1 for other endian and zero for 185 not EXPECTED. */ 186 187 GCOV_LINKAGE int 188 gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected) 189 { 190 if (magic == expected) 191 return 1; 192 magic = (magic >> 16) | (magic << 16); 193 magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); 194 if (magic == expected) 195 { 196 gcov_var.endian = 1; 197 return -1; 198 } 199 return 0; 200 } 201 #endif 202 203 #if !IN_LIBGCOV 204 static void 205 gcov_allocate (unsigned length) 206 { 207 size_t new_size = gcov_var.alloc; 208 209 if (!new_size) 210 new_size = GCOV_BLOCK_SIZE; 211 new_size += length; 212 new_size *= 2; 213 214 gcov_var.alloc = new_size; 215 gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2); 216 } 217 #endif 218 219 #if !IN_GCOV 220 /* Write out the current block, if needs be. */ 221 222 static void 223 gcov_write_block (unsigned size) 224 { 225 if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) 226 gcov_var.error = 1; 227 gcov_var.start += size; 228 gcov_var.offset -= size; 229 } 230 231 /* Allocate space to write BYTES bytes to the gcov file. Return a 232 pointer to those bytes, or NULL on failure. */ 233 234 static gcov_unsigned_t * 235 gcov_write_words (unsigned words) 236 { 237 gcov_unsigned_t *result; 238 239 gcc_assert (gcov_var.mode < 0); 240 #if IN_LIBGCOV 241 if (gcov_var.offset >= GCOV_BLOCK_SIZE) 242 { 243 gcov_write_block (GCOV_BLOCK_SIZE); 244 if (gcov_var.offset) 245 { 246 gcc_assert (gcov_var.offset == 1); 247 memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4); 248 } 249 } 250 #else 251 if (gcov_var.offset + words > gcov_var.alloc) 252 gcov_allocate (gcov_var.offset + words); 253 #endif 254 result = &gcov_var.buffer[gcov_var.offset]; 255 gcov_var.offset += words; 256 257 return result; 258 } 259 260 /* Write unsigned VALUE to coverage file. Sets error flag 261 appropriately. */ 262 263 GCOV_LINKAGE void 264 gcov_write_unsigned (gcov_unsigned_t value) 265 { 266 gcov_unsigned_t *buffer = gcov_write_words (1); 267 268 buffer[0] = value; 269 } 270 271 /* Write counter VALUE to coverage file. Sets error flag 272 appropriately. */ 273 274 #if IN_LIBGCOV 275 GCOV_LINKAGE void 276 gcov_write_counter (gcov_type value) 277 { 278 gcov_unsigned_t *buffer = gcov_write_words (2); 279 280 buffer[0] = (gcov_unsigned_t) value; 281 if (sizeof (value) > sizeof (gcov_unsigned_t)) 282 buffer[1] = (gcov_unsigned_t) (value >> 32); 283 else 284 buffer[1] = 0; 285 } 286 #endif /* IN_LIBGCOV */ 287 288 #if !IN_LIBGCOV 289 /* Write STRING to coverage file. Sets error flag on file 290 error, overflow flag on overflow */ 291 292 GCOV_LINKAGE void 293 gcov_write_string (const char *string) 294 { 295 unsigned length = 0; 296 unsigned alloc = 0; 297 gcov_unsigned_t *buffer; 298 299 if (string) 300 { 301 length = strlen (string); 302 alloc = (length + 4) >> 2; 303 } 304 305 buffer = gcov_write_words (1 + alloc); 306 307 buffer[0] = alloc; 308 buffer[alloc] = 0; 309 memcpy (&buffer[1], string, length); 310 } 311 #endif 312 313 #if !IN_LIBGCOV 314 /* Write a tag TAG and reserve space for the record length. Return a 315 value to be used for gcov_write_length. */ 316 317 GCOV_LINKAGE gcov_position_t 318 gcov_write_tag (gcov_unsigned_t tag) 319 { 320 gcov_position_t result = gcov_var.start + gcov_var.offset; 321 gcov_unsigned_t *buffer = gcov_write_words (2); 322 323 buffer[0] = tag; 324 buffer[1] = 0; 325 326 return result; 327 } 328 329 /* Write a record length using POSITION, which was returned by 330 gcov_write_tag. The current file position is the end of the 331 record, and is restored before returning. Returns nonzero on 332 overflow. */ 333 334 GCOV_LINKAGE void 335 gcov_write_length (gcov_position_t position) 336 { 337 unsigned offset; 338 gcov_unsigned_t length; 339 gcov_unsigned_t *buffer; 340 341 gcc_assert (gcov_var.mode < 0); 342 gcc_assert (position + 2 <= gcov_var.start + gcov_var.offset); 343 gcc_assert (position >= gcov_var.start); 344 offset = position - gcov_var.start; 345 length = gcov_var.offset - offset - 2; 346 buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset]; 347 buffer[1] = length; 348 if (gcov_var.offset >= GCOV_BLOCK_SIZE) 349 gcov_write_block (gcov_var.offset); 350 } 351 352 #else /* IN_LIBGCOV */ 353 354 /* Write a tag TAG and length LENGTH. */ 355 356 GCOV_LINKAGE void 357 gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) 358 { 359 gcov_unsigned_t *buffer = gcov_write_words (2); 360 361 buffer[0] = tag; 362 buffer[1] = length; 363 } 364 365 /* Write a summary structure to the gcov file. Return nonzero on 366 overflow. */ 367 368 GCOV_LINKAGE void 369 gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) 370 { 371 unsigned ix, h_ix, bv_ix, h_cnt = 0; 372 const struct gcov_ctr_summary *csum; 373 unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE]; 374 375 /* Count number of non-zero histogram entries, and fill in a bit vector 376 of non-zero indices. The histogram is only currently computed for arc 377 counters. */ 378 for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++) 379 histo_bitvector[bv_ix] = 0; 380 csum = &summary->ctrs[GCOV_COUNTER_ARCS]; 381 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) 382 { 383 if (csum->histogram[h_ix].num_counters > 0) 384 { 385 histo_bitvector[h_ix / 32] |= 1 << (h_ix % 32); 386 h_cnt++; 387 } 388 } 389 gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH(h_cnt)); 390 gcov_write_unsigned (summary->checksum); 391 for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) 392 { 393 gcov_write_unsigned (csum->num); 394 gcov_write_unsigned (csum->runs); 395 gcov_write_counter (csum->sum_all); 396 gcov_write_counter (csum->run_max); 397 gcov_write_counter (csum->sum_max); 398 if (ix != GCOV_COUNTER_ARCS) 399 { 400 for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++) 401 gcov_write_unsigned (0); 402 continue; 403 } 404 for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++) 405 gcov_write_unsigned (histo_bitvector[bv_ix]); 406 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) 407 { 408 if (!csum->histogram[h_ix].num_counters) 409 continue; 410 gcov_write_unsigned (csum->histogram[h_ix].num_counters); 411 gcov_write_counter (csum->histogram[h_ix].min_value); 412 gcov_write_counter (csum->histogram[h_ix].cum_value); 413 } 414 } 415 } 416 #endif /* IN_LIBGCOV */ 417 418 #endif /*!IN_GCOV */ 419 420 /* Return a pointer to read BYTES bytes from the gcov file. Returns 421 NULL on failure (read past EOF). */ 422 423 static const gcov_unsigned_t * 424 gcov_read_words (unsigned words) 425 { 426 const gcov_unsigned_t *result; 427 unsigned excess = gcov_var.length - gcov_var.offset; 428 429 gcc_assert (gcov_var.mode > 0); 430 if (excess < words) 431 { 432 gcov_var.start += gcov_var.offset; 433 #if IN_LIBGCOV 434 if (excess) 435 { 436 gcc_assert (excess == 1); 437 memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4); 438 } 439 #else 440 memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, excess * 4); 441 #endif 442 gcov_var.offset = 0; 443 gcov_var.length = excess; 444 #if IN_LIBGCOV 445 gcc_assert (!gcov_var.length || gcov_var.length == 1); 446 excess = GCOV_BLOCK_SIZE; 447 #else 448 if (gcov_var.length + words > gcov_var.alloc) 449 gcov_allocate (gcov_var.length + words); 450 excess = gcov_var.alloc - gcov_var.length; 451 #endif 452 excess = fread (gcov_var.buffer + gcov_var.length, 453 1, excess << 2, gcov_var.file) >> 2; 454 gcov_var.length += excess; 455 if (gcov_var.length < words) 456 { 457 gcov_var.overread += words - gcov_var.length; 458 gcov_var.length = 0; 459 return 0; 460 } 461 } 462 result = &gcov_var.buffer[gcov_var.offset]; 463 gcov_var.offset += words; 464 return result; 465 } 466 467 /* Read unsigned value from a coverage file. Sets error flag on file 468 error, overflow flag on overflow */ 469 470 GCOV_LINKAGE gcov_unsigned_t 471 gcov_read_unsigned (void) 472 { 473 gcov_unsigned_t value; 474 const gcov_unsigned_t *buffer = gcov_read_words (1); 475 476 if (!buffer) 477 return 0; 478 value = from_file (buffer[0]); 479 return value; 480 } 481 482 /* Read counter value from a coverage file. Sets error flag on file 483 error, overflow flag on overflow */ 484 485 GCOV_LINKAGE gcov_type 486 gcov_read_counter (void) 487 { 488 gcov_type value; 489 const gcov_unsigned_t *buffer = gcov_read_words (2); 490 491 if (!buffer) 492 return 0; 493 value = from_file (buffer[0]); 494 if (sizeof (value) > sizeof (gcov_unsigned_t)) 495 value |= ((gcov_type) from_file (buffer[1])) << 32; 496 else if (buffer[1]) 497 gcov_var.error = -1; 498 499 return value; 500 } 501 502 /* Read string from coverage file. Returns a pointer to a static 503 buffer, or NULL on empty string. You must copy the string before 504 calling another gcov function. */ 505 506 #if !IN_LIBGCOV 507 GCOV_LINKAGE const char * 508 gcov_read_string (void) 509 { 510 unsigned length = gcov_read_unsigned (); 511 512 if (!length) 513 return 0; 514 515 return (const char *) gcov_read_words (length); 516 } 517 #endif 518 519 GCOV_LINKAGE void 520 gcov_read_summary (struct gcov_summary *summary) 521 { 522 unsigned ix, h_ix, bv_ix, h_cnt = 0; 523 struct gcov_ctr_summary *csum; 524 unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE]; 525 unsigned cur_bitvector; 526 527 summary->checksum = gcov_read_unsigned (); 528 for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++) 529 { 530 csum->num = gcov_read_unsigned (); 531 csum->runs = gcov_read_unsigned (); 532 csum->sum_all = gcov_read_counter (); 533 csum->run_max = gcov_read_counter (); 534 csum->sum_max = gcov_read_counter (); 535 memset (csum->histogram, 0, 536 sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); 537 for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++) 538 { 539 histo_bitvector[bv_ix] = gcov_read_unsigned (); 540 #if IN_LIBGCOV 541 /* When building libgcov we don't include system.h, which includes 542 hwint.h (where popcount_hwi is declared). However, libgcov.a 543 is built by the bootstrapped compiler and therefore the builtins 544 are always available. */ 545 h_cnt += __builtin_popcount (histo_bitvector[bv_ix]); 546 #else 547 h_cnt += popcount_hwi (histo_bitvector[bv_ix]); 548 #endif 549 } 550 bv_ix = 0; 551 h_ix = 0; 552 cur_bitvector = 0; 553 while (h_cnt--) 554 { 555 /* Find the index corresponding to the next entry we will read in. 556 First find the next non-zero bitvector and re-initialize 557 the histogram index accordingly, then right shift and increment 558 the index until we find a set bit. */ 559 while (!cur_bitvector) 560 { 561 h_ix = bv_ix * 32; 562 gcc_assert(bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE); 563 cur_bitvector = histo_bitvector[bv_ix++]; 564 } 565 while (!(cur_bitvector & 0x1)) 566 { 567 h_ix++; 568 cur_bitvector >>= 1; 569 } 570 gcc_assert(h_ix < GCOV_HISTOGRAM_SIZE); 571 572 csum->histogram[h_ix].num_counters = gcov_read_unsigned (); 573 csum->histogram[h_ix].min_value = gcov_read_counter (); 574 csum->histogram[h_ix].cum_value = gcov_read_counter (); 575 /* Shift off the index we are done with and increment to the 576 corresponding next histogram entry. */ 577 cur_bitvector >>= 1; 578 h_ix++; 579 } 580 } 581 } 582 583 #if !IN_LIBGCOV 584 /* Reset to a known position. BASE should have been obtained from 585 gcov_position, LENGTH should be a record length. */ 586 587 GCOV_LINKAGE void 588 gcov_sync (gcov_position_t base, gcov_unsigned_t length) 589 { 590 gcc_assert (gcov_var.mode > 0); 591 base += length; 592 if (base - gcov_var.start <= gcov_var.length) 593 gcov_var.offset = base - gcov_var.start; 594 else 595 { 596 gcov_var.offset = gcov_var.length = 0; 597 fseek (gcov_var.file, base << 2, SEEK_SET); 598 gcov_var.start = ftell (gcov_var.file) >> 2; 599 } 600 } 601 #endif 602 603 #if IN_LIBGCOV 604 /* Move to a given position in a gcov file. */ 605 606 GCOV_LINKAGE void 607 gcov_seek (gcov_position_t base) 608 { 609 gcc_assert (gcov_var.mode < 0); 610 if (gcov_var.offset) 611 gcov_write_block (gcov_var.offset); 612 fseek (gcov_var.file, base << 2, SEEK_SET); 613 gcov_var.start = ftell (gcov_var.file) >> 2; 614 } 615 #endif 616 617 #if IN_GCOV > 0 618 /* Return the modification time of the current gcov file. */ 619 620 GCOV_LINKAGE time_t 621 gcov_time (void) 622 { 623 struct stat status; 624 625 if (fstat (fileno (gcov_var.file), &status)) 626 return 0; 627 else 628 return status.st_mtime; 629 } 630 #endif /* IN_GCOV */ 631 632 #if !IN_GCOV 633 /* Determine the index into histogram for VALUE. */ 634 635 #if IN_LIBGCOV 636 static unsigned 637 #else 638 GCOV_LINKAGE unsigned 639 #endif 640 gcov_histo_index (gcov_type value) 641 { 642 gcov_type_unsigned v = (gcov_type_unsigned)value; 643 unsigned r = 0; 644 unsigned prev2bits = 0; 645 646 /* Find index into log2 scale histogram, where each of the log2 647 sized buckets is divided into 4 linear sub-buckets for better 648 focus in the higher buckets. */ 649 650 /* Find the place of the most-significant bit set. */ 651 if (v > 0) 652 { 653 #if IN_LIBGCOV 654 /* When building libgcov we don't include system.h, which includes 655 hwint.h (where floor_log2 is declared). However, libgcov.a 656 is built by the bootstrapped compiler and therefore the builtins 657 are always available. */ 658 r = sizeof (long long) * __CHAR_BIT__ - 1 - __builtin_clzll (v); 659 #else 660 /* We use floor_log2 from hwint.c, which takes a HOST_WIDE_INT 661 that is either 32 or 64 bits, and gcov_type_unsigned may be 64 bits. 662 Need to check for the case where gcov_type_unsigned is 64 bits 663 and HOST_WIDE_INT is 32 bits and handle it specially. */ 664 #if HOST_BITS_PER_WIDEST_INT == HOST_BITS_PER_WIDE_INT 665 r = floor_log2 (v); 666 #elif HOST_BITS_PER_WIDEST_INT == 2 * HOST_BITS_PER_WIDE_INT 667 HOST_WIDE_INT hwi_v = v >> HOST_BITS_PER_WIDE_INT; 668 if (hwi_v) 669 r = floor_log2 (hwi_v) + HOST_BITS_PER_WIDE_INT; 670 else 671 r = floor_log2 ((HOST_WIDE_INT)v); 672 #else 673 gcc_unreachable (); 674 #endif 675 #endif 676 } 677 678 /* If at most the 2 least significant bits are set (value is 679 0 - 3) then that value is our index into the lowest set of 680 four buckets. */ 681 if (r < 2) 682 return (unsigned)value; 683 684 gcc_assert (r < 64); 685 686 /* Find the two next most significant bits to determine which 687 of the four linear sub-buckets to select. */ 688 prev2bits = (v >> (r - 2)) & 0x3; 689 /* Finally, compose the final bucket index from the log2 index and 690 the next 2 bits. The minimum r value at this point is 2 since we 691 returned above if r was 2 or more, so the minimum bucket at this 692 point is 4. */ 693 return (r - 1) * 4 + prev2bits; 694 } 695 696 /* Merge SRC_HISTO into TGT_HISTO. The counters are assumed to be in 697 the same relative order in both histograms, and are matched up 698 and merged in reverse order. Each counter is assigned an equal portion of 699 its entry's original cumulative counter value when computing the 700 new merged cum_value. */ 701 702 static void gcov_histogram_merge (gcov_bucket_type *tgt_histo, 703 gcov_bucket_type *src_histo) 704 { 705 int src_i, tgt_i, tmp_i = 0; 706 unsigned src_num, tgt_num, merge_num; 707 gcov_type src_cum, tgt_cum, merge_src_cum, merge_tgt_cum, merge_cum; 708 gcov_type merge_min; 709 gcov_bucket_type tmp_histo[GCOV_HISTOGRAM_SIZE]; 710 int src_done = 0; 711 712 memset(tmp_histo, 0, sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); 713 714 /* Assume that the counters are in the same relative order in both 715 histograms. Walk the histograms from largest to smallest entry, 716 matching up and combining counters in order. */ 717 src_num = 0; 718 src_cum = 0; 719 src_i = GCOV_HISTOGRAM_SIZE - 1; 720 for (tgt_i = GCOV_HISTOGRAM_SIZE - 1; tgt_i >= 0 && !src_done; tgt_i--) 721 { 722 tgt_num = tgt_histo[tgt_i].num_counters; 723 tgt_cum = tgt_histo[tgt_i].cum_value; 724 /* Keep going until all of the target histogram's counters at this 725 position have been matched and merged with counters from the 726 source histogram. */ 727 while (tgt_num > 0 && !src_done) 728 { 729 /* If this is either the first time through this loop or we just 730 exhausted the previous non-zero source histogram entry, look 731 for the next non-zero source histogram entry. */ 732 if (!src_num) 733 { 734 /* Locate the next non-zero entry. */ 735 while (src_i >= 0 && !src_histo[src_i].num_counters) 736 src_i--; 737 /* If source histogram has fewer counters, then just copy over the 738 remaining target counters and quit. */ 739 if (src_i < 0) 740 { 741 tmp_histo[tgt_i].num_counters += tgt_num; 742 tmp_histo[tgt_i].cum_value += tgt_cum; 743 if (!tmp_histo[tgt_i].min_value || 744 tgt_histo[tgt_i].min_value < tmp_histo[tgt_i].min_value) 745 tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value; 746 while (--tgt_i >= 0) 747 { 748 tmp_histo[tgt_i].num_counters 749 += tgt_histo[tgt_i].num_counters; 750 tmp_histo[tgt_i].cum_value += tgt_histo[tgt_i].cum_value; 751 if (!tmp_histo[tgt_i].min_value || 752 tgt_histo[tgt_i].min_value 753 < tmp_histo[tgt_i].min_value) 754 tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value; 755 } 756 757 src_done = 1; 758 break; 759 } 760 761 src_num = src_histo[src_i].num_counters; 762 src_cum = src_histo[src_i].cum_value; 763 } 764 765 /* The number of counters to merge on this pass is the minimum 766 of the remaining counters from the current target and source 767 histogram entries. */ 768 merge_num = tgt_num; 769 if (src_num < merge_num) 770 merge_num = src_num; 771 772 /* The merged min_value is the sum of the min_values from target 773 and source. */ 774 merge_min = tgt_histo[tgt_i].min_value + src_histo[src_i].min_value; 775 776 /* Compute the portion of source and target entries' cum_value 777 that will be apportioned to the counters being merged. 778 The total remaining cum_value from each entry is divided 779 equally among the counters from that histogram entry if we 780 are not merging all of them. */ 781 merge_src_cum = src_cum; 782 if (merge_num < src_num) 783 merge_src_cum = merge_num * src_cum / src_num; 784 merge_tgt_cum = tgt_cum; 785 if (merge_num < tgt_num) 786 merge_tgt_cum = merge_num * tgt_cum / tgt_num; 787 /* The merged cum_value is the sum of the source and target 788 components. */ 789 merge_cum = merge_src_cum + merge_tgt_cum; 790 791 /* Update the remaining number of counters and cum_value left 792 to be merged from this source and target entry. */ 793 src_cum -= merge_src_cum; 794 tgt_cum -= merge_tgt_cum; 795 src_num -= merge_num; 796 tgt_num -= merge_num; 797 798 /* The merged counters get placed in the new merged histogram 799 at the entry for the merged min_value. */ 800 tmp_i = gcov_histo_index(merge_min); 801 gcc_assert (tmp_i < GCOV_HISTOGRAM_SIZE); 802 tmp_histo[tmp_i].num_counters += merge_num; 803 tmp_histo[tmp_i].cum_value += merge_cum; 804 if (!tmp_histo[tmp_i].min_value || 805 merge_min < tmp_histo[tmp_i].min_value) 806 tmp_histo[tmp_i].min_value = merge_min; 807 808 /* Ensure the search for the next non-zero src_histo entry starts 809 at the next smallest histogram bucket. */ 810 if (!src_num) 811 src_i--; 812 } 813 } 814 815 gcc_assert (tgt_i < 0); 816 817 /* In the case where there were more counters in the source histogram, 818 accumulate the remaining unmerged cumulative counter values. Add 819 those to the smallest non-zero target histogram entry. Otherwise, 820 the total cumulative counter values in the histogram will be smaller 821 than the sum_all stored in the summary, which will complicate 822 computing the working set information from the histogram later on. */ 823 if (src_num) 824 src_i--; 825 while (src_i >= 0) 826 { 827 src_cum += src_histo[src_i].cum_value; 828 src_i--; 829 } 830 /* At this point, tmp_i should be the smallest non-zero entry in the 831 tmp_histo. */ 832 gcc_assert(tmp_i >= 0 && tmp_i < GCOV_HISTOGRAM_SIZE 833 && tmp_histo[tmp_i].num_counters > 0); 834 tmp_histo[tmp_i].cum_value += src_cum; 835 836 /* Finally, copy the merged histogram into tgt_histo. */ 837 memcpy(tgt_histo, tmp_histo, sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); 838 } 839 #endif /* !IN_GCOV */ 840