X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fdbxout.c;h=5732427f46c27782e1dd3ad73409e5dc34afa643;hp=e67008f9ef5346b778178c2dbd118237a6a99d93;hb=7bb1423a251afbd39495b8cb1a569bfa35ee6d12;hpb=d0de818d2c8adf1bd0c34a1e3a57af3fadd79235 diff --git a/gcc/dbxout.c b/gcc/dbxout.c index e67008f9ef5..5732427f46c 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -1,6 +1,7 @@ /* Output dbx-format symbol table information from GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. This file is part of GCC. @@ -16,8 +17,8 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ /* Output dbx-format symbol table data. @@ -89,6 +90,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "target.h" #include "langhooks.h" #include "obstack.h" +#include "expr.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" @@ -241,13 +243,6 @@ static GTY(()) int scope_labelno; static GTY(()) int dbxout_source_line_counter; -/* Nonzero if we have actually used any of the GDB extensions - to the debugging format. The idea is that we use them for the - first time only if there's a strong reason, but once we have done that, - we use them whenever convenient. */ - -static GTY(()) int have_used_extensions = 0; - /* Number for the next N_SOL filename stabs label. The number 0 is reserved for the N_SO filename stabs label. */ @@ -275,7 +270,7 @@ static int pending_bincls = 0; static const char *base_input_file; #ifdef DEBUG_SYMS_TEXT -#define FORCE_TEXT function_section (current_function_decl); +#define FORCE_TEXT switch_to_section (current_function_section ()) #else #define FORCE_TEXT #endif @@ -343,7 +338,7 @@ static void dbxout_handle_pch (unsigned); static void dbxout_source_line (unsigned int, const char *); static void dbxout_begin_prologue (unsigned int, const char *); static void dbxout_source_file (const char *); -static void dbxout_function_end (void); +static void dbxout_function_end (tree); static void dbxout_begin_function (tree); static void dbxout_begin_block (unsigned, unsigned); static void dbxout_end_block (unsigned, unsigned); @@ -378,7 +373,9 @@ const struct gcc_debug_hooks dbx_debug_hooks = debug_nothing_tree, /* outlining_inline_function */ debug_nothing_rtx, /* label */ dbxout_handle_pch, /* handle_pch */ - debug_nothing_rtx /* var_location */ + debug_nothing_rtx, /* var_location */ + debug_nothing_void, /* switch_text_section */ + 0 /* start_end_main_source_file */ }; #endif /* DBX_DEBUGGING_INFO */ @@ -408,7 +405,9 @@ const struct gcc_debug_hooks xcoff_debug_hooks = debug_nothing_tree, /* outlining_inline_function */ debug_nothing_rtx, /* label */ dbxout_handle_pch, /* handle_pch */ - debug_nothing_rtx /* var_location */ + debug_nothing_rtx, /* var_location */ + debug_nothing_void, /* switch_text_section */ + 0 /* start_end_main_source_file */ }; #endif /* XCOFF_DEBUGGING_INFO */ @@ -619,6 +618,16 @@ dbxout_begin_complex_stabs (void) gcc_assert (stabstr_last_contin_point == 0); } +/* As above, but do not force text or emit pending bincls. This is + used by dbxout_symbol_location, which needs to do something else. */ +static void +dbxout_begin_complex_stabs_noforcetext (void) +{ + fputs (ASM_STABS_OP, asm_out_file); + putc ('"', asm_out_file); + gcc_assert (stabstr_last_contin_point == 0); +} + /* Add CHR, a single character, to the string being built. */ #define stabstr_C(chr) obstack_1grow (&stabstr_ob, chr) @@ -786,7 +795,7 @@ stabstr_continue (void) all of the arguments to the .stabs directive after the string. Overridden by xcoffout.h. CODE is the stabs code for this symbol; LINE is the source line to write into the desc field (in extended - mode). + mode); SYM is the symbol itself. ADDR, LABEL, and NUMBER are three different ways to represent the stabs value field. At most one of these should be nonzero. @@ -802,7 +811,8 @@ stabstr_continue (void) register variable). It represents the value as a decimal integer. */ #ifndef DBX_FINISH_STABS -#define DBX_FINISH_STABS(CODE, LINE, ADDR, LABEL, NUMBER) do { \ +#define DBX_FINISH_STABS(SYM, CODE, LINE, ADDR, LABEL, NUMBER) \ +do { \ int line_ = use_gnu_debug_info_extensions ? LINE : 0; \ \ dbxout_int (CODE); \ @@ -833,10 +843,11 @@ static void dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code, rtx addr, const char *label, int number) { - int line = sym ? DECL_SOURCE_LINE (sym) : 0; + int line ATTRIBUTE_UNUSED; char *str; size_t len; + line = sym ? DECL_SOURCE_LINE (sym) : 0; if (DBX_CONTIN_LENGTH > 0) { char *chunk; @@ -847,7 +858,7 @@ dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code, obstack_1grow (&stabstr_ob, '\0'); len = obstack_object_size (&stabstr_ob); - chunk = str = obstack_finish (&stabstr_ob); + chunk = str = XOBFINISH (&stabstr_ob, char *); /* Within the buffer are a sequence of NUL-separated strings, each of which is to be written out as a separate stab @@ -863,7 +874,8 @@ dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code, len -= chunklen + 1; /* Only put a line number on the last stab in the sequence. */ - DBX_FINISH_STABS (code, len == 0 ? line : 0, addr, label, number); + DBX_FINISH_STABS (sym, code, len == 0 ? line : 0, + addr, label, number); if (len == 0) break; @@ -879,10 +891,10 @@ dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code, comma than to do a two-character fputs. */ obstack_grow (&stabstr_ob, "\",", 2); len = obstack_object_size (&stabstr_ob); - str = obstack_finish (&stabstr_ob); + str = XOBFINISH (&stabstr_ob, char *); fwrite (str, 1, len, asm_out_file); - DBX_FINISH_STABS (code, line, addr, label, number); + DBX_FINISH_STABS (sym, code, line, addr, label, number); } obstack_free (&stabstr_ob, str); } @@ -890,39 +902,48 @@ dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code, #if defined (DBX_DEBUGGING_INFO) static void -dbxout_function_end (void) +dbxout_function_end (tree decl) { char lscope_label_name[100]; /* The Lscope label must be emitted even if we aren't doing anything else; dbxout_block needs it. */ - function_section (current_function_decl); + switch_to_section (function_section (current_function_decl)); /* Convert Lscope into the appropriate format for local labels in case the system doesn't insert underscores in front of user generated labels. */ ASM_GENERATE_INTERNAL_LABEL (lscope_label_name, "Lscope", scope_labelno); targetm.asm_out.internal_label (asm_out_file, "Lscope", scope_labelno); - scope_labelno++; /* The N_FUN tag at the end of the function is a GNU extension, which may be undesirable, and is unnecessary if we do not have named sections. */ if (!use_gnu_debug_info_extensions || NO_DBX_FUNCTION_END - || !targetm.have_named_sections) + || !targetm.have_named_sections + || DECL_IGNORED_P (decl)) return; /* By convention, GCC will mark the end of a function with an N_FUN symbol and an empty string. */ -#ifdef DBX_OUTPUT_NFUN - DBX_OUTPUT_NFUN (asm_out_file, lscope_label_name, current_function_decl); -#else - dbxout_begin_empty_stabs (N_FUN); - dbxout_stab_value_label_diff (lscope_label_name, - XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); - -#endif + if (flag_reorder_blocks_and_partition) + { + dbxout_begin_empty_stabs (N_FUN); + dbxout_stab_value_label_diff (cfun->hot_section_end_label, + cfun->hot_section_label); + dbxout_begin_empty_stabs (N_FUN); + dbxout_stab_value_label_diff (cfun->cold_section_end_label, + cfun->cold_section_label); + } + else + { + char begin_label[20]; + /* Reference current function start using LFBB. */ + ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno); + dbxout_begin_empty_stabs (N_FUN); + dbxout_stab_value_label_diff (lscope_label_name, begin_label); + } if (!NO_DBX_BNSYM_ENSYM && !flag_debug_only_used_symbols) dbxout_stabd (N_ENSYM, 0); @@ -947,6 +968,8 @@ get_lang_number (void) return N_SO_PASCAL; else if (strcmp (language_string, "GNU Objective-C") == 0) return N_SO_OBJC; + else if (strcmp (language_string, "GNU Objective-C++") == 0) + return N_SO_OBJCPLUS; else return 0; @@ -1006,7 +1029,7 @@ dbxout_init (const char *input_file_name) if (used_ltext_label_name) { - text_section (); + switch_to_section (text_section); targetm.asm_out.internal_label (asm_out_file, "Ltext", 0); } @@ -1022,7 +1045,7 @@ dbxout_init (const char *input_file_name) next_type_number = 1; #ifdef DBX_USE_BINCL - current_file = xmalloc (sizeof *current_file); + current_file = XNEW (struct dbx_file); current_file->next = NULL; current_file->file_number = 0; current_file->next_type_number = 1; @@ -1131,7 +1154,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED, const char *filename ATTRIBUTE_UNUSED) { #ifdef DBX_USE_BINCL - struct dbx_file *n = xmalloc (sizeof *n); + struct dbx_file *n = XNEW (struct dbx_file); n->next = current_file; n->next_type_number = 1; @@ -1205,7 +1228,7 @@ dbxout_source_file (const char *filename) { /* Don't change section amid function. */ if (current_function_decl == NULL_TREE) - text_section (); + switch_to_section (text_section); dbxout_begin_simple_stabs (filename, N_SOL); dbxout_stab_value_internal_label ("Ltext", &source_label_number); @@ -1213,7 +1236,8 @@ dbxout_source_file (const char *filename) } } -/* Output N_BNSYM and line number symbol entry. */ +/* Output N_BNSYM, line number symbol entry, and local symbol at + function scope */ static void dbxout_begin_prologue (unsigned int lineno, const char *filename) @@ -1224,7 +1248,14 @@ dbxout_begin_prologue (unsigned int lineno, const char *filename) && !flag_debug_only_used_symbols) dbxout_stabd (N_BNSYM, 0); + /* pre-increment the scope counter */ + scope_labelno++; + dbxout_source_line (lineno, filename); + /* Output function begin block at function scope, referenced + by dbxout_block, dbxout_source_line and dbxout_function_end. */ + emit_pending_bincls_if_required (); + targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno); } /* Output a line number symbol entry for source file FILENAME and line @@ -1233,8 +1264,6 @@ dbxout_begin_prologue (unsigned int lineno, const char *filename) static void dbxout_source_line (unsigned int lineno, const char *filename) { - const char *begin_label = XSTR(XEXP(DECL_RTL(current_function_decl), 0), 0); - dbxout_source_file (filename); #ifdef DBX_OUTPUT_SOURCE_LINE @@ -1242,10 +1271,12 @@ dbxout_source_line (unsigned int lineno, const char *filename) #else if (DBX_LINES_FUNCTION_RELATIVE) { + char begin_label[20]; dbxout_begin_stabn_sline (lineno); + /* Reference current function start using LFBB. */ + ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno); dbxout_stab_value_internal_label_diff ("LM", &dbxout_source_line_counter, begin_label); - } else dbxout_stabd (N_SLINE, lineno); @@ -1284,7 +1315,7 @@ dbxout_function_decl (tree decl) dbxout_begin_function (decl); #endif dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl)); - dbxout_function_end (); + dbxout_function_end (decl); } #endif /* DBX_DEBUGGING_INFO */ @@ -1294,9 +1325,7 @@ dbxout_function_decl (tree decl) static void dbxout_global_decl (tree decl) { - if (TREE_CODE (decl) == VAR_DECL - && ! DECL_EXTERNAL (decl) - && DECL_RTL_SET_P (decl)) /* Not necessary? */ + if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) { int saved_tree_used = TREE_USED (decl); TREE_USED (decl) = 1; @@ -1323,7 +1352,7 @@ dbxout_finish (const char *filename ATTRIBUTE_UNUSED) DBX_OUTPUT_MAIN_SOURCE_FILE_END (asm_out_file, filename); #elif defined DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END { - text_section (); + switch_to_section (text_section); dbxout_begin_empty_stabs (N_SO); dbxout_stab_value_internal_label ("Letext", 0); } @@ -1375,14 +1404,14 @@ dbxout_type_fields (tree type) /* Omit here local type decls until we know how to support them. */ if (TREE_CODE (tem) == TYPE_DECL + /* Omit here the nameless fields that are used to skip bits. */ + || DECL_IGNORED_P (tem) /* Omit fields whose position or size are variable or too large to represent. */ || (TREE_CODE (tem) == FIELD_DECL && (! host_integerp (bit_position (tem), 0) || ! DECL_SIZE (tem) - || ! host_integerp (DECL_SIZE (tem), 1))) - /* Omit here the nameless fields that are used to skip bits. */ - || DECL_IGNORED_P (tem)) + || ! host_integerp (DECL_SIZE (tem), 1)))) continue; else if (TREE_CODE (tem) != CONST_DECL) @@ -1400,7 +1429,6 @@ dbxout_type_fields (tree type) && (TREE_PRIVATE (tem) || TREE_PROTECTED (tem) || TREE_CODE (tem) != FIELD_DECL)) { - have_used_extensions = 1; stabstr_C ('/'); stabstr_C (DECL_ACCESSIBILITY_CHAR (tem)); } @@ -1415,7 +1443,6 @@ dbxout_type_fields (tree type) { tree name = DECL_ASSEMBLER_NAME (tem); - have_used_extensions = 1; stabstr_C (':'); stabstr_I (name); stabstr_C (';'); @@ -1623,11 +1650,15 @@ dbxout_type (tree type, int full) tree tem; tree main_variant; static int anonymous_type_number = 0; + bool vector_type = false; if (TREE_CODE (type) == VECTOR_TYPE) - /* The frontend feeds us a representation for the vector as a struct - containing an array. Pull out the array type. */ - type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type))); + { + /* The frontend feeds us a representation for the vector as a struct + containing an array. Pull out the array type. */ + type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type))); + vector_type = true; + } /* If there was an input error and we don't really have a type, avoid crashing and write something that is at least valid @@ -1826,7 +1857,6 @@ dbxout_type (tree type, int full) if (use_gnu_debug_info_extensions && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) { - have_used_extensions = 1; stabstr_S ("@s"); stabstr_D (TYPE_PRECISION (type)); stabstr_C (';'); @@ -1843,7 +1873,6 @@ dbxout_type (tree type, int full) if (use_gnu_debug_info_extensions && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) { - have_used_extensions = 1; stabstr_S ("@s"); stabstr_D (TYPE_PRECISION (type)); stabstr_C (';'); @@ -1887,28 +1916,9 @@ dbxout_type (tree type, int full) stabstr_S (";0;"); break; - case CHAR_TYPE: - if (use_gnu_debug_info_extensions) - { - have_used_extensions = 1; - stabstr_S ("@s"); - stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type)); - stabstr_S (";-20;"); - } - else - { - /* Output the type `char' as a subrange of itself. - That is what pcc seems to do. */ - stabstr_C ('r'); - dbxout_type_index (char_type_node); - stabstr_S (TYPE_UNSIGNED (type) ? ";0;255;" : ";0;127;"); - } - break; - case BOOLEAN_TYPE: if (use_gnu_debug_info_extensions) { - have_used_extensions = 1; stabstr_S ("@s"); stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type)); stabstr_S (";-16;"); @@ -1917,11 +1927,6 @@ dbxout_type (tree type, int full) stabstr_S ("eFalse:0,True:1,;"); break; - case FILE_TYPE: - stabstr_C ('d'); - dbxout_type (TREE_TYPE (type), 0); - break; - case COMPLEX_TYPE: /* Differs from the REAL_TYPE by its new data type number. R3 is NF_COMPLEX. We don't try to use any of the other NF_* @@ -1955,28 +1960,10 @@ dbxout_type (tree type, int full) } break; - case SET_TYPE: - if (use_gnu_debug_info_extensions) - { - have_used_extensions = 1; - stabstr_S ("@s"); - stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type)); - stabstr_C (';'); - - /* Check if a bitstring type, which in Chill is - different from a [power]set. */ - if (TYPE_STRING_FLAG (type)) - stabstr_S ("@S;"); - } - stabstr_C ('S'); - dbxout_type (TYPE_DOMAIN (type), 0); - break; - case ARRAY_TYPE: /* Make arrays of packed bits look like bitstrings for chill. */ if (TYPE_PACKED (type) && use_gnu_debug_info_extensions) { - have_used_extensions = 1; stabstr_S ("@s"); stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type)); stabstr_S (";@S;S"); @@ -1984,6 +1971,9 @@ dbxout_type (tree type, int full) break; } + if (use_gnu_debug_info_extensions && vector_type) + stabstr_S ("@V;"); + /* Output "a" followed by a range type definition for the index type of the array followed by a reference to the target-type. @@ -1992,7 +1982,6 @@ dbxout_type (tree type, int full) different from an array of characters. */ if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions) { - have_used_extensions = 1; stabstr_S ("@S;"); } tem = TYPE_DOMAIN (type); @@ -2056,13 +2045,12 @@ dbxout_type (tree type, int full) { int i; tree child; - VEC (tree) *accesses = BINFO_BASE_ACCESSES (binfo); + VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo); if (use_gnu_debug_info_extensions) { if (BINFO_N_BASE_BINFOS (binfo)) { - have_used_extensions = 1; stabstr_C ('!'); stabstr_U (BINFO_N_BASE_BINFOS (binfo)); stabstr_C (','); @@ -2075,13 +2063,13 @@ dbxout_type (tree type, int full) if (use_gnu_debug_info_extensions) { - have_used_extensions = 1; stabstr_C (BINFO_VIRTUAL_P (child) ? '1' : '0'); stabstr_C (access == access_public_node ? '2' : access == access_protected_node ? '1' :'0'); if (BINFO_VIRTUAL_P (child) - && strcmp (lang_hooks.name, "GNU C++") == 0) + && (strcmp (lang_hooks.name, "GNU C++") == 0 + || strcmp (lang_hooks.name, "GNU Objective-C++") == 0)) /* For a virtual base, print the (negative) offset within the vtable where we must look to find the necessary adjustment. */ @@ -2120,7 +2108,6 @@ dbxout_type (tree type, int full) dbxout_type_fields (type); if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE) { - have_used_extensions = 1; dbxout_type_methods (type); } @@ -2130,7 +2117,6 @@ dbxout_type (tree type, int full) /* Avoid the ~ if we don't really need it--it confuses dbx. */ && TYPE_VFIELD (type)) { - have_used_extensions = 1; /* We need to write out info about what field this class uses as its "main" vtable pointer field, because if this @@ -2161,7 +2147,6 @@ dbxout_type (tree type, int full) if (use_gnu_debug_info_extensions && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) { - have_used_extensions = 1; stabstr_S ("@s"); stabstr_D (TYPE_PRECISION (type)); stabstr_C (';'); @@ -2197,7 +2182,6 @@ dbxout_type (tree type, int full) case METHOD_TYPE: if (use_gnu_debug_info_extensions) { - have_used_extensions = 1; stabstr_C ('#'); /* Write the argument types out longhand. */ @@ -2215,7 +2199,6 @@ dbxout_type (tree type, int full) case OFFSET_TYPE: if (use_gnu_debug_info_extensions) { - have_used_extensions = 1; stabstr_C ('@'); dbxout_type (TYPE_OFFSET_BASETYPE (type), 0); stabstr_C (','); @@ -2229,7 +2212,6 @@ dbxout_type (tree type, int full) case REFERENCE_TYPE: if (use_gnu_debug_info_extensions) { - have_used_extensions = 1; stabstr_C ('&'); } else @@ -2330,6 +2312,140 @@ dbxout_class_name_qualifiers (tree decl) } } +/* This is a specialized subset of expand_expr for use by dbxout_symbol in + evaluating DECL_VALUE_EXPR. In particular, we stop if we find decls that + havn't been expanded, or if the expression is getting so complex we won't + be able to represent it in stabs anyway. Returns NULL on failure. */ + +static rtx +dbxout_expand_expr (tree expr) +{ + switch (TREE_CODE (expr)) + { + case VAR_DECL: + case PARM_DECL: + if (DECL_HAS_VALUE_EXPR_P (expr)) + return dbxout_expand_expr (DECL_VALUE_EXPR (expr)); + /* FALLTHRU */ + + case CONST_DECL: + case RESULT_DECL: + return DECL_RTL_IF_SET (expr); + + case INTEGER_CST: + return expand_expr (expr, NULL_RTX, VOIDmode, EXPAND_INITIALIZER); + + case COMPONENT_REF: + case ARRAY_REF: + case ARRAY_RANGE_REF: + case BIT_FIELD_REF: + { + enum machine_mode mode; + HOST_WIDE_INT bitsize, bitpos; + tree offset, tem; + int volatilep = 0, unsignedp = 0; + rtx x; + + tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, + &mode, &unsignedp, &volatilep, true); + + x = dbxout_expand_expr (tem); + if (x == NULL || !MEM_P (x)) + return NULL; + if (offset != NULL) + { + if (!host_integerp (offset, 0)) + return NULL; + x = adjust_address_nv (x, mode, tree_low_cst (offset, 0)); + } + if (bitpos != 0) + x = adjust_address_nv (x, mode, bitpos / BITS_PER_UNIT); + + return x; + } + + default: + return NULL; + } +} + +/* Helper function for output_used_types. Queue one entry from the + used types hash to be output. */ + +static int +output_used_types_helper (void **slot, void *data) +{ + tree type = *slot; + VEC(tree, heap) **types_p = data; + + if ((TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == QUAL_UNION_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && TYPE_STUB_DECL (type) + && DECL_P (TYPE_STUB_DECL (type)) + && ! DECL_IGNORED_P (TYPE_STUB_DECL (type))) + VEC_quick_push (tree, *types_p, TYPE_STUB_DECL (type)); + else if (TYPE_NAME (type) + && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) + VEC_quick_push (tree, *types_p, TYPE_NAME (type)); + + return 1; +} + +/* This is a qsort callback which sorts types and declarations into a + predictable order (types, then declarations, sorted by UID + within). */ + +static int +output_types_sort (const void *pa, const void *pb) +{ + const tree lhs = *((const tree *)pa); + const tree rhs = *((const tree *)pb); + + if (TYPE_P (lhs)) + { + if (TYPE_P (rhs)) + return TYPE_UID (lhs) - TYPE_UID (rhs); + else + return 1; + } + else + { + if (TYPE_P (rhs)) + return -1; + else + return DECL_UID (lhs) - DECL_UID (rhs); + } +} + + +/* Force all types used by this function to be output in debug + information. */ + +static void +output_used_types (void) +{ + if (cfun && cfun->used_types_hash) + { + VEC(tree, heap) *types; + int i; + tree type; + + types = VEC_alloc (tree, heap, htab_elements (cfun->used_types_hash)); + htab_traverse (cfun->used_types_hash, output_used_types_helper, &types); + + /* Sort by UID to prevent dependence on hash table ordering. */ + qsort (VEC_address (tree, types), VEC_length (tree, types), + sizeof (tree), output_types_sort); + + for (i = 0; VEC_iterate (tree, types, i, type); i++) + debug_queue_symbol (type); + + VEC_free (tree, heap, types); + } +} + /* Output a .stabs for the symbol defined by DECL, which must be a ..._DECL node in the normal namespace. It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL. @@ -2342,6 +2458,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) tree type = TREE_TYPE (decl); tree context = NULL_TREE; int result = 0; + rtx decl_rtl; /* "Intercept" dbxout_symbol() calls like we do all debug_hooks. */ ++debug_nesting; @@ -2353,7 +2470,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) DBXOUT_DECR_NESTING_AND_RETURN (0); /* If we are to generate only the symbols actually used then such - symbol nodees are flagged with TREE_USED. Ignore any that + symbol nodes are flagged with TREE_USED. Ignore any that aren't flaged as TREE_USED. */ if (flag_debug_only_used_symbols @@ -2426,7 +2543,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) break; case FUNCTION_DECL: - if (DECL_RTL (decl) == 0) + decl_rtl = DECL_RTL_IF_SET (decl); + if (!decl_rtl) DBXOUT_DECR_NESTING_AND_RETURN (0); if (DECL_EXTERNAL (decl)) break; @@ -2434,10 +2552,16 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) context = decl_function_context (decl); if (context == current_function_decl) break; - if (!MEM_P (DECL_RTL (decl)) - || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF) + /* Don't mention an inline instance of a nested function. */ + if (context && DECL_FROM_INLINE (decl)) + break; + if (!MEM_P (decl_rtl) + || GET_CODE (XEXP (decl_rtl, 0)) != SYMBOL_REF) break; + if (flag_debug_only_used_symbols) + output_used_types (); + dbxout_begin_complex_stabs (); stabstr_I (DECL_ASSEMBLER_NAME (decl)); stabstr_S (TREE_PUBLIC (decl) ? ":F" : ":f"); @@ -2459,8 +2583,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) stabstr_I (DECL_NAME (context)); } - dbxout_finish_complex_stabs (decl, N_FUN, XEXP (DECL_RTL (decl), 0), - 0, 0); + dbxout_finish_complex_stabs (decl, N_FUN, XEXP (decl_rtl, 0), 0, 0); break; case TYPE_DECL: @@ -2502,7 +2625,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == QUAL_UNION_TYPE) && TYPE_NAME (type) == decl - && !(use_gnu_debug_info_extensions && have_used_extensions) + && !use_gnu_debug_info_extensions && !TREE_ASM_WRITTEN (TYPE_NAME (type)) /* Distinguish the implicit typedefs of C++ from explicit ones that might be found in C. */ @@ -2528,11 +2651,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) dbxout_begin_complex_stabs (); - /* Output leading class/struct qualifiers. - ??? why not set have_used_extensions here ... because - then the test of it below would always be true, I - guess. But it's not clear to me why we shouldn't do - that always in extended mode. */ + /* Output leading class/struct qualifiers. */ if (use_gnu_debug_info_extensions) dbxout_class_name_qualifiers (decl); @@ -2549,7 +2668,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) from explicit ones that might be found in C. */ && DECL_ARTIFICIAL (decl)) { - if (use_gnu_debug_info_extensions && have_used_extensions) + if (use_gnu_debug_info_extensions) { stabstr_C ('T'); TREE_ASM_WRITTEN (TYPE_NAME (type)) = 1; @@ -2614,10 +2733,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) gcc_unreachable (); case RESULT_DECL: - /* Named return value, treat like a VAR_DECL. */ case VAR_DECL: - if (! DECL_RTL_SET_P (decl)) - DBXOUT_DECR_NESTING_AND_RETURN (0); /* Don't mention a variable that is external. Let the file that defines it describe it. */ if (DECL_EXTERNAL (decl)) @@ -2632,7 +2748,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) && host_integerp (DECL_INITIAL (decl), 0) && ! TREE_ASM_WRITTEN (decl) && (DECL_CONTEXT (decl) == NULL_TREE - || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK) + || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK + || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL) && TREE_PUBLIC (decl) == 0) { /* The sun4 assembler does not grok this. */ @@ -2643,8 +2760,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl)); dbxout_begin_complex_stabs (); - stabstr_I (DECL_NAME (decl)); - stabstr_S (":c=i"); + dbxout_symbol_name (decl, NULL, 'c'); + stabstr_S ("=i"); stabstr_D (ival); dbxout_finish_complex_stabs (0, N_LSYM, 0, 0, 0); DBXOUT_DECR_NESTING; @@ -2655,13 +2772,17 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) } /* else it is something we handle like a normal variable. */ - SET_DECL_RTL (decl, eliminate_regs (DECL_RTL (decl), 0, NULL_RTX)); + decl_rtl = dbxout_expand_expr (decl); + if (!decl_rtl) + DBXOUT_DECR_NESTING_AND_RETURN (0); + + decl_rtl = eliminate_regs (decl_rtl, 0, NULL_RTX); #ifdef LEAF_REG_REMAP if (current_function_uses_only_leaf_regs) - leaf_renumber_regs_insn (DECL_RTL (decl)); + leaf_renumber_regs_insn (decl_rtl); #endif - result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl)); + result = dbxout_symbol_location (decl, type, 0, decl_rtl); break; default: @@ -2738,6 +2859,37 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home) letter = decl_function_context (decl) ? 'V' : 'S'; + /* 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 pool. Alternatively, the symbol + in the constant pool might be referenced by a different + symbol. */ + if (GET_CODE (addr) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (addr)) + { + bool marked; + rtx tmp = get_pool_constant_mark (addr, &marked); + + if (GET_CODE (tmp) == SYMBOL_REF) + { + addr = tmp; + if (CONSTANT_POOL_ADDRESS_P (addr)) + get_pool_constant_mark (addr, &marked); + else + marked = true; + } + else if (GET_CODE (tmp) == LABEL_REF) + { + addr = tmp; + marked = true; + } + + /* If all references to the constant pool were optimized + out, we just ignore the symbol. */ + if (!marked) + return 0; + } + /* This should be the same condition as in assemble_variable, but we don't have access to dont_output_data here. So, instead, we rely on the fact that error_mark_node initializers always @@ -2752,40 +2904,9 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home) code = DBX_STATIC_CONST_VAR_CODE; else { - /* 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 pool. Alternatively, the symbol - in the constant pool might be referenced by a different - symbol. */ - if (GET_CODE (addr) == SYMBOL_REF - && CONSTANT_POOL_ADDRESS_P (addr)) - { - bool marked; - rtx tmp = get_pool_constant_mark (addr, &marked); - - if (GET_CODE (tmp) == SYMBOL_REF) - { - addr = tmp; - if (CONSTANT_POOL_ADDRESS_P (addr)) - get_pool_constant_mark (addr, &marked); - else - marked = true; - } - else if (GET_CODE (tmp) == LABEL_REF) - { - addr = tmp; - marked = true; - } - - /* If all references to the constant pool were optimized - out, we just ignore the symbol. */ - if (!marked) - return 0; - } - /* Ultrix `as' seems to need this. */ #ifdef DBX_STATIC_STAB_DATA_SECTION - data_section (); + switch_to_section (data_section); #endif code = N_STSYM; } @@ -2901,12 +3022,14 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home) return 0; /* Ok, start a symtab entry and output the variable name. */ + emit_pending_bincls_if_required (); + FORCE_TEXT; #ifdef DBX_STATIC_BLOCK_START DBX_STATIC_BLOCK_START (asm_out_file, code); #endif - dbxout_begin_complex_stabs (); + dbxout_begin_complex_stabs_noforcetext (); dbxout_symbol_name (decl, suffix, letter); dbxout_type (type, 0); dbxout_finish_complex_stabs (decl, code, addr, 0, number); @@ -3077,7 +3200,7 @@ dbxout_parms (tree parms) That is, its address was passed in a register. Output it as if it lived in that register. The debugger will know from the type - that it was actually passed by invisible reference. */ + that it was actually passed by invisible reference. */ code = DBX_REGPARM_STABS_CODE; @@ -3224,15 +3347,11 @@ static void dbx_output_lbrac (const char *label, const char *begin_label ATTRIBUTE_UNUSED) { -#ifdef DBX_OUTPUT_LBRAC - DBX_OUTPUT_LBRAC (asm_out_file, label); -#else dbxout_begin_stabn (N_LBRAC); if (DBX_BLOCKS_FUNCTION_RELATIVE) dbxout_stab_value_label_diff (label, begin_label); else dbxout_stab_value_label (label); -#endif } /* Subroutine of dbxout_block. Emit an N_RBRAC stab referencing LABEL. @@ -3242,15 +3361,11 @@ static void dbx_output_rbrac (const char *label, const char *begin_label ATTRIBUTE_UNUSED) { -#ifdef DBX_OUTPUT_RBRAC - DBX_OUTPUT_RBRAC (asm_out_file, label); -#else dbxout_begin_stabn (N_RBRAC); if (DBX_BLOCKS_FUNCTION_RELATIVE) dbxout_stab_value_label_diff (label, begin_label); else dbxout_stab_value_label (label); -#endif } /* Output everything about a symbol block (a BLOCK node @@ -3273,8 +3388,9 @@ dbx_output_rbrac (const char *label, static void dbxout_block (tree block, int depth, tree args) { - const char *begin_label - = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); + char begin_label[20]; + /* Reference current function start using LFBB. */ + ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno); while (block) { @@ -3303,7 +3419,7 @@ dbxout_block (tree block, int depth, tree args) if (depth == 0) /* The outermost block doesn't get LBB labels; use - the function symbol. */ + the LFBB local symbol emitted by dbxout_begin_prologue. */ scope_start = begin_label; else { @@ -3358,7 +3474,12 @@ dbxout_block (tree block, int depth, tree args) static void dbxout_begin_function (tree decl) { - int saved_tree_used1 = TREE_USED (decl); + int saved_tree_used1; + + if (DECL_IGNORED_P (decl)) + return; + + saved_tree_used1 = TREE_USED (decl); TREE_USED (decl) = 1; if (DECL_NAME (DECL_RESULT (decl)) != 0) {