X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fdbxout.c;h=80d2f83849f921455cb515576491e63acb72643a;hb=82280733cf15fa787aa6b87aff533fbdc19fa40a;hp=35a228986d1767441dad0f975ec2a5660500bb29;hpb=f6cdb8eddd842d3a54d1d2836006b6c0a62c1e18;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/dbxout.c b/gcc/dbxout.c index 35a228986d1..80d2f83849f 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -1,5 +1,5 @@ /* Output dbx-format symbol table information from GNU compiler. - Copyright (C) 1987, 1988, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -15,7 +15,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* Output dbx-format symbol table data. @@ -112,6 +113,11 @@ extern int errno; #define DBX_REGPARM_STABS_LETTER 'P' #endif +/* This is used for parameters passed by invisible reference in a register. */ +#ifndef GDB_INV_REF_REGPARM_STABS_LETTER +#define GDB_INV_REF_REGPARM_STABS_LETTER 'a' +#endif + #ifndef DBX_MEMPARM_STABS_LETTER #define DBX_MEMPARM_STABS_LETTER 'p' #endif @@ -121,9 +127,20 @@ extern int errno; #endif /* Nonzero means if the type has methods, only output debugging - information if methods are actually written to the asm file. */ + information if methods are actually written to the asm file. This + optimization only works if the debugger can detect the special C++ + marker. */ + +#define MINIMAL_DEBUG 1 + +#ifdef NO_DOLLAR_IN_LABEL +#ifdef NO_DOT_IN_LABEL +#undef MINIMAL_DEBUG +#define MINIMAL_DEBUG 0 +#endif +#endif -static int flag_minimal_debug = 1; +static int flag_minimal_debug = MINIMAL_DEBUG; /* Nonzero if we have actually used any of the GDB extensions to the debugging format. The idea is that we use them for the @@ -137,6 +154,8 @@ static int have_used_extensions = 0; static int source_label_number = 1; +static int scope_labelno = 0; + char *getpwd (); /* Typical USG systems don't have stab.h, and they also have @@ -150,7 +169,7 @@ char *getpwd (); #define FORCE_TEXT #endif -#if defined (USG) || defined (NO_STAB_H) +#if defined (USG) || defined (NO_STAB_H) || defined (CROSS_COMPILE) #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */ #else #include /* On BSD, use the system's stab.h. */ @@ -199,15 +218,28 @@ static char *cwd; enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED}; -/* Vector recording the status of describing C data types. +/* Structure recording information about a C data type. + The status element says whether we have yet output + the definition of the type. TYPE_XREF says we have + output it as a cross-reference only. + The file_number and type_number elements are used if DBX_USE_BINCL + is defined. */ + +struct typeinfo +{ + enum typestatus status; +#ifdef DBX_USE_BINCL + int file_number; + int type_number; +#endif +}; + +/* Vector recording information about C data types. When we first notice a data type (a tree node), we assign it a number using next_type_number. - That is its index in this vector. - The vector element says whether we have yet output - the definition of the type. TYPE_XREF says we have - output it as a cross-reference only. */ + That is its index in this vector. */ -enum typestatus *typevec; +struct typeinfo *typevec; /* Number of elements of space allocated in `typevec'. */ @@ -219,6 +251,29 @@ static int typevec_len; static int next_type_number; +#ifdef DBX_USE_BINCL + +/* When using N_BINCL in dbx output, each type number is actually a + pair of the file number and the type number within the file. + This is a stack of input files. */ + +struct dbx_file +{ + struct dbx_file *next; + int file_number; + int next_type_number; +}; + +/* This is the top of the stack. */ + +static struct dbx_file *current_file; + +/* This is the next file number to use. */ + +static int next_file_number; + +#endif /* DBX_USE_BINCL */ + /* In dbx output, we must assign symbol-blocks id numbers in the order in which their beginnings are encountered. We output debugging info that refers to the beginning and @@ -269,121 +324,46 @@ static int current_sym_nchars; void dbxout_types (); void dbxout_args (); void dbxout_symbol (); -static void dbxout_type_name (); -static void dbxout_type (); -static void dbxout_typedefs (); -static void dbxout_symbol_name (); -static void dbxout_symbol_location (); -static void dbxout_prepare_symbol (); -static void dbxout_finish_symbol (); -static void dbxout_continue (); -static void print_int_cst_octal (); -static void print_octal (); + +static void dbxout_function_end PROTO((void)); +static void dbxout_typedefs PROTO((tree)); +static void dbxout_type_index PROTO((tree)); +static void dbxout_continue PROTO((void)); +static void dbxout_type_fields PROTO((tree)); +static void dbxout_type_method_1 PROTO((tree, char *)); +static void dbxout_type_methods PROTO((tree)); +static void dbxout_range_type PROTO((tree)); +static void dbxout_type PROTO((tree, int, int)); +static void print_int_cst_octal PROTO((tree)); +static void print_octal PROTO((unsigned HOST_WIDE_INT, int)); +static void dbxout_type_name PROTO((tree)); +static void dbxout_symbol_location PROTO((tree, tree, char *, rtx)); +static void dbxout_symbol_name PROTO((tree, char *, int)); +static void dbxout_prepare_symbol PROTO((tree)); +static void dbxout_finish_symbol PROTO((tree)); +static void dbxout_block PROTO((tree, int, tree)); +static void dbxout_really_begin_function PROTO((tree)); -#if 0 /* Not clear we will actually need this. */ - -/* Return the absolutized filename for the given relative - filename. Note that if that filename is already absolute, it may - still be returned in a modified form because this routine also - eliminates redundant slashes and single dots and eliminates double - dots to get a shortest possible filename from the given input - filename. The absolutization of relative filenames is made by - assuming that the given filename is to be taken as relative to - the first argument (cwd) or to the current directory if cwd is - NULL. */ - -static char * -abspath (rel_filename) - char *rel_filename; +static void +dbxout_function_end () { - /* Setup the current working directory as needed. */ - char *abs_buffer - = (char *) alloca (strlen (cwd) + strlen (rel_filename) + 1); - char *endp = abs_buffer; - char *outp, *inp; - char *value; - - /* Copy the filename (possibly preceded by the current working - directory name) into the absolutization buffer. */ - - { - char *src_p; - - if (rel_filename[0] != '/') - { - src_p = cwd; - while (*endp++ = *src_p++) - continue; - *(endp-1) = '/'; /* overwrite null */ - } - src_p = rel_filename; - while (*endp++ = *src_p++) - continue; - if (endp[-1] == '/') - *endp = '\0'; - - /* Now make a copy of abs_buffer into abs_buffer, shortening the - filename (by taking out slashes and dots) as we go. */ - - outp = inp = abs_buffer; - *outp++ = *inp++; /* copy first slash */ - for (;;) - { - if (!inp[0]) - break; - else if (inp[0] == '/' && outp[-1] == '/') - { - inp++; - continue; - } - else if (inp[0] == '.' && outp[-1] == '/') - { - if (!inp[1]) - break; - else if (inp[1] == '/') - { - inp += 2; - continue; - } - else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/')) - { - inp += (inp[2] == '/') ? 3 : 2; - outp -= 2; - while (outp >= abs_buffer && *outp != '/') - outp--; - if (outp < abs_buffer) - { - /* Catch cases like /.. where we try to backup to a - point above the absolute root of the logical file - system. */ - - fprintf (stderr, "%s: invalid file name: %s\n", - pname, rel_filename); - exit (1); - } - *++outp = '\0'; - continue; - } - } - *outp++ = *inp++; - } - - /* On exit, make sure that there is a trailing null, and make sure that - the last character of the returned string is *not* a slash. */ - - *outp = '\0'; - if (outp[-1] == '/') - *--outp = '\0'; - - /* Make a copy (in the heap) of the stuff left in the absolutization - buffer and return a pointer to the copy. */ - - value = (char *) oballoc (strlen (abs_buffer) + 1); - strcpy (value, abs_buffer); - return value; + char lscope_label_name[100]; + /* Convert Ltext 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); + ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Lscope", scope_labelno); + scope_labelno++; + + /* By convention, GCC will mark the end of a function with an N_FUN + symbol and an empty string. */ + fprintf (asmfile, "%s \"\",%d,0,0,", ASM_STABS_OP, N_FUN); + assemble_name (asmfile, lscope_label_name); + fputc ('-', asmfile); + assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); + fprintf (asmfile, "\n"); } -#endif /* 0 */ - + /* At the beginning of compilation, start writing the symbol table. Initialize `typevec' and output the standard data types of C. */ @@ -398,8 +378,8 @@ dbxout_init (asm_file, input_file_name, syms) asmfile = asm_file; typevec_len = 100; - typevec = (enum typestatus *) xmalloc (typevec_len * sizeof typevec[0]); - bzero (typevec, typevec_len * sizeof typevec[0]); + typevec = (struct typeinfo *) xmalloc (typevec_len * sizeof typevec[0]); + bzero ((char *) typevec, typevec_len * sizeof typevec[0]); /* Convert Ltext into the appropriate format for local labels in case the system doesn't insert underscores in front of user generated @@ -458,6 +438,14 @@ dbxout_init (asm_file, input_file_name, syms) next_type_number = 1; next_block_number = 2; +#ifdef DBX_USE_BINCL + current_file = (struct dbx_file *) xmalloc (sizeof *current_file); + current_file->next = NULL; + current_file->file_number = 0; + current_file->next_type_number = 1; + next_file_number = 1; +#endif + /* Make sure that types `int' and `char' have numbers 1 and 2. Definitions of other integer types will refer to those numbers. (Actually it should no longer matter what their numbers are. @@ -493,12 +481,45 @@ dbxout_typedefs (syms) tree type = TREE_TYPE (syms); if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && TYPE_SIZE (type) != NULL_TREE && ! TREE_ASM_WRITTEN (TYPE_NAME (type))) dbxout_symbol (TYPE_NAME (type), 0); } } } +/* Change to reading from a new source file. Generate a N_BINCL stab. */ + +void +dbxout_start_new_source_file (filename) + char *filename; +{ +#ifdef DBX_USE_BINCL + struct dbx_file *n = (struct dbx_file *) xmalloc (sizeof *n); + + n->next = current_file; + n->file_number = next_file_number++; + n->next_type_number = 1; + current_file = n; + fprintf (asmfile, "%s \"%s\",%d,0,0,0\n", ASM_STABS_OP, filename, N_BINCL); +#endif +} + +/* Revert to reading a previous source file. Generate a N_EINCL stab. */ + +void +dbxout_resume_previous_source_file () +{ +#ifdef DBX_USE_BINCL + struct dbx_file *next; + + fprintf (asmfile, "%s %d,0,0,0\n", ASM_STABN_OP, N_EINCL); + next = current_file->next; + free (current_file); + current_file = next; +#endif +} + /* Output debugging info to FILE to switch to sourcefile FILENAME. */ void @@ -518,8 +539,13 @@ dbxout_source_file (file, filename) fprintf (file, "%s ", ASM_STABS_OP); output_quoted_string (file, filename); fprintf (file, ",%d,0,0,%s\n", N_SOL, <ext_label_name[1]); - text_section (); - ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Ltext", source_label_number++); + if (current_function_decl != NULL_TREE + && DECL_SECTION_NAME (current_function_decl) != NULL_TREE) + ; /* Don't change section amid function. */ + else + text_section (); + ASM_OUTPUT_INTERNAL_LABEL (file, "Ltext", source_label_number); + source_label_number++; #endif lastfile = filename; } @@ -545,7 +571,7 @@ dbxout_source_line (file, filename, lineno) /* At the end of compilation, finish writing the symbol table. Unless you define DBX_OUTPUT_MAIN_SOURCE_FILE_END, the default is - to do nothing. */ + to do nothing. */ void dbxout_finish (file, filename) @@ -557,6 +583,22 @@ dbxout_finish (file, filename) #endif /* DBX_OUTPUT_MAIN_SOURCE_FILE_END */ } +/* Output the index of a type. */ + +static void +dbxout_type_index (type) + tree type; +{ +#ifndef DBX_USE_BINCL + fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type)); + CHARS (3); +#else + struct typeinfo *t = &typevec[TYPE_SYMTAB_ADDRESS (type)]; + fprintf (asmfile, "(%d,%d)", t->file_number, t->type_number); + CHARS (7); +#endif +} + /* Continue a symbol-description that gets too big. End one symbol table entry with a double-backslash and start a new one, eventually producing something like @@ -612,7 +654,7 @@ dbxout_type_fields (type) && DECL_ASSEMBLER_NAME (tem)) { have_used_extensions = 1; - CHARS (3 + IDENTIFIER_LENGTH (DECL_NAME (TYPE_NAME (DECL_FCONTEXT (tem))))); + CHARS (3 + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (tem))); fputs (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem)), asmfile); dbxout_type (DECL_FCONTEXT (tem), 0, 0); fprintf (asmfile, ":"); @@ -686,13 +728,13 @@ dbxout_type_method_1 (decl, debug_name) tree decl; char *debug_name; { - tree firstarg = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))); char c1 = 'A', c2; if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) c2 = '?'; else /* it's a METHOD_TYPE. */ { + tree firstarg = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))); /* A for normal functions. B for `const' member functions. C for `volatile' member functions. @@ -742,6 +784,7 @@ dbxout_type_methods (type) type_encoding = DECL_NAME (TYPE_NAME (type)); +#if 0 /* C++: Template classes break some assumptions made by this code about the class names, constructor names, and encodings for assembler label names. For now, disable output of dbx info for them. */ @@ -763,6 +806,7 @@ dbxout_type_methods (type) return; } } +#endif type_identifier_length = IDENTIFIER_LENGTH (type_encoding); @@ -792,7 +836,7 @@ dbxout_type_methods (type) /* This is the "mangled" name of the method. It encodes the argument types. */ char *debug_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)); - int destructor = 0; + int show_arg_types = 0; CONTIN; @@ -803,10 +847,23 @@ dbxout_type_methods (type) if (flag_minimal_debug) { + char marker; + + /* We can't optimize a method which uses an anonymous + class, because the debugger will not be able to + associate the arbitrary class name with the actual + class. */ +#ifndef NO_DOLLAR_IN_LABEL + marker = '$'; +#else + marker = '.'; +#endif + if (strchr (debug_name, marker)) + show_arg_types = 1; /* Detect ordinary methods because their mangled names start with the operation name. */ - if (!strncmp (IDENTIFIER_POINTER (name), debug_name, - IDENTIFIER_LENGTH (name))) + else if (!strncmp (IDENTIFIER_POINTER (name), debug_name, + IDENTIFIER_LENGTH (name))) { debug_name += IDENTIFIER_LENGTH (name); if (debug_name[0] == '_' && debug_name[1] == '_') @@ -816,7 +873,7 @@ dbxout_type_methods (type) /* Get past const and volatile qualifiers. */ while (*method_name == 'C' || *method_name == 'V') method_name++; - /* Skip digits for length of type_encoding. */ + /* Skip digits for length of type_encoding. */ while (*method_name == *length_ptr && *length_ptr) length_ptr++, method_name++; if (! strncmp (method_name, @@ -833,7 +890,7 @@ dbxout_type_methods (type) char *length_ptr = formatted_type_identifier_length; while (*ctor_name == 'C' || *ctor_name == 'V') ctor_name++; - /* Skip digits for length of type_encoding. */ + /* Skip digits for length of type_encoding. */ while (*ctor_name == *length_ptr && *length_ptr) length_ptr++, ctor_name++; if (!strncmp (IDENTIFIER_POINTER (type_encoding), ctor_name, @@ -842,7 +899,7 @@ dbxout_type_methods (type) } /* The other alternative is a destructor. */ else - destructor = 1; + show_arg_types = 1; /* Output the operation name just once, for the first method that we output. */ @@ -854,7 +911,7 @@ dbxout_type_methods (type) } } - dbxout_type (TREE_TYPE (fndecl), 0, destructor); + dbxout_type (TREE_TYPE (fndecl), 0, show_arg_types); dbxout_type_method_1 (fndecl, debug_name); } @@ -868,7 +925,7 @@ dbxout_type_methods (type) /* Emit a "range" type specification, which has the form: "r;;;". - TYPE is an INTEGER_TYPE. */ + TYPE is an INTEGER_TYPE. */ static void dbxout_range_type (type) @@ -877,11 +934,16 @@ dbxout_range_type (type) fprintf (asmfile, "r"); if (TREE_TYPE (type)) dbxout_type (TREE_TYPE (type), 0, 0); + else if (TREE_CODE (type) != INTEGER_TYPE) + dbxout_type (type, 0, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */ else { - /* This used to say `r1' and we used to take care - to make sure that `int' was type number 1. */ - fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (integer_type_node)); + /* Traditionally, we made sure 'int' was type 1, and builtin types + were defined to be sub-ranges of int. Unfortunately, this + does not allow us to distinguish true sub-ranges from integer + types. So, instead we define integer (non-sub-range) types as + sub-ranges of themselves. */ + dbxout_type_index (type); } if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST) fprintf (asmfile, ";%d", @@ -924,10 +986,21 @@ dbxout_type (type, full, show_arg_types) type = integer_type_node; else { - type = TYPE_MAIN_VARIANT (type); + /* Try to find the "main variant" with the same name but not const + or volatile. (Since stabs does not distinguish const and volatile, + there is no need to make them separate types. But types with + different names are usefully distinguished.) */ + + for (tem = TYPE_MAIN_VARIANT (type); tem; tem = TYPE_NEXT_VARIANT (tem)) + if (!TYPE_READONLY (tem) && !TYPE_VOLATILE (tem) + && TYPE_NAME (tem) == TYPE_NAME (type)) + { + type = tem; + break; + } if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && DECL_IGNORED_P (TYPE_NAME (type))) + && TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type))) full = 0; } @@ -940,15 +1013,24 @@ dbxout_type (type, full, show_arg_types) if (next_type_number == typevec_len) { - typevec = (enum typestatus *) xrealloc (typevec, typevec_len * 2 * sizeof typevec[0]); - bzero (typevec + typevec_len, typevec_len * sizeof typevec[0]); + typevec + = (struct typeinfo *) xrealloc (typevec, + typevec_len * 2 * sizeof typevec[0]); + bzero ((char *) (typevec + typevec_len), + typevec_len * sizeof typevec[0]); typevec_len *= 2; } + +#ifdef DBX_USE_BINCL + typevec[TYPE_SYMTAB_ADDRESS (type)].file_number + = current_file->file_number; + typevec[TYPE_SYMTAB_ADDRESS (type)].type_number + = current_file->next_type_number++; +#endif } /* Output the number of this type, to refer to it. */ - fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type)); - CHARS (3); + dbxout_type_index (type); #ifdef DBX_TYPE_DEFINED if (DBX_TYPE_DEFINED (type)) @@ -958,7 +1040,7 @@ dbxout_type (type, full, show_arg_types) /* If this type's definition has been output or is now being output, that is all. */ - switch (typevec[TYPE_SYMTAB_ADDRESS (type)]) + switch (typevec[TYPE_SYMTAB_ADDRESS (type)].status) { case TYPE_UNSEEN: break; @@ -979,15 +1061,24 @@ dbxout_type (type, full, show_arg_types) #ifdef DBX_NO_XREFS /* For systems where dbx output does not allow the `=xsNAME:' syntax, leave the type-number completely undefined rather than output - a cross-reference. */ - if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE - || TREE_CODE (type) == ENUMERAL_TYPE) - - if ((TYPE_NAME (type) != 0 && !full) - || TYPE_SIZE (type) == 0) + a cross-reference. If we have already used GNU debug info extensions, + then it is OK to output a cross reference. This is necessary to get + proper C++ debug output. */ + if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == QUAL_UNION_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && ! use_gnu_debug_info_extensions) + /* We must use the same test here as we use twice below when deciding + whether to emit a cross-reference. */ + if ((TYPE_NAME (type) != 0 + && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_IGNORED_P (TYPE_NAME (type))) + && !full) + || TYPE_SIZE (type) == 0 + /* No way in DBX fmt to describe a variable size. */ + || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) { - typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF; + typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; return; } #endif @@ -1000,7 +1091,14 @@ dbxout_type (type, full, show_arg_types) /* Mark it as defined, so that if it is self-referent we will not get into an infinite recursion of definitions. */ - typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_DEFINED; + typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_DEFINED; + + if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) + { + dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0, 0); + return; + } switch (TREE_CODE (type)) { @@ -1011,25 +1109,30 @@ dbxout_type (type, full, show_arg_types) without saying what it is. The debugger will make it a void type when the reference is seen, and nothing will ever override that default. */ - fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type)); - CHARS (3); + dbxout_type_index (type); break; case INTEGER_TYPE: if (type == char_type_node && ! TREE_UNSIGNED (type)) - /* Output the type `char' as a subrange of itself! - I don't understand this definition, just copied it - from the output of pcc. - This used to use `r2' explicitly and we used to - take care to make sure that `char' was type number 2. */ - fprintf (asmfile, "r%d;0;127;", TYPE_SYMTAB_ADDRESS (type)); + { + /* Output the type `char' as a subrange of itself! + I don't understand this definition, just copied it + from the output of pcc. + This used to use `r2' explicitly and we used to + take care to make sure that `char' was type number 2. */ + fprintf (asmfile, "r"); + dbxout_type_index (type); + fprintf (asmfile, ";0;127;"); + } else if (use_gnu_debug_info_extensions && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node) || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT)) { /* This used to say `r1' and we used to take care to make sure that `int' was type number 1. */ - fprintf (asmfile, "r%d;", TYPE_SYMTAB_ADDRESS (integer_type_node)); + fprintf (asmfile, "r"); + dbxout_type_index (integer_type_node); + fprintf (asmfile, ";"); print_int_cst_octal (TYPE_MIN_VALUE (type)); fprintf (asmfile, ";"); print_int_cst_octal (TYPE_MAX_VALUE (type)); @@ -1037,15 +1140,16 @@ dbxout_type (type, full, show_arg_types) } else /* Output other integer types as subranges of `int'. */ dbxout_range_type (type); - CHARS (25); + CHARS (22); break; case REAL_TYPE: /* This used to say `r1' and we used to take care to make sure that `int' was type number 1. */ - fprintf (asmfile, "r%d;%d;0;", TYPE_SYMTAB_ADDRESS (integer_type_node), - int_size_in_bytes (type)); - CHARS (16); + fprintf (asmfile, "r"); + dbxout_type_index (integer_type_node); + fprintf (asmfile, ";%d;0;", int_size_in_bytes (type)); + CHARS (13); break; case CHAR_TYPE: @@ -1053,10 +1157,13 @@ dbxout_type (type, full, show_arg_types) fprintf (asmfile, "@s%d;-20;", BITS_PER_UNIT * int_size_in_bytes (type)); else - /* Output the type `char' as a subrange of itself. - That is what pcc seems to do. */ - fprintf (asmfile, "r%d;0;%d;", TYPE_SYMTAB_ADDRESS (char_type_node), - TREE_UNSIGNED (type) ? 255 : 127); + { + /* Output the type `char' as a subrange of itself. + That is what pcc seems to do. */ + fprintf (asmfile, "r"); + dbxout_type_index (char_type_node); + fprintf (asmfile, ";0;%d;", TREE_UNSIGNED (type) ? 255 : 127); + } CHARS (9); break; @@ -1080,10 +1187,11 @@ dbxout_type (type, full, show_arg_types) if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE) { - fprintf (asmfile, "r%d;%d;0;", - TYPE_SYMTAB_ADDRESS (type), + fprintf (asmfile, "r"); + dbxout_type_index (type); + fprintf (asmfile, ";%d;0;", int_size_in_bytes (TREE_TYPE (type))); - CHARS (15); /* The number is probably incorrect here. */ + CHARS (12); /* The number is probably incorrect here. */ } else { @@ -1114,7 +1222,7 @@ dbxout_type (type, full, show_arg_types) fprintf (asmfile, "@s%d;", BITS_PER_UNIT * int_size_in_bytes (type)); /* Check if a bitstring type, which in Chill is - different from a [power]set. */ + different from a [power]set. */ if (TYPE_STRING_FLAG (type)) fprintf (asmfile, "@S;"); } @@ -1129,7 +1237,7 @@ dbxout_type (type, full, show_arg_types) followed by a reference to the target-type. ar1;0;N;M for a C array of type M and size N+1. */ /* Check if a character string type, which in Chill is - different from an array of characters. */ + different from an array of characters. */ if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions) { have_used_extensions = 1; @@ -1137,14 +1245,17 @@ dbxout_type (type, full, show_arg_types) } tem = TYPE_DOMAIN (type); if (tem == NULL) - fprintf (asmfile, "ar%d;0;-1;", - TYPE_SYMTAB_ADDRESS (integer_type_node)); + { + fprintf (asmfile, "ar"); + dbxout_type_index (integer_type_node); + fprintf (asmfile, ";0;-1;"); + } else { fprintf (asmfile, "a"); dbxout_range_type (tem); } - CHARS (17); + CHARS (14); dbxout_type (TREE_TYPE (type), 0, 0); break; @@ -1157,16 +1268,11 @@ dbxout_type (type, full, show_arg_types) if (TYPE_BINFO (type) != 0 && TYPE_BINFO_BASETYPES (type) != 0) n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)); - /* Output a structure type. */ + /* Output a structure type. We must use the same test here as we + use in the DBX_NO_XREFS case above. */ if ((TYPE_NAME (type) != 0 - /* Long ago, Tiemann said this creates output that "confuses GDB". - In April 93, mrs@cygnus.com said there is no such problem. - The type decls made automatically by struct specifiers - are marked with DECL_IGNORED_P in C++. */ -#if 0 /* This creates output for anonymous classes which confuses GDB. */ && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_IGNORED_P (TYPE_NAME (type))) -#endif && !full) || TYPE_SIZE (type) == 0 /* No way in DBX fmt to describe a variable size. */ @@ -1193,7 +1299,7 @@ dbxout_type (type, full, show_arg_types) else fprintf (asmfile, "$$%d", anonymous_type_number++); fprintf (asmfile, ":"); - typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF; + typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; break; } @@ -1278,21 +1384,28 @@ dbxout_type (type, full, show_arg_types) break; case ENUMERAL_TYPE: - if ((TYPE_NAME (type) != 0 && !full - && (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && ! DECL_IGNORED_P (TYPE_NAME (type)))) + /* We must use the same test here as we use in the DBX_NO_XREFS case + above. We simplify it a bit since an enum will never have a variable + size. */ + if ((TYPE_NAME (type) != 0 + && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_IGNORED_P (TYPE_NAME (type))) + && !full) || TYPE_SIZE (type) == 0) { fprintf (asmfile, "xe"); CHARS (3); dbxout_type_name (type); - typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF; + typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; fprintf (asmfile, ":"); return; } #ifdef DBX_OUTPUT_ENUM DBX_OUTPUT_ENUM (asmfile, type); #else + if (use_gnu_debug_info_extensions + && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) + fprintf (asmfile, "@s%d;", TYPE_PRECISION (type)); putc ('e', asmfile); CHARS (1); for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) @@ -1334,6 +1447,7 @@ dbxout_type (type, full, show_arg_types) /* Normally, just output the return type. The argument types are encoded in the method name. */ putc ('#', asmfile); + CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); putc (';', asmfile); CHARS (1); @@ -1564,13 +1678,13 @@ dbxout_symbol (decl, local) /* If this typedef name was defined by outputting the type, don't duplicate it. */ - if (typevec[TYPE_SYMTAB_ADDRESS (type)] == TYPE_DEFINED + if (typevec[TYPE_SYMTAB_ADDRESS (type)].status == TYPE_DEFINED && TYPE_NAME (TREE_TYPE (decl)) == decl) return; #endif /* Don't output the same typedef twice. And don't output what language-specific stuff doesn't want output. */ - if (TREE_ASM_WRITTEN (decl) || DECL_IGNORED_P (decl)) + if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl)) return; FORCE_TEXT; @@ -1596,10 +1710,7 @@ dbxout_symbol (decl, local) && !TREE_ASM_WRITTEN (TYPE_NAME (type)) /* Distinguish the implicit typedefs of C++ from explicit ones that might be found in C. */ - && (!strcmp (lang_identify (), "cplusplus") - /* The following line maybe unnecessary; - in 2.6, try removing it. */ - || DECL_SOURCE_LINE (decl) == 0)) + && DECL_ARTIFICIAL (decl)) { tree name = TYPE_NAME (type); if (TREE_CODE (name) == TYPE_DECL) @@ -1624,7 +1735,10 @@ dbxout_symbol (decl, local) if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == QUAL_UNION_TYPE) - && TYPE_NAME (type) == decl) + && TYPE_NAME (type) == decl + /* Distinguish the implicit typedefs of C++ + from explicit ones that might be found in C. */ + && DECL_ARTIFICIAL (decl)) { if (use_gnu_debug_info_extensions && have_used_extensions) { @@ -1648,7 +1762,10 @@ dbxout_symbol (decl, local) /* Don't output a tag if this is an incomplete type (TYPE_SIZE is zero). This prevents the sun4 Sun OS 4.x dbx from crashing. */ - if (tag_needed && TYPE_NAME (type) != 0 && TYPE_SIZE (type) != 0 + if (tag_needed && TYPE_NAME (type) != 0 + && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE + || (DECL_NAME (TYPE_NAME (type)) != 0)) + && TYPE_SIZE (type) != 0 && !TREE_ASM_WRITTEN (TYPE_NAME (type))) { /* For a TYPE_DECL with no name, but the type has a name, @@ -1742,7 +1859,7 @@ dbxout_symbol (decl, local) /* else it is something we handle like a normal variable. */ } - DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX); + DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX, 0); #ifdef LEAF_REG_REMAP if (leaf_function) leaf_renumber_regs_insn (DECL_RTL (decl)); @@ -1824,7 +1941,13 @@ dbxout_symbol_location (decl, type, suffix, home) letter = decl_function_context (decl) ? 'V' : 'S'; - if (!DECL_INITIAL (decl)) + /* 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 + end up in bss for C++ and never end up in bss for C. */ + if (DECL_INITIAL (decl) == 0 + || (!strcmp (lang_identify (), "cplusplus") + && DECL_INITIAL (decl) == error_mark_node)) current_sym_code = N_LCSYM; else if (DECL_IN_TEXT_SECTION (decl)) /* This is not quite right, but it's the closest @@ -1969,15 +2092,9 @@ dbxout_symbol_name (decl, suffix, letter) { /* One slight hitch: if this is a VAR_DECL which is a static class member, we must put out the mangled name instead of the - DECL_NAME. */ - - char *name; - /* Note also that static member (variable) names DO NOT begin + DECL_NAME. Note also that static member (variable) names DO NOT begin with underscores in .stabs directives. */ - if (DECL_LANG_SPECIFIC (decl)) - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - else - name = IDENTIFIER_POINTER (DECL_NAME (decl)); + char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); if (name == 0) name = "(anon)"; fprintf (asmfile, "%s \"%s%s:", ASM_STABS_OP, name, @@ -2054,8 +2171,8 @@ dbxout_parms (parms) /* 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); - DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX); + = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX, 0); + DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX, 0); #ifdef LEAF_REG_REMAP if (leaf_function) { @@ -2097,37 +2214,7 @@ dbxout_parms (parms) DBX_MEMPARM_STABS_LETTER); } - if (GET_CODE (DECL_RTL (parms)) == REG - && REGNO (DECL_RTL (parms)) >= 0 - && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) - dbxout_type (DECL_ARG_TYPE (parms), 0, 0); - else - { - int original_value = current_sym_value; - - /* This is the case where the parm is passed as an int or double - and it is converted to a char, short or float and stored back - in the parmlist. In this case, describe the parm - with the variable's declared type, and adjust the address - if the least significant bytes (which we are using) are not - the first ones. */ -#if BYTES_BIG_ENDIAN - if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) - current_sym_value += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) - - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))); -#endif - - if (GET_CODE (DECL_RTL (parms)) == MEM - && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS - && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == current_sym_value) - dbxout_type (TREE_TYPE (parms), 0, 0); - else - { - current_sym_value = original_value; - dbxout_type (DECL_ARG_TYPE (parms), 0, 0); - } - } + dbxout_type (DECL_ARG_TYPE (parms), 0, 0); current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr); dbxout_finish_symbol (parms); } @@ -2201,7 +2288,10 @@ dbxout_parms (parms) /* Parm passed in registers and lives in registers or nowhere. */ current_sym_code = DBX_REGPARM_STABS_CODE; - regparm_letter = DBX_REGPARM_STABS_LETTER; + if (use_gnu_debug_info_extensions) + regparm_letter = GDB_INV_REF_REGPARM_STABS_LETTER; + else + regparm_letter = DBX_REGPARM_STABS_LETTER; /* DECL_RTL looks like (MEM (REG...). Get the register number. If it is an unallocated pseudo-reg, then use the register where @@ -2221,13 +2311,13 @@ dbxout_parms (parms) fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms)), - DBX_REGPARM_STABS_LETTER); + regparm_letter); } else { current_sym_nchars = 8; fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP, - DBX_REGPARM_STABS_LETTER); + regparm_letter); } dbxout_type (TREE_TYPE (parms), 0, 0); @@ -2295,7 +2385,7 @@ dbxout_reg_parms (parms) tree parms; { for (; parms; parms = TREE_CHAIN (parms)) - if (DECL_NAME (parms)) + if (DECL_NAME (parms) && PARM_PASSED_IN_MEMORY (parms)) { dbxout_prepare_symbol (parms); @@ -2303,70 +2393,17 @@ dbxout_reg_parms (parms) but were passed in memory. */ if (GET_CODE (DECL_RTL (parms)) == REG && REGNO (DECL_RTL (parms)) >= 0 - && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER - && PARM_PASSED_IN_MEMORY (parms)) + && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) dbxout_symbol_location (parms, TREE_TYPE (parms), 0, DECL_RTL (parms)); - else if (GET_CODE (DECL_RTL (parms)) == CONCAT - && PARM_PASSED_IN_MEMORY (parms)) + else if (GET_CODE (DECL_RTL (parms)) == CONCAT) dbxout_symbol_location (parms, TREE_TYPE (parms), 0, DECL_RTL (parms)); /* Report parms that live in memory but not where they were passed. */ else if (GET_CODE (DECL_RTL (parms)) == MEM - && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS - && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT - && PARM_PASSED_IN_MEMORY (parms) && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms))) - { -#if 0 /* ??? It is not clear yet what should replace this. */ - int offset = DECL_OFFSET (parms) / BITS_PER_UNIT; - /* A parm declared char is really passed as an int, - so it occupies the least significant bytes. - On a big-endian machine those are not the low-numbered ones. */ -#if BYTES_BIG_ENDIAN - if (offset != -1 && TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) - offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) - - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))); -#endif - if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...} -#endif - dbxout_symbol_location (parms, TREE_TYPE (parms), - 0, DECL_RTL (parms)); - } -#if 0 - else if (GET_CODE (DECL_RTL (parms)) == MEM - && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG) - { - /* Parm was passed via invisible reference. - 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. */ - - current_sym_code = N_RSYM; - - /* DECL_RTL looks like (MEM (REG...). Get the register number. */ - current_sym_value = REGNO (XEXP (DECL_RTL (parms), 0)); - current_sym_addr = 0; - - FORCE_TEXT; - if (DECL_NAME (parms)) - { - current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms))); - - fprintf (asmfile, "%s \"%s:r", ASM_STABS_OP, - IDENTIFIER_POINTER (DECL_NAME (parms))); - } - else - { - current_sym_nchars = 8; - fprintf (asmfile, "%s \"(anon):r", ASM_STABS_OP); - } - - dbxout_type (TREE_TYPE (parms), 0, 0); - dbxout_finish_symbol (parms); - } -#endif + dbxout_symbol_location (parms, TREE_TYPE (parms), + 0, DECL_RTL (parms)); } } @@ -2562,5 +2599,13 @@ dbxout_function (decl) #ifdef DBX_OUTPUT_FUNCTION_END DBX_OUTPUT_FUNCTION_END (asmfile, decl); #endif +#if defined(ASM_OUTPUT_SECTION_NAME) + if (use_gnu_debug_info_extensions +#if defined(NO_DBX_FUNCTION_END) + && ! NO_DBX_FUNCTION_END +#endif + ) + dbxout_function_end (); +#endif } #endif /* DBX_DEBUGGING_INFO */