/* Output dbx-format symbol table information from GNU compiler.
- Copyright (C) 1987, 1988, 1992 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, 675 Mass Ave, Cambridge, MA 02139, 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. */
/* Output dbx-format symbol table data.
For more on data type definitions, see `dbxout_type'. */
-/* Include these first, because they may define MIN and MAX. */
-#include <stdio.h>
-#include <errno.h>
-
#include "config.h"
+#include "system.h"
+
#include "tree.h"
#include "rtl.h"
#include "flags.h"
#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. */
-
-#ifndef errno
-extern int errno;
-#endif
+#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
#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
-/* Nonzero means if the type has methods, only output debugging
- information if methods are actually written to the asm file. */
+#ifndef FILE_NAME_JOINER
+#define FILE_NAME_JOINER "/"
+#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
-static int flag_minimal_debug = 1;
+/* 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)
/* Nonzero if we have actually used any of the GDB extensions
to the debugging format. The idea is that we use them for the
static int have_used_extensions = 0;
-char *getpwd ();
-
-/* Typical USG systems don't have stab.h, and they also have
- no use for DBX-format debugging info. */
+/* 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 (XCOFF_DEBUGGING_INFO)
+#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 ();
#define FORCE_TEXT
#endif
-#if defined (USG) || defined (NO_STAB_H)
-#include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */
-#else
-#include <stab.h> /* On BSD, use the system's stab.h. */
-
-/* This is a GNU extension we need to reference in this file. */
-#ifndef N_CATCH
-#define N_CATCH 0x54
-#endif
-#endif /* not USG */
+#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. */
/* 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};
-/* 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'. */
static int next_type_number;
-/* 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. */
+#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;
-static int next_block_number;
+#endif /* DBX_USE_BINCL */
/* These variables are for dbxout_symbol to communicate to
dbxout_finish_symbol.
#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 ();
-static void dbxout_type_name ();
-static void dbxout_type ();
-static void dbxout_typedefs ();
-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_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 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));
\f
-#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;
+/* 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 =
{
- /* 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;
-}
-#endif /* 0 */
+ 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 */
\f
+#if defined (DBX_DEBUGGING_INFO)
+static void
+dbxout_function_end ()
+{
+ static int scope_labelno = 0;
+ 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);
+ putc ('-', asmfile);
+ assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+ fprintf (asmfile, "\n");
+}
+#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 = (enum typestatus *) xmalloc (typevec_len * sizeof typevec[0]);
- bzero (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
if (use_gnu_debug_info_extensions)
#endif
{
- if (cwd || (cwd = getpwd ()))
+ if (!cwd && (cwd = getpwd ()) && (!*cwd || cwd[strlen (cwd) - 1] != '/'))
+ 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 \"%s/\",%d,0,0,%s\n", ASM_STABS_OP,
- cwd, N_SO, <ext_label_name[1]);
+ fprintf (asmfile, "%s", ASM_STABS_OP);
+ output_quoted_string (asmfile, cwd);
+ fprintf (asmfile, ",%d,0,0,", N_SO);
+ assemble_name (asmfile, ltext_label_name);
+ fputc ('\n', asmfile);
#endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
}
}
/* 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 \"%s\",%d,0,0,%s\n", ASM_STABS_OP, input_file_name,
- N_SO, <ext_label_name[1]);
+ fprintf (asmfile, "%s", ASM_STABS_OP);
+ output_quoted_string (asmfile, input_file_name);
+ 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);
+ 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.
tree type = TREE_TYPE (syms);
if (TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && COMPLETE_TYPE_P (type)
&& ! 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. */
+
+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);
+
+ n->next = current_file;
+ n->file_number = next_file_number++;
+ n->next_type_number = 1;
+ current_file = n;
+ fprintf (asmfile, "%s", ASM_STABS_OP);
+ output_quoted_string (asmfile, filename);
+ fprintf (asmfile, ",%d,0,0,0\n", N_BINCL);
+#endif
+}
+
+/* Revert to reading a previous source file. Generate a N_EINCL stab. */
+
+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);
+ 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
- ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
- fprintf (file, "%s \"%s\",%d,0,0,%s\n", ASM_STABS_OP,
- filename, N_SOL, <ext_label_name[1]);
+ char ltext_label_name[100];
+
+ ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext",
+ source_label_number);
+ fprintf (file, "%s", ASM_STABS_OP);
+ output_quoted_string (file, filename);
+ 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. */
+ else
+ text_section ();
+ ASM_OUTPUT_INTERNAL_LABEL (file, "Ltext", source_label_number);
+ source_label_number++;
#endif
lastfile = 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. */
+ to do nothing. */
-void
-dbxout_finish (file, filename)
- FILE *file;
- char *filename;
+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 */
}
+/* 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 (9);
+#endif
+}
+
+#if DBX_CONTIN_LENGTH > 0
/* 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
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 */
\f
/* Subroutine of `dbxout_type'. Output the type fields of TYPE.
This must be a separate function because anonymous unions require
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))
{
- /* For nameless subunions and subrecords, treat their fields as ours. */
- if (DECL_NAME (tem) == NULL_TREE
- && (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
- || TREE_CODE (TREE_TYPE (tem)) == QUAL_UNION_TYPE
- || TREE_CODE (TREE_TYPE (tem)) == RECORD_TYPE))
- dbxout_type_fields (TREE_TYPE (tem));
/* Omit here local type decls until we know how to support them. */
- else if (TREE_CODE (tem) == TYPE_DECL)
+ 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;
- /* Omit here the nameless fields that are used to skip bits. */
- else if (DECL_NAME (tem) != 0 && TREE_CODE (tem) != CONST_DECL)
+
+ 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))
+ if (DECL_NAME (tem))
+ {
+ fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem)));
+ CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (tem)));
+ }
+ else
{
- have_used_extensions = 1;
- CHARS (3 + IDENTIFIER_LENGTH (DECL_NAME (TYPE_NAME (DECL_FCONTEXT (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);
- fprintf (asmfile, ",%d;",
- TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)));
- continue;
+ CHARS (1);
}
- fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem)));
- CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (tem)));
-
if (use_gnu_debug_info_extensions
&& (TREE_PRIVATE (tem) || TREE_PROTECTED (tem)
|| TREE_CODE (tem) != FIELD_DECL))
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
{
- fprintf (asmfile, ",%d,%d;",
- TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)),
- TREE_INT_CST_LOW (DECL_SIZE (tem)));
+ 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);
}
- else
- /* This has yet to be implemented. */
- abort ();
- CHARS (23);
}
}
}
static void
dbxout_type_method_1 (decl, debug_name)
tree decl;
- char *debug_name;
+ const 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.
}
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, "%d;",
- TREE_INT_CST_LOW (DECL_VINDEX (decl)));
- 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);
}
}
\f
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;
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. */
{
- 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)
{
static int warned;
if (!warned)
- {
warned = 1;
-#ifdef HAVE_TEMPLATES
- if (warn_template_debugging)
- warning ("dbx info for template class methods not yet supported");
-#endif
- }
return;
}
}
+#endif
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) == FUNCTION_DECL)
+ if (TREE_CODE (methods) != TREE_VEC)
fndecl = methods;
else if (TREE_VEC_ELT (methods, 0) != NULL_TREE)
fndecl = TREE_VEC_ELT (methods, 0);
while (fndecl)
{
- tree name = DECL_NAME (fndecl);
int need_prefix = 1;
/* Group together all the methods for the same operation.
{
/* 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;
+ 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)
{
- /* Detect ordinary methods because their mangled names
- start with the operation name. */
- 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
- destructor = 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, destructor);
+ dbxout_type (TREE_TYPE (fndecl), 0);
dbxout_type_method_1 (fndecl, debug_name);
}
/* Emit a "range" type specification, which has the form:
"r<index type>;<lower bound>;<upper bound>;".
- TYPE is an INTEGER_TYPE. */
+ TYPE is an INTEGER_TYPE. */
static void
dbxout_range_type (type)
tree type;
{
fprintf (asmfile, "r");
- if (TREE_TYPE (type) && TREE_CODE (TREE_TYPE(type)) != INTEGER_TYPE)
- dbxout_type (TREE_TYPE (type), 0, 0);
+ if (TREE_TYPE (type))
+ dbxout_type (TREE_TYPE (type), 0);
+ else if (TREE_CODE (type) != INTEGER_TYPE)
+ dbxout_type (type, 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. This matters for Chill. If this isn't
+ a subrange type, then we want to define it in terms of itself.
+ However, in C, this may be an anonymous integer type, and we don't
+ want to emit debug info referring to it. Just calling
+ dbxout_type_index won't work anyways, because the type hasn't been
+ defined yet. We make this work for both cases by checked to see
+ whether this is a defined type, referring to it if it is, and using
+ 'int' otherwise. */
+ if (TYPE_SYMTAB_ADDRESS (type) != 0)
+ dbxout_type_index (type);
+ else
+ dbxout_type_index (integer_type_node);
+ }
+
+ if (TYPE_MIN_VALUE (type) != 0
+ && host_integerp (TYPE_MIN_VALUE (type), 0))
+ {
+ putc (';', asmfile);
+ CHARS (1);
+ print_wide_int (tree_low_cst (TYPE_MIN_VALUE (type), 0));
}
- if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
- fprintf (asmfile, ";%d",
- TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)));
else
- fprintf (asmfile, ";0");
- if (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST)
- fprintf (asmfile, ";%d;",
- TREE_INT_CST_LOW (TYPE_MAX_VALUE (type)));
+ {
+ 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);
+ }
}
\f
/* Output a reference to a type. If the type has not yet been
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'. */
type = integer_type_node;
else
{
- type = TYPE_MAIN_VARIANT (type);
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;
}
+ /* 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. */
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]);
+ memset ((char *) (typevec + typevec_len), 0,
+ 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))
/* 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;
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:
#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)
+ || !COMPLETE_TYPE_P (type)
+ /* No way in DBX fmt to describe a variable size. */
+ || ! host_integerp (TYPE_SIZE (type), 1))
{
- typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
+ typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
return;
}
#endif
/* 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 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))
{
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));
- else if (use_gnu_debug_info_extensions && TYPE_PRECISION (type) > BITS_PER_WORD)
{
- /* 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));
- print_int_cst_octal (TYPE_MIN_VALUE (type));
- fprintf (asmfile, ";");
- print_int_cst_octal (TYPE_MAX_VALUE (type));
- fprintf (asmfile, ";");
+ /* 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");
+ CHARS (1);
+ dbxout_type_index (type);
+ fprintf (asmfile, ";0;127;");
+ CHARS (7);
}
- 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 (25);
+
+ 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%d;%d;0;", TYPE_SYMTAB_ADDRESS (integer_type_node),
- int_size_in_bytes (type));
- CHARS (16);
+ fprintf (asmfile, "r");
+ CHARS (1);
+ dbxout_type_index (integer_type_node);
+ putc (';', asmfile);
+ CHARS (1);
+ print_wide_int (int_size_in_bytes (type));
+ fputs (";0;", asmfile);
+ CHARS (3);
break;
case CHAR_TYPE:
- /* 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);
- CHARS (9);
+ if (use_gnu_debug_info_extensions)
+ {
+ have_used_extensions = 1;
+ fputs ("@s", asmfile);
+ 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);
+ }
break;
- case BOOLEAN_TYPE: /* Define as enumeral type (False, True) */
- fprintf (asmfile, "eFalse:0,True:1,;");
- CHARS (17);
+ case BOOLEAN_TYPE:
+ if (use_gnu_debug_info_extensions)
+ {
+ have_used_extensions = 1;
+ fputs ("@s", asmfile);
+ 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);
+ }
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:
if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
{
- fprintf (asmfile, "r%d;%d;0;",
- TYPE_SYMTAB_ADDRESS (type),
- int_size_in_bytes (TREE_TYPE (type)));
- CHARS (15); /* The number is probably incorrect here. */
+ fprintf (asmfile, "r");
+ CHARS (1);
+ dbxout_type_index (type);
+ putc (';', asmfile);
+ CHARS (1);
+ print_wide_int (2 * int_size_in_bytes (TREE_TYPE (type)));
+ fputs (";0;", asmfile);
+ CHARS (3);
}
else
{
/* Output a complex integer type as a structure,
pending some other way to do it. */
- fprintf (asmfile, "s%d", 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;
case SET_TYPE:
+ if (use_gnu_debug_info_extensions)
+ {
+ have_used_extensions = 1;
+ fputs ("@s", 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;");
+ CHARS (3);
+ }
+ }
putc ('S', asmfile);
CHARS (1);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TYPE_DOMAIN (type), 0);
break;
case ARRAY_TYPE:
+ /* Make arrays of packed bits look like bitstrings for chill. */
+ if (TYPE_PACKED (type) && use_gnu_debug_info_extensions)
+ {
+ have_used_extensions = 1;
+ fputs ("@s", asmfile);
+ 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.
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. */
+ if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions)
+ {
+ have_used_extensions = 1;
+ fprintf (asmfile, "@S;");
+ CHARS (3);
+ }
tem = TYPE_DOMAIN (type);
if (tem == NULL)
- fprintf(asmfile, "ar%d;0;-1",
- TYPE_SYMTAB_ADDRESS (integer_type_node));
+ {
+ fprintf (asmfile, "ar");
+ CHARS (2);
+ dbxout_type_index (integer_type_node);
+ fprintf (asmfile, ";0;-1;");
+ CHARS (6);
+ }
else
{
- fprintf(asmfile, "a");
+ fprintf (asmfile, "a");
+ CHARS (1);
dbxout_range_type (tem);
}
- CHARS (17);
- dbxout_type (TREE_TYPE (type), 0, 0);
+
+ dbxout_type (TREE_TYPE (type), 0);
break;
case RECORD_TYPE:
{
int i, n_baseclasses = 0;
- if (TYPE_BINFO (type) != 0 && TYPE_BINFO_BASETYPES (type) != 0)
+ if (TYPE_BINFO (type) != 0
+ && TREE_CODE (TYPE_BINFO (type)) == TREE_VEC
+ && 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
-#if 0 /* Tiemann says this creates output tha "confuses GDB".
- Too bad the info is so vague. Hope this doesn't lose. */
&& ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& DECL_IGNORED_P (TYPE_NAME (type)))
-#endif
&& !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.
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.
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, ":");
- typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
+ CHARS (1);
+ typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
break;
}
/* Identify record or union, and print its size. */
- fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "s%d" : "u%d",
- 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)
{
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, "%d,",
- TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT);
- 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
{
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);
- fprintf (asmfile, ",%d,%d;",
- TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT,
- TREE_INT_CST_LOW (DECL_SIZE (TYPE_NAME (BINFO_TYPE (child)))) * BITS_PER_UNIT);
- 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)
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. */
/* 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
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;
case ENUMERAL_TYPE:
- if ((TYPE_NAME (type) != 0 && !full
- && (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && ! DECL_IGNORED_P (TYPE_NAME (type))))
- || TYPE_SIZE (type) == 0)
+ /* 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)
+ || !COMPLETE_TYPE_P (type))
{
fprintf (asmfile, "xe");
- CHARS (3);
+ CHARS (2);
dbxout_type_name (type);
- typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
- fprintf (asmfile, ":");
+ typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
+ putc (':', asmfile);
+ CHARS (1);
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));
+ CHARS (5);
+ }
+
putc ('e', asmfile);
CHARS (1);
for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
{
- fprintf (asmfile, "%s:%d,", IDENTIFIER_POINTER (TREE_PURPOSE (tem)),
- TREE_INT_CST_LOW (TREE_VALUE (tem)));
- CHARS (11 + IDENTIFIER_LENGTH (TREE_PURPOSE (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)
+ print_wide_int (TREE_INT_CST_LOW (TREE_VALUE (tem)));
+ else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1
+ && (HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0)
+ print_wide_int (TREE_INT_CST_LOW (TREE_VALUE (tem)));
+ else
+ print_int_cst_octal (TREE_VALUE (tem));
+
+ putc (',', asmfile);
+ CHARS (1);
if (TREE_CHAIN (tem) != 0)
CONTIN;
}
+
putc (';', asmfile);
CHARS (1);
#endif
case POINTER_TYPE:
putc ('*', asmfile);
CHARS (1);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
break;
case METHOD_TYPE:
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);
- 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:
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:
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:
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));
+ 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
+ present. */
+ if (width == HOST_BITS_PER_WIDE_INT * 2)
+ ;
+ else if (width > HOST_BITS_PER_WIDE_INT)
+ high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);
+ else if (width == HOST_BITS_PER_WIDE_INT)
+ high = 0;
+ else
+ high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
fprintf (asmfile, "0");
+ CHARS (1);
if (excess == 3)
{
= ((high & (((HOST_WIDE_INT) 1 << excess) - 1)) << (3 - excess)
| (low >> (HOST_BITS_PER_WIDE_INT / 3 * 3)));
unsigned HOST_WIDE_INT end
- = low & (((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 3 * 3)) - 1);
- fprintf (asmfile, "%o%01o", beg, middle);
+ = low & (((unsigned HOST_WIDE_INT) 1
+ << (HOST_BITS_PER_WIDE_INT / 3 * 3))
+ - 1);
+
+ fprintf (asmfile, "%o%01o", (int) beg, (int) middle);
+ CHARS (2);
print_octal (end, HOST_BITS_PER_WIDE_INT / 3);
}
}
int i;
for (i = digits - 1; i >= 0; i--)
- fprintf (asmfile, "%01o", ((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)
/* 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;
{
- int letter = 0;
tree type = TREE_TYPE (decl);
tree context = NULL_TREE;
- int regno = -1;
+ int result = 0;
/* Cast avoids warning in old compilers. */
current_sym_code = (STAB_CODE_TYPE) 0;
if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL)
|| DECL_IGNORED_P (decl))
- return;
+ return 0;
dbxout_prepare_symbol (decl);
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. */
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
/* 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;
+ 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) || DECL_IGNORED_P (decl))
- return;
+ if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl))
+ return 0;
FORCE_TEXT;
-
+ result = 1;
{
int tag_needed = 1;
int did_output = 0;
&& !TREE_ASM_WRITTEN (TYPE_NAME (type))
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
- && DECL_SOURCE_LINE (decl) == 0)
+ && 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)
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. */
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)
{
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 && TYPE_SIZE (type) != 0
+ if (tag_needed && TYPE_NAME (type) != 0
+ && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE
+ || (DECL_NAME (TYPE_NAME (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,
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;
}
/* 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);
}
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))
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%d\",0x%x,0,0,0\n",
- ASM_STABS_OP, name, ival, N_LSYM);
+ 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)
{
/* else it is something we handle like a normal variable. */
}
- DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, 0);
+ SET_DECL_RTL (decl, eliminate_regs (DECL_RTL (decl), 0, NULL_RTX));
#ifdef LEAF_REG_REMAP
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
- /* Don't mention a variable at all
- if it was completely optimized into nothingness.
+ result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
+ break;
+
+ default:
+ break;
+ }
+ return result;
+}
+\f
+/* 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).
+ Returns 1 if the stab was really emitted. */
+
+static int
+dbxout_symbol_location (decl, type, suffix, home)
+ tree decl, type;
+ const char *suffix;
+ rtx home;
+{
+ int letter = 0;
+ int regno = -1;
+
+ /* Don't mention a variable at all
+ if it was completely optimized into nothingness.
+
+ 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) == SUBREG)
+ {
+ rtx value = home;
- If DECL was from an inline function, then it's rtl
- is not identically the rtl that was used in this
- particular compilation. */
- if (GET_CODE (DECL_RTL (decl)) == REG)
+ while (GET_CODE (value) == SUBREG)
+ value = SUBREG_REG (value);
+ if (GET_CODE (value) == REG)
{
- regno = REGNO (DECL_RTL (decl));
- if (regno >= FIRST_PSEUDO_REGISTER)
- return;
+ if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
+ return 0;
}
- else if (GET_CODE (DECL_RTL (decl)) == SUBREG)
+ 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
+ the variable is and on the scope of its name:
+ G and N_GSYM for static storage and global scope,
+ S for static storage and file scope,
+ V for static storage and local scope,
+ for those two, use N_LCSYM if data is in bss segment,
+ N_STSYM if in data segment, N_FUN otherwise.
+ (We used N_FUN originally, then changed to N_STSYM
+ to please GDB. However, it seems that confused ld.
+ Now GDB has been fixed to like N_FUN, says Kingdon.)
+ no letter at all, and N_LSYM, for auto variable,
+ r and N_RSYM for register variable. */
+
+ if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
+ {
+ if (TREE_PUBLIC (decl))
{
- rtx value = DECL_RTL (decl);
- int offset = 0;
- while (GET_CODE (value) == SUBREG)
- {
- offset += SUBREG_WORD (value);
- value = SUBREG_REG (value);
- }
- if (GET_CODE (value) == REG)
- {
- regno = REGNO (value);
- if (regno >= FIRST_PSEUDO_REGISTER)
- return;
- regno += offset;
- }
- alter_subreg (DECL_RTL (decl));
+ letter = 'G';
+ current_sym_code = N_GSYM;
}
-
- /* The kind-of-variable letter depends on where
- the variable is and on the scope of its name:
- G and N_GSYM for static storage and global scope,
- S for static storage and file scope,
- V for static storage and local scope,
- for those two, use N_LCSYM if data is in bss segment,
- N_STSYM if in data segment, N_FUN otherwise.
- (We used N_FUN originally, then changed to N_STSYM
- to please GDB. However, it seems that confused ld.
- Now GDB has been fixed to like N_FUN, says Kingdon.)
- no letter at all, and N_LSYM, for auto variable,
- r and N_RSYM for register variable. */
-
- if (GET_CODE (DECL_RTL (decl)) == MEM
- && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
+ else
{
- if (TREE_PUBLIC (decl))
- {
- letter = 'G';
- current_sym_code = N_GSYM;
- }
+ current_sym_addr = XEXP (home, 0);
+
+ letter = decl_function_context (decl) ? 'V' : 'S';
+
+ /* 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_hooks.name, "GNU C++")
+ && 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
+ of all the codes that Unix defines. */
+ current_sym_code = DBX_STATIC_CONST_VAR_CODE;
else
{
- current_sym_addr = XEXP (DECL_RTL (decl), 0);
-
- letter = decl_function_context (decl) ? 'V' : 'S';
-
- if (!DECL_INITIAL (decl))
- current_sym_code = N_LCSYM;
- else if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl))
- /* This is not quite right, but it's the closest
- of all the codes that Unix defines. */
- 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))
{
-/* Ultrix `as' seems to need this. */
+ rtx tmp = get_pool_constant (current_sym_addr);
+
+ if (GET_CODE (tmp) == SYMBOL_REF
+ || GET_CODE (tmp) == LABEL_REF)
+ current_sym_addr = tmp;
+ }
+
+ /* Ultrix `as' seems to need this. */
#ifdef DBX_STATIC_STAB_DATA_SECTION
- data_section ();
+ data_section ();
#endif
- current_sym_code = N_STSYM;
- }
+ current_sym_code = N_STSYM;
}
}
- else if (regno >= 0)
+ }
+ else if (regno >= 0)
+ {
+ letter = 'r';
+ current_sym_code = N_RSYM;
+ current_sym_value = DBX_REGISTER_NUMBER (regno);
+ }
+ else if (GET_CODE (home) == MEM
+ && (GET_CODE (XEXP (home, 0)) == MEM
+ || (GET_CODE (XEXP (home, 0)) == REG
+ && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
+ && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM
+#endif
+ )))
+ /* If the value is indirect by memory or by a register
+ that isn't the frame pointer
+ then it means the object is variable-sized and address through
+ that register or stack slot. DBX has no way to represent this
+ so all we can do is output the variable as a pointer.
+ If it's not a parameter, ignore it.
+ (VAR_DECLs like this can be made by integrate.c.) */
+ {
+ if (GET_CODE (XEXP (home, 0)) == REG)
{
letter = 'r';
current_sym_code = N_RSYM;
- current_sym_value = DBX_REGISTER_NUMBER (regno);
- }
- else if (GET_CODE (DECL_RTL (decl)) == MEM
- && (GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
- || (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG
- && REGNO (XEXP (DECL_RTL (decl), 0)) != FRAME_POINTER_REGNUM)))
- /* If the value is indirect by memory or by a register
- that isn't the frame pointer
- then it means the object is variable-sized and address through
- that register or stack slot. DBX has no way to represent this
- so all we can do is output the variable as a pointer.
- If it's not a parameter, ignore it.
- (VAR_DECLs like this can be made by integrate.c.) */
- {
- if (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG)
- {
- letter = 'r';
- current_sym_code = N_RSYM;
- current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (DECL_RTL (decl), 0)));
- }
- else
- {
- current_sym_code = N_LSYM;
- /* DECL_RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))).
- We want the value of that CONST_INT. */
- current_sym_value
- = DEBUGGER_AUTO_OFFSET (XEXP (XEXP (DECL_RTL (decl), 0), 0));
- }
-
- /* Effectively do build_pointer_type, but don't cache this type,
- since it might be temporary whereas the type it points to
- might have been saved for inlining. */
- /* Don't use REFERENCE_TYPE because dbx can't handle that. */
- type = make_node (POINTER_TYPE);
- TREE_TYPE (type) = TREE_TYPE (decl);
+ if (REGNO (XEXP (home, 0)) >= FIRST_PSEUDO_REGISTER)
+ return 0;
+ current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (home, 0)));
}
- else if (GET_CODE (DECL_RTL (decl)) == MEM
- && GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG)
- {
- current_sym_code = N_LSYM;
- current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0));
- }
- else if (GET_CODE (DECL_RTL (decl)) == MEM
- && GET_CODE (XEXP (DECL_RTL (decl), 0)) == PLUS
- && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 1)) == CONST_INT)
+ else
{
current_sym_code = N_LSYM;
- /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
+ /* RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))).
We want the value of that CONST_INT. */
- current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0));
- }
- else if (GET_CODE (DECL_RTL (decl)) == MEM
- && GET_CODE (XEXP (DECL_RTL (decl), 0)) == CONST)
- {
- /* Handle an obscure case which can arise when optimizing and
- when there are few available registers. (This is *always*
- the case for i386/i486 targets). The DECL_RTL looks like
- (MEM (CONST ...)) even though this variable is a local `auto'
- or a local `register' variable. In effect, what has happened
- is that the reload pass has seen that all assignments and
- references for one such a local variable can be replaced by
- equivalent assignments and references to some static storage
- variable, thereby avoiding the need for a register. In such
- cases we're forced to lie to debuggers and tell them that
- this variable was itself `static'. */
- current_sym_code = N_LCSYM;
- letter = 'V';
- current_sym_addr = XEXP (XEXP (DECL_RTL (decl), 0), 0);
+ current_sym_value
+ = DEBUGGER_AUTO_OFFSET (XEXP (XEXP (home, 0), 0));
}
+
+ /* Effectively do build_pointer_type, but don't cache this type,
+ since it might be temporary whereas the type it points to
+ might have been saved for inlining. */
+ /* Don't use REFERENCE_TYPE because dbx can't handle that. */
+ type = make_node (POINTER_TYPE);
+ TREE_TYPE (type) = TREE_TYPE (decl);
+ }
+ else if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == REG)
+ {
+ current_sym_code = N_LSYM;
+ current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
+ }
+ else if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
+ {
+ current_sym_code = N_LSYM;
+ /* RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
+ We want the value of that CONST_INT. */
+ current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
+ }
+ else if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == CONST)
+ {
+ /* Handle an obscure case which can arise when optimizing and
+ when there are few available registers. (This is *always*
+ the case for i386/i486 targets). The RTL looks like
+ (MEM (CONST ...)) even though this variable is a local `auto'
+ or a local `register' variable. In effect, what has happened
+ is that the reload pass has seen that all assignments and
+ references for one such a local variable can be replaced by
+ equivalent assignments and references to some static storage
+ variable, thereby avoiding the need for a register. In such
+ cases we're forced to lie to debuggers and tell them that
+ this variable was itself `static'. */
+ current_sym_code = N_LCSYM;
+ letter = 'V';
+ current_sym_addr = XEXP (XEXP (home, 0), 0);
+ }
+ else if (GET_CODE (home) == CONCAT)
+ {
+ 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. */
+ if (WORDS_BIG_ENDIAN)
+ dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 0));
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. */
- break;
+ dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 0));
- /* Ok, start a symtab entry and output the variable name. */
- FORCE_TEXT;
+ /* Cast avoids warning in old compilers. */
+ current_sym_code = (STAB_CODE_TYPE) 0;
+ current_sym_value = 0;
+ current_sym_addr = 0;
+ dbxout_prepare_symbol (decl);
+
+ if (WORDS_BIG_ENDIAN)
+ dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 1));
+ else
+ dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 1));
+ 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 0;
+
+ /* Ok, start a symtab entry and output the variable name. */
+ FORCE_TEXT;
#ifdef DBX_STATIC_BLOCK_START
- DBX_STATIC_BLOCK_START (asmfile, current_sym_code);
+ DBX_STATIC_BLOCK_START (asmfile, current_sym_code);
#endif
- /* 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
- with underscores in .stabs directives. */
- if (DECL_LANG_SPECIFIC (decl))
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- else
- name = IDENTIFIER_POINTER (DECL_NAME (decl));
- fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, name);
- }
- if (letter) putc (letter, asmfile);
- dbxout_type (type, 0, 0);
- dbxout_finish_symbol (decl);
+ dbxout_symbol_name (decl, suffix, letter);
+ dbxout_type (type, 0);
+ dbxout_finish_symbol (decl);
#ifdef DBX_STATIC_BLOCK_END
- DBX_STATIC_BLOCK_END (asmfile, current_sym_code);
+ DBX_STATIC_BLOCK_END (asmfile, current_sym_code);
#endif
- break;
- }
+ return 1;
}
+\f
+/* Output the symbol name of DECL for a stabs, with suffix SUFFIX.
+ Then output LETTER to indicate the kind of location the symbol has. */
static void
-dbxout_prepare_symbol (decl)
+dbxout_symbol_name (decl, suffix, letter)
tree decl;
+ const char *suffix;
+ int letter;
+{
+ 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,
+ (suffix ? suffix : ""));
+
+ if (letter)
+ putc (letter, asmfile);
+}
+
+static void
+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
#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;
}
\f
/* The following two functions output definitions of function parameters.
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 (leaf_function)
+ if (current_function_uses_only_leaf_regs)
{
leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms));
leaf_renumber_regs_insn (DECL_RTL (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);
}
- 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);
- }
- }
+ /* It is quite tempting to use:
+
+ 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
+ than the promoted type. This certainly makes GDB's life
+ easier, at least for some ports. The change is a bad idea
+ however, since GDB expects to be able access the type without
+ performing any conversions. So for example, if we were
+ 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 erroneous value. */
+ dbxout_type (DECL_ARG_TYPE (parms), 0);
current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
dbxout_finish_symbol (parms);
}
{
rtx best_rtl;
char regparm_letter;
+ tree parm_type;
/* Parm passed in registers and lives in registers or nowhere. */
current_sym_code = DBX_REGPARM_STABS_CODE;
/* If parm lives in a register, use that register;
pretend the parm was passed there. It would be more consistent
to describe the register where the parm was passed,
- but in practice that register usually holds something else. */
- if (REGNO (DECL_RTL (parms)) >= 0
- && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
- best_rtl = DECL_RTL (parms);
- /* If the parm lives nowhere,
- use the register where it was passed. */
+ but in practice that register usually holds something else.
+
+ 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)) < FIRST_PSEUDO_REGISTER)
+ {
+ best_rtl = DECL_RTL (parms);
+ parm_type = TREE_TYPE (parms);
+ }
+ /* If the parm lives nowhere, use the register where it was
+ passed. It is also better to use the declared type here. */
else
- best_rtl = DECL_INCOMING_RTL (parms);
+ {
+ best_rtl = DECL_INCOMING_RTL (parms);
+ parm_type = TREE_TYPE (parms);
+ }
current_sym_value = DBX_REGISTER_NUMBER (REGNO (best_rtl));
FORCE_TEXT;
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 (DECL_ARG_TYPE (parms), 0, 0);
+ dbxout_type (parm_type, 0);
dbxout_finish_symbol (parms);
}
else if (GET_CODE (DECL_RTL (parms)) == MEM
- && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG)
-/* && rtx_equal_p (XEXP (DECL_RTL (parms), 0),
- DECL_INCOMING_RTL (parms))) */
+ && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG
+ && REGNO (XEXP (DECL_RTL (parms), 0)) != HARD_FRAME_POINTER_REGNUM
+ && REGNO (XEXP (DECL_RTL (parms), 0)) != STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ && REGNO (XEXP (DECL_RTL (parms), 0)) != ARG_POINTER_REGNUM
+#endif
+ )
{
/* Parm was passed via invisible reference.
That is, its address was passed in a register.
/* 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
+ it was passed instead. */
+ 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));
- /* 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)));
+ 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_REGPARM_STABS_LETTER);
+ regparm_letter);
}
else
{
current_sym_nchars = 8;
- fprintf (asmfile, "%s \"(anon):%c", ASM_STABS_OP,
- DBX_REGPARM_STABS_LETTER);
+ 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);
+
+ current_sym_value
+ = DEBUGGER_ARG_OFFSET (current_sym_value,
+ XEXP (XEXP (DECL_RTL (parms), 0), 0));
+ dbxout_type (TREE_TYPE (parms), 0);
dbxout_finish_symbol (parms);
}
else if (GET_CODE (DECL_RTL (parms)) == MEM
- && XEXP (DECL_RTL (parms), 0) != const0_rtx)
+ && XEXP (DECL_RTL (parms), 0) != const0_rtx
+ /* ??? A constant address for a parm can happen
+ when the reg it lives in is equiv to a constant in memory.
+ Should make this not happen, after 2.4. */
+ && ! CONSTANT_P (XEXP (DECL_RTL (parms), 0)))
{
/* Parm was passed in registers but lives on the stack. */
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
+ parameter is not the same as the mode of the rtl. */
+ if (BYTES_BIG_ENDIAN
+ && TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms))
+ && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD)
+ {
+ 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);
}
}
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);
/* 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
- && PARM_PASSED_IN_MEMORY (parms))
- {
- current_sym_code = N_RSYM;
- current_sym_value = DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms)));
- current_sym_addr = 0;
-
- FORCE_TEXT;
- if (DECL_NAME (parms))
- {
- current_sym_nchars = 2 + IDENTIFIER_LENGTH (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);
- }
+ && 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)
+ 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
- current_sym_code = N_LSYM;
- current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (parms), 0));
- current_sym_addr = 0;
- FORCE_TEXT;
- if (DECL_NAME (parms))
- {
- current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));
- fprintf (asmfile, "%s \"%s:", ASM_STABS_OP,
- IDENTIFIER_POINTER (DECL_NAME (parms)));
- }
- else
- {
- current_sym_nchars = 8;
- fprintf (asmfile, "%s \"(anon):", ASM_STABS_OP);
- }
- dbxout_type (TREE_TYPE (parms), 0, 0);
- dbxout_finish_symbol (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));
}
}
\f
/* 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);
}
}
\f
-/* 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);
- }
-}
-\f
/* Output everything about a symbol block (a BLOCK node
that represents a scope level),
including recursive output of contained blocks.
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
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))
#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");
#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, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
+ 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
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, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)));
+ putc ('-', asmfile);
+ assemble_name (asmfile, begin_label);
#endif
fprintf (asmfile, "\n");
#endif
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);
if (DECL_NAME (DECL_RESULT (decl)) != 0)
dbxout_symbol (DECL_RESULT (decl), 1);
}
-
-/* Called at beginning of output of function definition. */
-
-void
-dbxout_begin_function (decl)
- tree decl;
-{
-#ifdef DBX_FUNCTION_FIRST
- dbxout_really_begin_function (decl);
-#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);
-#endif
- dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
-#ifdef DBX_OUTPUT_FUNCTION_END
- DBX_OUTPUT_FUNCTION_END (asmfile, decl);
-#endif
-}
#endif /* DBX_DEBUGGING_INFO */
+
+#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */