diff options
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 185 |
1 files changed, 143 insertions, 42 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index e39e687edbb..ed4d74d0e51 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -4489,6 +4489,8 @@ static bool dwarf2out_ignore_block (const_tree); static void dwarf2out_global_decl (tree); static void dwarf2out_type_decl (tree, int); static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool); +static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree, + dw_die_ref); static void dwarf2out_abstract_function (tree); static void dwarf2out_var_location (rtx); static void dwarf2out_begin_function (tree); @@ -4746,6 +4748,10 @@ static GTY((param_is (struct dwarf_file_data))) htab_t file_table; The key is a DECL_UID() which is a unique number identifying each decl. */ static GTY ((param_is (struct die_struct))) htab_t decl_die_table; +/* A hash table of references to DIE's that describe COMMON blocks. + The key is DECL_UID() ^ die_parent. */ +static GTY ((param_is (struct die_struct))) htab_t common_block_die_table; + /* Node of the variable location list. */ struct var_loc_node GTY ((chain_next ("%h.next"))) { @@ -4958,6 +4964,8 @@ static void equate_type_number_to_die (tree, dw_die_ref); static hashval_t decl_die_table_hash (const void *); static int decl_die_table_eq (const void *, const void *); static dw_die_ref lookup_decl_die (tree); +static hashval_t common_block_die_table_hash (const void *); +static int common_block_die_table_eq (const void *, const void *); static hashval_t decl_loc_table_hash (const void *); static int decl_loc_table_eq (const void *, const void *); static var_loc_list *lookup_decl_loc (const_tree); @@ -13810,6 +13818,26 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) } +/* Returns a hash value for X (which really is a die_struct). */ + +static hashval_t +common_block_die_table_hash (const void *x) +{ + const_dw_die_ref d = (const_dw_die_ref) x; + return (hashval_t) d->decl_id ^ htab_hash_pointer (d->die_parent); +} + +/* Return nonzero if decl_id and die_parent of die_struct X is the same + as decl_id and die_parent of die_struct Y. */ + +static int +common_block_die_table_eq (const void *x, const void *y) +{ + const_dw_die_ref d = (const_dw_die_ref) x; + const_dw_die_ref e = (const_dw_die_ref) y; + return d->decl_id == e->decl_id && d->die_parent == e->die_parent; +} + /* Generate a DIE to represent a declared data object. */ static void @@ -13851,6 +13879,7 @@ gen_variable_die (tree decl, dw_die_ref context_die) tree field; dw_die_ref com_die; dw_loc_descr_ref loc; + die_node com_die_arg; var_die = lookup_decl_die (decl); if (var_die) @@ -13861,21 +13890,41 @@ gen_variable_die (tree decl, dw_die_ref context_die) if (loc) { if (off) - add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, + { + /* Optimize the common case. */ + if (loc->dw_loc_opc == DW_OP_addr + && loc->dw_loc_next == NULL + && GET_CODE (loc->dw_loc_oprnd1.v.val_addr) + == SYMBOL_REF) + loc->dw_loc_oprnd1.v.val_addr + = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); + else + add_loc_descr (&loc, + new_loc_descr (DW_OP_plus_uconst, off, 0)); + } add_AT_loc (var_die, DW_AT_location, loc); remove_AT (var_die, DW_AT_declaration); } } return; } + + if (common_block_die_table == NULL) + common_block_die_table + = htab_create_ggc (10, common_block_die_table_hash, + common_block_die_table_eq, NULL); + field = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0); - com_die = lookup_decl_die (com_decl); + com_die_arg.decl_id = DECL_UID (com_decl); + com_die_arg.die_parent = context_die; + com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg); loc = loc_descriptor_from_tree (com_decl); if (com_die == NULL) { const char *cnam = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (com_decl)); + void **slot; com_die = new_die (DW_TAG_common_block, context_die, decl); add_name_and_src_coords_attributes (com_die, com_decl); @@ -13889,7 +13938,9 @@ gen_variable_die (tree decl, dw_die_ref context_die) else if (DECL_EXTERNAL (decl)) add_AT_flag (com_die, DW_AT_declaration, 1); add_pubname_string (cnam, com_die); /* ??? needed? */ - equate_decl_number_to_die (com_decl, com_die); + com_die->decl_id = DECL_UID (com_decl); + slot = htab_find_slot (common_block_die_table, com_die, INSERT); + *slot = (void *) com_die; } else if (get_AT (com_die, DW_AT_location) == NULL && loc) { @@ -13905,7 +13956,17 @@ gen_variable_die (tree decl, dw_die_ref context_die) if (loc) { if (off) - add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, off, 0)); + { + /* Optimize the common case. */ + if (loc->dw_loc_opc == DW_OP_addr + && loc->dw_loc_next == NULL + && GET_CODE (loc->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF) + loc->dw_loc_oprnd1.v.val_addr + = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); + else + add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, + off, 0)); + } add_AT_loc (var_die, DW_AT_location, loc); } else if (DECL_EXTERNAL (decl)) @@ -14918,6 +14979,9 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth) if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) && !(is_fortran () && TREE_PUBLIC (decl))) ; + else if (TREE_CODE (decl) == IMPORTED_DECL) + dwarf2out_imported_module_or_decl_1 (decl, DECL_NAME (decl), + stmt, context_die); else gen_decl_die (decl, context_die); } @@ -15309,6 +15373,7 @@ gen_decl_die (tree decl, dw_die_ref context_die) break; case NAMESPACE_DECL: + case IMPORTED_DECL: gen_namespace_die (decl); break; @@ -15343,44 +15408,20 @@ dwarf2out_type_decl (tree decl, int local) } /* Output debug information for imported module or decl DECL. - NAME is non-NULL name in context if the decl has been renamed. - CHILD is true if decl is one of the renamed decls as part of - importing whole module. */ - + NAME is non-NULL name in the lexical block if the decl has been renamed. + LEXICAL_BLOCK is the lexical block (which TREE_CODE is a BLOCK) + that DECL belongs to. + LEXICAL_BLOCK_DIE is the DIE of LEXICAL_BLOCK. */ static void -dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, - bool child) +dwarf2out_imported_module_or_decl_1 (tree decl, + tree name, + tree lexical_block, + dw_die_ref lexical_block_die) { - dw_die_ref imported_die, at_import_die; - dw_die_ref scope_die; expanded_location xloc; + dw_die_ref imported_die = NULL; + dw_die_ref at_import_die; - if (debug_info_level <= DINFO_LEVEL_TERSE) - return; - - gcc_assert (decl); - - /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs. - We need decl DIE for reference and scope die. First, get DIE for the decl - itself. */ - - /* Get the scope die for decl context. Use comp_unit_die for global module - or decl. If die is not found for non globals, force new die. */ - if (context - && TYPE_P (context) - && !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE)) - return; - scope_die = get_context_die (context); - - if (child) - { - gcc_assert (scope_die->die_child); - gcc_assert (scope_die->die_child->die_tag == DW_TAG_imported_module); - gcc_assert (TREE_CODE (decl) != NAMESPACE_DECL); - scope_die = scope_die->die_child; - } - - /* For TYPE_DECL or CONST_DECL, lookup TREE_TYPE. */ if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL) { if (is_base_type (TREE_TYPE (decl))) @@ -15398,6 +15439,19 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, gcc_assert (at_import_die); } } + else if (TREE_CODE (decl) == IMPORTED_DECL) + { + tree imported_ns_decl; + /* IMPORTED_DECL nodes that are not imported namespace are just not + supported yet. */ + gcc_assert (DECL_INITIAL (decl) + && TREE_CODE (DECL_INITIAL (decl)) == NAMESPACE_DECL); + imported_ns_decl = DECL_INITIAL (decl); + at_import_die = lookup_decl_die (imported_ns_decl); + if (!at_import_die) + at_import_die = force_decl_die (imported_ns_decl); + gcc_assert (at_import_die); + } else { at_import_die = lookup_decl_die (decl); @@ -15421,20 +15475,66 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, } } - /* OK, now we have DIEs for decl as well as scope. Emit imported die. */ if (TREE_CODE (decl) == NAMESPACE_DECL) - imported_die = new_die (DW_TAG_imported_module, scope_die, context); + imported_die = new_die (DW_TAG_imported_module, + lexical_block_die, + lexical_block); else - imported_die = new_die (DW_TAG_imported_declaration, scope_die, context); + imported_die = new_die (DW_TAG_imported_declaration, + lexical_block_die, + lexical_block); xloc = expand_location (input_location); add_AT_file (imported_die, DW_AT_decl_file, lookup_filename (xloc.file)); add_AT_unsigned (imported_die, DW_AT_decl_line, xloc.line); if (name) - add_AT_string (imported_die, DW_AT_name, IDENTIFIER_POINTER (name)); + add_AT_string (imported_die, DW_AT_name, + IDENTIFIER_POINTER (name)); add_AT_die_ref (imported_die, DW_AT_import, at_import_die); } +/* Output debug information for imported module or decl DECL. + NAME is non-NULL name in context if the decl has been renamed. + CHILD is true if decl is one of the renamed decls as part of + importing whole module. */ + +static void +dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, + bool child) +{ + /* dw_die_ref at_import_die; */ + dw_die_ref scope_die; + + if (debug_info_level <= DINFO_LEVEL_TERSE) + return; + + gcc_assert (decl); + + /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs. + We need decl DIE for reference and scope die. First, get DIE for the decl + itself. */ + + /* Get the scope die for decl context. Use comp_unit_die for global module + or decl. If die is not found for non globals, force new die. */ + if (context + && TYPE_P (context) + && !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE)) + return; + scope_die = get_context_die (context); + + if (child) + { + gcc_assert (scope_die->die_child); + gcc_assert (scope_die->die_child->die_tag == DW_TAG_imported_module); + gcc_assert (TREE_CODE (decl) != NAMESPACE_DECL); + scope_die = scope_die->die_child; + } + + /* OK, now we have DIEs for decl as well as scope. Emit imported die. */ + dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die); + +} + /* Write the debugging output for DECL. */ void @@ -15519,6 +15619,7 @@ dwarf2out_decl (tree decl) break; case NAMESPACE_DECL: + case IMPORTED_DECL: if (debug_info_level <= DINFO_LEVEL_TERSE) return; if (lookup_decl_die (decl) != NULL) |