/* Output sdb-format symbol table information from GNU compiler.
- Copyright (C) 1988-1990 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992 Free Software Foundation, Inc.
This file is part of GNU CC.
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.
*/
#include "insn-config.h"
#include "reload.h"
-/* Mips systems use the SDB functions to dump out it's symbols, but
+/* Mips systems use the SDB functions to dump out symbols, but
do not supply usable syms.h include files. */
-#if defined(USG) && !defined(MIPS)
+#if defined(USG) && !defined(MIPS) && !defined (hpux)
#include <syms.h>
/* Use T_INT if we don't have T_VOID. */
#ifndef T_VOID
static void sdbout_syms ();
static void sdbout_one_type ();
static void sdbout_queue_anonymous_type ();
-static void sdbout_dequeue_anonymous_type ();
+static void sdbout_dequeue_anonymous_types ();
static int plain_type_1 ();
\f
/* Define the default sizes for various types. */
/* 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;
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;
{
t = TYPE_NAME (type);
}
-#if 0 /* Don't use typedef names. */
- else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+#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 = 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);
}
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, "unsigned char"))
+ return T_UCHAR;
+ if (!strcmp (name, "signed char"))
+ return T_CHAR;
+ 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 == 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);
return 0;
}
case RECORD_TYPE:
case UNION_TYPE:
+ case QUAL_UNION_TYPE:
case ENUMERAL_TYPE:
{
char *tag;
}
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:
{
while (syms)
{
- sdbout_symbol (syms, 1);
+ if (TREE_CODE (syms) != LABEL_DECL)
+ sdbout_symbol (syms, 1);
syms = TREE_CHAIN (syms);
}
}
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))
+ if (DECL_EXTERNAL (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);
}
/* Emit any structure, union, or enum type that has not been output.
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));
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)) != 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
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. */
{
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)))
{
register tree type = TREE_VALUE (link);
- if (! TREE_ASM_WRITTEN (type))
+ if (type && ! TREE_ASM_WRITTEN (type))
sdbout_one_type (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_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));
+ 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)
/* 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);
+ 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))
{