diff options
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 1297 |
1 files changed, 935 insertions, 362 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index b3ca159..9876750 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -79,6 +79,7 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "expr.h" #include "dwarf2out.h" +#include "dwarf2ctf.h" #include "dwarf2asm.h" #include "toplev.h" #include "md5.h" @@ -171,6 +172,7 @@ static GTY(()) section *debug_line_str_section; static GTY(()) section *debug_str_dwo_section; static GTY(()) section *debug_str_offsets_section; static GTY(()) section *debug_ranges_section; +static GTY(()) section *debug_ranges_dwo_section; static GTY(()) section *debug_frame_section; /* Maximum size (in bytes) of an artificially generated label. */ @@ -258,13 +260,21 @@ static GTY(()) int dw2_string_counter; /* True if the compilation unit places functions in more than one section. */ static GTY(()) bool have_multiple_function_sections = false; -/* Whether the default text and cold text sections have been used at all. */ -static GTY(()) bool text_section_used = false; -static GTY(()) bool cold_text_section_used = false; - /* The default cold text section. */ static GTY(()) section *cold_text_section; +/* True if currently in text section. */ +static GTY(()) bool in_text_section_p = false; + +/* Last debug-on location in corresponding section. */ +static GTY(()) const char *last_text_label; +static GTY(()) const char *last_cold_label; + +/* Mark debug-on/off locations per section. + NULL means the section is not used at all. */ +static GTY(()) vec<const char *, va_gc> *switch_text_ranges; +static GTY(()) vec<const char *, va_gc> *switch_cold_ranges; + /* The DIE for C++14 'auto' in a function return type. */ static GTY(()) dw_die_ref auto_die; @@ -274,7 +284,6 @@ static GTY(()) dw_die_ref decltype_auto_die; /* Forward declarations for functions defined in this file. */ static void output_call_frame_info (int); -static void dwarf2out_note_section_used (void); /* Personality decl of current unit. Used only when assembler does not support personality CFI. */ @@ -385,13 +394,12 @@ dump_struct_debug (tree type, enum debug_info_usage usage, #endif /* Get the number of HOST_WIDE_INTs needed to represent the precision - of the number. Some constants have a large uniform precision, so - we get the precision needed for the actual value of the number. */ + of the number. */ static unsigned int get_full_len (const wide_int &op) { - int prec = wi::min_precision (op, UNSIGNED); + int prec = wi::get_precision (op); return ((prec + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT); } @@ -1107,6 +1115,8 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED, fde->dw_fde_current_label = dup_label; fde->in_std_section = (fnsec == text_section || (cold_text_section && fnsec == cold_text_section)); + fde->ignored_debug = DECL_IGNORED_P (current_function_decl); + in_text_section_p = fnsec == text_section; /* We only want to output line number information for the genuine dwarf2 prologue case, not the eh frame case. */ @@ -1174,6 +1184,59 @@ dwarf2out_vms_begin_epilogue (unsigned int line ATTRIBUTE_UNUSED, fde->dw_fde_vms_begin_epilogue = xstrdup (label); } +/* Mark the ranges of non-debug subsections in the std text sections. */ + +static void +mark_ignored_debug_section (dw_fde_ref fde, bool second) +{ + bool std_section; + const char *begin_label, *end_label; + const char **last_end_label; + vec<const char *, va_gc> **switch_ranges; + + if (second) + { + std_section = fde->second_in_std_section; + begin_label = fde->dw_fde_second_begin; + end_label = fde->dw_fde_second_end; + } + else + { + std_section = fde->in_std_section; + begin_label = fde->dw_fde_begin; + end_label = fde->dw_fde_end; + } + + if (!std_section) + return; + + if (in_text_section_p) + { + last_end_label = &last_text_label; + switch_ranges = &switch_text_ranges; + } + else + { + last_end_label = &last_cold_label; + switch_ranges = &switch_cold_ranges; + } + + if (fde->ignored_debug) + { + if (*switch_ranges && !(vec_safe_length (*switch_ranges) & 1)) + vec_safe_push (*switch_ranges, *last_end_label); + } + else + { + *last_end_label = end_label; + + if (!*switch_ranges) + vec_alloc (*switch_ranges, 16); + else if (vec_safe_length (*switch_ranges) & 1) + vec_safe_push (*switch_ranges, begin_label); + } +} + /* Output a marker (i.e. a label) for the absolute end of the generated code for a function definition. This gets called *after* the epilogue code has been generated. */ @@ -1200,6 +1263,8 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED, gcc_assert (fde != NULL); if (fde->dw_fde_second_begin == NULL) fde->dw_fde_end = xstrdup (label); + + mark_ignored_debug_section (fde, fde->dw_fde_second_begin != NULL); } void @@ -1214,18 +1279,6 @@ dwarf2out_frame_finish (void) output_call_frame_info (1); } -/* Note that the current function section is being used for code. */ - -static void -dwarf2out_note_section_used (void) -{ - section *sec = current_function_section (); - if (sec == text_section) - text_section_used = true; - else if (sec == cold_text_section) - cold_text_section_used = true; -} - static void var_location_switch_text_section (void); static void set_cur_line_info_table (section *); @@ -1254,13 +1307,11 @@ dwarf2out_switch_text_section (void) } have_multiple_function_sections = true; - /* There is no need to mark used sections when not debugging. */ - if (cold_text_section != NULL) - dwarf2out_note_section_used (); - if (dwarf2out_do_cfi_asm ()) fprintf (asm_out_file, "\t.cfi_endproc\n"); + mark_ignored_debug_section (fde, false); + /* Now do the real section switch. */ sect = current_function_section (); switch_to_section (sect); @@ -1268,6 +1319,7 @@ dwarf2out_switch_text_section (void) fde->second_in_std_section = (sect == text_section || (cold_text_section && sect == cold_text_section)); + in_text_section_p = sect == text_section; if (dwarf2out_do_cfi_asm ()) dwarf2out_do_cfi_startproc (true); @@ -1281,12 +1333,6 @@ dwarf2out_switch_text_section (void) /* And now, the subset of the debugging information support code necessary for emitting location expressions. */ -/* Data about a single source file. */ -struct GTY((for_user)) dwarf_file_data { - const char * filename; - int emitted_number; -}; - /* Describe an entry into the .debug_addr section. */ enum ate_kind { @@ -2801,6 +2847,7 @@ static void dwarf2out_function_decl (tree); static void dwarf2out_begin_block (unsigned, unsigned); static void dwarf2out_end_block (unsigned, unsigned); static bool dwarf2out_ignore_block (const_tree); +static void dwarf2out_set_ignored_loc (unsigned, unsigned, const char *); static void dwarf2out_early_global_decl (tree); static void dwarf2out_late_global_decl (tree); static void dwarf2out_type_decl (tree, int); @@ -2836,6 +2883,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = dwarf2out_end_block, dwarf2out_ignore_block, dwarf2out_source_line, + dwarf2out_set_ignored_loc, dwarf2out_begin_prologue, #if VMS_DEBUGGING_INFO dwarf2out_vms_end_prologue, @@ -2885,6 +2933,7 @@ const struct gcc_debug_hooks dwarf2_lineno_debug_hooks = debug_nothing_int_int, /* end_block */ debug_true_const_tree, /* ignore_block */ dwarf2out_source_line, /* source_line */ + debug_nothing_int_int_charstar, /* set_ignored_loc */ debug_nothing_int_int_charstar, /* begin_prologue */ debug_nothing_int_charstar, /* end_prologue */ debug_nothing_int_charstar, /* begin_epilogue */ @@ -3069,17 +3118,6 @@ maybe_reset_location_view (rtx_insn *insn, dw_line_info_table *table) RESET_NEXT_VIEW (table->view); } -/* Each DIE attribute has a field specifying the attribute kind, - a link to the next attribute in the chain, and an attribute value. - Attributes are typically linked below the DIE they modify. */ - -typedef struct GTY(()) dw_attr_struct { - enum dwarf_attribute dw_attr; - dw_val_node dw_attr_val; -} -dw_attr_node; - - /* The Debugging Information Entry (DIE) structure. DIEs form a tree. The children of each node form a circular list linked by die_sib. die_child points to the node *before* the "first" child node. */ @@ -3152,11 +3190,17 @@ struct GTY(()) dw_ranges { /* If this is positive, it's a block number, otherwise it's a bitwise-negated index into dw_ranges_by_label. */ int num; + /* If idx is equal to DW_RANGES_IDX_SKELETON, it should be emitted + into .debug_rnglists section rather than .debug_rnglists.dwo + for -gsplit-dwarf and DWARF >= 5. */ +#define DW_RANGES_IDX_SKELETON ((1U << 31) - 1) /* Index for the range list for DW_FORM_rnglistx. */ unsigned int idx : 31; /* True if this range might be possibly in a different section from previous entry. */ unsigned int maybe_new_sec : 1; + addr_table_entry *begin_entry; + addr_table_entry *end_entry; }; /* A structure to hold a macinfo entry. */ @@ -3651,14 +3695,11 @@ static const char *dwarf_form_name (unsigned); static tree decl_ultimate_origin (const_tree); static tree decl_class_context (tree); static void add_dwarf_attr (dw_die_ref, dw_attr_node *); -static inline enum dw_val_class AT_class (dw_attr_node *); static inline unsigned int AT_index (dw_attr_node *); static void add_AT_flag (dw_die_ref, enum dwarf_attribute, unsigned); static inline unsigned AT_flag (dw_attr_node *); static void add_AT_int (dw_die_ref, enum dwarf_attribute, HOST_WIDE_INT); -static inline HOST_WIDE_INT AT_int (dw_attr_node *); static void add_AT_unsigned (dw_die_ref, enum dwarf_attribute, unsigned HOST_WIDE_INT); -static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_node *); static void add_AT_double (dw_die_ref, enum dwarf_attribute, HOST_WIDE_INT, unsigned HOST_WIDE_INT); static inline void add_AT_vec (dw_die_ref, enum dwarf_attribute, unsigned int, @@ -3673,7 +3714,6 @@ static inline dw_die_ref AT_ref (dw_attr_node *); static inline int AT_ref_external (dw_attr_node *); static inline void set_AT_ref_external (dw_attr_node *, int); static void add_AT_loc (dw_die_ref, enum dwarf_attribute, dw_loc_descr_ref); -static inline dw_loc_descr_ref AT_loc (dw_attr_node *); static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute, dw_loc_list_ref); static inline dw_loc_list_ref AT_loc_list (dw_attr_node *); @@ -3690,12 +3730,7 @@ static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *); static void add_AT_range_list (dw_die_ref, enum dwarf_attribute, unsigned long, bool); static inline const char *AT_lbl (dw_attr_node *); -static dw_attr_node *get_AT (dw_die_ref, enum dwarf_attribute); static const char *get_AT_low_pc (dw_die_ref); -static const char *get_AT_string (dw_die_ref, enum dwarf_attribute); -static int get_AT_flag (dw_die_ref, enum dwarf_attribute); -static unsigned get_AT_unsigned (dw_die_ref, enum dwarf_attribute); -static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute); static bool is_c (void); static bool is_cxx (void); static bool is_cxx (const_tree); @@ -3705,11 +3740,9 @@ static bool remove_AT (dw_die_ref, enum dwarf_attribute); static void remove_child_TAG (dw_die_ref, enum dwarf_tag); static void add_child_die (dw_die_ref, dw_die_ref); static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree); -static dw_die_ref lookup_type_die (tree); static dw_die_ref strip_naming_typedef (tree, dw_die_ref); static dw_die_ref lookup_type_die_strip_naming_typedef (tree); static void equate_type_number_to_die (tree, dw_die_ref); -static dw_die_ref lookup_decl_die (tree); static var_loc_list *lookup_decl_loc (const_tree); static void equate_decl_number_to_die (tree, dw_die_ref); static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *, var_loc_view); @@ -3782,7 +3815,6 @@ static void output_ranges (void); static dw_line_info_table *new_line_info_table (void); static void output_line_info (bool); static void output_file_names (void); -static dw_die_ref base_type_die (tree, bool); static int is_base_type (tree); static dw_die_ref subrange_type_die (tree, tree, tree, tree, dw_die_ref); static int decl_quals (const_tree); @@ -3825,12 +3857,11 @@ static void add_data_member_location_attribute (dw_die_ref, tree, static bool add_const_value_attribute (dw_die_ref, rtx); static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *); static void insert_wide_int (const wide_int &, unsigned char *, int); -static void insert_float (const_rtx, unsigned char *); +static unsigned insert_float (const_rtx, unsigned char *); static rtx rtl_for_decl_location (tree); static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool); static bool tree_add_const_value_attribute (dw_die_ref, tree); static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree); -static void add_name_attribute (dw_die_ref, const char *); static void add_desc_attribute (dw_die_ref, tree); static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref); static void add_comp_dir_attribute (dw_die_ref); @@ -3923,8 +3954,10 @@ static void prune_unused_types (void); static int maybe_emit_file (struct dwarf_file_data *fd); static inline const char *AT_vms_delta1 (dw_attr_node *); static inline const char *AT_vms_delta2 (dw_attr_node *); +#if VMS_DEBUGGING_INFO static inline void add_AT_vms_delta (dw_die_ref, enum dwarf_attribute, const char *, const char *); +#endif static void append_entry_to_tmpl_value_parm_die_table (dw_die_ref, tree); static void gen_remaining_tmpl_value_param_die_attribute (void); static bool generic_type_p (tree); @@ -4099,6 +4132,9 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel) #ifndef DEBUG_RNGLISTS_SECTION #define DEBUG_RNGLISTS_SECTION ".debug_rnglists" #endif +#ifndef DEBUG_DWO_RNGLISTS_SECTION +#define DEBUG_DWO_RNGLISTS_SECTION ".debug_rnglists.dwo" +#endif #ifndef DEBUG_LINE_STR_SECTION #define DEBUG_LINE_STR_SECTION ".debug_line_str" #endif @@ -4432,7 +4468,7 @@ add_dwarf_attr (dw_die_ref die, dw_attr_node *attr) vec_safe_push (die->die_attr, *attr); } -static inline enum dw_val_class +enum dw_val_class AT_class (dw_attr_node *a) { return a->dw_attr_val.val_class; @@ -4488,7 +4524,7 @@ add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_va add_dwarf_attr (die, &attr); } -static inline HOST_WIDE_INT +HOST_WIDE_INT AT_int (dw_attr_node *a) { gcc_assert (a && (AT_class (a) == dw_val_class_const @@ -4511,7 +4547,7 @@ add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind, add_dwarf_attr (die, &attr); } -static inline unsigned HOST_WIDE_INT +unsigned HOST_WIDE_INT AT_unsigned (dw_attr_node *a) { gcc_assert (a && (AT_class (a) == dw_val_class_unsigned_const @@ -4895,7 +4931,7 @@ add_AT_loc (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_descr_ref loc add_dwarf_attr (die, &attr); } -static inline dw_loc_descr_ref +dw_loc_descr_ref AT_loc (dw_attr_node *a) { gcc_assert (a && AT_class (a) == dw_val_class_loc); @@ -5136,6 +5172,30 @@ index_addr_table_entry (addr_table_entry **h, unsigned int *index) return 1; } +/* Return the tag of a given DIE. */ + +enum dwarf_tag +dw_get_die_tag (dw_die_ref die) +{ + return die->die_tag; +} + +/* Return a reference to the children list of a given DIE. */ + +dw_die_ref +dw_get_die_child (dw_die_ref die) +{ + return die->die_child; +} + +/* Return a reference to the sibling of a given DIE. */ + +dw_die_ref +dw_get_die_sib (dw_die_ref die) +{ + return die->die_sib; +} + /* Add an address constant attribute value to a DIE. When using dwarf_split_debug_info, address attributes in dies destined for the final executable should be direct references--setting the parameter @@ -5191,6 +5251,7 @@ AT_file (dw_attr_node *a) return a->dw_attr_val.v.val_file; } +#if VMS_DEBUGGING_INFO /* Add a vms delta attribute value to a DIE. */ static inline void @@ -5206,6 +5267,7 @@ add_AT_vms_delta (dw_die_ref die, enum dwarf_attribute attr_kind, attr.dw_attr_val.v.val_vms_delta.lbl2 = xstrdup (lbl2); add_dwarf_attr (die, &attr); } +#endif /* Add a symbolic view identifier attribute value to a DIE. */ @@ -5331,7 +5393,7 @@ AT_lbl (dw_attr_node *a) /* Get the attribute of type attr_kind. */ -static dw_attr_node * +dw_attr_node * get_AT (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_node *a; @@ -5386,7 +5448,7 @@ get_AT_low_pc (dw_die_ref die) /* Return the value of the string attribute designated by ATTR_KIND, or NULL if it is not present. */ -static inline const char * +const char * get_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_node *a = get_AT (die, attr_kind); @@ -5397,7 +5459,7 @@ get_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind) /* Return the value of the flag attribute designated by ATTR_KIND, or -1 if it is not present. */ -static inline int +int get_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_node *a = get_AT (die, attr_kind); @@ -5408,7 +5470,7 @@ get_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind) /* Return the value of the unsigned attribute designated by ATTR_KIND, or 0 if it is not present. */ -static inline unsigned +unsigned get_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_node *a = get_AT (die, attr_kind); @@ -5416,7 +5478,7 @@ get_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind) return a ? AT_unsigned (a) : 0; } -static inline dw_die_ref +dw_die_ref get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_node *a = get_AT (die, attr_kind); @@ -5424,7 +5486,7 @@ get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind) return a ? AT_ref (a) : NULL; } -static inline struct dwarf_file_data * +struct dwarf_file_data * get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_node *a = get_AT (die, attr_kind); @@ -5465,7 +5527,7 @@ is_cxx (const_tree decl) { const_tree context = get_ultimate_context (decl); if (context && TRANSLATION_UNIT_LANGUAGE (context)) - return strncmp (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++", 7) == 0; + return startswith (TRANSLATION_UNIT_LANGUAGE (context), "GNU C++"); } return is_cxx (); } @@ -5709,7 +5771,7 @@ splice_child_die (dw_die_ref parent, dw_die_ref child) /* Create and return a new die with TAG_VALUE as tag. */ -static inline dw_die_ref +dw_die_ref new_die_raw (enum dwarf_tag tag_value) { dw_die_ref die = ggc_cleared_alloc<die_node> (); @@ -5775,7 +5837,7 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t) /* Return the DIE associated with the given type specifier. */ -static inline dw_die_ref +dw_die_ref lookup_type_die (tree type) { dw_die_ref die = TYPE_SYMTAB_DIE (type); @@ -5854,7 +5916,7 @@ decl_die_hasher::equal (die_node *x, tree y) /* Return the DIE associated with a given declaration. */ -static inline dw_die_ref +dw_die_ref lookup_decl_die (tree decl) { dw_die_ref *die = decl_die_table->find_slot_with_hash (decl, DECL_UID (decl), @@ -9743,10 +9805,12 @@ size_of_aranges (void) size = DWARF_ARANGES_HEADER_SIZE; /* Count the address/length pair for this compilation unit. */ - if (text_section_used) - size += 2 * DWARF2_ADDR_SIZE; - if (cold_text_section_used) - size += 2 * DWARF2_ADDR_SIZE; + if (switch_text_ranges) + size += 2 * DWARF2_ADDR_SIZE + * (vec_safe_length (switch_text_ranges) / 2 + 1); + if (switch_cold_ranges) + size += 2 * DWARF2_ADDR_SIZE + * (vec_safe_length (switch_cold_ranges) / 2 + 1); if (have_multiple_function_sections) { unsigned fde_idx; @@ -9754,7 +9818,7 @@ size_of_aranges (void) FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde) { - if (DECL_IGNORED_P (fde->decl)) + if (fde->ignored_debug) continue; if (!fde->in_std_section) size += 2 * DWARF2_ADDR_SIZE; @@ -11700,18 +11764,52 @@ output_aranges (void) the address may end up as 0 if the section is discarded by ld --gc-sections, leaving an invalid (0, 0) entry that can be confused with the terminator. */ - if (text_section_used) + if (switch_text_ranges) { - dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address"); - dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, - text_section_label, "Length"); + const char *prev_loc = text_section_label; + const char *loc; + unsigned idx; + + FOR_EACH_VEC_ELT (*switch_text_ranges, idx, loc) + if (prev_loc) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, loc, prev_loc, "Length"); + prev_loc = NULL; + } + else + prev_loc = loc; + + if (prev_loc) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, + prev_loc, "Length"); + } } - if (cold_text_section_used) + + if (switch_cold_ranges) { - dw2_asm_output_addr (DWARF2_ADDR_SIZE, cold_text_section_label, - "Address"); - dw2_asm_output_delta (DWARF2_ADDR_SIZE, cold_end_label, - cold_text_section_label, "Length"); + const char *prev_loc = cold_text_section_label; + const char *loc; + unsigned idx; + + FOR_EACH_VEC_ELT (*switch_cold_ranges, idx, loc) + if (prev_loc) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, loc, prev_loc, "Length"); + prev_loc = NULL; + } + else + prev_loc = loc; + + if (prev_loc) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, cold_end_label, + prev_loc, "Length"); + } } if (have_multiple_function_sections) @@ -11721,7 +11819,7 @@ output_aranges (void) FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde) { - if (DECL_IGNORED_P (fde->decl)) + if (fde->ignored_debug) continue; if (!fde->in_std_section) { @@ -11751,7 +11849,7 @@ output_aranges (void) static unsigned int add_ranges_num (int num, bool maybe_new_sec) { - dw_ranges r = { NULL, num, 0, maybe_new_sec }; + dw_ranges r = { NULL, num, 0, maybe_new_sec, NULL, NULL }; vec_safe_push (ranges_table, r); return vec_safe_length (ranges_table) - 1; } @@ -11796,6 +11894,8 @@ add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end, add_AT_range_list (die, DW_AT_ranges, offset, force_direct); *added = true; note_rnglist_head (offset); + if (dwarf_split_debug_info && force_direct) + (*ranges_table)[offset].idx = DW_RANGES_IDX_SKELETON; } } @@ -11920,24 +12020,96 @@ asm_outputs_debug_line_str (void) } } +/* Return true if it is beneficial to use DW_RLE_base_address{,x}. + I is index of the following range. */ -/* Assign .debug_rnglists indexes. */ +static bool +use_distinct_base_address_for_range (unsigned int i) +{ + if (i >= vec_safe_length (ranges_table)) + return false; + + dw_ranges *r2 = &(*ranges_table)[i]; + /* Use DW_RLE_base_address{,x} if there is a next range in the + range list and is guaranteed to be in the same section. */ + return r2->num != 0 && r2->label == NULL && !r2->maybe_new_sec; +} + +/* Assign .debug_rnglists indexes and unique indexes into the debug_addr + section when needed. */ static void index_rnglists (void) { unsigned i; dw_ranges *r; + bool base = false; FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r) - if (r->label) - r->idx = rnglist_idx++; + { + if (r->label && r->idx != DW_RANGES_IDX_SKELETON) + r->idx = rnglist_idx++; + + if (!have_multiple_function_sections) + continue; + int block_num = r->num; + if (HAVE_AS_LEB128 && (r->label || r->maybe_new_sec)) + base = false; + if (block_num > 0) + { + char blabel[MAX_ARTIFICIAL_LABEL_BYTES]; + char elabel[MAX_ARTIFICIAL_LABEL_BYTES]; + + ASM_GENERATE_INTERNAL_LABEL (blabel, BLOCK_BEGIN_LABEL, block_num); + ASM_GENERATE_INTERNAL_LABEL (elabel, BLOCK_END_LABEL, block_num); + + if (HAVE_AS_LEB128) + { + if (!base && use_distinct_base_address_for_range (i + 1)) + { + r->begin_entry = add_addr_table_entry (xstrdup (blabel), + ate_kind_label); + base = true; + } + if (base) + /* If we have a base, no need for further + begin_entry/end_entry, as DW_RLE_offset_pair will be + used. */ + continue; + r->begin_entry + = add_addr_table_entry (xstrdup (blabel), ate_kind_label); + /* No need for end_entry, DW_RLE_start{,x}_length will use + length as opposed to a pair of addresses. */ + } + else + { + r->begin_entry + = add_addr_table_entry (xstrdup (blabel), ate_kind_label); + r->end_entry + = add_addr_table_entry (xstrdup (elabel), ate_kind_label); + } + } + + /* Negative block_num stands for an index into ranges_by_label. */ + else if (block_num < 0) + { + int lab_idx = - block_num - 1; + const char *blabel = (*ranges_by_label)[lab_idx].begin; + const char *elabel = (*ranges_by_label)[lab_idx].end; + + r->begin_entry + = add_addr_table_entry (xstrdup (blabel), ate_kind_label); + if (!HAVE_AS_LEB128) + r->end_entry + = add_addr_table_entry (xstrdup (elabel), ate_kind_label); + } + } } -/* Emit .debug_rnglists section. */ +/* Emit .debug_rnglists or (when DWO is true) .debug_rnglists.dwo section. */ -static void -output_rnglists (unsigned generation) +static bool +output_rnglists (unsigned generation, bool dwo) { unsigned i; dw_ranges *r; @@ -11945,14 +12117,19 @@ output_rnglists (unsigned generation) char l2[MAX_ARTIFICIAL_LABEL_BYTES]; char basebuf[MAX_ARTIFICIAL_LABEL_BYTES]; - switch_to_section (debug_ranges_section); - ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label); + if (dwo) + switch_to_section (debug_ranges_dwo_section); + else + { + switch_to_section (debug_ranges_section); + ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label); + } /* There are up to 4 unique ranges labels per generation. See also init_sections_and_labels. */ ASM_GENERATE_INTERNAL_LABEL (l1, DEBUG_RANGES_SECTION_LABEL, - 2 + generation * 4); + 2 + 2 * dwo + generation * 6); ASM_GENERATE_INTERNAL_LABEL (l2, DEBUG_RANGES_SECTION_LABEL, - 3 + generation * 4); + 3 + 2 * dwo + generation * 6); if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) dw2_asm_output_data (4, 0xffffffff, "Initial length escape value indicating " @@ -11969,29 +12146,43 @@ output_rnglists (unsigned generation) the offset table plus corresponding DW_FORM_rnglistx uleb128 indexes into it are usually larger than just DW_FORM_sec_offset offsets into the .debug_rnglists section. */ - dw2_asm_output_data (4, dwarf_split_debug_info ? rnglist_idx : 0, + dw2_asm_output_data (4, dwo ? rnglist_idx : 0, "Offset Entry Count"); - if (dwarf_split_debug_info) + if (dwo) { ASM_OUTPUT_LABEL (asm_out_file, ranges_base_label); FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r) - if (r->label) + if (r->label && r->idx != DW_RANGES_IDX_SKELETON) dw2_asm_output_delta (dwarf_offset_size, r->label, ranges_base_label, NULL); } const char *lab = ""; - unsigned int len = vec_safe_length (ranges_table); const char *base = NULL; + bool skipping = false; + bool ret = false; FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r) { int block_num = r->num; if (r->label) { + if (dwarf_split_debug_info + && (r->idx == DW_RANGES_IDX_SKELETON) == dwo) + { + ret = true; + skipping = true; + continue; + } ASM_OUTPUT_LABEL (asm_out_file, r->label); lab = r->label; } + if (skipping) + { + if (block_num == 0) + skipping = false; + continue; + } if (HAVE_AS_LEB128 && (r->label || r->maybe_new_sec)) base = NULL; if (block_num > 0) @@ -12017,23 +12208,25 @@ output_rnglists (unsigned generation) "Range end address (%s)", lab); continue; } - if (base == NULL) + if (base == NULL && use_distinct_base_address_for_range (i + 1)) { - dw_ranges *r2 = NULL; - if (i < len - 1) - r2 = &(*ranges_table)[i + 1]; - if (r2 - && r2->num != 0 - && r2->label == NULL - && !r2->maybe_new_sec) + if (dwarf_split_debug_info) + { + dw2_asm_output_data (1, DW_RLE_base_addressx, + "DW_RLE_base_addressx (%s)", lab); + dw2_asm_output_data_uleb128 (r->begin_entry->index, + "Base address index (%s)", + blabel); + } + else { dw2_asm_output_data (1, DW_RLE_base_address, "DW_RLE_base_address (%s)", lab); dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel, "Base address (%s)", lab); - strcpy (basebuf, blabel); - base = basebuf; } + strcpy (basebuf, blabel); + base = basebuf; } if (base) { @@ -12045,13 +12238,35 @@ output_rnglists (unsigned generation) "Range end address (%s)", lab); continue; } - dw2_asm_output_data (1, DW_RLE_start_length, - "DW_RLE_start_length (%s)", lab); - dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel, - "Range begin address (%s)", lab); + if (dwarf_split_debug_info) + { + dw2_asm_output_data (1, DW_RLE_startx_length, + "DW_RLE_startx_length (%s)", lab); + dw2_asm_output_data_uleb128 (r->begin_entry->index, + "Range begin address index " + "(%s)", blabel); + } + else + { + dw2_asm_output_data (1, DW_RLE_start_length, + "DW_RLE_start_length (%s)", lab); + dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel, + "Range begin address (%s)", lab); + } dw2_asm_output_delta_uleb128 (elabel, blabel, "Range length (%s)", lab); } + else if (dwarf_split_debug_info) + { + dw2_asm_output_data (1, DW_RLE_startx_endx, + "DW_RLE_startx_endx (%s)", lab); + dw2_asm_output_data_uleb128 (r->begin_entry->index, + "Range begin address index " + "(%s)", blabel); + dw2_asm_output_data_uleb128 (r->end_entry->index, + "Range end address index " + "(%s)", elabel); + } else { dw2_asm_output_data (1, DW_RLE_start_end, @@ -12074,13 +12289,35 @@ output_rnglists (unsigned generation) gcc_unreachable (); if (HAVE_AS_LEB128) { - dw2_asm_output_data (1, DW_RLE_start_length, - "DW_RLE_start_length (%s)", lab); - dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel, - "Range begin address (%s)", lab); + if (dwarf_split_debug_info) + { + dw2_asm_output_data (1, DW_RLE_startx_length, + "DW_RLE_startx_length (%s)", lab); + dw2_asm_output_data_uleb128 (r->begin_entry->index, + "Range begin address index " + "(%s)", blabel); + } + else + { + dw2_asm_output_data (1, DW_RLE_start_length, + "DW_RLE_start_length (%s)", lab); + dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel, + "Range begin address (%s)", lab); + } dw2_asm_output_delta_uleb128 (elabel, blabel, "Range length (%s)", lab); } + else if (dwarf_split_debug_info) + { + dw2_asm_output_data (1, DW_RLE_startx_endx, + "DW_RLE_startx_endx (%s)", lab); + dw2_asm_output_data_uleb128 (r->begin_entry->index, + "Range begin address index " + "(%s)", blabel); + dw2_asm_output_data_uleb128 (r->end_entry->index, + "Range end address index " + "(%s)", elabel); + } else { dw2_asm_output_data (1, DW_RLE_start_end, @@ -12096,6 +12333,7 @@ output_rnglists (unsigned generation) "DW_RLE_end_of_list (%s)", lab); } ASM_OUTPUT_LABEL (asm_out_file, l2); + return ret; } /* Data structure containing information about input files. */ @@ -12185,7 +12423,7 @@ file_name_acquire (dwarf_file_data **slot, file_name_acquire_data *fnad) fi = fnad->files + fnad->used_files++; - f = remap_debug_filename (d->filename); + f = d->filename; /* Skip all leading "./". */ while (f[0] == '.' && IS_DIR_SEPARATOR (f[1])) @@ -12907,7 +13145,7 @@ need_endianity_attribute_p (bool reverse) This routine must only be called for GCC type nodes that correspond to Dwarf base (fundamental) types. */ -static dw_die_ref +dw_die_ref base_type_die (tree type, bool reverse) { dw_die_ref base_type_result; @@ -13303,6 +13541,7 @@ modified_type_die (tree type, int cv_quals, bool reverse, tree qualified_type; tree name, low, high; dw_die_ref mod_scope; + struct array_descr_info info; /* Only these cv-qualifiers are currently handled. */ const int cv_qual_mask = (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC | @@ -13547,6 +13786,13 @@ modified_type_die (tree type, int cv_quals, bool reverse, } } } + else if (code == ARRAY_TYPE + || (lang_hooks.types.get_array_descr_info + && lang_hooks.types.get_array_descr_info (type, &info))) + { + gen_type_die (type, context_die); + return lookup_type_die (type); + } else if (code == INTEGER_TYPE && TREE_TYPE (type) != NULL_TREE && subrange_type_for_debug_p (type, &low, &high)) @@ -13583,8 +13829,7 @@ modified_type_die (tree type, int cv_quals, bool reverse, copy was created to help us keep track of typedef names) and that copy might have a different TYPE_UID from the original ..._TYPE node. */ - if (TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == METHOD_TYPE) + if (code == FUNCTION_TYPE || code == METHOD_TYPE) { /* For function/method types, can't just use type_main_variant here, because that can have different ref-qualifiers for C++, @@ -13597,13 +13842,12 @@ modified_type_die (tree type, int cv_quals, bool reverse, return lookup_type_die (t); return lookup_type_die (type); } - else if (TREE_CODE (type) != VECTOR_TYPE - && TREE_CODE (type) != ARRAY_TYPE) - return lookup_type_die (type_main_variant (type)); - else - /* Vectors have the debugging information in the type, - not the main variant. */ + /* Vectors have the debugging information in the type, + not the main variant. */ + else if (code == VECTOR_TYPE) return lookup_type_die (type); + else + return lookup_type_die (type_main_variant (type)); } /* Builtin types don't have a DECL_ORIGINAL_TYPE. For those, @@ -14933,7 +15177,7 @@ scompare_loc_descriptor_narrow (enum dwarf_location_atom op, rtx rtl, return compare_loc_descriptor (op, op0, op1); } -/* Return location descriptor for unsigned comparison OP RTL. */ +/* Return location descriptor for signed comparison OP RTL. */ static dw_loc_descr_ref scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl, @@ -16164,11 +16408,13 @@ mem_loc_descriptor (rtx rtl, machine_mode mode, if ((!dwarf_strict || dwarf_version >= 5) && is_a <scalar_int_mode> (mode, &int_mode)) { - if (GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE) + /* We can use a signed divide if the sign bit is not set. */ + if (GET_MODE_SIZE (int_mode) < DWARF2_ADDR_SIZE) { op = DW_OP_div; goto do_binop; } + mem_loc_result = typed_binop (DW_OP_div, rtl, base_type_for_mode (int_mode, 1), int_mode, mem_mode); @@ -16292,11 +16538,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode, scalar_float_mode float_mode = as_a <scalar_float_mode> (mode); unsigned int length = GET_MODE_SIZE (float_mode); unsigned char *array = ggc_vec_alloc<unsigned char> (length); + unsigned int elt_size = insert_float (rtl, array); - insert_float (rtl, array); mem_loc_result->dw_loc_oprnd2.val_class = dw_val_class_vec; - mem_loc_result->dw_loc_oprnd2.v.val_vec.length = length / 4; - mem_loc_result->dw_loc_oprnd2.v.val_vec.elt_size = 4; + mem_loc_result->dw_loc_oprnd2.v.val_vec.length + = length / elt_size; + mem_loc_result->dw_loc_oprnd2.v.val_vec.elt_size = elt_size; mem_loc_result->dw_loc_oprnd2.v.val_vec.array = array; } } @@ -16866,11 +17113,11 @@ loc_descriptor (rtx rtl, machine_mode mode, { unsigned int length = GET_MODE_SIZE (smode); unsigned char *array = ggc_vec_alloc<unsigned char> (length); + unsigned int elt_size = insert_float (rtl, array); - insert_float (rtl, array); loc_result->dw_loc_oprnd2.val_class = dw_val_class_vec; - loc_result->dw_loc_oprnd2.v.val_vec.length = length / 4; - loc_result->dw_loc_oprnd2.v.val_vec.elt_size = 4; + loc_result->dw_loc_oprnd2.v.val_vec.length = length / elt_size; + loc_result->dw_loc_oprnd2.v.val_vec.elt_size = elt_size; loc_result->dw_loc_oprnd2.v.val_vec.array = array; } } @@ -17750,6 +17997,8 @@ struct loc_descr_context bool placeholder_arg; /* True if PLACEHOLDER_EXPR has been seen. */ bool placeholder_seen; + /* True if strict preservation of signedness has been requested. */ + bool strict_signedness; }; /* DWARF procedures generation @@ -17818,7 +18067,7 @@ new_dwarf_proc_die (dw_loc_descr_ref location, tree fndecl, /* Return whether TYPE is a supported type as a DWARF procedure argument type or return type (we handle only scalar types and pointer types that - aren't wider than the DWARF expression evaluation stack. */ + aren't wider than the DWARF expression evaluation stack). */ static bool is_handled_procedure_type (tree type) @@ -17960,6 +18209,12 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset, case DW_OP_bit_piece: case DW_OP_implicit_value: case DW_OP_stack_value: + case DW_OP_deref_type: + case DW_OP_convert: + case DW_OP_reinterpret: + case DW_OP_GNU_deref_type: + case DW_OP_GNU_convert: + case DW_OP_GNU_reinterpret: break; case DW_OP_addr: @@ -18091,9 +18346,6 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset, case DW_OP_entry_value: case DW_OP_const_type: case DW_OP_regval_type: - case DW_OP_deref_type: - case DW_OP_convert: - case DW_OP_reinterpret: case DW_OP_form_tls_address: case DW_OP_GNU_push_tls_address: case DW_OP_GNU_uninit: @@ -18102,9 +18354,6 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset, case DW_OP_GNU_entry_value: case DW_OP_GNU_const_type: case DW_OP_GNU_regval_type: - case DW_OP_GNU_deref_type: - case DW_OP_GNU_convert: - case DW_OP_GNU_reinterpret: case DW_OP_GNU_parameter_ref: /* loc_list_from_tree will probably not output these operations for size functions, so assume they will not appear here. */ @@ -18153,8 +18402,8 @@ resolve_args_picking (dw_loc_descr_ref loc, unsigned initial_frame_offset, this operation. */ hash_map<dw_loc_descr_ref, unsigned> frame_offsets; - return resolve_args_picking_1 (loc, initial_frame_offset, dpi, - frame_offsets); + return + resolve_args_picking_1 (loc, initial_frame_offset, dpi, frame_offsets); } /* Try to generate a DWARF procedure that computes the same result as FNDECL. @@ -18163,8 +18412,15 @@ resolve_args_picking (dw_loc_descr_ref loc, unsigned initial_frame_offset, static dw_die_ref function_to_dwarf_procedure (tree fndecl) { - struct loc_descr_context ctx; struct dwarf_procedure_info dpi; + struct loc_descr_context ctx = { + NULL_TREE, /* context_type */ + NULL_TREE, /* base_decl */ + &dpi, /* dpi */ + false, /* placeholder_arg */ + false, /* placeholder_seen */ + true /* strict_signedness */ + }; dw_die_ref dwarf_proc_die; tree tree_body = DECL_SAVED_TREE (fndecl); dw_loc_descr_ref loc_body, epilogue; @@ -18209,11 +18465,6 @@ function_to_dwarf_procedure (tree fndecl) cause an infinite recursion if its call graph has a cycle. This is very unlikely for size functions, however, so don't bother with such things at the moment. */ - ctx.context_type = NULL_TREE; - ctx.base_decl = NULL_TREE; - ctx.dpi = &dpi; - ctx.placeholder_arg = false; - ctx.placeholder_seen = false; dpi.fndecl = fndecl; dpi.args_count = list_length (DECL_ARGUMENTS (fndecl)); loc_body = loc_descriptor_from_tree (tree_body, 0, &ctx); @@ -18255,6 +18506,48 @@ function_to_dwarf_procedure (tree fndecl) return dwarf_proc_die; } +/* Helper function for loc_list_from_tree. Perform OP binary op, + but after converting arguments to type_die, afterwards convert + back to unsigned. */ + +static dw_loc_list_ref +typed_binop_from_tree (enum dwarf_location_atom op, tree loc, + dw_die_ref type_die, scalar_int_mode mode, + struct loc_descr_context *context) +{ + dw_loc_list_ref op0, op1; + dw_loc_descr_ref cvt, binop; + + if (type_die == NULL) + return NULL; + + op0 = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context); + op1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context); + if (op0 == NULL || op1 == NULL) + return NULL; + + cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0); + cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; + cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; + add_loc_descr_to_each (op0, cvt); + + cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0); + cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die; + cvt->dw_loc_oprnd1.v.val_die_ref.external = 0; + add_loc_descr_to_each (op1, cvt); + + add_loc_list (&op0, op1); + if (op0 == NULL) + return NULL; + + binop = new_loc_descr (op, 0, 0); + convert_descriptor_to_mode (mode, binop); + add_loc_descr_to_each (op0, binop); + + return op0; +} /* Generate Dwarf location list representing LOC. If WANT_ADDRESS is false, expression computing LOC will be computed @@ -18342,47 +18635,48 @@ loc_list_from_tree_1 (tree loc, int want_address, case CALL_EXPR: { - const int nargs = call_expr_nargs (loc); tree callee = get_callee_fndecl (loc); - int i; dw_die_ref dwarf_proc; - if (callee == NULL_TREE) - goto call_expansion_failed; - - /* We handle only functions that return an integer. */ - if (!is_handled_procedure_type (TREE_TYPE (TREE_TYPE (callee)))) - goto call_expansion_failed; - - dwarf_proc = function_to_dwarf_procedure (callee); - if (dwarf_proc == NULL) - goto call_expansion_failed; - - /* Evaluate arguments right-to-left so that the first argument will - be the top-most one on the stack. */ - for (i = nargs - 1; i >= 0; --i) + if (callee + && is_handled_procedure_type (TREE_TYPE (TREE_TYPE (callee))) + && (dwarf_proc = function_to_dwarf_procedure (callee))) { - dw_loc_descr_ref loc_descr - = loc_descriptor_from_tree (CALL_EXPR_ARG (loc, i), 0, - context); + /* DWARF procedures are used for size functions, which are built + when size expressions contain conditional constructs, so we + request strict preservation of signedness for comparisons. */ + bool old_strict_signedness; + if (context) + { + old_strict_signedness = context->strict_signedness; + context->strict_signedness = true; + } - if (loc_descr == NULL) - goto call_expansion_failed; + /* Evaluate arguments right-to-left so that the first argument + will be the top-most one on the stack. */ + for (int i = call_expr_nargs (loc) - 1; i >= 0; --i) + { + tree arg = CALL_EXPR_ARG (loc, i); + ret1 = loc_descriptor_from_tree (arg, 0, context); + if (!ret1) + { + expansion_failed (arg, NULL_RTX, "CALL_EXPR argument"); + return NULL; + } + add_loc_descr (&ret, ret1); + } - add_loc_descr (&ret, loc_descr); + ret1 = new_loc_descr (DW_OP_call4, 0, 0); + ret1->dw_loc_oprnd1.val_class = dw_val_class_die_ref; + ret1->dw_loc_oprnd1.v.val_die_ref.die = dwarf_proc; + ret1->dw_loc_oprnd1.v.val_die_ref.external = 0; + add_loc_descr (&ret, ret1); + if (context) + context->strict_signedness = old_strict_signedness; } - - ret1 = new_loc_descr (DW_OP_call4, 0, 0); - ret1->dw_loc_oprnd1.val_class = dw_val_class_die_ref; - ret1->dw_loc_oprnd1.v.val_die_ref.die = dwarf_proc; - ret1->dw_loc_oprnd1.v.val_die_ref.external = 0; - add_loc_descr (&ret, ret1); + else + expansion_failed (loc, NULL_RTX, "CALL_EXPR target"); break; - - call_expansion_failed: - expansion_failed (loc, NULL_RTX, "CALL_EXPR"); - /* There are no opcodes for these operations. */ - return 0; } case PREINCREMENT_EXPR: @@ -18504,8 +18798,20 @@ loc_list_from_tree_1 (tree loc, int want_address, case RESULT_DECL: if (DECL_HAS_VALUE_EXPR_P (loc)) - return loc_list_from_tree_1 (DECL_VALUE_EXPR (loc), - want_address, context); + { + tree value_expr = DECL_VALUE_EXPR (loc); + + /* Non-local frame structures are DECL_IGNORED_P variables so we need + to wait until they get an RTX in order to reference them. */ + if (early_dwarf + && TREE_CODE (value_expr) == COMPONENT_REF + && VAR_P (TREE_OPERAND (value_expr, 0)) + && DECL_NONLOCAL_FRAME (TREE_OPERAND (value_expr, 0))) + ; + else + return loc_list_from_tree_1 (value_expr, want_address, context); + } + /* FALLTHRU */ case FUNCTION_DECL: @@ -18524,25 +18830,25 @@ loc_list_from_tree_1 (tree loc, int want_address, { if (TREE_CODE (loc) != FUNCTION_DECL && early_dwarf - && current_function_decl && want_address != 1 && ! DECL_IGNORED_P (loc) && (INTEGRAL_TYPE_P (TREE_TYPE (loc)) || POINTER_TYPE_P (TREE_TYPE (loc))) - && DECL_CONTEXT (loc) == current_function_decl && (GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (loc))) <= DWARF2_ADDR_SIZE)) { dw_die_ref ref = lookup_decl_die (loc); - ret = new_loc_descr (DW_OP_GNU_variable_value, 0, 0); if (ref) { + ret = new_loc_descr (DW_OP_GNU_variable_value, 0, 0); ret->dw_loc_oprnd1.val_class = dw_val_class_die_ref; ret->dw_loc_oprnd1.v.val_die_ref.die = ref; ret->dw_loc_oprnd1.v.val_die_ref.external = 0; } - else + else if (current_function_decl + && DECL_CONTEXT (loc) == current_function_decl) { + ret = new_loc_descr (DW_OP_GNU_variable_value, 0, 0); ret->dw_loc_oprnd1.val_class = dw_val_class_decl_ref; ret->dw_loc_oprnd1.v.val_decl_ref = loc; } @@ -18835,13 +19141,53 @@ loc_list_from_tree_1 (tree loc, int want_address, op = DW_OP_or; goto do_binop; + case EXACT_DIV_EXPR: case FLOOR_DIV_EXPR: + case TRUNC_DIV_EXPR: + /* Turn a divide by a power of 2 into a shift when possible. */ + if (TYPE_UNSIGNED (TREE_TYPE (loc)) + && tree_fits_uhwi_p (TREE_OPERAND (loc, 1))) + { + const int log2 = exact_log2 (tree_to_uhwi (TREE_OPERAND (loc, 1))); + if (log2 > 0) + { + list_ret + = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context); + if (list_ret == 0) + return 0; + + add_loc_descr_to_each (list_ret, uint_loc_descriptor (log2)); + add_loc_descr_to_each (list_ret, + new_loc_descr (DW_OP_shr, 0, 0)); + break; + } + } + + /* fall through */ + case CEIL_DIV_EXPR: case ROUND_DIV_EXPR: - case TRUNC_DIV_EXPR: - case EXACT_DIV_EXPR: if (TYPE_UNSIGNED (TREE_TYPE (loc))) - return 0; + { + enum machine_mode mode = TYPE_MODE (TREE_TYPE (loc)); + scalar_int_mode int_mode; + + if ((dwarf_strict && dwarf_version < 5) + || !is_a <scalar_int_mode> (mode, &int_mode)) + return 0; + + /* We can use a signed divide if the sign bit is not set. */ + if (GET_MODE_SIZE (int_mode) < DWARF2_ADDR_SIZE) + { + op = DW_OP_div; + goto do_binop; + } + + list_ret = typed_binop_from_tree (DW_OP_div, loc, + base_type_for_mode (int_mode, 1), + int_mode, context); + break; + } op = DW_OP_div; goto do_binop; @@ -19030,7 +19376,14 @@ loc_list_from_tree_1 (tree loc, int want_address, = loc_list_from_tree_1 (TREE_OPERAND (loc, 2), 0, context); dw_loc_descr_ref bra_node, jump_node, tmp; - list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context); + /* DW_OP_bra is branch-on-nonzero so avoid doing useless work. */ + if (TREE_CODE (TREE_OPERAND (loc, 0)) == NE_EXPR + && integer_zerop (TREE_OPERAND (TREE_OPERAND (loc, 0), 1))) + list_ret + = loc_list_from_tree_1 (TREE_OPERAND (TREE_OPERAND (loc, 0), 0), + 0, context); + else + list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context); if (list_ret == 0 || lhs == 0 || rhs == 0) return 0; @@ -19056,6 +19409,10 @@ loc_list_from_tree_1 (tree loc, int want_address, case FIX_TRUNC_EXPR: return 0; + case COMPOUND_LITERAL_EXPR: + return loc_list_from_tree_1 (COMPOUND_LITERAL_EXPR_DECL (loc), + 0, context); + default: /* Leave front-end specific codes as simply unknown. This comes up, for instance, with the C STMT_EXPR. */ @@ -19110,23 +19467,50 @@ loc_list_from_tree_1 (tree loc, int want_address, if (!want_address && have_address) { HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc)); + enum machine_mode mode = TYPE_MODE (TREE_TYPE (loc)); + scalar_int_mode int_mode; + dw_die_ref type_die; + dw_loc_descr_ref deref; + /* If the size is greater than DWARF2_ADDR_SIZE, bail out. */ if (size > DWARF2_ADDR_SIZE || size == -1) { expansion_failed (loc, NULL_RTX, "DWARF address size mismatch"); return 0; } + + /* If it is equal to DWARF2_ADDR_SIZE, extension does not matter. */ else if (size == DWARF2_ADDR_SIZE) - op = DW_OP_deref; + deref = new_loc_descr (DW_OP_deref, size, 0); + + /* If it is lower than DWARF2_ADDR_SIZE, DW_OP_deref_size will zero- + extend the value, which is really OK for unsigned types only. */ + else if (!(context && context->strict_signedness) + || TYPE_UNSIGNED (TREE_TYPE (loc)) + || (dwarf_strict && dwarf_version < 5) + || !is_a <scalar_int_mode> (mode, &int_mode) + || !(type_die = base_type_for_mode (mode, false))) + deref = new_loc_descr (DW_OP_deref_size, size, 0); + + /* Use DW_OP_deref_type for signed integral types if possible, but + convert back to the generic type to avoid type mismatches later. */ else - op = DW_OP_deref_size; + { + deref = new_loc_descr (dwarf_OP (DW_OP_deref_type), size, 0); + deref->dw_loc_oprnd2.val_class = dw_val_class_die_ref; + deref->dw_loc_oprnd2.v.val_die_ref.die = type_die; + deref->dw_loc_oprnd2.v.val_die_ref.external = 0; + add_loc_descr (&deref, + new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0)); + } if (ret) - add_loc_descr (&ret, new_loc_descr (op, size, 0)); + add_loc_descr (&ret, deref); else - add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0)); + add_loc_descr_to_each (list_ret, deref); } + if (ret) list_ret = new_loc_list (ret, NULL, 0, NULL, 0, NULL); @@ -19209,35 +19593,6 @@ round_up_to_align (const offset_int &t, unsigned int align) return wi::udiv_trunc (t + align - 1, align) * align; } -/* Compute the size of TYPE in bytes. If possible, return NULL and store the - size as an integer constant in CST_SIZE. Otherwise, if possible, return a - DWARF expression that computes the size. Return NULL and set CST_SIZE to -1 - if we fail to return the size in one of these two forms. */ - -static dw_loc_descr_ref -type_byte_size (const_tree type, HOST_WIDE_INT *cst_size) -{ - tree tree_size; - struct loc_descr_context ctx; - - /* Return a constant integer in priority, if possible. */ - *cst_size = int_size_in_bytes (type); - if (*cst_size != -1) - return NULL; - - ctx.context_type = const_cast<tree> (type); - ctx.base_decl = NULL_TREE; - ctx.dpi = NULL; - ctx.placeholder_arg = false; - ctx.placeholder_seen = false; - - type = TYPE_MAIN_VARIANT (type); - tree_size = TYPE_SIZE_UNIT (type); - return ((tree_size != NULL_TREE) - ? loc_descriptor_from_tree (tree_size, 0, &ctx) - : NULL); -} - /* Helper structure for RECORD_TYPE processing. */ struct vlr_context { @@ -19412,12 +19767,14 @@ field_byte_offset (const_tree decl, struct vlr_context *ctx, *cst_offset = wi::to_offset (tree_result).to_shwi (); return NULL; } + struct loc_descr_context loc_ctx = { ctx->struct_type, /* context_type */ NULL_TREE, /* base_decl */ NULL, /* dpi */ false, /* placeholder_arg */ - false /* placeholder_seen */ + false, /* placeholder_seen */ + false /* strict_signedness */ }; loc_result = loc_list_from_tree (tree_result, 0, &loc_ctx); @@ -19563,22 +19920,23 @@ add_data_member_location_attribute (dw_die_ref die, { loc_descr = field_byte_offset (decl, ctx, &offset); - /* If loc_descr is available then we know the field offset is dynamic. - However, GDB does not handle dynamic field offsets very well at the - moment. */ - if (loc_descr != NULL && gnat_encodings != DWARF_GNAT_ENCODINGS_MINIMAL) + if (!loc_descr) + ; + + /* If loc_descr is available, then we know the offset is dynamic. */ + else if (gnat_encodings == DWARF_GNAT_ENCODINGS_ALL) { loc_descr = NULL; offset = 0; } - /* Data member location evalutation starts with the base address on the + /* Data member location evaluation starts with the base address on the stack. Compute the field offset and add it to this base address. */ - else if (loc_descr != NULL) + else add_loc_descr (&loc_descr, new_loc_descr (DW_OP_plus, 0, 0)); } - if (! loc_descr) + if (!loc_descr) { /* While DW_AT_data_bit_offset has been added already in DWARF4, e.g. GDB only added support to it in November 2016. For DWARF5 @@ -19689,7 +20047,7 @@ insert_wide_int (const wide_int &val, unsigned char *dest, int elt_size) /* Writes floating point values to dw_vec_const array. */ -static void +static unsigned insert_float (const_rtx rtl, unsigned char *array) { long val[4]; @@ -19699,11 +20057,19 @@ insert_float (const_rtx rtl, unsigned char *array) real_to_target (val, CONST_DOUBLE_REAL_VALUE (rtl), mode); /* real_to_target puts 32-bit pieces in each long. Pack them. */ + if (GET_MODE_SIZE (mode) < 4) + { + gcc_assert (GET_MODE_SIZE (mode) == 2); + insert_int (val[0], 2, array); + return 2; + } + for (i = 0; i < GET_MODE_SIZE (mode) / 4; i++) { insert_int (val[i], 4, array); array += 4; } + return 4; } /* Attach a DW_AT_const_value attribute for a variable or a parameter which @@ -19732,8 +20098,9 @@ add_const_value_attribute (dw_die_ref die, rtx rtl) { wide_int w1 = rtx_mode_t (rtl, MAX_MODE_INT); unsigned int prec = MIN (wi::min_precision (w1, UNSIGNED), - (unsigned int)CONST_WIDE_INT_NUNITS (rtl) * HOST_BITS_PER_WIDE_INT); - wide_int w = wi::zext (w1, prec); + (unsigned int) CONST_WIDE_INT_NUNITS (rtl) + * HOST_BITS_PER_WIDE_INT); + wide_int w = wide_int::from (w1, prec, UNSIGNED); add_AT_wide (die, DW_AT_const_value, w); } return true; @@ -19752,9 +20119,10 @@ add_const_value_attribute (dw_die_ref die, rtx rtl) scalar_float_mode mode = as_a <scalar_float_mode> (GET_MODE (rtl)); unsigned int length = GET_MODE_SIZE (mode); unsigned char *array = ggc_vec_alloc<unsigned char> (length); + unsigned int elt_size = insert_float (rtl, array); - insert_float (rtl, array); - add_AT_vec (die, DW_AT_const_value, length / 4, 4, array); + add_AT_vec (die, DW_AT_const_value, length / elt_size, elt_size, + array); } return true; @@ -20632,7 +21000,7 @@ compute_frame_pointer_to_fb_displacement (poly_int64 offset) /* Generate a DW_AT_name attribute given some string value to be included as the value of the attribute. */ -static void +void add_name_attribute (dw_die_ref die, const char *name_string) { if (name_string != NULL && *name_string != 0) @@ -20890,6 +21258,7 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value, { if (get_AT (decl_die, DW_AT_location) || get_AT (decl_die, DW_AT_data_member_location) + || get_AT (decl_die, DW_AT_data_bit_offset) || get_AT (decl_die, DW_AT_const_value)) { add_AT_die_ref (die, attr, decl_die); @@ -21027,12 +21396,9 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, /* FALLTHRU */ default: - /* Because of the complex interaction there can be with other GNAT - encodings, GDB isn't ready yet to handle proper DWARF description - for self-referencial subrange bounds: let GNAT encodings do the - magic in such a case. */ + /* Let GNAT encodings do the magic for self-referential bounds. */ if (is_ada () - && gnat_encodings != DWARF_GNAT_ENCODINGS_MINIMAL + && gnat_encodings == DWARF_GNAT_ENCODINGS_ALL && contains_placeholder_p (bound)) return; @@ -21047,8 +21413,6 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing possibly nested array subscripts in a flat sequence if COLLAPSE_P is true. - Note that the block of subscript information for an array type also - includes information about the element type of the given array type. This function reuses previously set type and bound information if available. */ @@ -21056,9 +21420,21 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, static void add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p) { - unsigned dimension_number; - tree lower, upper; dw_die_ref child = type_die->die_child; + struct array_descr_info info; + int dimension_number; + + if (lang_hooks.types.get_array_descr_info) + { + memset (&info, 0, sizeof (info)); + if (lang_hooks.types.get_array_descr_info (type, &info)) + /* Fortran sometimes emits array types with no dimension. */ + gcc_assert (info.ndimensions >= 0 + && info.ndimensions + <= DWARF2OUT_ARRAY_DESCR_INFO_MAX_DIMEN); + } + else + info.ndimensions = 0; for (dimension_number = 0; TREE_CODE (type) == ARRAY_TYPE && (dimension_number == 0 || collapse_p); @@ -21106,26 +21482,22 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p) if (domain) { /* We have an array type with specified bounds. */ - lower = TYPE_MIN_VALUE (domain); - upper = TYPE_MAX_VALUE (domain); + tree lower = TYPE_MIN_VALUE (domain); + tree upper = TYPE_MAX_VALUE (domain); + tree index_type = TREE_TYPE (domain); - /* Define the index type. */ - if (TREE_TYPE (domain) - && !get_AT (subrange_die, DW_AT_type)) + if (dimension_number <= info.ndimensions - 1) { - /* ??? This is probably an Ada unnamed subrange type. Ignore the - TREE_TYPE field. We can't emit debug info for this - because it is an unnamed integral type. */ - if (TREE_CODE (domain) == INTEGER_TYPE - && TYPE_NAME (domain) == NULL_TREE - && TREE_CODE (TREE_TYPE (domain)) == INTEGER_TYPE - && TYPE_NAME (TREE_TYPE (domain)) == NULL_TREE) - ; - else - add_type_attribute (subrange_die, TREE_TYPE (domain), - TYPE_UNQUALIFIED, false, type_die); + lower = info.dimen[dimension_number].lower_bound; + upper = info.dimen[dimension_number].upper_bound; + index_type = info.dimen[dimension_number].bounds_type; } + /* Define the index type. */ + if (index_type && !get_AT (subrange_die, DW_AT_type)) + add_type_attribute (subrange_die, index_type, TYPE_UNQUALIFIED, + false, type_die); + /* ??? If upper is NULL, the array has unspecified length, but it does have a lower bound. This happens with Fortran dimension arr(N:*) @@ -21133,8 +21505,9 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p) to produce useful results, go ahead and output the lower bound solo, and hope the debugger can cope. */ - if (!get_AT (subrange_die, DW_AT_lower_bound)) + if (lower && !get_AT (subrange_die, DW_AT_lower_bound)) add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL); + if (!get_AT (subrange_die, DW_AT_upper_bound) && !get_AT (subrange_die, DW_AT_count)) { @@ -21160,7 +21533,6 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node) { dw_die_ref decl_die; HOST_WIDE_INT size; - dw_loc_descr_ref size_expr = NULL; switch (TREE_CODE (tree_node)) { @@ -21177,7 +21549,7 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node) add_AT_die_ref (die, DW_AT_byte_size, decl_die); return; } - size_expr = type_byte_size (tree_node, &size); + size = int_size_in_bytes (tree_node); break; case FIELD_DECL: /* For a data member of a struct or union, the DW_AT_byte_size is @@ -21190,19 +21562,32 @@ add_byte_size_attribute (dw_die_ref die, tree tree_node) gcc_unreachable (); } - /* Support for dynamically-sized objects was introduced by DWARFv3. - At the moment, GDB does not handle variable byte sizes very well, - though. */ - if ((dwarf_version >= 3 || !dwarf_strict) - && gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL - && size_expr != NULL) - add_AT_loc (die, DW_AT_byte_size, size_expr); - /* Note that `size' might be -1 when we get to this point. If it is, that - indicates that the byte size of the entity in question is variable and - that we could not generate a DWARF expression that computes it. */ + indicates that the byte size of the entity in question is variable. */ if (size >= 0) add_AT_unsigned (die, DW_AT_byte_size, size); + + /* Support for dynamically-sized objects was introduced in DWARF3. */ + else if (TYPE_P (tree_node) + && (dwarf_version >= 3 || !dwarf_strict) + && gnat_encodings != DWARF_GNAT_ENCODINGS_ALL) + { + struct loc_descr_context ctx = { + const_cast<tree> (tree_node), /* context_type */ + NULL_TREE, /* base_decl */ + NULL, /* dpi */ + false, /* placeholder_arg */ + false, /* placeholder_seen */ + false /* strict_signedness */ + }; + + tree tree_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (tree_node)); + add_scalar_info (die, DW_AT_byte_size, tree_size, + dw_scalar_form_constant + | dw_scalar_form_exprloc + | dw_scalar_form_reference, + &ctx); + } } /* Add a DW_AT_alignment attribute to DIE with TREE_NODE's non-default @@ -21863,6 +22248,7 @@ decl_start_label (tree decl) /* For variable-length arrays that have been previously generated, but may be incomplete due to missing subscript info, fill the subscript info. Return TRUE if this is one of those cases. */ + static bool fill_variable_array_bounds (tree type) { @@ -22034,8 +22420,14 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info, { const dw_die_ref scope_die = scope_die_for (type, context_die); const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type); - struct loc_descr_context context = { type, info->base_decl, NULL, - false, false }; + struct loc_descr_context context = { + type, /* context_type */ + info->base_decl, /* base_decl */ + NULL, /* dpi */ + false, /* placeholder_arg */ + false, /* placeholder_seen */ + false /* strict_signedness */ + }; enum dwarf_tag subrange_tag = DW_TAG_subrange_type; int dim; @@ -23378,7 +23770,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) resolve_variable_values (); } - /* Generate child dies for template paramaters. */ + /* Generate child dies for template parameters. */ if (early_dwarf && debug_info_level > DINFO_LEVEL_TERSE) gen_generic_params_dies (decl); @@ -24089,7 +24481,26 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) && DECL_RTL_SET_P (decl_or_origin)))) { if (early_dwarf) - add_pubname (decl_or_origin, var_die); + { + add_pubname (decl_or_origin, var_die); + /* For global register variables, emit DW_AT_location if possible + already during early_dwarf, as late_global_decl won't be usually + called. */ + if (DECL_HARD_REGISTER (decl_or_origin) + && TREE_STATIC (decl_or_origin) + && !decl_by_reference_p (decl_or_origin) + && !get_AT (var_die, DW_AT_location) + && !get_AT (var_die, DW_AT_const_value) + && DECL_RTL_SET_P (decl_or_origin) + && REG_P (DECL_RTL (decl_or_origin))) + { + dw_loc_descr_ref descr + = reg_loc_descriptor (DECL_RTL (decl_or_origin), + VAR_INIT_STATUS_INITIALIZED); + if (descr) + add_AT_loc (var_die, DW_AT_location, descr); + } + } else add_location_or_const_value_attribute (var_die, decl_or_origin, decl == NULL); @@ -24572,8 +24983,8 @@ gen_compile_unit_die (const char *filename) common_lang = TRANSLATION_UNIT_LANGUAGE (t); else if (strcmp (common_lang, TRANSLATION_UNIT_LANGUAGE (t)) == 0) ; - else if (strncmp (common_lang, "GNU C", 5) == 0 - && strncmp (TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0) + else if (startswith (common_lang, "GNU C") + && startswith (TRANSLATION_UNIT_LANGUAGE (t), "GNU C")) /* Mixing C and C++ is ok, use C++ in that case. */ common_lang = highest_c_language (common_lang, TRANSLATION_UNIT_LANGUAGE (t)); @@ -24590,7 +25001,7 @@ gen_compile_unit_die (const char *filename) } language = DW_LANG_C; - if (strncmp (language_string, "GNU C", 5) == 0 + if (startswith (language_string, "GNU C") && ISDIGIT (language_string[5])) { language = DW_LANG_C89; @@ -24606,7 +25017,7 @@ gen_compile_unit_die (const char *filename) language = DW_LANG_C11; } } - else if (strncmp (language_string, "GNU C++", 7) == 0) + else if (startswith (language_string, "GNU C++")) { language = DW_LANG_C_plus_plus; if (dwarf_version >= 5 /* || !dwarf_strict */) @@ -24628,7 +25039,7 @@ gen_compile_unit_die (const char *filename) { if (strcmp (language_string, "GNU Ada") == 0) language = DW_LANG_Ada95; - else if (strncmp (language_string, "GNU Fortran", 11) == 0) + else if (startswith (language_string, "GNU Fortran")) { language = DW_LANG_Fortran95; if (dwarf_version >= 5 /* || !dwarf_strict */) @@ -24652,7 +25063,7 @@ gen_compile_unit_die (const char *filename) } } /* Use a degraded Fortran setting in strict DWARF2 so is_fortran works. */ - else if (strncmp (language_string, "GNU Fortran", 11) == 0) + else if (startswith (language_string, "GNU Fortran")) language = DW_LANG_Fortran90; /* Likewise for Ada. */ else if (strcmp (language_string, "GNU Ada") == 0) @@ -25018,13 +25429,6 @@ gen_variant_part (tree variant_part_decl, struct vlr_context *vlr_ctx, { const tree variant_part_type = TREE_TYPE (variant_part_decl); tree variant_part_offset = vlr_ctx->variant_part_offset; - struct loc_descr_context ctx = { - vlr_ctx->struct_type, /* context_type */ - NULL_TREE, /* base_decl */ - NULL, /* dpi */ - false, /* placeholder_arg */ - false /* placeholder_seen */ - }; /* The FIELD_DECL node in STRUCT_TYPE that acts as the discriminant, or NULL_TREE if there is no such field. */ @@ -25055,11 +25459,19 @@ gen_variant_part (tree variant_part_decl, struct vlr_context *vlr_ctx, } /* If the offset for this variant part is more complex than a constant, - create a DWARF procedure for it so that we will not have to generate DWARF - expressions for it for each member. */ + create a DWARF procedure for it so that we will not have to generate + DWARF expressions for it for each member. */ if (TREE_CODE (variant_part_offset) != INTEGER_CST && (dwarf_version >= 3 || !dwarf_strict)) { + struct loc_descr_context ctx = { + vlr_ctx->struct_type, /* context_type */ + NULL_TREE, /* base_decl */ + NULL, /* dpi */ + false, /* placeholder_arg */ + false, /* placeholder_seen */ + false /* strict_signedness */ + }; const tree dwarf_proc_fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, NULL_TREE, build_function_type (TREE_TYPE (variant_part_offset), @@ -25240,11 +25652,11 @@ gen_member_die (tree type, dw_die_ref context_die) splice_child_die (context_die, child); } - /* Do not generate standard DWARF for variant parts if we are generating - the corresponding GNAT encodings: DIEs generated for both would - conflict in our mappings. */ + /* Do not generate DWARF for variant parts if we are generating the + corresponding GNAT encodings: DIEs generated for the two schemes + would conflict in our mappings. */ else if (is_variant_part (member) - && gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL) + && gnat_encodings != DWARF_GNAT_ENCODINGS_ALL) { vlr_ctx.variant_part_offset = byte_position (member); gen_variant_part (member, &vlr_ctx, context_die); @@ -25307,7 +25719,7 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die, scope_die = scope_die_for (type, context_die); - /* Generate child dies for template paramaters. */ + /* Generate child dies for template parameters. */ if (!type_die && debug_info_level > DINFO_LEVEL_TERSE) schedule_generic_params_dies_gen (type); @@ -27071,13 +27483,13 @@ dwarf2out_ignore_block (const_tree block) bool dwarf_file_hasher::equal (dwarf_file_data *p1, const char *p2) { - return filename_cmp (p1->filename, p2) == 0; + return filename_cmp (p1->key, p2) == 0; } hashval_t dwarf_file_hasher::hash (dwarf_file_data *p) { - return htab_hash_string (p->filename); + return htab_hash_string (p->key); } /* Lookup FILE_NAME (in the list of filenames that we know about here in @@ -27107,7 +27519,8 @@ lookup_filename (const char *file_name) return *slot; created = ggc_alloc<dwarf_file_data> (); - created->filename = file_name; + created->key = file_name; + created->filename = remap_debug_filename (file_name); created->emitted_number = 0; *slot = created; return created; @@ -27133,8 +27546,7 @@ maybe_emit_file (struct dwarf_file_data * fd) if (output_asm_line_debug_info ()) { fprintf (asm_out_file, "\t.file %u ", fd->emitted_number); - output_quoted_string (asm_out_file, - remap_debug_filename (fd->filename)); + output_quoted_string (asm_out_file, fd->filename); fputc ('\n', asm_out_file); } } @@ -27844,7 +28256,6 @@ dwarf2out_begin_function (tree fun) switch_to_section (sec); } - dwarf2out_note_section_used (); call_site_count = 0; tail_call_site_count = 0; @@ -27949,7 +28360,10 @@ dwarf2out_source_line (unsigned int line, unsigned int column, dw_line_info_table *table; static var_loc_view lvugid; - if (debug_info_level < DINFO_LEVEL_TERSE) + /* 'line_info_table' information gathering is not needed when the debug + info level is set to the lowest value. Also, the current DWARF-based + debug formats do not use this info. */ + if (debug_info_level < DINFO_LEVEL_TERSE || !dwarf_debuginfo_p ()) return; table = cur_line_info_table; @@ -28147,6 +28561,20 @@ dwarf2out_source_line (unsigned int line, unsigned int column, table->in_use = true; } +/* Record a source file location for a DECL_IGNORED_P function. */ + +static void +dwarf2out_set_ignored_loc (unsigned int line, unsigned int column, + const char *filename) +{ + dw_fde_ref fde = cfun->fde; + + fde->ignored_debug = false; + set_cur_line_info_table (function_section (fde->decl)); + + dwarf2out_source_line (line, column, filename, 0, true); +} + /* Record the beginning of a new source file. */ static void @@ -28823,6 +29251,10 @@ init_sections_and_labels (bool early_lto_debug) debug_macinfo_section = get_section (debug_macinfo_section_name, SECTION_DEBUG | SECTION_EXCLUDE, NULL); + if (dwarf_version >= 5) + debug_ranges_dwo_section + = get_section (DEBUG_DWO_RNGLISTS_SECTION, + SECTION_DEBUG | SECTION_EXCLUDE, NULL); } debug_aranges_section = get_section (DEBUG_ARANGES_SECTION, SECTION_DEBUG, NULL); @@ -28857,15 +29289,15 @@ init_sections_and_labels (bool early_lto_debug) ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label, DEBUG_LINE_SECTION_LABEL, init_sections_and_labels_generation); - /* There are up to 4 unique ranges labels per generation. + /* There are up to 6 unique ranges labels per generation. See also output_rnglists. */ ASM_GENERATE_INTERNAL_LABEL (ranges_section_label, DEBUG_RANGES_SECTION_LABEL, - init_sections_and_labels_generation * 4); + init_sections_and_labels_generation * 6); if (dwarf_version >= 5 && dwarf_split_debug_info) ASM_GENERATE_INTERNAL_LABEL (ranges_base_label, DEBUG_RANGES_SECTION_LABEL, - 1 + init_sections_and_labels_generation * 4); + 1 + init_sections_and_labels_generation * 6); ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label, DEBUG_ADDR_SECTION_LABEL, init_sections_and_labels_generation); @@ -28957,6 +29389,41 @@ dwarf2out_assembly_start (void) && dwarf2out_do_cfi_asm () && !dwarf2out_do_eh_frame ()) fprintf (asm_out_file, "\t.cfi_sections\t.debug_frame\n"); + +#if defined(HAVE_AS_GDWARF_5_DEBUG_FLAG) && defined(HAVE_AS_WORKING_DWARF_N_FLAG) + if (output_asm_line_debug_info () && dwarf_version >= 5) + { + /* When gas outputs DWARF5 .debug_line[_str] then we have to + tell it the comp_dir and main file name for the zero entry + line table. */ + const char *comp_dir, *filename0; + + comp_dir = comp_dir_string (); + if (comp_dir == NULL) + comp_dir = ""; + + filename0 = get_AT_string (comp_unit_die (), DW_AT_name); + if (filename0 == NULL) + filename0 = ""; + + fprintf (asm_out_file, "\t.file 0 "); + output_quoted_string (asm_out_file, remap_debug_filename (comp_dir)); + fputc (' ', asm_out_file); + output_quoted_string (asm_out_file, remap_debug_filename (filename0)); + fputc ('\n', asm_out_file); + } + else +#endif + /* Work around for PR101575: output a dummy .file directive. */ + if (!last_emitted_file && dwarf_debuginfo_p () + && debug_info_level >= DINFO_LEVEL_TERSE) + { + const char *filename0 = get_AT_string (comp_unit_die (), DW_AT_name); + + if (filename0 == NULL) + filename0 = "<dummy>"; + maybe_emit_file (lookup_filename (filename0)); + } } /* A helper function for dwarf2out_finish called through @@ -29827,6 +30294,40 @@ mark_base_types (dw_loc_descr_ref loc) } } +/* Stripped-down variant of resolve_addr, mark DW_TAG_base_type nodes + referenced from typed stack ops and count how often they are used. */ + +static void +mark_base_types (dw_die_ref die) +{ + dw_die_ref c; + dw_attr_node *a; + dw_loc_list_ref *curr; + unsigned ix; + + FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a) + switch (AT_class (a)) + { + case dw_val_class_loc_list: + curr = AT_loc_list_ptr (a); + while (*curr) + { + mark_base_types ((*curr)->expr); + curr = &(*curr)->dw_loc_next; + } + break; + + case dw_val_class_loc: + mark_base_types (AT_loc (a)); + break; + + default: + break; + } + + FOR_EACH_CHILD (die, c, mark_base_types (c)); +} + /* Comparison function for sorting marked base types. */ static int @@ -31451,6 +31952,15 @@ dwarf2out_finish (const char *filename) unsigned char checksum[16]; char dl_section_ref[MAX_ARTIFICIAL_LABEL_BYTES]; + /* Generate CTF/BTF debug info. */ + if ((ctf_debug_info_level > CTFINFO_LEVEL_NONE + || btf_debuginfo_p ()) && lang_GNU_C ()) + ctf_debug_finish (filename); + + /* Skip emitting DWARF if not required. */ + if (!dwarf_debuginfo_p ()) + return; + /* Flush out any latecomers to the limbo party. */ flush_limbo_die_list (); @@ -31580,30 +32090,68 @@ dwarf2out_finish (const char *filename) /* We can only use the low/high_pc attributes if all of the code was in .text. */ - if (!have_multiple_function_sections + if ((!have_multiple_function_sections + && vec_safe_length (switch_text_ranges) < 2) || (dwarf_version < 3 && dwarf_strict)) { + const char *end_label = text_end_label; + if (vec_safe_length (switch_text_ranges) == 1) + end_label = (*switch_text_ranges)[0]; /* Don't add if the CU has no associated code. */ - if (text_section_used) - add_AT_low_high_pc (main_comp_unit_die, text_section_label, - text_end_label, true); + if (switch_text_ranges) + add_AT_low_high_pc (main_comp_unit_die, text_section_label, + end_label, true); } else { unsigned fde_idx; dw_fde_ref fde; bool range_list_added = false; + if (switch_text_ranges) + { + const char *prev_loc = text_section_label; + const char *loc; + unsigned idx; + + FOR_EACH_VEC_ELT (*switch_text_ranges, idx, loc) + if (prev_loc) + { + add_ranges_by_labels (main_comp_unit_die, prev_loc, + loc, &range_list_added, true); + prev_loc = NULL; + } + else + prev_loc = loc; - if (text_section_used) - add_ranges_by_labels (main_comp_unit_die, text_section_label, - text_end_label, &range_list_added, true); - if (cold_text_section_used) - add_ranges_by_labels (main_comp_unit_die, cold_text_section_label, - cold_end_label, &range_list_added, true); + if (prev_loc) + add_ranges_by_labels (main_comp_unit_die, prev_loc, + text_end_label, &range_list_added, true); + } + + if (switch_cold_ranges) + { + const char *prev_loc = cold_text_section_label; + const char *loc; + unsigned idx; + + FOR_EACH_VEC_ELT (*switch_cold_ranges, idx, loc) + if (prev_loc) + { + add_ranges_by_labels (main_comp_unit_die, prev_loc, + loc, &range_list_added, true); + prev_loc = NULL; + } + else + prev_loc = loc; + + if (prev_loc) + add_ranges_by_labels (main_comp_unit_die, prev_loc, + cold_end_label, &range_list_added, true); + } FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde) { - if (DECL_IGNORED_P (fde->decl)) + if (fde->ignored_debug) continue; if (!fde->in_std_section) add_ranges_by_labels (main_comp_unit_die, fde->dw_fde_begin, @@ -31627,6 +32175,7 @@ dwarf2out_finish (const char *filename) add_AT_addr (main_comp_unit_die, DW_AT_entry_pc, const0_rtx, true); add_ranges (NULL); + have_multiple_function_sections = true; } } @@ -31665,6 +32214,9 @@ dwarf2out_finish (const char *filename) index_location_lists (comp_unit_die ()); } + if (dwarf_version >= 5 && !vec_safe_is_empty (ranges_table)) + index_rnglists (); + if (addr_index_table != NULL) { unsigned int index = 0; @@ -31730,9 +32282,6 @@ dwarf2out_finish (const char *filename) int mark; struct md5_ctx ctx; - if (dwarf_version >= 5 && !vec_safe_is_empty (ranges_table)) - index_rnglists (); - /* Compute a checksum of the comp_unit to use as the dwo_id. */ md5_init_ctx (&ctx); mark = 0; @@ -31752,10 +32301,7 @@ dwarf2out_finish (const char *filename) comp-unit DIE. */ if (!vec_safe_is_empty (ranges_table)) { - if (dwarf_version >= 5) - add_AT_lineptr (main_comp_unit_die, DW_AT_rnglists_base, - ranges_base_label); - else + if (dwarf_version < 5) add_AT_lineptr (main_comp_unit_die, DW_AT_GNU_ranges_base, ranges_section_label); } @@ -31833,7 +32379,22 @@ dwarf2out_finish (const char *filename) if (!vec_safe_is_empty (ranges_table)) { if (dwarf_version >= 5) - output_rnglists (generation); + { + if (dwarf_split_debug_info) + { + /* We don't know right now whether there are any + ranges for .debug_rnglists and any for .debug_rnglists.dwo. + Depending on into which of those two belongs the first + ranges_table entry, emit that section first and that + output_rnglists call will return true if the other kind of + ranges needs to be emitted as well. */ + bool dwo = (*ranges_table)[0].idx != DW_RANGES_IDX_SKELETON; + if (output_rnglists (generation, dwo)) + output_rnglists (generation, !dwo); + } + else + output_rnglists (generation, false); + } else output_ranges (); } @@ -31858,27 +32419,6 @@ dwarf2out_finish (const char *filename) ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label); if (! output_asm_line_debug_info ()) output_line_info (false); - else if (asm_outputs_debug_line_str ()) - { - /* When gas outputs DWARF5 .debug_line[_str] then we have to - tell it the comp_dir and main file name for the zero entry - line table. */ - const char *comp_dir, *filename0; - - comp_dir = comp_dir_string (); - if (comp_dir == NULL) - comp_dir = ""; - - filename0 = get_AT_string (comp_unit_die (), DW_AT_name); - if (filename0 == NULL) - filename0 = ""; - - fprintf (asm_out_file, "\t.file 0 "); - output_quoted_string (asm_out_file, remap_debug_filename (comp_dir)); - fputc (' ', asm_out_file); - output_quoted_string (asm_out_file, remap_debug_filename (filename0)); - fputc ('\n', asm_out_file); - } if (dwarf_split_debug_info && info_section_emitted) { @@ -32176,12 +32716,26 @@ note_variable_value (dw_die_ref die) FOR_EACH_CHILD (die, c, note_variable_value (c)); } +/* Process DWARF dies for CTF generation. */ + +static void +ctf_debug_do_cu (dw_die_ref die) +{ + dw_die_ref c; + + if (!ctf_do_die (die)) + return; + + FOR_EACH_CHILD (die, c, ctf_do_die (c)); +} + /* Perform any cleanups needed after the early debug generation pass has run. */ static void dwarf2out_early_finish (const char *filename) { + comdat_type_node *ctnode; set_early_dwarf s; char dl_section_ref[MAX_ARTIFICIAL_LABEL_BYTES]; @@ -32261,8 +32815,7 @@ dwarf2out_early_finish (const char *filename) /* For each new comdat type unit, copy declarations for incomplete types to make the new unit self-contained (i.e., no direct references to the main compile unit). */ - for (comdat_type_node *ctnode = comdat_type_list; - ctnode != NULL; ctnode = ctnode->next) + for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next) copy_decls_for_unworthy_types (ctnode->root_die); copy_decls_for_unworthy_types (comp_unit_die ()); @@ -32277,8 +32830,7 @@ dwarf2out_early_finish (const char *filename) note_variable_value (comp_unit_die ()); for (limbo_die_node *node = cu_die_list; node; node = node->next) note_variable_value (node->die); - for (comdat_type_node *ctnode = comdat_type_list; ctnode != NULL; - ctnode = ctnode->next) + for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next) note_variable_value (ctnode->root_die); for (limbo_die_node *node = limbo_die_list; node; node = node->next) note_variable_value (node->die); @@ -32298,6 +32850,20 @@ dwarf2out_early_finish (const char *filename) print_die (comp_unit_die (), dump_file); } + /* Generate CTF/BTF debug info. */ + if ((ctf_debug_info_level > CTFINFO_LEVEL_NONE + || btf_debuginfo_p ()) && lang_GNU_C ()) + { + ctf_debug_init (); + ctf_debug_do_cu (comp_unit_die ()); + for (limbo_die_node *node = limbo_die_list; node; node = node->next) + ctf_debug_do_cu (node->die); + /* Post process the debug data in the CTF container if necessary. */ + ctf_debug_init_postprocess (btf_debuginfo_p ()); + + ctf_debug_early_finish (filename); + } + /* Do not generate DWARF assembler now when not producing LTO bytecode. */ if ((!flag_generate_lto && !flag_generate_offload) /* FIXME: Disable debug info generation for (PE-)COFF targets since the @@ -32316,13 +32882,17 @@ dwarf2out_early_finish (const char *filename) location related output removed and some LTO specific changes. Some refactoring might make both smaller and easier to match up. */ + for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next) + mark_base_types (ctnode->root_die); + mark_base_types (comp_unit_die ()); + move_marked_base_types (); + /* Traverse the DIE's and add sibling attributes to those DIE's that have children. */ add_sibling_attributes (comp_unit_die ()); for (limbo_die_node *node = limbo_die_list; node; node = node->next) add_sibling_attributes (node->die); - for (comdat_type_node *ctnode = comdat_type_list; - ctnode != NULL; ctnode = ctnode->next) + for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next) add_sibling_attributes (ctnode->root_die); /* AIX Assembler inserts the length, so adjust the reference to match the @@ -32352,8 +32922,7 @@ dwarf2out_early_finish (const char *filename) output_comp_unit (node->die, 0, NULL); hash_table<comdat_type_hasher> comdat_type_table (100); - for (comdat_type_node *ctnode = comdat_type_list; - ctnode != NULL; ctnode = ctnode->next) + for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next) { comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT); @@ -32457,6 +33026,7 @@ dwarf2out_c_finalize (void) debug_str_dwo_section = NULL; debug_str_offsets_section = NULL; debug_ranges_section = NULL; + debug_ranges_dwo_section = NULL; debug_frame_section = NULL; fde_vec = NULL; debug_str_hash = NULL; @@ -32464,9 +33034,12 @@ dwarf2out_c_finalize (void) skeleton_debug_str_hash = NULL; dw2_string_counter = 0; have_multiple_function_sections = false; - text_section_used = false; - cold_text_section_used = false; + in_text_section_p = false; cold_text_section = NULL; + last_text_label = NULL; + last_cold_label = NULL; + switch_text_ranges = NULL; + switch_cold_ranges = NULL; current_unit_personality = NULL; early_dwarf = false; |