X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcoverage.c;h=6facdce39f695db4044f2f30bb8ab88f47fc3c07;hp=49cf14a26893aea8295298c2705bc8141cb54944;hb=3bdec96a2fb0b7f20277ab0fb361c2acd1a57731;hpb=f0c569c760fbee1842d76f8fae86a84ca6101ba5 diff --git a/gcc/coverage.c b/gcc/coverage.c index 49cf14a2689..6facdce39f6 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -49,8 +49,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA struct function_list { - struct function_list *next; /* next function */ - unsigned ident; /* function ident */ + struct function_list *next; /* next function */ + unsigned ident; /* function ident */ unsigned checksum; /* function checksum */ unsigned n_ctrs[GCOV_COUNTERS];/* number of counters. */ }; @@ -61,7 +61,7 @@ typedef struct counts_entry /* We hash by */ unsigned ident; unsigned ctr; - + /* Store */ unsigned checksum; gcov_type *counts; @@ -69,7 +69,7 @@ typedef struct counts_entry /* Workspace */ struct counts_entry *chain; - + } counts_entry_t; static struct function_list *functions_head = 0; @@ -81,7 +81,7 @@ static unsigned prg_ctr_mask; /* Mask of counter types generated. */ static unsigned prg_n_ctrs[GCOV_COUNTERS]; /* Total counters allocated. */ /* Counter information for current function. */ -static unsigned fn_ctr_mask; /* Mask of counters used. */ +static unsigned fn_ctr_mask; /* Mask of counters used. */ static unsigned fn_n_ctrs[GCOV_COUNTERS]; /* Counters allocated. */ static unsigned fn_b_ctrs[GCOV_COUNTERS]; /* Allocation base. */ @@ -104,23 +104,22 @@ static const char *const ctr_merge_functions[GCOV_COUNTERS] = GCOV_MERGE_FUNCTIO static const char *const ctr_names[GCOV_COUNTERS] = GCOV_COUNTER_NAMES; /* Forward declarations. */ -static hashval_t htab_counts_entry_hash PARAMS ((const void *)); -static int htab_counts_entry_eq PARAMS ((const void *, const void *)); -static void htab_counts_entry_del PARAMS ((void *)); -static void read_counts_file PARAMS ((void)); -static unsigned compute_checksum PARAMS ((void)); -static unsigned checksum_string PARAMS ((unsigned, const char *)); -static tree build_fn_info_type PARAMS ((unsigned)); -static tree build_fn_info_value PARAMS ((const struct function_list *, tree)); -static tree build_ctr_info_type PARAMS ((void)); -static tree build_ctr_info_value PARAMS ((unsigned, tree)); -static tree build_gcov_info PARAMS ((void)); -static void create_coverage PARAMS ((void)); +static hashval_t htab_counts_entry_hash (const void *); +static int htab_counts_entry_eq (const void *, const void *); +static void htab_counts_entry_del (void *); +static void read_counts_file (void); +static unsigned compute_checksum (void); +static unsigned checksum_string (unsigned, const char *); +static tree build_fn_info_type (unsigned); +static tree build_fn_info_value (const struct function_list *, tree); +static tree build_ctr_info_type (void); +static tree build_ctr_info_value (unsigned, tree); +static tree build_gcov_info (void); +static void create_coverage (void); static hashval_t -htab_counts_entry_hash (of) - const void *of; +htab_counts_entry_hash (const void *of) { const counts_entry_t *entry = of; @@ -128,9 +127,7 @@ htab_counts_entry_hash (of) } static int -htab_counts_entry_eq (of1, of2) - const void *of1; - const void *of2; +htab_counts_entry_eq (const void *of1, const void *of2) { const counts_entry_t *entry1 = of1; const counts_entry_t *entry2 = of2; @@ -139,8 +136,7 @@ htab_counts_entry_eq (of1, of2) } static void -htab_counts_entry_del (of) - void *of; +htab_counts_entry_del (void *of) { counts_entry_t *entry = of; @@ -151,11 +147,10 @@ htab_counts_entry_del (of) /* Read in the counts file, if available. */ static void -read_counts_file () +read_counts_file (void) { gcov_unsigned_t fn_ident = 0; - gcov_unsigned_t version, checksum = -1; - unsigned ix; + gcov_unsigned_t checksum = -1; counts_entry_t *summaried = NULL; unsigned seen_summary = 0; gcov_unsigned_t tag; @@ -163,28 +158,28 @@ read_counts_file () if (!gcov_open (da_file_name, 1)) return; - - if (gcov_read_unsigned () != GCOV_DATA_MAGIC) + + if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC)) { warning ("`%s' is not a gcov data file", da_file_name); gcov_close (); return; } - else if ((version = gcov_read_unsigned ()) != GCOV_VERSION) + else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION) { char v[4], e[4]; - gcov_unsigned_t required = GCOV_VERSION; - - for (ix = 4; ix--; required >>= 8, version >>= 8) - { - v[ix] = version; - e[ix] = required; - } + + GCOV_UNSIGNED2STRING (v, tag); + GCOV_UNSIGNED2STRING (e, GCOV_VERSION); + warning ("`%s' is version `%.4s', expected version `%.4s'", - da_file_name, v, e); + da_file_name, v, e); gcov_close (); return; } + + /* Read and discard the stamp. */ + gcov_read_unsigned (); counts_hash = htab_create (10, htab_counts_entry_hash, htab_counts_entry_eq, @@ -193,7 +188,7 @@ read_counts_file () { gcov_unsigned_t length; gcov_position_t offset; - + length = gcov_read_unsigned (); offset = gcov_position (); if (tag == GCOV_TAG_FUNCTION) @@ -206,7 +201,7 @@ read_counts_file () new function begins a new set of program runs. We must unlink the summaried chain. */ counts_entry_t *entry, *chain; - + for (entry = summaried; entry; entry = chain) { chain = entry->chain; @@ -220,13 +215,13 @@ read_counts_file () { counts_entry_t *entry; struct gcov_summary summary; - + gcov_read_summary (&summary); seen_summary = 1; for (entry = summaried; entry; entry = entry->chain) { struct gcov_ctr_summary *csum = &summary.ctrs[entry->ctr]; - + entry->summary.runs += csum->runs; entry->summary.sum_all += csum->sum_all; if (entry->summary.run_max < csum->run_max) @@ -237,7 +232,7 @@ read_counts_file () else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident) { counts_entry_t **slot, *entry, elt; - unsigned n_counts = length / 8; + unsigned n_counts = GCOV_TAG_COUNTER_NUM (length); unsigned ix; elt.ident = fn_ident; @@ -271,8 +266,8 @@ read_counts_file () if (elt.ctr < GCOV_COUNTERS_SUMMABLE /* This should always be true for a just allocated entry, - and always false for an existing one. Check this way, in - case the gcov file is corrupt. */ + and always false for an existing one. Check this way, in + case the gcov file is corrupt. */ && (!entry->chain || summaried != entry)) { entry->chain = summaried; @@ -293,7 +288,7 @@ read_counts_file () da_file_name); htab_delete (counts_hash); } - + gcov_close (); } @@ -305,7 +300,7 @@ get_coverage_counts (unsigned counter, unsigned expected, { counts_entry_t *entry, elt; - /* No hash table, no counts. */ + /* No hash table, no counts. */ if (!counts_hash) { static int warned = 0; @@ -325,7 +320,7 @@ get_coverage_counts (unsigned counter, unsigned expected, (DECL_ASSEMBLER_NAME (current_function_decl))); return 0; } - + if (expected != entry->summary.num || compute_checksum () != entry->checksum) { @@ -333,7 +328,7 @@ get_coverage_counts (unsigned counter, unsigned expected, (DECL_ASSEMBLER_NAME (current_function_decl))); return NULL; } - + if (summary) *summary = &entry->summary; @@ -348,15 +343,15 @@ coverage_counter_alloc (unsigned counter, unsigned num) { if (no_coverage) return 0; - + if (!num) return 1; - + if (!ctr_labels[counter]) { /* Generate and save a copy of this so it can be shared. */ char buf[20]; - + ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", counter + 1); ctr_labels[counter] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); } @@ -386,7 +381,7 @@ coverage_counter_ref (unsigned counter, unsigned no) } /* Generate a checksum for a string. CHKSUM is the current - checksum. */ + checksum. */ static unsigned checksum_string (unsigned chksum, const char *string) @@ -399,21 +394,21 @@ checksum_string (unsigned chksum, const char *string) for (ix = 8; ix--; value <<= 1) { unsigned feedback; - + feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0; chksum <<= 1; chksum ^= feedback; } } while (*string++); - + return chksum; } /* Compute checksum for the current function. We generate a CRC32. */ static unsigned -compute_checksum () +compute_checksum (void) { unsigned chksum = DECL_SOURCE_LINE (current_function_decl); @@ -430,29 +425,30 @@ compute_checksum () should be output. */ int -coverage_begin_output () +coverage_begin_output (void) { if (no_coverage) return 0; - + if (!bbg_function_announced) { const char *file = DECL_SOURCE_FILE (current_function_decl); unsigned line = DECL_SOURCE_LINE (current_function_decl); unsigned long offset; - + if (!bbg_file_opened) { if (!gcov_open (bbg_file_name, -1)) error ("cannot open %s", bbg_file_name); else { - gcov_write_unsigned (GCOV_GRAPH_MAGIC); + gcov_write_unsigned (GCOV_NOTE_MAGIC); gcov_write_unsigned (GCOV_VERSION); + gcov_write_unsigned (local_tick); } bbg_file_opened = 1; } - + /* Announce function */ offset = gcov_write_tag (GCOV_TAG_FUNCTION); gcov_write_unsigned (current_function_funcdef_no + 1); @@ -472,12 +468,12 @@ coverage_begin_output () error has occurred. Save function coverage counts. */ void -coverage_end_function () +coverage_end_function (void) { unsigned i; - + if (bbg_file_opened > 1 && gcov_is_error ()) - { + { warning ("error writing `%s'", bbg_file_name); bbg_file_opened = -1; } @@ -485,12 +481,12 @@ coverage_end_function () if (fn_ctr_mask) { struct function_list *item; - + item = xmalloc (sizeof (struct function_list)); - + *functions_tail = item; functions_tail = &item->next; - + item->next = 0; item->ident = current_function_funcdef_no + 1; item->checksum = compute_checksum (); @@ -509,13 +505,12 @@ coverage_end_function () /* Creates the gcov_fn_info RECORD_TYPE. */ static tree -build_fn_info_type (counters) - unsigned counters; +build_fn_info_type (unsigned int counters) { tree type = (*lang_hooks.types.make_type) (RECORD_TYPE); tree field, fields; tree array_type; - + /* ident */ fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node); @@ -526,7 +521,7 @@ build_fn_info_type (counters) array_type = build_index_type (build_int_2 (counters - 1, 0)); array_type = build_array_type (unsigned_type_node, array_type); - + /* counters */ field = build_decl (FIELD_DECL, NULL_TREE, array_type); TREE_CHAIN (field) = fields; @@ -542,51 +537,49 @@ build_fn_info_type (counters) RECORD_TYPE. */ static tree -build_fn_info_value (function, type) - const struct function_list *function; - tree type; +build_fn_info_value (const struct function_list *function, tree type) { tree value = NULL_TREE; tree fields = TYPE_FIELDS (type); unsigned ix; tree array_value = NULL_TREE; - + /* ident */ value = tree_cons (fields, convert (unsigned_intSI_type_node, build_int_2 (function->ident, 0)), value); fields = TREE_CHAIN (fields); - + /* checksum */ value = tree_cons (fields, convert (unsigned_intSI_type_node, build_int_2 (function->checksum, 0)), value); fields = TREE_CHAIN (fields); - + /* counters */ for (ix = 0; ix != GCOV_COUNTERS; ix++) if (prg_ctr_mask & (1 << ix)) { tree counters = convert (unsigned_type_node, build_int_2 (function->n_ctrs[ix], 0)); - + array_value = tree_cons (NULL_TREE, counters, array_value); } - + array_value = build_constructor (TREE_TYPE (fields), nreverse (array_value)); value = tree_cons (fields, array_value, value); value = build_constructor (type, nreverse (value)); - + return value; } /* Creates the gcov_ctr_info RECORD_TYPE. */ static tree -build_ctr_info_type () +build_ctr_info_type (void) { tree type = (*lang_hooks.types.make_type) (RECORD_TYPE); tree field, fields = NULL_TREE; @@ -623,9 +616,7 @@ build_ctr_info_type () RECORD_TYPE. */ static tree -build_ctr_info_value (counter, type) - unsigned counter; - tree type; +build_ctr_info_value (unsigned int counter, tree type) { tree value = NULL_TREE; tree fields = TYPE_FIELDS (type); @@ -641,16 +632,16 @@ build_ctr_info_value (counter, type) if (prg_n_ctrs[counter]) { tree array_type, array; - + array_type = build_index_type (build_int_2 (prg_n_ctrs[counter] - 1, 0)); array_type = build_array_type (TREE_TYPE (TREE_TYPE (fields)), array_type); - + array = build (VAR_DECL, array_type, NULL_TREE, NULL_TREE); TREE_STATIC (array) = 1; DECL_NAME (array) = get_identifier (XSTR (ctr_labels[counter], 0)); assemble_variable (array, 0, 0, 0); - + value = tree_cons (fields, build1 (ADDR_EXPR, TREE_TYPE (fields), array), value); @@ -671,7 +662,7 @@ build_ctr_info_value (counter, type) value); value = build_constructor (type, nreverse (value)); - + return value; } @@ -679,7 +670,7 @@ build_ctr_info_value (counter, type) CONSTRUCTOR. */ static tree -build_gcov_info () +build_gcov_info (void) { unsigned n_ctr_types, ix; tree type, const_type; @@ -694,15 +685,15 @@ build_gcov_info () unsigned n_fns; const struct function_list *fn; tree string_type; - + /* Count the number of active counters. */ for (n_ctr_types = 0, ix = 0; ix != GCOV_COUNTERS; ix++) if (prg_ctr_mask & (1 << ix)) n_ctr_types++; - + type = (*lang_hooks.types.make_type) (RECORD_TYPE); const_type = build_qualified_type (type, TYPE_QUAL_CONST); - + /* Version ident */ field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node); TREE_CHAIN (field) = fields; @@ -710,13 +701,21 @@ build_gcov_info () value = tree_cons (field, convert (unsigned_intSI_type_node, build_int_2 (GCOV_VERSION, 0)), value); - + /* next -- NULL */ field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type (const_type)); TREE_CHAIN (field) = fields; fields = field; value = tree_cons (field, null_pointer_node, value); - + + /* stamp */ + field = build_decl (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node); + TREE_CHAIN (field) = fields; + fields = field; + value = tree_cons (field, convert (unsigned_intSI_type_node, + build_int_2 (local_tick, 0)), + value); + /* Filename */ string_type = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST)); @@ -736,7 +735,7 @@ build_gcov_info () build_index_type (build_int_2 (filename_len, 0))); value = tree_cons (field, build1 (ADDR_EXPR, string_type, filename_string), value); - + /* Build the fn_info type and initializer. */ fn_info_type = build_fn_info_type (n_ctr_types); fn_info_ptr_type = build_pointer_type (build_qualified_type @@ -751,13 +750,13 @@ build_gcov_info () array_type = build_index_type (build_int_2 (n_fns - 1, 0)); array_type = build_array_type (fn_info_type, array_type); - + fn_info_value = build_constructor (array_type, nreverse (fn_info_value)); fn_info_value = build1 (ADDR_EXPR, fn_info_ptr_type, fn_info_value); } else fn_info_value = null_pointer_node; - + /* number of functions */ field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node); TREE_CHAIN (field) = fields; @@ -765,7 +764,7 @@ build_gcov_info () value = tree_cons (field, convert (unsigned_type_node, build_int_2 (n_fns, 0)), value); - + /* fn_info table */ field = build_decl (FIELD_DECL, NULL_TREE, fn_info_ptr_type); TREE_CHAIN (field) = fields; @@ -780,7 +779,7 @@ build_gcov_info () convert (unsigned_type_node, build_int_2 (prg_ctr_mask, 0)), value); - + /* counters */ ctr_info_type = build_ctr_info_type (); ctr_info_ary_type = build_index_type (build_int_2 (n_ctr_types, 0)); @@ -797,11 +796,11 @@ build_gcov_info () TREE_CHAIN (field) = fields; fields = field; value = tree_cons (field, ctr_info_value, value); - + finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE); value = build_constructor (type, nreverse (value)); - + return value; } @@ -810,7 +809,7 @@ build_gcov_info () gcov-io.h. Write out the constructor to call __gcov_init. */ static void -create_coverage () +create_coverage (void) { tree gcov_info, gcov_info_value; char name[20]; @@ -819,10 +818,10 @@ create_coverage () rtx gcov_info_address; no_coverage = 1; /* Disable any further coverage. */ - + if (!prg_ctr_mask) return; - + gcov_info_value = build_gcov_info (); gcov_info = build (VAR_DECL, TREE_TYPE (gcov_info_value), @@ -832,7 +831,7 @@ create_coverage () TREE_STATIC (gcov_info) = 1; ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0); DECL_NAME (gcov_info) = get_identifier (name); - + /* Build structure. */ assemble_variable (gcov_info, 0, 0, 0); @@ -866,7 +865,7 @@ create_coverage () emit_library_call (gcov_init_libfunc, LCT_NORMAL, VOIDmode, 1, gcov_info_address, Pmode); - expand_function_end (input_filename, input_line, 0); + expand_function_end (); (*lang_hooks.decls.poplevel) (1, 0, 1); rest_of_compilation (ctor); @@ -881,23 +880,22 @@ create_coverage () } /* Perform file-level initialization. Read in data file, generate name - of graph file. */ + of graph file. */ void -coverage_init (filename) - const char *filename; +coverage_init (const char *filename) { int len = strlen (filename); /* Name of da file. */ - da_file_name = (char *) xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1); + da_file_name = xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1); strcpy (da_file_name, filename); strcat (da_file_name, GCOV_DATA_SUFFIX); - + /* Name of bbg file. */ - bbg_file_name = (char *) xmalloc (len + strlen (GCOV_GRAPH_SUFFIX) + 1); + bbg_file_name = xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1); strcpy (bbg_file_name, filename); - strcat (bbg_file_name, GCOV_GRAPH_SUFFIX); + strcat (bbg_file_name, GCOV_NOTE_SUFFIX); read_counts_file (); } @@ -906,22 +904,18 @@ coverage_init (filename) variables and constructor. */ void -coverage_finish () +coverage_finish (void) { create_coverage (); if (bbg_file_opened) { int error = gcov_close (); - + if (error) unlink (bbg_file_name); -#if SELF_COVERAGE - /* If the compiler is instrumented, we should not - unconditionally remove the counts file, because we might be - recompiling ourselves. The .da files are all removed during - copying the stage1 files. */ - if (error) -#endif + if (!local_tick) + /* Only remove the da file, if we cannot stamp it. If we can + stamp it, libgcov will DTRT. */ unlink (da_file_name); } }