/* Output sdb-format symbol table information from GNU compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
- Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003, 2004 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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, 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
*/
#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;
+
+/* Counter for sdbout_source_line. */
+
+static GTY(()) int sdbout_source_line_counter;
+
+/* Counter to generate unique "names" for nameless struct members. */
+
+static GTY(()) int unnamed_struct_number;
+
+/* Declarations whose debug info was deferred till end of compilation. */
+
+static GTY(()) varray_type deferred_global_decls;
+
+/* The C front end may call sdbout_symbol before sdbout_init runs.
+ We save all such decls in this list and output them when we get
+ to sdbout_init. */
+
+static GTY(()) tree preinit_symbols;
+static GTY(()) bool sdbout_initialized;
#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"
#include "tm_p.h"
-
-/* 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(__INTERIX) && !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
#include "gsyms.h"
-#endif
-
-/* #include <storclass.h> used to be this instead of syms.h. */
+#include "langhooks.h"
+#include "target.h"
/* 1 if PARM is passed to this function in memory. */
int sdb_begin_function_line = -1;
-/* Counter to generate unique "names" for nameless struct members. */
-
-static int unnamed_struct_number = 0;
extern FILE *asm_out_file;
#include "sdbout.h"
-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));
-\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
+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
-
-#ifndef DOUBLE_TYPE_SIZE
-#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
+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 LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-\f
/* Random macros describing parts of SDB data. */
-/* Put something here if lines get too long */
-#define CONTIN
-
/* Default value of delimiter is ";". */
#ifndef SDB_DELIM
#define SDB_DELIM ";"
#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); \
+ 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_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
#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); \
+ 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_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));
#endif
/* Return the sdb tag identifier string for TYPE
- if TYPE has already been defined; otherwise return a null pointer. */
+ if TYPE has already been defined; otherwise return a null pointer. */
#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_POINTER (TYPE) = (NAME)
+ TYPE_SYMTAB_POINTER (TYPE) = (char *)(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
+ if ((int) 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
struct sdb_file
{
struct sdb_file *next;
- char *name;
+ const 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. */
-void
-sdbout_init (asm_file, input_file_name, syms)
- FILE *asm_file ATTRIBUTE_UNUSED;
- char *input_file_name ATTRIBUTE_UNUSED;
- tree syms ATTRIBUTE_UNUSED;
+/* The debug hooks structure. */
+const 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
- 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
-
-/* return the tag identifier for type
- */
-
-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);
-}
+ /* 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_charstar, /* 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 */
+ sdbout_symbol, /* type_decl */
+ debug_nothing_tree_tree, /* imported_module_or_decl */
+ debug_nothing_tree, /* deferred_inline_function */
+ debug_nothing_tree, /* outlining_inline_function */
+ sdbout_label, /* label */
+ debug_nothing_int, /* handle_pch */
+ debug_nothing_rtx /* var_location */
+};
/* Return a unique string to name an anonymous type. */
static char *
-gen_fake_label ()
+gen_fake_label (void)
{
char label[10];
char *labelstr;
SDB_GENERATE_FAKE (label, unnamed_struct_number);
unnamed_struct_number++;
- labelstr = (char *) permalloc (strlen (label) + 1);
- strcpy (labelstr, label);
+ labelstr = xstrdup (label);
return labelstr;
}
-\f
+
/* Return the number which describes TYPE for SDB.
For pointers, etc., this function is recursive.
Each record, union or enumeral type must already have had a
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) & ~(int)N_BTMASK) << (int)N_TSHIFT) \
- | ((int)DT_type << (int)N_BTSHFT) \
- | ((PREV) & (int)N_BTMASK))
+ ((((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;
static int sdb_type_size = -1;
static int
-plain_type (type)
- tree type;
+plain_type (tree type)
{
int val = plain_type_1 (type, 0);
}
static int
-template_name_p (name)
- tree name;
+template_name_p (tree name)
{
- register char *ptr = IDENTIFIER_POINTER (name);
+ const char *ptr = IDENTIFIER_POINTER (name);
while (*ptr && *ptr != '<')
ptr++;
}
static void
-sdbout_record_type_name (type)
- tree type;
+sdbout_record_type_name (tree type)
{
- char *name = 0;
+ const char *name = 0;
int no_name;
if (KNOWN_TYPE_TAG (type))
if (TYPE_NAME (type) != 0)
{
tree t = 0;
+
/* Find the IDENTIFIER_NODE for the type name. */
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
t = TYPE_NAME (type);
infinite loop. */
static int
-plain_type_1 (type, level)
- tree type;
- int level;
+plain_type_1 (tree type, int level)
{
if (type == 0)
type = void_type_node;
&& 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 *const name
+ = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
if (!strcmp (name, "char"))
return T_CHAR;
return 0;
}
}
-\f
+
/* Output the symbols defined in block number DO_BLOCK.
This function works by walking the tree structure of blocks,
static int do_block = 0;
static void
-sdbout_block (block)
- register tree block;
+sdbout_block (tree block)
{
while (block)
{
block = BLOCK_CHAIN (block);
}
}
-\f
+
/* Call sdbout_symbol on each decl in the chain SYMS. */
static void
-sdbout_syms (syms)
- tree syms;
+sdbout_syms (tree syms)
{
while (syms)
{
LOCAL is nonzero if the symbol is not file-scope. */
void
-sdbout_symbol (decl, local)
- tree decl;
- int local;
+sdbout_symbol (tree decl, int local)
{
tree type = TREE_TYPE (decl);
tree context = NULL_TREE;
rtx value;
int regno = -1;
- char *name;
+ const char *name;
- sdbout_one_type (type);
+ /* If we are called before sdbout_init is run, just save the symbol
+ for later. */
+ if (!sdbout_initialized)
+ {
+ preinit_symbols = tree_cons (0, decl, preinit_symbols);
+ return;
+ }
-#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
+ sdbout_one_type (type);
switch (TREE_CODE (decl))
{
/* 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 (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (DECL_RTL (decl));
particular compilation. */
if (GET_CODE (value) == REG)
{
- regno = REGNO (DECL_RTL (decl));
+ regno = REGNO (value);
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);
- }
+ 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));
- value = DECL_RTL (decl);
+ regno = REGNO (alter_subreg (&value));
+ SET_DECL_RTL (decl, value);
}
/* Don't output anything if an auto variable
gets RTL that is static.
|| 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. */
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ 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)
if (TREE_PUBLIC (decl))
{
PUT_SDB_VAL (XEXP (value, 0));
- PUT_SDB_SCL (C_EXT);
+ PUT_SDB_SCL (C_EXT);
}
else
{
PUT_SDB_VAL (XEXP (value, 0));
- PUT_SDB_SCL (C_STAT);
+ PUT_SDB_SCL (C_STAT);
}
}
else if (regno >= 0)
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. */
PUT_SDB_TYPE (plain_type (type));
PUT_SDB_ENDEF;
}
-\f
+
/* Output SDB information for a top-level initialized variable
that has been delayed. */
-void
-sdbout_toplevel_data (decl)
- tree decl;
+static void
+sdbout_toplevel_data (tree decl)
{
tree type = TREE_TYPE (decl);
PUT_SDB_TYPE (plain_type (type));
PUT_SDB_ENDEF;
}
-\f
+
#ifdef SDB_ALLOW_FORWARD_REFERENCES
/* Machinery to record and output anonymous types. */
-static tree anonymous_types;
-
static void
-sdbout_queue_anonymous_type (type)
- tree type;
+sdbout_queue_anonymous_type (tree type)
{
- anonymous_types = saveable_tree_cons (NULL_TREE, type, anonymous_types);
+ anonymous_types = tree_cons (NULL_TREE, type, anonymous_types);
}
static void
-sdbout_dequeue_anonymous_types ()
+sdbout_dequeue_anonymous_types (void)
{
- register tree types, link;
+ tree types, link;
while (anonymous_types)
{
for (link = types; link; link = TREE_CHAIN (link))
{
- register tree type = TREE_VALUE (link);
+ tree type = TREE_VALUE (link);
if (type && ! TREE_ASM_WRITTEN (type))
sdbout_one_type (type);
}
#endif
-\f
+
/* Given a chain of ..._TYPE nodes, all of which have names,
output definitions of those names, as typedefs. */
void
-sdbout_types (types)
- register tree types;
+sdbout_types (tree types)
{
- register tree link;
+ tree link;
for (link = types; link; link = TREE_CHAIN (link))
sdbout_one_type (link);
}
static void
-sdbout_type (type)
- tree type;
+sdbout_type (tree type)
{
if (type == error_mark_node)
type = integer_type_node;
Now james@bigtex.cactus.org says to try them. */
static void
-sdbout_field_types (type)
- tree type;
+sdbout_field_types (tree type)
{
tree tail;
for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
- /* This condition should match the one for emitting the actual members
- below. */
+ /* This condition should match the one for emitting the actual
+ members below. */
if (TREE_CODE (tail) == FIELD_DECL
- && DECL_NAME (tail) != 0
- && ! host_integerp (DECL_SIZE (tail), 1)
- && ! host_integerp (bit_position (tail), 0))
+ && 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)));
It may NOT be called recursively. */
static void
-sdbout_one_type (type)
- tree type;
+sdbout_one_type (tree type)
{
if (current_function_decl != NULL_TREE
&& DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
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;
-#if 1
+
/* This is reputed to cause trouble with the following case,
but perhaps checking TYPE_SIZE above will fix it. */
- /* Here is a test case:
+ /* Here is a testcase:
struct foo {
struct badstr *bbb;
int ccccc;
} badtype; */
-#if 0
- TREE_ASM_BEING_WRITTEN (type) = 1;
-#endif
/* This change, which ought to make better output,
used to make the COFF assembler unhappy.
Changes involving KNOWN_TYPE_TAG may fix the problem. */
are not used if forward references are in use. */
if (TREE_CODE (type) != ENUMERAL_TYPE)
sdbout_field_types (type);
-#if 0
- TREE_ASM_WRITTEN (type) = 1;
-#endif
-#endif
/* Output a structure type. */
{
/* Print out the base class information with fields
named after the types they hold. */
- /* This is only relevent to aggregate types. TYPE_BINFO is used
+ /* This is only relevant 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)
else
continue;
- 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);
}
}
- /* output the individual fields */
+ /* Output the individual fields. */
if (TREE_CODE (type) == ENUMERAL_TYPE)
{
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
+ && DECL_NAME (tem)
+ && DECL_SIZE (tem)
&& host_integerp (DECL_SIZE (tem), 1)
&& host_integerp (bit_position (tem), 0))
{
- char *name;
+ const char *name;
- CONTIN;
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem));
+ name = IDENTIFIER_POINTER (DECL_NAME (tem));
PUT_SDB_DEF (name);
if (DECL_BIT_FIELD_TYPE (tem))
{
}
PUT_SDB_ENDEF;
}
- /* output end of a structure,union, or enumeral definition */
+ /* Output end of a structure,union, or enumeral definition. */
PUT_SDB_PLAIN_DEF ("eos");
PUT_SDB_INT_VAL (size);
}
}
}
-\f
+
/* The following two functions output definitions of function parameters.
Each parameter gets a definition locating it in the parameter list.
Each parameter that is a register variable gets a second definition
of all the parms in PARMS, which is a chain of PARM_DECL nodes. */
static void
-sdbout_parms (parms)
- tree parms;
+sdbout_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));
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
if (name == 0 || *name == 0)
name = gen_fake_label ();
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);
+ 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. */
PARMS is a chain of PARM_DECL nodes. */
static void
-sdbout_reg_parms (parms)
- tree parms;
+sdbout_reg_parms (tree parms)
{
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))
{
}
}
}
-\f
+
+/* Output debug information for a global DECL. Called from toplev.c
+ after compilation proper has finished. */
+
+static void
+sdbout_global_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);
+ else
+ VARRAY_PUSH_TREE (deferred_global_decls, decl);
+
+ /* 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 (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);
+
+ VARRAY_FREE (deferred_global_decls);
+}
+
/* 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 ATTRIBUTE_UNUSED;
- int line;
- int n;
+static void
+sdbout_begin_block (unsigned int line, unsigned int n)
{
tree decl = current_function_decl;
MAKE_LINE_SAFE (line);
/* Describe the end line-number of an internal block within a function. */
-void
-sdbout_end_block (file, line, n)
- FILE *file ATTRIBUTE_UNUSED;
- int line;
- int n ATTRIBUTE_UNUSED;
+static void
+sdbout_end_block (unsigned int line, unsigned int n ATTRIBUTE_UNUSED)
{
MAKE_LINE_SAFE (line);
PUT_SDB_BLOCK_END (line - sdb_begin_function_line);
}
+/* Output a line number symbol entry for source file FILENAME and line
+ number LINE. */
+
+static void
+sdbout_source_line (unsigned int line, const char *filename ATTRIBUTE_UNUSED)
+{
+ /* COFF relative line numbers must be positive. */
+ if ((int) line > sdb_begin_function_line)
+ {
+#ifdef ASM_OUTPUT_SOURCE_LINE
+ sdbout_source_line_counter += 1;
+ ASM_OUTPUT_SOURCE_LINE (asm_out_file, line, sdbout_source_line_counter);
+#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 (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 (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);
/* Called at end of function (before epilogue).
Describe end of outermost block. */
-void
-sdbout_end_function (line)
- int line;
+static void
+sdbout_end_function (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
-sdbout_end_epilogue ()
+static void
+sdbout_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
+ const char *file ATTRIBUTE_UNUSED)
{
- char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
+ 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
}
/* Output sdb info for the given label. Called only if LABEL_NAME (insn)
is present. */
-void
-sdbout_label (insn)
- register rtx insn;
+static void
+sdbout_label (rtx insn)
{
PUT_SDB_DEF (LABEL_NAME (insn));
PUT_SDB_VAL (insn);
/* Change to reading from a new source file. */
-void
-sdbout_start_new_source_file (filename)
- char *filename ATTRIBUTE_UNUSED;
+static void
+sdbout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
+ const char *filename ATTRIBUTE_UNUSED)
{
#ifdef MIPS_DEBUGGING_INFO
- struct sdb_file *n = (struct sdb_file *) xmalloc (sizeof *n);
+ struct sdb_file *n = xmalloc (sizeof *n);
n->next = current_file;
n->name = filename;
/* Revert to reading a previous source file. */
-void
-sdbout_resume_previous_source_file ()
+static void
+sdbout_end_source_file (unsigned int line ATTRIBUTE_UNUSED)
{
#ifdef MIPS_DEBUGGING_INFO
struct sdb_file *next;
#endif
}
+/* Set up for SDB output at the start of compilation. */
+
+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");
+
+ /* Emit debug information which was queued by sdbout_symbol before
+ we got here. */
+ sdbout_initialized = true;
+
+ for (t = nreverse (preinit_symbols); t; t = TREE_CHAIN (t))
+ sdbout_symbol (TREE_VALUE (t), 0);
+ preinit_symbols = 0;
+}
+
+#else /* SDB_DEBUGGING_INFO */
+
+/* This should never be used, but its address is needed for comparisons. */
+const struct gcc_debug_hooks sdb_debug_hooks;
+
#endif /* SDB_DEBUGGING_INFO */
+
+#include "gt-sdbout.h"