summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog34
-rw-r--r--gcc/common.opt3
-rw-r--r--gcc/config/rs6000/darwin.h1
-rw-r--r--gcc/dbxout.c153
-rw-r--r--gcc/debug.h6
-rw-r--r--gcc/doc/invoke.texi7
-rw-r--r--gcc/final.c86
-rw-r--r--gcc/opts.c4
-rw-r--r--gcc/toplev.c20
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 <dpatel@apple.com>
+
+ * 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 <roger@eyesopen.com>
Jakub Jelinek <jakub@redhat.com>
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 %<gused }\
%{static: %{Zdynamic: %e conflicting code gen style switches are used}}\
%{!static:%{!mdynamic-no-pic:-fPIC}}"
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index f4f35dbef97..71557486a4d 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -93,6 +93,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "xcoffout.h"
#endif
+extern int flag_debug_only_used_symbols;
+
+#undef DBXOUT_DECR_NESTING
+#define DBXOUT_DECR_NESTING \
+ if (--debug_nesting == 0 && symbol_queue_index > 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