- 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')),
- "_GCOV", NULL);
- ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
- build_function_type (void_type_node, NULL_TREE));
- free (ctor_name);
- DECL_EXTERNAL (ctor) = 0;
-
- /* It can be a static function as long as collect2 does not have
- to scan the object file to find its ctor/dtor routine. */
- TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
- TREE_USED (ctor) = 1;
- DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
-
- ctor = (*lang_hooks.decls.pushdecl) (ctor);
- rest_of_decl_compilation (ctor, 0, 1, 0);
- announce_function (ctor);
- current_function_decl = ctor;
- DECL_INITIAL (ctor) = error_mark_node;
- make_decl_rtl (ctor, NULL);
- init_function_start (ctor, input_filename, lineno);
- (*lang_hooks.decls.pushlevel) (0);
- expand_function_start (ctor, 0);
- 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);
-
- /* Since ctor isn't in the list of globals, it would never be emitted
- when it's considered to be 'safe' for inlining, so turn off
- flag_inline_functions. */
- flag_inline_functions = 0;
-
- rest_of_compilation (ctor);
-
- /* Reset flag_inline_functions to its original value. */
- flag_inline_functions = save_flag_inline_functions;
-
- if (! quiet_flag)
- fflush (asm_out_file);
- current_function_decl = NULL_TREE;
-
- if (targetm.have_ctors_dtors)
- (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
- DEFAULT_INIT_PRIORITY);
-}
-\f
-/* Output instructions as RTL to increment the edge execution count. */
-
-static rtx
-gen_edge_profiler (edgeno)
- int edgeno;
-{
- enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
- rtx mem_ref, tmp;
- rtx sequence;
-
- start_sequence ();
-
- tmp = force_reg (Pmode, profiler_label);
- tmp = plus_constant (tmp, GCOV_TYPE_SIZE / BITS_PER_UNIT * edgeno);
- mem_ref = validize_mem (gen_rtx_MEM (mode, tmp));
-
- set_mem_alias_set (mem_ref, new_alias_set ());
-
- tmp = expand_simple_binop (mode, PLUS, mem_ref, const1_rtx,
- mem_ref, 0, OPTAB_WIDEN);
-
- if (tmp != mem_ref)
- emit_move_insn (copy_rtx (mem_ref), tmp);
-
- sequence = get_insns ();
- end_sequence ();
- return sequence;