diff options
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r-- | gcc/dwarf2out.c | 392 |
1 files changed, 292 insertions, 100 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 2e8fe614188..afd02e27f84 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -1,6 +1,6 @@ /* Output Dwarf2 format symbol table information from the GNU C compiler. - Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 - Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004 Free Software Foundation, Inc. Contributed by Gary Funck (gary@intrepid.com). Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com). Extensively modified by Jason Merrill (jason@cygnus.com). @@ -386,9 +386,9 @@ static void def_cfa_1 PARAMS ((const char *, /* Hook used by __throw. */ rtx -expand_builtin_dwarf_fp_regnum () +expand_builtin_dwarf_sp_column () { - return GEN_INT (DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM)); + return GEN_INT (DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM)); } /* Return a pointer to a copy of the section string name S with all @@ -432,6 +432,15 @@ expand_builtin_init_dwarf_reg_sizes (address) emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size)); } + +#ifdef DWARF_ALT_FRAME_RETURN_COLUMN + { + enum machine_mode save_mode = Pmode; + HOST_WIDE_INT offset = DWARF_ALT_FRAME_RETURN_COLUMN * GET_MODE_SIZE (mode); + HOST_WIDE_INT size = GET_MODE_SIZE (save_mode); + emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size)); + } +#endif } /* Convert a DWARF call frame info. operation to its string name */ @@ -1812,7 +1821,7 @@ output_call_frame_info (for_eh) dw_fde_ref fde; dw_cfi_ref cfi; char l1[20], l2[20], section_start_label[20]; - int any_lsda_needed = 0; + bool any_lsda_needed = false; char augmentation[6]; int augmentation_size; int fde_encoding = DW_EH_PE_absptr; @@ -1823,17 +1832,19 @@ output_call_frame_info (for_eh) if (fde_table_in_use == 0) return; - /* If we don't have any functions we'll want to unwind out of, don't emit any - EH unwind information. */ + /* If we don't have any functions we'll want to unwind out of, don't + emit any EH unwind information. Note that if exceptions aren't + enabled, we won't have collected nothrow information, and if we + asked for asynchronous tables, we always want this info. */ if (for_eh) { - int any_eh_needed = flag_asynchronous_unwind_tables; + bool any_eh_needed = !flag_exceptions || flag_asynchronous_unwind_tables; for (i = 0; i < fde_table_in_use; i++) if (fde_table[i].uses_eh_lsda) - any_eh_needed = any_lsda_needed = 1; + any_eh_needed = any_lsda_needed = true; else if (! fde_table[i].nothrow) - any_eh_needed = 1; + any_eh_needed = true; if (! any_eh_needed) return; @@ -1971,7 +1982,7 @@ output_call_frame_info (for_eh) fde = &fde_table[i]; /* Don't emit EH unwind info for leaf functions that don't need it. */ - if (!flag_asynchronous_unwind_tables && for_eh + if (for_eh && !flag_asynchronous_unwind_tables && flag_exceptions && (fde->nothrow || fde->all_throwers_are_sibcalls) && !fde->uses_eh_lsda) continue; @@ -2222,7 +2233,7 @@ typedef enum dw_val_class_const, dw_val_class_unsigned_const, dw_val_class_long_long, - dw_val_class_float, + dw_val_class_vec, dw_val_class_flag, dw_val_class_die_ref, dw_val_class_fde_ref, @@ -2242,14 +2253,15 @@ typedef struct dw_long_long_struct } dw_long_long_const; -/* Describe a floating point constant value. */ +/* Describe a floating point constant value, or a vector constant value. */ -typedef struct dw_fp_struct +typedef struct dw_vec_struct { - long *array; + unsigned char *array; unsigned length; + unsigned elt_size; } -dw_float_const; +dw_vec_const; /* The dw_val_node describes an attribute's value, as it is represented internally. */ @@ -2266,7 +2278,7 @@ typedef struct dw_val_struct long int val_int; long unsigned val_unsigned; dw_long_long_const val_long_long; - dw_float_const val_float; + dw_vec_const val_vec; struct { dw_die_ref die; @@ -3512,9 +3524,10 @@ static void add_AT_long_long PARAMS ((dw_die_ref, enum dwarf_attribute, unsigned long, unsigned long)); -static void add_AT_float PARAMS ((dw_die_ref, +static void add_AT_vec PARAMS ((dw_die_ref, enum dwarf_attribute, - unsigned, long *)); + unsigned int, unsigned int, + unsigned char *)); static void add_AT_string PARAMS ((dw_die_ref, enum dwarf_attribute, const char *)); @@ -3669,6 +3682,11 @@ static void add_const_value_attribute PARAMS ((dw_die_ref, rtx)); static rtx rtl_for_decl_location PARAMS ((tree)); static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree)); static void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree)); +static void insert_int PARAMS ((HOST_WIDE_INT, + unsigned, unsigned char *)); +static HOST_WIDE_INT extract_int PARAMS ((const unsigned char *, + unsigned)); +static void insert_float PARAMS ((rtx, unsigned char *)); static void add_name_attribute PARAMS ((dw_die_ref, const char *)); static void add_bound_info PARAMS ((dw_die_ref, enum dwarf_attribute, tree)); @@ -3778,7 +3796,9 @@ static void mark_limbo_die_list PARAMS ((void *)); /* Section flags for .debug_str section. */ #ifdef HAVE_GAS_SHF_MERGE #define DEBUG_STR_SECTION_FLAGS \ - (SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1) + (flag_merge_constants \ + ? SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1 \ + : SECTION_DEBUG) #else #define DEBUG_STR_SECTION_FLAGS SECTION_DEBUG #endif @@ -4516,19 +4536,21 @@ add_AT_long_long (die, attr_kind, val_hi, val_low) /* Add a floating point attribute value to a DIE and return it. */ static inline void -add_AT_float (die, attr_kind, length, array) +add_AT_vec (die, attr_kind, length, elt_size, array) dw_die_ref die; enum dwarf_attribute attr_kind; - unsigned length; - long *array; + unsigned int length; + unsigned int elt_size; + unsigned char *array; { dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_float; - attr->dw_attr_val.v.val_float.length = length; - attr->dw_attr_val.v.val_float.array = array; + attr->dw_attr_val.val_class = dw_val_class_vec; + attr->dw_attr_val.v.val_vec.length = length; + attr->dw_attr_val.v.val_vec.elt_size = elt_size; + attr->dw_attr_val.v.val_vec.array = array; add_dwarf_attr (die, attr); } @@ -4990,8 +5012,8 @@ free_AT (a) free (a->dw_attr_val.v.val_lbl_id); break; - case dw_val_class_float: - free (a->dw_attr_val.v.val_float.array); + case dw_val_class_vec: + free (a->dw_attr_val.v.val_vec.array); break; default: @@ -5274,8 +5296,8 @@ print_die (die, outfile) a->dw_attr_val.v.val_long_long.hi, a->dw_attr_val.v.val_long_long.low); break; - case dw_val_class_float: - fprintf (outfile, "floating-point constant"); + case dw_val_class_vec: + fprintf (outfile, "floating-point or vector constant"); break; case dw_val_class_flag: fprintf (outfile, "%u", AT_flag (a)); @@ -5485,8 +5507,8 @@ attr_checksum (at, ctx, mark) case dw_val_class_long_long: CHECKSUM (at->dw_attr_val.v.val_long_long); break; - case dw_val_class_float: - CHECKSUM (at->dw_attr_val.v.val_float); + case dw_val_class_vec: + CHECKSUM (at->dw_attr_val.v.val_vec); break; case dw_val_class_flag: CHECKSUM (at->dw_attr_val.v.val_flag); @@ -5583,7 +5605,6 @@ same_dw_val_p (v1, v2, mark) { dw_loc_descr_ref loc1, loc2; rtx r1, r2; - unsigned i; if (v1->val_class != v2->val_class) return 0; @@ -5597,12 +5618,13 @@ same_dw_val_p (v1, v2, mark) case dw_val_class_long_long: return v1->v.val_long_long.hi == v2->v.val_long_long.hi && v1->v.val_long_long.low == v2->v.val_long_long.low; - case dw_val_class_float: - if (v1->v.val_float.length != v2->v.val_float.length) + case dw_val_class_vec: + if (v1->v.val_vec.length != v2->v.val_vec.length + || v1->v.val_vec.elt_size != v2->v.val_vec.elt_size) + return 0; + if (memcmp (v1->v.val_vec.array, v2->v.val_vec.array, + v1->v.val_vec.length * v1->v.val_vec.elt_size)) return 0; - for (i = 0; i < v1->v.val_float.length; i++) - if (v1->v.val_float.array[i] != v2->v.val_float.array[i]) - return 0; return 1; case dw_val_class_flag: return v1->v.val_flag == v2->v.val_flag; @@ -6229,8 +6251,9 @@ size_of_die (die) case dw_val_class_long_long: size += 1 + 2*HOST_BITS_PER_LONG/HOST_BITS_PER_CHAR; /* block */ break; - case dw_val_class_float: - size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */ + case dw_val_class_vec: + size += 1 + (a->dw_attr_val.v.val_vec.length + * a->dw_attr_val.v.val_vec.elt_size); /* block */ break; case dw_val_class_flag: size += 1; @@ -6426,7 +6449,7 @@ value_format (a) } case dw_val_class_long_long: return DW_FORM_block1; - case dw_val_class_float: + case dw_val_class_vec: return DW_FORM_block1; case dw_val_class_flag: return DW_FORM_flag; @@ -6706,16 +6729,24 @@ output_die (die) } break; - case dw_val_class_float: + case dw_val_class_vec: { + unsigned int elt_size = a->dw_attr_val.v.val_vec.elt_size; + unsigned int len = a->dw_attr_val.v.val_vec.length; unsigned int i; + unsigned char *p; - dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4, - "%s", name); - - for (i = 0; i < a->dw_attr_val.v.val_float.length; i++) - dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i], - "fp constant word %u", i); + dw2_asm_output_data (1, len * elt_size, "%s", name); + if (elt_size > sizeof (HOST_WIDE_INT)) + { + elt_size /= 2; + len *= 2; + } + for (i = 0, p = a->dw_attr_val.v.val_vec.array; + i < len; + i++, p += elt_size) + dw2_asm_output_data (elt_size, extract_int (p, elt_size), + "fp or vector constant word %u", i); break; } @@ -8177,6 +8208,11 @@ mem_loc_descriptor (rtl, mode) add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); break; + case LO_SUM: + rtl = XEXP (rtl, 1); + + /* ... fall through ... */ + case LABEL_REF: /* Some ports can transform a symbol ref into a label ref, because the symbol ref is too far away and has to be dumped into a constant @@ -9040,6 +9076,81 @@ add_data_member_location_attribute (die, decl) add_AT_loc (die, DW_AT_data_member_location, loc_descr); } +/* Writes integer values to dw_vec_const array. */ + +static void +insert_int (val, size, dest) + HOST_WIDE_INT val; + unsigned int size; + unsigned char *dest; +{ + while (size != 0) + { + *dest++ = val & 0xff; + val >>= 8; + --size; + } +} + +/* Reads integers from dw_vec_const array. Inverse of insert_int. */ + +static HOST_WIDE_INT +extract_int (src, size) + const unsigned char *src; + unsigned int size; +{ + HOST_WIDE_INT val = 0; + + src += size; + while (size != 0) + { + val <<= 8; + val |= *--src & 0xff; + --size; + } + return val; +} + +/* Writes floating point values to dw_vec_const array. */ + +static void +insert_float (rtl, array) + rtx rtl; + unsigned char *array; +{ + REAL_VALUE_TYPE rv; + long val[4]; + int i; + + REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl); + switch (GET_MODE (rtl)) + { + case SFmode: + REAL_VALUE_TO_TARGET_SINGLE (rv, val[0]); + break; + + case DFmode: + REAL_VALUE_TO_TARGET_DOUBLE (rv, val); + break; + + case XFmode: + case TFmode: + REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, val); + break; + + default: + abort (); + } + + /* REAL_VALUE_TO_TARGET_* puts 32-bit pieces in each long. + Pack them. */ + for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++) + { + insert_int (val[i], 4, array); + array += 4; + } +} + /* Attach an DW_AT_const_value attribute for a variable or a parameter which does not have a "location" either in memory or in a register. These things can arise in GNU C when a constant is passed as an actual parameter @@ -9089,31 +9200,11 @@ add_const_value_attribute (die, rtl) if (GET_MODE_CLASS (mode) == MODE_FLOAT) { - unsigned length = GET_MODE_SIZE (mode) / 4; - long *array = (long *) xmalloc (sizeof (long) * length); - REAL_VALUE_TYPE rv; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl); - switch (mode) - { - case SFmode: - REAL_VALUE_TO_TARGET_SINGLE (rv, array[0]); - break; - - case DFmode: - REAL_VALUE_TO_TARGET_DOUBLE (rv, array); - break; + unsigned int length = GET_MODE_SIZE (mode); + unsigned char *array = xmalloc (length); - case XFmode: - case TFmode: - REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, array); - break; - - default: - abort (); - } - - add_AT_float (die, DW_AT_const_value, length, array); + insert_float (rtl, array); + add_AT_vec (die, DW_AT_const_value, length / 4, 4, array); } else { @@ -9127,6 +9218,68 @@ add_const_value_attribute (die, rtl) } break; + case CONST_VECTOR: + { + enum machine_mode mode = GET_MODE (rtl); + unsigned int elt_size = GET_MODE_UNIT_SIZE (mode); + unsigned int length = CONST_VECTOR_NUNITS (rtl); + unsigned char *array = xmalloc (length * elt_size); + unsigned int i; + unsigned char *p; + + if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + { + for (i = 0, p = array; i < length; i++, p += elt_size) + { + rtx elt = CONST_VECTOR_ELT (rtl, i); + HOST_WIDE_INT lo, hi; + if (GET_CODE (elt) == CONST_INT) + { + lo = INTVAL (elt); + hi = -(lo < 0); + } + else if (GET_CODE (elt) == CONST_DOUBLE) + { + lo = CONST_DOUBLE_LOW (elt); + hi = CONST_DOUBLE_HIGH (elt); + } + else + abort (); + + if (elt_size <= sizeof (HOST_WIDE_INT)) + insert_int (lo, elt_size, p); + else if (elt_size == 2 * sizeof (HOST_WIDE_INT)) + { + unsigned char *p0 = p; + unsigned char *p1 = p + sizeof (HOST_WIDE_INT); + + if (WORDS_BIG_ENDIAN) + { + p0 = p1; + p1 = p; + } + insert_int (lo, sizeof (HOST_WIDE_INT), p0); + insert_int (hi, sizeof (HOST_WIDE_INT), p1); + } + else + abort (); + } + } + else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) + { + for (i = 0, p = array; i < length; i++, p += elt_size) + { + rtx elt = CONST_VECTOR_ELT (rtl, i); + insert_float (elt, p); + } + } + else + abort (); + + add_AT_vec (die, DW_AT_const_value, length, elt_size, array); + } + break; + case CONST_STRING: add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0)); break; @@ -9242,13 +9395,17 @@ rtl_for_decl_location (decl) rtl = DECL_RTL_IF_SET (decl); /* When generating abstract instances, ignore everything except - constants and symbols living in memory. */ + constants, symbols living in memory, and symbols living in + fixed registers. */ if (! reload_completed) { if (rtl && (CONSTANT_P (rtl) || (GET_CODE (rtl) == MEM - && CONSTANT_P (XEXP (rtl, 0))))) + && CONSTANT_P (XEXP (rtl, 0))) + || (GET_CODE (rtl) == REG + && TREE_CODE (decl) == VAR_DECL + && TREE_STATIC (decl)))) { #ifdef ASM_SIMPLIFY_DWARF_ADDR rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); @@ -9409,6 +9566,7 @@ add_location_or_const_value_attribute (die, decl) case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST_STRING: case SYMBOL_REF: case LABEL_REF: @@ -10368,19 +10526,20 @@ gen_enumeration_type_die (type, context_die) link != NULL; link = TREE_CHAIN (link)) { dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link); + tree value = TREE_VALUE (link); add_name_attribute (enum_die, IDENTIFIER_POINTER (TREE_PURPOSE (link))); - if (host_integerp (TREE_VALUE (link), 0)) - { - if (tree_int_cst_sgn (TREE_VALUE (link)) < 0) - add_AT_int (enum_die, DW_AT_const_value, - tree_low_cst (TREE_VALUE (link), 0)); - else - add_AT_unsigned (enum_die, DW_AT_const_value, - tree_low_cst (TREE_VALUE (link), 0)); - } + if (host_integerp (value, TREE_UNSIGNED (TREE_TYPE (value)))) + /* DWARF2 does not provide a way of indicating whether or + not enumeration constants are signed or unsigned. GDB + always assumes the values are signed, so we output all + values as if they were signed. That means that + enumeration constants with very large unsigned values + will appear to have negative values in the debugger. */ + add_AT_int (enum_die, DW_AT_const_value, + tree_low_cst (value, tree_int_cst_sgn (value) > 0)); } } else @@ -11039,16 +11198,20 @@ gen_inlined_subroutine_die (stmt, context_die, depth) dw_die_ref context_die; int depth; { + tree decl = block_ultimate_origin (stmt); + + /* Emit info for the abstract instance first, if we haven't yet. We + must emit this even if the block is abstract, otherwise when we + emit the block below (or elsewhere), we may end up trying to emit + a die whose origin die hasn't been emitted, and crashing. */ + dwarf2out_abstract_function (decl); + if (! BLOCK_ABSTRACT (stmt)) { dw_die_ref subr_die = new_die (DW_TAG_inlined_subroutine, context_die, stmt); - tree decl = block_ultimate_origin (stmt); char label[MAX_ARTIFICIAL_LABEL_BYTES]; - /* Emit info for the abstract instance first, if we haven't yet. */ - dwarf2out_abstract_function (decl); - add_abstract_origin_attribute (subr_die, decl); ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, BLOCK_NUMBER (stmt)); @@ -11082,8 +11245,12 @@ gen_field_die (decl, context_die) tree decl; dw_die_ref context_die; { - dw_die_ref decl_die = new_die (DW_TAG_member, context_die, decl); + dw_die_ref decl_die; + if (TREE_TYPE (decl) == error_mark_node) + return; + + decl_die = new_die (DW_TAG_member, context_die, decl); add_name_and_src_coords_attributes (decl_die, decl); add_type_attribute (decl_die, member_declared_type (decl), TREE_READONLY (decl), TREE_THIS_VOLATILE (decl), @@ -11473,20 +11640,12 @@ gen_type_die (type, context_die) if (type == NULL_TREE || type == error_mark_node) return; - /* We are going to output a DIE to represent the unqualified version - of this type (i.e. without any const or volatile qualifiers) so - get the main variant (i.e. the unqualified version) of this type - now. (Vectors are special because the debugging info is in the - cloned type itself). */ - if (TREE_CODE (type) != VECTOR_TYPE) - type = type_main_variant (type); - - if (TREE_ASM_WRITTEN (type)) - return; - if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) { + if (TREE_ASM_WRITTEN (type)) + return; + /* Prevent broken recursion; we can't hand off to the same type. */ if (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) == type) abort (); @@ -11496,6 +11655,17 @@ gen_type_die (type, context_die) return; } + /* We are going to output a DIE to represent the unqualified version + of this type (i.e. without any const or volatile qualifiers) so + get the main variant (i.e. the unqualified version) of this type + now. (Vectors are special because the debugging info is in the + cloned type itself). */ + if (TREE_CODE (type) != VECTOR_TYPE) + type = type_main_variant (type); + + if (TREE_ASM_WRITTEN (type)) + return; + switch (TREE_CODE (type)) { case ERROR_MARK: @@ -11799,6 +11969,10 @@ decls_for_scope (stmt, context_die, depth) gen_decl_die (decl, context_die); } + /* If we're at -g1, we're not interested in subblocks. */ + if (debug_info_level <= DINFO_LEVEL_TERSE) + return; + /* Output the DIEs to represent all sub-blocks (and the items declared therein) of this block. */ for (subblocks = BLOCK_SUBBLOCKS (stmt); @@ -12076,7 +12250,9 @@ dwarf2out_decl (decl) /* If we're a nested function, initially use a parent of NULL; if we're a plain function, this will be fixed up in decls_for_scope. If we're a method, it will be ignored, since we already have a DIE. */ - if (decl_function_context (decl)) + if (decl_function_context (decl) + /* But if we're in terse mode, we don't care about scope. */ + && debug_info_level > DINFO_LEVEL_TERSE) context_die = NULL; break; @@ -12559,6 +12735,22 @@ dwarf2out_finish (input_filename) limbo_die_node *node, *next_node; dw_die_ref die = 0; + if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL) + { + char *wd = getpwd (); + unsigned i; + + if (wd != NULL) + { + for (i = 1; i < file_table.in_use; i++) + if (file_table.table[i][0] != DIR_SEPARATOR) + { + add_AT_string (comp_unit_die, DW_AT_comp_dir, wd); + break; + } + } + } + /* Traverse the limbo die list, and add parent/child links. The only dies without parents that should be here are concrete instances of inline functions, and the comp_unit_die. We can ignore the comp_unit_die. |