X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fdwarf2out.c;h=ac0258c98d39a8e5a36246de85fd36e44295d938;hb=e1688da489e851634921cfaa5b6e1c3a9ab5d377;hp=8dfe65d1fbec7cc6f384a2e4a247731cc89e7ba1;hpb=95a523745131a4aa45828df36769ffefeaac1df7;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 8dfe65d1fbe..ac0258c98d3 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -79,7 +79,6 @@ along with GCC; see the file COPYING3. If not see #include "dwarf2out.h" #include "dwarf2asm.h" #include "toplev.h" -#include "varray.h" #include "ggc.h" #include "md5.h" #include "tm_p.h" @@ -1040,7 +1039,7 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p) cfi = new_cfi (); - if (loc.reg == old_cfa.reg && !loc.indirect) + if (loc.reg == old_cfa.reg && !loc.indirect && !old_cfa.indirect) { /* Construct a "DW_CFA_def_cfa_offset " instruction, indicating the CFA register did not change but the offset did. The data @@ -1056,7 +1055,8 @@ def_cfa_1 (const char *label, dw_cfa_location *loc_p) #ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */ else if (loc.offset == old_cfa.offset && old_cfa.reg != INVALID_REGNUM - && !loc.indirect) + && !loc.indirect + && !old_cfa.indirect) { /* Construct a "DW_CFA_def_cfa_register " instruction, indicating the CFA register has changed to but the @@ -1115,8 +1115,8 @@ reg_save (const char *label, unsigned int reg, unsigned int sreg, HOST_WIDE_INT && sreg == INVALID_REGNUM) { cfi->dw_cfi_opc = DW_CFA_expression; - cfi->dw_cfi_oprnd2.dw_cfi_reg_num = reg; - cfi->dw_cfi_oprnd1.dw_cfi_loc + cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg; + cfi->dw_cfi_oprnd2.dw_cfi_loc = build_cfa_aligned_loc (offset, fde->stack_realignment); } else if (sreg == INVALID_REGNUM) @@ -2911,6 +2911,7 @@ dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi) case DW_CFA_same_value: case DW_CFA_def_cfa_register: case DW_CFA_register: + case DW_CFA_expression: return dw_cfi_oprnd_reg_num; case DW_CFA_def_cfa_offset: @@ -2919,7 +2920,6 @@ dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi) return dw_cfi_oprnd_offset; case DW_CFA_def_cfa_expression: - case DW_CFA_expression: return dw_cfi_oprnd_loc; default: @@ -2946,6 +2946,9 @@ dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi) case DW_CFA_register: return dw_cfi_oprnd_reg_num; + case DW_CFA_expression: + return dw_cfi_oprnd_loc; + default: return dw_cfi_oprnd_unused; } @@ -3048,7 +3051,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh) { r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh); dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)), - "DW_CFA_offset, column 0x%lx", r); + "DW_CFA_offset, column %#lx", r); off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset); dw2_asm_output_data_uleb128 (off, NULL); } @@ -3056,7 +3059,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh) { r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh); dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)), - "DW_CFA_restore, column 0x%lx", r); + "DW_CFA_restore, column %#lx", r); } else { @@ -3248,7 +3251,7 @@ output_cfi_directive (dw_cfi_ref cfi) break; case DW_CFA_GNU_args_size: - fprintf (asm_out_file, "\t.cfi_escape 0x%x,", DW_CFA_GNU_args_size); + fprintf (asm_out_file, "\t.cfi_escape %#x,", DW_CFA_GNU_args_size); dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset); if (flag_debug_asm) fprintf (asm_out_file, "\t%s args_size "HOST_WIDE_INT_PRINT_DEC, @@ -3262,7 +3265,7 @@ output_cfi_directive (dw_cfi_ref cfi) case DW_CFA_def_cfa_expression: case DW_CFA_expression: - fprintf (asm_out_file, "\t.cfi_escape 0x%x,", cfi->dw_cfi_opc); + fprintf (asm_out_file, "\t.cfi_escape %#x,", cfi->dw_cfi_opc); output_cfa_loc_raw (cfi); fputc ('\n', asm_out_file); break; @@ -3768,6 +3771,11 @@ output_call_frame_info (int for_eh) } dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation"); + if (dw_cie_version >= 4) + { + dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "CIE Address Size"); + dw2_asm_output_data (1, 0, "CIE Segment Size"); + } dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor"); dw2_asm_output_data_sleb128 (DWARF_CIE_DATA_ALIGNMENT, "CIE Data Alignment Factor"); @@ -3860,7 +3868,7 @@ dwarf2out_do_cfi_startproc (bool second) if (enc & DW_EH_PE_indirect) ref = dw2_force_const_mem (ref, true); - fprintf (asm_out_file, "\t.cfi_personality 0x%x,", enc); + fprintf (asm_out_file, "\t.cfi_personality %#x,", enc); output_addr_const (asm_out_file, ref); fputc ('\n', asm_out_file); } @@ -3878,7 +3886,7 @@ dwarf2out_do_cfi_startproc (bool second) if (enc & DW_EH_PE_indirect) ref = dw2_force_const_mem (ref, true); - fprintf (asm_out_file, "\t.cfi_lsda 0x%x,", enc); + fprintf (asm_out_file, "\t.cfi_lsda %#x,", enc); output_addr_const (asm_out_file, ref); fputc ('\n', asm_out_file); } @@ -5172,7 +5180,7 @@ output_loc_sequence_raw (dw_loc_descr_ref loc) while (1) { /* Output the opcode. */ - fprintf (asm_out_file, "0x%x", loc->dw_loc_opc); + fprintf (asm_out_file, "%#x", loc->dw_loc_opc); output_loc_operands_raw (loc); if (!loc->dw_loc_next) @@ -5193,10 +5201,14 @@ output_cfa_loc (dw_cfi_ref cfi) unsigned long size; if (cfi->dw_cfi_opc == DW_CFA_expression) - dw2_asm_output_data (1, cfi->dw_cfi_oprnd2.dw_cfi_reg_num, NULL); + { + dw2_asm_output_data (1, cfi->dw_cfi_oprnd1.dw_cfi_reg_num, NULL); + loc = cfi->dw_cfi_oprnd2.dw_cfi_loc; + } + else + loc = cfi->dw_cfi_oprnd1.dw_cfi_loc; /* Output the size of the block. */ - loc = cfi->dw_cfi_oprnd1.dw_cfi_loc; size = size_of_locs (loc); dw2_asm_output_data_uleb128 (size, NULL); @@ -5213,10 +5225,14 @@ output_cfa_loc_raw (dw_cfi_ref cfi) unsigned long size; if (cfi->dw_cfi_opc == DW_CFA_expression) - fprintf (asm_out_file, "0x%x,", cfi->dw_cfi_oprnd2.dw_cfi_reg_num); + { + fprintf (asm_out_file, "%#x,", cfi->dw_cfi_oprnd1.dw_cfi_reg_num); + loc = cfi->dw_cfi_oprnd2.dw_cfi_loc; + } + else + loc = cfi->dw_cfi_oprnd1.dw_cfi_loc; /* Output the size of the block. */ - loc = cfi->dw_cfi_oprnd1.dw_cfi_loc; size = size_of_locs (loc); dw2_asm_output_data_uleb128_raw (size); fputc (',', asm_out_file); @@ -5399,6 +5415,7 @@ static void dwarf2out_define (unsigned int, const char *); static void dwarf2out_undef (unsigned int, const char *); static void dwarf2out_start_source_file (unsigned, const char *); static void dwarf2out_end_source_file (unsigned); +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); @@ -5436,7 +5453,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = dwarf2out_end_epilogue, dwarf2out_begin_function, debug_nothing_int, /* end_function */ - dwarf2out_decl, /* function_decl */ + dwarf2out_function_decl, /* function_decl */ dwarf2out_global_decl, dwarf2out_type_decl, /* type_decl */ dwarf2out_imported_module_or_decl, @@ -5677,6 +5694,11 @@ skeleton_chain_node; is not made available by the GCC front-end. */ #define DWARF_LINE_DEFAULT_IS_STMT_START 1 +/* Maximum number of operations per instruction bundle. */ +#ifndef DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN +#define DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN 1 +#endif + #ifdef DWARF2_DEBUGGING_INFO /* This location is used by calc_die_sizes() to keep track the offset of each DIE within the .debug_info section. */ @@ -5693,8 +5715,7 @@ static GTY(()) comdat_type_node *comdat_type_list; static GTY(()) limbo_die_node *limbo_die_list; /* A list of DIEs for which we may have to generate - DW_AT_MIPS_linkage_name once their DECL_ASSEMBLER_NAMEs are - set. */ + DW_AT_{,MIPS_}linkage_name once their DECL_ASSEMBLER_NAMEs are set. */ static GTY(()) limbo_die_node *deferred_asm_name; /* Filenames referenced by this compilation unit. */ @@ -5720,7 +5741,6 @@ DEF_VEC_ALLOC_O(die_arg_entry,gc); struct GTY ((chain_next ("%h.next"))) var_loc_node { rtx GTY (()) var_loc_note; const char * GTY (()) label; - const char * GTY (()) section_label; struct var_loc_node * GTY (()) next; }; @@ -5728,8 +5748,12 @@ struct GTY ((chain_next ("%h.next"))) var_loc_node { struct GTY (()) var_loc_list_def { struct var_loc_node * GTY (()) first; - /* Do not mark the last element of the chained list because - it is marked through the chain. */ + /* Pointer to the last but one or last element of the + chained list. If the list is empty, both first and + last are NULL, if the list contains just one node + or the last node certainly is not redundant, it points + to the last node, otherwise points to the last but one. + Do not mark it for GC because it is marked through the chain. */ struct var_loc_node * GTY ((skip ("%h"))) last; /* DECL_UID of the variable decl. */ @@ -5953,9 +5977,7 @@ 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_family (void); static bool is_cxx (void); -static bool is_java (void); static bool is_fortran (void); static bool is_ada (void); static void remove_AT (dw_die_ref, enum dwarf_attribute); @@ -5973,7 +5995,7 @@ static hashval_t decl_loc_table_hash (const void *); static int decl_loc_table_eq (const void *, const void *); static var_loc_list *lookup_decl_loc (const_tree); static void equate_decl_number_to_die (tree, dw_die_ref); -static struct var_loc_node *add_var_loc_to_decl (tree, rtx); +static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *); static void print_spaces (FILE *); static void print_die (dw_die_ref, FILE *); static void print_dwarf_line_table (FILE *); @@ -6259,6 +6281,12 @@ static void gen_remaining_tmpl_value_param_die_attribute (void); #define DEBUG_MACINFO_SECTION_LABEL "Ldebug_macinfo" #endif +/* Mangled name attribute to use. This used to be a vendor extension + until DWARF 4 standardized it. */ +#define AT_linkage_name \ + (dwarf_version >= 4 ? DW_AT_linkage_name : DW_AT_MIPS_linkage_name) + + /* Definitions of defaults for formats and names of various special (artificial) labels which may be generated within this file (when the -g options is used and DWARF2_DEBUGGING_INFO is in effect. @@ -7432,18 +7460,6 @@ get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind) return a ? AT_file (a) : NULL; } -/* Return TRUE if the language is C or C++. */ - -static inline bool -is_c_family (void) -{ - unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); - - return (lang == DW_LANG_C || lang == DW_LANG_C89 || lang == DW_LANG_ObjC - || lang == DW_LANG_C99 - || lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus); -} - /* Return TRUE if the language is C++. */ static inline bool @@ -7466,16 +7482,6 @@ is_fortran (void) || lang == DW_LANG_Fortran95); } -/* Return TRUE if the language is Java. */ - -static inline bool -is_java (void) -{ - unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); - - return lang == DW_LANG_Java; -} - /* Return TRUE if the language is Ada. */ static inline bool @@ -7753,7 +7759,7 @@ equate_decl_number_to_die (tree decl, dw_die_ref decl_die) /* Add a variable location node to the linked list for DECL. */ static struct var_loc_node * -add_var_loc_to_decl (tree decl, rtx loc_note) +add_var_loc_to_decl (tree decl, rtx loc_note, const char *label) { unsigned int decl_id = DECL_UID (decl); var_loc_list *temp; @@ -7772,23 +7778,62 @@ add_var_loc_to_decl (tree decl, rtx loc_note) if (temp->last) { + struct var_loc_node *last = temp->last, *unused = NULL; + if (last->next) + { + last = last->next; + gcc_assert (last->next == NULL); + } + /* TEMP->LAST here is either pointer to the last but one or + last element in the chained list, LAST is pointer to the + last element. */ + /* If the last note doesn't cover any instructions, remove it. */ + if (label && strcmp (last->label, label) == 0) + { + if (temp->last != last) + { + temp->last->next = NULL; + unused = last; + last = temp->last; + gcc_assert (strcmp (last->label, label) != 0); + } + else + { + gcc_assert (temp->first == temp->last); + memset (temp->last, '\0', sizeof (*temp->last)); + return temp->last; + } + } /* If the current location is the same as the end of the list, and either both or neither of the locations is uninitialized, we have nothing to do. */ - if ((!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->var_loc_note), + if ((!rtx_equal_p (NOTE_VAR_LOCATION_LOC (last->var_loc_note), NOTE_VAR_LOCATION_LOC (loc_note))) - || ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note) + || ((NOTE_VAR_LOCATION_STATUS (last->var_loc_note) != NOTE_VAR_LOCATION_STATUS (loc_note)) - && ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note) + && ((NOTE_VAR_LOCATION_STATUS (last->var_loc_note) == VAR_INIT_STATUS_UNINITIALIZED) || (NOTE_VAR_LOCATION_STATUS (loc_note) == VAR_INIT_STATUS_UNINITIALIZED)))) { - /* Add LOC to the end of list and update LAST. */ - loc = GGC_CNEW (struct var_loc_node); - temp->last->next = loc; - temp->last = loc; + /* Add LOC to the end of list and update LAST. If the last + element of the list has been removed above, reuse its + memory for the new node, otherwise allocate a new one. */ + if (unused) + { + loc = unused; + memset (loc, '\0', sizeof (*loc)); + } + else + loc = GGC_CNEW (struct var_loc_node); + last->next = loc; + /* Ensure TEMP->LAST will point either to the new last but one + element of the chain, or to the last element in it. */ + if (last != temp->last) + temp->last = last; } + else if (unused) + ggc_free (unused); } else { @@ -8253,6 +8298,7 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at, if ((at->dw_attr == DW_AT_type && (tag == DW_TAG_pointer_type || tag == DW_TAG_reference_type + || tag == DW_TAG_rvalue_reference_type || tag == DW_TAG_ptr_to_member_type)) || (at->dw_attr == DW_AT_friend && tag == DW_TAG_friend)) @@ -8967,6 +9013,7 @@ is_type_die (dw_die_ref die) case DW_TAG_enumeration_type: case DW_TAG_pointer_type: case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: case DW_TAG_string_type: case DW_TAG_structure_type: case DW_TAG_subroutine_type: @@ -9004,6 +9051,7 @@ is_comdat_die (dw_die_ref c) if (c->die_tag == DW_TAG_pointer_type || c->die_tag == DW_TAG_reference_type + || c->die_tag == DW_TAG_rvalue_reference_type || c->die_tag == DW_TAG_const_type || c->die_tag == DW_TAG_volatile_type) { @@ -9252,6 +9300,7 @@ should_move_die_to_comdat (dw_die_ref die) case DW_TAG_interface_type: case DW_TAG_pointer_type: case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: case DW_TAG_string_type: case DW_TAG_subroutine_type: case DW_TAG_ptr_to_member_type: @@ -9335,6 +9384,7 @@ clone_as_declaration (dw_die_ref die) case DW_AT_name: case DW_AT_type: case DW_AT_virtuality: + case DW_AT_linkage_name: case DW_AT_MIPS_linkage_name: add_dwarf_attr (clone, a); break; @@ -9909,7 +9959,10 @@ size_of_die (dw_die_ref die) unsigned long lsize = size_of_locs (AT_loc (a)); /* Block length. */ - size += constant_size (lsize); + if (dwarf_version >= 4) + size += size_of_uleb128 (lsize); + else + size += constant_size (lsize); size += lsize; } break; @@ -9937,7 +9990,16 @@ size_of_die (dw_die_ref die) * a->dw_attr_val.v.val_vec.elt_size; /* block */ break; case dw_val_class_flag: - size += 1; + if (dwarf_version >= 4) + /* Currently all add_AT_flag calls pass in 1 as last argument, + so DW_FORM_flag_present can be used. If that ever changes, + we'll need to use DW_FORM_flag and have some optimization + in build_abbrev_table that will change those to + DW_FORM_flag_present if it is set to 1 in all DIEs using + the same abbrev entry. */ + gcc_assert (a->dw_attr_val.v.val_flag == 1); + else + size += 1; break; case dw_val_class_die_ref: if (AT_ref_external (a)) @@ -10131,8 +10193,11 @@ value_format (dw_attr_ref a) gcc_unreachable (); } case dw_val_class_range_list: - case dw_val_class_offset: case dw_val_class_loc_list: + if (dwarf_version >= 4) + return DW_FORM_sec_offset; + /* FALLTHRU */ + case dw_val_class_offset: switch (DWARF_OFFSET_SIZE) { case 4: @@ -10143,6 +10208,8 @@ value_format (dw_attr_ref a) gcc_unreachable (); } case dw_val_class_loc: + if (dwarf_version >= 4) + return DW_FORM_exprloc; switch (constant_size (size_of_locs (AT_loc (a)))) { case 1: @@ -10195,6 +10262,17 @@ value_format (dw_attr_ref a) gcc_unreachable (); } case dw_val_class_flag: + if (dwarf_version >= 4) + { + /* Currently all add_AT_flag calls pass in 1 as last argument, + so DW_FORM_flag_present can be used. If that ever changes, + we'll need to use DW_FORM_flag and have some optimization + in build_abbrev_table that will change those to + DW_FORM_flag_present if it is set to 1 in all DIEs using + the same abbrev entry. */ + gcc_assert (a->dw_attr_val.v.val_flag == 1); + return DW_FORM_flag_present; + } return DW_FORM_flag; case dw_val_class_die_ref: if (AT_ref_external (a)) @@ -10207,7 +10285,7 @@ value_format (dw_attr_ref a) return DW_FORM_addr; case dw_val_class_lineptr: case dw_val_class_macptr: - return DW_FORM_data; + return dwarf_version >= 4 ? DW_FORM_sec_offset : DW_FORM_data; case dw_val_class_str: return AT_string_form (a); case dw_val_class_file: @@ -10404,7 +10482,7 @@ output_die (dw_die_ref die) if (dwarf_version < 4 && die->die_id.die_symbol) output_die_symbol (die); - dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (0x%lx) %s)", + dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)", (unsigned long)die->die_offset, dwarf_tag_name (die->die_tag)); @@ -10439,7 +10517,10 @@ output_die (dw_die_ref die) size = size_of_locs (AT_loc (a)); /* Output the block length for this list of location operations. */ - dw2_asm_output_data (constant_size (size), size, "%s", name); + if (dwarf_version >= 4) + dw2_asm_output_data_uleb128 (size, "%s", name); + else + dw2_asm_output_data (constant_size (size), size, "%s", name); output_loc_sequence (AT_loc (a)); break; @@ -10507,6 +10588,20 @@ output_die (dw_die_ref die) } case dw_val_class_flag: + if (dwarf_version >= 4) + { + /* Currently all add_AT_flag calls pass in 1 as last argument, + so DW_FORM_flag_present can be used. If that ever changes, + we'll need to use DW_FORM_flag and have some optimization + in build_abbrev_table that will change those to + DW_FORM_flag_present if it is set to 1 in all DIEs using + the same abbrev entry. */ + gcc_assert (AT_flag (a) == 1); + if (flag_debug_asm) + fprintf (asm_out_file, "\t\t\t%s %s\n", + ASM_COMMENT_START, name); + break; + } dw2_asm_output_data (1, AT_flag (a), "%s", name); break; @@ -10619,7 +10714,7 @@ output_die (dw_die_ref die) /* Add null byte to terminate sibling list. */ if (die->die_child != NULL) - dw2_asm_output_data (1, 0, "end of children of DIE 0x%lx", + dw2_asm_output_data (1, 0, "end of children of DIE %#lx", (unsigned long) die->die_offset); } @@ -10631,11 +10726,6 @@ output_compilation_unit_header (void) { int ver = dwarf_version; - /* Don't mark the output as DWARF-4 until we make full use of the - version 4 extensions, and gdb supports them. For now, -gdwarf-4 - selects only a few extensions from the DWARF-4 spec. */ - if (ver > 3) - ver = 3; if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) dw2_asm_output_data (4, 0xffffffff, "Initial length escape value indicating 64-bit DWARF extension"); @@ -11050,7 +11140,7 @@ static void output_ranges (void) { unsigned i; - static const char *const start_fmt = "Offset 0x%x"; + static const char *const start_fmt = "Offset %#x"; const char *fmt = start_fmt; for (i = 0; i < ranges_table_in_use; i++) @@ -11392,7 +11482,7 @@ output_file_names (void) dw2_asm_output_nstring (dirs[i].path, dirs[i].length - !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR, - "Directory Entry: 0x%x", i + idx_offset); + "Directory Entry: %#x", i + idx_offset); dw2_asm_output_data (1, 0, "End directory table"); @@ -11428,7 +11518,7 @@ output_file_names (void) files[file_idx].path + dirs[dir_idx].length, ver); dw2_asm_output_nstring - (filebuf, -1, "File Entry: 0x%x", (unsigned) i + 1); + (filebuf, -1, "File Entry: %#x", (unsigned) i + 1); /* Include directory index. */ dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL); @@ -11446,7 +11536,7 @@ output_file_names (void) NULL); #else dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1, - "File Entry: 0x%x", (unsigned) i + 1); + "File Entry: %#x", (unsigned) i + 1); /* Include directory index. */ dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL); @@ -11482,12 +11572,6 @@ output_line_info (void) unsigned long function; int ver = dwarf_version; - /* Don't mark the output as DWARF-4 until we make full use of the - version 4 extensions, and gdb supports them. For now, -gdwarf-4 - selects only a few extensions from the DWARF-4 spec. */ - if (ver > 3) - ver = 3; - ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, 0); ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, 0); ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0); @@ -11515,6 +11599,9 @@ output_line_info (void) dw2_asm_output_data (1, 1, "Minimum Instruction Length"); + if (ver >= 4) + dw2_asm_output_data (1, DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN, + "Maximum Operations Per Instruction"); dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START, "Default is_stmt_start flag"); dw2_asm_output_data (1, DWARF_LINE_BASE, @@ -11540,7 +11627,7 @@ output_line_info (void) break; } - dw2_asm_output_data (1, n_op_args, "opcode: 0x%x has %d args", + dw2_asm_output_data (1, n_op_args, "opcode: %#x has %d args", opc, n_op_args); } @@ -12117,7 +12204,8 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type, name = qualified_type ? TYPE_NAME (qualified_type) : NULL; /* Handle C typedef types. */ - if (name && TREE_CODE (name) == TYPE_DECL && DECL_ORIGINAL_TYPE (name)) + if (name && TREE_CODE (name) == TYPE_DECL && DECL_ORIGINAL_TYPE (name) + && !DECL_ARTIFICIAL (name)) { tree dtype = TREE_TYPE (name); @@ -12162,7 +12250,11 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type, } else if (code == REFERENCE_TYPE) { - mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type); + if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4) + mod_type_die = new_die (DW_TAG_rvalue_reference_type, comp_unit_die, + type); + else + mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type); add_AT_unsigned (mod_type_die, DW_AT_byte_size, simple_type_size_in_bits (type) / BITS_PER_UNIT); item_type = TREE_TYPE (type); @@ -13572,6 +13664,10 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, case POPCOUNT: case PARITY: case ASM_OPERANDS: + case VEC_MERGE: + case VEC_SELECT: + case VEC_CONCAT: + case VEC_DUPLICATE: case UNSPEC: case HIGH: /* If delegitimize_address couldn't do anything with the UNSPEC, we @@ -13716,10 +13812,12 @@ loc_descriptor (rtx rtl, enum machine_mode mode, case VAR_LOCATION: /* Single part. */ - if (GET_CODE (XEXP (rtl, 1)) != PARALLEL) + if (GET_CODE (PAT_VAR_LOCATION_LOC (rtl)) != PARALLEL) { - loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), mode, - initialized); + rtx loc = PAT_VAR_LOCATION_LOC (rtl); + if (GET_CODE (loc) == EXPR_LIST) + loc = XEXP (loc, 0); + loc_result = loc_descriptor (loc, mode, initialized); break; } @@ -13971,9 +14069,11 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address, { gcc_assert (GET_CODE (varloc) == VAR_LOCATION); /* Single part. */ - if (GET_CODE (XEXP (varloc, 1)) != PARALLEL) + if (GET_CODE (PAT_VAR_LOCATION_LOC (varloc)) != PARALLEL) { - varloc = XEXP (XEXP (varloc, 1), 0); + varloc = PAT_VAR_LOCATION_LOC (varloc); + if (GET_CODE (varloc) == EXPR_LIST) + varloc = XEXP (varloc, 0); mode = GET_MODE (varloc); if (MEM_P (varloc)) { @@ -15770,10 +15870,7 @@ rtl_for_decl_location (tree decl) && !DECL_HARD_REGISTER (decl) && DECL_MODE (decl) != VOIDmode) { - rtl = DECL_RTL (decl); - /* Reset DECL_RTL back, as various parts of the compiler expects - DECL_RTL set meaning it is actually going to be output. */ - SET_DECL_RTL (decl, NULL); + rtl = make_decl_rtl_for_debug (decl); if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF || SYMBOL_REF_DECL (XEXP (rtl, 0)) != decl) @@ -15871,7 +15968,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, loc_list = lookup_decl_loc (decl); if (loc_list && loc_list->first - && loc_list->first == loc_list->last + && loc_list->first->next == NULL && NOTE_VAR_LOCATION (loc_list->first->var_loc_note) && NOTE_VAR_LOCATION_LOC (loc_list->first->var_loc_note)) { @@ -15879,7 +15976,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, node = loc_list->first; rtl = NOTE_VAR_LOCATION_LOC (node->var_loc_note); - if (GET_CODE (rtl) != PARALLEL) + if (GET_CODE (rtl) == EXPR_LIST) rtl = XEXP (rtl, 0); if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING) && add_const_value_attribute (die, rtl)) @@ -16278,14 +16375,49 @@ add_comp_dir_attribute (dw_die_ref die) add_AT_string (die, DW_AT_comp_dir, remap_debug_filename (wd)); } +/* Return the default for DW_AT_lower_bound, or -1 if there is not any + default. */ + +static int +lower_bound_default (void) +{ + switch (get_AT_unsigned (comp_unit_die, DW_AT_language)) + { + case DW_LANG_C: + case DW_LANG_C89: + case DW_LANG_C99: + case DW_LANG_C_plus_plus: + case DW_LANG_ObjC: + case DW_LANG_ObjC_plus_plus: + case DW_LANG_Java: + return 0; + case DW_LANG_Fortran77: + case DW_LANG_Fortran90: + case DW_LANG_Fortran95: + return 1; + case DW_LANG_UPC: + case DW_LANG_D: + case DW_LANG_Python: + return dwarf_version >= 4 ? 0 : -1; + case DW_LANG_Ada95: + case DW_LANG_Ada83: + case DW_LANG_Cobol74: + case DW_LANG_Cobol85: + case DW_LANG_Pascal83: + case DW_LANG_Modula2: + case DW_LANG_PLI: + return dwarf_version >= 4 ? 1 : -1; + default: + return -1; + } +} + /* Given a tree node describing an array bound (either lower or upper) output a representation for that bound. */ static void add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound) { - int want_address = 2; - switch (TREE_CODE (bound)) { case ERROR_MARK: @@ -16295,11 +16427,13 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b case INTEGER_CST: { unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound)); + int dflt; /* Use the default if possible. */ if (bound_attr == DW_AT_lower_bound - && (((is_c_family () || is_java ()) && integer_zerop (bound)) - || (is_fortran () && integer_onep (bound)))) + && host_integerp (bound, 0) + && (dflt = lower_bound_default ()) != -1 + && tree_low_cst (bound, 0) == dflt) ; /* Otherwise represent the bound as an unsigned value with the @@ -16346,7 +16480,6 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b add_AT_die_ref (subrange_die, bound_attr, decl_die); break; } - want_address = 0; } /* FALLTHRU */ @@ -16358,15 +16491,23 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b dw_die_ref ctx, decl_die; dw_loc_list_ref list; - list = loc_list_from_tree (bound, want_address); - if (list == NULL) - break; - - if (single_element_loc_list_p (list)) + list = loc_list_from_tree (bound, 2); + if (list == NULL || single_element_loc_list_p (list)) { - add_AT_loc (subrange_die, bound_attr, list->expr); - break; + /* If DW_AT_*bound is not a reference nor constant, it is + a DWARF expression rather than location description. + For that loc_list_from_tree (bound, 0) is needed. + If that fails to give a single element list, + fall back to outputting this as a reference anyway. */ + dw_loc_list_ref list2 = loc_list_from_tree (bound, 0); + if (list2 && single_element_loc_list_p (list2)) + { + add_AT_loc (subrange_die, bound_attr, list2->expr); + break; + } } + if (list == NULL) + break; if (current_function_decl == 0) ctx = comp_unit_die; @@ -16667,8 +16808,7 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl) if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) && TREE_PUBLIC (decl) && !DECL_ABSTRACT (decl) - && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl)) - && !is_fortran ()) + && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))) { /* Defer until we have an assembler name set. */ if (!DECL_ASSEMBLER_NAME_SET_P (decl)) @@ -16682,7 +16822,7 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl) deferred_asm_name = asm_name; } else if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)) - add_AT_string (die, DW_AT_MIPS_linkage_name, + add_AT_string (die, AT_linkage_name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); } } @@ -17200,11 +17340,11 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info, if (info->dimen[dim].lower_bound) { /* If it is the default value, omit it. */ - if ((is_c_family () || is_java ()) - && integer_zerop (info->dimen[dim].lower_bound)) - ; - else if (is_fortran () - && integer_onep (info->dimen[dim].lower_bound)) + int dflt; + + if (host_integerp (info->dimen[dim].lower_bound, 0) + && (dflt = lower_bound_default ()) != -1 + && tree_low_cst (info->dimen[dim].lower_bound, 0) == dflt) ; else add_descr_info_field (subrange_die, DW_AT_lower_bound, @@ -17307,6 +17447,9 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die) scope_die_for (type, context_die), type); equate_type_number_to_die (type, type_die); add_name_attribute (type_die, type_tag (type)); + if ((dwarf_version >= 4 || !dwarf_strict) + && ENUM_IS_SCOPED (type)) + add_AT_flag (type_die, DW_AT_enum_class, 1); } else if (! TYPE_SIZE (type)) return type_die; @@ -18222,9 +18365,9 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die) /* If the compiler emitted a definition for the DECL declaration and if we already emitted a DIE for it, don't emit a second - DIE for it again. */ - if (old_die - && declaration) + DIE for it again. Allow re-declarations of DECLs that are + inside functions, though. */ + if (old_die && declaration && !local_scope_p (context_die)) return; /* For static data members, the declaration in the class is supposed @@ -18552,8 +18695,12 @@ gen_pointer_type_die (tree type, dw_die_ref context_die) static void gen_reference_type_die (tree type, dw_die_ref context_die) { - dw_die_ref ref_die - = new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type); + dw_die_ref ref_die, scope_die = scope_die_for (type, context_die); + + if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4) + ref_die = new_die (DW_TAG_rvalue_reference_type, scope_die, type); + else + ref_die = new_die (DW_TAG_reference_type, scope_die, type); equate_type_number_to_die (type, ref_die); add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die); @@ -19909,6 +20056,16 @@ dwarf2out_decl (tree decl) gen_decl_die (decl, NULL, context_die); } +/* Write the debugging output for DECL. */ + +static void +dwarf2out_function_decl (tree decl) +{ + dwarf2out_decl (decl); + + htab_empty (decl_loc_table); +} + /* Output a marker (i.e. a label) for the beginning of the generated code for a lexical block. */ @@ -20269,22 +20426,33 @@ dwarf2out_var_location (rtx loc_note) if (next_real == NULL_RTX) return; + /* If there were any real insns between note we processed last time + and this note (or if it is the first note), clear + last_{,postcall_}label so that they are not reused this time. */ + if (last_var_location_insn == NULL_RTX + || last_var_location_insn != next_real + || last_in_cold_section_p != in_cold_section_p) + { + last_label = NULL; + last_postcall_label = NULL; + } + decl = NOTE_VAR_LOCATION_DECL (loc_note); - newloc = add_var_loc_to_decl (decl, loc_note); + newloc = add_var_loc_to_decl (decl, loc_note, + NOTE_DURING_CALL_P (loc_note) + ? last_postcall_label : last_label); if (newloc == NULL) return; /* If there were no real insns between note we processed last time - and this note, use the label we emitted last time. */ - if (last_var_location_insn == NULL_RTX - || last_var_location_insn != next_real - || last_in_cold_section_p != in_cold_section_p) + and this note, use the label we emitted last time. Otherwise + create a new label and emit it. */ + if (last_label == NULL) { ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num); loclabel_num++; last_label = ggc_strdup (loclabel); - last_postcall_label = NULL; } newloc->var_loc_note = loc_note; newloc->next = NULL; @@ -20301,11 +20469,6 @@ dwarf2out_var_location (rtx loc_note) newloc->label = last_postcall_label; } - if (cfun && in_cold_section_p) - newloc->section_label = crtl->subsections.cold_section_label; - else - newloc->section_label = text_section_label; - last_var_location_insn = next_real; last_in_cold_section_p = in_cold_section_p; } @@ -20318,8 +20481,6 @@ dwarf2out_var_location (rtx loc_note) static void dwarf2out_begin_function (tree fun) { - htab_empty (decl_loc_table); - if (function_section (fun) != text_section) have_multiple_function_sections = true; @@ -20822,6 +20983,7 @@ prune_unused_types_walk (dw_die_ref die) case DW_TAG_packed_type: case DW_TAG_pointer_type: case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: case DW_TAG_volatile_type: case DW_TAG_typedef: case DW_TAG_array_type: @@ -21041,7 +21203,7 @@ htab_ct_eq (const void *of1, const void *of2) DWARF_TYPE_SIGNATURE_SIZE)); } -/* Move a DW_AT_MIPS_linkage_name attribute just added to dw_die_ref +/* Move a DW_AT_{,MIPS_}linkage_name attribute just added to dw_die_ref to the location it would have been added, should we know its DECL_ASSEMBLER_NAME when we added other attributes. This will probably improve compactness of debug info, removing equivalent @@ -21054,7 +21216,7 @@ move_linkage_attr (dw_die_ref die) unsigned ix = VEC_length (dw_attr_node, die->die_attr); dw_attr_node linkage = *VEC_index (dw_attr_node, die->die_attr, ix - 1); - gcc_assert (linkage.dw_attr == DW_AT_MIPS_linkage_name); + gcc_assert (linkage.dw_attr == AT_linkage_name); while (--ix > 0) { @@ -21288,7 +21450,7 @@ dwarf2out_finish (const char *filename) tree decl = node->created_for; if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)) { - add_AT_string (node->die, DW_AT_MIPS_linkage_name, + add_AT_string (node->die, AT_linkage_name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); move_linkage_attr (node->die); }