#include "config.h"
#ifdef SDB_DEBUGGING_INFO
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "regs.h"
#include "defaults.h"
#include "flags.h"
#include "insn-config.h"
#include "reload.h"
#include "output.h"
#include "toplev.h"
#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(_WIN32) && !defined(__linux__) && !defined(__INTERIX) && !defined(CROSS_COMPILE)
#include <syms.h>
#ifndef T_VOID
#define T_VOID T_INT
#endif
#else
#include "gsyms.h"
#endif
#define PARM_PASSED_IN_MEMORY(PARM) \
(GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
#ifndef DEBUGGER_AUTO_OFFSET
#define DEBUGGER_AUTO_OFFSET(X) \
(GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
#endif
#ifndef DEBUGGER_ARG_OFFSET
#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
#endif
int sdb_begin_function_line = -1;
static int unnamed_struct_number = 0;
extern FILE *asm_out_file;
extern tree current_function_decl;
#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));
#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)
#endif
#ifndef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
#define CONTIN
#ifndef SDB_DELIM
#define SDB_DELIM ";"
#endif
#ifndef SDB_MAX_DIM
#define SDB_MAX_DIM 4
#endif
#ifndef PUT_SDB_SCL
#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\t.scl\t%d%s", (a), SDB_DELIM)
#endif
#ifndef PUT_SDB_INT_VAL
#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
#define PUT_SDB_VAL(a) \
( fputs ("\t.val\t", asm_out_file), \
output_addr_const (asm_out_file, (a)), \
fprintf (asm_out_file, SDB_DELIM))
#endif
#ifndef PUT_SDB_DEF
#define PUT_SDB_DEF(a) \
do { fprintf (asm_out_file, "\t.def\t"); \
ASM_OUTPUT_LABELREF (asm_out_file, a); \
fprintf (asm_out_file, SDB_DELIM); } while (0)
#endif
#ifndef PUT_SDB_PLAIN_DEF
#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\t.def\t.%s%s",a, SDB_DELIM)
#endif
#ifndef PUT_SDB_ENDEF
#define PUT_SDB_ENDEF fputs("\t.endef\n", asm_out_file)
#endif
#ifndef PUT_SDB_TYPE
#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%o%s", a, SDB_DELIM)
#endif
#ifndef PUT_SDB_SIZE
#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
#define PUT_SDB_START_DIM fprintf(asm_out_file, "\t.dim\t")
#endif
#ifndef PUT_SDB_NEXT_DIM
#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
#endif
#ifndef PUT_SDB_LAST_DIM
#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d%s", a, SDB_DELIM)
#endif
#ifndef PUT_SDB_TAG
#define PUT_SDB_TAG(a) \
do { fprintf (asm_out_file, "\t.tag\t"); \
ASM_OUTPUT_LABELREF (asm_out_file, a); \
fprintf (asm_out_file, SDB_DELIM); } while (0)
#endif
#ifndef PUT_SDB_BLOCK_START
#define PUT_SDB_BLOCK_START(LINE) \
fprintf (asm_out_file, \
"\t.def\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
#endif
#ifndef PUT_SDB_BLOCK_END
#define PUT_SDB_BLOCK_END(LINE) \
fprintf (asm_out_file, \
"\t.def\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
#endif
#ifndef PUT_SDB_FUNCTION_START
#define PUT_SDB_FUNCTION_START(LINE) \
fprintf (asm_out_file, \
"\t.def\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
#endif
#ifndef PUT_SDB_FUNCTION_END
#define PUT_SDB_FUNCTION_END(LINE) \
fprintf (asm_out_file, \
"\t.def\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
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));
#endif
#define KNOWN_TYPE_TAG(type) TYPE_SYMTAB_POINTER (type)
#define SET_KNOWN_TYPE_TAG(TYPE, NAME) \
TYPE_SYMTAB_POINTER (TYPE) = (NAME)
#define TAG_NAME(link) \
(((link) && TREE_PURPOSE ((link)) \
&& IDENTIFIER_POINTER (TREE_PURPOSE ((link)))) \
? IDENTIFIER_POINTER (TREE_PURPOSE ((link))) : (char *) 0)
#define MAKE_LINE_SAFE(line) \
if (line <= sdb_begin_function_line) line = sdb_begin_function_line + 1
#ifdef MIPS_DEBUGGING_INFO
#ifndef PUT_SDB_SRC_FILE
#define PUT_SDB_SRC_FILE(FILENAME) \
output_file_directive (asm_out_file, (FILENAME))
#endif
struct sdb_file
{
struct sdb_file *next;
char *name;
};
static struct sdb_file *current_file;
#endif
void
sdbout_init (asm_file, input_file_name, syms)
FILE *asm_file;
char *input_file_name;
tree syms 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 = 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
char *
tag_of_ru_type (type,link)
tree type,link;
{
if (TYPE_SYMTAB_ADDRESS (type))
return TYPE_SYMTAB_ADDRESS (type);
if (link && TREE_PURPOSE (link)
&& IDENTIFIER_POINTER (TREE_PURPOSE (link)))
TYPE_SYMTAB_ADDRESS (type) = IDENTIFIER_POINTER (TREE_PURPOSE (link));
else
return (char *) TYPE_SYMTAB_ADDRESS (type);
}
#endif
static char *
gen_fake_label ()
{
char label[10];
char *labelstr;
SDB_GENERATE_FAKE (label, unnamed_struct_number);
unnamed_struct_number++;
labelstr = (char *) permalloc (strlen (label) + 1);
strcpy (labelstr, label);
return labelstr;
}
#define PUSH_DERIVED_LEVEL(DT_type,PREV) \
((((PREV) & ~(int)N_BTMASK) << (int)N_TSHIFT) \
| ((int)DT_type << (int)N_BTSHFT) \
| ((PREV) & (int)N_BTMASK))
static int sdb_n_dims = 0;
static int sdb_dims[SDB_MAX_DIM];
static int sdb_type_size = -1;
static int
plain_type (type)
tree type;
{
int val = plain_type_1 (type, 0);
if (sdb_n_dims > 0)
{
int i;
PUT_SDB_START_DIM;
for (i = sdb_n_dims - 1; i > 0; i--)
PUT_SDB_NEXT_DIM (sdb_dims[i]);
PUT_SDB_LAST_DIM (sdb_dims[0]);
sdb_n_dims = 0;
sdb_type_size = int_size_in_bytes (type);
if (sdb_type_size < 0)
sdb_type_size = 0;
}
if (sdb_type_size >= 0)
{
PUT_SDB_SIZE (sdb_type_size);
sdb_type_size = -1;
}
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;
{
char *name = 0;
int no_name;
if (KNOWN_TYPE_TAG (type))
return;
if (TYPE_NAME (type) != 0)
{
tree t = 0;
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
t = TYPE_NAME (type);
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
{
t = DECL_NAME (TYPE_NAME (type));
if (t && template_name_p (t))
t = DECL_ASSEMBLER_NAME (TYPE_NAME (type));
}
if (t != NULL_TREE)
name = IDENTIFIER_POINTER (t);
}
no_name = (name == 0 || *name == 0);
if (no_name)
name = gen_fake_label ();
SET_KNOWN_TYPE_TAG (type, name);
#ifdef SDB_ALLOW_FORWARD_REFERENCES
if (no_name)
sdbout_queue_anonymous_type (type);
#endif
}
static int
plain_type_1 (type, level)
tree type;
int level;
{
if (type == 0)
type = void_type_node;
else if (type == error_mark_node)
type = integer_type_node;
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;
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 == LONG_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
if (size == LONG_LONG_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
return 0;
}
case REAL_TYPE:
{
int precision = TYPE_PRECISION (type);
if (precision == FLOAT_TYPE_SIZE)
return T_FLOAT;
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;
#endif
return 0;
}
case ARRAY_TYPE:
{
int m;
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)
&& 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;
#ifdef SDB_ALLOW_FORWARD_REFERENCES
sdbout_record_type_name (type);
#endif
#ifndef SDB_ALLOW_UNKNOWN_REFERENCES
if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0)
#ifdef SDB_ALLOW_FORWARD_REFERENCES
|| TYPE_MODE (type) != VOIDmode
#endif
)
#endif
{
tag = KNOWN_TYPE_TAG (type);
PUT_SDB_TAG (tag);
sdb_type_size = int_size_in_bytes (type);
if (sdb_type_size < 0)
sdb_type_size = 0;
}
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;
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;
if (level >= 6)
return T_VOID;
else
m = plain_type_1 (TREE_TYPE (type), level+1);
return PUSH_DERIVED_LEVEL (DT_FCN, m);
}
default:
return 0;
}
}
static int do_block = 0;
static int next_block_number;
static void
sdbout_block (block)
register tree block;
{
while (block)
{
if (TREE_USED (block))
{
if (next_block_number == do_block)
{
sdbout_syms (BLOCK_VARS (block));
}
if (next_block_number > do_block)
return;
next_block_number++;
sdbout_block (BLOCK_SUBBLOCKS (block));
}
block = BLOCK_CHAIN (block);
}
}
static void
sdbout_syms (syms)
tree syms;
{
while (syms)
{
if (TREE_CODE (syms) != LABEL_DECL)
sdbout_symbol (syms, 1);
syms = TREE_CHAIN (syms);
}
}
void
sdbout_symbol (decl, local)
tree decl;
int local;
{
tree type = TREE_TYPE (decl);
tree context = NULL_TREE;
rtx value;
int regno = -1;
char *name;
sdbout_one_type (type);
#if 0
if (DECL_IGNORED_P (decl))
return;
#endif
switch (TREE_CODE (decl))
{
case CONST_DECL:
return;
case FUNCTION_DECL:
context = decl_function_context (decl);
if (context == current_function_decl)
return;
if (! DECL_INITIAL (decl))
return;
if (GET_CODE (DECL_RTL (decl)) != MEM
|| GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
return;
PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
PUT_SDB_SCL (TREE_PUBLIC (decl) ? C_EXT : C_STAT);
break;
case TYPE_DECL:
if (DECL_NAME (decl) == 0)
return;
if (DECL_IGNORED_P (decl))
return;
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 PARM_DECL:
abort ();
case VAR_DECL:
if (DECL_EXTERNAL (decl))
return;
if (DECL_IGNORED_P (decl))
return;
if (DECL_RTL (decl) == 0)
return;
DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
value = DECL_RTL (decl);
if (GET_CODE (value) == REG)
{
regno = REGNO (DECL_RTL (decl));
if (regno >= FIRST_PSEUDO_REGISTER)
return;
}
else if (GET_CODE (value) == SUBREG)
{
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));
value = DECL_RTL (decl);
}
else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0))
&& ! TREE_STATIC (decl))
return;
if (TREE_CODE (type) == ENUMERAL_TYPE
|| TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
{
if (TYPE_SIZE (type) != 0
&& KNOWN_TYPE_TAG (type) == 0)
sdbout_one_type (type);
}
if (! local
&& GET_CODE (value) == MEM
&& DECL_INITIAL (decl))
return;
if (DECL_NAME (decl) == NULL_TREE)
return;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
if (GET_CODE (value) == MEM
&& GET_CODE (XEXP (value, 0)) == SYMBOL_REF)
{
PUT_SDB_DEF (name);
if (TREE_PUBLIC (decl))
{
PUT_SDB_VAL (XEXP (value, 0));
PUT_SDB_SCL (C_EXT);
}
else
{
PUT_SDB_VAL (XEXP (value, 0));
PUT_SDB_SCL (C_STAT);
}
}
else if (regno >= 0)
{
PUT_SDB_DEF (name);
PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (regno));
PUT_SDB_SCL (C_REG);
}
else if (GET_CODE (value) == MEM
&& (GET_CODE (XEXP (value, 0)) == MEM
|| (GET_CODE (XEXP (value, 0)) == REG
&& REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM
&& REGNO (XEXP (value, 0)) != STACK_POINTER_REGNUM)))
{
PUT_SDB_DEF (name);
if (GET_CODE (XEXP (value, 0)) == REG)
{
PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (XEXP (value, 0))));
PUT_SDB_SCL (C_REG);
}
else
{
PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
(XEXP (XEXP (value, 0), 0)));
PUT_SDB_SCL (C_AUTO);
}
type = make_node (POINTER_TYPE);
TREE_TYPE (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)) == REG)))
{
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)
{
PUT_SDB_DEF (name);
PUT_SDB_VAL (XEXP (XEXP (value, 0), 0));
PUT_SDB_SCL (C_STAT);
}
else
{
return;
}
break;
default:
break;
}
PUT_SDB_TYPE (plain_type (type));
PUT_SDB_ENDEF;
}
void
sdbout_toplevel_data (decl)
tree decl;
{
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)))
abort ();
PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
if (TREE_PUBLIC (decl))
{
PUT_SDB_SCL (C_EXT);
}
else
{
PUT_SDB_SCL (C_STAT);
}
PUT_SDB_TYPE (plain_type (type));
PUT_SDB_ENDEF;
}
#ifdef SDB_ALLOW_FORWARD_REFERENCES
static tree anonymous_types;
static void
sdbout_queue_anonymous_type (type)
tree type;
{
anonymous_types = saveable_tree_cons (NULL_TREE, type, anonymous_types);
}
static void
sdbout_dequeue_anonymous_types ()
{
register tree types, link;
while (anonymous_types)
{
types = nreverse (anonymous_types);
anonymous_types = NULL_TREE;
for (link = types; link; link = TREE_CHAIN (link))
{
register tree type = TREE_VALUE (link);
if (type && ! TREE_ASM_WRITTEN (type))
sdbout_one_type (type);
}
}
}
#endif
void
sdbout_types (types)
register tree types;
{
register tree link;
for (link = types; link; link = TREE_CHAIN (link))
sdbout_one_type (link);
#ifdef SDB_ALLOW_FORWARD_REFERENCES
sdbout_dequeue_anonymous_types ();
#endif
}
static void
sdbout_type (type)
tree type;
{
if (type == error_mark_node)
type = integer_type_node;
PUT_SDB_TYPE (plain_type (type));
}
static void
sdbout_field_types (type)
tree type;
{
tree tail;
for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
if (TREE_CODE (tail) == FIELD_DECL
&& DECL_NAME (tail) != 0
&& TREE_CODE (DECL_SIZE (tail)) == INTEGER_CST
&& TREE_CODE (DECL_FIELD_BITPOS (tail)) == INTEGER_CST)
{
if (POINTER_TYPE_P (TREE_TYPE (tail)))
sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
else
sdbout_one_type (TREE_TYPE (tail));
}
}
static void
sdbout_one_type (type)
tree type;
{
if (current_function_decl != NULL_TREE
&& DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
;
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);
if (TREE_ASM_WRITTEN (type))
return;
if (TYPE_SIZE (type) == 0)
return;
TREE_ASM_WRITTEN (type) = 1;
#if 1
#if 0
TREE_ASM_BEING_WRITTEN (type) = 1;
#endif
if (TREE_CODE (type) != ENUMERAL_TYPE)
sdbout_field_types (type);
#if 0
TREE_ASM_WRITTEN (type) = 1;
#endif
#endif
{
int size = int_size_in_bytes (type);
int member_scl;
tree tem;
int i, n_baseclasses = 0;
sdbout_record_type_name (type);
PUT_SDB_DEF (KNOWN_TYPE_TAG (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;
break;
case RECORD_TYPE:
PUT_SDB_SCL (C_STRTAG);
PUT_SDB_TYPE (T_STRUCT);
member_scl = C_MOS;
break;
case ENUMERAL_TYPE:
PUT_SDB_SCL (C_ENTAG);
PUT_SDB_TYPE (T_ENUM);
member_scl = C_MOE;
break;
default:
break;
}
PUT_SDB_SIZE (size);
PUT_SDB_ENDEF;
if (TREE_CODE (type) != ENUMERAL_TYPE)
{
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;
}
}
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;
}
else
for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
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)
{
char *name;
CONTIN;
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_SCL (C_FIELD);
sdbout_type (DECL_BIT_FIELD_TYPE (tem));
PUT_SDB_SIZE (TREE_INT_CST_LOW (DECL_SIZE (tem)));
}
else
{
PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem))
/ BITS_PER_UNIT);
PUT_SDB_SCL (member_scl);
sdbout_type (TREE_TYPE (tem));
}
PUT_SDB_ENDEF;
}
PUT_SDB_PLAIN_DEF ("eos");
PUT_SDB_INT_VAL (size);
PUT_SDB_SCL (C_EOS);
PUT_SDB_TAG (KNOWN_TYPE_TAG (type));
PUT_SDB_SIZE (size);
PUT_SDB_ENDEF;
break;
default:
break;
}
}
}
static void
sdbout_parms (parms)
tree parms;
{
for (; parms; parms = TREE_CHAIN (parms))
if (DECL_NAME (parms))
{
int current_sym_value = 0;
char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
if (name == 0 || *name == 0)
name = gen_fake_label ();
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))
{
rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
tree type;
if (GET_CODE (addr) == PLUS
&& GET_CODE (XEXP (addr, 1)) == CONST_INT)
current_sym_value = INTVAL (XEXP (addr, 1));
else
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
{
int original_sym_value = current_sym_value;
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))));
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))
type = TREE_TYPE (parms);
else
{
current_sym_value = original_sym_value;
type = DECL_ARG_TYPE (parms);
}
}
PUT_SDB_DEF (name);
PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, addr));
PUT_SDB_SCL (C_ARG);
PUT_SDB_TYPE (plain_type (type));
PUT_SDB_ENDEF;
}
else if (GET_CODE (DECL_RTL (parms)) == REG)
{
rtx best_rtl;
if (REGNO (DECL_RTL (parms)) >= 0
&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
best_rtl = DECL_RTL (parms);
else
best_rtl = DECL_INCOMING_RTL (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)));
PUT_SDB_ENDEF;
}
else if (GET_CODE (DECL_RTL (parms)) == MEM
&& XEXP (DECL_RTL (parms), 0) != const0_rtx)
{
if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG
|| GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)
current_sym_value = 0;
else
current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
PUT_SDB_DEF (name);
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)));
PUT_SDB_ENDEF;
}
}
}
static void
sdbout_reg_parms (parms)
tree parms;
{
for (; parms; parms = TREE_CHAIN (parms))
if (DECL_NAME (parms))
{
char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
if (GET_CODE (DECL_RTL (parms)) == REG
&& REGNO (DECL_RTL (parms)) >= 0
&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER
&& PARM_PASSED_IN_MEMORY (parms))
{
if (name == 0 || *name == 0)
name = gen_fake_label ();
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)));
PUT_SDB_ENDEF;
}
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
int offset = DECL_OFFSET (parms) / BITS_PER_UNIT;
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))));
if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...}
#endif
{
if (name == 0 || *name == 0)
name = gen_fake_label ();
PUT_SDB_DEF (name);
PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
(XEXP (DECL_RTL (parms), 0)));
PUT_SDB_SCL (C_AUTO);
PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
PUT_SDB_ENDEF;
}
}
}
}
void
sdbout_begin_block (file, line, n)
FILE *file;
int line;
int n;
{
tree decl = current_function_decl;
MAKE_LINE_SAFE (line);
#ifndef MIPS_DEBUGGING_INFO
if (n != 1)
#endif
PUT_SDB_BLOCK_START (line - sdb_begin_function_line);
if (n == 1)
{
next_block_number = 0;
do_block = 0;
sdbout_block (DECL_INITIAL (decl));
}
if (debug_info_level != DINFO_LEVEL_TERSE)
{
next_block_number = 0;
do_block = n;
sdbout_block (DECL_INITIAL (decl));
}
#ifdef SDB_ALLOW_FORWARD_REFERENCES
sdbout_dequeue_anonymous_types ();
#endif
}
void
sdbout_end_block (file, line, n)
FILE *file;
int line;
int n ATTRIBUTE_UNUSED;
{
MAKE_LINE_SAFE (line);
#ifndef MIPS_DEBUGGING_INFO
if (n != 1)
#endif
PUT_SDB_BLOCK_END (line - sdb_begin_function_line);
}
void
sdbout_mark_begin_function ()
{
sdbout_symbol (current_function_decl, 0);
}
void
sdbout_begin_function (line)
int line;
{
sdb_begin_function_line = line - 1;
PUT_SDB_FUNCTION_START (line);
sdbout_parms (DECL_ARGUMENTS (current_function_decl));
sdbout_reg_parms (DECL_ARGUMENTS (current_function_decl));
}
void
sdbout_end_function (line)
int line;
{
#ifdef SDB_ALLOW_FORWARD_REFERENCES
sdbout_dequeue_anonymous_types ();
#endif
MAKE_LINE_SAFE (line);
PUT_SDB_FUNCTION_END (line - sdb_begin_function_line);
sdb_begin_function_line = -1;
}
void
sdbout_end_epilogue ()
{
char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
PUT_SDB_EPILOGUE_END (name);
}
void
sdbout_label (insn)
register rtx insn;
{
PUT_SDB_DEF (LABEL_NAME (insn));
PUT_SDB_VAL (insn);
PUT_SDB_SCL (C_LABEL);
PUT_SDB_TYPE (T_NULL);
PUT_SDB_ENDEF;
}
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
}
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