diff options
Diffstat (limited to 'gcc-4.4.0/gcc/dwarf2out.c')
-rw-r--r-- | gcc-4.4.0/gcc/dwarf2out.c | 551 |
1 files changed, 480 insertions, 71 deletions
diff --git a/gcc-4.4.0/gcc/dwarf2out.c b/gcc-4.4.0/gcc/dwarf2out.c index 606d30186..deac83a7e 100644 --- a/gcc-4.4.0/gcc/dwarf2out.c +++ b/gcc-4.4.0/gcc/dwarf2out.c @@ -94,6 +94,10 @@ along with GCC; see the file COPYING3. If not see static void dwarf2out_source_line (unsigned int, const char *, int, bool); #endif +/* True if generating only the minimum line table (-gmlt). */ +#define GENERATE_MINIMUM_LINE_TABLE (debug_info_level == DINFO_LEVEL_TERSE \ + && generate_debug_line_table) + #ifndef DWARF2_FRAME_INFO # ifdef DWARF2_DEBUGGING_INFO # define DWARF2_FRAME_INFO \ @@ -194,6 +198,8 @@ static GTY(()) section *debug_line_section; static GTY(()) section *debug_loc_section; static GTY(()) section *debug_pubnames_section; static GTY(()) section *debug_pubtypes_section; +static GTY(()) section *debug_dcall_section; +static GTY(()) section *debug_vcall_section; static GTY(()) section *debug_str_section; static GTY(()) section *debug_ranges_section; static GTY(()) section *debug_frame_section; @@ -4245,17 +4251,11 @@ new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1, static inline dw_loc_descr_ref new_reg_loc_descr (unsigned int reg, unsigned HOST_WIDE_INT offset) { - if (offset) - { - if (reg <= 31) - return new_loc_descr (DW_OP_breg0 + reg, offset, 0); - else - return new_loc_descr (DW_OP_bregx, reg, offset); - } - else if (reg <= 31) - return new_loc_descr (DW_OP_reg0 + reg, 0, 0); + if (reg <= 31) + return new_loc_descr ((enum dwarf_location_atom) (DW_OP_breg0 + reg), + offset, 0); else - return new_loc_descr (DW_OP_regx, reg, 0); + return new_loc_descr (DW_OP_bregx, reg, offset); } /* Add a location description term to a location description expression. */ @@ -4930,7 +4930,11 @@ 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_direct_call (tree); +static void dwarf2out_virtual_call_token (tree, int); +static void dwarf2out_virtual_call (int); static void dwarf2out_begin_function (tree); +static void dwarf2out_set_name (tree, tree); /* The debug hooks structure. */ @@ -4964,6 +4968,10 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = debug_nothing_int, /* handle_pch */ dwarf2out_var_location, dwarf2out_switch_text_section, + dwarf2out_direct_call, + dwarf2out_virtual_call_token, + dwarf2out_virtual_call, + dwarf2out_set_name, 1 /* start_end_main_source_file */ }; #endif @@ -5340,6 +5348,48 @@ static GTY(()) bool have_location_lists; /* Unique label counter. */ static GTY(()) unsigned int loclabel_num; +/* Unique label counter for point-of-call tables. */ +static GTY (()) unsigned int poc_label_num; + +/* The direct call table structure. */ + +typedef struct dcall_struct GTY (()) +{ + unsigned int poc_label_num; + tree poc_decl; + dw_die_ref targ_die; +} +dcall_entry; + +DEF_VEC_O(dcall_entry); +DEF_VEC_ALLOC_O(dcall_entry, gc); + +/* The virtual call table structure. */ + +typedef struct vcall_struct GTY (()) +{ + unsigned int poc_label_num; + unsigned int vtable_slot; +} +vcall_entry; + +DEF_VEC_O(vcall_entry); +DEF_VEC_ALLOC_O(vcall_entry, gc); + +/* Pointers to the direct and virtual call tables. */ +static GTY (()) VEC (dcall_entry, gc) * dcall_table; +static GTY (()) VEC (vcall_entry, gc) * vcall_table; + +/* A hash table to map INSN_UIDs to vtable slot indexes. */ + +struct vcall_insn GTY (()) +{ + int insn_uid; + unsigned int vtable_slot; +}; + +static GTY ((param_is (struct vcall_insn))) htab_t vcall_insn_table; + #ifdef DWARF2_DEBUGGING_INFO /* Record whether the function being analyzed contains inlined functions. */ static int current_function_has_inlines; @@ -5517,7 +5567,8 @@ static void add_arange (tree, dw_die_ref); static void output_aranges (void); static unsigned int add_ranges_num (int); static unsigned int add_ranges (const_tree); -static unsigned int add_ranges_by_labels (const char *, const char *); +static void add_ranges_by_labels (dw_die_ref, const char *, const char *, + bool *); static void output_ranges (void); static void output_line_info (void); static void output_file_names (void); @@ -5662,6 +5713,12 @@ static int maybe_emit_file (struct dwarf_file_data *fd); #ifndef DEBUG_PUBNAMES_SECTION #define DEBUG_PUBNAMES_SECTION ".debug_pubnames" #endif +#ifndef DEBUG_DCALL_SECTION +#define DEBUG_DCALL_SECTION ".debug_dcall" +#endif +#ifndef DEBUG_VCALL_SECTION +#define DEBUG_VCALL_SECTION ".debug_vcall" +#endif #ifndef DEBUG_STR_SECTION #define DEBUG_STR_SECTION ".debug_str" #endif @@ -6386,12 +6443,9 @@ debug_str_eq (const void *x1, const void *x2) (const char *)x2) == 0; } -/* Add a string attribute value to a DIE. */ - -static inline void -add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str) +static struct indirect_string_node * +find_AT_string (const char *str) { - dw_attr_node attr; struct indirect_string_node *node; void **slot; @@ -6412,6 +6466,18 @@ add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str) node = (struct indirect_string_node *) *slot; node->refcount++; + return node; +} + +/* Add a string attribute value to a DIE. */ + +static inline void +add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str) +{ + dw_attr_node attr; + struct indirect_string_node *node; + + node = find_AT_string (str); attr.dw_attr = attr_kind; attr.dw_attr_val.val_class = dw_val_class_str; @@ -8995,6 +9061,12 @@ copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, htab_t decl_table) entry = (struct decl_table_entry *) *slot; return entry->copy; } + + /* Record in DECL_TABLE that DIE has been copied to UNIT. */ + entry = XCNEW (struct decl_table_entry); + entry->orig = die; + entry->copy = NULL; + *slot = entry; } if (parent != NULL) @@ -9010,17 +9082,12 @@ copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, htab_t decl_table) copy = clone_as_declaration (die); add_child_die (new_parent, copy); - /* Make sure the copy is marked as part of the type unit. */ if (decl_table != NULL) - copy->die_mark = 1; - - if (slot != NULL) { - /* Record in DECL_TABLE that DIE has been copied to UNIT. */ - entry = XCNEW (struct decl_table_entry); - entry->orig = die; + /* Make sure the copy is marked as part of the type unit. */ + copy->die_mark = 1; + /* Record the pointer to the copy. */ entry->copy = copy; - *slot = entry; } return copy; @@ -10312,10 +10379,12 @@ add_ranges (const_tree block) /* Add a new entry to .debug_ranges corresponding to a pair of labels. */ -static unsigned int -add_ranges_by_labels (const char *begin, const char *end) +static void +add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end, + bool *added) { unsigned int in_use = ranges_by_label_in_use; + unsigned int offset; if (in_use == ranges_by_label_allocated) { @@ -10332,7 +10401,12 @@ add_ranges_by_labels (const char *begin, const char *end) ranges_by_label[in_use].end = end; ranges_by_label_in_use = in_use + 1; - return add_ranges_num (-(int)in_use - 1); + offset = add_ranges_num (-(int)in_use - 1); + if (!*added) + { + add_AT_range_list (die, DW_AT_ranges, offset); + *added = true; + } } static void @@ -11028,6 +11102,128 @@ output_line_info (void) /* Output the marker for the end of the line number info. */ ASM_OUTPUT_LABEL (asm_out_file, l2); } + +/* Return the size of the .debug_dcall table for the compilation unit. */ + +static unsigned long +size_of_dcall_table (void) +{ + unsigned long size; + unsigned int i; + dcall_entry *p; + tree last_poc_decl = NULL; + + /* Header: version + debug info section pointer + pointer size. */ + size = 2 + DWARF_OFFSET_SIZE + 1; + + /* Each entry: code label + DIE offset. */ + for (i = 0; VEC_iterate (dcall_entry, dcall_table, i, p); i++) + { + gcc_assert (p->targ_die != NULL); + /* Insert a "from" entry when the point-of-call DIE offset changes. */ + if (p->poc_decl != last_poc_decl) + { + dw_die_ref poc_die = lookup_decl_die (p->poc_decl); + last_poc_decl = p->poc_decl; + if (poc_die) + size += (DWARF_OFFSET_SIZE + + size_of_uleb128 (poc_die->die_offset)); + } + size += DWARF_OFFSET_SIZE + size_of_uleb128 (p->targ_die->die_offset); + } + + return size; +} + +/* Output the direct call table used to disambiguate PC values when + identical function have been merged. */ + +static void +output_dcall_table (void) +{ + unsigned i; + unsigned long dcall_length = size_of_dcall_table (); + dcall_entry *p; + char poc_label[MAX_ARTIFICIAL_LABEL_BYTES]; + tree last_poc_decl = NULL; + + if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); + dw2_asm_output_data (DWARF_OFFSET_SIZE, dcall_length, + "Length of Direct Call Table"); + dw2_asm_output_data (2, 4, "Version number"); + dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label, + debug_info_section, + "Offset of Compilation Unit Info"); + dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)"); + + for (i = 0; VEC_iterate (dcall_entry, dcall_table, i, p); i++) + { + /* Insert a "from" entry when the point-of-call DIE offset changes. */ + if (p->poc_decl != last_poc_decl) + { + dw_die_ref poc_die = lookup_decl_die (p->poc_decl); + last_poc_decl = p->poc_decl; + if (poc_die) + { + dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, "New caller"); + dw2_asm_output_data_uleb128 (poc_die->die_offset, + "Caller DIE offset"); + } + } + ASM_GENERATE_INTERNAL_LABEL (poc_label, "LPOC", p->poc_label_num); + dw2_asm_output_addr (DWARF_OFFSET_SIZE, poc_label, "Point of call"); + dw2_asm_output_data_uleb128 (p->targ_die->die_offset, + "Callee DIE offset"); + } +} + +/* Return the size of the .debug_vcall table for the compilation unit. */ + +static unsigned long +size_of_vcall_table (void) +{ + unsigned long size; + unsigned int i; + vcall_entry *p; + + /* Header: version + pointer size. */ + size = 2 + 1; + + /* Each entry: code label + vtable slot index. */ + for (i = 0; VEC_iterate (vcall_entry, vcall_table, i, p); i++) + size += DWARF_OFFSET_SIZE + size_of_uleb128 (p->vtable_slot); + + return size; +} + +/* Output the virtual call table used to disambiguate PC values when + identical function have been merged. */ + +static void +output_vcall_table (void) +{ + unsigned i; + unsigned long vcall_length = size_of_vcall_table (); + vcall_entry *p; + char poc_label[MAX_ARTIFICIAL_LABEL_BYTES]; + + if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); + dw2_asm_output_data (DWARF_OFFSET_SIZE, vcall_length, + "Length of Virtual Call Table"); + dw2_asm_output_data (2, 4, "Version number"); + dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)"); + + for (i = 0; VEC_iterate (vcall_entry, vcall_table, i, p); i++) + { + ASM_GENERATE_INTERNAL_LABEL (poc_label, "LPOC", p->poc_label_num); + dw2_asm_output_addr (DWARF_OFFSET_SIZE, poc_label, "Point of call"); + dw2_asm_output_data_uleb128 (p->vtable_slot, "Vtable slot"); + } +} /* Given a pointer to a tree node for some base type, return a pointer to a DIE that describes the given type. @@ -11466,7 +11662,13 @@ reg_loc_descriptor (rtx rtl, enum var_init_status initialized) static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int regno, enum var_init_status initialized) { - dw_loc_descr_ref reg_loc_descr = new_reg_loc_descr (regno, 0); + dw_loc_descr_ref reg_loc_descr; + + if (regno <= 31) + reg_loc_descr + = new_loc_descr ((enum dwarf_location_atom) (DW_OP_reg0 + regno), 0, 0); + else + reg_loc_descr = new_loc_descr (DW_OP_regx, regno, 0); if (initialized == VAR_INIT_STATUS_UNINITIALIZED) add_loc_descr (®_loc_descr, new_loc_descr (DW_OP_GNU_uninit, 0, 0)); @@ -13505,6 +13707,31 @@ loc_by_reference (dw_loc_descr_ref loc, tree decl) || !DECL_BY_REFERENCE (decl)) return loc; + /* If loc is DW_OP_reg{0...31,x}, don't add DW_OP_deref, instead + change it into corresponding DW_OP_breg{0...31,x} 0. Then the + location expression is considered to be address of a memory location, + rather than the register itself. */ + if (((loc->dw_loc_opc >= DW_OP_reg0 && loc->dw_loc_opc <= DW_OP_reg31) + || loc->dw_loc_opc == DW_OP_regx) + && (loc->dw_loc_next == NULL + || (loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_uninit + && loc->dw_loc_next->dw_loc_next == NULL))) + { + if (loc->dw_loc_opc == DW_OP_regx) + { + loc->dw_loc_opc = DW_OP_bregx; + loc->dw_loc_oprnd2.v.val_int = 0; + } + else + { + loc->dw_loc_opc + = (enum dwarf_location_atom) + (loc->dw_loc_opc + (DW_OP_breg0 - DW_OP_reg0)); + loc->dw_loc_oprnd1.v.val_int = 0; + } + return loc; + } + size = int_size_in_bytes (TREE_TYPE (decl)); if (size > DWARF2_ADDR_SIZE || size == -1) return 0; @@ -14356,7 +14583,8 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl) if (! DECL_ARTIFICIAL (decl)) add_src_coords_attributes (die, decl); - if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) + if (!GENERATE_MINIMUM_LINE_TABLE + && (TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) && TREE_PUBLIC (decl) && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !DECL_ABSTRACT (decl) @@ -14610,6 +14838,22 @@ decl_start_label (tree decl) return fnname; } #endif + +/* Returns the DIE for a context. */ + +static inline dw_die_ref +get_context_die (tree context) +{ + if (context) + { + /* Find die that represents this context. */ + if (TYPE_P (context)) + return force_type_die (context); + else + return force_decl_die (context); + } + return comp_unit_die; +} /* These routines generate the internal representation of the DIE's for the compilation unit. Debugging information is collected by walking @@ -15451,8 +15695,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) FUNC_LABEL_ID (cfun)); add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id); - add_pubname (decl, subr_die); - add_arange (decl, subr_die); + /* If we're generating minimum line tables (-gmlt), don't output + pubnames or aranges. */ + if (!GENERATE_MINIMUM_LINE_TABLE) + { + add_pubname (decl, subr_die); + add_arange (decl, subr_die); + } } else { /* Do nothing for now; maybe need to duplicate die, one for @@ -16483,6 +16732,17 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die, statement. */ TREE_ASM_WRITTEN (type) = 1; + /* Figure out the proper context for the basis type. If it is + local to a function, use NULL for now; it will be fixed up + in decls_for_scope. */ + if (TYPE_STUB_DECL (TREE_TYPE (type)) != NULL_TREE) + { + if (decl_function_context (TYPE_STUB_DECL (TREE_TYPE (type)))) + context_die = NULL; + else + context_die = get_context_die (TYPE_CONTEXT (TREE_TYPE (type))); + } + /* For these types, all that is required is that we output a DIE (or a set of DIEs) to represent the "basis" type. */ gen_type_die_with_usage (TREE_TYPE (type), context_die, @@ -16663,7 +16923,10 @@ gen_block_die (tree stmt, dw_die_ref context_die, int depth) if (must_output_die) { if (inlined_func) - gen_inlined_subroutine_die (stmt, context_die, depth); + { + if (! BLOCK_ABSTRACT (stmt)) + gen_inlined_subroutine_die (stmt, context_die, depth); + } else gen_lexical_block_die (stmt, context_die, depth); } @@ -16718,14 +16981,18 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth) declared directly within this block but not within any nested sub-blocks. Also, nested function and tag DIEs have been generated with a parent of NULL; fix that up now. */ - for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl)) - process_scope_var (stmt, decl, NULL_TREE, context_die); - for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++) - process_scope_var (stmt, NULL, BLOCK_NONLOCALIZED_VAR (stmt, i), - context_die); + if (debug_info_level > DINFO_LEVEL_TERSE) + { + for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl)) + process_scope_var (stmt, decl, NULL_TREE, context_die); + for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++) + process_scope_var (stmt, NULL, BLOCK_NONLOCALIZED_VAR (stmt, i), + context_die); + } - /* If we're at -g1, we're not interested in subblocks. */ - if (debug_info_level <= DINFO_LEVEL_TERSE) + /* If we're at -g1 and not generating minimal line tables, + we're not interested in subblocks. */ + if (!generate_debug_line_table && debug_info_level <= DINFO_LEVEL_TERSE) return; /* Output the DIEs to represent all sub-blocks (and the items declared @@ -16755,22 +17022,6 @@ is_redundant_typedef (const_tree decl) return 0; } -/* Returns the DIE for a context. */ - -static inline dw_die_ref -get_context_die (tree context) -{ - if (context) - { - /* Find die that represents this context. */ - if (TYPE_P (context)) - return force_type_die (context); - else - return force_decl_die (context); - } - return comp_unit_die; -} - /* Returns the DIE for decl. A DIE will always be returned. */ static dw_die_ref @@ -16813,6 +17064,10 @@ force_decl_die (tree decl) dwarf2out_decl (decl); break; + case TRANSLATION_UNIT_DECL: + decl_die = comp_unit_die; + break; + default: gcc_unreachable (); } @@ -17538,6 +17793,128 @@ maybe_emit_file (struct dwarf_file_data * fd) return fd->emitted_number; } +/* Called by the final INSN scan whenever we see a direct function call. + Make an entry into the direct call table, recording the point of call + and a reference to the target function's debug entry. */ + +static void +dwarf2out_direct_call (tree targ) +{ + dcall_entry e; + tree origin = decl_ultimate_origin (targ); + + /* If this is a clone, use the abstract origin as the target. */ + if (origin) + targ = origin; + + e.poc_label_num = poc_label_num++; + e.poc_decl = current_function_decl; + e.targ_die = force_decl_die (targ); + VEC_safe_push (dcall_entry, gc, dcall_table, &e); + + /* Drop a label at the return point to mark the point of call. */ + ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LPOC", e.poc_label_num); +} + +/* Returns a hash value for X (which really is a struct vcall_insn). */ + +static hashval_t +vcall_insn_table_hash (const void *x) +{ + return (hashval_t) ((const struct vcall_insn *) x)->insn_uid; +} + +/* Return nonzero if insn_uid of struct vcall_insn *X is the same as + insnd_uid of *Y. */ + +static int +vcall_insn_table_eq (const void *x, const void *y) +{ + return (((const struct vcall_insn *) x)->insn_uid + == ((const struct vcall_insn *) y)->insn_uid); +} + +/* Called when lowering indirect calls to RTL. We make a note of INSN_UID + and the OBJ_TYPE_REF_TOKEN from ADDR. For C++ virtual calls, the token + is the vtable slot index that we will need to put in the virtual call + table later. */ + +static void +dwarf2out_virtual_call_token (tree addr, int insn_uid) +{ + if (is_cxx() && TREE_CODE (addr) == OBJ_TYPE_REF) + { + tree token = OBJ_TYPE_REF_TOKEN (addr); + if (TREE_CODE (token) == INTEGER_CST) + { + struct vcall_insn *item = XNEW (struct vcall_insn); + struct vcall_insn **slot; + + gcc_assert (item); + item->insn_uid = insn_uid; + item->vtable_slot = TREE_INT_CST_LOW (token); + slot = (struct vcall_insn **) + htab_find_slot_with_hash (vcall_insn_table, (void *) &item, + (hashval_t) insn_uid, INSERT); + *slot = item; + } + } +} + +/* Called by the final INSN scan whenever we see a virtual function call. + Make an entry into the virtual call table, recording the point of call + and the slot index of the vtable entry used to call the virtual member + function. The slot index was associated with the INSN_UID during the + lowering to RTL. */ + +static void +dwarf2out_virtual_call (int insn_uid) +{ + vcall_entry e; + struct vcall_insn item; + struct vcall_insn *p; + + item.insn_uid = insn_uid; + item.vtable_slot = 0; + p = (struct vcall_insn *) htab_find_with_hash (vcall_insn_table, + (void *) &item, + (hashval_t) insn_uid); + if (p == NULL) + return; + + e.poc_label_num = poc_label_num++; + e.vtable_slot = p->vtable_slot; + VEC_safe_push (vcall_entry, gc, vcall_table, &e); + + /* Drop a label at the return point to mark the point of call. */ + ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LPOC", e.poc_label_num); +} + +/* Replace DW_AT_name for the decl with name. */ + +static void +dwarf2out_set_name (tree decl, tree name) +{ + dw_die_ref die; + dw_attr_ref attr; + + die = TYPE_SYMTAB_DIE (decl); + if (!die) + return; + + attr = get_AT (die, DW_AT_name); + if (attr) + { + struct indirect_string_node *node; + + node = find_AT_string (dwarf2_name (name, 0)); + /* replace the string. */ + attr->dw_attr_val.v.val_str = node; + } + + else + add_name_attribute (die, dwarf2_name (name, 0)); +} /* Called by the final INSN scan whenever we see a var location. We use it to drop labels in the right places, and throw the location in our lookup table. */ @@ -17614,8 +17991,7 @@ dwarf2out_source_line (unsigned int line, const char *filename, { static bool last_is_stmt = true; - if (debug_info_level >= DINFO_LEVEL_NORMAL - && line != 0) + if (generate_debug_line_table && line != 0) { int file_num = maybe_emit_file (lookup_filename (filename)); @@ -17812,6 +18188,12 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED) pubname_table = VEC_alloc (pubname_entry, gc, 32); pubtype_table = VEC_alloc (pubname_entry, gc, 32); + /* Allocate the direct and indirect call tables. */ + dcall_table = VEC_alloc (dcall_entry, gc, 32); + vcall_table = VEC_alloc (vcall_entry, gc, 32); + vcall_insn_table = htab_create_ggc (10, vcall_insn_table_hash, + vcall_insn_table_eq, NULL); + /* Generate the initial DIE for the .debug section. Note that the (string) value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE will (typically) be a relative pathname and that this pathname should be @@ -17842,6 +18224,10 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED) debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION, SECTION_DEBUG, NULL); #endif + debug_dcall_section = get_section (DEBUG_DCALL_SECTION, + SECTION_DEBUG, NULL); + debug_vcall_section = get_section (DEBUG_VCALL_SECTION, + SECTION_DEBUG, NULL); debug_str_section = get_section (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS, NULL); debug_ranges_section = get_section (DEBUG_RANGES_SECTION, @@ -18192,6 +18578,7 @@ prune_unused_types (void) limbo_die_node *node; comdat_type_node *ctnode; pubname_ref pub; + dcall_entry *dcall; #if ENABLE_ASSERT_CHECKING /* All the marks should already be clear. */ @@ -18219,6 +18606,10 @@ prune_unused_types (void) for (i = 0; i < arange_table_in_use; i++) prune_unused_types_mark (arange_table[i], 1); + /* Mark nodes referenced from the direct call table. */ + for (i = 0; VEC_iterate (dcall_entry, dcall_table, i, dcall); i++) + prune_unused_types_mark (dcall->targ_die, 1); + /* Get rid of nodes that aren't marked; and update the string counts. */ if (debug_str_hash) htab_empty (debug_str_hash); @@ -18426,6 +18817,7 @@ dwarf2out_finish (const char *filename) else { unsigned fde_idx = 0; + bool range_list_added = false; /* We need to give .debug_loc and .debug_ranges an appropriate "base address". Use zero so that these addresses become @@ -18435,12 +18827,12 @@ dwarf2out_finish (const char *filename) add_AT_addr (comp_unit_die, DW_AT_low_pc, const0_rtx); add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx); - add_AT_range_list (comp_unit_die, DW_AT_ranges, - add_ranges_by_labels (text_section_label, - text_end_label)); - if (flag_reorder_blocks_and_partition) - add_ranges_by_labels (cold_text_section_label, - cold_end_label); + if (text_section_used) + add_ranges_by_labels (comp_unit_die, text_section_label, + text_end_label, &range_list_added); + if (flag_reorder_blocks_and_partition && cold_text_section_used) + add_ranges_by_labels (comp_unit_die, cold_text_section_label, + cold_end_label, &range_list_added); for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++) { @@ -18448,17 +18840,22 @@ dwarf2out_finish (const char *filename) if (fde->dw_fde_switched_sections) { - add_ranges_by_labels (fde->dw_fde_hot_section_label, - fde->dw_fde_hot_section_end_label); - add_ranges_by_labels (fde->dw_fde_unlikely_section_label, - fde->dw_fde_unlikely_section_end_label); + add_ranges_by_labels (comp_unit_die, + fde->dw_fde_hot_section_label, + fde->dw_fde_hot_section_end_label, + &range_list_added); + add_ranges_by_labels (comp_unit_die, + fde->dw_fde_unlikely_section_label, + fde->dw_fde_unlikely_section_end_label, + &range_list_added); } else - add_ranges_by_labels (fde->dw_fde_begin, - fde->dw_fde_end); + add_ranges_by_labels (comp_unit_die, fde->dw_fde_begin, + fde->dw_fde_end, &range_list_added); } - add_ranges (NULL); + if (range_list_added) + add_ranges (NULL); } /* Output location list section if necessary. */ @@ -18472,7 +18869,7 @@ dwarf2out_finish (const char *filename) output_location_lists (die); } - if (debug_info_level >= DINFO_LEVEL_NORMAL) + if (generate_debug_line_table) add_AT_lineptr (comp_unit_die, DW_AT_stmt_list, debug_line_section_label); @@ -18529,6 +18926,18 @@ dwarf2out_finish (const char *filename) } #endif + /* Output direct and virtual call tables if necessary. */ + if (!VEC_empty (dcall_entry, dcall_table)) + { + switch_to_section (debug_dcall_section); + output_dcall_table (); + } + if (!VEC_empty (vcall_entry, vcall_table)) + { + switch_to_section (debug_vcall_section); + output_vcall_table (); + } + /* Output the address range information. We only put functions in the arange table, so don't write it out if we don't have any. */ if (fde_table_in_use) |