X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fdbxout.c;h=a314e7b4430dca73c70faee7f9757422948124c1;hp=8c2d6eac5e46a53ac11c0e64e458ffdc67cc6601;hb=48c4e66fb5de419c7bf5baa613580844d40eeb85;hpb=16037b3108af0f2c006321eff56cbfc00ec50bd4 diff --git a/gcc/dbxout.c b/gcc/dbxout.c index 8c2d6eac5e4..a314e7b4430 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -1,12 +1,13 @@ /* 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, 2007, 2008, 2009 + Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 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. */ +along with GCC; see the file COPYING3. If not see +. */ /* Output dbx-format symbol table data. @@ -89,6 +89,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" @@ -170,8 +171,7 @@ enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED}; The file_number and type_number elements are used if DBX_USE_BINCL is defined. */ -struct typeinfo GTY(()) -{ +struct GTY(()) typeinfo { enum typestatus status; int file_number; int type_number; @@ -216,8 +216,8 @@ struct dbx_file struct dbx_file *prev; /* Chain to traverse all pending bincls. */ }; -/* This is the top of the stack. - +/* This is the top of the stack. + This is not saved for PCH, because restoring a PCH should not change it. next_file_number does have to be saved, because the PCH may use some file numbers; however, just before restoring a PCH, next_file_number @@ -241,13 +241,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,15 +268,13 @@ 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 #include "gstab.h" -#define STAB_CODE_TYPE enum __stab_debug_code - /* 1 if PARM is passed to this function in memory. */ #define PARM_PASSED_IN_MEMORY(PARM) \ @@ -315,7 +306,7 @@ static void emit_pending_bincls (void); static inline void emit_pending_bincls_if_required (void); static void dbxout_init (const char *); - + static void dbxout_finish (const char *); static void dbxout_start_source_file (unsigned, const char *); static void dbxout_end_source_file (unsigned); @@ -325,14 +316,16 @@ static void dbxout_args (tree); static void dbxout_type_fields (tree); static void dbxout_type_method_1 (tree); static void dbxout_type_methods (tree); -static void dbxout_range_type (tree); +static void dbxout_range_type (tree, tree, tree); static void dbxout_type (tree, int); -static bool print_int_cst_bounds_in_octal_p (tree); +static bool print_int_cst_bounds_in_octal_p (tree, tree, tree); +static bool is_fortran (void); static void dbxout_type_name (tree); static void dbxout_class_name_qualifiers (tree); static int dbxout_symbol_location (tree, tree, const char *, rtx); static void dbxout_symbol_name (tree, const char *, int); -static void dbxout_block (tree, int, tree); +static void dbxout_common_name (tree, const char *, stab_code_type); +static const char *dbxout_common_check (tree, int *); static void dbxout_global_decl (tree); static void dbxout_type_decl (tree, int); static void dbxout_handle_pch (unsigned); @@ -340,10 +333,10 @@ static void dbxout_handle_pch (unsigned); /* The debug hooks structure. */ #if defined (DBX_DEBUGGING_INFO) -static void dbxout_source_line (unsigned int, const char *); +static void dbxout_source_line (unsigned int, const char *, int, bool); 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); @@ -353,13 +346,14 @@ const struct gcc_debug_hooks dbx_debug_hooks = { dbxout_init, dbxout_finish, + debug_nothing_void, debug_nothing_int_charstar, debug_nothing_int_charstar, dbxout_start_source_file, dbxout_end_source_file, dbxout_begin_block, dbxout_end_block, - debug_true_tree, /* ignore_block */ + debug_true_const_tree, /* ignore_block */ dbxout_source_line, /* source_line */ dbxout_begin_prologue, /* begin_prologue */ debug_nothing_int_charstar, /* end_prologue */ @@ -373,12 +367,19 @@ const struct gcc_debug_hooks dbx_debug_hooks = dbxout_function_decl, dbxout_global_decl, /* global_decl */ dbxout_type_decl, /* type_decl */ - debug_nothing_tree_tree, /* imported_module_or_decl */ + debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */ debug_nothing_tree, /* deferred_inline_function */ 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 */ + debug_nothing_tree, /* direct_call */ + debug_nothing_tree_int, /* virtual_call_token */ + debug_nothing_rtx_rtx, /* copy_call_info */ + debug_nothing_uid, /* virtual_call */ + debug_nothing_tree_tree, /* set_name */ + 0 /* start_end_main_source_file */ }; #endif /* DBX_DEBUGGING_INFO */ @@ -387,13 +388,14 @@ const struct gcc_debug_hooks xcoff_debug_hooks = { dbxout_init, dbxout_finish, + debug_nothing_void, debug_nothing_int_charstar, debug_nothing_int_charstar, dbxout_start_source_file, dbxout_end_source_file, xcoffout_begin_block, xcoffout_end_block, - debug_true_tree, /* ignore_block */ + debug_true_const_tree, /* ignore_block */ xcoffout_source_line, xcoffout_begin_prologue, /* begin_prologue */ debug_nothing_int_charstar, /* end_prologue */ @@ -403,12 +405,19 @@ const struct gcc_debug_hooks xcoff_debug_hooks = debug_nothing_tree, /* function_decl */ dbxout_global_decl, /* global_decl */ dbxout_type_decl, /* type_decl */ - debug_nothing_tree_tree, /* imported_module_or_decl */ + debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */ debug_nothing_tree, /* deferred_inline_function */ 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 */ + debug_nothing_tree, /* direct_call */ + debug_nothing_tree_int, /* virtual_call_token */ + debug_nothing_rtx_rtx, /* copy_call_info */ + debug_nothing_uid, /* virtual_call */ + debug_nothing_tree_tree, /* set_name */ + 0 /* start_end_main_source_file */ }; #endif /* XCOFF_DEBUGGING_INFO */ @@ -839,9 +848,9 @@ do { \ SYM is the DECL of the symbol under consideration; it is used only for its DECL_SOURCE_LINE. The other arguments are all passed directly to DBX_FINISH_STABS; see above for details. */ - + static void -dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code, +dbxout_finish_complex_stabs (tree sym, stab_code_type code, rtx addr, const char *label, int number) { int line ATTRIBUTE_UNUSED; @@ -859,7 +868,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 @@ -892,8 +901,8 @@ 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 (sym, code, line, addr, label, number); } @@ -903,20 +912,19 @@ 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 ATTRIBUTE_UNUSED) { 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 @@ -928,14 +936,23 @@ dbxout_function_end (void) /* 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 (crtl->subsections.hot_section_end_label, + crtl->subsections.hot_section_label); + dbxout_begin_empty_stabs (N_FUN); + dbxout_stab_value_label_diff (crtl->subsections.cold_section_end_label, + crtl->subsections.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); @@ -954,17 +971,27 @@ get_lang_number (void) return N_SO_CC; else if (strcmp (language_string, "GNU F77") == 0) return N_SO_FORTRAN; - else if (strcmp (language_string, "GNU F95") == 0) + else if (strcmp (language_string, "GNU Fortran") == 0) return N_SO_FORTRAN90; /* CHECKME */ else if (strcmp (language_string, "GNU Pascal") == 0) 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; } +static bool +is_fortran (void) +{ + unsigned int lang = get_lang_number (); + + return (lang == N_SO_FORTRAN) || (lang == N_SO_FORTRAN90); +} + /* At the beginning of compilation, start writing the symbol table. Initialize `typevec' and output the standard data types of C. */ @@ -974,9 +1001,10 @@ dbxout_init (const char *input_file_name) char ltext_label_name[100]; bool used_ltext_label_name = false; tree syms = lang_hooks.decls.getdecls (); + const char *mapped_name; typevec_len = 100; - typevec = ggc_calloc (typevec_len, sizeof typevec[0]); + typevec = GGC_CNEWVEC (struct typeinfo, typevec_len); /* stabstr_ob contains one string, which will be just fine with 1-byte alignment. */ @@ -999,6 +1027,7 @@ dbxout_init (const char *input_file_name) cwd = "/"; else if (!IS_DIR_SEPARATOR (cwd[strlen (cwd) - 1])) cwd = concat (cwd, "/", NULL); + cwd = remap_debug_filename (cwd); } #ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asm_out_file, cwd); @@ -1009,17 +1038,18 @@ dbxout_init (const char *input_file_name) #endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */ } + mapped_name = remap_debug_filename (input_file_name); #ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME - DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, input_file_name); + DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, mapped_name); #else - dbxout_begin_simple_stabs_desc (input_file_name, N_SO, get_lang_number ()); + dbxout_begin_simple_stabs_desc (mapped_name, N_SO, get_lang_number ()); dbxout_stab_value_label (ltext_label_name); used_ltext_label_name = true; #endif if (used_ltext_label_name) { - text_section (); + switch_to_section (text_section); targetm.asm_out.internal_label (asm_out_file, "Ltext", 0); } @@ -1035,7 +1065,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; @@ -1144,17 +1174,17 @@ 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; - /* Do not assign file number now. + /* Do not assign file number now. Delay it until we actually emit BINCL. */ n->file_number = 0; n->prev = NULL; current_file->prev = n; n->bincl_status = BINCL_PENDING; - n->pending_bincl_name = filename; + n->pending_bincl_name = remap_debug_filename (filename); pending_bincls = 1; current_file = n; #endif @@ -1203,6 +1233,9 @@ dbxout_handle_pch (unsigned at_end) } #if defined (DBX_DEBUGGING_INFO) + +static void dbxout_block (tree, int, tree); + /* Output debugging info to FILE to switch to sourcefile FILENAME. */ static void @@ -1218,15 +1251,16 @@ 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_begin_simple_stabs (remap_debug_filename (filename), N_SOL); dbxout_stab_value_internal_label ("Ltext", &source_label_number); lastfile = 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) @@ -1237,14 +1271,23 @@ dbxout_begin_prologue (unsigned int lineno, const char *filename) && !flag_debug_only_used_symbols) dbxout_stabd (N_BNSYM, 0); - dbxout_source_line (lineno, filename); + /* pre-increment the scope counter */ + scope_labelno++; + + dbxout_source_line (lineno, filename, 0, true); + /* 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 number LINENO. */ static void -dbxout_source_line (unsigned int lineno, const char *filename) +dbxout_source_line (unsigned int lineno, const char *filename, + int discriminator ATTRIBUTE_UNUSED, + bool is_stmt ATTRIBUTE_UNUSED) { dbxout_source_file (filename); @@ -1253,11 +1296,12 @@ dbxout_source_line (unsigned int lineno, const char *filename) #else if (DBX_LINES_FUNCTION_RELATIVE) { - rtx begin_label = XEXP (DECL_RTL (current_function_decl), 0); + 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, - XSTR (begin_label, 0)); - + begin_label); } else dbxout_stabd (N_SLINE, lineno); @@ -1296,7 +1340,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 */ @@ -1306,9 +1350,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; @@ -1335,7 +1377,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); } @@ -1387,14 +1429,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) @@ -1412,7 +1454,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)); } @@ -1427,7 +1468,6 @@ dbxout_type_fields (tree type) { tree name = DECL_ASSEMBLER_NAME (tem); - have_used_extensions = 1; stabstr_C (':'); stabstr_I (name); stabstr_C (';'); @@ -1562,10 +1602,10 @@ dbxout_type_methods (tree type) /* Emit a "range" type specification, which has the form: "r;;;". - TYPE is an INTEGER_TYPE. */ + TYPE is an INTEGER_TYPE, LOW and HIGH are the bounds. */ static void -dbxout_range_type (tree type) +dbxout_range_type (tree type, tree low, tree high) { stabstr_C ('r'); if (TREE_TYPE (type)) @@ -1593,25 +1633,23 @@ dbxout_range_type (tree type) } stabstr_C (';'); - if (TYPE_MIN_VALUE (type) != 0 - && host_integerp (TYPE_MIN_VALUE (type), 0)) + if (low && host_integerp (low, 0)) { - if (print_int_cst_bounds_in_octal_p (type)) - stabstr_O (TYPE_MIN_VALUE (type)); + if (print_int_cst_bounds_in_octal_p (type, low, high)) + stabstr_O (low); else - stabstr_D (tree_low_cst (TYPE_MIN_VALUE (type), 0)); + stabstr_D (tree_low_cst (low, 0)); } else stabstr_C ('0'); stabstr_C (';'); - if (TYPE_MAX_VALUE (type) != 0 - && host_integerp (TYPE_MAX_VALUE (type), 0)) + if (high && host_integerp (high, 0)) { - if (print_int_cst_bounds_in_octal_p (type)) - stabstr_O (TYPE_MAX_VALUE (type)); + if (print_int_cst_bounds_in_octal_p (type, low, high)) + stabstr_O (high); else - stabstr_D (tree_low_cst (TYPE_MAX_VALUE (type), 0)); + stabstr_D (tree_low_cst (high, 0)); stabstr_C (';'); } else @@ -1632,14 +1670,38 @@ dbxout_range_type (tree type) static void dbxout_type (tree type, int full) { - tree tem; - tree main_variant; static int anonymous_type_number = 0; + bool vector_type = false; + tree tem, main_variant, low, high; 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 (TREE_CODE (type) == INTEGER_TYPE) + { + if (TREE_TYPE (type) == 0) + { + low = TYPE_MIN_VALUE (type); + high = TYPE_MAX_VALUE (type); + } + + else if (subrange_type_for_debug_p (type, &low, &high)) + ; + + /* If this is a subtype that should not be emitted as a subrange type, + use the base type. */ + else + { + type = TREE_TYPE (type); + low = TYPE_MIN_VALUE (type); + high = TYPE_MAX_VALUE (type); + } + } /* If there was an input error and we don't really have a type, avoid crashing and write something that is at least valid @@ -1675,8 +1737,7 @@ dbxout_type (tree type, int full) if (next_type_number == typevec_len) { - typevec - = ggc_realloc (typevec, (typevec_len * 2 * sizeof typevec[0])); + typevec = GGC_RESIZEVEC (struct typeinfo, typevec, typevec_len * 2); memset (typevec + typevec_len, 0, typevec_len * sizeof typevec[0]); typevec_len *= 2; } @@ -1838,13 +1899,12 @@ 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 (';'); } - dbxout_range_type (type); + dbxout_range_type (type, low, high); } else @@ -1855,13 +1915,12 @@ 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 (';'); } - if (print_int_cst_bounds_in_octal_p (type)) + if (print_int_cst_bounds_in_octal_p (type, low, high)) { stabstr_C ('r'); @@ -1876,20 +1935,21 @@ dbxout_type (tree type, int full) dbxout_type_index (type); stabstr_C (';'); - stabstr_O (TYPE_MIN_VALUE (type)); + stabstr_O (low); stabstr_C (';'); - stabstr_O (TYPE_MAX_VALUE (type)); + stabstr_O (high); stabstr_C (';'); } else /* Output other integer types as subranges of `int'. */ - dbxout_range_type (type); + dbxout_range_type (type, low, high); } break; case REAL_TYPE: + case FIXED_POINT_TYPE: /* This used to say `r1' and we used to take care to make sure that `int' was type number 1. */ stabstr_C ('r'); @@ -1899,28 +1959,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;"); @@ -1929,11 +1970,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_* @@ -1971,7 +2007,6 @@ dbxout_type (tree type, int full) /* 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"); @@ -1979,6 +2014,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. @@ -1987,7 +2025,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); @@ -2000,7 +2037,7 @@ dbxout_type (tree type, int full) else { stabstr_C ('a'); - dbxout_range_type (tem); + dbxout_range_type (tem, TYPE_MIN_VALUE (tem), TYPE_MAX_VALUE (tem)); } dbxout_type (TREE_TYPE (type), 0); @@ -2030,7 +2067,11 @@ dbxout_type (tree type, int full) another type's definition; instead, output an xref and let the definition come when the name is defined. */ stabstr_S ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu"); - if (TYPE_NAME (type) != 0) + if (TYPE_NAME (type) != 0 + /* The C frontend creates for anonymous variable length + records/unions TYPE_NAME with DECL_NAME NULL. */ + && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL + || DECL_NAME (TYPE_NAME (type)))) dbxout_type_name (type); else { @@ -2051,13 +2092,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 (','); @@ -2070,13 +2110,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. */ @@ -2115,7 +2155,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); } @@ -2125,7 +2164,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 @@ -2156,7 +2194,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 (';'); @@ -2165,16 +2202,21 @@ dbxout_type (tree type, int full) stabstr_C ('e'); for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) { + tree value = TREE_VALUE (tem); + stabstr_I (TREE_PURPOSE (tem)); stabstr_C (':'); - if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == 0) - stabstr_D (TREE_INT_CST_LOW (TREE_VALUE (tem))); - else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1 - && (HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0) - stabstr_D (TREE_INT_CST_LOW (TREE_VALUE (tem))); + if (TREE_CODE (value) == CONST_DECL) + value = DECL_INITIAL (value); + + if (TREE_INT_CST_HIGH (value) == 0) + stabstr_D (TREE_INT_CST_LOW (value)); + else if (TREE_INT_CST_HIGH (value) == -1 + && (HOST_WIDE_INT) TREE_INT_CST_LOW (value) < 0) + stabstr_D (TREE_INT_CST_LOW (value)); else - stabstr_O (TREE_VALUE (tem)); + stabstr_O (value); stabstr_C (','); if (TREE_CHAIN (tem) != 0) @@ -2192,7 +2234,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. */ @@ -2210,7 +2251,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 (','); @@ -2224,7 +2264,6 @@ dbxout_type (tree type, int full) case REFERENCE_TYPE: if (use_gnu_debug_info_extensions) { - have_used_extensions = 1; stabstr_C ('&'); } else @@ -2246,7 +2285,7 @@ dbxout_type (tree type, int full) should be printed in octal format. */ static bool -print_int_cst_bounds_in_octal_p (tree type) +print_int_cst_bounds_in_octal_p (tree type, tree low, tree high) { /* If we can use GDB extensions and the size is wider than a long (the size used by GDB to read them) or we may have trouble writing @@ -2260,10 +2299,8 @@ print_int_cst_bounds_in_octal_p (tree type) can't span same size unsigned types. */ if (use_gnu_debug_info_extensions - && TYPE_MIN_VALUE (type) != 0 - && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST - && TYPE_MAX_VALUE (type) != 0 - && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST + && low && TREE_CODE (low) == INTEGER_CST + && high && TREE_CODE (high) == INTEGER_CST && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node) || ((TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) && TYPE_UNSIGNED (type)) @@ -2283,7 +2320,7 @@ static void dbxout_type_name (tree type) { tree t = TYPE_NAME (type); - + gcc_assert (t); switch (TREE_CODE (t)) { @@ -2325,6 +2362,149 @@ 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 + haven'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: + /* We can't handle emulated tls variables, because the address is an + offset to the return value of __emutls_get_address, and there is no + way to express that in stabs. Also, there are name mangling issues + here. We end up with references to undefined symbols if we don't + disable debug info for these variables. */ + if (!targetm.have_tls && DECL_THREAD_LOCAL_P (expr)) + return NULL; + /* FALLTHRU */ + + 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 = (tree) *slot; + VEC(tree, heap) **types_p = (VEC(tree, heap) **) 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. @@ -2337,6 +2517,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; @@ -2348,8 +2529,8 @@ 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 - aren't flaged as TREE_USED. */ + symbol nodes are flagged with TREE_USED. Ignore any that + aren't flagged as TREE_USED. */ if (flag_debug_only_used_symbols && (!TREE_USED (decl) @@ -2421,7 +2602,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; @@ -2429,10 +2611,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"); @@ -2454,8 +2642,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: @@ -2497,7 +2684,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. */ @@ -2523,11 +2710,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); @@ -2544,7 +2727,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; @@ -2604,15 +2787,18 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) } case PARM_DECL: - /* Parm decls go in their own separate chains - and are output by dbxout_reg_parms and dbxout_parms. */ - gcc_unreachable (); + if (DECL_HAS_VALUE_EXPR_P (decl)) + decl = DECL_VALUE_EXPR (decl); + + /* PARM_DECLs go in their own separate chain and are output by + dbxout_reg_parms and dbxout_parms, except for those that are + disguised VAR_DECLs like Out parameters in Ada. */ + gcc_assert (TREE_CODE (decl) == VAR_DECL); + + /* ... fall through ... */ 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)) @@ -2627,7 +2813,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. */ @@ -2638,8 +2825,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; @@ -2650,13 +2837,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, VOIDmode, 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: @@ -2676,7 +2867,7 @@ static int dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home) { int letter = 0; - STAB_CODE_TYPE code; + stab_code_type code; rtx addr = 0; int number = 0; int regno = -1; @@ -2724,8 +2915,15 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home) { if (TREE_PUBLIC (decl)) { + int offs; letter = 'G'; code = N_GSYM; + if (NULL != dbxout_common_check (decl, &offs)) + { + letter = 'V'; + addr = 0; + number = offs; + } } else { @@ -2733,6 +2931,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 @@ -2740,47 +2969,26 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home) if (DECL_INITIAL (decl) == 0 || (!strcmp (lang_hooks.name, "GNU C++") && DECL_INITIAL (decl) == error_mark_node)) - code = N_LCSYM; + { + int offs; + code = N_LCSYM; + if (NULL != dbxout_common_check (decl, &offs)) + { + addr = 0; + number = offs; + letter = 'V'; + code = N_GSYM; + } + } else if (DECL_IN_TEXT_SECTION (decl)) /* This is not quite right, but it's the closest of all the codes that Unix defines. */ 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; } @@ -2839,7 +3047,7 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home) } else if (MEM_P (home) && GET_CODE (XEXP (home, 0)) == PLUS - && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT) + && CONST_INT_P (XEXP (XEXP (home, 0), 1))) { code = N_LSYM; /* RTL looks like (MEM (PLUS (REG...) (CONST_INT...))) @@ -2860,9 +3068,17 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home) variable, thereby avoiding the need for a register. In such cases we're forced to lie to debuggers and tell them that this variable was itself `static'. */ + int offs; code = N_LCSYM; letter = 'V'; - addr = XEXP (XEXP (home, 0), 0); + if (NULL == dbxout_common_check (decl, &offs)) + addr = XEXP (XEXP (home, 0), 0); + else + { + addr = 0; + number = offs; + code = N_GSYM; + } } else if (GET_CODE (home) == CONCAT) { @@ -2922,7 +3138,7 @@ dbxout_symbol_name (tree decl, const char *suffix, int letter) { tree name; - if (DECL_CONTEXT (decl) + if (DECL_CONTEXT (decl) && (TYPE_P (DECL_CONTEXT (decl)) || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)) /* One slight hitch: if this is a VAR_DECL which is a class member @@ -2947,6 +3163,114 @@ dbxout_symbol_name (tree decl, const char *suffix, int letter) stabstr_C (letter); } + +/* Output the common block name for DECL in a stabs. + + Symbols in global common (.comm) get wrapped with an N_BCOMM/N_ECOMM pair + around each group of symbols in the same .comm area. The N_GSYM stabs + that are emitted only contain the offset in the common area. This routine + emits the N_BCOMM and N_ECOMM stabs. */ + +static void +dbxout_common_name (tree decl, const char *name, stab_code_type op) +{ + dbxout_begin_complex_stabs (); + stabstr_S (name); + dbxout_finish_complex_stabs (decl, op, NULL_RTX, NULL, 0); +} + +/* Check decl to determine whether it is a VAR_DECL destined for storage in a + common area. If it is, the return value will be a non-null string giving + the name of the common storage block it will go into. If non-null, the + value is the offset into the common block for that symbol's storage. */ + +static const char * +dbxout_common_check (tree decl, int *value) +{ + rtx home; + rtx sym_addr; + const char *name = NULL; + + /* If the decl isn't a VAR_DECL, or if it isn't static, or if + it does not have a value (the offset into the common area), or if it + is thread local (as opposed to global) then it isn't common, and shouldn't + be handled as such. + + ??? DECL_THREAD_LOCAL_P check prevents problems with improper .stabs + for thread-local symbols. Can be handled via same mechanism as used + in dwarf2out.c. */ + if (TREE_CODE (decl) != VAR_DECL + || !TREE_STATIC(decl) + || !DECL_HAS_VALUE_EXPR_P(decl) + || DECL_THREAD_LOCAL_P (decl) + || !is_fortran ()) + return NULL; + + home = DECL_RTL (decl); + if (home == NULL_RTX || GET_CODE (home) != MEM) + return NULL; + + sym_addr = dbxout_expand_expr (DECL_VALUE_EXPR (decl)); + if (sym_addr == NULL_RTX || GET_CODE (sym_addr) != MEM) + return NULL; + + sym_addr = XEXP (sym_addr, 0); + if (GET_CODE (sym_addr) == CONST) + sym_addr = XEXP (sym_addr, 0); + if ((GET_CODE (sym_addr) == SYMBOL_REF || GET_CODE (sym_addr) == PLUS) + && DECL_INITIAL (decl) == 0) + { + + /* We have a sym that will go into a common area, meaning that it + will get storage reserved with a .comm/.lcomm assembler pseudo-op. + + Determine name of common area this symbol will be an offset into, + and offset into that area. Also retrieve the decl for the area + that the symbol is offset into. */ + tree cdecl = NULL; + + switch (GET_CODE (sym_addr)) + { + case PLUS: + if (CONST_INT_P (XEXP (sym_addr, 0))) + { + name = + targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 1), 0)); + *value = INTVAL (XEXP (sym_addr, 0)); + cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 1)); + } + else + { + name = + targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 0), 0)); + *value = INTVAL (XEXP (sym_addr, 1)); + cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 0)); + } + break; + + case SYMBOL_REF: + name = targetm.strip_name_encoding(XSTR (sym_addr, 0)); + *value = 0; + cdecl = SYMBOL_REF_DECL (sym_addr); + break; + + default: + error ("common symbol debug info is not structured as " + "symbol+offset"); + } + + /* Check area common symbol is offset into. If this is not public, then + it is not a symbol in a common block. It must be a .lcomm symbol, not + a .comm symbol. */ + if (cdecl == NULL || !TREE_PUBLIC(cdecl)) + name = NULL; + } + else + name = NULL; + + return name; +} + /* Output definitions of all the decls in a chain. Return nonzero if anything was output */ @@ -2954,11 +3278,38 @@ int dbxout_syms (tree syms) { int result = 0; + const char *comm_prev = NULL; + tree syms_prev = NULL; + while (syms) { + int temp, copen, cclos; + const char *comm_new; + + /* Check for common symbol, and then progression into a new/different + block of common symbols. Emit closing/opening common bracket if + necessary. */ + comm_new = dbxout_common_check (syms, &temp); + copen = comm_new != NULL + && (comm_prev == NULL || strcmp (comm_new, comm_prev)); + cclos = comm_prev != NULL + && (comm_new == NULL || strcmp (comm_new, comm_prev)); + if (cclos) + dbxout_common_name (syms_prev, comm_prev, N_ECOMM); + if (copen) + { + dbxout_common_name (syms, comm_new, N_BCOMM); + syms_prev = syms; + } + comm_prev = comm_new; + result += dbxout_symbol (syms, 1); syms = TREE_CHAIN (syms); } + + if (comm_prev != NULL) + dbxout_common_name (syms_prev, comm_prev, N_ECOMM); + return result; } @@ -2988,14 +3339,15 @@ dbxout_parms (tree parms) { tree eff_type; char letter; - STAB_CODE_TYPE code; + stab_code_type code; int number; /* Perform any necessary register eliminations on the parameter's rtl, so that the debugging output will be accurate. */ DECL_INCOMING_RTL (parms) - = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX); - SET_DECL_RTL (parms, eliminate_regs (DECL_RTL (parms), 0, NULL_RTX)); + = eliminate_regs (DECL_INCOMING_RTL (parms), VOIDmode, NULL_RTX); + SET_DECL_RTL (parms, + eliminate_regs (DECL_RTL (parms), VOIDmode, NULL_RTX)); #ifdef LEAF_REG_REMAP if (current_function_uses_only_leaf_regs) { @@ -3013,7 +3365,7 @@ dbxout_parms (tree parms) If that is not true, we produce meaningless results, but do not crash. */ if (GET_CODE (inrtl) == PLUS - && GET_CODE (XEXP (inrtl, 1)) == CONST_INT) + && CONST_INT_P (XEXP (inrtl, 1))) number = INTVAL (XEXP (inrtl, 1)); else number = 0; @@ -3056,6 +3408,8 @@ dbxout_parms (tree parms) was passed. */ if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) best_rtl = DECL_RTL (parms); + else if (GET_CODE (DECL_INCOMING_RTL (parms)) == PARALLEL) + best_rtl = XEXP (XVECEXP (DECL_INCOMING_RTL (parms), 0, 0), 0); else best_rtl = DECL_INCOMING_RTL (parms); @@ -3077,7 +3431,7 @@ dbxout_parms (tree parms) that it was actually passed by invisible reference. */ code = DBX_REGPARM_STABS_CODE; - + /* GDB likes this marked with a special letter. */ letter = (use_gnu_debug_info_extensions ? 'a' : DBX_REGPARM_STABS_LETTER); @@ -3148,7 +3502,7 @@ dbxout_parms (tree parms) continue; dbxout_begin_complex_stabs (); - + if (DECL_NAME (parms)) { stabstr_I (DECL_NAME (parms)); @@ -3214,6 +3568,8 @@ dbxout_args (tree args) } } +#if defined (DBX_DEBUGGING_INFO) + /* Subroutine of dbxout_block. Emit an N_LBRAC stab referencing LABEL. BEGIN_LABEL is the name of the beginning of the function, which may be required. */ @@ -3221,15 +3577,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. @@ -3239,15 +3591,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 @@ -3270,8 +3618,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) { @@ -3300,7 +3649,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 { @@ -3308,20 +3657,6 @@ dbxout_block (tree block, int depth, tree args) scope_start = buf; } - if (BLOCK_HANDLER_BLOCK (block)) - { - /* A catch block. Must precede N_LBRAC. */ - tree decl = BLOCK_VARS (block); - while (decl) - { - dbxout_begin_complex_stabs (); - stabstr_I (DECL_NAME (decl)); - stabstr_S (":C1"); - dbxout_finish_complex_stabs (0, N_CATCH, 0, - scope_start, 0); - decl = TREE_CHAIN (decl); - } - } dbx_output_lbrac (scope_start, begin_label); } @@ -3351,11 +3686,12 @@ dbxout_block (tree block, int depth, tree args) Usually this follows the function's code, but on some systems, it comes before. */ -#if defined (DBX_DEBUGGING_INFO) static void dbxout_begin_function (tree decl) { - int saved_tree_used1 = TREE_USED (decl); + int saved_tree_used1; + + saved_tree_used1 = TREE_USED (decl); TREE_USED (decl) = 1; if (DECL_NAME (DECL_RESULT (decl)) != 0) {