This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] rtlopt branch merge part 10 -- profiler sections
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 9 Feb 2003 22:43:35 +0100
- Subject: [PATCH] rtlopt branch merge part 10 -- profiler sections
Hello,
there are two additional profiled quantities on rtlopt-branch (histograms of
loop iterations and of values of variables); the counters for these profiles
are kept in own sections of .da files. This patch creates infrastructure for
easy addition of new sections.
Zdenek
* gcov-dump.c (print_prefix): Fix signedness warning.
* gcov-io.h (struct counter_section, struct counter_section_data): New.
(struct function_info): n_arc_counts field removed, n_counter_sections,
counter_sections fields added.
(struct gcov_info): arc_counts, n_arc_counts fields removed,
n_counter_sections, counter_sections fields added.
* libgcov.c (gcov_exit, __gcov_flush): Add support for multiple
profile sections.
* profile.h (MAX_COUNTER_SECTIONS): New.
(struct section_info): New.
(struct profile_info): count_instrumented_edges,
count_edges_instrumented_now fields removed, n_sections, section_info
fields added.
(find_counters_section): Declare.
* profile.c (struct function_list): count_edges field removed,
n_counter_sections, counter_sections fields added.
(set_purpose, label_for_tag, build_counter_section_fields,
build_counter_section_value, build_counter_section_data_fields,
build_counter_section_data_value, build_function_info_fields,
build_function_info_value, build_gcov_info_fields,
build_gcov_info_value): New static functions.
(find_counters_section): New function.
(instrument_edges, get_exec_counts, compute_branch_probabilities,
branch_prob, create_profiler): Modified to support multiple profile
sections.
Index: gcov-dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcov-dump.c,v
retrieving revision 1.3
diff -c -3 -p -r1.3 gcov-dump.c
*** gcov-dump.c 5 Jan 2003 04:37:08 -0000 1.3
--- gcov-dump.c 9 Feb 2003 19:57:45 -0000
*************** print_prefix (filename, depth)
*** 131,137 ****
{
static const char prefix[] = " ";
! printf ("%s:%.*s", filename, depth, prefix);
}
static void
--- 131,137 ----
{
static const char prefix[] = " ";
! printf ("%s:%.*s", filename, (int) depth, prefix);
}
static void
Index: gcov-io.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcov-io.h,v
retrieving revision 1.19
diff -c -3 -p -r1.19 gcov-io.h
*** gcov-io.h 24 Jan 2003 01:46:50 -0000 1.19
--- gcov-io.h 9 Feb 2003 19:57:46 -0000
*************** struct gcov_summary
*** 216,231 ****
gcov_type arc_sum_max; /* sum of max_one */
};
- #if IN_LIBGCC2
/* Structures embedded in coveraged program. The structures generated
by write_profile must match these. */
/* Information about a single function. */
struct function_info
{
const char *name; /* (mangled) name of function */
unsigned checksum; /* function checksum */
! unsigned n_arc_counts; /* number of instrumented arcs */
};
/* Information about a single object file. */
--- 216,248 ----
gcov_type arc_sum_max; /* sum of max_one */
};
/* Structures embedded in coveraged program. The structures generated
by write_profile must match these. */
+ /* Information about section of counters for a function. */
+ struct counter_section
+ {
+ unsigned tag; /* Tag of the section. */
+ unsigned n_counters; /* Number of counters in the section. */
+ };
+
+ #if IN_LIBGCC2
+ /* Information about section of counters for an object file. */
+ struct counter_section_data
+ {
+ unsigned tag; /* Tag of the section. */
+ unsigned n_counters; /* Number of counters in the section. */
+ gcov_type *counters; /* The data. */
+ };
+
/* Information about a single function. */
struct function_info
{
const char *name; /* (mangled) name of function */
unsigned checksum; /* function checksum */
! unsigned n_counter_sections; /* Number of types of counters */
! const struct counter_section *counter_sections;
! /* The section descriptions */
};
/* Information about a single object file. */
*************** struct gcov_info
*** 237,247 ****
const char *filename; /* output file name */
long wkspc; /* libgcc workspace */
- const struct function_info *functions; /* table of functions */
unsigned n_functions; /* number of functions */
! gcov_type *arc_counts; /* table of arc counts */
! unsigned n_arc_counts; /* number of arc counts */
};
/* Register a new object file module. */
--- 254,265 ----
const char *filename; /* output file name */
long wkspc; /* libgcc workspace */
unsigned n_functions; /* number of functions */
+ const struct function_info *functions; /* table of functions */
! unsigned n_counter_sections; /* Number of types of counters */
! const struct counter_section_data *counter_sections;
! /* The data to be put into the sections. */
};
/* Register a new object file module. */
Index: libgcov.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcov.c,v
retrieving revision 1.1
diff -c -3 -p -r1.1 libgcov.c
*** libgcov.c 27 Jan 2003 23:22:15 -0000 1.1
--- libgcov.c 9 Feb 2003 19:57:46 -0000
*************** gcov_exit (void)
*** 112,125 ****
int merging = 0;
long base;
const struct function_info *fn_info;
gcov_type *count_ptr;
gcov_type object_max_one = 0;
ptr->wkspc = 0;
if (!ptr->filename)
continue;
! for (ix = ptr->n_arc_counts, count_ptr = ptr->arc_counts; ix--;)
{
gcov_type count = *count_ptr++;
--- 112,146 ----
int merging = 0;
long base;
const struct function_info *fn_info;
+ gcov_type **counters;
gcov_type *count_ptr;
gcov_type object_max_one = 0;
+ gcov_type count;
+ unsigned tag, length, flength, checksum;
+ unsigned arc_data_index, f_sect_index, sect_index;
ptr->wkspc = 0;
if (!ptr->filename)
continue;
! counters = malloc (sizeof (gcov_type *) * ptr->n_counter_sections);
! for (ix = 0; ix < ptr->n_counter_sections; ix++)
! counters[ix] = ptr->counter_sections[ix].counters;
!
! for (arc_data_index = 0;
! arc_data_index < ptr->n_counter_sections
! && ptr->counter_sections[arc_data_index].tag != GCOV_TAG_ARC_COUNTS;
! arc_data_index++)
! continue;
!
! if (arc_data_index == ptr->n_counter_sections)
! {
! /* For now; later we may want to just measure other profiles,
! but now I am lazy to check for all consequences. */
! abort ();
! }
! for (ix = ptr->counter_sections[arc_data_index].n_counters,
! count_ptr = ptr->counter_sections[arc_data_index].counters; ix--;)
{
gcov_type count = *count_ptr++;
*************** gcov_exit (void)
*** 155,161 ****
if (merging)
{
/* Merge data from file. */
- unsigned tag, length;
if (gcov_read_unsigned (da_file, &tag) || tag != GCOV_DATA_MAGIC)
{
--- 176,181 ----
*************** gcov_exit (void)
*** 173,179 ****
}
/* Merge execution counts for each function. */
- count_ptr = ptr->arc_counts;
for (ix = ptr->n_functions, fn_info = ptr->functions;
ix--; fn_info++)
{
--- 193,198 ----
*************** gcov_exit (void)
*** 194,226 ****
ptr->filename, fn_info->name);
goto read_fatal;
}
! {
! unsigned flength, checksum;
!
! if (gcov_read_unsigned (da_file, &flength)
! || gcov_skip_string (da_file, flength)
! || gcov_read_unsigned (da_file, &checksum))
! goto read_error;
! if (flength != strlen (fn_info->name)
! || checksum != fn_info->checksum)
! goto read_mismatch;
! }
! /* Check arc counts */
! if (gcov_read_unsigned (da_file, &tag)
! || gcov_read_unsigned (da_file, &length))
goto read_error;
! if (tag != GCOV_TAG_ARC_COUNTS
! || length / 8 != fn_info->n_arc_counts)
goto read_mismatch;
! {
! gcov_type count;
!
! for (jx = fn_info->n_arc_counts; jx--; count_ptr++)
! if (gcov_read_counter (da_file, &count))
goto read_error;
! else
! *count_ptr += count;
! }
}
/* Check object summary */
--- 213,252 ----
ptr->filename, fn_info->name);
goto read_fatal;
}
!
! if (gcov_read_unsigned (da_file, &flength)
! || gcov_skip_string (da_file, flength)
! || gcov_read_unsigned (da_file, &checksum))
goto read_error;
! if (flength != strlen (fn_info->name)
! || checksum != fn_info->checksum)
goto read_mismatch;
!
! /* Counters. */
! for (f_sect_index = 0;
! f_sect_index < fn_info->n_counter_sections;
! f_sect_index++)
! {
! if (gcov_read_unsigned (da_file, &tag)
! || gcov_read_unsigned (da_file, &length))
goto read_error;
! for (sect_index = 0;
! sect_index < ptr->n_counter_sections;
! sect_index++)
! if (ptr->counter_sections[sect_index].tag == tag)
! break;
! if (fn_info->counter_sections[f_sect_index].tag != tag
! || sect_index == ptr->n_counter_sections
! || length / 8 != fn_info->counter_sections[f_sect_index].n_counters)
! goto read_mismatch;
!
! for (jx = fn_info->counter_sections[f_sect_index].n_counters;
! jx--; counters[sect_index]++)
! if (gcov_read_counter (da_file, &count))
! goto read_error;
! else
! *counters[sect_index] += count;
! }
}
/* Check object summary */
*************** gcov_exit (void)
*** 279,285 ****
}
object.runs++;
! object.arcs = ptr->n_arc_counts;
object.arc_sum = 0;
if (object.arc_max_one < object_max_one)
object.arc_max_one = object_max_one;
--- 305,311 ----
}
object.runs++;
! object.arcs = ptr->counter_sections[arc_data_index].n_counters;
object.arc_sum = 0;
if (object.arc_max_one < object_max_one)
object.arc_max_one = object_max_one;
*************** gcov_exit (void)
*** 299,305 ****
}
/* Write execution counts for each function. */
! count_ptr = ptr->arc_counts;
for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
{
/* Announce function. */
--- 325,332 ----
}
/* Write execution counts for each function. */
! for (ix = 0; ix < ptr->n_counter_sections; ix++)
! counters[ix] = ptr->counter_sections[ix].counters;
for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
{
/* Announce function. */
*************** gcov_exit (void)
*** 312,335 ****
|| gcov_write_unsigned (da_file, fn_info->checksum)
|| gcov_write_length (da_file, base))
goto write_error;
!
! /* arc counts. */
! if (gcov_write_unsigned (da_file, GCOV_TAG_ARC_COUNTS)
! || !(base = gcov_reserve_length (da_file)))
! goto write_error;
!
! for (jx = fn_info->n_arc_counts; jx--;)
{
! gcov_type count = *count_ptr++;
! object.arc_sum += count;
! if (object.arc_max_sum < count)
! object.arc_max_sum = count;
! if (gcov_write_counter (da_file, count))
! goto write_error; /* RIP Edsger Dijkstra */
}
- if (gcov_write_length (da_file, base))
- goto write_error;
}
/* Object file summary. */
--- 339,379 ----
|| gcov_write_unsigned (da_file, fn_info->checksum)
|| gcov_write_length (da_file, base))
goto write_error;
!
! /* counters. */
! for (f_sect_index = 0;
! f_sect_index < fn_info->n_counter_sections;
! f_sect_index++)
{
! tag = fn_info->counter_sections[f_sect_index].tag;
! for (sect_index = 0;
! sect_index < ptr->n_counter_sections;
! sect_index++)
! if (ptr->counter_sections[sect_index].tag == tag)
! break;
! if (sect_index == ptr->n_counter_sections)
! abort ();
!
! if (gcov_write_unsigned (da_file, tag)
! || !(base = gcov_reserve_length (da_file)))
! goto write_error;
!
! for (jx = fn_info->counter_sections[f_sect_index].n_counters; jx--;)
! {
! gcov_type count = *counters[sect_index]++;
! if (tag == GCOV_TAG_ARC_COUNTS)
! {
! object.arc_sum += count;
! if (object.arc_max_sum < count)
! object.arc_max_sum = count;
! }
! if (gcov_write_counter (da_file, count))
! goto write_error; /* RIP Edsger Dijkstra */
! }
! if (gcov_write_length (da_file, base))
! goto write_error;
}
}
/* Object file summary. */
*************** gcov_exit (void)
*** 367,377 ****
}
else
{
! program_arcs += ptr->n_arc_counts;
program_sum += object.arc_sum;
if (program_max_sum < object.arc_max_sum)
program_max_sum = object.arc_max_sum;
}
}
/* Generate whole program statistics. */
--- 411,422 ----
}
else
{
! program_arcs += ptr->counter_sections[arc_data_index].n_counters;
program_sum += object.arc_sum;
if (program_max_sum < object.arc_max_sum)
program_max_sum = object.arc_max_sum;
}
+ free(counters);
}
/* Generate whole program statistics. */
*************** __gcov_flush (void)
*** 465,473 ****
gcov_exit ();
for (ptr = gcov_list; ptr; ptr = ptr->next)
{
! unsigned i;
! for (i = ptr->n_arc_counts; i--;)
! ptr->arc_counts[i] = 0;
}
}
--- 510,519 ----
gcov_exit ();
for (ptr = gcov_list; ptr; ptr = ptr->next)
{
! unsigned i, j;
! for (j = 0; j < ptr->n_counter_sections; j++)
! for (i = ptr->counter_sections[j].n_counters; i--;)
! ptr->counter_sections[j].counters[i] = 0;
}
}
Index: profile.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/profile.c,v
retrieving revision 1.107
diff -c -3 -p -r1.107 profile.c
*** profile.c 27 Jan 2003 23:22:15 -0000 1.107
--- profile.c 9 Feb 2003 19:58:01 -0000
*************** struct function_list
*** 96,102 ****
struct function_list *next; /* next function */
const char *name; /* function name */
unsigned cfg_checksum; /* function checksum */
! unsigned count_edges; /* number of intrumented edges */
};
static struct function_list *functions_head = 0;
--- 96,104 ----
struct function_list *next; /* next function */
const char *name; /* function name */
unsigned cfg_checksum; /* function checksum */
! unsigned n_counter_sections; /* number of counter sections */
! struct counter_section counter_sections[MAX_COUNTER_SECTIONS];
! /* the sections */
};
static struct function_list *functions_head = 0;
*************** static gcov_type * get_exec_counts PARAM
*** 156,161 ****
--- 158,173 ----
static unsigned compute_checksum PARAMS ((void));
static basic_block find_group PARAMS ((basic_block));
static void union_groups PARAMS ((basic_block, basic_block));
+ static void set_purpose PARAMS ((tree, tree));
+ static rtx label_for_tag PARAMS ((unsigned));
+ static tree build_counter_section_fields PARAMS ((void));
+ static tree build_counter_section_value PARAMS ((unsigned, unsigned));
+ static tree build_counter_section_data_fields PARAMS ((void));
+ static tree build_counter_section_data_value PARAMS ((unsigned, unsigned));
+ static tree build_function_info_fields PARAMS ((void));
+ static tree build_function_info_value PARAMS ((struct function_list *));
+ static tree build_gcov_info_fields PARAMS ((tree));
+ static tree build_gcov_info_value PARAMS ((void));
/* Add edge instrumentation code to the entire insn chain.
*************** instrument_edges (el)
*** 170,175 ****
--- 182,188 ----
int num_instr_edges = 0;
int num_edges = NUM_EDGES (el);
basic_block bb;
+ struct section_info *section_info;
remove_fake_edges ();
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
*************** instrument_edges (el)
*** 194,208 ****
}
}
! profile_info.count_edges_instrumented_now = num_instr_edges;
total_num_edges_instrumented += num_instr_edges;
! profile_info.count_instrumented_edges = total_num_edges_instrumented;
total_num_blocks_created += num_edges;
if (rtl_dump_file)
fprintf (rtl_dump_file, "%d edges instrumented\n", num_instr_edges);
-
- commit_edge_insertions_watch_calls ();
}
struct section_reference
--- 207,220 ----
}
}
! section_info = find_counters_section (GCOV_TAG_ARC_COUNTS);
! section_info->n_counters_now = num_instr_edges;
total_num_edges_instrumented += num_instr_edges;
! section_info->n_counters = total_num_edges_instrumented;
total_num_blocks_created += num_edges;
if (rtl_dump_file)
fprintf (rtl_dump_file, "%d edges instrumented\n", num_instr_edges);
}
struct section_reference
*************** compute_branch_probabilities ()
*** 847,852 ****
--- 858,864 ----
free_aux_for_blocks ();
if (exec_counts)
free (exec_counts);
+ find_counters_section (GCOV_TAG_ARC_COUNTS)->present = 1;
}
/* Compute checksum for the current function. We generate a CRC32. */
*************** void
*** 908,920 ****
branch_prob ()
{
basic_block bb;
! int i;
! int num_edges, ignored_edges;
struct edge_list *el;
const char *name = IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (current_function_decl));
profile_info.current_function_cfg_checksum = compute_checksum ();
if (rtl_dump_file)
fprintf (rtl_dump_file, "CFG checksum is %u\n",
--- 920,937 ----
branch_prob ()
{
basic_block bb;
! unsigned i;
! unsigned num_edges, ignored_edges;
struct edge_list *el;
const char *name = IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (current_function_decl));
profile_info.current_function_cfg_checksum = compute_checksum ();
+ for (i = 0; i < profile_info.n_sections; i++)
+ {
+ profile_info.section_info[i].n_counters_now = 0;
+ profile_info.section_info[i].present = 0;
+ }
if (rtl_dump_file)
fprintf (rtl_dump_file, "CFG checksum is %u\n",
*************** branch_prob ()
*** 1082,1088 ****
if (gcov_write_unsigned (bbg_file, GCOV_TAG_BLOCKS)
|| !(offset = gcov_reserve_length (bbg_file)))
goto bbg_error;
! for (i = 0; i != n_basic_blocks + 2; i++)
if (gcov_write_unsigned (bbg_file, 0))
goto bbg_error;
if (gcov_write_length (bbg_file, offset))
--- 1099,1105 ----
if (gcov_write_unsigned (bbg_file, GCOV_TAG_BLOCKS)
|| !(offset = gcov_reserve_length (bbg_file)))
goto bbg_error;
! for (i = 0; i != (unsigned) (n_basic_blocks + 2); i++)
if (gcov_write_unsigned (bbg_file, 0))
goto bbg_error;
if (gcov_write_length (bbg_file, offset))
*************** branch_prob ()
*** 1118,1123 ****
--- 1135,1141 ----
goto bbg_error;
}
}
+
if (gcov_write_length (bbg_file, offset))
goto bbg_error;
}
*************** branch_prob ()
*** 1184,1189 ****
--- 1202,1208 ----
}
insn = NEXT_INSN (insn);
}
+
if (offset)
{
if (gcov_write_unsigned (bbg_file, 0)
*************** branch_prob ()
*** 1210,1215 ****
--- 1229,1237 ----
struct function_list *item;
instrument_edges (el);
+
+ /* Commit changes done by instrumentation. */
+ commit_edge_insertions_watch_calls ();
allocate_reg_info (max_reg_num (), FALSE, FALSE);
/* ??? Probably should re-use the existing struct function. */
*************** branch_prob ()
*** 1221,1237 ****
item->next = 0;
item->name = xstrdup (name);
item->cfg_checksum = profile_info.current_function_cfg_checksum;
! item->count_edges = profile_info.count_edges_instrumented_now;
}
remove_fake_edges ();
/* Re-merge split basic blocks and the mess introduced by
insert_insn_on_edge. */
cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0);
if (rtl_dump_file)
dump_flow_info (rtl_dump_file);
- free_aux_for_edges ();
free_edge_list (el);
}
--- 1243,1268 ----
item->next = 0;
item->name = xstrdup (name);
item->cfg_checksum = profile_info.current_function_cfg_checksum;
! item->n_counter_sections = 0;
! for (i = 0; i < profile_info.n_sections; i++)
! if (profile_info.section_info[i].n_counters_now)
! {
! item->counter_sections[item->n_counter_sections].tag =
! profile_info.section_info[i].tag;
! item->counter_sections[item->n_counter_sections].n_counters =
! profile_info.section_info[i].n_counters_now;
! item->n_counter_sections++;
! }
}
remove_fake_edges ();
+ free_aux_for_edges ();
/* Re-merge split basic blocks and the mess introduced by
insert_insn_on_edge. */
cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0);
if (rtl_dump_file)
dump_flow_info (rtl_dump_file);
free_edge_list (el);
}
*************** end_branch_prob ()
*** 1477,1674 ****
}
}
! /* Write out the structure which libgcc uses to locate all the arc
! counters. The structures used here must match those defined in
! gcov-io.h. Write out the constructor to call __gcov_init. */
! void
! create_profiler ()
{
! tree fields, field, value = NULL_TREE;
! tree ginfo_type;
! tree string_type;
! tree gcov_type, gcov_ptr_type;
! char name[20];
! char *ctor_name;
! tree structure, ctor;
! rtx structure_address;
! int save_flag_inline_functions = flag_inline_functions;
! if (!profile_info.count_instrumented_edges)
! return;
! string_type = build_pointer_type
! (build_qualified_type (char_type_node, TYPE_QUAL_CONST));
gcov_type = make_signed_type (GCOV_TYPE_SIZE);
gcov_ptr_type
= build_pointer_type (build_qualified_type
(gcov_type, TYPE_QUAL_CONST));
! ginfo_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
!
/* Version ident */
fields = build_decl (FIELD_DECL, NULL_TREE, long_unsigned_type_node);
! value = tree_cons (fields, convert (long_unsigned_type_node, build_int_2
! (GCOV_VERSION, 0)), value);
!
! /* NULL */
! field = build_decl (FIELD_DECL, NULL_TREE, build_pointer_type
! (build_qualified_type
! (ginfo_type, TYPE_QUAL_CONST)));
TREE_CHAIN (field) = fields;
fields = field;
- value = tree_cons (fields, null_pointer_node, value);
/* Filename */
! {
! tree filename_string;
! char *filename;
! int filename_len;
!
! filename = getpwd ();
! filename = (filename && da_file_name[0] != '/'
! ? concat (filename, "/", da_file_name, NULL)
! : da_file_name);
! filename_len = strlen (filename);
! filename_string = build_string (filename_len + 1, filename);
! if (filename != da_file_name)
! free (filename);
! TREE_TYPE (filename_string) = build_array_type
! (char_type_node, build_index_type
! (build_int_2 (filename_len, 0)));
!
! field = build_decl (FIELD_DECL, NULL_TREE, string_type);
! TREE_CHAIN (field) = fields;
! fields = field;
! value = tree_cons (fields, build1 (ADDR_EXPR, string_type,
! filename_string), value);
! }
/* Workspace */
field = build_decl (FIELD_DECL, NULL_TREE, long_integer_type_node);
TREE_CHAIN (field) = fields;
fields = field;
! value = tree_cons (fields,
! convert (long_integer_type_node, integer_zero_node),
! value);
/* function_info table */
! {
! struct function_list *item;
! int num_nodes = 0;
! tree array_value = NULL_TREE;
! tree finfo_type, finfo_ptr_type;
! tree name, checksum, arcs;
!
! finfo_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
! name = build_decl (FIELD_DECL, NULL_TREE, string_type);
! checksum = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (checksum) = name;
! arcs = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (arcs) = checksum;
! finish_builtin_struct (finfo_type, "__function_info",
! arcs, NULL_TREE);
! finfo_ptr_type = build_pointer_type
! (build_qualified_type (finfo_type, TYPE_QUAL_CONST));
! for (item = functions_head; item != 0; item = item->next, num_nodes++)
! {
! size_t name_len = strlen (item->name);
! tree finfo_value = NULL_TREE;
! tree fname = build_string (name_len + 1, item->name);
!
! TREE_TYPE (fname) = build_array_type
! (char_type_node, build_index_type (build_int_2 (name_len, 0)));
! finfo_value = tree_cons (name, build1
! (ADDR_EXPR, string_type,
! fname), finfo_value);
! finfo_value = tree_cons (checksum, convert
! (unsigned_type_node,
! build_int_2 (item->cfg_checksum, 0)),
! finfo_value);
! finfo_value = tree_cons (arcs, convert
! (unsigned_type_node,
! build_int_2 (item->count_edges, 0)),
! finfo_value);
! array_value = tree_cons (NULL_TREE, build
! (CONSTRUCTOR, finfo_type, NULL_TREE,
! nreverse (finfo_value)), array_value);
! }
! /* Create constructor for array. */
! if (num_nodes)
! {
! tree array_type;
! array_type = build_array_type (finfo_type, build_index_type
! (build_int_2 (num_nodes - 1, 0)));
! array_value = build (CONSTRUCTOR, array_type,
! NULL_TREE, nreverse (array_value));
! array_value = build1
! (ADDR_EXPR, finfo_ptr_type, array_value);
! }
! else
! array_value = null_pointer_node;
!
! field = build_decl (FIELD_DECL, NULL_TREE, finfo_ptr_type);
! TREE_CHAIN (field) = fields;
! fields = field;
! value = tree_cons (fields, array_value, value);
!
! /* number of functions */
! field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (field) = fields;
! fields = field;
! value = tree_cons (fields, convert (unsigned_type_node, build_int_2
! (num_nodes, 0)), value);
! }
! /* arc count table */
! {
! tree counts_table = null_pointer_node;
!
! if (profile_info.count_instrumented_edges)
! {
! tree gcov_type_array_type
! = build_array_type (gcov_type, build_index_type
! (build_int_2 (profile_info.
! count_instrumented_edges - 1, 0)));
! /* No values. */
! counts_table
! = build (VAR_DECL, gcov_type_array_type, NULL_TREE, NULL_TREE);
! TREE_STATIC (counts_table) = 1;
! DECL_NAME (counts_table) = get_identifier (XSTR (profiler_label, 0));
! assemble_variable (counts_table, 0, 0, 0);
! counts_table = build1 (ADDR_EXPR, gcov_ptr_type, counts_table);
! }
!
! field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
! TREE_CHAIN (field) = fields;
! fields = field;
! value = tree_cons (fields, counts_table, value);
! }
! /* number of arc counts */
! field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (field) = fields;
! fields = field;
! value = tree_cons (fields, convert
! (unsigned_type_node,
! build_int_2 (profile_info
! .count_instrumented_edges, 0)),
value);
! finish_builtin_struct (ginfo_type, "__gcov_info", fields, NULL_TREE);
! structure = build (VAR_DECL, ginfo_type, NULL_TREE, NULL_TREE);
! DECL_INITIAL (structure)
! = build (CONSTRUCTOR, ginfo_type, NULL_TREE, nreverse (value));
! TREE_STATIC (structure) = 1;
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
! DECL_NAME (structure) = get_identifier (name);
/* Build structure. */
! assemble_variable (structure, 0, 0, 0);
/* Build the constructor function to invoke __gcov_init. */
ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
--- 1508,2077 ----
}
}
! /* Find (and create if not present) a section with TAG. */
! struct section_info *
! find_counters_section (tag)
! unsigned tag;
! {
! unsigned i;
! for (i = 0; i < profile_info.n_sections; i++)
! if (profile_info.section_info[i].tag == tag)
! return profile_info.section_info + i;
!
! if (i == MAX_COUNTER_SECTIONS)
! abort ();
!
! profile_info.section_info[i].tag = tag;
! profile_info.section_info[i].present = 0;
! profile_info.section_info[i].n_counters = 0;
! profile_info.section_info[i].n_counters_now = 0;
! profile_info.n_sections++;
!
! return profile_info.section_info + i;
! }
!
! /* Set FIELDS as purpose to VALUE. */
! static void
! set_purpose (value, fields)
! tree value;
! tree fields;
{
! tree act_field, act_value;
!
! for (act_field = fields, act_value = value;
! act_field;
! act_field = TREE_CHAIN (act_field), act_value = TREE_CHAIN (act_value))
! TREE_PURPOSE (act_value) = act_field;
! }
! /* Returns label for base of counters inside TAG section. */
! static rtx
! label_for_tag (tag)
! unsigned tag;
! {
! switch (tag)
! {
! case GCOV_TAG_ARC_COUNTS:
! return profiler_label;
! default:
! abort ();
! }
! }
!
! /* Creates fields of struct counter_section (in gcov-io.h). */
! static tree
! build_counter_section_fields ()
! {
! tree field, fields;
!
! /* tag */
! fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
!
! /* n_counters */
! field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (field) = fields;
! fields = field;
!
! return fields;
! }
!
! /* Creates value of struct counter_section (in gcov-io.h). */
! static tree
! build_counter_section_value (tag, n_counters)
! unsigned tag;
! unsigned n_counters;
! {
! tree value = NULL_TREE;
!
! /* tag */
! value = tree_cons (NULL_TREE,
! convert (unsigned_type_node,
! build_int_2 (tag, 0)),
! value);
! /* n_counters */
! value = tree_cons (NULL_TREE,
! convert (unsigned_type_node,
! build_int_2 (n_counters, 0)),
! value);
!
! return value;
! }
!
! /* Creates fields of struct counter_section_data (in gcov-io.h). */
! static tree
! build_counter_section_data_fields ()
! {
! tree field, fields, gcov_type, gcov_ptr_type;
!
! gcov_type = make_signed_type (GCOV_TYPE_SIZE);
! gcov_ptr_type =
! build_pointer_type (build_qualified_type (gcov_type,
! TYPE_QUAL_CONST));
!
! /* tag */
! fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
!
! /* n_counters */
! field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (field) = fields;
! fields = field;
!
! /* counters */
! field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
! TREE_CHAIN (field) = fields;
! fields = field;
!
! return fields;
! }
!
! /* Creates value of struct counter_section_data (in gcov-io.h). */
! static tree
! build_counter_section_data_value (tag, n_counters)
! unsigned tag;
! unsigned n_counters;
! {
! tree value = NULL_TREE, counts_table, gcov_type, gcov_ptr_type;
!
gcov_type = make_signed_type (GCOV_TYPE_SIZE);
gcov_ptr_type
= build_pointer_type (build_qualified_type
(gcov_type, TYPE_QUAL_CONST));
+
+ /* tag */
+ value = tree_cons (NULL_TREE,
+ convert (unsigned_type_node,
+ build_int_2 (tag, 0)),
+ value);
! /* n_counters */
! value = tree_cons (NULL_TREE,
! convert (unsigned_type_node,
! build_int_2 (n_counters, 0)),
! value);
!
! /* counters */
! if (n_counters)
! {
! tree gcov_type_array_type =
! build_array_type (gcov_type,
! build_index_type (build_int_2 (n_counters - 1,
! 0)));
! counts_table =
! build (VAR_DECL, gcov_type_array_type, NULL_TREE, NULL_TREE);
! TREE_STATIC (counts_table) = 1;
! DECL_NAME (counts_table) = get_identifier (XSTR (label_for_tag (tag), 0));
! assemble_variable (counts_table, 0, 0, 0);
! counts_table = build1 (ADDR_EXPR, gcov_ptr_type, counts_table);
! }
! else
! counts_table = null_pointer_node;
!
! value = tree_cons (NULL_TREE, counts_table, value);
!
! return value;
! }
!
! /* Creates fields for struct function_info type (in gcov-io.h). */
! static tree
! build_function_info_fields ()
! {
! tree field, fields, counter_section_fields, counter_section_type;
! tree counter_sections_ptr_type;
! tree string_type =
! build_pointer_type (build_qualified_type (char_type_node,
! TYPE_QUAL_CONST));
! /* name */
! fields = build_decl (FIELD_DECL, NULL_TREE, string_type);
!
! /* checksum */
! field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (field) = fields;
! fields = field;
!
! /* n_counter_sections */
! field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (field) = fields;
! fields = field;
!
! /* counter_sections */
! counter_section_fields = build_counter_section_fields ();
! counter_section_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
! finish_builtin_struct (counter_section_type, "__counter_section",
! counter_section_fields, NULL_TREE);
! counter_sections_ptr_type =
! build_pointer_type
! (build_qualified_type (counter_section_type,
! TYPE_QUAL_CONST));
! field = build_decl (FIELD_DECL, NULL_TREE, counter_sections_ptr_type);
! TREE_CHAIN (field) = fields;
! fields = field;
!
! return fields;
! }
!
! /* Creates value for struct function_info (in gcov-io.h). */
! static tree
! build_function_info_value (function)
! struct function_list *function;
! {
! tree value = NULL_TREE;
! size_t name_len = strlen (function->name);
! tree fname = build_string (name_len + 1, function->name);
! tree string_type =
! build_pointer_type (build_qualified_type (char_type_node,
! TYPE_QUAL_CONST));
! tree counter_section_fields, counter_section_type, counter_sections_value;
! tree counter_sections_ptr_type, counter_sections_array_type;
! unsigned i;
!
! /* name */
! TREE_TYPE (fname) =
! build_array_type (char_type_node,
! build_index_type (build_int_2 (name_len, 0)));
! value = tree_cons (NULL_TREE,
! build1 (ADDR_EXPR,
! string_type,
! fname),
! value);
!
! /* checksum */
! value = tree_cons (NULL_TREE,
! convert (unsigned_type_node,
! build_int_2 (function->cfg_checksum, 0)),
! value);
!
! /* n_counter_sections */
!
! value = tree_cons (NULL_TREE,
! convert (unsigned_type_node,
! build_int_2 (function->n_counter_sections, 0)),
! value);
!
! /* counter_sections */
! counter_section_fields = build_counter_section_fields ();
! counter_section_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
! counter_sections_ptr_type =
! build_pointer_type
! (build_qualified_type (counter_section_type,
! TYPE_QUAL_CONST));
! counter_sections_array_type =
! build_array_type (counter_section_type,
! build_index_type (
! build_int_2 (function->n_counter_sections - 1,
! 0)));
!
! counter_sections_value = NULL_TREE;
! for (i = 0; i < function->n_counter_sections; i++)
! {
! tree counter_section_value =
! build_counter_section_value (function->counter_sections[i].tag,
! function->counter_sections[i].n_counters);
! set_purpose (counter_section_value, counter_section_fields);
! counter_sections_value = tree_cons (NULL_TREE,
! build (CONSTRUCTOR,
! counter_section_type,
! NULL_TREE,
! nreverse (counter_section_value)),
! counter_sections_value);
! }
! finish_builtin_struct (counter_section_type, "__counter_section",
! counter_section_fields, NULL_TREE);
!
! if (function->n_counter_sections)
! {
! counter_sections_value =
! build (CONSTRUCTOR,
! counter_sections_array_type,
! NULL_TREE,
! nreverse (counter_sections_value)),
! counter_sections_value = build1 (ADDR_EXPR,
! counter_sections_ptr_type,
! counter_sections_value);
! }
! else
! counter_sections_value = null_pointer_node;
!
! value = tree_cons (NULL_TREE, counter_sections_value, value);
!
! return value;
! }
!
! /* Creates fields of struct gcov_info type (in gcov-io.h). */
! static tree
! build_gcov_info_fields (gcov_info_type)
! tree gcov_info_type;
! {
! tree field, fields;
! char *filename;
! int filename_len;
! tree string_type =
! build_pointer_type (build_qualified_type (char_type_node,
! TYPE_QUAL_CONST));
! tree function_info_fields, function_info_type, function_info_ptr_type;
! tree counter_section_data_fields, counter_section_data_type;
! tree counter_section_data_ptr_type;
/* Version ident */
fields = build_decl (FIELD_DECL, NULL_TREE, long_unsigned_type_node);
!
! /* next -- NULL */
! field = build_decl (FIELD_DECL, NULL_TREE,
! build_pointer_type (build_qualified_type (gcov_info_type,
! TYPE_QUAL_CONST)));
TREE_CHAIN (field) = fields;
fields = field;
/* Filename */
! filename = getpwd ();
! filename = (filename && da_file_name[0] != '/'
! ? concat (filename, "/", da_file_name, NULL)
! : da_file_name);
! filename_len = strlen (filename);
! if (filename != da_file_name)
! free (filename);
!
! field = build_decl (FIELD_DECL, NULL_TREE, string_type);
! TREE_CHAIN (field) = fields;
! fields = field;
/* Workspace */
field = build_decl (FIELD_DECL, NULL_TREE, long_integer_type_node);
TREE_CHAIN (field) = fields;
fields = field;
!
! /* number of functions */
! field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (field) = fields;
! fields = field;
/* function_info table */
! function_info_fields = build_function_info_fields ();
! function_info_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
! finish_builtin_struct (function_info_type, "__function_info",
! function_info_fields, NULL_TREE);
! function_info_ptr_type =
! build_pointer_type
! (build_qualified_type (function_info_type,
! TYPE_QUAL_CONST));
! field = build_decl (FIELD_DECL, NULL_TREE, function_info_ptr_type);
! TREE_CHAIN (field) = fields;
! fields = field;
! /* n_counter_sections */
! field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
! TREE_CHAIN (field) = fields;
! fields = field;
!
! /* counter sections */
! counter_section_data_fields = build_counter_section_data_fields ();
! counter_section_data_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
! finish_builtin_struct (counter_section_data_type, "__counter_section_data",
! counter_section_data_fields, NULL_TREE);
! counter_section_data_ptr_type =
! build_pointer_type
! (build_qualified_type (counter_section_data_type,
! TYPE_QUAL_CONST));
! field = build_decl (FIELD_DECL, NULL_TREE, counter_section_data_ptr_type);
! TREE_CHAIN (field) = fields;
! fields = field;
! return fields;
! }
! /* Creates struct gcov_info value (in gcov-io.h). */
! static tree
! build_gcov_info_value ()
! {
! tree value = NULL_TREE;
! tree filename_string;
! char *filename;
! int filename_len;
! unsigned n_functions, i;
! struct function_list *item;
! tree string_type =
! build_pointer_type (build_qualified_type (char_type_node,
! TYPE_QUAL_CONST));
! tree function_info_fields, function_info_type, function_info_ptr_type;
! tree functions;
! tree counter_section_data_fields, counter_section_data_type;
! tree counter_section_data_ptr_type, counter_sections;
!
! /* Version ident */
! value = tree_cons (NULL_TREE,
! convert (long_unsigned_type_node,
! build_int_2 (GCOV_VERSION, 0)),
! value);
!
! /* next -- NULL */
! value = tree_cons (NULL_TREE, null_pointer_node, value);
! /* Filename */
! filename = getpwd ();
! filename = (filename && da_file_name[0] != '/'
! ? concat (filename, "/", da_file_name, NULL)
! : da_file_name);
! filename_len = strlen (filename);
! filename_string = build_string (filename_len + 1, filename);
! if (filename != da_file_name)
! free (filename);
! TREE_TYPE (filename_string) =
! build_array_type (char_type_node,
! build_index_type (build_int_2 (filename_len, 0)));
! value = tree_cons (NULL_TREE,
! build1 (ADDR_EXPR,
! string_type,
! filename_string),
! value);
! /* Workspace */
! value = tree_cons (NULL_TREE,
! convert (long_integer_type_node, integer_zero_node),
value);
+
+ /* number of functions */
+ n_functions = 0;
+ for (item = functions_head; item != 0; item = item->next, n_functions++)
+ continue;
+ value = tree_cons (NULL_TREE,
+ convert (unsigned_type_node,
+ build_int_2 (n_functions, 0)),
+ value);
+
+ /* function_info table */
+ function_info_fields = build_function_info_fields ();
+ function_info_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
+ function_info_ptr_type =
+ build_pointer_type (
+ build_qualified_type (function_info_type,
+ TYPE_QUAL_CONST));
+ functions = NULL_TREE;
+ for (item = functions_head; item != 0; item = item->next)
+ {
+ tree function_info_value = build_function_info_value (item);
+ set_purpose (function_info_value, function_info_fields);
+ functions = tree_cons (NULL_TREE,
+ build (CONSTRUCTOR,
+ function_info_type,
+ NULL_TREE,
+ nreverse (function_info_value)),
+ functions);
+ }
+ finish_builtin_struct (function_info_type, "__function_info",
+ function_info_fields, NULL_TREE);
+
+ /* Create constructor for array. */
+ if (n_functions)
+ {
+ tree array_type;
+
+ array_type = build_array_type (
+ function_info_type,
+ build_index_type (build_int_2 (n_functions - 1, 0)));
+ functions = build (CONSTRUCTOR,
+ array_type,
+ NULL_TREE,
+ nreverse (functions));
+ functions = build1 (ADDR_EXPR,
+ function_info_ptr_type,
+ functions);
+ }
+ else
+ functions = null_pointer_node;
+
+ value = tree_cons (NULL_TREE, functions, value);
+
+ /* n_counter_sections */
+ value = tree_cons (NULL_TREE,
+ convert (unsigned_type_node,
+ build_int_2 (profile_info.n_sections, 0)),
+ value);
+
+ /* counter sections */
+ counter_section_data_fields = build_counter_section_data_fields ();
+ counter_section_data_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
+ counter_sections = NULL_TREE;
+ for (i = 0; i < profile_info.n_sections; i++)
+ {
+ tree counter_sections_value =
+ build_counter_section_data_value (
+ profile_info.section_info[i].tag,
+ profile_info.section_info[i].n_counters);
+ set_purpose (counter_sections_value, counter_section_data_fields);
+ counter_sections = tree_cons (NULL_TREE,
+ build (CONSTRUCTOR,
+ counter_section_data_type,
+ NULL_TREE,
+ nreverse (counter_sections_value)),
+ counter_sections);
+ }
+ finish_builtin_struct (counter_section_data_type, "__counter_section_data",
+ counter_section_data_fields, NULL_TREE);
+ counter_section_data_ptr_type =
+ build_pointer_type
+ (build_qualified_type (counter_section_data_type,
+ TYPE_QUAL_CONST));
+
+ if (profile_info.n_sections)
+ {
+ counter_sections =
+ build (CONSTRUCTOR,
+ build_array_type (
+ counter_section_data_type,
+ build_index_type (build_int_2 (profile_info.n_sections - 1, 0))),
+ NULL_TREE,
+ nreverse (counter_sections));
+ counter_sections = build1 (ADDR_EXPR,
+ counter_section_data_ptr_type,
+ counter_sections);
+ }
+ else
+ counter_sections = null_pointer_node;
+ value = tree_cons (NULL_TREE, counter_sections, value);
+
+ return value;
+ }
+
+ /* Write out the structure which libgcc uses to locate all the arc
+ counters. The structures used here must match those defined in
+ gcov-io.h. Write out the constructor to call __gcov_init. */
+
+ void
+ create_profiler ()
+ {
+ tree gcov_info_fields, gcov_info_type, gcov_info_value, gcov_info;
+ char name[20];
+ char *ctor_name;
+ tree ctor;
+ rtx gcov_info_address;
+ int save_flag_inline_functions = flag_inline_functions;
+ unsigned i;
+
+ for (i = 0; i < profile_info.n_sections; i++)
+ if (profile_info.section_info[i].n_counters_now)
+ break;
+ if (i == profile_info.n_sections)
+ return;
! gcov_info_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
! gcov_info_fields = build_gcov_info_fields (gcov_info_type);
! gcov_info_value = build_gcov_info_value ();
! set_purpose (gcov_info_value, gcov_info_fields);
! finish_builtin_struct (gcov_info_type, "__gcov_info",
! gcov_info_fields, NULL_TREE);
!
! gcov_info = build (VAR_DECL, gcov_info_type, NULL_TREE, NULL_TREE);
! DECL_INITIAL (gcov_info) =
! build (CONSTRUCTOR, gcov_info_type, NULL_TREE,
! nreverse (gcov_info_value));
!
! 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);
/* Build the constructor function to invoke __gcov_init. */
ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
*************** create_profiler ()
*** 1696,1707 ****
cfun->arc_profile = 0;
/* Actually generate the code to call __gcov_init. */
! structure_address = force_reg (Pmode, gen_rtx_SYMBOL_REF
! (Pmode, IDENTIFIER_POINTER
! (DECL_NAME (structure))));
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__gcov_init"),
LCT_NORMAL, VOIDmode, 1,
! structure_address, Pmode);
expand_function_end (input_filename, lineno, 0);
(*lang_hooks.decls.poplevel) (1, 0, 1);
--- 2099,2112 ----
cfun->arc_profile = 0;
/* Actually generate the code to call __gcov_init. */
! gcov_info_address = force_reg (Pmode,
! gen_rtx_SYMBOL_REF (
! Pmode,
! IDENTIFIER_POINTER (
! DECL_NAME (gcov_info))));
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__gcov_init"),
LCT_NORMAL, VOIDmode, 1,
! gcov_info_address, Pmode);
expand_function_end (input_filename, lineno, 0);
(*lang_hooks.decls.poplevel) (1, 0, 1);
Index: profile.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/profile.h,v
retrieving revision 1.4
diff -c -3 -p -r1.4 profile.h
*** profile.h 16 Dec 2002 18:19:47 -0000 1.4
--- profile.h 9 Feb 2003 19:58:01 -0000
*************** Software Foundation, 59 Temple Place - S
*** 21,38 ****
#ifndef GCC_PROFILE_H
#define GCC_PROFILE_H
! struct profile_info
! {
! /* Used by final, for allocating the proper amount of storage for the
! instrumented arc execution counts. */
!
! int count_instrumented_edges;
!
! /* Used by final, for writing correct # of instrumented edges
! in this function. */
! int count_edges_instrumented_now;
/* Checksum of the cfg. Used for 'identification' of code.
Used by final. */
--- 21,45 ----
#ifndef GCC_PROFILE_H
#define GCC_PROFILE_H
! /* The number of different counter sections. */
! #define MAX_COUNTER_SECTIONS 1
! /* Info about number of counters in the section. */
! struct section_info
! {
! unsigned tag; /* Section tag. */
! int present; /* Are the data from this section read into gcc? */
! int n_counters; /* Total number of counters. */
! int n_counters_now; /* Number of counters in the current function. */
! };
+ struct profile_info
+ {
+ /* Information about numbers of counters in counter sections, for
+ allocating the storage and storing the sizes. */
+ unsigned n_sections;
+ struct section_info section_info[MAX_COUNTER_SECTIONS];
+
/* Checksum of the cfg. Used for 'identification' of code.
Used by final. */
*************** struct profile_info
*** 46,54 ****
/* The number of profiles merged to form the profile data for the current
function. */
int count_profiles_merged;
-
};
extern struct profile_info profile_info;
#endif
--- 53,62 ----
/* The number of profiles merged to form the profile data for the current
function. */
int count_profiles_merged;
};
extern struct profile_info profile_info;
+
+ struct section_info *find_counters_section PARAMS ((unsigned));
#endif