summaryrefslogtreecommitdiff
path: root/gcc/libgcc2.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2002-05-09 12:54:19 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2002-05-09 12:54:19 +0000
commit90c2be4439c656f63074408d6c91442511a9e061 (patch)
treeda04474c0297ae3c91b3bdce0c519ca2f9d2e5a8 /gcc/libgcc2.c
parent40734805198ef874623eb7be9ec3de9251c799b7 (diff)
downloadgcc-90c2be4439c656f63074408d6c91442511a9e061.tar.gz
* final.c (end_final): Use C trees to output data structures for profiling.
* Makefile.in (LIBGCC_DEPS): Added missing dependency on gcov-io.h (profile.o): New dependency profile.h (final.o): New dependency profile.h * profile.h: New file. New global structure profile_info. * final.h (count_edges_instrumented_now): Declare. (current_function_cfg_checksum): Declare. (function_list): New structure. (functions_head, functions_tail): New static variables. (end_final): Emits more data, removed some -ax stuff. (final): Stores function names and chcksums. * gcov-io.h (__write_gcov_string): New function. (__read_gcov_string): New function. * gcov.c (read_profile): New function. (create_program_flow_graph): Uses read_profile instead of reading da_file. (read_files): Removed da_file checking, it's done by read_profile now. * libgcc2.c (bb_function_info): New structure. (bb): New field in structure, removed some -ax stuff. (__bb_exit_func): Changed structure of da_file. * profile.c (count_edges_instrumented_now): New global variable. (current_function_cfg_checksum): New global variable. (max_counter_in_program): New global variable. (get_exec_counts): New function. (compute_checksum): New function. (instrument_edges): Sets count_edges_instrumented_now. (compute_branch_probabilities): Uses get_exec_counts instead of reading da_file. (branch_prob): Calls compute_checksum and writes extra data to bbg_file. (init_branch_prob): Removed da_file checking, done in get_exec_counts now. (end_branch_prob): Removed da_file checking, done in get_exec_counts now. * gcov.texi: Updated information about gcov file format. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@53326 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/libgcc2.c')
-rw-r--r--gcc/libgcc2.c204
1 files changed, 115 insertions, 89 deletions
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
index a06b7951ab9..6c004a59a3b 100644
--- a/gcc/libgcc2.c
+++ b/gcc/libgcc2.c
@@ -1238,12 +1238,11 @@ __eprintf (const char *string, const char *expression,
#ifdef L_bb
-#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
-typedef long gcov_type;
-#else
-typedef long long gcov_type;
-#endif
-
+struct bb_function_info {
+ long checksum;
+ int arc_count;
+ const char *name;
+};
/* Structure emitted by -a */
struct bb
@@ -1253,14 +1252,10 @@ struct bb
gcov_type *counts;
long ncounts;
struct bb *next;
- const unsigned long *addresses;
/* Older GCC's did not emit these fields. */
long nwords;
- const char **functions;
- const long *line_nums;
- const char **filenames;
- char *flags;
+ struct bb_function_info *function_infos;
};
#ifdef BLOCK_PROFILER_CODE
@@ -1283,39 +1278,66 @@ BLOCK_PROFILER_CODE
#include <errno.h>
#endif
+#include <gthr.h>
+
static struct bb *bb_head;
+int __global_counters = 0, __gthreads_active = 0;
+
void
__bb_exit_func (void)
{
FILE *da_file;
- int i;
struct bb *ptr;
+ long n_counters_p = 0;
+ gcov_type max_counter_p = 0;
+ gcov_type sum_counters_p = 0;
if (bb_head == 0)
return;
- i = strlen (bb_head->filename) - 3;
+ /* Calculate overall "statistics". */
+ for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
+ {
+ int i;
+
+ n_counters_p += ptr->ncounts;
+
+ for (i = 0; i < ptr->ncounts; i++)
+ {
+ sum_counters_p += ptr->counts[i];
+
+ if (ptr->counts[i] > max_counter_p)
+ max_counter_p = ptr->counts[i];
+ }
+ }
for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
{
- int firstchar;
+ gcov_type max_counter_o = 0;
+ gcov_type sum_counters_o = 0;
+ int i;
+
+ /* Calculate the per-object statistics. */
- /* Make sure the output file exists -
- but don't clobber exiting data. */
- if ((da_file = fopen (ptr->filename, "a")) != 0)
- fclose (da_file);
+ for (i = 0; i < ptr->ncounts; i++)
+ {
+ sum_counters_o += ptr->counts[i];
- /* Need to re-open in order to be able to write from the start. */
- da_file = fopen (ptr->filename, "r+b");
+ if (ptr->counts[i] > max_counter_o)
+ max_counter_o = ptr->counts[i];
+ }
+
+ /* open the file for appending, creating it if necessary. */
+ da_file = fopen (ptr->filename, "ab");
/* Some old systems might not allow the 'b' mode modifier.
Therefore, try to open without it. This can lead to a race
condition so that when you delete and re-create the file, the
file might be opened in text mode, but then, you shouldn't
delete the file in the first place. */
if (da_file == 0)
- da_file = fopen (ptr->filename, "r+");
+ da_file = fopen (ptr->filename, "a");
if (da_file == 0)
{
fprintf (stderr, "arc profiling: Can't open output file %s.\n",
@@ -1341,92 +1363,96 @@ __bb_exit_func (void)
}
#endif
- /* If the file is not empty, and the number of counts in it is the
- same, then merge them in. */
- firstchar = fgetc (da_file);
- if (firstchar == EOF)
+ if (__write_long (-123, da_file, 4) != 0) /* magic */
{
- if (ferror (da_file))
- {
- fprintf (stderr, "arc profiling: Can't read output file ");
- perror (ptr->filename);
- }
+ fprintf (stderr, "arc profiling: Error writing output file %s.\n",
+ ptr->filename);
}
else
{
- long n_counts = 0;
-
- if (ungetc (firstchar, da_file) == EOF)
- rewind (da_file);
- if (__read_long (&n_counts, da_file, 8) != 0)
- {
- fprintf (stderr, "arc profiling: Can't read output file %s.\n",
- ptr->filename);
- continue;
- }
- if (n_counts == ptr->ncounts)
+ struct bb_function_info *fn_info;
+ gcov_type *count_ptr = ptr->counts;
+ int i;
+ int count_functions = 0;
+
+ for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
+ fn_info++)
+ count_functions++;
+
+ /* number of functions in this block. */
+ __write_long (count_functions, da_file, 4);
+
+ /* length of extra data in bytes. */
+ __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4);
+
+ /* overall statistics. */
+ /* number of counters. */
+ __write_long (n_counters_p, da_file, 4);
+ /* sum of counters. */
+ __write_gcov_type (sum_counters_p, da_file, 8);
+ /* maximal counter. */
+ __write_gcov_type (max_counter_p, da_file, 8);
+
+ /* per-object statistics. */
+ /* number of counters. */
+ __write_long (ptr->ncounts, da_file, 4);
+ /* sum of counters. */
+ __write_gcov_type (sum_counters_o, da_file, 8);
+ /* maximal counter. */
+ __write_gcov_type (max_counter_o, da_file, 8);
+
+ /* write execution counts for each function. */
+
+ for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
+ fn_info++)
{
- int i;
-
- for (i = 0; i < n_counts; i++)
+ /* new function. */
+ if (__write_gcov_string
+ (fn_info->name, strlen (fn_info->name), da_file, -1) != 0)
{
- gcov_type v = 0;
-
- if (__read_gcov_type (&v, da_file, 8) != 0)
- {
- fprintf (stderr,
- "arc profiling: Can't read output file %s.\n",
- ptr->filename);
- break;
- }
- ptr->counts[i] += v;
+ fprintf (stderr,
+ "arc profiling: Error writing output file %s.\n",
+ ptr->filename);
+ break;
}
- }
- }
-
- rewind (da_file);
-
- /* ??? Should first write a header to the file. Preferably, a 4 byte
- magic number, 4 bytes containing the time the program was
- compiled, 4 bytes containing the last modification time of the
- source file, and 4 bytes indicating the compiler options used.
+ if (__write_long (fn_info->checksum, da_file, 4) != 0)
+ {
+ fprintf (stderr,
+ "arc profiling: Error writing output file %s.\n",
+ ptr->filename);
+ break;
+ }
- That way we can easily verify that the proper source/executable/
- data file combination is being used from gcov. */
+ if (__write_long (fn_info->arc_count, da_file, 4) != 0)
+ {
+ fprintf (stderr,
+ "arc profiling: Error writing output file %s.\n",
+ ptr->filename);
+ break;
+ }
- if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
- {
+ for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
+ {
+ if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
+ break;
+ }
- fprintf (stderr, "arc profiling: Error writing output file %s.\n",
- ptr->filename);
- }
- else
- {
- int j;
- gcov_type *count_ptr = ptr->counts;
- int ret = 0;
- for (j = ptr->ncounts; j > 0; j--)
- {
- if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
+ if (i) /* there was an error */
{
- ret = 1;
+ fprintf (stderr,
+ "arc profiling: Error writing output file %s.\n",
+ ptr->filename);
break;
}
- count_ptr++;
}
- if (ret)
- fprintf (stderr, "arc profiling: Error writing output file %s.\n",
- ptr->filename);
}
- if (fclose (da_file) == EOF)
+ if (fclose (da_file) != 0)
fprintf (stderr, "arc profiling: Error closing output file %s.\n",
ptr->filename);
}
-
- return;
}
void
@@ -1437,8 +1463,8 @@ __bb_init_func (struct bb *blocks)
if (blocks->zero_word)
return;
-
- /* Initialize destructor. */
+
+ /* Initialize destructor and per-thread data. */
if (!bb_head)
atexit (__bb_exit_func);
@@ -1451,7 +1477,7 @@ __bb_init_func (struct bb *blocks)
/* Called before fork or exec - write out profile information gathered so
far and reset it to zero. This avoids duplication or loss of the
profile information gathered so far. */
-void
+void
__bb_fork_func (void)
{
struct bb *ptr;