#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "debug.h"
#include "tree.h"
#include "ggc.h"
#include "varray.h"
static GTY(()) tree anonymous_types;
static GTY(()) int unnamed_struct_number;
static GTY(()) varray_type deferred_global_decls;
static GTY(()) tree preinit_symbols;
static GTY(()) bool sdbout_initialized;
#ifdef SDB_DEBUGGING_INFO
#include "rtl.h"
#include "regs.h"
#include "flags.h"
#include "insn-config.h"
#include "reload.h"
#include "output.h"
#include "toplev.h"
#include "tm_p.h"
#include "gsyms.h"
#include "langhooks.h"
#include "target.h"
#define PARM_PASSED_IN_MEMORY(PARM) \
(MEM_P (DECL_INCOMING_RTL (PARM)))
#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;
extern FILE *asm_out_file;
extern tree current_function_decl;
#include "sdbout.h"
static void sdbout_init (const char *);
static void sdbout_finish (const char *);
static void sdbout_start_source_file (unsigned int, const char *);
static void sdbout_end_source_file (unsigned int);
static void sdbout_begin_block (unsigned int, unsigned int);
static void sdbout_end_block (unsigned int, unsigned int);
static void sdbout_source_line (unsigned int, const char *);
static void sdbout_end_epilogue (unsigned int, const char *);
static void sdbout_global_decl (tree);
#ifndef MIPS_DEBUGGING_INFO
static void sdbout_begin_prologue (unsigned int, const char *);
#endif
static void sdbout_end_prologue (unsigned int, const char *);
static void sdbout_begin_function (tree);
static void sdbout_end_function (unsigned int);
static void sdbout_toplevel_data (tree);
static void sdbout_label (rtx);
static char *gen_fake_label (void);
static int plain_type (tree);
static int template_name_p (tree);
static void sdbout_record_type_name (tree);
static int plain_type_1 (tree, int);
static void sdbout_block (tree);
static void sdbout_syms (tree);
#ifdef SDB_ALLOW_FORWARD_REFERENCES
static void sdbout_queue_anonymous_type (tree);
static void sdbout_dequeue_anonymous_types (void);
#endif
static void sdbout_type (tree);
static void sdbout_field_types (tree);
static void sdbout_one_type (tree);
static void sdbout_parms (tree);
static void sdbout_reg_parms (tree);
static void sdbout_global_decl (tree);
#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 { \
fprintf (asm_out_file, "\t.val\t" HOST_WIDE_INT_PRINT_DEC "%s", \
(HOST_WIDE_INT) (a), 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"); \
assemble_name (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 { \
fprintf (asm_out_file, "\t.size\t" HOST_WIDE_INT_PRINT_DEC "%s", \
(HOST_WIDE_INT) (a), 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"); \
assemble_name (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
#define KNOWN_TYPE_TAG(type) TYPE_SYMTAB_POINTER (type)
#define SET_KNOWN_TYPE_TAG(TYPE, NAME) \
TYPE_SYMTAB_POINTER (TYPE) = (char *)(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 ((int) line <= sdb_begin_function_line) \
line = sdb_begin_function_line + 1
#ifdef MIPS_DEBUGGING_INFO
struct sdb_file
{
struct sdb_file *next;
const char *name;
};
static struct sdb_file *current_file;
#endif
const struct gcc_debug_hooks sdb_debug_hooks =
{
sdbout_init,
sdbout_finish,
debug_nothing_int_charstar,
debug_nothing_int_charstar,
sdbout_start_source_file,
sdbout_end_source_file,
sdbout_begin_block,
sdbout_end_block,
debug_true_tree,
sdbout_source_line,
#ifdef MIPS_DEBUGGING_INFO
debug_nothing_int_charstar,
sdbout_end_prologue,
#else
sdbout_begin_prologue,
debug_nothing_int_charstar,
#endif
sdbout_end_epilogue,
sdbout_begin_function,
sdbout_end_function,
debug_nothing_tree,
sdbout_global_decl,
sdbout_symbol,
debug_nothing_tree_tree,
debug_nothing_tree,
debug_nothing_tree,
sdbout_label,
debug_nothing_int,
debug_nothing_rtx,
0
};
static char *
gen_fake_label (void)
{
char label[10];
char *labelstr;
sprintf (label, ".%dfake", unnamed_struct_number);
unnamed_struct_number++;
labelstr = xstrdup (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 (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 (tree name)
{
const char *ptr = IDENTIFIER_POINTER (name);
while (*ptr && *ptr != '<')
ptr++;
return *ptr != '\0';
}
static void
sdbout_record_type_name (tree type)
{
const 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 (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)
{
const char *const 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 (TYPE_UNSIGNED (type) ? T_UINT : T_INT);
if (size == CHAR_TYPE_SIZE)
return (TYPE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
if (size == SHORT_TYPE_SIZE)
return (TYPE_UNSIGNED (type) ? T_USHORT : T_SHORT);
if (size == LONG_TYPE_SIZE)
return (TYPE_UNSIGNED (type) ? T_ULONG : T_LONG);
if (size == LONG_LONG_TYPE_SIZE)
return (TYPE_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_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);
}
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 void
sdbout_block (tree block)
{
while (block)
{
if (TREE_USED (block))
{
if (BLOCK_NUMBER (block) == do_block)
sdbout_syms (BLOCK_VARS (block));
if (BLOCK_NUMBER (block) > do_block)
return;
sdbout_block (BLOCK_SUBBLOCKS (block));
}
block = BLOCK_CHAIN (block);
}
}
static void
sdbout_syms (tree syms)
{
while (syms)
{
if (TREE_CODE (syms) != LABEL_DECL)
sdbout_symbol (syms, 1);
syms = TREE_CHAIN (syms);
}
}
void
sdbout_symbol (tree decl, int local)
{
tree type = TREE_TYPE (decl);
tree context = NULL_TREE;
rtx value;
int regno = -1;
const char *name;
if (!sdbout_initialized)
{
preinit_symbols = tree_cons (0, decl, preinit_symbols);
return;
}
sdbout_one_type (type);
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 (!MEM_P (DECL_RTL (decl))
|| 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 (DECL_IS_BUILTIN (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:
gcc_unreachable ();
case VAR_DECL:
if (DECL_EXTERNAL (decl))
return;
if (DECL_IGNORED_P (decl))
return;
if (!DECL_RTL_SET_P (decl))
return;
SET_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 (REG_P (value))
{
regno = REGNO (value);
if (regno >= FIRST_PSEUDO_REGISTER)
return;
}
else if (GET_CODE (value) == SUBREG)
{
while (GET_CODE (value) == SUBREG)
value = SUBREG_REG (value);
if (REG_P (value))
{
if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
return;
}
regno = REGNO (alter_subreg (&value));
SET_DECL_RTL (decl, value);
}
else if (MEM_P (value) && 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 (COMPLETE_TYPE_P (type)
&& KNOWN_TYPE_TAG (type) == 0)
sdbout_one_type (type);
}
if (! local
&& MEM_P (value)
&& DECL_INITIAL (decl))
return;
if (DECL_NAME (decl) == NULL_TREE)
return;
if (local)
name = IDENTIFIER_POINTER (DECL_NAME (decl));
else
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
if (MEM_P (value)
&& 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 (MEM_P (value)
&& (MEM_P (XEXP (value, 0))
|| (REG_P (XEXP (value, 0))
&& REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM
&& REGNO (XEXP (value, 0)) != STACK_POINTER_REGNUM)))
{
PUT_SDB_DEF (name);
if (REG_P (XEXP (value, 0)))
{
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 (MEM_P (value)
&& ((GET_CODE (XEXP (value, 0)) == PLUS
&& REG_P (XEXP (XEXP (value, 0), 0))
&& GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)
|| (REG_P (XEXP (value, 0)))))
{
PUT_SDB_DEF (name);
PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0)));
PUT_SDB_SCL (C_AUTO);
}
else
{
return;
}
break;
default:
break;
}
PUT_SDB_TYPE (plain_type (type));
PUT_SDB_ENDEF;
}
static void
sdbout_toplevel_data (tree decl)
{
tree type = TREE_TYPE (decl);
if (DECL_IGNORED_P (decl))
return;
gcc_assert (TREE_CODE (decl) == VAR_DECL);
gcc_assert (MEM_P (DECL_RTL (decl)));
gcc_assert (DECL_INITIAL (decl));
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 void
sdbout_queue_anonymous_type (tree type)
{
anonymous_types = tree_cons (NULL_TREE, type, anonymous_types);
}
static void
sdbout_dequeue_anonymous_types (void)
{
tree types, link;
while (anonymous_types)
{
types = nreverse (anonymous_types);
anonymous_types = NULL_TREE;
for (link = types; link; link = TREE_CHAIN (link))
{
tree type = TREE_VALUE (link);
if (type && ! TREE_ASM_WRITTEN (type))
sdbout_one_type (type);
}
}
}
#endif
void
sdbout_types (tree types)
{
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 (tree type)
{
if (type == error_mark_node)
type = integer_type_node;
PUT_SDB_TYPE (plain_type (type));
}
static void
sdbout_field_types (tree type)
{
tree tail;
for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
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));
}
}
static void
sdbout_one_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 (!COMPLETE_TYPE_P (type))
return;
TREE_ASM_WRITTEN (type) = 1;
if (TREE_CODE (type) != ENUMERAL_TYPE)
sdbout_field_types (type);
{
int size = int_size_in_bytes (type);
int member_scl = 0;
tree tem;
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 && TYPE_BINFO (type))
{
int i;
tree binfo, child;
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, child); 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;
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;
}
}
if (TREE_CODE (type) == ENUMERAL_TYPE)
{
for (tem = TYPE_VALUES (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
for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
if (TREE_CODE (tem) == FIELD_DECL
&& DECL_NAME (tem)
&& DECL_SIZE (tem)
&& host_integerp (DECL_SIZE (tem), 1)
&& host_integerp (bit_position (tem), 0))
{
const char *name;
name = IDENTIFIER_POINTER (DECL_NAME (tem));
PUT_SDB_DEF (name);
if (DECL_BIT_FIELD_TYPE (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_low_cst (DECL_SIZE (tem), 1));
}
else
{
PUT_SDB_INT_VAL (int_bit_position (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 (tree parms)
{
for (; parms; parms = TREE_CHAIN (parms))
if (DECL_NAME (parms))
{
int current_sym_value = 0;
const 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);
SET_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 (REG_P (DECL_RTL (parms))
&& 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 (MEM_P (DECL_RTL (parms))
&& 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 (REG_P (DECL_RTL (parms)))
{
rtx best_rtl;
if (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 (MEM_P (DECL_RTL (parms))
&& XEXP (DECL_RTL (parms), 0) != const0_rtx)
{
if (REG_P (XEXP (DECL_RTL (parms), 0))
|| MEM_P (XEXP (DECL_RTL (parms), 0)))
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 (tree parms)
{
for (; parms; parms = TREE_CHAIN (parms))
if (DECL_NAME (parms))
{
const char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
if (REG_P (DECL_RTL (parms))
&& 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 (MEM_P (DECL_RTL (parms))
&& 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;
}
}
}
}
static void
sdbout_global_decl (tree decl)
{
if (TREE_CODE (decl) == VAR_DECL
&& !DECL_EXTERNAL (decl)
&& DECL_RTL_SET_P (decl))
{
if (!DECL_INITIAL (decl) || !TREE_PUBLIC (decl))
sdbout_symbol (decl, 0);
else
VARRAY_PUSH_TREE (deferred_global_decls, decl);
if (DECL_INITIAL (decl) && MEM_P (DECL_RTL (decl)))
sdbout_toplevel_data (decl);
}
}
static void
sdbout_finish (const char *main_filename ATTRIBUTE_UNUSED)
{
size_t i;
for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_global_decls); i++)
sdbout_symbol (VARRAY_TREE (deferred_global_decls, i), 0);
}
static void
sdbout_begin_block (unsigned int line, unsigned 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)
{
do_block = BLOCK_NUMBER (DECL_INITIAL (decl));
sdbout_block (DECL_INITIAL (decl));
}
if (debug_info_level != DINFO_LEVEL_TERSE)
{
do_block = n;
sdbout_block (DECL_INITIAL (decl));
}
#ifdef SDB_ALLOW_FORWARD_REFERENCES
sdbout_dequeue_anonymous_types ();
#endif
}
static void
sdbout_end_block (unsigned int line, unsigned 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);
}
static void
sdbout_source_line (unsigned int line, const char *filename ATTRIBUTE_UNUSED)
{
if ((int) line > sdb_begin_function_line)
{
#ifdef SDB_OUTPUT_SOURCE_LINE
SDB_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
}
}
static void
sdbout_begin_function (tree decl ATTRIBUTE_UNUSED)
{
sdbout_symbol (current_function_decl, 0);
}
#ifndef MIPS_DEBUGGING_INFO
static void
sdbout_begin_prologue (unsigned int line, const char *file ATTRIBUTE_UNUSED)
{
sdbout_end_prologue (line, file);
}
#endif
static void
sdbout_end_prologue (unsigned int line, const char *file ATTRIBUTE_UNUSED)
{
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));
}
static void
sdbout_end_function (unsigned 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;
}
static void
sdbout_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
const char *file ATTRIBUTE_UNUSED)
{
const char *const name ATTRIBUTE_UNUSED
= 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
}
static void
sdbout_label (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;
}
static void
sdbout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
const char *filename ATTRIBUTE_UNUSED)
{
#ifdef MIPS_DEBUGGING_INFO
struct sdb_file *n = xmalloc (sizeof *n);
n->next = current_file;
n->name = filename;
current_file = n;
output_file_directive (asm_out_file, filename);
#endif
}
static void
sdbout_end_source_file (unsigned int line ATTRIBUTE_UNUSED)
{
#ifdef MIPS_DEBUGGING_INFO
struct sdb_file *next;
next = current_file->next;
free (current_file);
current_file = next;
output_file_directive (asm_out_file, current_file->name);
#endif
}
static void
sdbout_init (const char *input_file_name ATTRIBUTE_UNUSED)
{
tree t;
#ifdef MIPS_DEBUGGING_INFO
current_file = xmalloc (sizeof *current_file);
current_file->next = NULL;
current_file->name = input_file_name;
#endif
VARRAY_TREE_INIT (deferred_global_decls, 12, "deferred_global_decls");
sdbout_initialized = true;
for (t = nreverse (preinit_symbols); t; t = TREE_CHAIN (t))
sdbout_symbol (TREE_VALUE (t), 0);
preinit_symbols = 0;
}
#else
const struct gcc_debug_hooks sdb_debug_hooks;
#endif
#include "gt-sdbout.h"