From 6a08f7b337df863c8835f0fc66fd65d72c3824c8 Mon Sep 17 00:00:00 2001 From: Devang Patel Date: Thu, 26 Jun 2003 20:04:40 -0700 Subject: [PATCH] final.c (debug_flush_symbol_queue): New function. * final.c (debug_flush_symbol_queue): New function. (debug_queue_symbol): New function. (debug_free_queue): New function. (debug_nesting): New variable. (symbol_queue): New variable. (symbol_queue_index): Same. (symbol_queue_size): Same. * debug.h (debug_flush_symbol_queue): New. (debug_queue_symbol): New. (debug_free_queue): New. (debug_nesting): New. (symbol_queue_index): New. * dbxout.c (DBXOUT_DECR_NESTING): New macro. (DBXOUT_DECR_NESTING_AND_RETURN): New macro. (dbxout_init): Delay symbol output. (dbxout_global_decl): Save, set and reset TREE_USED bit around dbxout_symbol() call. (dbxout_begin_function): Same. (dbxout_finish): Free symbol queue. (dbxout_type): Put appropriate symbols in queue. (dbxout_symbol): Put info for symbol's type in queue. Decrement/Increment nesting counts flush symbol queue appropriately. (dbxout_parms): Increment dbxout nesting. (dbxout_reg_parms): Same. * flags.h (flag_debug_only_used_symbols): New. * toplev.c (flag_debug_only_used_symbols): New variable. (lang_independent_options): Add entries for new option -feliminate-unused-debug-symbols. * common.opt: Add entry for -feliminate-unused-debug-symbols. * opts.c (common_handle_options): Same. * config/rs6000/darwin.h (CC1_SPEC): Interpret -gused as -feliminate-unused-debug-symbols. * doc/invoke.texi (Debugging Options): Document -feliminate-unused-debug-symbols. From-SVN: r68556 --- gcc/ChangeLog | 34 +++++++++ gcc/common.opt | 3 + gcc/config/rs6000/darwin.h | 1 + gcc/dbxout.c | 153 ++++++++++++++++++++++++++++++++----- gcc/debug.h | 6 ++ gcc/doc/invoke.texi | 7 +- gcc/final.c | 86 +++++++++++++++++++++ gcc/opts.c | 4 + gcc/toplev.c | 20 +++++ 9 files changed, 292 insertions(+), 22 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f06e8a6ef66..4291f67ba85 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2003-06-26 Devang Patel + + * final.c (debug_flush_symbol_queue): New function. + (debug_queue_symbol): New function. + (debug_free_queue): New function. + (debug_nesting): New variable. + (symbol_queue): New variable. + (symbol_queue_index): Same. + (symbol_queue_size): Same. + * debug.h (debug_flush_symbol_queue): New. + (debug_queue_symbol): New. + (debug_free_queue): New. + (debug_nesting): New. + (symbol_queue_index): New. + * dbxout.c (DBXOUT_DECR_NESTING): New macro. + (DBXOUT_DECR_NESTING_AND_RETURN): New macro. + (dbxout_init): Delay symbol output. + (dbxout_global_decl): Save, set and reset TREE_USED bit around dbxout_symbol() + call. + (dbxout_begin_function): Same. + (dbxout_finish): Free symbol queue. + (dbxout_type): Put appropriate symbols in queue. + (dbxout_symbol): Put info for symbol's type in queue. Decrement/Increment + nesting counts flush symbol queue appropriately. + (dbxout_parms): Increment dbxout nesting. + (dbxout_reg_parms): Same. + * flags.h (flag_debug_only_used_symbols): New. + * toplev.c (flag_debug_only_used_symbols): New variable. + (lang_independent_options): Add entries for new option -feliminate-unused-debug-symbols. + * common.opt: Add entry for -feliminate-unused-debug-symbols. + * opts.c (common_handle_options): Same. + * config/rs6000/darwin.h (CC1_SPEC): Interpret -gused as -feliminate-unused-debug-symbols. + * doc/invoke.texi (Debugging Options): Document -feliminate-unused-debug-symbols. + 2003-06-26 Roger Sayle Jakub Jelinek diff --git a/gcc/common.opt b/gcc/common.opt index cca70d65a0e..347b59f2483 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -241,6 +241,9 @@ Common feliminate-dwarf2-dups Common +feliminate-unused-debug-symbols +Common + feliminate-unused-debug-types Common diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h index 30b10da257e..52340a8e029 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -93,6 +93,7 @@ do { \ #define CC1_SPEC "\ +%{gused: -feliminate-unused-debug-symbols % 0) \ + debug_flush_symbol_queue () + +#undef DBXOUT_DECR_NESTING_AND_RETURN +#define DBXOUT_DECR_NESTING_AND_RETURN(x) \ + do {--debug_nesting; return (x);} while (0) + #ifndef ASM_STABS_OP #define ASM_STABS_OP "\t.stabs\t" #endif @@ -505,9 +516,6 @@ dbxout_init (input_file_name) #ifdef DBX_OUTPUT_STANDARD_TYPES DBX_OUTPUT_STANDARD_TYPES (syms); -#else - dbxout_symbol (TYPE_NAME (integer_type_node), 0); - dbxout_symbol (TYPE_NAME (char_type_node), 0); #endif /* Get all permanent types that have typedef names, @@ -705,7 +713,12 @@ dbxout_global_decl (decl) if (TREE_CODE (decl) == VAR_DECL && ! DECL_EXTERNAL (decl) && DECL_RTL_SET_P (decl)) /* Not necessary? */ - dbxout_symbol (decl, 0); + { + int saved_tree_used = TREE_USED (decl); + TREE_USED (decl) = 1; + dbxout_symbol (decl, 0); + TREE_USED (decl) = saved_tree_used; + } } /* At the end of compilation, finish writing the symbol table. @@ -719,6 +732,8 @@ dbxout_finish (filename) #ifdef DBX_OUTPUT_MAIN_SOURCE_FILE_END DBX_OUTPUT_MAIN_SOURCE_FILE_END (asmfile, filename); #endif /* DBX_OUTPUT_MAIN_SOURCE_FILE_END */ + + debug_free_queue (); } /* Output floating point type values used by the 'R' stab letter. @@ -1125,6 +1140,7 @@ dbxout_range_type (type) } } + /* Output a reference to a type. If the type has not yet been described in the dbx output, output its definition now. For a type already defined, just refer to its definition @@ -1200,6 +1216,21 @@ dbxout_type (type, full) #endif } + if (flag_debug_only_used_symbols) + { + if ((TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == QUAL_UNION_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && TYPE_STUB_DECL (type) + && TREE_CODE_CLASS (TREE_CODE (TYPE_STUB_DECL (type))) == 'd' + && ! DECL_IGNORED_P (TYPE_STUB_DECL (type))) + debug_queue_symbol (TYPE_STUB_DECL (type)); + else if (TYPE_NAME (type) + && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) + debug_queue_symbol (TYPE_NAME (type)); + } + /* Output the number of this type, to refer to it. */ dbxout_type_index (type); @@ -1283,6 +1314,18 @@ dbxout_type (type, full) } else if (main_variant != TYPE_MAIN_VARIANT (type)) { + if (flag_debug_only_used_symbols) + { + tree orig_type = DECL_ORIGINAL_TYPE (TYPE_NAME (type)); + + if ((TREE_CODE (orig_type) == RECORD_TYPE + || TREE_CODE (orig_type) == UNION_TYPE + || TREE_CODE (orig_type) == QUAL_UNION_TYPE + || TREE_CODE (orig_type) == ENUMERAL_TYPE) + && TYPE_STUB_DECL (orig_type) + && ! DECL_IGNORED_P (TYPE_STUB_DECL (orig_type))) + debug_queue_symbol (TYPE_STUB_DECL (orig_type)); + } /* 'type' is a typedef; output the type it refers to. */ dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0); return; @@ -1992,6 +2035,9 @@ dbxout_symbol (decl, local) tree context = NULL_TREE; int result = 0; + /* "Intercept" dbxout_symbol() calls like we do all debug_hooks. */ + ++debug_nesting; + /* Cast avoids warning in old compilers. */ current_sym_code = (STAB_CODE_TYPE) 0; current_sym_value = 0; @@ -2001,7 +2047,62 @@ dbxout_symbol (decl, local) if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL) || DECL_IGNORED_P (decl)) - return 0; + DBXOUT_DECR_NESTING_AND_RETURN (0); + + /* If we are to generate only the symbols actualy used then such + symbol nodees are flagged with TREE_USED. Ignore any that + aren't flaged as TREE_USED. */ + + if (flag_debug_only_used_symbols) + { + tree t; + + if (!TREE_USED (decl) + && (TREE_CODE (decl) != VAR_DECL || !DECL_INITIAL (decl))) + DBXOUT_DECR_NESTING_AND_RETURN (0); + + /* We now have a used symbol. We need to generate the info for + the symbol's type in addition to the symbol itself. These + type symbols are queued to be generated after were done with + the symbol itself (done because the symbol's info is generated + with fprintf's, etc. as it determines what's needed). + + Note, because the TREE_TYPE(type) might be something like a + pointer to a named type we need to look for the first name + we see following the TREE_TYPE chain. */ + + t = type; + while (POINTER_TYPE_P (t)) + t = TREE_TYPE (t); + + /* RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, and ENUMERAL_TYPE + need special treatment. The TYPE_STUB_DECL field in these + types generally represents the tag name type we want to + output. In addition there could be a typedef type with + a different name. In that case we also want to output + that. */ + + if ((TREE_CODE (t) == RECORD_TYPE + || TREE_CODE (t) == UNION_TYPE + || TREE_CODE (t) == QUAL_UNION_TYPE + || TREE_CODE (t) == ENUMERAL_TYPE) + && TYPE_STUB_DECL (t) + && TYPE_STUB_DECL (t) != decl + && TREE_CODE_CLASS (TREE_CODE (TYPE_STUB_DECL (t))) == 'd' + && ! DECL_IGNORED_P (TYPE_STUB_DECL (t))) + { + debug_queue_symbol (TYPE_STUB_DECL (t)); + if (TYPE_NAME (t) + && TYPE_NAME (t) != TYPE_STUB_DECL (t) + && TYPE_NAME (t) != decl + && TREE_CODE_CLASS (TREE_CODE (TYPE_NAME (t))) == 'd') + debug_queue_symbol (TYPE_NAME (t)); + } + else if (TYPE_NAME (t) + && TYPE_NAME (t) != decl + && TREE_CODE_CLASS (TREE_CODE (TYPE_NAME (t))) == 'd') + debug_queue_symbol (TYPE_NAME (t)); + } dbxout_prepare_symbol (decl); @@ -2019,7 +2120,7 @@ dbxout_symbol (decl, local) case FUNCTION_DECL: if (DECL_RTL (decl) == 0) - return 0; + DBXOUT_DECR_NESTING_AND_RETURN (0); if (DECL_EXTERNAL (decl)) break; /* Don't mention a nested function under its parent. */ @@ -2056,22 +2157,10 @@ dbxout_symbol (decl, local) break; case TYPE_DECL: -#if 0 - /* This seems all wrong. Outputting most kinds of types gives no name - at all. A true definition gives no name; a cross-ref for a - structure can give the tag name, but not a type name. - It seems that no typedef name is defined by outputting a type. */ - - /* If this typedef name was defined by outputting the type, - don't duplicate it. */ - if (typevec[TYPE_SYMTAB_ADDRESS (type)].status == TYPE_DEFINED - && TYPE_NAME (TREE_TYPE (decl)) == decl) - return 0; -#endif /* Don't output the same typedef twice. And don't output what language-specific stuff doesn't want output. */ if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl)) - return 0; + DBXOUT_DECR_NESTING_AND_RETURN (0); FORCE_TEXT; result = 1; @@ -2097,6 +2186,8 @@ dbxout_symbol (decl, local) /* Distinguish the implicit typedefs of C++ from explicit ones that might be found in C. */ && DECL_ARTIFICIAL (decl) + /* Do not generate a tag for incomplete records. */ + && COMPLETE_TYPE_P (type) /* Do not generate a tag for records of variable size, since this type can not be properly described in the DBX format, and it confuses some tools such as objdump. */ @@ -2218,7 +2309,7 @@ dbxout_symbol (decl, local) /* Named return value, treat like a VAR_DECL. */ case VAR_DECL: if (! DECL_RTL_SET_P (decl)) - return 0; + DBXOUT_DECR_NESTING_AND_RETURN (0); /* Don't mention a variable that is external. Let the file that defines it describe it. */ if (DECL_EXTERNAL (decl)) @@ -2245,6 +2336,7 @@ dbxout_symbol (decl, local) fprintf (asmfile, "%s\"%s:c=i" HOST_WIDE_INT_PRINT_DEC "\",0x%x,0,0,0\n", ASM_STABS_OP, name, ival, N_LSYM); + DBXOUT_DECR_NESTING; return 1; } else if (TREE_CODE (TREE_TYPE (decl)) == REAL_TYPE) @@ -2268,6 +2360,7 @@ dbxout_symbol (decl, local) default: break; } + DBXOUT_DECR_NESTING; return result; } @@ -2604,6 +2697,8 @@ void dbxout_parms (parms) tree parms; { + ++debug_nesting; + for (; parms; parms = TREE_CHAIN (parms)) if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node) { @@ -2861,6 +2956,7 @@ dbxout_parms (parms) dbxout_finish_symbol (parms); } } + DBXOUT_DECR_NESTING; } /* Output definitions for the places where parms live during the function, @@ -2878,6 +2974,8 @@ void dbxout_reg_parms (parms) tree parms; { + ++debug_nesting; + for (; parms; parms = TREE_CHAIN (parms)) if (DECL_NAME (parms) && PARM_PASSED_IN_MEMORY (parms)) { @@ -2898,6 +2996,7 @@ dbxout_reg_parms (parms) dbxout_symbol_location (parms, TREE_TYPE (parms), 0, DECL_RTL (parms)); } + DBXOUT_DECR_NESTING; } /* Given a chain of ..._TYPE nodes (as come in a parameter list), @@ -3035,7 +3134,19 @@ static void dbxout_begin_function (decl) tree decl; { - dbxout_symbol (decl, 0); + int saved_tree_used1 = TREE_USED (decl); + TREE_USED (decl) = 1; + if (DECL_NAME (DECL_RESULT (decl)) != 0) + { + int saved_tree_used2 = TREE_USED (DECL_RESULT (decl)); + TREE_USED (DECL_RESULT (decl)) = 1; + dbxout_symbol (decl, 0); + TREE_USED (DECL_RESULT (decl)) = saved_tree_used2; + } + else + dbxout_symbol (decl, 0); + TREE_USED (decl) = saved_tree_used1; + dbxout_parms (DECL_ARGUMENTS (decl)); if (DECL_NAME (DECL_RESULT (decl)) != 0) dbxout_symbol (DECL_RESULT (decl), 1); diff --git a/gcc/debug.h b/gcc/debug.h index 2793e302115..c1c0842069d 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -146,4 +146,10 @@ extern void dwarf2out_frame_finish PARAMS ((void)); translation unit. */ extern int dwarf2out_do_frame PARAMS ((void)); +extern void debug_flush_symbol_queue PARAMS ((void)); +extern void debug_queue_symbol PARAMS ((tree)); +extern void debug_free_queue PARAMS ((void)); +extern int debug_nesting; +extern int symbol_queue_index; + #endif /* !GCC_DEBUG_H */ diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a9c1c046729..a751d8e419f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -244,7 +244,7 @@ in the following sections. -fdump-tree-optimized@r{[}-@var{n}@r{]} @gol -fdump-tree-inlined@r{[}-@var{n}@r{]} @gol -feliminate-dwarf2-dups -feliminate-unused-debug-types @gol --fmem-report -fprofile-arcs @gol +-feliminate-unused-debug-symbols -fmem-report -fprofile-arcs @gol -frandom-seed=@var{string} -fsched-verbose=@var{n} @gol -ftest-coverage -ftime-report @gol -g -g@var{level} -gcoff -gdwarf -gdwarf-1 -gdwarf-1+ -gdwarf-2 @gol @@ -2916,6 +2916,11 @@ systems. On MIPS, Alpha and System V Release 4 systems this option produces stabs debugging output which is not understood by DBX or SDB@. On System V Release 4 systems this option requires the GNU assembler. +@item -feliminate-unused-debug-symbols +@opindex feliminate-unused-debug-symbols +Produce debugging information in stabs format (if that is supported), +for only symbols that are actualy used. + @item -gstabs+ @opindex gstabs+ Produce debugging information in stabs format (if that is supported), diff --git a/gcc/final.c b/gcc/final.c index 6015cd000e5..b7a04f5d510 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -81,6 +81,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "dwarf2out.h" #endif +#ifdef DBX_DEBUGGING_INFO +#include "dbxout.h" +#endif + /* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a null default for it to save conditionalization later. */ #ifndef CC_STATUS_INIT @@ -3847,3 +3851,85 @@ leaf_renumber_regs_insn (in_rtx) } } #endif + + +/* When -gused is used, emit debug info for only used symbols. But in + addition to the standard intercepted debug_hooks there are some direct + calls into this file, i.e., dbxout_symbol, dbxout_parms, and dbxout_reg_params. + Those routines may also be called from a higher level intercepted routine. So + to prevent recording data for an inner call to one of these for an intercept, + we maintain a intercept nesting counter (debug_nesting). We only save the + intercepted arguments if the nesting is 1. */ +int debug_nesting = 0; + +static tree *symbol_queue; +int symbol_queue_index = 0; +static int symbol_queue_size = 0; + +/* Generate the symbols for any queued up type symbols we encountered + while generating the type info for some originally used symbol. + This might generate additional entries in the queue. Only when + the nesting depth goes to 0 is this routine called. */ + +void +debug_flush_symbol_queue () +{ + int i; + + /* Make sure that additionally queued items are not flushed + prematurely. */ + + ++debug_nesting; + + for (i = 0; i < symbol_queue_index; ++i) + { + /* If we pushed queued symbols then such symbols are must be + output no matter what anyone else says. Specifically, + we need to make sure dbxout_symbol() thinks the symbol was + used and also we need to override TYPE_DECL_SUPPRESS_DEBUG + which may be set for outside reasons. */ + int saved_tree_used = TREE_USED (symbol_queue[i]); + int saved_suppress_debug = TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]); + TREE_USED (symbol_queue[i]) = 1; + TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = 0; + +#ifdef DBX_DEBUGGING_INFO + dbxout_symbol (symbol_queue[i], 0); +#endif + + TREE_USED (symbol_queue[i]) = saved_tree_used; + TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = saved_suppress_debug; + } + + symbol_queue_index = 0; + --debug_nesting; +} + +/* Queue a type symbol needed as part of the definition of a decl + symbol. These symbols are generated when debug_flush_symbol_queue() + is called. */ + +void +debug_queue_symbol (tree decl) +{ + if (symbol_queue_index >= symbol_queue_size) + { + symbol_queue_size += 10; + symbol_queue = (tree *) xrealloc (symbol_queue, + symbol_queue_size * sizeof (tree)); + } + + symbol_queue[symbol_queue_index++] = decl; +} + +/* Free symbol queue */ +void +debug_free_queue () +{ + if (symbol_queue) + { + free (symbol_queue); + symbol_queue = NULL; + symbol_queue_size = 0; + } +} diff --git a/gcc/opts.c b/gcc/opts.c index a5e8297d1e4..b1238beb291 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -737,6 +737,10 @@ common_handle_option (size_t scode, const char *arg, flag_eliminate_unused_debug_types = value; break; + case OPT_feliminate_unused_debug_symbols: + flag_debug_only_used_symbols = value; + break; + case OPT_fexceptions: flag_exceptions = value; break; diff --git a/gcc/toplev.c b/gcc/toplev.c index 6d1dd44f119..6fd02eb6ad4 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -402,6 +402,9 @@ int flag_eliminate_dwarf2_dups = 0; int flag_eliminate_unused_debug_types = 1; +/* Nonzero means emit debugging information only for symbols which are used. */ +int flag_debug_only_used_symbols = 0; + /* Nonzero if generating code to do profiling. */ int profile_flag = 0; @@ -1056,6 +1059,8 @@ static const lang_independent_options f_options[] = N_("Perform DWARF2 duplicate elimination") }, {"eliminate-unused-debug-types", &flag_dummy, 1, N_("Perform unused type elimination in debug info") }, + {"eliminate-unused-debug-symbols", &flag_dummy, 1, + N_("Perform unused type elimination in debug info") }, {"float-store", &flag_dummy, 1, N_("Do not store floats in registers") }, {"defer-pop", &flag_dummy, 1, @@ -4584,6 +4589,21 @@ general_init (char *argv0) init_ggc (); init_stringpool (); init_ttree (); + + /* APPLE LOCAL setrlimit */ +#ifdef RLIMIT_STACK + /* Get rid of any avoidable limit on stack size. */ + { + struct rlimit rlim; + + /* Set the stack limit huge. (Compiles normally work within + a megabyte of stack, but the normal limit on OSX is 512K for + some reason.) */ + getrlimit (RLIMIT_STACK, &rlim); + rlim.rlim_cur = rlim.rlim_max; + setrlimit (RLIMIT_STACK, &rlim); + } +#endif /* RLIMIT_STACK defined */ } /* Parse command line options and set default flag values, called