/* Output sdb-format symbol table information from GNU compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 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. */
/* mike@tredysvr.Tredydev.Unisys.COM says:
I modified the struct.c example and have a nm of a .o resulting from the
#ifdef SDB_DEBUGGING_INFO
+#include "system.h"
#include "tree.h"
#include "rtl.h"
-#include <stdio.h>
#include "regs.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)
-#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 */
+#include "output.h"
+#include "toplev.h"
+#include "ggc.h"
+#include "tm_p.h"
#include "gsyms.h"
-#endif /* not USG, or MIPS */
-
-/* #include <storclass.h> used to be this instead of syms.h. */
+#include "debug.h"
/* 1 if PARM is passed to this function in memory. */
extern tree current_function_decl;
-void sdbout_init ();
-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 ();
-\f
-/* Define the default sizes for various types. */
-
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
-
-#ifndef SHORT_TYPE_SIZE
-#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2))
-#endif
-
-#ifndef INT_TYPE_SIZE
-#define INT_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef LONG_TYPE_SIZE
-#define LONG_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef LONG_LONG_TYPE_SIZE
-#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-#ifndef FLOAT_TYPE_SIZE
-#define FLOAT_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef DOUBLE_TYPE_SIZE
-#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
+#include "sdbout.h"
+
+static void sdbout_init PARAMS ((const char *));
+static void sdbout_finish PARAMS ((const char *));
+static void sdbout_start_source_file PARAMS ((unsigned, const char *));
+static void sdbout_end_source_file PARAMS ((unsigned));
+static void sdbout_begin_block PARAMS ((unsigned, unsigned));
+static void sdbout_end_block PARAMS ((unsigned, unsigned));
+static void sdbout_source_line PARAMS ((unsigned int, const char *));
+static void sdbout_end_epilogue PARAMS ((void));
+static void sdbout_global_decl PARAMS ((tree));
+#ifndef MIPS_DEBUGGING_INFO
+static void sdbout_begin_prologue PARAMS ((unsigned int, const char *));
#endif
-
-#ifndef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
+static void sdbout_end_prologue PARAMS ((unsigned int));
+static void sdbout_begin_function PARAMS ((tree));
+static void sdbout_end_function PARAMS ((unsigned int));
+static void sdbout_toplevel_data PARAMS ((tree));
+static void sdbout_label PARAMS ((rtx));
+static char *gen_fake_label PARAMS ((void));
+static int plain_type PARAMS ((tree));
+static int template_name_p PARAMS ((tree));
+static void sdbout_record_type_name PARAMS ((tree));
+static int plain_type_1 PARAMS ((tree, int));
+static void sdbout_block PARAMS ((tree));
+static void sdbout_syms PARAMS ((tree));
+#ifdef SDB_ALLOW_FORWARD_REFERENCES
+static void sdbout_queue_anonymous_type PARAMS ((tree));
+static void sdbout_dequeue_anonymous_types PARAMS ((void));
#endif
+static void sdbout_type PARAMS ((tree));
+static void sdbout_field_types PARAMS ((tree));
+static void sdbout_one_type PARAMS ((tree));
+static void sdbout_parms PARAMS ((tree));
+static void sdbout_reg_parms PARAMS ((tree));
+static void sdbout_global_decl PARAMS ((tree));
\f
/* Random macros describing parts of SDB data. */
#endif
#ifndef PUT_SDB_INT_VAL
-#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\t.val\t%d%s", (a), SDB_DELIM)
+#define PUT_SDB_INT_VAL(a) \
+ do { \
+ fputs ("\t.val\t", asm_out_file); \
+ fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(a)); \
+ fprintf (asm_out_file, "%s", SDB_DELIM); \
+ } while (0)
+
#endif
#ifndef PUT_SDB_VAL
#ifndef PUT_SDB_DEF
#define PUT_SDB_DEF(a) \
do { fprintf (asm_out_file, "\t.def\t"); \
- ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ assemble_name (asm_out_file, a); \
fprintf (asm_out_file, SDB_DELIM); } while (0)
#endif
#endif
#ifndef PUT_SDB_SIZE
-#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\t.size\t%d%s", a, SDB_DELIM)
+#define PUT_SDB_SIZE(a) \
+ do { \
+ fputs ("\t.size\t", asm_out_file); \
+ fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(a)); \
+ fprintf (asm_out_file, "%s", SDB_DELIM); \
+ } while(0)
#endif
#ifndef PUT_SDB_START_DIM
#ifndef PUT_SDB_TAG
#define PUT_SDB_TAG(a) \
do { fprintf (asm_out_file, "\t.tag\t"); \
- ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ assemble_name (asm_out_file, a); \
fprintf (asm_out_file, SDB_DELIM); } while (0)
#endif
SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
#endif
-#ifndef PUT_SDB_EPILOGUE_END
-#define PUT_SDB_EPILOGUE_END(NAME) \
-do { fprintf (asm_out_file, "\t.def\t"); \
- ASM_OUTPUT_LABELREF (asm_out_file, NAME); \
- fprintf (asm_out_file, \
- "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n", \
- SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0)
-#endif
-
#ifndef SDB_GENERATE_FAKE
#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
sprintf ((BUFFER), ".%dfake", (NUMBER));
/* 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
-\f
-/* Set up for SDB output at the start of compilation. */
-void
-sdbout_init (asm_file, input_file_name, syms)
- FILE *asm_file;
- char *input_file_name;
- tree syms;
-{
-#ifdef RMS_QUICK_HACK_1
- tree t;
- for (t = syms; t; t = TREE_CHAIN (t))
- if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0
- && !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
- sdbout_symbol (t, 0);
-#endif
+/* 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. */
-#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. */
+#ifdef MIPS_DEBUGGING_INFO
- sdbout_typedefs (syms);
+#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;
+ const char *name;
+};
+
+/* This is the top of the stack. */
+
+static struct sdb_file *current_file;
+
+#endif /* MIPS_DEBUGGING_INFO */
+\f
+/* The debug hooks structure. */
+struct gcc_debug_hooks sdb_debug_hooks =
+{
+ sdbout_init, /* init */
+ sdbout_finish, /* finish */
+ debug_nothing_int_charstar, /* define */
+ debug_nothing_int_charstar, /* undef */
+ sdbout_start_source_file, /* start_source_file */
+ sdbout_end_source_file, /* end_source_file */
+ sdbout_begin_block, /* begin_block */
+ sdbout_end_block, /* end_block */
+ debug_true_tree, /* ignore_block */
+ sdbout_source_line, /* source_line */
+#ifdef MIPS_DEBUGGING_INFO
+ /* Defer on MIPS systems so that parameter descriptions follow
+ function entry. */
+ debug_nothing_int_charstar, /* begin_prologue */
+ sdbout_end_prologue, /* end_prologue */
+#else
+ sdbout_begin_prologue, /* begin_prologue */
+ debug_nothing_int, /* end_prologue */
+#endif
+ sdbout_end_epilogue, /* end_epilogue */
+ sdbout_begin_function, /* begin_function */
+ sdbout_end_function, /* end_function */
+ debug_nothing_tree, /* function_decl */
+ sdbout_global_decl, /* global_decl */
+ debug_nothing_tree, /* deferred_inline_function */
+ debug_nothing_tree, /* outlining_inline_function */
+ sdbout_label
+};
+\f
#if 0
/* return the tag identifier for type
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)
template_name_p (name)
tree name;
{
- register char *ptr = IDENTIFIER_POINTER (name);
+ register const char *ptr = IDENTIFIER_POINTER (name);
while (*ptr && *ptr != '<')
ptr++;
sdbout_record_type_name (type)
tree type;
{
- char *name = 0;
+ const char *name = 0;
int no_name;
if (KNOWN_TYPE_TAG (type))
tree t = 0;
/* Find the IDENTIFIER_NODE for the type name. */
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- {
- t = TYPE_NAME (type);
- }
-#if 1 /* As a temporary hack, use typedef names for C++ only. */
- else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && TYPE_LANG_SPECIFIC (type))
+ t = TYPE_NAME (type);
+ else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
{
t = DECL_NAME (TYPE_NAME (type));
/* The DECL_NAME for templates includes "<>", which breaks
if (t && template_name_p (t))
t = DECL_ASSEMBLER_NAME (TYPE_NAME (type));
}
-#endif
/* Now get the name as a string, or invent one. */
if (t != NULL_TREE)
#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 VOID_TYPE:
return T_VOID;
+ case BOOLEAN_TYPE:
case INTEGER_TYPE:
{
int size = int_size_in_bytes (type) * BITS_PER_UNIT;
&& DECL_NAME (TYPE_NAME (type)) != 0
&& TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
{
- char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ const char *name
+ = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ if (!strcmp (name, "char"))
+ return T_CHAR;
if (!strcmp (name, "unsigned char"))
return T_UCHAR;
if (!strcmp (name, "signed char"))
return T_CHAR;
+ if (!strcmp (name, "int"))
+ return T_INT;
if (!strcmp (name, "unsigned int"))
return T_UINT;
if (!strcmp (name, "short int"))
return T_ULONG;
}
+ if (size == INT_TYPE_SIZE)
+ return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
if (size == CHAR_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
if (size == SHORT_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT);
- if (size == INT_TYPE_SIZE)
- return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
if (size == LONG_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
if (size == LONG_LONG_TYPE_SIZE) /* better than nothing */
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;
+#else
+ if (precision == LONG_DOUBLE_TYPE_SIZE)
+ return T_DOUBLE; /* better than nothing */
+#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
+ && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != 0
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0
+ && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
+ && host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0)
+ ? (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
+ - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 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:
}
\f
/* Output the symbols defined in block number DO_BLOCK.
- Set NEXT_BLOCK_NUMBER to 0 before calling.
This function works by walking the tree structure of blocks,
counting blocks until it finds the desired block. */
static int do_block = 0;
-static int next_block_number;
-
static void
sdbout_block (block)
register tree block;
if (TREE_USED (block))
{
/* When we reach the specified block, output its symbols. */
- if (next_block_number == do_block)
- {
- sdbout_syms (BLOCK_VARS (block));
- }
+ if (BLOCK_NUMBER (block) == do_block)
+ sdbout_syms (BLOCK_VARS (block));
/* If we are past the specified block, stop the scan. */
- if (next_block_number > do_block)
+ if (BLOCK_NUMBER (block) > do_block)
return;
- next_block_number++;
-
/* Scan the blocks within this block. */
sdbout_block (BLOCK_SUBBLOCKS (block));
}
tree context = NULL_TREE;
rtx value;
int regno = -1;
- char *name;
+ const char *name;
sdbout_one_type (type);
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 there was an error in the declaration, don't dump core
if there is no RTL associated with the variable doesn't
exist. */
- if (DECL_RTL (decl) == 0)
+ if (!DECL_RTL_SET_P (decl))
return;
- DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
+ SET_DECL_RTL (decl,
+ eliminate_regs (DECL_RTL (decl), 0, NULL_RTX));
#ifdef LEAF_REG_REMAP
- if (leaf_function)
+ if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
value = DECL_RTL (decl);
}
else if (GET_CODE (value) == SUBREG)
{
- int offset = 0;
while (GET_CODE (value) == SUBREG)
- {
- offset += SUBREG_WORD (value);
- value = SUBREG_REG (value);
- }
+ value = SUBREG_REG (value);
if (GET_CODE (value) == REG)
{
- regno = REGNO (value);
- if (regno >= FIRST_PSEUDO_REGISTER)
+ if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
return;
- regno += offset;
}
- alter_subreg (DECL_RTL (decl));
+ regno = REGNO (alter_subreg (DECL_RTL (decl)));
value = DECL_RTL (decl);
}
/* Don't output anything if an auto variable
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
{
- if (TYPE_SIZE (type) != 0 /* not a forward reference */
+ if (COMPLETE_TYPE_P (type) /* not a forward reference */
&& KNOWN_TYPE_TAG (type) == 0) /* not yet declared */
sdbout_one_type (type);
}
return;
/* Record the name for, starting a symtab entry. */
- if (DECL_LANG_SPECIFIC (decl))
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- else
+ if (local)
name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ else
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
if (GET_CODE (value) == MEM
&& GET_CODE (XEXP (value, 0)) == SYMBOL_REF)
PUT_SDB_SCL (C_AUTO);
}
- type = build_pointer_type (TREE_TYPE (decl));
+ /* 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 (value) == MEM
&& ((GET_CODE (XEXP (value, 0)) == PLUS
return;
}
break;
+
+ default:
+ break;
}
PUT_SDB_TYPE (plain_type (type));
PUT_SDB_ENDEF;
/* Output SDB information for a top-level initialized variable
that has been delayed. */
-void
+static void
sdbout_toplevel_data (decl)
tree 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;
sdbout_queue_anonymous_type (type)
tree type;
{
- anonymous_types = saveable_tree_cons (NULL_TREE, type, anonymous_types);
+ anonymous_types = tree_cons (NULL_TREE, type, anonymous_types);
}
static void
tree type;
{
tree tail;
+
for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
- if (TREE_CODE (TREE_TYPE (tail)) == POINTER_TYPE)
- sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
- else
- sdbout_one_type (TREE_TYPE (tail));
+ /* This condition should match the one for emitting the actual
+ members below. */
+ if (TREE_CODE (tail) == FIELD_DECL
+ && DECL_NAME (tail)
+ && DECL_SIZE (tail)
+ && host_integerp (DECL_SIZE (tail), 1)
+ && host_integerp (bit_position (tail), 0))
+ {
+ if (POINTER_TYPE_P (TREE_TYPE (tail)))
+ sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
+ else
+ sdbout_one_type (TREE_TYPE (tail));
+ }
}
/* Use this to put out the top level defined record and union types
sdbout_one_type (type)
tree type;
{
- text_section ();
+ if (current_function_decl != NULL_TREE
+ && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
+ ; /* Don't change section amid function. */
+ else
+ text_section ();
switch (TREE_CODE (type))
{
return;
/* Output nothing if type is not yet defined. */
- if (TYPE_SIZE (type) == 0)
+ if (!COMPLETE_TYPE_P (type))
return;
TREE_ASM_WRITTEN (type) = 1;
/* Output a structure type. */
{
int size = int_size_in_bytes (type);
- int member_scl;
+ int member_scl = 0;
tree tem;
int i, n_baseclasses = 0;
PUT_SDB_TYPE (T_ENUM);
member_scl = C_MOE;
break;
+
+ default:
+ break;
}
PUT_SDB_SIZE (size);
/* Print out the base class information with fields
named after the types they hold. */
- if (TYPE_BINFO (type)
- && TYPE_BINFO_BASETYPES (type))
- n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
- for (i = 0; i < n_baseclasses; i++)
+ /* This is only relevent to aggregate types. TYPE_BINFO is used
+ for other purposes in an ENUMERAL_TYPE, so we must exclude that
+ case. */
+ if (TREE_CODE (type) != ENUMERAL_TYPE)
{
- tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i);
- tree child_type = BINFO_TYPE (child);
- tree child_type_name;
- if (TYPE_NAME (child_type) == 0)
- continue;
- if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
- child_type_name = TYPE_NAME (child_type);
- else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
+ if (TYPE_BINFO (type)
+ && TYPE_BINFO_BASETYPES (type))
+ n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
+ for (i = 0; i < n_baseclasses; i++)
{
- child_type_name = DECL_NAME (TYPE_NAME (child_type));
- if (child_type_name && template_name_p (child_type_name))
- child_type_name
- = DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
- }
- else
- continue;
+ tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)),
+ i);
+ tree child_type = BINFO_TYPE (child);
+ tree child_type_name;
+ if (TYPE_NAME (child_type) == 0)
+ continue;
+ if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
+ child_type_name = TYPE_NAME (child_type);
+ else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
+ {
+ child_type_name = DECL_NAME (TYPE_NAME (child_type));
+ if (child_type_name && template_name_p (child_type_name))
+ child_type_name
+ = DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
+ }
+ else
+ continue;
- CONTIN;
- PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
- PUT_SDB_INT_VAL (TREE_INT_CST_LOW (BINFO_OFFSET (child)));
- PUT_SDB_SCL (member_scl);
- sdbout_type (BINFO_TYPE (child));
- PUT_SDB_ENDEF;
+ CONTIN;
+ PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
+ PUT_SDB_INT_VAL (tree_low_cst (BINFO_OFFSET (child), 0));
+ PUT_SDB_SCL (member_scl);
+ sdbout_type (BINFO_TYPE (child));
+ PUT_SDB_ENDEF;
+ }
}
/* output the individual fields */
if (TREE_CODE (type) == ENUMERAL_TYPE)
- for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
- {
- PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
- PUT_SDB_INT_VAL (TREE_INT_CST_LOW (TREE_VALUE (tem)));
- PUT_SDB_SCL (C_MOE);
- PUT_SDB_TYPE (T_MOE);
- PUT_SDB_ENDEF;
- }
-
+ {
+ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+ if (host_integerp (TREE_VALUE (tem), 0))
+ {
+ PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
+ PUT_SDB_INT_VAL (tree_low_cst (TREE_VALUE (tem), 0));
+ PUT_SDB_SCL (C_MOE);
+ PUT_SDB_TYPE (T_MOE);
+ PUT_SDB_ENDEF;
+ }
+ }
else /* record or union type */
for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
/* Output the name, type, position (in bits), size (in bits)
Also omit fields with variable size or position.
Also omit non FIELD_DECL nodes that GNU C++ may put here. */
if (TREE_CODE (tem) == FIELD_DECL
- && DECL_NAME (tem) != 0
- && TREE_CODE (DECL_SIZE (tem)) == INTEGER_CST
- && TREE_CODE (DECL_FIELD_BITPOS (tem)) == INTEGER_CST)
+ && DECL_NAME (tem)
+ && DECL_SIZE (tem)
+ && host_integerp (DECL_SIZE (tem), 1)
+ && host_integerp (bit_position (tem), 0))
{
- char *name;
+ const char *name;
CONTIN;
- if (DECL_LANG_SPECIFIC (tem))
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem));
- else
- name = IDENTIFIER_POINTER (DECL_NAME (tem));
+ name = IDENTIFIER_POINTER (DECL_NAME (tem));
PUT_SDB_DEF (name);
if (DECL_BIT_FIELD_TYPE (tem))
{
- PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)));
+ PUT_SDB_INT_VAL (int_bit_position (tem));
PUT_SDB_SCL (C_FIELD);
sdbout_type (DECL_BIT_FIELD_TYPE (tem));
- PUT_SDB_SIZE (TREE_INT_CST_LOW (DECL_SIZE (tem)));
+ PUT_SDB_SIZE (tree_low_cst (DECL_SIZE (tem), 1));
}
else
{
- PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem))
- / BITS_PER_UNIT);
+ PUT_SDB_INT_VAL (int_bit_position (tem) / BITS_PER_UNIT);
PUT_SDB_SCL (member_scl);
sdbout_type (TREE_TYPE (tem));
}
PUT_SDB_SIZE (size);
PUT_SDB_ENDEF;
break;
+
+ default:
+ break;
}
}
}
if (DECL_NAME (parms))
{
int current_sym_value = 0;
- char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
if (name == 0 || *name == 0)
name = gen_fake_label ();
/* 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);
+ SET_DECL_RTL (parms,
+ eliminate_regs (DECL_RTL (parms), 0, NULL_RTX));
if (PARM_PASSED_IN_MEMORY (parms))
{
current_sym_value = 0;
if (GET_CODE (DECL_RTL (parms)) == REG
- && REGNO (DECL_RTL (parms)) >= 0
&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
type = DECL_ARG_TYPE (parms);
else
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)
+ if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
best_rtl = DECL_RTL (parms);
/* If the parm lives nowhere,
use the register where it was passed. */
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;
}
}
for (; parms; parms = TREE_CHAIN (parms))
if (DECL_NAME (parms))
{
- char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (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))
{
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. */
}
}
\f
+/* Output debug information for a global DECL. Called from toplev.c
+ after compilation proper has finished. */
+
+static void
+sdbout_global_decl (decl)
+ tree decl;
+{
+ if (TREE_CODE (decl) == VAR_DECL
+ && !DECL_EXTERNAL (decl)
+ && DECL_RTL_SET_P (decl))
+ {
+ /* The COFF linker can move initialized global vars to the end.
+ And that can screw up the symbol ordering. Defer those for
+ sdbout_finish (). */
+ if (!DECL_INITIAL (decl) || !TREE_PUBLIC (decl))
+ sdbout_symbol (decl, 0);
+
+ /* Output COFF information for non-global file-scope initialized
+ variables. */
+ if (DECL_INITIAL (decl) && GET_CODE (DECL_RTL (decl)) == MEM)
+ sdbout_toplevel_data (decl);
+ }
+}
+
+/* Output initialized global vars at the end, in the order of
+ definition. See comment in sdbout_global_decl. */
+
+static void
+sdbout_finish (main_filename)
+ const char *main_filename ATTRIBUTE_UNUSED;
+{
+ tree decl = getdecls ();
+ unsigned int len = list_length (decl);
+ tree *vec = (tree *) xmalloc (sizeof (tree) * len);
+ unsigned int i;
+
+ /* Process the decls in reverse order--earliest first. Put them
+ into VEC from back to front, then take out from front. */
+
+ for (i = 0; i < len; i++, decl = TREE_CHAIN (decl))
+ vec[len - i - 1] = decl;
+
+ for (i = 0; i < len; i++)
+ {
+ decl = vec[i];
+ if (TREE_CODE (decl) == VAR_DECL
+ && ! DECL_EXTERNAL (decl)
+ && DECL_INITIAL (decl)
+ && TREE_PUBLIC (decl)
+ && DECL_RTL_SET_P (decl))
+ sdbout_symbol (decl, 0);
+ }
+
+ free (vec);
+}
+\f
/* Describe the beginning of an internal block within a function.
Also output descriptions of variables defined in this block.
The blocks match the BLOCKs in DECL_INITIAL (current_function_decl),
if the count starts at 0 for the outermost one. */
-void
-sdbout_begin_block (file, line, n)
- FILE *file;
- int line;
- int n;
+static void
+sdbout_begin_block (line, n)
+ unsigned int line;
+ unsigned int n;
{
tree decl = current_function_decl;
MAKE_LINE_SAFE (line);
if (n == 1)
{
/* Include the outermost BLOCK's variables in block 1. */
- next_block_number = 0;
- do_block = 0;
+ do_block = BLOCK_NUMBER (DECL_INITIAL (decl));
sdbout_block (DECL_INITIAL (decl));
}
/* If -g1, suppress all the internal symbols of functions
except for arguments. */
if (debug_info_level != DINFO_LEVEL_TERSE)
{
- next_block_number = 0;
do_block = n;
sdbout_block (DECL_INITIAL (decl));
}
/* Describe the end line-number of an internal block within a function. */
-void
-sdbout_end_block (file, line, n)
- FILE *file;
- int line;
- int n;
+static void
+sdbout_end_block (line, n)
+ unsigned int line;
+ unsigned int n ATTRIBUTE_UNUSED;
{
MAKE_LINE_SAFE (line);
PUT_SDB_BLOCK_END (line - sdb_begin_function_line);
}
+static void
+sdbout_source_line (line, filename)
+ unsigned int line;
+ const char *filename ATTRIBUTE_UNUSED;
+{
+ /* COFF relative line numbers must be positive. */
+ if (line > sdb_begin_function_line)
+ {
+#ifdef ASM_OUTPUT_SOURCE_LINE
+ ASM_OUTPUT_SOURCE_LINE (asm_out_file, line);
+#else
+ fprintf (asm_out_file, "\t.ln\t%d\n",
+ ((sdb_begin_function_line > -1)
+ ? line - sdb_begin_function_line : 1));
+#endif
+ }
+}
+
/* Output sdb info for the current function name.
Called from assemble_start_function. */
-void
-sdbout_mark_begin_function ()
+static void
+sdbout_begin_function (decl)
+ tree decl ATTRIBUTE_UNUSED;
{
sdbout_symbol (current_function_decl, 0);
}
-/* Called at beginning of function body (after prologue).
- Record the function's starting line number, so we can output
- relative line numbers for the other lines.
- Describe beginning of outermost block.
- Also describe the parameter list. */
+/* Called at beginning of function body (before or after prologue,
+ depending on MIPS_DEBUGGING_INFO). Record the function's starting
+ line number, so we can output relative line numbers for the other
+ lines. Describe beginning of outermost block. Also describe the
+ parameter list. */
-void
-sdbout_begin_function (line)
- int line;
+#ifndef MIPS_DEBUGGING_INFO
+static void
+sdbout_begin_prologue (line, file)
+ unsigned int line;
+ const char *file ATTRIBUTE_UNUSED;
+{
+ sdbout_end_prologue (line);
+}
+#endif
+
+static void
+sdbout_end_prologue (line)
+ unsigned int line;
{
sdb_begin_function_line = line - 1;
PUT_SDB_FUNCTION_START (line);
/* Called at end of function (before epilogue).
Describe end of outermost block. */
-void
+static void
sdbout_end_function (line)
- int line;
+ unsigned int line;
{
#ifdef SDB_ALLOW_FORWARD_REFERENCES
sdbout_dequeue_anonymous_types ();
/* Output sdb info for the absolute end of a function.
Called after the epilogue is output. */
-void
+static void
sdbout_end_epilogue ()
{
- char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
+ const char *name
+ = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
+
+#ifdef PUT_SDB_EPILOGUE_END
PUT_SDB_EPILOGUE_END (name);
+#else
+ fprintf (asm_out_file, "\t.def\t");
+ assemble_name (asm_out_file, name);
+ fprintf (asm_out_file, "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n",
+ SDB_DELIM, SDB_DELIM, SDB_DELIM);
+#endif
}
/* Output sdb info for the given label. Called only if LABEL_NAME (insn)
is present. */
-void
+static void
sdbout_label (insn)
register rtx insn;
{
PUT_SDB_ENDEF;
}
+/* Change to reading from a new source file. */
+
+static void
+sdbout_start_source_file (line, filename)
+ unsigned int line ATTRIBUTE_UNUSED;
+ const char *filename ATTRIBUTE_UNUSED;
+{
+#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. */
+
+static void
+sdbout_end_source_file (line)
+ unsigned int line ATTRIBUTE_UNUSED;
+{
+#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
+}
+
+/* Set up for SDB output at the start of compilation. */
+
+static void
+sdbout_init (input_file_name)
+ const char *input_file_name ATTRIBUTE_UNUSED;
+{
+#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 = getdecls (); t; t = TREE_CHAIN (t))
+ if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0
+ && !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
+ sdbout_symbol (t, 0);
+#endif
+
+#ifdef SDB_ALLOW_FORWARD_REFERENCES
+ ggc_add_tree_root (&anonymous_types, 1);
+#endif
+}
+
#endif /* SDB_DEBUGGING_INFO */