/* Output sdb-format symbol table information from GNU compiler.
- Copyright (C) 1988-1990 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92-97, 1998 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
4. All structure .defs are emitted before the typedefs that refer to them.
5. All top level static and external variable definitions are moved to the
- end of file with all top level statics occuring first before externs.
+ end of file with all top level statics occurring first before externs.
6. All undefined references are at the end of the file.
*/
#ifdef SDB_DEBUGGING_INFO
+#include "system.h"
#include "tree.h"
#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 it's symbols, but
- do not supply usable syms.h include files. */
-#if defined(USG) && !defined(MIPS)
+/* 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. */
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_type ();
-static int plain_type_1 ();
+#include "sdbout.h"
+
+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 sdbout_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. */
/* Return the sdb tag identifier string for TYPE
if TYPE has already been defined; otherwise return a null pointer. */
-#define KNOWN_TYPE_TAG(type) (char *)(TYPE_SYMTAB_ADDRESS (type))
+#define KNOWN_TYPE_TAG(type) TYPE_SYMTAB_POINTER (type)
/* Set the sdb tag identifier string for TYPE to NAME. */
#define SET_KNOWN_TYPE_TAG(TYPE, NAME) \
- (TYPE_SYMTAB_ADDRESS (TYPE) = (int)(NAME))
+ TYPE_SYMTAB_POINTER (TYPE) = (NAME)
/* Return the name (a string) of the struct, union or enum tag
described by the TREE_LIST node LINK. This is 0 for an anonymous one. */
/* 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;
{
-#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);
+#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))
+ if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0
+ && !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
+ sdbout_symbol (t, 0);
+#endif
}
#if 0
tree type,link;
{
if (TYPE_SYMTAB_ADDRESS (type))
- return (char *)TYPE_SYMTAB_ADDRESS (type);
+ return TYPE_SYMTAB_ADDRESS (type);
if (link && TREE_PURPOSE (link)
&& IDENTIFIER_POINTER (TREE_PURPOSE (link)))
- TYPE_SYMTAB_ADDRESS (type)
- = (int)IDENTIFIER_POINTER (TREE_PURPOSE (link));
+ TYPE_SYMTAB_ADDRESS (type) = IDENTIFIER_POINTER (TREE_PURPOSE (link));
else
return (char *) TYPE_SYMTAB_ADDRESS (type);
}
/* Produce the number that describes a pointer, function or array type.
PREV is the number describing the target, value or element type.
DT_type describes how to transform that type. */
-#define PUSH_DERIVED_LEVEL(DT_type,PREV) \
- ((((PREV)&~N_BTMASK)<<N_TSHIFT)|(DT_type<<N_BTSHFT)|(PREV&N_BTMASK))
+#define PUSH_DERIVED_LEVEL(DT_type,PREV) \
+ ((((PREV) & ~(int)N_BTMASK) << (int)N_TSHIFT) \
+ | ((int)DT_type << (int)N_BTSHFT) \
+ | ((PREV) & (int)N_BTMASK))
/* Number of elements used in sdb_dims. */
static int sdb_n_dims = 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)
return val;
}
+static int
+template_name_p (name)
+ tree name;
+{
+ register char *ptr = IDENTIFIER_POINTER (name);
+ while (*ptr && *ptr != '<')
+ ptr++;
+
+ return *ptr != '\0';
+}
+
static void
sdbout_record_type_name (type)
tree 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 0 /* Don't use typedef names. */
+ 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
+ most assemblers. Use its assembler name instead, which
+ has been mangled into being safe. */
+ 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 != 0)
+ if (t != NULL_TREE)
name = IDENTIFIER_POINTER (t);
}
#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 INTEGER_TYPE:
{
int size = int_size_in_bytes (type) * BITS_PER_UNIT;
+
+ /* Carefully distinguish all the standard types of C,
+ without messing up if the language is not C.
+ Note that we check only for the names that contain spaces;
+ other names might occur by coincidence in other languages. */
+ if (TYPE_NAME (type) != 0
+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && DECL_NAME (TYPE_NAME (type)) != 0
+ && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
+ {
+ 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_SHORT;
+ if (!strcmp (name, "short unsigned int"))
+ return T_USHORT;
+ if (!strcmp (name, "long int"))
+ return T_LONG;
+ if (!strcmp (name, "long unsigned 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 */
+ return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
return 0;
}
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_MAX_VALUE (TYPE_DOMAIN (type))
+ && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
+ && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
+ ? (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);
}
case RECORD_TYPE:
case UNION_TYPE:
+ case QUAL_UNION_TYPE:
case ENUMERAL_TYPE:
{
char *tag;
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.
}
return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT
: (TREE_CODE (type) == UNION_TYPE) ? T_UNION
+ : (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION
: T_ENUM);
}
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:
{
while (syms)
{
- sdbout_symbol (syms, 1);
+ if (TREE_CODE (syms) != LABEL_DECL)
+ sdbout_symbol (syms, 1);
syms = TREE_CHAIN (syms);
}
}
tree decl;
int local;
{
- int letter = 0;
tree type = TREE_TYPE (decl);
tree context = NULL_TREE;
rtx value;
sdbout_one_type (type);
+#if 0 /* This loses when functions are marked to be ignored,
+ which happens in the C++ front end. */
+ if (DECL_IGNORED_P (decl))
+ return;
+#endif
+
switch (TREE_CODE (decl))
{
case CONST_DECL:
context = decl_function_context (decl);
if (context == current_function_decl)
return;
- if (TREE_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)
/* Done with tagged types. */
if (DECL_NAME (decl) == 0)
return;
+ if (DECL_IGNORED_P (decl))
+ return;
/* Output typedef name. */
- PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));
+ if (template_name_p (DECL_NAME (decl)))
+ PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+ else
+ PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));
PUT_SDB_SCL (C_TPDEF);
break;
case VAR_DECL:
/* Don't mention a variable that is external.
Let the file that defines it describe it. */
- if (TREE_EXTERNAL (decl))
+ if (DECL_EXTERNAL (decl))
+ return;
+
+ /* Ignore __FUNCTION__, etc. */
+ if (DECL_IGNORED_P (decl))
return;
/* If there was an error in the declaration, don't dump core
if (DECL_RTL (decl) == 0)
return;
- value = eliminate_regs (DECL_RTL (decl), 0, 0);
+ DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
+#ifdef LEAF_REG_REMAP
+ if (leaf_function)
+ leaf_renumber_regs_insn (DECL_RTL (decl));
+#endif
+ value = DECL_RTL (decl);
/* Don't mention a variable at all
if it was completely optimized into nothingness.
{
regno = REGNO (DECL_RTL (decl));
if (regno >= FIRST_PSEUDO_REGISTER)
- regno = reg_renumber[REGNO (DECL_RTL (decl))];
- if (regno < 0)
return;
}
- else if (GET_CODE (DECL_RTL (decl)) == SUBREG)
+ else if (GET_CODE (value) == SUBREG)
{
int offset = 0;
while (GET_CODE (value) == SUBREG)
{
regno = REGNO (value);
if (regno >= FIRST_PSEUDO_REGISTER)
- regno = reg_renumber[REGNO (value)];
- if (regno >= 0)
- regno += offset;
+ return;
+ regno += offset;
}
+ alter_subreg (DECL_RTL (decl));
+ value = DECL_RTL (decl);
}
+ /* Don't output anything if an auto variable
+ gets RTL that is static.
+ GAS version 2.2 can't handle such output. */
+ else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0))
+ && ! TREE_STATIC (decl))
+ return;
/* Emit any structure, union, or enum type that has not been output.
This occurs for tag-less structs (et al) used to declare variables
within functions. */
if (TREE_CODE (type) == ENUMERAL_TYPE
|| TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE)
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE)
{
if (TYPE_SIZE (type) != 0 /* not a forward reference */
&& KNOWN_TYPE_TAG (type) == 0) /* not yet declared */
&& DECL_INITIAL (decl))
return;
+ /* C++ in 2.3 makes nameless symbols. That will be fixed later.
+ For now, avoid crashing. */
+ if (DECL_NAME (decl) == NULL_TREE)
+ return;
+
/* Record the name for, starting a symtab entry. */
- name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
if (GET_CODE (value) == MEM
&& GET_CODE (XEXP (value, 0)) == SYMBOL_REF)
else if (GET_CODE (value) == MEM
&& (GET_CODE (XEXP (value, 0)) == MEM
|| (GET_CODE (XEXP (value, 0)) == REG
- && REGNO (XEXP (value, 0)) != FRAME_POINTER_REGNUM)))
+ && REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM
+ && REGNO (XEXP (value, 0)) != STACK_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
type = build_pointer_type (TREE_TYPE (decl));
}
else if (GET_CODE (value) == MEM
- && GET_CODE (XEXP (value, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
- && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)
+ && ((GET_CODE (XEXP (value, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)
+ /* This is for variables which are at offset zero from
+ the frame pointer. This happens on the Alpha.
+ Non-frame pointer registers are excluded above. */
+ || (GET_CODE (XEXP (value, 0)) == REG)))
{
- /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))).
- We want the value of that CONST_INT. */
+ /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
+ or (MEM (REG...)). We want the value of that CONST_INT
+ or zero. */
PUT_SDB_DEF (name);
PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0)));
PUT_SDB_SCL (C_AUTO);
}
+ else if (GET_CODE (value) == MEM && GET_CODE (XEXP (value, 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'. */
+ PUT_SDB_DEF (name);
+ PUT_SDB_VAL (XEXP (XEXP (value, 0), 0));
+ PUT_SDB_SCL (C_STAT);
+ }
else
{
/* It is something we don't know how to represent for SDB. */
return;
}
break;
+
+ default:
+ break;
}
PUT_SDB_TYPE (plain_type (type));
PUT_SDB_ENDEF;
{
tree type = TREE_TYPE (decl);
+ if (DECL_IGNORED_P (decl))
+ return;
+
if (! (TREE_CODE (decl) == VAR_DECL
&& GET_CODE (DECL_RTL (decl)) == MEM
&& DECL_INITIAL (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;
{
register tree type = TREE_VALUE (link);
- if (! TREE_ASM_WRITTEN (type))
+ if (type && ! TREE_ASM_WRITTEN (type))
sdbout_one_type (type);
}
}
sdbout_type (type)
tree type;
{
- register tree tem;
if (type == error_mark_node)
type = integer_type_node;
PUT_SDB_TYPE (plain_type (type));
tree type;
{
tree tail;
+
for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
- if (TREE_CODE (TREE_TYPE (tail)) == POINTER_TYPE)
+ if (POINTER_TYPE_P (TREE_TYPE (tail)))
sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
else
sdbout_one_type (TREE_TYPE (tail));
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))
{
case RECORD_TYPE:
case UNION_TYPE:
+ case QUAL_UNION_TYPE:
case ENUMERAL_TYPE:
type = TYPE_MAIN_VARIANT (type);
/* Don't output a type twice. */
TREE_ASM_WRITTEN (type) = 1;
#if 1
/* This is reputed to cause trouble with the following case,
- but perhaps checking TYPE_SIZE above will fix it.
+ but perhaps checking TYPE_SIZE above will fix it. */
/* Here is a test case:
int size = int_size_in_bytes (type);
int member_scl;
tree tem;
+ int i, n_baseclasses = 0;
/* Record the type tag, but not in its permanent place just yet. */
sdbout_record_type_name (type);
switch (TREE_CODE (type))
{
case UNION_TYPE:
+ case QUAL_UNION_TYPE:
PUT_SDB_SCL (C_UNTAG);
PUT_SDB_TYPE (T_UNION);
member_scl = C_MOU;
PUT_SDB_TYPE (T_ENUM);
member_scl = C_MOE;
break;
+
+ default:
+ break;
}
PUT_SDB_SIZE (size);
PUT_SDB_ENDEF;
+ /* 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++)
+ {
+ 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;
+ }
+
/* output the individual fields */
if (TREE_CODE (type) == ENUMERAL_TYPE)
&& TREE_CODE (DECL_SIZE (tem)) == INTEGER_CST
&& TREE_CODE (DECL_FIELD_BITPOS (tem)) == INTEGER_CST)
{
+ char *name;
+
CONTIN;
- PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (tem)));
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_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_SIZE (size);
PUT_SDB_ENDEF;
break;
+
+ default:
+ break;
}
}
}
/* 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, 0);
- DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, 0);
+ DECL_INCOMING_RTL (parms)
+ = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
+ DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
if (PARM_PASSED_IN_MEMORY (parms))
{
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))
+ if (BYTES_BIG_ENDIAN
+ && 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))
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. */
/* 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))
+ if (BYTES_BIG_ENDIAN
+ && 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
{
{
tree decl = current_function_decl;
MAKE_LINE_SAFE (line);
- PUT_SDB_BLOCK_START (line - sdb_begin_function_line);
+
+ /* The SCO compiler does not emit a separate block for the function level
+ scope, so we avoid it here also. However, mips ECOFF compilers do emit
+ a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined. */
+#ifndef MIPS_DEBUGGING_INFO
+ if (n != 1)
+#endif
+ PUT_SDB_BLOCK_START (line - sdb_begin_function_line);
+
if (n == 1)
{
/* Include the outermost BLOCK's variables in block 1. */
/* Describe the end line-number of an internal block within a function. */
void
-sdbout_end_block (file, line)
+sdbout_end_block (file, line, n)
FILE *file;
int line;
+ int n;
{
MAKE_LINE_SAFE (line);
+
+ /* The SCO compiler does not emit a separate block for the function level
+ scope, so we avoid it here also. However, mips ECOFF compilers do emit
+ a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined. */
+#ifndef MIPS_DEBUGGING_INFO
+ if (n != 1)
+#endif
PUT_SDB_BLOCK_END (line - sdb_begin_function_line);
}
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 */