/* Output sdb-format symbol table information from GNU compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* mike@tredysvr.Tredydev.Unisys.COM says:
I modified the struct.c example and have a nm of a .o resulting from the
#include "rtl.h"
#include <stdio.h>
#include "regs.h"
+#include "defaults.h"
#include "flags.h"
#include "insn-config.h"
#include "reload.h"
-/* Mips systems use the SDB functions to dump out symbols, but
- do not supply usable syms.h include files. */
-#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(WINNT) && !defined(__linux__)
+/* Mips systems use the SDB functions to dump out symbols, but do not
+ supply usable syms.h include files. Which syms.h file to use is a
+ target parameter so don't use the native one if we're cross compiling. */
+
+#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(_WIN32) && !defined(__linux__) && !defined(CROSS_COMPILE)
#include <syms.h>
/* Use T_INT if we don't have T_VOID. */
#ifndef T_VOID
#define T_VOID T_INT
#endif
-#else /* not USG, or MIPS */
+#else
#include "gsyms.h"
-#endif /* not USG, or MIPS */
+#endif
/* #include <storclass.h> used to be this instead of syms.h. */
void sdbout_symbol ();
void sdbout_types();
-static void sdbout_typedefs ();
-static void sdbout_syms ();
-static void sdbout_one_type ();
-static void sdbout_queue_anonymous_type ();
-static void sdbout_dequeue_anonymous_types ();
-static int plain_type_1 ();
+static char *gen_fake_label PROTO((void));
+static int plain_type PROTO((tree));
+static int template_name_p PROTO((tree));
+static void sdbout_record_type_name PROTO((tree));
+static int plain_type_1 PROTO((tree, int));
+static void sdbout_block PROTO((tree));
+static void sdbout_syms PROTO((tree));
+static void sdbout_queue_anonymous_type PROTO((tree));
+static void sdbout_dequeue_anonymous_types PROTO((void));
+static void sdbout_type PROTO((tree));
+static void sbdout_field_types PROTO((tree));
+static void sdbout_one_type PROTO((tree));
+static void sdbout_parms PROTO((tree));
+static void sdbout_reg_parms PROTO((tree));
\f
/* Define the default sizes for various types. */
/* Ensure we don't output a negative line number. */
#define MAKE_LINE_SAFE(line) \
if (line <= sdb_begin_function_line) line = sdb_begin_function_line + 1
+
+/* Perform linker optimization of merging header file definitions together
+ for targets with MIPS_DEBUGGING_INFO defined. This won't work without a
+ post 960826 version of GAS. Nothing breaks with earlier versions of GAS,
+ the optimization just won't be done. The native assembler already has the
+ necessary support. */
+
+#ifdef MIPS_DEBUGGING_INFO
+
+#ifndef PUT_SDB_SRC_FILE
+#define PUT_SDB_SRC_FILE(FILENAME) \
+output_file_directive (asm_out_file, (FILENAME))
+#endif
+
+/* ECOFF linkers have an optimization that does the same kind of thing as
+ N_BINCL/E_INCL in stabs: eliminate duplicate debug information in the
+ executable. To achieve this, GCC must output a .file for each file
+ name change. */
+
+/* This is a stack of input files. */
+
+struct sdb_file
+{
+ struct sdb_file *next;
+ char *name;
+};
+
+/* This is the top of the stack. */
+
+static struct sdb_file *current_file;
+
+#endif /* MIPS_DEBUGGING_INFO */
\f
/* Set up for SDB output at the start of compilation. */
char *input_file_name;
tree syms;
{
+#ifdef MIPS_DEBUGGING_INFO
+ current_file = (struct sdb_file *) xmalloc (sizeof *current_file);
+ current_file->next = NULL;
+ current_file->name = input_file_name;
+#endif
+
#ifdef RMS_QUICK_HACK_1
tree t;
for (t = syms; t; t = TREE_CHAIN (t))
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
sdbout_symbol (t, 0);
#endif
-
-#if 0 /* Nothing need be output for the predefined types. */
- /* Get all permanent types that have typedef names,
- and output them all, except for those already output. */
-
- sdbout_typedefs (syms);
-#endif
}
#if 0
plain_type (type)
tree type;
{
- int val = plain_type_1 (type);
+ int val = plain_type_1 (type, 0);
/* If we have already saved up some array dimensions, print them now. */
if (sdb_n_dims > 0)
#endif
}
+/* Return the .type value for type TYPE.
+
+ LEVEL indicates how many levels deep we have recursed into the type.
+ The SDB debug format can only represent 6 derived levels of types.
+ After that, we must output inaccurate debug info. We deliberately
+ stop before the 7th level, so that ADA recursive types will not give an
+ infinite loop. */
+
static int
-plain_type_1 (type)
+plain_type_1 (type, level)
tree type;
+ int level;
{
if (type == 0)
type = void_type_node;
- if (type == error_mark_node)
+ else if (type == error_mark_node)
type = integer_type_node;
- type = TYPE_MAIN_VARIANT (type);
+ else
+ type = TYPE_MAIN_VARIANT (type);
switch (TREE_CODE (type))
{
case REAL_TYPE:
{
- int size = int_size_in_bytes (type) * BITS_PER_UNIT;
- if (size == FLOAT_TYPE_SIZE)
+ int precision = TYPE_PRECISION (type);
+ if (precision == FLOAT_TYPE_SIZE)
return T_FLOAT;
- if (size == DOUBLE_TYPE_SIZE)
+ if (precision == DOUBLE_TYPE_SIZE)
return T_DOUBLE;
+#ifdef EXTENDED_SDB_BASIC_TYPES
+ if (precision == LONG_DOUBLE_TYPE_SIZE)
+ return T_LNGDBL;
+#endif
return 0;
}
case ARRAY_TYPE:
{
int m;
- m = plain_type_1 (TREE_TYPE (type));
+ if (level >= 6)
+ return T_VOID;
+ else
+ m = plain_type_1 (TREE_TYPE (type), level+1);
if (sdb_n_dims < SDB_MAX_DIM)
sdb_dims[sdb_n_dims++]
= (TYPE_DOMAIN (type)
- ? TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1
+ ? (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) + 1)
: 0);
return PUSH_DERIVED_LEVEL (DT_ARY, m);
}
only if the .def has already been finished.
At least on 386, the Unix assembler
cannot handle forward references to tags. */
- /* But the 88100, it requires them, sigh... */
- /* And the MIPS requires unknown refs as well... */
+ /* But the 88100, it requires them, sigh... */
+ /* And the MIPS requires unknown refs as well... */
tag = KNOWN_TYPE_TAG (type);
PUT_SDB_TAG (tag);
/* These 3 lines used to follow the close brace.
case POINTER_TYPE:
case REFERENCE_TYPE:
{
- int m = plain_type_1 (TREE_TYPE (type));
+ int m;
+ if (level >= 6)
+ return T_VOID;
+ else
+ m = plain_type_1 (TREE_TYPE (type), level+1);
return PUSH_DERIVED_LEVEL (DT_PTR, m);
}
case FUNCTION_TYPE:
case METHOD_TYPE:
{
- int m = plain_type_1 (TREE_TYPE (type));
+ int m;
+ if (level >= 6)
+ return T_VOID;
+ else
+ m = plain_type_1 (TREE_TYPE (type), level+1);
return PUSH_DERIVED_LEVEL (DT_FCN, m);
}
default:
context = decl_function_context (decl);
if (context == current_function_decl)
return;
- if (DECL_EXTERNAL (decl))
+ /* Check DECL_INITIAL to distinguish declarations from definitions.
+ Don't output debug info here for declarations; they will have
+ a DECL_INITIAL value of 0. */
+ if (! DECL_INITIAL (decl))
return;
if (GET_CODE (DECL_RTL (decl)) != MEM
|| GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
if (DECL_RTL (decl) == 0)
return;
- DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
+ DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX, 0);
#ifdef LEAF_REG_REMAP
if (leaf_function)
leaf_renumber_regs_insn (DECL_RTL (decl));
\f
#ifdef SDB_ALLOW_FORWARD_REFERENCES
-/* Machinery to record and output anonymous types. */
+/* Machinery to record and output anonymous types. */
static tree anonymous_types;
/* Perform any necessary register eliminations on the parameter's rtl,
so that the debugging output will be accurate. */
- DECL_INCOMING_RTL (parms) =
- eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
- DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
+ DECL_INCOMING_RTL (parms)
+ = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX, 0);
+ DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX, 0);
if (PARM_PASSED_IN_MEMORY (parms))
{
PUT_SDB_DEF (name);
PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl)));
PUT_SDB_SCL (C_REGPARM);
- PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
+ PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
PUT_SDB_ENDEF;
}
else if (GET_CODE (DECL_RTL (parms)) == MEM
PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value,
XEXP (DECL_RTL (parms), 0)));
PUT_SDB_SCL (C_ARG);
- PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
+ PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
PUT_SDB_ENDEF;
}
}
PUT_SDB_DEF (name);
PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))));
PUT_SDB_SCL (C_REG);
- PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
+ PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
PUT_SDB_ENDEF;
}
/* Report parms that live in memory but not where they were passed. */
PUT_SDB_ENDEF;
}
+/* Change to reading from a new source file. */
+
+void
+sdbout_start_new_source_file (filename)
+ char *filename;
+{
+#ifdef MIPS_DEBUGGING_INFO
+ struct sdb_file *n = (struct sdb_file *) xmalloc (sizeof *n);
+
+ n->next = current_file;
+ n->name = filename;
+ current_file = n;
+ PUT_SDB_SRC_FILE (filename);
+#endif
+}
+
+/* Revert to reading a previous source file. */
+
+void
+sdbout_resume_previous_source_file ()
+{
+#ifdef MIPS_DEBUGGING_INFO
+ struct sdb_file *next;
+
+ next = current_file->next;
+ free (current_file);
+ current_file = next;
+ PUT_SDB_SRC_FILE (current_file->name);
+#endif
+}
+
#endif /* SDB_DEBUGGING_INFO */