diff options
author | obrien <obrien@FreeBSD.org> | 2002-02-01 19:10:11 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2002-02-01 19:10:11 +0000 |
commit | e638c832dc1f5992593bfe7dc13bbbc09c19e490 (patch) | |
tree | dfde6957e6a448b733852e587f9898a753db8007 /contrib | |
parent | 460c84b46faf7a4c13edd82ce7de006a1c6dc474 (diff) | |
download | FreeBSD-src-e638c832dc1f5992593bfe7dc13bbbc09c19e490.zip FreeBSD-src-e638c832dc1f5992593bfe7dc13bbbc09c19e490.tar.gz |
Use the stock 3.1-snap file now.
I do not think our rev 1.2 changes are needed any longer.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/gcc/dbxout.c | 1458 |
1 files changed, 810 insertions, 648 deletions
diff --git a/contrib/gcc/dbxout.c b/contrib/gcc/dbxout.c index 3f561d6..6e5d1ff 100644 --- a/contrib/gcc/dbxout.c +++ b/contrib/gcc/dbxout.c @@ -1,22 +1,23 @@ /* Output dbx-format symbol table information from GNU compiler. - Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001 Free Software Foundation, Inc. -This file is part of GNU CC. +This file is part of GCC. -GNU CC 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 version. +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 +version. -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +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 GNU CC; 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 COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ /* $FreeBSD$ */ @@ -78,21 +79,26 @@ Boston, MA 02111-1307, USA. */ #include "regs.h" #include "insn-config.h" #include "reload.h" -#include "defaults.h" #include "output.h" /* ASM_OUTPUT_SOURCE_LINE may refer to sdb functions. */ #include "dbxout.h" #include "toplev.h" +#include "tm_p.h" +#include "ggc.h" +#include "debug.h" +#include "function.h" +#include "target.h" +#include "langhooks.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" #endif #ifndef ASM_STABS_OP -#define ASM_STABS_OP ".stabs" +#define ASM_STABS_OP "\t.stabs\t" #endif #ifndef ASM_STABN_OP -#define ASM_STABN_OP ".stabn" +#define ASM_STABN_OP "\t.stabn\t" #endif #ifndef DBX_TYPE_DECL_STABS_CODE @@ -124,29 +130,18 @@ Boston, MA 02111-1307, USA. */ #define FILE_NAME_JOINER "/" #endif -/* Nonzero means if the type has methods, only output debugging - 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 +/* GDB needs to know that the stabs were generated by GCC. We emit an + N_OPT stab at the beginning of the source file to indicate this. + The string is historical, and different on a very few targets. */ +#ifndef STABS_GCC_MARKER +#define STABS_GCC_MARKER "gcc2_compiled." #endif -char *getpwd (); - /* Typical USG systems don't have stab.h, and they also have no use for DBX-format debugging info. */ #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) -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 first time only if there's a strong reason, but once we have done that, @@ -157,7 +152,9 @@ static 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. */ +#if defined (DBX_DEBUGGING_INFO) && !defined (DBX_OUTPUT_SOURCE_FILENAME) static int source_label_number = 1; +#endif #ifdef DEBUG_SYMS_TEXT #define FORCE_TEXT text_section (); @@ -165,26 +162,9 @@ static int source_label_number = 1; #define FORCE_TEXT #endif -/* If there is a system stab.h, use it. Otherwise, use our own. */ -/* ??? This is supposed to describe the target's stab format, so using - the host HAVE_STAB_H appears to be wrong. For now, we use our own file - when cross compiling. */ -#if defined (USG) || !defined (HAVE_STAB_H) || defined (CROSS_COMPILE) -#include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */ -#else -#include <stab.h> - -/* This is a GNU extension we need to reference in this file. */ -#ifndef N_CATCH -#define N_CATCH 0x54 -#endif -#endif +#include "gstab.h" -#ifdef __GNU_STAB__ #define STAB_CODE_TYPE enum __stab_debug_code -#else -#define STAB_CODE_TYPE int -#endif /* 1 if PARM is passed to this function in memory. */ @@ -210,11 +190,11 @@ static FILE *asmfile; /* Last source file name mentioned in a NOTE insn. */ -static char *lastfile; +static const char *lastfile; /* Current working directory. */ -static char *cwd; +static const char *cwd; enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED}; @@ -274,16 +254,6 @@ 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 - end of the ranges of code in each block - with assembler labels LBBn and LBEn, where n is the block number. - The labels are generated in final, which assigns numbers to the - blocks in the same way. */ - -static int next_block_number; - /* These variables are for dbxout_symbol to communicate to dbxout_finish_symbol. current_sym_code is the symbol-type-code, a symbol N_... define in stab.h. @@ -318,37 +288,102 @@ static int current_sym_nchars; #define CONTIN \ do {if (current_sym_nchars > DBX_CONTIN_LENGTH) dbxout_continue ();} while (0) #else -#define CONTIN +#define CONTIN do { } while (0) #endif -void dbxout_types (); -void dbxout_args (); -void dbxout_symbol (); - -#if defined(ASM_OUTPUT_SECTION_NAME) -static void dbxout_function_end PROTO((void)); -#endif -static void dbxout_typedefs PROTO((tree)); -static void dbxout_type_index PROTO((tree)); +static void dbxout_init PARAMS ((const char *)); +static void dbxout_finish PARAMS ((const char *)); +static void dbxout_start_source_file PARAMS ((unsigned, const char *)); +static void dbxout_end_source_file PARAMS ((unsigned)); +static void dbxout_typedefs PARAMS ((tree)); +static void dbxout_type_index PARAMS ((tree)); #if DBX_CONTIN_LENGTH > 0 -static void dbxout_continue PROTO((void)); -#endif -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)); +static void dbxout_continue PARAMS ((void)); +#endif +static void dbxout_args PARAMS ((tree)); +static void dbxout_type_fields PARAMS ((tree)); +static void dbxout_type_method_1 PARAMS ((tree, const char *)); +static void dbxout_type_methods PARAMS ((tree)); +static void dbxout_range_type PARAMS ((tree)); +static void dbxout_type PARAMS ((tree, int)); +static void print_int_cst_octal PARAMS ((tree)); +static void print_octal PARAMS ((unsigned HOST_WIDE_INT, int)); +static void print_wide_int PARAMS ((HOST_WIDE_INT)); +static void dbxout_type_name PARAMS ((tree)); +static int dbxout_symbol_location PARAMS ((tree, tree, const char *, rtx)); +static void dbxout_symbol_name PARAMS ((tree, const char *, int)); +static void dbxout_prepare_symbol PARAMS ((tree)); +static void dbxout_finish_symbol PARAMS ((tree)); +static void dbxout_block PARAMS ((tree, int, tree)); +static void dbxout_global_decl PARAMS ((tree)); + +/* The debug hooks structure. */ +#if defined (DBX_DEBUGGING_INFO) + +static void dbxout_source_line PARAMS ((unsigned int, const char *)); +static void dbxout_source_file PARAMS ((FILE *, const char *)); +static void dbxout_function_end PARAMS ((void)); +static void dbxout_begin_function PARAMS ((tree)); +static void dbxout_begin_block PARAMS ((unsigned, unsigned)); +static void dbxout_end_block PARAMS ((unsigned, unsigned)); +static void dbxout_function_decl PARAMS ((tree)); + +struct gcc_debug_hooks dbx_debug_hooks = +{ + dbxout_init, + dbxout_finish, + 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 */ + dbxout_source_line, /* source_line */ + dbxout_source_line, /* begin_prologue: just output line info */ + debug_nothing_int, /* end_prologue */ + debug_nothing_void, /* end_epilogue */ +#ifdef DBX_FUNCTION_FIRST + dbxout_begin_function, +#else + debug_nothing_tree, /* begin_function */ +#endif + debug_nothing_int, /* end_function */ + dbxout_function_decl, + dbxout_global_decl, /* global_decl */ + debug_nothing_tree, /* deferred_inline_function */ + debug_nothing_tree, /* outlining_inline_function */ + debug_nothing_rtx /* label */ +}; +#endif /* DBX_DEBUGGING_INFO */ + +#if defined (XCOFF_DEBUGGING_INFO) +struct gcc_debug_hooks xcoff_debug_hooks = +{ + dbxout_init, + dbxout_finish, + 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 */ + xcoffout_source_line, + xcoffout_begin_prologue, /* begin_prologue */ + debug_nothing_int, /* end_prologue */ + xcoffout_end_epilogue, + debug_nothing_tree, /* begin_function */ + xcoffout_end_function, + debug_nothing_tree, /* function_decl */ + dbxout_global_decl, /* global_decl */ + debug_nothing_tree, /* deferred_inline_function */ + debug_nothing_tree, /* outlining_inline_function */ + debug_nothing_rtx /* label */ +}; +#endif /* XCOFF_DEBUGGING_INFO */ -#if defined(ASM_OUTPUT_SECTION_NAME) +#if defined (DBX_DEBUGGING_INFO) static void dbxout_function_end () { @@ -363,30 +398,28 @@ dbxout_function_end () /* 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); + fprintf (asmfile, "%s\"\",%d,0,0,", ASM_STABS_OP, N_FUN); assemble_name (asmfile, lscope_label_name); - fputc ('-', asmfile); + putc ('-', asmfile); assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); fprintf (asmfile, "\n"); } -#endif /* ! NO_DBX_FUNCTION_END */ +#endif /* DBX_DEBUGGING_INFO */ /* At the beginning of compilation, start writing the symbol table. Initialize `typevec' and output the standard data types of C. */ -void -dbxout_init (asm_file, input_file_name, syms) - FILE *asm_file; - char *input_file_name; - tree syms; +static void +dbxout_init (input_file_name) + const char *input_file_name; { char ltext_label_name[100]; + tree syms = getdecls (); - asmfile = asm_file; + asmfile = asm_out_file; typevec_len = 100; - typevec = (struct typeinfo *) xmalloc (typevec_len * sizeof typevec[0]); - bzero ((char *) typevec, typevec_len * sizeof typevec[0]); + typevec = (struct typeinfo *) xcalloc (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 @@ -400,19 +433,17 @@ dbxout_init (asm_file, input_file_name, syms) #endif { if (!cwd && (cwd = getpwd ()) && (!*cwd || cwd[strlen (cwd) - 1] != '/')) - { - char *wdslash = xmalloc (strlen (cwd) + sizeof (FILE_NAME_JOINER)); - sprintf (wdslash, "%s%s", cwd, FILE_NAME_JOINER); - cwd = wdslash; - } + cwd = concat (cwd, FILE_NAME_JOINER, NULL); if (cwd) { #ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asmfile, cwd); #else /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */ - fprintf (asmfile, "%s ", ASM_STABS_OP); + fprintf (asmfile, "%s", ASM_STABS_OP); output_quoted_string (asmfile, cwd); - fprintf (asmfile, ",%d,0,0,%s\n", N_SO, <ext_label_name[1]); + fprintf (asmfile, ",%d,0,0,", N_SO); + assemble_name (asmfile, ltext_label_name); + fputc ('\n', asmfile); #endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */ } } @@ -425,25 +456,26 @@ dbxout_init (asm_file, input_file_name, syms) /* We include outputting `Ltext:' here, because that gives you a way to override it. */ /* Used to put `Ltext:' before the reference, but that loses on sun 4. */ - fprintf (asmfile, "%s ", ASM_STABS_OP); + fprintf (asmfile, "%s", ASM_STABS_OP); output_quoted_string (asmfile, input_file_name); - fprintf (asmfile, ",%d,0,0,%s\n", - N_SO, <ext_label_name[1]); + fprintf (asmfile, ",%d,0,0,", N_SO); + assemble_name (asmfile, ltext_label_name); + fputc ('\n', asmfile); text_section (); ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Ltext", 0); #endif /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */ - /* Possibly output something to inform GDB that this compilation was by - GCC. It's easier for GDB to parse it when after the N_SO's. This - is used in Solaris 2. */ -#ifdef ASM_IDENTIFY_GCC_AFTER_SOURCE - ASM_IDENTIFY_GCC_AFTER_SOURCE (asmfile); +#ifdef DBX_OUTPUT_GCC_MARKER + DBX_OUTPUT_GCC_MARKER (asmfile); +#else + /* Emit an N_OPT stab to indicate that this file was compiled by GCC. */ + fprintf (asmfile, "%s\"%s\",%d,0,0,0\n", + ASM_STABS_OP, STABS_GCC_MARKER, N_OPT); #endif lastfile = input_file_name; next_type_number = 1; - next_block_number = 2; #ifdef DBX_USE_BINCL current_file = (struct dbx_file *) xmalloc (sizeof *current_file); @@ -488,7 +520,7 @@ dbxout_typedefs (syms) tree type = TREE_TYPE (syms); if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && TYPE_SIZE (type) != NULL_TREE + && COMPLETE_TYPE_P (type) && ! TREE_ASM_WRITTEN (TYPE_NAME (type))) dbxout_symbol (TYPE_NAME (type), 0); } @@ -497,9 +529,10 @@ dbxout_typedefs (syms) /* Change to reading from a new source file. Generate a N_BINCL stab. */ -void -dbxout_start_new_source_file (filename) - char *filename ATTRIBUTE_UNUSED; +static void +dbxout_start_source_file (line, filename) + unsigned int line ATTRIBUTE_UNUSED; + const char *filename ATTRIBUTE_UNUSED; { #ifdef DBX_USE_BINCL struct dbx_file *n = (struct dbx_file *) xmalloc (sizeof *n); @@ -508,7 +541,7 @@ dbxout_start_new_source_file (filename) n->file_number = next_file_number++; n->next_type_number = 1; current_file = n; - fprintf (asmfile, "%s ", ASM_STABS_OP); + fprintf (asmfile, "%s", ASM_STABS_OP); output_quoted_string (asmfile, filename); fprintf (asmfile, ",%d,0,0,0\n", N_BINCL); #endif @@ -516,38 +549,42 @@ dbxout_start_new_source_file (filename) /* Revert to reading a previous source file. Generate a N_EINCL stab. */ -void -dbxout_resume_previous_source_file () +static void +dbxout_end_source_file (line) + unsigned int line ATTRIBUTE_UNUSED; { #ifdef DBX_USE_BINCL struct dbx_file *next; - fprintf (asmfile, "%s %d,0,0,0\n", ASM_STABN_OP, N_EINCL); + fprintf (asmfile, "%s%d,0,0,0\n", ASM_STABN_OP, N_EINCL); next = current_file->next; free (current_file); current_file = next; #endif } +#if defined (DBX_DEBUGGING_INFO) /* Output debugging info to FILE to switch to sourcefile FILENAME. */ -void +static void dbxout_source_file (file, filename) FILE *file; - char *filename; + const char *filename; { - char ltext_label_name[100]; - if (filename && (lastfile == 0 || strcmp (filename, lastfile))) { #ifdef DBX_OUTPUT_SOURCE_FILENAME DBX_OUTPUT_SOURCE_FILENAME (file, filename); #else + char ltext_label_name[100]; + ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", source_label_number); - fprintf (file, "%s ", ASM_STABS_OP); + fprintf (file, "%s", ASM_STABS_OP); output_quoted_string (file, filename); - fprintf (file, ",%d,0,0,%s\n", N_SOL, <ext_label_name[1]); + fprintf (asmfile, ",%d,0,0,", N_SOL); + assemble_name (asmfile, ltext_label_name); + fputc ('\n', asmfile); if (current_function_decl != NULL_TREE && DECL_SECTION_NAME (current_function_decl) != NULL_TREE) ; /* Don't change section amid function. */ @@ -560,35 +597,92 @@ dbxout_source_file (file, filename) } } -/* Output a line number symbol entry into output stream FILE, - for source file FILENAME and line number LINENO. */ +/* Output a line number symbol entry for source file FILENAME and line + number LINENO. */ -void -dbxout_source_line (file, filename, lineno) - FILE *file; - char *filename; - int lineno; +static void +dbxout_source_line (lineno, filename) + unsigned int lineno; + const char *filename; { - dbxout_source_file (file, filename); + dbxout_source_file (asmfile, filename); #ifdef ASM_OUTPUT_SOURCE_LINE - ASM_OUTPUT_SOURCE_LINE (file, lineno); + ASM_OUTPUT_SOURCE_LINE (asmfile, lineno); #else - fprintf (file, "\t%s %d,0,%d\n", ASM_STABD_OP, N_SLINE, lineno); + fprintf (asmfile, "%s%d,0,%d\n", ASM_STABD_OP, N_SLINE, lineno); +#endif +} + +/* Describe the beginning of an internal block within a function. */ + +static void +dbxout_begin_block (line, n) + unsigned int line ATTRIBUTE_UNUSED; + unsigned int n; +{ + ASM_OUTPUT_INTERNAL_LABEL (asmfile, "LBB", n); +} + +/* Describe the end line-number of an internal block within a function. */ + +static void +dbxout_end_block (line, n) + unsigned int line ATTRIBUTE_UNUSED; + unsigned int n; +{ + ASM_OUTPUT_INTERNAL_LABEL (asmfile, "LBE", n); +} + +/* Output dbx data for a function definition. + This includes a definition of the function name itself (a symbol), + definitions of the parameters (locating them in the parameter list) + and then output the block that makes up the function's body + (including all the auto variables of the function). */ + +static void +dbxout_function_decl (decl) + tree decl; +{ +#ifndef DBX_FUNCTION_FIRST + dbxout_begin_function (decl); +#endif + dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl)); +#ifdef DBX_OUTPUT_FUNCTION_END + DBX_OUTPUT_FUNCTION_END (asmfile, decl); +#endif + if (use_gnu_debug_info_extensions +#if defined(NO_DBX_FUNCTION_END) + && ! NO_DBX_FUNCTION_END #endif + && targetm.have_named_sections) + dbxout_function_end (); } +#endif /* DBX_DEBUGGING_INFO */ + +/* Debug information for a global DECL. Called from toplev.c after + compilation proper has finished. */ +static void +dbxout_global_decl (decl) + tree decl; +{ + if (TREE_CODE (decl) == VAR_DECL + && ! DECL_EXTERNAL (decl) + && DECL_RTL_SET_P (decl)) /* Not necessary? */ + dbxout_symbol (decl, 0); +} + /* 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. */ -void -dbxout_finish (file, filename) - FILE *file ATTRIBUTE_UNUSED; - char *filename ATTRIBUTE_UNUSED; +static void +dbxout_finish (filename) + const char *filename ATTRIBUTE_UNUSED; { #ifdef DBX_OUTPUT_MAIN_SOURCE_FILE_END - DBX_OUTPUT_MAIN_SOURCE_FILE_END (file, filename); + DBX_OUTPUT_MAIN_SOURCE_FILE_END (asmfile, filename); #endif /* DBX_OUTPUT_MAIN_SOURCE_FILE_END */ } @@ -604,7 +698,7 @@ dbxout_type_index (type) #else struct typeinfo *t = &typevec[TYPE_SYMTAB_ADDRESS (type)]; fprintf (asmfile, "(%d,%d)", t->file_number, t->type_number); - CHARS (7); + CHARS (9); #endif } @@ -624,7 +718,7 @@ dbxout_continue () fprintf (asmfile, "\\\\"); #endif dbxout_finish_symbol (NULL_TREE); - fprintf (asmfile, "%s \"", ASM_STABS_OP); + fprintf (asmfile, "%s\"", ASM_STABS_OP); current_sym_nchars = 0; } #endif /* DBX_CONTIN_LENGTH > 0 */ @@ -638,48 +732,29 @@ dbxout_type_fields (type) tree type; { tree tem; + /* Output the name, type, position (in bits), size (in bits) of each - field. */ + field that we can support. */ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) { /* Omit here local type decls until we know how to support them. */ - if (TREE_CODE (tem) == TYPE_DECL) - continue; - /* Omit fields whose position or size are variable. */ - else if (TREE_CODE (tem) == FIELD_DECL - && (TREE_CODE (DECL_FIELD_BITPOS (tem)) != INTEGER_CST - || TREE_CODE (DECL_SIZE (tem)) != INTEGER_CST)) - continue; - /* Omit here the nameless fields that are used to skip bits. */ - else if (DECL_IGNORED_P (tem)) + if (TREE_CODE (tem) == TYPE_DECL + /* 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)) continue; + else if (TREE_CODE (tem) != CONST_DECL) { /* Continue the line if necessary, but not before the first field. */ if (tem != TYPE_FIELDS (type)) - { - CONTIN; - } - - if (use_gnu_debug_info_extensions - && flag_minimal_debug - && TREE_CODE (tem) == FIELD_DECL - && DECL_VIRTUAL_P (tem) - && DECL_ASSEMBLER_NAME (tem)) - { - have_used_extensions = 1; - 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, ":"); - dbxout_type (TREE_TYPE (tem), 0, 0); - fputc (',', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem))); - fputc (';', asmfile); - continue; - } + CONTIN; if (DECL_NAME (tem)) { @@ -689,7 +764,7 @@ dbxout_type_fields (type) else { fprintf (asmfile, ":"); - CHARS (2); + CHARS (1); } if (use_gnu_debug_info_extensions @@ -706,35 +781,34 @@ dbxout_type_fields (type) dbxout_type ((TREE_CODE (tem) == FIELD_DECL && DECL_BIT_FIELD_TYPE (tem)) - ? DECL_BIT_FIELD_TYPE (tem) - : TREE_TYPE (tem), 0, 0); + ? DECL_BIT_FIELD_TYPE (tem) : TREE_TYPE (tem), 0); if (TREE_CODE (tem) == VAR_DECL) { if (TREE_STATIC (tem) && use_gnu_debug_info_extensions) { - char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem)); + tree name = DECL_ASSEMBLER_NAME (tem); + have_used_extensions = 1; - fprintf (asmfile, ":%s;", name); - CHARS (strlen (name)); + fprintf (asmfile, ":%s;", IDENTIFIER_POINTER (name)); + CHARS (IDENTIFIER_LENGTH (name) + 2); } else { /* If TEM is non-static, GDB won't understand it. */ fprintf (asmfile, ",0,0;"); + CHARS (5); } } - else if (TREE_CODE (DECL_FIELD_BITPOS (tem)) == INTEGER_CST) + else { - fputc (',', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem))); - fputc (',', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (DECL_SIZE (tem))); - fputc (';', asmfile); + putc (',', asmfile); + print_wide_int (int_bit_position (tem)); + putc (',', asmfile); + print_wide_int (tree_low_cst (DECL_SIZE (tem), 1)); + putc (';', asmfile); + CHARS (3); } - CHARS (23); } } } @@ -747,7 +821,7 @@ dbxout_type_fields (type) static void dbxout_type_method_1 (decl, debug_name) tree decl; - char *debug_name; + const char *debug_name; { char c1 = 'A', c2; @@ -772,17 +846,19 @@ dbxout_type_method_1 (decl, debug_name) } fprintf (asmfile, ":%s;%c%c%c", debug_name, - TREE_PRIVATE (decl) ? '0' : TREE_PROTECTED (decl) ? '1' : '2', c1, c2); + TREE_PRIVATE (decl) ? '0' + : TREE_PROTECTED (decl) ? '1' : '2', c1, c2); CHARS (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl)) + 6 - (debug_name - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)))); - if (DECL_VINDEX (decl)) + + if (DECL_VINDEX (decl) && host_integerp (DECL_VINDEX (decl), 0)) { - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (DECL_VINDEX (decl))); - fputc (';', asmfile); - dbxout_type (DECL_CONTEXT (decl), 0, 0); + print_wide_int (tree_low_cst (DECL_VINDEX (decl), 0)); + putc (';', asmfile); + CHARS (1); + dbxout_type (DECL_CONTEXT (decl), 0); fprintf (asmfile, ";"); - CHARS (8); + CHARS (1); } } @@ -791,15 +867,15 @@ dbxout_type_method_1 (decl, debug_name) static void dbxout_type_methods (type) - register tree type; + tree type; { /* C++: put out the method names and their parameter lists */ tree methods = TYPE_METHODS (type); tree type_encoding; - register tree fndecl; - register tree last; + tree fndecl; + tree last; char formatted_type_identifier_length[16]; - register int type_identifier_length; + int type_identifier_length; if (methods == NULL_TREE) return; @@ -811,7 +887,7 @@ dbxout_type_methods (type) the class names, constructor names, and encodings for assembler label names. For now, disable output of dbx info for them. */ { - char *ptr = IDENTIFIER_POINTER (type_encoding); + const char *ptr = IDENTIFIER_POINTER (type_encoding); /* This should use index. (mrs) */ while (*ptr && *ptr != '<') ptr++; if (*ptr != 0) @@ -826,7 +902,7 @@ dbxout_type_methods (type) type_identifier_length = IDENTIFIER_LENGTH (type_encoding); - sprintf(formatted_type_identifier_length, "%d", type_identifier_length); + sprintf (formatted_type_identifier_length, "%d", type_identifier_length); if (TREE_CODE (methods) != TREE_VEC) fndecl = methods; @@ -837,7 +913,6 @@ dbxout_type_methods (type) while (fndecl) { - tree name = DECL_NAME (fndecl); int need_prefix = 1; /* Group together all the methods for the same operation. @@ -851,83 +926,36 @@ 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 show_arg_types = 0; + const char *debug_name; + + /* Skip methods that aren't FUNCTION_DECLs. (In C++, these + include TEMPLATE_DECLs.) The debugger doesn't know what + to do with such entities anyhow. */ + if (TREE_CODE (fndecl) != FUNCTION_DECL) + continue; + + debug_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)); CONTIN; last = fndecl; - if (DECL_IGNORED_P (fndecl)) + /* Also ignore abstract methods; those are only interesting to + the DWARF backends. */ + if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT (fndecl)) continue; - if (flag_minimal_debug) + /* Redundantly output the plain name, since that's what gdb + expects. */ + if (need_prefix) { - 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. */ - else if (!strncmp (IDENTIFIER_POINTER (name), debug_name, - IDENTIFIER_LENGTH (name))) - { - debug_name += IDENTIFIER_LENGTH (name); - if (debug_name[0] == '_' && debug_name[1] == '_') - { - char *method_name = debug_name + 2; - char *length_ptr = formatted_type_identifier_length; - /* Get past const and volatile qualifiers. */ - while (*method_name == 'C' || *method_name == 'V') - method_name++; - /* Skip digits for length of type_encoding. */ - while (*method_name == *length_ptr && *length_ptr) - length_ptr++, method_name++; - if (! strncmp (method_name, - IDENTIFIER_POINTER (type_encoding), - type_identifier_length)) - method_name += type_identifier_length; - debug_name = method_name; - } - } - /* Detect constructors by their style of name mangling. */ - else if (debug_name[0] == '_' && debug_name[1] == '_') - { - char *ctor_name = debug_name + 2; - char *length_ptr = formatted_type_identifier_length; - while (*ctor_name == 'C' || *ctor_name == 'V') - ctor_name++; - /* 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, - type_identifier_length)) - debug_name = ctor_name + type_identifier_length; - } - /* The other alternative is a destructor. */ - else - show_arg_types = 1; - - /* Output the operation name just once, for the first method - that we output. */ - if (need_prefix) - { - fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name)); - CHARS (IDENTIFIER_LENGTH (name) + 2); - need_prefix = 0; - } + tree name = DECL_NAME (fndecl); + fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name)); + CHARS (IDENTIFIER_LENGTH (name) + 2); + need_prefix = 0; } - dbxout_type (TREE_TYPE (fndecl), 0, show_arg_types); + dbxout_type (TREE_TYPE (fndecl), 0); dbxout_type_method_1 (fndecl, debug_name); } @@ -949,9 +977,9 @@ dbxout_range_type (type) { fprintf (asmfile, "r"); if (TREE_TYPE (type)) - dbxout_type (TREE_TYPE (type), 0, 0); + dbxout_type (TREE_TYPE (type), 0); else if (TREE_CODE (type) != INTEGER_TYPE) - dbxout_type (type, 0, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */ + dbxout_type (type, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */ else { /* Traditionally, we made sure 'int' was type 1, and builtin types @@ -971,24 +999,34 @@ dbxout_range_type (type) else dbxout_type_index (integer_type_node); } - if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST) + + if (TYPE_MIN_VALUE (type) != 0 + && host_integerp (TYPE_MIN_VALUE (type), 0)) { - fputc (';', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (TYPE_MIN_VALUE (type))); + putc (';', asmfile); + CHARS (1); + print_wide_int (tree_low_cst (TYPE_MIN_VALUE (type), 0)); } else - fprintf (asmfile, ";0"); - if (TYPE_MAX_VALUE (type) - && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST) { - fputc (';', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (TYPE_MAX_VALUE (type))); - fputc (';', asmfile); + fprintf (asmfile, ";0"); + CHARS (2); + } + + if (TYPE_MAX_VALUE (type) != 0 + && host_integerp (TYPE_MAX_VALUE (type), 0)) + { + putc (';', asmfile); + CHARS (1); + print_wide_int (tree_low_cst (TYPE_MAX_VALUE (type), 0)); + putc (';', asmfile); + CHARS (1); } else - fprintf (asmfile, ";-1;"); + { + fprintf (asmfile, ";-1;"); + CHARS (4); + } } /* Output a reference to a type. If the type has not yet been @@ -999,20 +1037,20 @@ dbxout_range_type (type) If FULL is nonzero, and the type has been described only with a forward-reference, output the definition now. If FULL is zero in this case, just refer to the forward-reference - using the number previously allocated. - - If SHOW_ARG_TYPES is nonzero, we output a description of the argument - types for a METHOD_TYPE. */ + using the number previously allocated. */ static void -dbxout_type (type, full, show_arg_types) +dbxout_type (type, full) tree type; int full; - int show_arg_types; { - register tree tem; + tree tem; + tree main_variant; static int anonymous_type_number = 0; + if (TREE_CODE (type) == VECTOR_TYPE) + type = TYPE_DEBUG_REPRESENTATION_TYPE (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 by assuming `int'. */ @@ -1020,24 +1058,24 @@ dbxout_type (type, full, show_arg_types) type = integer_type_node; else { - /* 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 && TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type))) full = 0; } + /* Try to find the "main variant" with the same name. */ + if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) + main_variant = TREE_TYPE (TYPE_NAME (type)); + else + main_variant = TYPE_MAIN_VARIANT (type); + + /* If we are not using extensions, stabs does not distinguish const and + volatile, so there is no need to make them separate types. */ + if (!use_gnu_debug_info_extensions) + type = main_variant; + if (TYPE_SYMTAB_ADDRESS (type) == 0) { /* Type has no dbx number assigned. Assign next available number. */ @@ -1050,7 +1088,7 @@ dbxout_type (type, full, show_arg_types) typevec = (struct typeinfo *) xrealloc (typevec, typevec_len * 2 * sizeof typevec[0]); - bzero ((char *) (typevec + typevec_len), + memset ((char *) (typevec + typevec_len), 0, typevec_len * sizeof typevec[0]); typevec_len *= 2; } @@ -1083,9 +1121,9 @@ dbxout_type (type, full, show_arg_types) and either that's all we want or that's the best we could do, don't repeat the cross reference. Sun dbx crashes if we do. */ - if (! full || TYPE_SIZE (type) == 0 + if (! full || !COMPLETE_TYPE_P (type) /* No way in DBX fmt to describe a variable size. */ - || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + || ! host_integerp (TYPE_SIZE (type), 1)) return; break; case TYPE_DEFINED: @@ -1108,9 +1146,9 @@ dbxout_type (type, full, show_arg_types) && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_IGNORED_P (TYPE_NAME (type))) && !full) - || TYPE_SIZE (type) == 0 + || !COMPLETE_TYPE_P (type) /* No way in DBX fmt to describe a variable size. */ - || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + || ! host_integerp (TYPE_SIZE (type), 1)) { typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; return; @@ -1127,12 +1165,30 @@ dbxout_type (type, full, show_arg_types) 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); + /* If this type is a variant of some other, hand off. Types with + different names are usefully distinguished. We only distinguish + cv-qualified types if we're using extensions. */ + if (TYPE_READONLY (type) > TYPE_READONLY (main_variant)) + { + putc ('k', asmfile); + CHARS (1); + dbxout_type (build_type_variant (type, 0, TYPE_VOLATILE (type)), 0); + return; + } + else if (TYPE_VOLATILE (type) > TYPE_VOLATILE (main_variant)) + { + putc ('B', asmfile); + CHARS (1); + dbxout_type (build_type_variant (type, TYPE_READONLY (type), 0), 0); return; } + else if (main_variant != TYPE_MAIN_VARIANT (type)) + { + /* 'type' is a typedef; output the type it refers to. */ + dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0); + return; + } + /* else continue. */ switch (TREE_CODE (type)) { @@ -1155,78 +1211,132 @@ dbxout_type (type, full, show_arg_types) This used to use `r2' explicitly and we used to take care to make sure that `char' was type number 2. */ fprintf (asmfile, "r"); + CHARS (1); dbxout_type_index (type); fprintf (asmfile, ";0;127;"); + CHARS (7); } - /* This used to check if the type's precision was more than - HOST_BITS_PER_WIDE_INT. That is wrong since gdb uses a - long (it has no concept of HOST_BITS_PER_WIDE_INT). */ - else if (use_gnu_debug_info_extensions - && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node) - || TYPE_PRECISION (type) >= HOST_BITS_PER_LONG)) - { - /* This used to say `r1' and we used to take care - to make sure that `int' was type number 1. */ - 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)); - fprintf (asmfile, ";"); - } - else /* Output other integer types as subranges of `int'. */ + + /* If this is a subtype of another integer type, always prefer to + write it as a subtype. */ + else if (TREE_TYPE (type) != 0 + && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE) dbxout_range_type (type); - CHARS (22); + + else + { + /* If the size is non-standard, say what it is if we can use + GDB extensions. */ + + if (use_gnu_debug_info_extensions + && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) + { + have_used_extensions = 1; + fprintf (asmfile, "@s%d;", TYPE_PRECISION (type)); + CHARS (5); + } + + /* 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 the bounds the usual way, write them in + octal. Note the test is for the *target's* size of "long", + not that of the host. The host test is just to make sure we + can write it out in case the host wide int is narrower than the + target "long". */ + + /* For unsigned types, we use octal if they are the same size or + larger. This is because we print the bounds as signed decimal, + and hence they 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 + && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node) + || ((TYPE_PRECISION (type) + == TYPE_PRECISION (integer_type_node)) + && TREE_UNSIGNED (type)) + || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT + || (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT + && TREE_UNSIGNED (type)))) + { + fprintf (asmfile, "r"); + CHARS (1); + dbxout_type_index (type); + fprintf (asmfile, ";"); + CHARS (1); + print_int_cst_octal (TYPE_MIN_VALUE (type)); + fprintf (asmfile, ";"); + CHARS (1); + print_int_cst_octal (TYPE_MAX_VALUE (type)); + fprintf (asmfile, ";"); + CHARS (1); + } + + else + /* Output other integer types as subranges of `int'. */ + dbxout_range_type (type); + } + 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"); + CHARS (1); dbxout_type_index (integer_type_node); - fputc (';', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, int_size_in_bytes (type)); + putc (';', asmfile); + CHARS (1); + print_wide_int (int_size_in_bytes (type)); fputs (";0;", asmfile); - CHARS (13); + CHARS (3); break; case CHAR_TYPE: if (use_gnu_debug_info_extensions) { + have_used_extensions = 1; fputs ("@s", asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - BITS_PER_UNIT * int_size_in_bytes (type)); + CHARS (2); + print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type)); fputs (";-20;", asmfile); + CHARS (4); } else { /* Output the type `char' as a subrange of itself. That is what pcc seems to do. */ fprintf (asmfile, "r"); + CHARS (1); dbxout_type_index (char_type_node); fprintf (asmfile, ";0;%d;", TREE_UNSIGNED (type) ? 255 : 127); + CHARS (7); } - CHARS (9); break; case BOOLEAN_TYPE: if (use_gnu_debug_info_extensions) { + have_used_extensions = 1; fputs ("@s", asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - BITS_PER_UNIT * int_size_in_bytes (type)); + CHARS (2); + print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type)); fputs (";-16;", asmfile); + CHARS (4); } else /* Define as enumeral type (False, True) */ - fprintf (asmfile, "eFalse:0,True:1,;"); - CHARS (17); + { + fprintf (asmfile, "eFalse:0,True:1,;"); + CHARS (17); + } break; case FILE_TYPE: putc ('d', asmfile); CHARS (1); - dbxout_type (TREE_TYPE (type), 0, 0); + dbxout_type (TREE_TYPE (type), 0); break; case COMPLEX_TYPE: @@ -1235,33 +1345,33 @@ dbxout_type (type, full, show_arg_types) if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE) { fprintf (asmfile, "r"); + CHARS (1); dbxout_type_index (type); - fputc (';', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - int_size_in_bytes (TREE_TYPE (type))); + putc (';', asmfile); + CHARS (1); + print_wide_int (2 * int_size_in_bytes (TREE_TYPE (type))); fputs (";0;", asmfile); - CHARS (12); /* The number is probably incorrect here. */ + CHARS (3); } else { /* Output a complex integer type as a structure, pending some other way to do it. */ - fputc ('s', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, int_size_in_bytes (type)); - + putc ('s', asmfile); + CHARS (1); + print_wide_int (int_size_in_bytes (type)); fprintf (asmfile, "real:"); - CHARS (10); - dbxout_type (TREE_TYPE (type), 0, 0); - fprintf (asmfile, ",%d,%d;", - 0, TYPE_PRECISION (TREE_TYPE (type))); - CHARS (8); + CHARS (5); + + dbxout_type (TREE_TYPE (type), 0); + fprintf (asmfile, ",0,%d;", TYPE_PRECISION (TREE_TYPE (type))); + CHARS (7); fprintf (asmfile, "imag:"); CHARS (5); - dbxout_type (TREE_TYPE (type), 0, 0); - fprintf (asmfile, ",%d,%d;;", - TYPE_PRECISION (TREE_TYPE (type)), + dbxout_type (TREE_TYPE (type), 0); + fprintf (asmfile, ",%d,%d;;", TYPE_PRECISION (TREE_TYPE (type)), TYPE_PRECISION (TREE_TYPE (type))); - CHARS (9); + CHARS (10); } break; @@ -1270,17 +1380,22 @@ dbxout_type (type, full, show_arg_types) { have_used_extensions = 1; fputs ("@s", asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - BITS_PER_UNIT * int_size_in_bytes (type)); - fputc (';', asmfile); + CHARS (2); + print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type)); + putc (';', asmfile); + CHARS (1); + /* Check if a bitstring type, which in Chill is different from a [power]set. */ if (TYPE_STRING_FLAG (type)) - fprintf (asmfile, "@S;"); + { + fprintf (asmfile, "@S;"); + CHARS (3); + } } putc ('S', asmfile); CHARS (1); - dbxout_type (TYPE_DOMAIN (type), 0, 0); + dbxout_type (TYPE_DOMAIN (type), 0); break; case ARRAY_TYPE: @@ -1289,15 +1404,14 @@ dbxout_type (type, full, show_arg_types) { have_used_extensions = 1; fputs ("@s", asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - BITS_PER_UNIT * int_size_in_bytes (type)); - fputc (';', asmfile); - fprintf (asmfile, "@S;"); - putc ('S', asmfile); - CHARS (1); - dbxout_type (TYPE_DOMAIN (type), 0, 0); + CHARS (2); + print_wide_int (BITS_PER_UNIT * int_size_in_bytes (type)); + fprintf (asmfile, ";@S;S"); + CHARS (5); + dbxout_type (TYPE_DOMAIN (type), 0); break; } + /* Output "a" followed by a range type definition for the index type of the array followed by a reference to the target-type. @@ -1308,21 +1422,25 @@ dbxout_type (type, full, show_arg_types) { have_used_extensions = 1; fprintf (asmfile, "@S;"); + CHARS (3); } tem = TYPE_DOMAIN (type); if (tem == NULL) { fprintf (asmfile, "ar"); + CHARS (2); dbxout_type_index (integer_type_node); fprintf (asmfile, ";0;-1;"); + CHARS (6); } else { fprintf (asmfile, "a"); + CHARS (1); dbxout_range_type (tem); } - CHARS (14); - dbxout_type (TREE_TYPE (type), 0, 0); + + dbxout_type (TREE_TYPE (type), 0); break; case RECORD_TYPE: @@ -1342,9 +1460,9 @@ dbxout_type (type, full, show_arg_types) && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_IGNORED_P (TYPE_NAME (type))) && !full) - || TYPE_SIZE (type) == 0 + || !COMPLETE_TYPE_P (type) /* No way in DBX fmt to describe a variable size. */ - || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + || ! host_integerp (TYPE_SIZE (type), 1)) { /* If the type is just a cross reference, output one and mark the type as partially described. @@ -1353,8 +1471,8 @@ dbxout_type (type, full, show_arg_types) If the type has a name, don't nest its definition within another type's definition; instead, output an xref and let the definition come when the name is defined. */ - fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu"); - CHARS (3); + fputs ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu", asmfile); + CHARS (2); #if 0 /* This assertion is legitimately false in C++. */ /* We shouldn't be outputting a reference to a type before its definition unless the type has a tag name. @@ -1365,16 +1483,21 @@ dbxout_type (type, full, show_arg_types) if (TYPE_NAME (type) != 0) dbxout_type_name (type); else - fprintf (asmfile, "$$%d", anonymous_type_number++); + { + fprintf (asmfile, "$$%d", anonymous_type_number++); + CHARS (5); + } + fprintf (asmfile, ":"); + CHARS (1); typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; break; } /* Identify record or union, and print its size. */ - fputc (((TREE_CODE (type) == RECORD_TYPE) ? 's' : 'u'), asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - int_size_in_bytes (type)); + putc (((TREE_CODE (type) == RECORD_TYPE) ? 's' : 'u'), asmfile); + CHARS (1); + print_wide_int (int_size_in_bytes (type)); if (use_gnu_debug_info_extensions) { @@ -1388,21 +1511,27 @@ dbxout_type (type, full, show_arg_types) for (i = 0; i < n_baseclasses; i++) { tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i); + if (use_gnu_debug_info_extensions) { have_used_extensions = 1; - putc (TREE_VIA_VIRTUAL (child) ? '1' - : '0', - asmfile); - putc (TREE_VIA_PUBLIC (child) ? '2' - : '0', - asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT); - fputc (',', asmfile); - CHARS (15); - dbxout_type (BINFO_TYPE (child), 0, 0); + putc (TREE_VIA_VIRTUAL (child) ? '1' : '0', asmfile); + putc (TREE_VIA_PUBLIC (child) ? '2' : '0', asmfile); + CHARS (2); + if (TREE_VIA_VIRTUAL (child) && strcmp (lang_hooks.name, "GNU C++") == 0) + /* For a virtual base, print the (negative) offset within + the vtable where we must look to find the necessary + adjustment. */ + print_wide_int (tree_low_cst (BINFO_VPTR_FIELD (child), 0) + * BITS_PER_UNIT); + else + print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0) + * BITS_PER_UNIT); + putc (',', asmfile); + CHARS (1); + dbxout_type (BINFO_TYPE (child), 0); putc (';', asmfile); + CHARS (1); } else { @@ -1410,21 +1539,25 @@ dbxout_type (type, full, show_arg_types) which have the same names at the types they hold. */ dbxout_type_name (BINFO_TYPE (child)); putc (':', asmfile); - dbxout_type (BINFO_TYPE (child), full, 0); - fputc (',', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT); - fputc (',', asmfile); - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (DECL_SIZE (TYPE_NAME (BINFO_TYPE (child)))) * BITS_PER_UNIT); - fputc (';', asmfile); - CHARS (20); + CHARS (1); + dbxout_type (BINFO_TYPE (child), full); + putc (',', asmfile); + CHARS (1); + print_wide_int (tree_low_cst (BINFO_OFFSET (child), 0) + * BITS_PER_UNIT); + putc (',', asmfile); + CHARS (1); + print_wide_int (tree_low_cst (DECL_SIZE + (TYPE_NAME + (BINFO_TYPE (child))), + 0) + * BITS_PER_UNIT); + putc (';', asmfile); + CHARS (1); } } } - CHARS (11); - /* Write out the field declarations. */ dbxout_type_fields (type); if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE) @@ -1432,7 +1565,9 @@ dbxout_type (type, full, show_arg_types) have_used_extensions = 1; dbxout_type_methods (type); } + putc (';', asmfile); + CHARS (1); if (use_gnu_debug_info_extensions && TREE_CODE (type) == RECORD_TYPE /* Avoid the ~ if we don't really need it--it confuses dbx. */ @@ -1442,6 +1577,7 @@ dbxout_type (type, full, show_arg_types) /* Tell GDB+ that it may keep reading. */ putc ('~', asmfile); + CHARS (1); /* We need to write out info about what field this class uses as its "main" vtable pointer field, because if this @@ -1450,10 +1586,12 @@ dbxout_type (type, full, show_arg_types) if (TYPE_VFIELD (type)) { putc ('%', asmfile); - dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0, 0); + CHARS (1); + dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0); } + putc (';', asmfile); - CHARS (3); + CHARS (1); } break; @@ -1465,13 +1603,14 @@ dbxout_type (type, full, show_arg_types) && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_IGNORED_P (TYPE_NAME (type))) && !full) - || TYPE_SIZE (type) == 0) + || !COMPLETE_TYPE_P (type)) { fprintf (asmfile, "xe"); - CHARS (3); + CHARS (2); dbxout_type_name (type); typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; - fprintf (asmfile, ":"); + putc (':', asmfile); + CHARS (1); return; } #ifdef DBX_OUTPUT_ENUM @@ -1479,28 +1618,31 @@ dbxout_type (type, full, show_arg_types) #else if (use_gnu_debug_info_extensions && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) - fprintf (asmfile, "@s%d;", TYPE_PRECISION (type)); + { + fprintf (asmfile, "@s%d;", TYPE_PRECISION (type)); + CHARS (5); + } + putc ('e', asmfile); CHARS (1); for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) { fprintf (asmfile, "%s:", IDENTIFIER_POINTER (TREE_PURPOSE (tem))); + CHARS (IDENTIFIER_LENGTH (TREE_PURPOSE (tem)) + 1); if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == 0) - fprintf (asmfile, HOST_WIDE_INT_PRINT_UNSIGNED, - TREE_INT_CST_LOW (TREE_VALUE (tem))); + print_wide_int (TREE_INT_CST_LOW (TREE_VALUE (tem))); else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1 - && TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0) - fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (TREE_VALUE (tem))); + && (HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0) + print_wide_int (TREE_INT_CST_LOW (TREE_VALUE (tem))); else print_int_cst_octal (TREE_VALUE (tem)); - fprintf (asmfile, ","); - CHARS (20 + IDENTIFIER_LENGTH (TREE_PURPOSE (tem))); + + putc (',', asmfile); + CHARS (1); if (TREE_CHAIN (tem) != 0) - { - CONTIN; - } + CONTIN; } + putc (';', asmfile); CHARS (1); #endif @@ -1509,7 +1651,7 @@ dbxout_type (type, full, show_arg_types) case POINTER_TYPE: putc ('*', asmfile); CHARS (1); - dbxout_type (TREE_TYPE (type), 0, 0); + dbxout_type (TREE_TYPE (type), 0); break; case METHOD_TYPE: @@ -1518,34 +1660,19 @@ dbxout_type (type, full, show_arg_types) have_used_extensions = 1; putc ('#', asmfile); CHARS (1); - if (flag_minimal_debug && !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); - } - else - { - /* When outputting destructors, we need to write - the argument types out longhand. */ - dbxout_type (TYPE_METHOD_BASETYPE (type), 0, 0); - putc (',', asmfile); - CHARS (1); - dbxout_type (TREE_TYPE (type), 0, 0); - dbxout_args (TYPE_ARG_TYPES (type)); - putc (';', asmfile); - CHARS (1); - } + + /* Write the argument types out longhand. */ + dbxout_type (TYPE_METHOD_BASETYPE (type), 0); + putc (',', asmfile); + CHARS (1); + dbxout_type (TREE_TYPE (type), 0); + dbxout_args (TYPE_ARG_TYPES (type)); + putc (';', asmfile); + CHARS (1); } else - { - /* Treat it as a function type. */ - dbxout_type (TREE_TYPE (type), 0, 0); - } + /* Treat it as a function type. */ + dbxout_type (TREE_TYPE (type), 0); break; case OFFSET_TYPE: @@ -1554,17 +1681,14 @@ dbxout_type (type, full, show_arg_types) have_used_extensions = 1; putc ('@', asmfile); CHARS (1); - dbxout_type (TYPE_OFFSET_BASETYPE (type), 0, 0); + dbxout_type (TYPE_OFFSET_BASETYPE (type), 0); putc (',', asmfile); CHARS (1); - dbxout_type (TREE_TYPE (type), 0, 0); + dbxout_type (TREE_TYPE (type), 0); } else - { - /* Should print as an int, because it is really - just an offset. */ - dbxout_type (integer_type_node, 0, 0); - } + /* Should print as an int, because it is really just an offset. */ + dbxout_type (integer_type_node, 0); break; case REFERENCE_TYPE: @@ -1572,13 +1696,13 @@ dbxout_type (type, full, show_arg_types) have_used_extensions = 1; putc (use_gnu_debug_info_extensions ? '&' : '*', asmfile); CHARS (1); - dbxout_type (TREE_TYPE (type), 0, 0); + dbxout_type (TREE_TYPE (type), 0); break; case FUNCTION_TYPE: putc ('f', asmfile); CHARS (1); - dbxout_type (TREE_TYPE (type), 0, 0); + dbxout_type (TREE_TYPE (type), 0); break; default: @@ -1596,7 +1720,7 @@ print_int_cst_octal (c) unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (c); unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (c); int excess = (3 - (HOST_BITS_PER_WIDE_INT % 3)); - int width = TYPE_PRECISION (TREE_TYPE (c)); + unsigned int width = TYPE_PRECISION (TREE_TYPE (c)); /* GDB wants constants with no extra leading "1" bits, so we need to remove any sign-extension that might be @@ -1611,6 +1735,7 @@ print_int_cst_octal (c) high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1); fprintf (asmfile, "0"); + CHARS (1); if (excess == 3) { @@ -1628,7 +1753,8 @@ print_int_cst_octal (c) << (HOST_BITS_PER_WIDE_INT / 3 * 3)) - 1); - fprintf (asmfile, "%o%01o", (int)beg, (int)middle); + fprintf (asmfile, "%o%01o", (int) beg, (int) middle); + CHARS (2); print_octal (end, HOST_BITS_PER_WIDE_INT / 3); } } @@ -1641,16 +1767,37 @@ print_octal (value, digits) int i; for (i = digits - 1; i >= 0; i--) - fprintf (asmfile, "%01o", (int)((value >> (3 * i)) & 7)); + fprintf (asmfile, "%01o", (int) ((value >> (3 * i)) & 7)); + + CHARS (digits); } +/* Output C in decimal while adjusting the number of digits written. */ + +static void +print_wide_int (c) + HOST_WIDE_INT c; +{ + int digs = 0; + + fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, c); + + if (c < 0) + digs++, c = -c; + + while (c > 0) + c /= 10; digs++; + + CHARS (digs); +} + /* Output the name of type TYPE, with no punctuation. Such names can be set up either by typedef declarations or by struct, enum and union tags. */ static void dbxout_type_name (type) - register tree type; + tree type; { tree t; if (TYPE_NAME (type) == 0) @@ -1673,15 +1820,17 @@ dbxout_type_name (type) /* 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. - LOCAL is nonzero if the scope is less than the entire file. */ + LOCAL is nonzero if the scope is less than the entire file. + Return 1 if a stabs might have been emitted. */ -void +int dbxout_symbol (decl, local) tree decl; - int local; + int local ATTRIBUTE_UNUSED; { tree type = TREE_TYPE (decl); tree context = NULL_TREE; + int result = 0; /* Cast avoids warning in old compilers. */ current_sym_code = (STAB_CODE_TYPE) 0; @@ -1692,7 +1841,7 @@ dbxout_symbol (decl, local) if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL) || DECL_IGNORED_P (decl)) - return; + return 0; dbxout_prepare_symbol (decl); @@ -1710,7 +1859,7 @@ dbxout_symbol (decl, local) case FUNCTION_DECL: if (DECL_RTL (decl) == 0) - return; + return 0; if (DECL_EXTERNAL (decl)) break; /* Don't mention a nested function under its parent. */ @@ -1722,17 +1871,18 @@ dbxout_symbol (decl, local) break; FORCE_TEXT; - fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, + fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), TREE_PUBLIC (decl) ? 'F' : 'f'); + result = 1; current_sym_code = N_FUN; current_sym_addr = XEXP (DECL_RTL (decl), 0); if (TREE_TYPE (type)) - dbxout_type (TREE_TYPE (type), 0, 0); + dbxout_type (TREE_TYPE (type), 0); else - dbxout_type (void_type_node, 0, 0); + dbxout_type (void_type_node, 0); /* For a nested function, when that function is compiled, mention the containing function name @@ -1756,15 +1906,15 @@ dbxout_symbol (decl, local) don't duplicate it. */ if (typevec[TYPE_SYMTAB_ADDRESS (type)].status == TYPE_DEFINED && TYPE_NAME (TREE_TYPE (decl)) == decl) - return; + return 0; #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) || TYPE_DECL_SUPPRESS_DEBUG (decl)) - return; + return 0; FORCE_TEXT; - + result = 1; { int tag_needed = 1; int did_output = 0; @@ -1786,7 +1936,11 @@ 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. */ - && DECL_ARTIFICIAL (decl)) + && DECL_ARTIFICIAL (decl) + /* Do not generate a tag for records of variable size, + since this type can not be properly described in the + DBX format, and it confuses some tools such as objdump. */ + && host_integerp (TYPE_SIZE (type), 1)) { tree name = TYPE_NAME (type); if (TREE_CODE (name) == TYPE_DECL) @@ -1797,14 +1951,14 @@ dbxout_symbol (decl, local) current_sym_addr = 0; current_sym_nchars = 2 + IDENTIFIER_LENGTH (name); - fprintf (asmfile, "%s \"%s:T", ASM_STABS_OP, + fprintf (asmfile, "%s\"%s:T", ASM_STABS_OP, IDENTIFIER_POINTER (name)); - dbxout_type (type, 1, 0); + dbxout_type (type, 1); dbxout_finish_symbol (NULL_TREE); } /* Output typedef name. */ - fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, + fprintf (asmfile, "%s\"%s:", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (decl))); /* Short cut way to output a tag also. */ @@ -1830,18 +1984,18 @@ dbxout_symbol (decl, local) putc ('t', asmfile); current_sym_code = DBX_TYPE_DECL_STABS_CODE; - dbxout_type (type, 1, 0); + dbxout_type (type, 1); dbxout_finish_symbol (decl); did_output = 1; } - /* 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. */ + /* Don't output a tag if this is an incomplete type. This prevents + the sun4 Sun OS 4.x dbx from crashing. */ if (tag_needed && TYPE_NAME (type) != 0 && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE || (DECL_NAME (TYPE_NAME (type)) != 0)) - && TYPE_SIZE (type) != 0 + && COMPLETE_TYPE_P (type) && !TREE_ASM_WRITTEN (TYPE_NAME (type))) { /* For a TYPE_DECL with no name, but the type has a name, @@ -1858,9 +2012,9 @@ dbxout_symbol (decl, local) current_sym_addr = 0; current_sym_nchars = 2 + IDENTIFIER_LENGTH (name); - fprintf (asmfile, "%s \"%s:T", ASM_STABS_OP, + fprintf (asmfile, "%s\"%s:T", ASM_STABS_OP, IDENTIFIER_POINTER (name)); - dbxout_type (type, 1, 0); + dbxout_type (type, 1); dbxout_finish_symbol (NULL_TREE); did_output = 1; } @@ -1877,8 +2031,8 @@ dbxout_symbol (decl, local) /* Some debuggers fail when given NULL names, so give this a harmless name of ` '. */ - fprintf (asmfile, "%s \" :T", ASM_STABS_OP); - dbxout_type (type, 1, 0); + fprintf (asmfile, "%s\" :T", ASM_STABS_OP); + dbxout_type (type, 1); dbxout_finish_symbol (NULL_TREE); } @@ -1895,8 +2049,8 @@ dbxout_symbol (decl, local) case RESULT_DECL: /* Named return value, treat like a VAR_DECL. */ case VAR_DECL: - if (DECL_RTL (decl) == 0) - return; + if (! DECL_RTL_SET_P (decl)) + return 0; /* Don't mention a variable that is external. Let the file that defines it describe it. */ if (DECL_EXTERNAL (decl)) @@ -1906,27 +2060,29 @@ dbxout_symbol (decl, local) and not written in memory, inform the debugger. */ if (TREE_STATIC (decl) && TREE_READONLY (decl) && DECL_INITIAL (decl) != 0 + && host_integerp (DECL_INITIAL (decl), 0) && ! TREE_ASM_WRITTEN (decl) - && (DECL_FIELD_CONTEXT (decl) == NULL_TREE - || TREE_CODE (DECL_FIELD_CONTEXT (decl)) == BLOCK)) + && (DECL_CONTEXT (decl) == NULL_TREE + || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK)) { if (TREE_PUBLIC (decl) == 0) { /* The sun4 assembler does not grok this. */ - char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); + const char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); + if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE) { - HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl)); + HOST_WIDE_INT ival = tree_low_cst (DECL_INITIAL (decl), 0); #ifdef DBX_OUTPUT_CONSTANT_SYMBOL DBX_OUTPUT_CONSTANT_SYMBOL (asmfile, name, ival); #else - fprintf (asmfile, "%s \"%s:c=i", ASM_STABS_OP, name); + fprintf (asmfile, "%s\"%s:c=i", ASM_STABS_OP, name); fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC, ival); fprintf (asmfile, "\",0x%x,0,0,0\n", N_LSYM); #endif - return; + return 1; } else if (TREE_CODE (TREE_TYPE (decl)) == REAL_TYPE) { @@ -1937,29 +2093,31 @@ 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); + SET_DECL_RTL (decl, eliminate_regs (DECL_RTL (decl), 0, NULL_RTX)); #ifdef LEAF_REG_REMAP if (current_function_uses_only_leaf_regs) leaf_renumber_regs_insn (DECL_RTL (decl)); #endif - dbxout_symbol_location (decl, type, 0, DECL_RTL (decl)); + result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl)); break; default: break; } + return result; } /* Output the stab for DECL, a VAR_DECL, RESULT_DECL or PARM_DECL. Add SUFFIX to its name, if SUFFIX is not 0. Describe the variable as residing in HOME - (usually HOME is DECL_RTL (DECL), but not always). */ + (usually HOME is DECL_RTL (DECL), but not always). + Returns 1 if the stab was really emitted. */ -static void +static int dbxout_symbol_location (decl, type, suffix, home) tree decl, type; - char *suffix; + const char *suffix; rtx home; { int letter = 0; @@ -1971,29 +2129,24 @@ dbxout_symbol_location (decl, type, suffix, home) If the decl was from an inline function, then its rtl is not identically the rtl that was used in this particular compilation. */ - if (GET_CODE (home) == REG) - { - regno = REGNO (home); - if (regno >= FIRST_PSEUDO_REGISTER) - return; - } - else if (GET_CODE (home) == SUBREG) + if (GET_CODE (home) == SUBREG) { rtx value = home; - int offset = 0; + while (GET_CODE (value) == SUBREG) - { - offset += SUBREG_WORD (value); - value = SUBREG_REG (value); - } + value = SUBREG_REG (value); if (GET_CODE (value) == REG) { - regno = REGNO (value); - if (regno >= FIRST_PSEUDO_REGISTER) - return; - regno += offset; + if (REGNO (value) >= FIRST_PSEUDO_REGISTER) + return 0; } - alter_subreg (home); + home = alter_subreg (&home); + } + if (GET_CODE (home) == REG) + { + regno = REGNO (home); + if (regno >= FIRST_PSEUDO_REGISTER) + return 0; } /* The kind-of-variable letter depends on where @@ -2028,7 +2181,7 @@ dbxout_symbol_location (decl, type, suffix, home) 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") + || (!strcmp (lang_hooks.name, "GNU C++") && DECL_INITIAL (decl) == error_mark_node)) current_sym_code = N_LCSYM; else if (DECL_IN_TEXT_SECTION (decl)) @@ -2037,6 +2190,20 @@ dbxout_symbol_location (decl, type, suffix, home) current_sym_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 (current_sym_addr) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (current_sym_addr)) + { + rtx tmp = get_pool_constant (current_sym_addr); + + if (GET_CODE (tmp) == SYMBOL_REF) + current_sym_addr = tmp; + } + /* Ultrix `as' seems to need this. */ #ifdef DBX_STATIC_STAB_DATA_SECTION data_section (); @@ -2072,6 +2239,8 @@ dbxout_symbol_location (decl, type, suffix, home) { letter = 'r'; current_sym_code = N_RSYM; + if (REGNO (XEXP (home, 0)) >= FIRST_PSEUDO_REGISTER) + return 0; current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (home, 0))); } else @@ -2125,7 +2294,15 @@ dbxout_symbol_location (decl, type, suffix, home) } else if (GET_CODE (home) == CONCAT) { - tree subtype = TREE_TYPE (type); + tree subtype; + + /* If TYPE is not a COMPLEX_TYPE (it might be a RECORD_TYPE, + for example), then there is no easy way to figure out + what SUBTYPE should be. So, we give up. */ + if (TREE_CODE (type) != COMPLEX_TYPE) + return 0; + + subtype = TREE_TYPE (type); /* If the variable's storage is in two parts, output each as a separate stab with a modified name. */ @@ -2144,13 +2321,13 @@ dbxout_symbol_location (decl, type, suffix, home) dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 1)); else dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 1)); - return; + return 1; } else /* Address might be a MEM, when DECL is a variable-sized object. Or it might be const0_rtx, meaning previous passes want us to ignore this variable. */ - return; + return 0; /* Ok, start a symtab entry and output the variable name. */ FORCE_TEXT; @@ -2160,12 +2337,13 @@ dbxout_symbol_location (decl, type, suffix, home) #endif dbxout_symbol_name (decl, suffix, letter); - dbxout_type (type, 0, 0); + dbxout_type (type, 0); dbxout_finish_symbol (decl); #ifdef DBX_STATIC_BLOCK_END DBX_STATIC_BLOCK_END (asmfile, current_sym_code); #endif + return 1; } /* Output the symbol name of DECL for a stabs, with suffix SUFFIX. @@ -2174,20 +2352,29 @@ dbxout_symbol_location (decl, type, suffix, home) static void dbxout_symbol_name (decl, suffix, letter) tree decl; - char *suffix; + const char *suffix; int 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. Note also that static member (variable) names DO NOT begin - with underscores in .stabs directives. */ - char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + const char *name; + + if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) + /* 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. Note also that static member (variable) names DO NOT begin + with underscores in .stabs directives. */ + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + else + /* ...but if we're function-local, we don't want to include the junk + added by ASM_FORMAT_PRIVATE_NAME. */ + name = IDENTIFIER_POINTER (DECL_NAME (decl)); + if (name == 0) name = "(anon)"; - fprintf (asmfile, "%s \"%s%s:", ASM_STABS_OP, name, + fprintf (asmfile, "%s\"%s%s:", ASM_STABS_OP, name, (suffix ? suffix : "")); - if (letter) putc (letter, asmfile); + if (letter) + putc (letter, asmfile); } static void @@ -2195,7 +2382,7 @@ dbxout_prepare_symbol (decl) tree decl ATTRIBUTE_UNUSED; { #ifdef WINNING_GDB - char *filename = DECL_SOURCE_FILE (decl); + const char *filename = DECL_SOURCE_FILE (decl); dbxout_source_file (asmfile, filename); #endif @@ -2221,17 +2408,20 @@ dbxout_finish_symbol (sym) #endif } -/* Output definitions of all the decls in a chain. */ +/* Output definitions of all the decls in a chain. Return non-zero if + anything was output */ -void +int dbxout_syms (syms) tree syms; { + int result = 0; while (syms) { - dbxout_symbol (syms, 1); + result += dbxout_symbol (syms, 1); syms = TREE_CHAIN (syms); } + return result; } /* The following two functions output definitions of function parameters. @@ -2259,7 +2449,7 @@ dbxout_parms (parms) 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); + SET_DECL_RTL (parms, eliminate_regs (DECL_RTL (parms), 0, NULL_RTX)); #ifdef LEAF_REG_REMAP if (current_function_uses_only_leaf_regs) { @@ -2290,20 +2480,20 @@ dbxout_parms (parms) { current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); - fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, + fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms)), DBX_MEMPARM_STABS_LETTER); } else { current_sym_nchars = 8; - fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP, + fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP, DBX_MEMPARM_STABS_LETTER); } /* It is quite tempting to use: - dbxout_type (TREE_TYPE (parms), 0, 0); + dbxout_type (TREE_TYPE (parms), 0); as the next statement, rather than using DECL_ARG_TYPE(), so that gcc reports the actual type of the parameter, rather @@ -2314,8 +2504,8 @@ dbxout_parms (parms) passing a float to an unprototyped function, gcc will store a double on the stack, but if we emit a stab saying the type is a float, then gdb will only read in a single value, and this will - produce an erropneous value. */ - dbxout_type (DECL_ARG_TYPE (parms), 0, 0); + produce an erroneous value. */ + dbxout_type (DECL_ARG_TYPE (parms), 0); current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr); dbxout_finish_symbol (parms); } @@ -2337,8 +2527,7 @@ dbxout_parms (parms) If we use DECL_RTL, then we must use the declared type of the variable, not the type that it arrived in. */ - if (REGNO (DECL_RTL (parms)) >= 0 - && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) + if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) { best_rtl = DECL_RTL (parms); parm_type = TREE_TYPE (parms); @@ -2356,18 +2545,18 @@ dbxout_parms (parms) if (DECL_NAME (parms)) { current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms)); - fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, + fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms)), regparm_letter); } else { current_sym_nchars = 8; - fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP, + fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP, regparm_letter); } - dbxout_type (parm_type, 0, 0); + dbxout_type (parm_type, 0); dbxout_finish_symbol (parms); } else if (GET_CODE (DECL_RTL (parms)) == MEM @@ -2397,8 +2586,7 @@ dbxout_parms (parms) /* DECL_RTL looks like (MEM (REG...). Get the register number. If it is an unallocated pseudo-reg, then use the register where it was passed instead. */ - if (REGNO (XEXP (DECL_RTL (parms), 0)) >= 0 - && REGNO (XEXP (DECL_RTL (parms), 0)) < FIRST_PSEUDO_REGISTER) + if (REGNO (XEXP (DECL_RTL (parms), 0)) < FIRST_PSEUDO_REGISTER) current_sym_value = REGNO (XEXP (DECL_RTL (parms), 0)); else current_sym_value = REGNO (DECL_INCOMING_RTL (parms)); @@ -2408,20 +2596,43 @@ dbxout_parms (parms) FORCE_TEXT; if (DECL_NAME (parms)) { - current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms))); + current_sym_nchars + = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms))); - fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, + fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms)), regparm_letter); } else { current_sym_nchars = 8; - fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP, + fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP, regparm_letter); } - dbxout_type (TREE_TYPE (parms), 0, 0); + dbxout_type (TREE_TYPE (parms), 0); + dbxout_finish_symbol (parms); + } + else if (GET_CODE (DECL_RTL (parms)) == MEM + && GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM) + { + /* Parm was passed via invisible reference, with the reference + living on the stack. DECL_RTL looks like + (MEM (MEM (PLUS (REG ...) (CONST_INT ...)))) or it + could look like (MEM (MEM (REG))). */ + const char *const decl_name = (DECL_NAME (parms) + ? IDENTIFIER_POINTER (DECL_NAME (parms)) + : "(anon)"); + if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG) + current_sym_value = 0; + else + current_sym_value + = INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1)); + current_sym_addr = 0; + + FORCE_TEXT; + fprintf (asmfile, "%s\"%s:v", ASM_STABS_OP, decl_name); + dbxout_type (TREE_TYPE (parms), 0); dbxout_finish_symbol (parms); } else if (GET_CODE (DECL_RTL (parms)) == MEM @@ -2436,13 +2647,14 @@ dbxout_parms (parms) current_sym_code = N_PSYM; /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))), in which case we want the value of that CONST_INT, - or (MEM (REG ...)) or (MEM (MEM ...)), + or (MEM (REG ...)), in which case we use a value of zero. */ - if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG - || GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM) + if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG) current_sym_value = 0; else - current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)); + current_sym_value + = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)); + current_sym_addr = 0; /* Make a big endian correction if the mode of the type of the @@ -2451,29 +2663,32 @@ dbxout_parms (parms) && TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms)) && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD) { - current_sym_value += UNITS_PER_WORD - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))); + current_sym_value += + GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))) + - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))); } FORCE_TEXT; if (DECL_NAME (parms)) { - current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms))); + current_sym_nchars + = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms))); - fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, + fprintf (asmfile, "%s\"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (parms)), DBX_MEMPARM_STABS_LETTER); } else { current_sym_nchars = 8; - fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP, + fprintf (asmfile, "%s\"(anon):%c", ASM_STABS_OP, DBX_MEMPARM_STABS_LETTER); } current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, XEXP (DECL_RTL (parms), 0)); - dbxout_type (TREE_TYPE (parms), 0, 0); + dbxout_type (TREE_TYPE (parms), 0); dbxout_finish_symbol (parms); } } @@ -2502,7 +2717,6 @@ dbxout_reg_parms (parms) /* Report parms that live in registers during the function but were passed in memory. */ if (GET_CODE (DECL_RTL (parms)) == REG - && REGNO (DECL_RTL (parms)) >= 0 && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) dbxout_symbol_location (parms, TREE_TYPE (parms), 0, DECL_RTL (parms)); @@ -2520,37 +2734,19 @@ dbxout_reg_parms (parms) /* Given a chain of ..._TYPE nodes (as come in a parameter list), output definitions of those names, in raw form */ -void +static void dbxout_args (args) tree args; { while (args) { putc (',', asmfile); - dbxout_type (TREE_VALUE (args), 0, 0); + dbxout_type (TREE_VALUE (args), 0); CHARS (1); args = TREE_CHAIN (args); } } -/* Given a chain of ..._TYPE nodes, - find those which have typedef names and output those names. - This is to ensure those types get output. */ - -void -dbxout_types (types) - register tree types; -{ - while (types) - { - if (TYPE_NAME (types) - && TREE_CODE (TYPE_NAME (types)) == TYPE_DECL - && ! TREE_ASM_WRITTEN (TYPE_NAME (types))) - dbxout_symbol (TYPE_NAME (types), 1); - types = TREE_CHAIN (types); - } -} - /* Output everything about a symbol block (a BLOCK node that represents a scope level), including recursive output of contained blocks. @@ -2570,21 +2766,35 @@ dbxout_types (types) static void dbxout_block (block, depth, args) - register tree block; + tree block; int depth; tree args; { - int blocknum; + int blocknum = -1; + +#if DBX_BLOCKS_FUNCTION_RELATIVE + const char *begin_label; + if (current_function_func_begin_label != NULL_TREE) + begin_label = IDENTIFIER_POINTER (current_function_func_begin_label); + else + begin_label = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); +#endif while (block) { /* Ignore blocks never expanded or otherwise marked as real. */ - if (TREE_USED (block)) + if (TREE_USED (block) && TREE_ASM_WRITTEN (block)) { -#ifndef DBX_LBRAC_FIRST - /* In dbx format, the syms of a block come before the N_LBRAC. */ + int did_output; + +#ifdef DBX_LBRAC_FIRST + did_output = 1; +#else + /* In dbx format, the syms of a block come before the N_LBRAC. + If nothing is output, we don't need the N_LBRAC, either. */ + did_output = 0; if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0) - dbxout_syms (BLOCK_VARS (block)); + did_output = dbxout_syms (BLOCK_VARS (block)); if (args) dbxout_reg_parms (args); #endif @@ -2593,10 +2803,10 @@ dbxout_block (block, depth, args) the block. Use the block's tree-walk order to generate the assembler symbols LBBn and LBEn that final will define around the code in this block. */ - if (depth > 0 && debug_info_level != DINFO_LEVEL_TERSE) + if (depth > 0 && did_output) { char buf[20]; - blocknum = next_block_number++; + blocknum = BLOCK_NUMBER (block); ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", blocknum); if (BLOCK_HANDLER_BLOCK (block)) @@ -2608,7 +2818,7 @@ dbxout_block (block, depth, args) #ifdef DBX_OUTPUT_CATCH DBX_OUTPUT_CATCH (asmfile, decl, buf); #else - fprintf (asmfile, "%s \"%s:C1\",%d,0,0,", ASM_STABS_OP, + fprintf (asmfile, "%s\"%s:C1\",%d,0,0,", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (decl)), N_CATCH); assemble_name (asmfile, buf); fprintf (asmfile, "\n"); @@ -2620,18 +2830,15 @@ dbxout_block (block, depth, args) #ifdef DBX_OUTPUT_LBRAC DBX_OUTPUT_LBRAC (asmfile, buf); #else - fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_LBRAC); + fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_LBRAC); assemble_name (asmfile, buf); #if DBX_BLOCKS_FUNCTION_RELATIVE - fputc ('-', asmfile); - assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); + putc ('-', asmfile); + assemble_name (asmfile, begin_label); #endif fprintf (asmfile, "\n"); #endif } - else if (depth > 0) - /* Count blocks the same way regardless of debug_info_level. */ - next_block_number++; #ifdef DBX_LBRAC_FIRST /* On some weird machines, the syms of a block @@ -2646,18 +2853,18 @@ dbxout_block (block, depth, args) dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE); /* Refer to the marker for the end of the block. */ - if (depth > 0 && debug_info_level != DINFO_LEVEL_TERSE) + if (depth > 0 && did_output) { char buf[20]; ASM_GENERATE_INTERNAL_LABEL (buf, "LBE", blocknum); #ifdef DBX_OUTPUT_RBRAC DBX_OUTPUT_RBRAC (asmfile, buf); #else - fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_RBRAC); + fprintf (asmfile, "%s%d,0,0,", ASM_STABN_OP, N_RBRAC); assemble_name (asmfile, buf); #if DBX_BLOCKS_FUNCTION_RELATIVE - fputc ('-', asmfile); - assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); + putc ('-', asmfile); + assemble_name (asmfile, begin_label); #endif fprintf (asmfile, "\n"); #endif @@ -2671,8 +2878,9 @@ dbxout_block (block, depth, args) Usually this follows the function's code, but on some systems, it comes before. */ +#if defined (DBX_DEBUGGING_INFO) static void -dbxout_really_begin_function (decl) +dbxout_begin_function (decl) tree decl; { dbxout_symbol (decl, 0); @@ -2680,52 +2888,6 @@ dbxout_really_begin_function (decl) if (DECL_NAME (DECL_RESULT (decl)) != 0) dbxout_symbol (DECL_RESULT (decl), 1); } +#endif /* DBX_DEBUGGING_INFO */ -/* Called at beginning of output of function definition. */ - -void -dbxout_begin_function (decl) - tree decl ATTRIBUTE_UNUSED; -{ -#ifdef DBX_FUNCTION_FIRST - dbxout_really_begin_function (decl); -#else -#ifdef DBX_CHECK_FUNCTION_FIRST - if (DBX_CHECK_FUNCTION_FIRST) - dbxout_really_begin_function (decl); -#endif -#endif -} - -/* Output dbx data for a function definition. - This includes a definition of the function name itself (a symbol), - definitions of the parameters (locating them in the parameter list) - and then output the block that makes up the function's body - (including all the auto variables of the function). */ - -void -dbxout_function (decl) - tree decl; -{ -#ifndef DBX_FUNCTION_FIRST - dbxout_really_begin_function (decl); -#else -#ifdef DBX_CHECK_FUNCTION_FIRST - if (!(DBX_CHECK_FUNCTION_FIRST)) - dbxout_really_begin_function (decl); -#endif -#endif - dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (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 || XCOFF_DEBUGGING_INFO */ |