diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 70ee88419807..a76a0a89d292 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -109,7 +109,6 @@ typedef struct dw_loc_descr_struct *dw_loc_descr_ref; typedef struct dw_cfi_struct *dw_cfi_ref; typedef struct dw_fde_struct *dw_fde_ref; typedef union dw_cfi_oprnd_struct *dw_cfi_oprnd_ref; -typedef struct backchain *backchain_ref; /* Describe a double word constant value. */ typedef struct dw_double_const_struct @@ -197,7 +196,7 @@ typedef struct dw_cfi_struct dw_cfi_node; /* All call frame descriptions (FDE's) in the GCC generated DWARF - refer to a signle Common Information Entry (CIE), defined at + refer to a single Common Information Entry (CIE), defined at the beginning of the .debug_frame section. This used of a single CIE obviates the need to keep track of multiple CIE's in the DWARF generation routines below. */ @@ -227,17 +226,6 @@ typedef struct die_struct } die_node; -/* The structure for backchaining support, when structure tags are declared - before they are defined. */ - -typedef struct backchain - { - tree type; - dw_die_ref placeholder; - backchain_ref next; - } -backchain_t; - /* How to start an assembler comment. */ #ifndef ASM_COMMENT_START #define ASM_COMMENT_START ";#" @@ -567,10 +555,6 @@ static dw_die_ref int_base_type_die; declaration are. */ static tree dwarf_last_decl; -/* A list of DIE reference attributes values that need backchaining - support. */ -static backchain_ref backchain; - /* Forward declarations for functions defined in this file. */ static void gen_type_die (); static void add_type_attribute (); @@ -2088,23 +2072,6 @@ add_AT_section_offset (die, attr_kind, section) } } -/* Save a DIE reference attribute value to a DIE for later backchaining. */ -inline void -backchain_AT_die_ref (type, placeholder) - register tree type; - register dw_die_ref placeholder; -{ - register backchain_ref back = (backchain_ref) xmalloc (sizeof (backchain_t)); - if (back != NULL) - { - back->type = type; - back->placeholder = placeholder; - - back->next = backchain; - backchain = back; - } -} - /* Test if die refers to an external subroutine. */ inline int is_extern_subr_die (die) @@ -2220,6 +2187,62 @@ get_AT_hi_pc (die) return hi_pc; } +/* Remove the specified attribute if present. */ +inline void +remove_AT (die, attr_kind) + register dw_die_ref die; + register enum dwarf_attribute attr_kind; +{ + register dw_attr_ref a; + register dw_attr_ref removed = NULL;; + if (die != NULL) + { + if (die->die_attr->dw_attr == attr_kind) + { + removed = die->die_attr; + if (die->die_attr_last == die->die_attr) + die->die_attr_last = NULL; + die->die_attr = die->die_attr->dw_attr_next; + } + else for (a = die->die_attr; a->dw_attr_next != NULL; + a = a->dw_attr_next) + if (a->dw_attr_next->dw_attr == attr_kind) + { + removed = a->dw_attr_next; + if (die->die_attr_last == a->dw_attr_next) + die->die_attr_last = a; + a->dw_attr_next = a->dw_attr_next->dw_attr_next; + return; + } + if (removed) + free (removed); + } +} + +/* Discard the children of this DIE. */ +inline void +remove_children (die) + register dw_die_ref die; +{ + register dw_die_ref child_die = die->die_child; + die->die_child = NULL; + die->die_child_last = NULL; + while (child_die != NULL) + { + register dw_die_ref tmp_die = child_die; + register dw_attr_ref a; + child_die = child_die->die_sib; + + for (a = tmp_die->die_attr; a != NULL; ) + { + register dw_attr_ref tmp_a = a; + a = a->dw_attr_next; + free (tmp_a); + } + free (tmp_die); + } +} + /* Add a child DIE below its parent. */ inline void add_child_die (die, child_die) @@ -4557,6 +4580,8 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die) } else { + gen_type_die (type, context_die); + /* We have to get the type_main_variant here (and pass that to the `lookup_type_die' routine) because the ..._TYPE node we have might simply be a *copy* of some original type node (where the @@ -4567,17 +4592,8 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die) handles DIEs representing *main variants*, and it never even knows about non-main-variants.). */ mod_type_die = lookup_type_die (type_main_variant (type)); - - /* Normally, we assume that all types are defined before they are - referenced. If this is not the case, then mod_type_die will - be NULL here, and we must backchain. This can happen as the - result of a forward declaration of a structure tag. */ if (mod_type_die == NULL) - { - dw_die_ref placeholder_die = new_die (DW_TAG_padding, - context_die); - backchain_AT_die_ref (type, placeholder_die); - } + abort (); } } if (sub_die != NULL) @@ -4588,32 +4604,6 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die) return mod_type_die; } -/* Fix all unresolved die references that resulted from forward - declarations. */ -static void -resolve_backchains () -{ - register backchain_ref back; - - back = backchain; - while (back) - { - register dw_die_ref type_die; - - type_die = lookup_type_die (type_main_variant (back->type)); - - assert (type_die != NULL); - - /* ??? It would be cleaner to find the die attribute, and change - the val_dir_ref field to point to this new die. Just overwriting - the temporary die with the correct one is easier though, and seems - to work just as well. */ - memcpy (back->placeholder, type_die, sizeof (die_node)); - - back = back->next; - } -} - /* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is an enumerated type. */ inline int @@ -6118,7 +6108,7 @@ gen_subprogram_die (decl, context_die) { char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; register tree origin = decl_ultimate_origin (decl); - register dw_die_ref subr_die = new_die (DW_TAG_subprogram, context_die); + register dw_die_ref subr_die; register dw_loc_descr_ref fp_loc = NULL; register unsigned fp_reg; register tree type; @@ -6129,17 +6119,32 @@ gen_subprogram_die (decl, context_die) if (origin != NULL) { + subr_die = new_die (DW_TAG_subprogram, context_die); add_abstract_origin_attribute (subr_die, origin); } else if (old_die) { + register unsigned file_index + = lookup_filename (DECL_SOURCE_FILE (decl)); if (get_AT_flag (old_die, DW_AT_declaration) != 1) abort (); - add_AT_die_ref (subr_die, DW_AT_specification, old_die); - if (DECL_NAME (decl)) + + /* If the definition comes from the same place as the declaration, + use the old DIE. */ + if (get_AT_unsigned (old_die, DW_AT_decl_file) == file_index + && (get_AT_unsigned (old_die, DW_AT_decl_line) + == DECL_SOURCE_LINE (decl))) { - register unsigned file_index - = lookup_filename (DECL_SOURCE_FILE (decl)); + subr_die = old_die; + + /* Clear out the declaration attribute and the parm types. */ + remove_AT (subr_die, DW_AT_declaration); + remove_children (subr_die); + } + else + { + subr_die = new_die (DW_TAG_subprogram, context_die); + add_AT_die_ref (subr_die, DW_AT_specification, old_die); if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) add_AT_unsigned (subr_die, DW_AT_decl_file, file_index); if (get_AT_unsigned (old_die, DW_AT_decl_line) @@ -6150,6 +6155,7 @@ gen_subprogram_die (decl, context_die) } else { + subr_die = new_die (DW_TAG_subprogram, context_die); if (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)) { add_AT_flag (subr_die, DW_AT_external, 1); @@ -6657,6 +6663,10 @@ gen_struct_or_union_type_die (type, is_complete, context_die) equate_type_number_to_die (type, type_die); add_name_attribute (type_die, type_tag (type)); } + else if (is_complete) + remove_AT (type_die, DW_AT_declaration); + else + return; /* If this type has been completed, then give it a byte_size attribute and then give a list of members. */ @@ -6671,6 +6681,8 @@ gen_struct_or_union_type_die (type, is_complete, context_die) gen_member_die (type, type_die); } } + else + add_AT_flag (type_die, DW_AT_declaration, 1); } /* Generate a DIE for a subroutine _type_. */ @@ -6838,6 +6850,11 @@ gen_type_die (type, context_die) { gen_struct_or_union_type_die (type, is_complete, context_die); } + + /* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix + it up if it is ever completed. */ + if (! is_complete) + return; break; case VOID_TYPE: @@ -7076,18 +7093,6 @@ gen_decl_die (decl, context_die) { break; } - /* Before we describe the FUNCTION_DECL itself, make sure that we have - described its context. */ - origin = decl_class_context (decl); - if (origin && ! decl_ultimate_origin (decl)) - { - dw_die_ref old_die; - gen_type_die (origin, context_die); - /* We may have just generated the DIE we need; let's check. */ - old_die = lookup_decl_die (decl); - if (old_die && get_AT_flag (old_die, DW_AT_declaration) != 1) - break; - } /* Before we describe the FUNCTION_DECL itself, make sure that we have described its return type. */ @@ -7154,19 +7159,6 @@ gen_decl_die (decl, context_die) break; } - /* Before we describe the VAR_DECL itself, make sure that we have - described its context. */ - origin = decl_class_context (decl); - if (origin && ! decl_ultimate_origin (decl)) - { - dw_die_ref old_die; - gen_type_die (origin, context_die); - /* We may have just generated the DIE we need; let's check. */ - old_die = lookup_decl_die (decl); - if (old_die && get_AT_flag (old_die, DW_AT_declaration) != 1) - break; - } - /* Output any DIEs that are needed to specify the type of this data object. */ gen_type_die (TREE_TYPE (decl), context_die); @@ -7748,9 +7740,6 @@ dwarfout_init (asm_out_file, main_input_filename) /* clear the association between base types and their DIE's */ init_base_type_table (); - - /* clear the backchain list. */ - backchain = NULL; } /* Output stuff that dwarf requires at the end of every file, @@ -7758,9 +7747,6 @@ dwarfout_init (asm_out_file, main_input_filename) void dwarfout_finish () { - - resolve_backchains (); - /* Traverse the DIE tree and add sibling attributes to those DIE's that have children. */ add_sibling_attributes (comp_unit_die);