diff options
author | Dodji Seketeli <dodji@redhat.com> | 2009-09-23 16:07:13 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2009-09-23 18:07:13 +0200 |
commit | b646ba3f1c134c4fc22b000caff77725ccec1791 (patch) | |
tree | 716216bf133fc60984e49edb258a912ca31ba3e8 | |
parent | 4c6858252cf0b39482c1a436f6d9dcd7cc0a44f9 (diff) | |
download | gcc-b646ba3f1c134c4fc22b000caff77725ccec1791.zip gcc-b646ba3f1c134c4fc22b000caff77725ccec1791.tar.gz gcc-b646ba3f1c134c4fc22b000caff77725ccec1791.tar.bz2 |
re PR debug/41065 (DW_TAG_enumeration_type+DW_TAG_enumerator is sometimes missing)
Fix PR debug/41065
gcc/ChangeLog:
PR debug/41065
* function.h (types_used_by_vars_hash): Declare new hash table.
(types_used_by_vars_eq, types_used_by_var_decl_insert): Declare
equality and hash function for the hash table.
(types_used_by_cur_var_decl): Declare a new global chained list.
(types_used_by_var_decl_insert): Declare new function.
* function.c (types_used_by_vars_hash): Define the hashtable ...
(types_used_by_vars_eq, types_used_by_vars_do_hash): ... as well as
its equality and hash functions.
(hash_types_used_by_vars_entry): New hash helper.
(types_used_by_cur_var_decl): Define the global chained list.
(used_types_insert): Update the list of types used by the global
variable being parsed.
(types_used_by_var_decl_insert): Define new function.
* c-common.h (record_types_used_by_current_var_decl): Declare ...
* c-common.c (record_types_used_by_current_var_decl): ... new
function.
* c-decl.c (finish_decl): Record the types used by the global
variable declaration we've just parsed.
* dwarf2out.c (premark_used_types): Insert a new line between
comment and function.
(premark_used_types_helper): Fix comment.
(premark_types_used_by_global_vars_helper,
premark_types_used_by_global_vars): New functions.
(prune_unused_types): Do not prune types used by global variables.
gcc/cp/ChangeLog:
PR debug/41065
* decl.c (cp_finish_decl): Record the types used by the global
variable declaration we've just parsed.
gcc/testsuite/ChangeLog:
PR debug/41065
* gcc.dg/debug/dwarf2/global-used-types.c: New test.
From-SVN: r152085
-rw-r--r-- | gcc/c-common.c | 25 | ||||
-rw-r--r-- | gcc/c-common.h | 1 | ||||
-rw-r--r-- | gcc/c-decl.c | 7 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 9 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 51 | ||||
-rw-r--r-- | gcc/function.c | 81 | ||||
-rw-r--r-- | gcc/function.h | 22 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/debug/dwarf2/global-used-types-1.C | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/debug/dwarf2/global-used-types.c | 14 |
11 files changed, 232 insertions, 2 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c index 25c0c01..a9e1286 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -9182,6 +9182,31 @@ is_typedef_decl (tree x) && DECL_ORIGINAL_TYPE (x) != NULL_TREE); } +/* Record the types used by the current global variable declaration + being parsed, so that we can decide later to emit their debug info. + Those types are in types_used_by_cur_var_decl, and we are going to + store them in the types_used_by_vars_hash hash table. + DECL is the declaration of the global variable that has been parsed. */ + +void +record_types_used_by_current_var_decl (tree decl) +{ + gcc_assert (decl && DECL_P (decl) && TREE_STATIC (decl)); + + if (types_used_by_cur_var_decl) + { + tree node; + for (node = types_used_by_cur_var_decl; + node; + node = TREE_CHAIN (node)) + { + tree type = TREE_PURPOSE (node); + types_used_by_var_decl_insert (type, decl); + } + types_used_by_cur_var_decl = NULL; + } +} + /* The C and C++ parsers both use vectors to hold function arguments. For efficiency, we keep a cache of unused vectors. This is the cache. */ diff --git a/gcc/c-common.h b/gcc/c-common.h index 9b7905b..6a02e04 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -1130,6 +1130,7 @@ extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree); /* Not in c-omp.c; provided by the front end. */ extern bool c_omp_sharing_predetermined (tree); extern tree c_omp_remap_decl (tree, bool); +extern void record_types_used_by_current_var_decl (tree); /* In order for the format checking to accept the C frontend diagnostic framework extensions, you must include this file before diff --git a/gcc/c-decl.c b/gcc/c-decl.c index c44e35c..e237332 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -4064,6 +4064,13 @@ finish_decl (tree decl, location_t init_loc, tree init, if (asmspec_tree) asmspec = TREE_STRING_POINTER (asmspec_tree); + if (TREE_CODE (decl) == VAR_DECL + && TREE_STATIC (decl) + && global_bindings_p ()) + /* So decl is a global variable. Record the types it uses + so that we can decide later to emit debug info for them. */ + record_types_used_by_current_var_decl (decl); + /* If `start_decl' didn't like having an initialization, ignore it now. */ if (init != 0 && DECL_INITIAL (decl) == 0) init = 0; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ae3045e..338e725 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2009-09-23 Dodji Seketeli <dodji@redhat.com> + + PR debug/41065 + * decl.c (cp_finish_decl): Record the types used by the global + variable declaration we've just parsed. + 2009-09-22 Dodji Seketeli <dodji@redhat.com> * cp-lang.c (LANG_HOOKS_FUNCTION_PARAMETER_PACK_P, diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 614dbb0..407f734 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5801,6 +5801,15 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, type. */ else if (TREE_CODE (type) == ARRAY_TYPE) layout_type (type); + + if (!processing_template_decl + && TREE_STATIC (decl) + && !at_function_scope_p () + && current_function_decl == NULL) + /* So decl is a global variable or a static member of a + non local class. Record the types it uses + so that we can decide later to emit debug info for them. */ + record_types_used_by_current_var_decl (decl); } else if (TREE_CODE (decl) == FIELD_DECL && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type)) diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index a2e91d4..b8a0434 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -15649,10 +15649,11 @@ dwarf2out_abstract_function (tree decl) } /* Helper function of premark_used_types() which gets called through - htab_traverse_resize(). + htab_traverse. Marks the DIE of a given type in *SLOT as perennial, so it never gets marked as unused by prune_unused_types. */ + static int premark_used_types_helper (void **slot, void *data ATTRIBUTE_UNUSED) { @@ -15666,7 +15667,42 @@ premark_used_types_helper (void **slot, void *data ATTRIBUTE_UNUSED) return 1; } +/* Helper function of premark_types_used_by_global_vars which gets called + through htab_traverse. + + Marks the DIE of a given type in *SLOT as perennial, so it never gets + marked as unused by prune_unused_types. The DIE of the type is marked + only if the global variable using the type will actually be emitted. */ + +static int +premark_types_used_by_global_vars_helper (void **slot, + void *data ATTRIBUTE_UNUSED) +{ + struct types_used_by_vars_entry *entry; + dw_die_ref die; + + entry = (struct types_used_by_vars_entry *) *slot; + gcc_assert (entry->type != NULL + && entry->var_decl != NULL); + die = lookup_type_die (entry->type); + if (die) + { + /* Ask cgraph if the global variable really is to be emitted. + If yes, then we'll keep the DIE of ENTRY->TYPE. */ + struct varpool_node *node = varpool_node (entry->var_decl); + if (node->needed) + { + die->die_perennial_p = 1; + /* Keep the parent DIEs as well. */ + while ((die = die->die_parent) && die->die_perennial_p == 0) + die->die_perennial_p = 1; + } + } + return 1; +} + /* Mark all members of used_types_hash as perennial. */ + static void premark_used_types (void) { @@ -15674,6 +15710,16 @@ premark_used_types (void) htab_traverse (cfun->used_types_hash, premark_used_types_helper, NULL); } +/* Mark all members of types_used_by_vars_entry as perennial. */ + +static void +premark_types_used_by_global_vars (void) +{ + if (types_used_by_vars_hash) + htab_traverse (types_used_by_vars_hash, + premark_types_used_by_global_vars_helper, NULL); +} + /* Generate a DIE to represent a declared function (either file-scope or block-local). */ @@ -18776,6 +18822,9 @@ prune_unused_types (void) verify_marks_clear (node->die); #endif /* ENABLE_ASSERT_CHECKING */ + /* Mark types that are used in global variables. */ + premark_types_used_by_global_vars (); + /* Set the mark on nodes that are actually used. */ prune_unused_types_walk (comp_unit_die); for (node = limbo_die_list; node; node = node->next) diff --git a/gcc/function.c b/gcc/function.c index 6c9bea8..aaed57a 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -130,6 +130,10 @@ static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) htab_t epilogue_insn_hash; + +htab_t types_used_by_vars_hash = NULL; +tree types_used_by_cur_var_decl = NULL; + /* Forward declarations. */ static struct temp_slot *find_temp_slot_from_address (rtx); @@ -5426,6 +5430,7 @@ rest_of_handle_check_leaf_regs (void) } /* Insert a TYPE into the used types hash table of CFUN. */ + static void used_types_insert_helper (tree type, struct function *func) { @@ -5450,7 +5455,81 @@ used_types_insert (tree t) t = TREE_TYPE (t); t = TYPE_MAIN_VARIANT (t); if (debug_info_level > DINFO_LEVEL_NONE) - used_types_insert_helper (t, cfun); + { + if (cfun) + used_types_insert_helper (t, cfun); + else + /* So this might be a type referenced by a global variable. + Record that type so that we can later decide to emit its debug + information. */ + types_used_by_cur_var_decl = + tree_cons (t, NULL, types_used_by_cur_var_decl); + + } +} + +/* Helper to Hash a struct types_used_by_vars_entry. */ + +static hashval_t +hash_types_used_by_vars_entry (const struct types_used_by_vars_entry *entry) +{ + gcc_assert (entry && entry->var_decl && entry->type); + + return iterative_hash_object (entry->type, + iterative_hash_object (entry->var_decl, 0)); +} + +/* Hash function of the types_used_by_vars_entry hash table. */ + +hashval_t +types_used_by_vars_do_hash (const void *x) +{ + const struct types_used_by_vars_entry *entry = + (const struct types_used_by_vars_entry *) x; + + return hash_types_used_by_vars_entry (entry); +} + +/*Equality function of the types_used_by_vars_entry hash table. */ + +int +types_used_by_vars_eq (const void *x1, const void *x2) +{ + const struct types_used_by_vars_entry *e1 = + (const struct types_used_by_vars_entry *) x1; + const struct types_used_by_vars_entry *e2 = + (const struct types_used_by_vars_entry *)x2; + + return (e1->var_decl == e2->var_decl && e1->type == e2->type); +} + +/* Inserts an entry into the types_used_by_vars_hash hash table. */ + +void +types_used_by_var_decl_insert (tree type, tree var_decl) +{ + if (type != NULL && var_decl != NULL) + { + void **slot; + struct types_used_by_vars_entry e; + e.var_decl = var_decl; + e.type = type; + if (types_used_by_vars_hash == NULL) + types_used_by_vars_hash = + htab_create_ggc (37, types_used_by_vars_do_hash, + types_used_by_vars_eq, NULL); + slot = htab_find_slot_with_hash (types_used_by_vars_hash, &e, + hash_types_used_by_vars_entry (&e), INSERT); + if (*slot == NULL) + { + struct types_used_by_vars_entry *entry; + entry = (struct types_used_by_vars_entry*) ggc_alloc + (sizeof (struct types_used_by_vars_entry)); + entry->type = type; + entry->var_decl = var_decl; + *slot = entry; + } + } } struct rtl_opt_pass pass_leaf_regs = diff --git a/gcc/function.h b/gcc/function.h index 72aad00..4825d16 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -622,6 +622,28 @@ extern int virtuals_instantiated; /* Nonzero if at least one trampoline has been created. */ extern int trampolines_created; +struct GTY(()) types_used_by_vars_entry { + tree type; + tree var_decl; +}; + +/* Hash table making the relationship between a global variable + and the types it references in its initializer. The key of the + entry is a referenced type, and the value is the DECL of the global + variable. types_use_by_vars_do_hash and types_used_by_vars_eq below are + the hash and equality functions to use for this hash table. */ +extern GTY((param_is (struct types_used_by_vars_entry))) htab_t + types_used_by_vars_hash; + +hashval_t types_used_by_vars_do_hash (const void*); +int types_used_by_vars_eq (const void *, const void *); +void types_used_by_var_decl_insert (tree type, tree var_decl); + +/* During parsing of a global variable, this linked list points to + the list of types referenced by the global variable. */ +extern GTY(()) tree types_used_by_cur_var_decl; + + /* cfun shouldn't be set directly; use one of these functions instead. */ extern void set_cfun (struct function *new_cfun); extern void push_cfun (struct function *new_cfun); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5b611f7..5fa33fd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ + 2009-09-23 Dodji Seketeli <dodji@redhat.com> + + PR debug/41065 + * gcc.dg/debug/dwarf2/global-used-types.c: New test. + 2009-09-23 Andreas Schwab <schwab@redhat.com> * lib/profopt.exp (profopt-get-options): Set tool_flags for diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/global-used-types-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/global-used-types-1.C new file mode 100644 index 0000000..bad08ed --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/global-used-types-1.C @@ -0,0 +1,13 @@ +// Contributed by Dodji Seketeli <dodji@redhat.com> +// { dg-options "-g -dA -fno-merge-debug-strings" } +// { dg-do compile } +// { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_enumeration_type" 1 } } +// { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_enumerator" 2 } } +// { dg-final { scan-assembler-times "ascii \"a.0\"\[\t \]+.*?DW_AT_name" 1 } } +// { dg-final { scan-assembler-times "ascii \"b.0\"\[\t \]+.*?DW_AT_name" 1 } } + +struct foo +{ + enum { a, b }; +}; +char s[foo::b]; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/global-used-types.c b/gcc/testsuite/gcc.dg/debug/dwarf2/global-used-types.c new file mode 100644 index 0000000..1c2d403 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/global-used-types.c @@ -0,0 +1,14 @@ +/* + Contributed by Dodji Seketeli <dodji@redhat.com> + { dg-options "-g -dA -fno-merge-debug-strings" } + { dg-do compile } + { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_enumeration_type" 1 } } + { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_enumerator" 2 } } + { dg-final { scan-assembler-times "ascii \"a.0\"\[\t \]+.*?DW_AT_name" 1 } } + { dg-final { scan-assembler-times "ascii \"b.0\"\[\t \]+.*?DW_AT_name" 1 } } + */ + +enum { a, b }; + +int v = a; +char s[b]; |