aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/coverage.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/coverage.c')
-rw-r--r--gcc-4.9/gcc/coverage.c162
1 files changed, 147 insertions, 15 deletions
diff --git a/gcc-4.9/gcc/coverage.c b/gcc-4.9/gcc/coverage.c
index bfc5731ff..93f394d84 100644
--- a/gcc-4.9/gcc/coverage.c
+++ b/gcc-4.9/gcc/coverage.c
@@ -177,6 +177,10 @@ static unsigned num_cpp_defines = 0;
static struct str_list *cpp_includes_head = NULL, *cpp_includes_tail = NULL;
static unsigned num_cpp_includes = 0;
+/* List of lines read from -fprofile-generate-buildinfo=filename. */
+struct str_list *build_info_array_head = NULL, *build_info_array_tail = NULL;
+static unsigned num_build_info = 0;
+
/* True if the current module has any asm statements. */
static bool has_asm_statement;
@@ -805,6 +809,25 @@ read_counts_file (const char *da_file_name, unsigned module_id)
sum.ctrs[GCOV_COUNTER_ARCS].histogram);
new_summary = 0;
}
+ else if (tag == GCOV_TAG_BUILD_INFO)
+ {
+ /* Build info strings are not used by the compiler, read and
+ ignore. */
+ gcov_unsigned_t num_strings;
+ char **build_info_strings = gcov_read_build_info (length,
+ &num_strings);
+ for (unsigned i = 0; i < num_strings; i++)
+ free (build_info_strings[i]);
+ free (build_info_strings);
+ }
+ else if (tag == GCOV_TAG_COMDAT_ZERO_FIXUP)
+ {
+ /* Zero-profile fixup flags are not used by the compiler, read and
+ ignore. */
+ gcov_unsigned_t num_fn;
+ int *zero_fixup_flags = gcov_read_comdat_zero_fixup (length, &num_fn);
+ free (zero_fixup_flags);
+ }
else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
{
counts_entry_t **slot, *entry, elt;
@@ -1761,6 +1784,7 @@ build_info_type (tree type, tree fn_info_ptr_type)
{
tree field, fields = NULL_TREE;
tree merge_fn_type, mod_type;
+ tree string_type, string_ptr_type;
/* Version ident */
field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
@@ -1828,6 +1852,17 @@ build_info_type (tree type, tree fn_info_ptr_type)
DECL_CHAIN (field) = fields;
fields = field;
+ /* build_info string array */
+ string_type = build_pointer_type (
+ build_qualified_type (char_type_node,
+ TYPE_QUAL_CONST));
+ string_ptr_type = build_pointer_type
+ (build_qualified_type (string_type, TYPE_QUAL_CONST));
+ field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ NULL_TREE, string_ptr_type);
+ DECL_CHAIN (field) = fields;
+ fields = field;
+
finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
}
@@ -2227,6 +2262,96 @@ build_gcov_module_info_value (tree mod_type)
return mod_info;
}
+/* Returns the value of the build info string read earlier. */
+
+static tree
+build_gcov_build_info_value (void)
+{
+ tree build_info;
+ tree value = NULL_TREE;
+ tree string_type, index_type, string_array_type;
+ vec<constructor_elt,va_gc> *v = NULL;
+ char name_buf[50];
+
+ string_type = build_pointer_type (
+ build_qualified_type (char_type_node,
+ TYPE_QUAL_CONST));
+ index_type = build_index_type (build_int_cst (NULL_TREE, num_build_info));
+ string_array_type = build_array_type (string_type, index_type);
+
+ build_str_array_value (string_type, &v,
+ build_info_array_head);
+ value = build_constructor (string_array_type, v);
+
+ build_info = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ NULL_TREE, TREE_TYPE (value));
+ TREE_STATIC (build_info) = 1;
+ ASM_GENERATE_INTERNAL_LABEL (name_buf, "BUILDINFO", 0);
+ DECL_NAME (build_info) = get_identifier (name_buf);
+ DECL_INITIAL (build_info) = value;
+
+ /* Build structure. */
+ varpool_finalize_decl (build_info);
+
+ return build_info;
+}
+
+/* Add S to the end of the string-list, the head and tail of which are
+ pointed-to by HEAD and TAIL, respectively. */
+
+static void
+str_list_append (struct str_list **head, struct str_list **tail, const char *s)
+{
+ struct str_list *e = XNEW (struct str_list);
+ e->str = XNEWVEC (char, strlen (s) + 1);
+ strcpy (e->str, s);
+ e->next = NULL;
+ if (*tail)
+ (*tail)->next = e;
+ else
+ *head = e;
+ *tail = e;
+}
+
+/* Read file specified to -fprofile-generate-buildinfo=filename option and
+ create a list of strings to include in build_info array. */
+
+static void
+read_buildinfo (void)
+{
+ char buf[1024];
+ FILE *buildinfo = fopen (flag_profile_generate_buildinfo, "r");
+ if (!buildinfo)
+ {
+ error ("could not open -fprofile-generate-buildinfo file %qs: %m",
+ flag_profile_generate_buildinfo);
+ }
+
+ while (fgets (buf, sizeof buf, buildinfo) != NULL)
+ {
+ /* Remove end of line. */
+ int len = strlen (buf);
+ if (len >= 1 && buf[len - 1] =='\n')
+ buf[len - 1] = '\0';
+ str_list_append (&build_info_array_head, &build_info_array_tail, buf);
+ num_build_info++;
+ }
+ /* Terminate with an empty string. */
+ str_list_append (&build_info_array_head, &build_info_array_tail, "");
+ num_build_info++;
+ if (ferror (buildinfo))
+ {
+ error ("error reading -fprofile-generate-buildinfo file %qs: %m",
+ flag_profile_generate_buildinfo);
+ }
+
+ if (fclose (buildinfo))
+ {
+ error ("could not close -fprofile-generate-buildinfo file %qs: %m",
+ flag_profile_generate_buildinfo);
+ }
+}
+
/* Returns a CONSTRUCTOR for the gcov_info object. INFO_TYPE is the
gcov_info structure type, FN_ARY is the array of pointers to
function info objects. */
@@ -2238,6 +2363,7 @@ build_info (tree info_type, tree fn_ary)
tree merge_fn_type, n_funcs;
unsigned ix;
tree mod_value = NULL_TREE;
+ tree buildinfo_value = NULL_TREE;
tree filename_string;
int da_file_name_len;
vec<constructor_elt, va_gc> *v1 = NULL;
@@ -2320,6 +2446,20 @@ build_info (tree info_type, tree fn_ary)
build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary));
info_fields = DECL_CHAIN (info_fields);
+ /* build_info string array */
+ if (flag_profile_generate_buildinfo)
+ read_buildinfo ();
+ if (num_build_info)
+ {
+ buildinfo_value = build_gcov_build_info_value ();
+ CONSTRUCTOR_APPEND_ELT (v1, info_fields,
+ build1 (ADDR_EXPR, TREE_TYPE (info_fields),
+ buildinfo_value));
+ }
+ else
+ CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
+ info_fields = DECL_CHAIN (info_fields);
+
gcc_assert (!info_fields);
return build_constructor (info_type, v1);
}
@@ -2846,22 +2986,9 @@ coverage_finish (void)
da_file_name = NULL;
}
-/* Add S to the end of the string-list, the head and tail of which are
- pointed-to by HEAD and TAIL, respectively. */
+extern bool is_kernel_build;
-static void
-str_list_append (struct str_list **head, struct str_list **tail, const char *s)
-{
- struct str_list *e = XNEW (struct str_list);
- e->str = XNEWVEC (char, strlen (s) + 1);
- strcpy (e->str, s);
- e->next = NULL;
- if (*tail)
- (*tail)->next = e;
- else
- *head = e;
- *tail = e;
-}
+#define KERNEL_BUILD_PREDEF_STRING "__KERNEL__"
/* Copies the macro def or undef CPP_DEF and saves the copy
in a list. IS_DEF is a flag indicating if CPP_DEF represents
@@ -2875,6 +3002,11 @@ coverage_note_define (const char *cpp_def, bool is_def)
strcpy (s + 1, cpp_def);
str_list_append (&cpp_defines_head, &cpp_defines_tail, s);
num_cpp_defines++;
+
+ /* When -D__KERNEL__ is in the option list, we assume this is
+ compilation for Linux Kernel. */
+ if (!strcmp(cpp_def, KERNEL_BUILD_PREDEF_STRING))
+ is_kernel_build = is_def;
}
/* Copies the -imacro/-include FILENAME and saves the copy in a list. */