X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fsdbout.c;h=87a00b4a61e1a102e279e4578b3dd9c383576acb;hb=5dee2817fd4f8b8c16c7a8ee0acf43eb3af48fc7;hp=8405c0a8f29d1422fc90e73ec6aed864b1f5af7f;hpb=47c251e561cd22357a6f18c9c210ed29abbbedc9;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/sdbout.c b/gcc/sdbout.c index 8405c0a8f29..87a00b4a61e 100644 --- a/gcc/sdbout.c +++ b/gcc/sdbout.c @@ -1,12 +1,13 @@ /* Output sdb-format symbol table information from GNU compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 + Free Software Foundation, Inc. This file is part of GCC. 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 +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,9 +16,8 @@ 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 GCC; 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 COPYING3. If not see +. */ /* mike@tredysvr.Tredydev.Unisys.COM says: I modified the struct.c example and have a nm of a .o resulting from the @@ -42,11 +42,33 @@ AT&T C compiler. From the example below I would conclude the following: */ #include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "debug.h" +#include "tree.h" +#include "ggc.h" +#include "vec.h" + +static GTY(()) tree anonymous_types; + +/* 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(()) VEC(tree,gc) *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 "flags.h" @@ -54,15 +76,15 @@ AT&T C compiler. From the example below I would conclude the following: #include "reload.h" #include "output.h" #include "toplev.h" -#include "ggc.h" #include "tm_p.h" #include "gsyms.h" -#include "debug.h" +#include "langhooks.h" +#include "target.h" /* 1 if PARM is passed to this function in memory. */ #define PARM_PASSED_IN_MEMORY(PARM) \ - (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM) + (MEM_P (DECL_INCOMING_RTL (PARM))) /* A C expression for the integer offset value of an automatic variable (C_AUTO) having address X (an RTX). */ @@ -82,9 +104,6 @@ AT&T C compiler. From the example below I would conclude the following: 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; @@ -92,45 +111,42 @@ extern tree current_function_decl; #include "sdbout.h" -static void sdbout_init PARAMS ((const char *)); -static void sdbout_finish PARAMS ((const char *)); -static void sdbout_start_source_file PARAMS ((unsigned int, const char *)); -static void sdbout_end_source_file PARAMS ((unsigned int)); -static void sdbout_begin_block PARAMS ((unsigned int, unsigned int)); -static void sdbout_end_block PARAMS ((unsigned int, unsigned int)); -static void sdbout_source_line PARAMS ((unsigned int, const char *)); -static void sdbout_end_epilogue PARAMS ((void)); -static void sdbout_global_decl PARAMS ((tree)); +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 *, int, bool); +static void sdbout_end_epilogue (unsigned int, const char *); +static void sdbout_global_decl (tree); #ifndef MIPS_DEBUGGING_INFO -static void sdbout_begin_prologue PARAMS ((unsigned int, const char *)); +static void sdbout_begin_prologue (unsigned int, const char *); #endif -static void sdbout_end_prologue PARAMS ((unsigned int)); -static void sdbout_begin_function PARAMS ((tree)); -static void sdbout_end_function PARAMS ((unsigned int)); -static void sdbout_toplevel_data PARAMS ((tree)); -static void sdbout_label PARAMS ((rtx)); -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)); +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 PARAMS ((tree)); -static void sdbout_dequeue_anonymous_types PARAMS ((void)); +static void sdbout_queue_anonymous_type (tree); +static void sdbout_dequeue_anonymous_types (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)); -static void sdbout_global_decl PARAMS ((tree)); - -/* Random macros describing parts of SDB data. */ +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); -/* Put something here if lines get too long */ -#define CONTIN +/* Random macros describing parts of SDB data. */ /* Default value of delimiter is ";". */ #ifndef SDB_DELIM @@ -149,9 +165,8 @@ static void sdbout_global_decl PARAMS ((tree)); #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 @@ -166,7 +181,7 @@ static void sdbout_global_decl PARAMS ((tree)); #ifndef PUT_SDB_DEF #define PUT_SDB_DEF(a) \ do { fprintf (asm_out_file, "\t.def\t"); \ - assemble_name (asm_out_file, a); \ + assemble_name (asm_out_file, a); \ fprintf (asm_out_file, SDB_DELIM); } while (0) #endif @@ -185,9 +200,8 @@ do { fprintf (asm_out_file, "\t.def\t"); \ #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 @@ -238,11 +252,6 @@ do { fprintf (asm_out_file, "\t.tag\t"); \ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) #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. */ @@ -251,7 +260,7 @@ do { fprintf (asm_out_file, "\t.tag\t"); \ /* 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) = (const 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. */ @@ -274,11 +283,6 @@ do { fprintf (asm_out_file, "\t.tag\t"); \ #ifdef MIPS_DEBUGGING_INFO -#ifndef PUT_SDB_SRC_FILE -#define PUT_SDB_SRC_FILE(FILENAME) \ -output_file_directive (asm_out_file, (FILENAME)) -#endif - /* ECOFF linkers have an optimization that does the same kind of thing as N_BINCL/E_INCL in stabs: eliminate duplicate debug information in the executable. To achieve this, GCC must output a .file for each file @@ -297,72 +301,64 @@ struct sdb_file static struct sdb_file *current_file; #endif /* MIPS_DEBUGGING_INFO */ - + /* The debug hooks structure. */ -struct gcc_debug_hooks sdb_debug_hooks = +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 */ + sdbout_init, /* init */ + sdbout_finish, /* finish */ + debug_nothing_void, /* assembly_start */ + 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_const_tree, /* ignore_block */ + sdbout_source_line, /* source_line */ #ifdef MIPS_DEBUGGING_INFO /* Defer on MIPS systems so that parameter descriptions follow function entry. */ - debug_nothing_int_charstar, /* begin_prologue */ - sdbout_end_prologue, /* end_prologue */ + debug_nothing_int_charstar, /* begin_prologue */ + sdbout_end_prologue, /* end_prologue */ #else - sdbout_begin_prologue, /* begin_prologue */ - debug_nothing_int, /* end_prologue */ + 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 */ - debug_nothing_tree, /* deferred_inline_function */ - debug_nothing_tree, /* outlining_inline_function */ - sdbout_label + 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_tree_bool, /* 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 */ + debug_nothing_void, /* switch_text_section */ + debug_nothing_tree, /* direct_call */ + debug_nothing_tree_int, /* virtual_call_token */ + debug_nothing_rtx_rtx, /* copy_call_info */ + debug_nothing_uid, /* virtual_call */ + debug_nothing_tree_tree, /* set_name */ + 0 /* start_end_main_source_file */ }; - -#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); -} -#endif /* 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); + sprintf (label, ".%dfake", unnamed_struct_number); unnamed_struct_number++; - labelstr = (char *) permalloc (strlen (label) + 1); - strcpy (labelstr, label); + labelstr = xstrdup (label); return labelstr; } - + /* 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 @@ -395,8 +391,7 @@ static int sdb_dims[SDB_MAX_DIM]; static int sdb_type_size = -1; static int -plain_type (type) - tree type; +plain_type (tree type) { int val = plain_type_1 (type, 0); @@ -426,8 +421,7 @@ plain_type (type) } static int -template_name_p (name) - tree name; +template_name_p (tree name) { const char *ptr = IDENTIFIER_POINTER (name); while (*ptr && *ptr != '<') @@ -437,8 +431,7 @@ template_name_p (name) } static void -sdbout_record_type_name (type) - tree type; +sdbout_record_type_name (tree type) { const char *name = 0; int no_name; @@ -488,9 +481,7 @@ sdbout_record_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; @@ -541,15 +532,15 @@ plain_type_1 (type, level) } if (size == INT_TYPE_SIZE) - return (TREE_UNSIGNED (type) ? T_UINT : T_INT); + return (TYPE_UNSIGNED (type) ? T_UINT : T_INT); if (size == CHAR_TYPE_SIZE) - return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR); + return (TYPE_UNSIGNED (type) ? T_UCHAR : T_CHAR); if (size == SHORT_TYPE_SIZE) - return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT); + return (TYPE_UNSIGNED (type) ? T_USHORT : T_SHORT); if (size == LONG_TYPE_SIZE) - return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG); + return (TYPE_UNSIGNED (type) ? T_ULONG : T_LONG); if (size == LONG_LONG_TYPE_SIZE) /* better than nothing */ - return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG); + return (TYPE_UNSIGNED (type) ? T_ULONG : T_LONG); return 0; } @@ -596,7 +587,7 @@ plain_type_1 (type, level) case QUAL_UNION_TYPE: case ENUMERAL_TYPE: { - char *tag; + const char *tag; #ifdef SDB_ALLOW_FORWARD_REFERENCES sdbout_record_type_name (type); #endif @@ -652,7 +643,7 @@ plain_type_1 (type, level) return 0; } } - + /* Output the symbols defined in block number DO_BLOCK. This function works by walking the tree structure of blocks, @@ -661,8 +652,7 @@ plain_type_1 (type, level) static int do_block = 0; static void -sdbout_block (block) - tree block; +sdbout_block (tree block) { while (block) { @@ -684,12 +674,11 @@ sdbout_block (block) block = BLOCK_CHAIN (block); } } - + /* Call sdbout_symbol on each decl in the chain SYMS. */ static void -sdbout_syms (syms) - tree syms; +sdbout_syms (tree syms) { while (syms) { @@ -703,9 +692,7 @@ sdbout_syms (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; @@ -713,13 +700,15 @@ sdbout_symbol (decl, local) int regno = -1; 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)) { @@ -737,7 +726,7 @@ sdbout_symbol (decl, local) a DECL_INITIAL value of 0. */ if (! DECL_INITIAL (decl)) return; - if (GET_CODE (DECL_RTL (decl)) != MEM + 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))); @@ -751,6 +740,11 @@ sdbout_symbol (decl, local) return; if (DECL_IGNORED_P (decl)) return; + /* Don't output intrinsic types. GAS chokes on SDB .def + statements that contain identifiers with embedded spaces + (eg "unsigned long"). */ + if (DECL_IS_BUILTIN (decl)) + return; /* Output typedef name. */ if (template_name_p (DECL_NAME (decl))) @@ -763,7 +757,7 @@ sdbout_symbol (decl, local) case PARM_DECL: /* Parm decls go in their own separate chains and are output by sdbout_reg_parms and sdbout_parms. */ - abort (); + gcc_unreachable (); case VAR_DECL: /* Don't mention a variable that is external. @@ -781,8 +775,8 @@ sdbout_symbol (decl, local) if (!DECL_RTL_SET_P (decl)) return; - SET_DECL_RTL (decl, - eliminate_regs (DECL_RTL (decl), 0, NULL_RTX)); + SET_DECL_RTL (decl, + eliminate_regs (DECL_RTL (decl), VOIDmode, NULL_RTX)); #ifdef LEAF_REG_REMAP if (current_function_uses_only_leaf_regs) leaf_renumber_regs_insn (DECL_RTL (decl)); @@ -795,7 +789,7 @@ sdbout_symbol (decl, local) If DECL was from an inline function, then its rtl is not identically the rtl that was used in this particular compilation. */ - if (GET_CODE (value) == REG) + if (REG_P (value)) { regno = REGNO (value); if (regno >= FIRST_PSEUDO_REGISTER) @@ -805,7 +799,7 @@ sdbout_symbol (decl, local) { while (GET_CODE (value) == SUBREG) value = SUBREG_REG (value); - if (GET_CODE (value) == REG) + if (REG_P (value)) { if (REGNO (value) >= FIRST_PSEUDO_REGISTER) return; @@ -816,7 +810,7 @@ sdbout_symbol (decl, local) /* Don't output anything if an auto variable gets RTL that is static. GAS version 2.2 can't handle such output. */ - else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0)) + else if (MEM_P (value) && CONSTANT_P (XEXP (value, 0)) && ! TREE_STATIC (decl)) return; @@ -835,7 +829,7 @@ sdbout_symbol (decl, local) /* Defer SDB information for top-level initialized variables! */ if (! local - && GET_CODE (value) == MEM + && MEM_P (value) && DECL_INITIAL (decl)) return; @@ -850,19 +844,19 @@ sdbout_symbol (decl, local) else name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - if (GET_CODE (value) == MEM + 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); + 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) @@ -871,9 +865,9 @@ sdbout_symbol (decl, local) 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 + 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))) /* If the value is indirect by memory or by a register @@ -883,7 +877,7 @@ sdbout_symbol (decl, local) so all we can do is output the variable as a pointer. */ { PUT_SDB_DEF (name); - if (GET_CODE (XEXP (value, 0)) == REG) + if (REG_P (XEXP (value, 0))) { PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (XEXP (value, 0)))); PUT_SDB_SCL (C_REG); @@ -906,14 +900,14 @@ sdbout_symbol (decl, local) type = make_node (POINTER_TYPE); TREE_TYPE (type) = TREE_TYPE (decl); } - else if (GET_CODE (value) == MEM + else if (MEM_P (value) && ((GET_CODE (XEXP (value, 0)) == PLUS - && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG - && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT) + && REG_P (XEXP (XEXP (value, 0), 0)) + && CONST_INT_P (XEXP (XEXP (value, 0), 1))) /* This is for variables which are at offset zero from the frame pointer. This happens on the Alpha. Non-frame pointer registers are excluded above. */ - || (GET_CODE (XEXP (value, 0)) == REG))) + || (REG_P (XEXP (value, 0))))) { /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))) or (MEM (REG...)). We want the value of that CONST_INT @@ -922,23 +916,6 @@ sdbout_symbol (decl, local) 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. */ @@ -952,23 +929,21 @@ sdbout_symbol (decl, local) PUT_SDB_TYPE (plain_type (type)); PUT_SDB_ENDEF; } - + /* Output SDB information for a top-level initialized variable that has been delayed. */ static void -sdbout_toplevel_data (decl) - tree decl; +sdbout_toplevel_data (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 (); + 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)); @@ -983,22 +958,19 @@ sdbout_toplevel_data (decl) PUT_SDB_TYPE (plain_type (type)); PUT_SDB_ENDEF; } - + #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 = tree_cons (NULL_TREE, type, anonymous_types); } static void -sdbout_dequeue_anonymous_types () +sdbout_dequeue_anonymous_types (void) { tree types, link; @@ -1018,13 +990,12 @@ sdbout_dequeue_anonymous_types () } #endif - + /* Given a chain of ..._TYPE nodes, all of which have names, output definitions of those names, as typedefs. */ void -sdbout_types (types) - tree types; +sdbout_types (tree types) { tree link; @@ -1037,8 +1008,7 @@ sdbout_types (types) } static void -sdbout_type (type) - tree type; +sdbout_type (tree type) { if (type == error_mark_node) type = integer_type_node; @@ -1052,8 +1022,7 @@ sdbout_type (type) Now james@bigtex.cactus.org says to try them. */ static void -sdbout_field_types (type) - tree type; +sdbout_field_types (tree type) { tree tail; @@ -1081,14 +1050,13 @@ sdbout_field_types (type) 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) ; /* Don't change section amid function. */ else - text_section (); + switch_to_section (text_section); switch (TREE_CODE (type)) { @@ -1107,11 +1075,11 @@ sdbout_one_type (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; @@ -1125,9 +1093,6 @@ sdbout_one_type (type) 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. */ @@ -1136,17 +1101,12 @@ sdbout_one_type (type) 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. */ { int size = int_size_in_bytes (type); int member_scl = 0; tree tem; - int i, n_baseclasses = 0; /* Record the type tag, but not in its permanent place just yet. */ sdbout_record_type_name (type); @@ -1186,17 +1146,17 @@ sdbout_one_type (type) /* 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) + if (TREE_CODE (type) != ENUMERAL_TYPE && TYPE_BINFO (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++) + int i; + tree binfo, child; + + for (binfo = TYPE_BINFO (type), i = 0; + BINFO_BASE_ITERATE (binfo, i, child); 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) @@ -1211,7 +1171,6 @@ sdbout_one_type (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); @@ -1220,19 +1179,26 @@ sdbout_one_type (type) } } - /* output the individual fields */ + /* Output the individual fields. */ if (TREE_CODE (type) == ENUMERAL_TYPE) { - for (tem = TYPE_FIELDS (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; - } + for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) + { + tree value = TREE_VALUE (tem); + + if (TREE_CODE (value) == CONST_DECL) + value = DECL_INITIAL (value); + + if (host_integerp (value, 0)) + { + PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem))); + PUT_SDB_INT_VAL (tree_low_cst (value, 0)); + PUT_SDB_SCL (C_MOE); + PUT_SDB_TYPE (T_MOE); + PUT_SDB_ENDEF; + } + } } else /* record or union type */ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) @@ -1250,7 +1216,6 @@ sdbout_one_type (type) { const char *name; - CONTIN; name = IDENTIFIER_POINTER (DECL_NAME (tem)); PUT_SDB_DEF (name); if (DECL_BIT_FIELD_TYPE (tem)) @@ -1268,7 +1233,7 @@ sdbout_one_type (type) } 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); @@ -1277,13 +1242,13 @@ sdbout_one_type (type) PUT_SDB_SIZE (size); PUT_SDB_ENDEF; break; - - default: - break; } + + default: + break; } } - + /* 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 @@ -1297,8 +1262,7 @@ sdbout_one_type (type) 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)) @@ -1312,9 +1276,9 @@ sdbout_parms (parms) /* 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, NULL_RTX); + = eliminate_regs (DECL_INCOMING_RTL (parms), VOIDmode, NULL_RTX); SET_DECL_RTL (parms, - eliminate_regs (DECL_RTL (parms), 0, NULL_RTX)); + eliminate_regs (DECL_RTL (parms), VOIDmode, NULL_RTX)); if (PARM_PASSED_IN_MEMORY (parms)) { @@ -1326,12 +1290,12 @@ sdbout_parms (parms) If that is not true, we produce meaningless results, but do not crash. */ if (GET_CODE (addr) == PLUS - && GET_CODE (XEXP (addr, 1)) == CONST_INT) + && CONST_INT_P (XEXP (addr, 1))) current_sym_value = INTVAL (XEXP (addr, 1)); else current_sym_value = 0; - if (GET_CODE (DECL_RTL (parms)) == REG + if (REG_P (DECL_RTL (parms)) && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) type = DECL_ARG_TYPE (parms); else @@ -1350,7 +1314,7 @@ sdbout_parms (parms) (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))); - if (GET_CODE (DECL_RTL (parms)) == MEM + 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) @@ -1370,7 +1334,7 @@ sdbout_parms (parms) PUT_SDB_TYPE (plain_type (type)); PUT_SDB_ENDEF; } - else if (GET_CODE (DECL_RTL (parms)) == REG) + else if (REG_P (DECL_RTL (parms))) { rtx best_rtl; /* Parm passed in registers and lives in registers or nowhere. */ @@ -1392,7 +1356,7 @@ sdbout_parms (parms) PUT_SDB_TYPE (plain_type (TREE_TYPE (parms))); PUT_SDB_ENDEF; } - else if (GET_CODE (DECL_RTL (parms)) == MEM + else if (MEM_P (DECL_RTL (parms)) && XEXP (DECL_RTL (parms), 0) != const0_rtx) { /* Parm was passed in registers but lives on the stack. */ @@ -1401,8 +1365,8 @@ sdbout_parms (parms) in which case we want the value of that CONST_INT, or (MEM (REG ...)) or (MEM (MEM ...)), in which case we use a value of zero. */ - if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG - || GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM) + 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)); @@ -1430,8 +1394,7 @@ sdbout_parms (parms) 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)) @@ -1440,7 +1403,7 @@ sdbout_reg_parms (parms) /* Report parms that live in registers during the function but were passed in memory. */ - if (GET_CODE (DECL_RTL (parms)) == REG + if (REG_P (DECL_RTL (parms)) && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER && PARM_PASSED_IN_MEMORY (parms)) { @@ -1453,9 +1416,9 @@ sdbout_reg_parms (parms) PUT_SDB_ENDEF; } /* Report parms that live in memory but not where they were passed. */ - else if (GET_CODE (DECL_RTL (parms)) == MEM + 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 + && CONST_INT_P (XEXP (XEXP (DECL_RTL (parms), 0), 1)) && PARM_PASSED_IN_MEMORY (parms) && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms))) { @@ -1484,13 +1447,12 @@ sdbout_reg_parms (parms) } } } - + /* Output debug information for a global DECL. Called from toplev.c after compilation proper has finished. */ static void -sdbout_global_decl (decl) - tree decl; +sdbout_global_decl (tree decl) { if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl) @@ -1501,10 +1463,12 @@ sdbout_global_decl (decl) sdbout_finish (). */ if (!DECL_INITIAL (decl) || !TREE_PUBLIC (decl)) sdbout_symbol (decl, 0); + else + VEC_safe_push (tree, gc, deferred_global_decls, decl); /* Output COFF information for non-global file-scope initialized variables. */ - if (DECL_INITIAL (decl) && GET_CODE (DECL_RTL (decl)) == MEM) + if (DECL_INITIAL (decl) && MEM_P (DECL_RTL (decl))) sdbout_toplevel_data (decl); } } @@ -1513,34 +1477,15 @@ sdbout_global_decl (decl) definition. See comment in sdbout_global_decl. */ static void -sdbout_finish (main_filename) - const char *main_filename ATTRIBUTE_UNUSED; +sdbout_finish (const char *main_filename ATTRIBUTE_UNUSED) { - tree decl = getdecls (); - unsigned int len = list_length (decl); - tree *vec = (tree *) xmalloc (sizeof (tree) * len); - unsigned int i; - - /* Process the decls in reverse order--earliest first. Put them - into VEC from back to front, then take out from front. */ - - for (i = 0; i < len; i++, decl = TREE_CHAIN (decl)) - vec[len - i - 1] = decl; - - for (i = 0; i < len; i++) - { - decl = vec[i]; - if (TREE_CODE (decl) == VAR_DECL - && ! DECL_EXTERNAL (decl) - && DECL_INITIAL (decl) - && TREE_PUBLIC (decl) - && DECL_RTL_SET_P (decl)) - sdbout_symbol (decl, 0); - } + size_t i; + tree decl; - free (vec); + for (i = 0; VEC_iterate (tree, deferred_global_decls, i, decl); i++) + sdbout_symbol (decl, 0); } - + /* Describe the beginning of an internal block within a function. Also output descriptions of variables defined in this block. @@ -1550,9 +1495,7 @@ sdbout_finish (main_filename) if the count starts at 0 for the outermost one. */ static void -sdbout_begin_block (line, n) - unsigned int line; - unsigned int n; +sdbout_begin_block (unsigned int line, unsigned int n) { tree decl = current_function_decl; MAKE_LINE_SAFE (line); @@ -1587,9 +1530,7 @@ sdbout_begin_block (line, n) /* Describe the end line-number of an internal block within a function. */ static void -sdbout_end_block (line, n) - unsigned int line; - unsigned int n ATTRIBUTE_UNUSED; +sdbout_end_block (unsigned int line, unsigned int n ATTRIBUTE_UNUSED) { MAKE_LINE_SAFE (line); @@ -1602,16 +1543,19 @@ sdbout_end_block (line, n) 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 (line, filename) - unsigned int line; - const char *filename ATTRIBUTE_UNUSED; +sdbout_source_line (unsigned int line, const char *filename ATTRIBUTE_UNUSED, + int discriminator ATTRIBUTE_UNUSED, + bool is_stmt ATTRIBUTE_UNUSED) { /* COFF relative line numbers must be positive. */ if ((int) line > sdb_begin_function_line) { -#ifdef ASM_OUTPUT_SOURCE_LINE - ASM_OUTPUT_SOURCE_LINE (asm_out_file, 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) @@ -1624,8 +1568,7 @@ sdbout_source_line (line, filename) Called from assemble_start_function. */ static void -sdbout_begin_function (decl) - tree decl ATTRIBUTE_UNUSED; +sdbout_begin_function (tree decl ATTRIBUTE_UNUSED) { sdbout_symbol (current_function_decl, 0); } @@ -1638,17 +1581,14 @@ sdbout_begin_function (decl) #ifndef MIPS_DEBUGGING_INFO static void -sdbout_begin_prologue (line, file) - unsigned int line; - const char *file ATTRIBUTE_UNUSED; +sdbout_begin_prologue (unsigned int line, const char *file ATTRIBUTE_UNUSED) { - sdbout_end_prologue (line); + sdbout_end_prologue (line, file); } #endif static void -sdbout_end_prologue (line) - unsigned int line; +sdbout_end_prologue (unsigned int line, const char *file ATTRIBUTE_UNUSED) { sdb_begin_function_line = line - 1; PUT_SDB_FUNCTION_START (line); @@ -1660,8 +1600,7 @@ sdbout_end_prologue (line) Describe end of outermost block. */ static void -sdbout_end_function (line) - unsigned int line; +sdbout_end_function (unsigned int line) { #ifdef SDB_ALLOW_FORWARD_REFERENCES sdbout_dequeue_anonymous_types (); @@ -1678,7 +1617,8 @@ sdbout_end_function (line) Called after the epilogue is output. */ static void -sdbout_end_epilogue () +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)); @@ -1697,8 +1637,7 @@ sdbout_end_epilogue () is present. */ static void -sdbout_label (insn) - rtx insn; +sdbout_label (rtx insn) { PUT_SDB_DEF (LABEL_NAME (insn)); PUT_SDB_VAL (insn); @@ -1710,25 +1649,23 @@ sdbout_label (insn) /* Change to reading from a new source file. */ static void -sdbout_start_source_file (line, filename) - unsigned int line ATTRIBUTE_UNUSED; - const char *filename ATTRIBUTE_UNUSED; +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 = XNEW (struct sdb_file); n->next = current_file; n->name = filename; current_file = n; - PUT_SDB_SRC_FILE (filename); + output_file_directive (asm_out_file, filename); #endif } /* Revert to reading a previous source file. */ static void -sdbout_end_source_file (line) - unsigned int line ATTRIBUTE_UNUSED; +sdbout_end_source_file (unsigned int line ATTRIBUTE_UNUSED) { #ifdef MIPS_DEBUGGING_INFO struct sdb_file *next; @@ -1736,33 +1673,74 @@ sdbout_end_source_file (line) next = current_file->next; free (current_file); current_file = next; - PUT_SDB_SRC_FILE (current_file->name); + output_file_directive (asm_out_file, current_file->name); #endif } /* Set up for SDB output at the start of compilation. */ static void -sdbout_init (input_file_name) - const char *input_file_name ATTRIBUTE_UNUSED; +sdbout_init (const char *input_file_name ATTRIBUTE_UNUSED) { + tree t; + #ifdef MIPS_DEBUGGING_INFO - current_file = (struct sdb_file *) xmalloc (sizeof *current_file); + current_file = XNEW (struct sdb_file); current_file->next = NULL; current_file->name = input_file_name; #endif -#ifdef RMS_QUICK_HACK_1 - tree t; - for (t = getdecls (); 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 + deferred_global_decls = VEC_alloc (tree, gc, 12); -#ifdef SDB_ALLOW_FORWARD_REFERENCES - ggc_add_tree_root (&anonymous_types, 1); -#endif + /* 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 = +{ + 0, /* init */ + 0, /* finish */ + 0, /* assembly_start */ + 0, /* define */ + 0, /* undef */ + 0, /* start_source_file */ + 0, /* end_source_file */ + 0, /* begin_block */ + 0, /* end_block */ + 0, /* ignore_block */ + 0, /* source_line */ + 0, /* begin_prologue */ + 0, /* end_prologue */ + 0, /* end_epilogue */ + 0, /* begin_function */ + 0, /* end_function */ + 0, /* function_decl */ + 0, /* global_decl */ + 0, /* type_decl */ + 0, /* imported_module_or_decl */ + 0, /* deferred_inline_function */ + 0, /* outlining_inline_function */ + 0, /* label */ + 0, /* handle_pch */ + 0, /* var_location */ + 0, /* switch_text_section */ + 0, /* direct_call */ + 0, /* virtual_call_token */ + 0, /* copy_call_info */ + 0, /* virtual_call */ + 0, /* set_name */ + 0 /* start_end_main_source_file */ +}; + + #endif /* SDB_DEBUGGING_INFO */ + +#include "gt-sdbout.h"