Mercurial > hg > CbC > CbC_gcc
diff libgcc/libgcov-driver.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/libgcc/libgcov-driver.c Thu Oct 25 07:37:49 2018 +0900 +++ b/libgcc/libgcov-driver.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,6 +1,6 @@ /* Routines required for instrumenting a program. */ /* Compile this one with gcc. */ -/* Copyright (C) 1989-2018 Free Software Foundation, Inc. +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. This file is part of GCC. @@ -53,6 +53,8 @@ #include "gcov-io.c" +#define GCOV_PROF_PREFIX "libgcov profiling error:%s:" + struct gcov_fn_buffer { struct gcov_fn_buffer *next; @@ -151,12 +153,33 @@ return &fn_buffer->next; fail: - gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix, + gcov_error (GCOV_PROF_PREFIX "Function %u %s %u \n", filename, fn_ix, len ? "cannot allocate" : "counter mismatch", len ? len : ix); return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix); } +/* Convert VERSION into a string description and return the it. + BUFFER is used for storage of the string. The code should be + aligned wit gcov-iov.c. */ + +static char * +gcov_version_string (char *buffer, char version[4]) +{ + if (version[0] < 'A' || version[0] > 'Z' + || version[1] < '0' || version[1] > '9' + || version[2] < '0' || version[2] > '9') + sprintf (buffer, "(unknown)"); + else + { + unsigned major = 10 * (version[0] - 'A') + (version[1] - '0'); + unsigned minor = version[2] - '0'; + sprintf (buffer, "%u.%u (%s)", major, minor, + version[3] == '*' ? "release" : "experimental"); + } + return buffer; +} + /* Check if VERSION of the info block PTR matches libgcov one. Return 1 on success, or zero in case of versions mismatch. If FILENAME is not NULL, its value used for reporting purposes @@ -169,12 +192,16 @@ if (version != GCOV_VERSION) { char v[4], e[4]; + char version_string[128], expected_string[128]; GCOV_UNSIGNED2STRING (v, version); GCOV_UNSIGNED2STRING (e, GCOV_VERSION); - gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n", - filename? filename : ptr->filename, e, v); + gcov_error (GCOV_PROF_PREFIX "Version mismatch - expected %s (%.4s) " + "got %s (%.4s)\n", + filename? filename : ptr->filename, + gcov_version_string (expected_string, e), e, + gcov_version_string (version_string, v), v); return 0; } return 1; @@ -186,6 +213,51 @@ /* Including system dependent components. */ #include "libgcov-driver-system.c" +/* Prune TOP N value COUNTERS. It's needed in order to preserve + reproducibility of builds. */ + +static void +prune_topn_counter (gcov_type *counters, gcov_type all) +{ + for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++) + if (counters[2 * i + 1] < all) + { + counters[2 * i] = 0; + counters[2 * i + 1] = 0; + } +} + +/* Prune counters so that they are ready to store or merge. */ + +static void +prune_counters (struct gcov_info *gi) +{ + for (unsigned i = 0; i < gi->n_functions; i++) + { + const struct gcov_fn_info *gfi = gi->functions[i]; + const struct gcov_ctr_info *ci = gfi->ctrs; + + for (unsigned j = 0; j < GCOV_COUNTERS; j++) + { + if (gi->merge[j] == NULL) + continue; + + if (gi->merge[j] == __gcov_merge_topn) + { + gcc_assert (!(ci->num % GCOV_TOPN_VALUES_COUNTERS)); + for (unsigned k = 0; k < (ci->num / GCOV_TOPN_VALUES_COUNTERS); + k++) + { + gcov_type *counters + = ci->values + (k * GCOV_TOPN_VALUES_COUNTERS); + prune_topn_counter (counters + 1, *counters); + } + } + ci++; + } + } +} + /* This function merges counters in GI_PTR to an existing gcda file. Return 0 on success. Return -1 on error. In this case, caller will goto read_fatal. */ @@ -209,7 +281,7 @@ if (length != gi_ptr->stamp) { /* Read from a different compilation. Overwrite the file. */ - gcov_error ("profiling:%s:overwriting an existing profile data " + gcov_error (GCOV_PROF_PREFIX "overwriting an existing profile data " "with a different timestamp\n", filename); return 0; } @@ -289,7 +361,7 @@ if (tag) { read_mismatch:; - gcov_error ("profiling:%s:Merge mismatch for %s %u\n", + gcov_error (GCOV_PROF_PREFIX "Merge mismatch for %s %u\n", filename, f_ix >= 0 ? "function" : "summary", f_ix < 0 ? -1 - f_ix : f_ix); return -1; @@ -297,7 +369,7 @@ return 0; read_error: - gcov_error ("profiling:%s:%s merging\n", filename, + gcov_error (GCOV_PROF_PREFIX "%s merging\n", filename, error < 0 ? "Overflow": "Error"); return -1; } @@ -388,84 +460,6 @@ } } -/* Sort N entries in VALUE_ARRAY in descending order. - Each entry in VALUE_ARRAY has two values. The sorting - is based on the second value. */ - -GCOV_LINKAGE void -gcov_sort_n_vals (gcov_type *value_array, int n) -{ - int j, k; - - for (j = 2; j < n; j += 2) - { - gcov_type cur_ent[2]; - - cur_ent[0] = value_array[j]; - cur_ent[1] = value_array[j + 1]; - k = j - 2; - while (k >= 0 && value_array[k + 1] < cur_ent[1]) - { - value_array[k + 2] = value_array[k]; - value_array[k + 3] = value_array[k+1]; - k -= 2; - } - value_array[k + 2] = cur_ent[0]; - value_array[k + 3] = cur_ent[1]; - } -} - -/* Sort the profile counters for all indirect call sites. Counters - for each call site are allocated in array COUNTERS. */ - -static void -gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters) -{ - int i; - gcov_type *values; - int n = counters->num; - - gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS)); - values = counters->values; - - for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS) - { - gcov_type *value_array = &values[i + 1]; - gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1); - } -} - -/* Sort topn indirect_call profile counters in GI_PTR. */ - -static void -gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr) -{ - unsigned int i; - int f_ix; - const struct gcov_fn_info *gfi_ptr; - const struct gcov_ctr_info *ci_ptr; - - if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV]) - return; - - for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) - { - gfi_ptr = gi_ptr->functions[f_ix]; - ci_ptr = gfi_ptr->ctrs; - for (i = 0; i < GCOV_COUNTERS; i++) - { - if (!gi_ptr->merge[i]) - continue; - if (i == GCOV_COUNTER_ICALL_TOPNV) - { - gcov_sort_icall_topn_counter (ci_ptr); - break; - } - ci_ptr++; - } - } -} - /* Dump the coverage counts for one gcov_info object. We merge with existing counts when possible, to avoid growing the .da files ad infinitum. We use this program's checksum to make sure we only accumulate whole program @@ -480,10 +474,10 @@ struct gcov_summary summary = {}; int error; gcov_unsigned_t tag; - fn_buffer = 0; - gcov_sort_topn_counter_arrays (gi_ptr); + /* Prune current counters before we merge them. */ + prune_counters (gi_ptr); error = gcov_exit_open_gcda_file (gi_ptr, gf); if (error == -1) @@ -495,7 +489,8 @@ /* Merge data from file. */ if (tag != GCOV_DATA_MAGIC) { - gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename); + gcov_error (GCOV_PROF_PREFIX "Not a gcov data file\n", + gf->filename); goto read_fatal; } error = merge_one_data (gf->filename, gi_ptr, &summary); @@ -516,8 +511,8 @@ if ((error = gcov_close ())) gcov_error (error < 0 ? - "profiling:%s:Overflow writing\n" : - "profiling:%s:Error writing\n", + GCOV_PROF_PREFIX "Overflow writing\n" : + GCOV_PROF_PREFIX "Error writing\n", gf->filename); }