Message ID | Pine.LNX.4.64.1011191248580.17023@digraph.polyomino.org.uk |
---|---|
State | New |
Headers | show |
On Fri, Nov 19, 2010 at 1:49 PM, Joseph S. Myers <joseph@codesourcery.com> wrote: > This patch, relative to a tree with > <http://gcc.gnu.org/ml/gcc-patches/2010-11/msg01778.html> (pending > review) and <http://gcc.gnu.org/ml/gcc-patches/2010-11/msg01858.html> > (approved) applied, eliminates use of global data for > -femit-struct-debug- options and the use of tree interfaces in opts.c. > > The -femit-struct-debug- state now goes in the gcc_options structure. > The should_emit_struct_debug function that uses that state, and uses > tree interfaces so is unsuitable for the driver, is made a static > function in dwarf2out.c, since that is the only place that uses is and > the options are documented as only supported for DWARF2. > > With this patch applied, opts.c no longer uses tree interfaces. It > still uses one function declared in tree.h (vect_set_verbosity_level), > though that is easy to deal with. While the tree.h include is > formally redundant with the expr.h include that follows, removing both > is trickier; langhooks.h depends on tree.h (which will be resolved by > moving various functions to opts-global.c), and the insn-attr.h > include for INSN_SCHEDULING depends on rtl.h having been included by > expr.h (as insn-attr.h includes insn-addr.h which needs INSN_UID). A > subsequent patch will at least make these reasons explicit in > comments. > > Bootstrapped with no regressions on x86_64-unknown-linux-gnu. OK to > commit? Ok. Thanks, Richard. > 2010-11-19 Joseph Myers <joseph@codesourcery.com> > > * common.opt (debug_struct_ordinary, debug_struct_generic): New > Variable entries. > * dwarf2out.c (matches_main_base, dump_struct_debug, DUMP_GSTRUCT, > should_emit_struct_debug): Move from opts.c. > * flag-types.h (enum debug_struct_file): Move from opts.c. > * flags.h (should_emit_struct_debug): Remove. > (base_of_path): Declare. > (set_struct_debug_option): Add gcc_options parameter. > * optc-gen.awk, opth-gen.awk: Handle array variables. > * opts.c (enum debug_struct_file, debug_struct_ordinary, > debug_struct_generic): Remove. > (set_struct_debug_option): Add gcc_options parameter. > (base_of_path): Remove static. > (main_input_basename, main_input_baselength, matches_main_base, > dump_struct_debug, DUMP_GSTRUCT, should_emit_struct_debug): > Remove. > * toplev.c (main_input_basename, main_input_baselength): Define > here. > * toplev.h (main_input_basename, main_input_baselength): Declare > here. > > c-family: > 2010-11-19 Joseph Myers <joseph@codesourcery.com> > > * c-opts.c (c_common_handle_option): Update calls to > set_struct_debug_option. > > diff -rupN --exclude=.svn gcc-mainline-1/gcc/c-family/c-opts.c gcc-mainline/gcc/c-family/c-opts.c > --- gcc-mainline-1/gcc/c-family/c-opts.c 2010-11-17 06:29:21.000000000 -0800 > +++ gcc-mainline/gcc/c-family/c-opts.c 2010-11-18 16:22:22.000000000 -0800 > @@ -654,15 +654,16 @@ c_common_handle_option (size_t scode, co > break; > > case OPT_femit_struct_debug_baseonly: > - set_struct_debug_option ("base"); > + set_struct_debug_option (&global_options, "base"); > break; > > case OPT_femit_struct_debug_reduced: > - set_struct_debug_option ("dir:ord:sys,dir:gen:any,ind:base"); > + set_struct_debug_option (&global_options, > + "dir:ord:sys,dir:gen:any,ind:base"); > break; > > case OPT_femit_struct_debug_detailed_: > - set_struct_debug_option (arg); > + set_struct_debug_option (&global_options, arg); > break; > > case OPT_idirafter: > diff -rupN --exclude=.svn gcc-mainline-1/gcc/common.opt gcc-mainline/gcc/common.opt > --- gcc-mainline-1/gcc/common.opt 2010-11-17 12:38:37.000000000 -0800 > +++ gcc-mainline/gcc/common.opt 2010-11-18 16:17:45.000000000 -0800 > @@ -113,6 +113,19 @@ void *flag_instrument_functions_exclude_ > Variable > void *flag_instrument_functions_exclude_files > > +; Generic structs (e.g. templates not explicitly specialized) > +; may not have a compilation unit associated with them, and so > +; may need to be treated differently from ordinary structs. > +; > +; Structs only handled by reference (indirectly), will also usually > +; not need as much debugging information. > + > +Variable > +enum debug_struct_file debug_struct_ordinary[DINFO_USAGE_NUM_ENUMS] = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY } > + > +Variable > +enum debug_struct_file debug_struct_generic[DINFO_USAGE_NUM_ENUMS] = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY } > + > ### > Driver > > diff -rupN --exclude=.svn gcc-mainline-1/gcc/dwarf2out.c gcc-mainline/gcc/dwarf2out.c > --- gcc-mainline-1/gcc/dwarf2out.c 2010-11-15 17:01:15.000000000 -0800 > +++ gcc-mainline/gcc/dwarf2out.c 2010-11-18 16:33:59.000000000 -0800 > @@ -546,6 +546,89 @@ static struct dw_loc_descr_struct *mem_l > #define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) > #endif > > +/* Match the base name of a file to the base name of a compilation unit. */ > + > +static int > +matches_main_base (const char *path) > +{ > + /* Cache the last query. */ > + static const char *last_path = NULL; > + static int last_match = 0; > + if (path != last_path) > + { > + const char *base; > + int length = base_of_path (path, &base); > + last_path = path; > + last_match = (length == main_input_baselength > + && memcmp (base, main_input_basename, length) == 0); > + } > + return last_match; > +} > + > +#ifdef DEBUG_DEBUG_STRUCT > + > +static int > +dump_struct_debug (tree type, enum debug_info_usage usage, > + enum debug_struct_file criterion, int generic, > + int matches, int result) > +{ > + /* Find the type name. */ > + tree type_decl = TYPE_STUB_DECL (type); > + tree t = type_decl; > + const char *name = 0; > + if (TREE_CODE (t) == TYPE_DECL) > + t = DECL_NAME (t); > + if (t) > + name = IDENTIFIER_POINTER (t); > + > + fprintf (stderr, " struct %d %s %s %s %s %d %p %s\n", > + criterion, > + DECL_IN_SYSTEM_HEADER (type_decl) ? "sys" : "usr", > + matches ? "bas" : "hdr", > + generic ? "gen" : "ord", > + usage == DINFO_USAGE_DFN ? ";" : > + usage == DINFO_USAGE_DIR_USE ? "." : "*", > + result, > + (void*) type_decl, name); > + return result; > +} > +#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ > + dump_struct_debug (type, usage, criterion, generic, matches, result) > + > +#else > + > +#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ > + (result) > + > +#endif > + > +static bool > +should_emit_struct_debug (tree type, enum debug_info_usage usage) > +{ > + enum debug_struct_file criterion; > + tree type_decl; > + bool generic = lang_hooks.types.generic_p (type); > + > + if (generic) > + criterion = debug_struct_generic[usage]; > + else > + criterion = debug_struct_ordinary[usage]; > + > + if (criterion == DINFO_STRUCT_FILE_NONE) > + return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); > + if (criterion == DINFO_STRUCT_FILE_ANY) > + return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); > + > + type_decl = TYPE_STUB_DECL (type); > + > + if (criterion == DINFO_STRUCT_FILE_SYS && DECL_IN_SYSTEM_HEADER (type_decl)) > + return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); > + > + if (matches_main_base (DECL_SOURCE_FILE (type_decl))) > + return DUMP_GSTRUCT (type, usage, criterion, generic, true, true); > + return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); > +} > + > /* Hook used by __throw. */ > > rtx > diff -rupN --exclude=.svn gcc-mainline-1/gcc/flag-types.h gcc-mainline/gcc/flag-types.h > --- gcc-mainline-1/gcc/flag-types.h 2010-11-16 14:58:29.000000000 -0800 > +++ gcc-mainline/gcc/flag-types.h 2010-11-18 16:16:19.000000000 -0800 > @@ -58,6 +58,41 @@ enum debug_info_usage > DINFO_USAGE_NUM_ENUMS /* The number of enumerators. */ > }; > > +/* A major contribution to object and executable size is debug > + information size. A major contribution to debug information size > + is struct descriptions replicated in several object files. The > + following flags attempt to reduce this information. The basic > + idea is to not emit struct debugging information in the current > + compilation unit when that information will be generated by > + another compilation unit. > + > + Debug information for a struct defined in the current source > + file should be generated in the object file. Likewise the > + debug information for a struct defined in a header should be > + generated in the object file of the corresponding source file. > + Both of these case are handled when the base name of the file of > + the struct definition matches the base name of the source file > + of the current compilation unit. This matching emits minimal > + struct debugging information. > + > + The base file name matching rule above will fail to emit debug > + information for structs defined in system headers. So a second > + category of files includes system headers in addition to files > + with matching bases. > + > + The remaining types of files are library headers and application > + headers. We cannot currently distinguish these two types. */ > + > +enum debug_struct_file > +{ > + DINFO_STRUCT_FILE_NONE, /* Debug no structs. */ > + DINFO_STRUCT_FILE_BASE, /* Debug structs defined in files with the > + same base name as the compilation unit. */ > + DINFO_STRUCT_FILE_SYS, /* Also debug structs defined in system > + header files. */ > + DINFO_STRUCT_FILE_ANY /* Debug structs defined in all files. */ > +}; > + > /* Enumerate visibility settings. This is deliberately ordered from most > to least visibility. */ > #ifndef SYMBOL_VISIBILITY_DEFINED > diff -rupN --exclude=.svn gcc-mainline-1/gcc/flags.h gcc-mainline/gcc/flags.h > --- gcc-mainline-1/gcc/flags.h 2010-11-17 12:42:47.000000000 -0800 > +++ gcc-mainline/gcc/flags.h 2010-11-18 16:37:32.000000000 -0800 > @@ -37,8 +37,9 @@ extern const char *const debug_type_name > /* Specify how much debugging info to generate. */ > extern enum debug_info_level debug_info_level; > > -extern bool should_emit_struct_debug (tree type_decl, enum debug_info_usage); > -extern void set_struct_debug_option (const char *value); > +extern int base_of_path (const char *path, const char **base_out); > +extern void set_struct_debug_option (struct gcc_options *opts, > + const char *value); > > /* Nonzero means use GNU-only extensions in the generated symbolic > debugging information. */ > diff -rupN --exclude=.svn gcc-mainline-1/gcc/optc-gen.awk gcc-mainline/gcc/optc-gen.awk > --- gcc-mainline-1/gcc/optc-gen.awk 2010-10-12 04:23:31.000000000 -0700 > +++ gcc-mainline/gcc/optc-gen.awk 2010-11-18 16:12:11.000000000 -0800 > @@ -91,6 +91,7 @@ for (i = 0; i < n_extra_vars; i++) { > sub(".*= *", "", init) > sub(" *=.*", "", var) > sub("^.*[ *]", "", var) > + sub("\\[.*\\]$", "", var) > } else { > init = "0" > } > diff -rupN --exclude=.svn gcc-mainline-1/gcc/opth-gen.awk gcc-mainline/gcc/opth-gen.awk > --- gcc-mainline-1/gcc/opth-gen.awk 2010-10-12 04:23:31.000000000 -0700 > +++ gcc-mainline/gcc/opth-gen.awk 2010-11-18 16:11:38.000000000 -0800 > @@ -86,13 +86,17 @@ for (i = 0; i < n_extra_vars; i++) { > orig_var = var > name = var > type = var > + type_after = var > sub("^.*[ *]", "", name) > + sub("\\[.*\\]$", "", name) > + sub("\\[.*\\]$", "", type) > sub(" *" name "$", "", type) > + sub("^.*" name, "", type_after) > var_seen[name] = 1 > print "#ifdef GENERATOR_FILE" > print "extern " orig_var ";" > print "#else" > - print " " type " x_" name ";" > + print " " type " x_" name type_after ";" > print "#define " name " global_options.x_" name > print "#endif" > } > diff -rupN --exclude=.svn gcc-mainline-1/gcc/opts.c gcc-mainline/gcc/opts.c > --- gcc-mainline-1/gcc/opts.c 2010-11-17 12:44:07.000000000 -0800 > +++ gcc-mainline/gcc/opts.c 2010-11-18 16:53:19.000000000 -0800 > @@ -53,53 +53,6 @@ enum debug_info_type write_symbols = NO_ > the definitions of the different possible levels. */ > enum debug_info_level debug_info_level = DINFO_LEVEL_NONE; > > -/* A major contribution to object and executable size is debug > - information size. A major contribution to debug information size > - is struct descriptions replicated in several object files. The > - following flags attempt to reduce this information. The basic > - idea is to not emit struct debugging information in the current > - compilation unit when that information will be generated by > - another compilation unit. > - > - Debug information for a struct defined in the current source > - file should be generated in the object file. Likewise the > - debug information for a struct defined in a header should be > - generated in the object file of the corresponding source file. > - Both of these case are handled when the base name of the file of > - the struct definition matches the base name of the source file > - of the current compilation unit. This matching emits minimal > - struct debugging information. > - > - The base file name matching rule above will fail to emit debug > - information for structs defined in system headers. So a second > - category of files includes system headers in addition to files > - with matching bases. > - > - The remaining types of files are library headers and application > - headers. We cannot currently distinguish these two types. */ > - > -enum debug_struct_file > -{ > - DINFO_STRUCT_FILE_NONE, /* Debug no structs. */ > - DINFO_STRUCT_FILE_BASE, /* Debug structs defined in files with the > - same base name as the compilation unit. */ > - DINFO_STRUCT_FILE_SYS, /* Also debug structs defined in system > - header files. */ > - DINFO_STRUCT_FILE_ANY /* Debug structs defined in all files. */ > -}; > - > -/* Generic structs (e.g. templates not explicitly specialized) > - may not have a compilation unit associated with them, and so > - may need to be treated differently from ordinary structs. > - > - Structs only handled by reference (indirectly), will also usually > - not need as much debugging information. */ > - > -static enum debug_struct_file debug_struct_ordinary[DINFO_USAGE_NUM_ENUMS] > - = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY }; > -static enum debug_struct_file debug_struct_generic[DINFO_USAGE_NUM_ENUMS] > - = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY }; > - > /* Run the second compilation of -fcompare-debug. Not defined using > Var in common.opt because this is used in Ada code and so must be > an actual variable not a macro. */ > @@ -113,7 +66,7 @@ int flag_compare_debug; > ? ((string += sizeof prefix - 1), 1) : 0) > > void > -set_struct_debug_option (const char *spec) > +set_struct_debug_option (struct gcc_options *opts, const char *spec) > { > /* various labels for comparison */ > static char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:"; > @@ -158,27 +111,27 @@ set_struct_debug_option (const char *spe > { > if (ord) > { > - debug_struct_ordinary[DINFO_USAGE_DFN] = files; > - debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files; > - debug_struct_ordinary[DINFO_USAGE_IND_USE] = files; > + opts->x_debug_struct_ordinary[DINFO_USAGE_DFN] = files; > + opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files; > + opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] = files; > } > if (gen) > { > - debug_struct_generic[DINFO_USAGE_DFN] = files; > - debug_struct_generic[DINFO_USAGE_DIR_USE] = files; > - debug_struct_generic[DINFO_USAGE_IND_USE] = files; > + opts->x_debug_struct_generic[DINFO_USAGE_DFN] = files; > + opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] = files; > + opts->x_debug_struct_generic[DINFO_USAGE_IND_USE] = files; > } > } > else > { > if (ord) > - debug_struct_ordinary[usage] = files; > + opts->x_debug_struct_ordinary[usage] = files; > if (gen) > - debug_struct_generic[usage] = files; > + opts->x_debug_struct_generic[usage] = files; > } > > if (*spec == ',') > - set_struct_debug_option (spec+1); > + set_struct_debug_option (opts, spec+1); > else > { > /* No more -femit-struct-debug-detailed specifications. > @@ -186,10 +139,10 @@ set_struct_debug_option (const char *spe > if (*spec != '\0') > error ("argument %qs to %<-femit-struct-debug-detailed%> unknown", > spec); > - if (debug_struct_ordinary[DINFO_USAGE_DIR_USE] > - < debug_struct_ordinary[DINFO_USAGE_IND_USE] > - || debug_struct_generic[DINFO_USAGE_DIR_USE] > - < debug_struct_generic[DINFO_USAGE_IND_USE]) > + if (opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] > + < opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] > + || opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] > + < opts->x_debug_struct_generic[DINFO_USAGE_IND_USE]) > error ("%<-femit-struct-debug-detailed=dir:...%> must allow at least" > " as much as %<-femit-struct-debug-detailed=ind:...%>"); > } > @@ -197,7 +150,7 @@ set_struct_debug_option (const char *spe > > /* Find the base name of a path, stripping off both directories and > a single final extension. */ > -static int > +int > base_of_path (const char *path, const char **base_out) > { > const char *base = path; > @@ -221,93 +174,6 @@ base_of_path (const char *path, const ch > return dot - base; > } > > -/* Match the base name of a file to the base name of a compilation unit. */ > - > -static const char *main_input_basename; > -static int main_input_baselength; > - > -static int > -matches_main_base (const char *path) > -{ > - /* Cache the last query. */ > - static const char *last_path = NULL; > - static int last_match = 0; > - if (path != last_path) > - { > - const char *base; > - int length = base_of_path (path, &base); > - last_path = path; > - last_match = (length == main_input_baselength > - && memcmp (base, main_input_basename, length) == 0); > - } > - return last_match; > -} > - > -#ifdef DEBUG_DEBUG_STRUCT > - > -static int > -dump_struct_debug (tree type, enum debug_info_usage usage, > - enum debug_struct_file criterion, int generic, > - int matches, int result) > -{ > - /* Find the type name. */ > - tree type_decl = TYPE_STUB_DECL (type); > - tree t = type_decl; > - const char *name = 0; > - if (TREE_CODE (t) == TYPE_DECL) > - t = DECL_NAME (t); > - if (t) > - name = IDENTIFIER_POINTER (t); > - > - fprintf (stderr, " struct %d %s %s %s %s %d %p %s\n", > - criterion, > - DECL_IN_SYSTEM_HEADER (type_decl) ? "sys" : "usr", > - matches ? "bas" : "hdr", > - generic ? "gen" : "ord", > - usage == DINFO_USAGE_DFN ? ";" : > - usage == DINFO_USAGE_DIR_USE ? "." : "*", > - result, > - (void*) type_decl, name); > - return result; > -} > -#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ > - dump_struct_debug (type, usage, criterion, generic, matches, result) > - > -#else > - > -#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ > - (result) > - > -#endif > - > - > -bool > -should_emit_struct_debug (tree type, enum debug_info_usage usage) > -{ > - enum debug_struct_file criterion; > - tree type_decl; > - bool generic = lang_hooks.types.generic_p (type); > - > - if (generic) > - criterion = debug_struct_generic[usage]; > - else > - criterion = debug_struct_ordinary[usage]; > - > - if (criterion == DINFO_STRUCT_FILE_NONE) > - return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); > - if (criterion == DINFO_STRUCT_FILE_ANY) > - return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); > - > - type_decl = TYPE_STUB_DECL (type); > - > - if (criterion == DINFO_STRUCT_FILE_SYS && DECL_IN_SYSTEM_HEADER (type_decl)) > - return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); > - > - if (matches_main_base (DECL_SOURCE_FILE (type_decl))) > - return DUMP_GSTRUCT (type, usage, criterion, generic, true, true); > - return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); > -} > - > /* Nonzero means use GNU-only extensions in the generated symbolic > debugging information. Currently, this only has an effect when > write_symbols is set to DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG. */ > diff -rupN --exclude=.svn gcc-mainline-1/gcc/toplev.c gcc-mainline/gcc/toplev.c > --- gcc-mainline-1/gcc/toplev.c 2010-11-17 12:28:27.000000000 -0800 > +++ gcc-mainline/gcc/toplev.c 2010-11-18 16:33:14.000000000 -0800 > @@ -136,6 +136,12 @@ unsigned int save_decoded_options_count; > > const char *main_input_filename; > > +/* Pointer to base name in main_input_filename, with directories and a > + single final extension removed, and the length of this base > + name. */ > +const char *main_input_basename; > +int main_input_baselength; > + > /* Used to enable -fvar-tracking, -fweb and -frename-registers according > to optimize in process_options (). */ > #define AUTODETECT_VALUE 2 > diff -rupN --exclude=.svn gcc-mainline-1/gcc/toplev.h gcc-mainline/gcc/toplev.h > --- gcc-mainline-1/gcc/toplev.h 2010-11-10 09:18:38.000000000 -0800 > +++ gcc-mainline/gcc/toplev.h 2010-11-18 16:33:25.000000000 -0800 > @@ -73,6 +73,8 @@ extern unsigned local_tick; > > /* Top-level source file. */ > extern const char *main_input_filename; > +extern const char *main_input_basename; > +extern int main_input_baselength; > > extern const char *profile_data_prefix; > extern bool exit_after_options; > > -- > Joseph S. Myers > joseph@codesourcery.com >
diff -rupN --exclude=.svn gcc-mainline-1/gcc/c-family/c-opts.c gcc-mainline/gcc/c-family/c-opts.c --- gcc-mainline-1/gcc/c-family/c-opts.c 2010-11-17 06:29:21.000000000 -0800 +++ gcc-mainline/gcc/c-family/c-opts.c 2010-11-18 16:22:22.000000000 -0800 @@ -654,15 +654,16 @@ c_common_handle_option (size_t scode, co break; case OPT_femit_struct_debug_baseonly: - set_struct_debug_option ("base"); + set_struct_debug_option (&global_options, "base"); break; case OPT_femit_struct_debug_reduced: - set_struct_debug_option ("dir:ord:sys,dir:gen:any,ind:base"); + set_struct_debug_option (&global_options, + "dir:ord:sys,dir:gen:any,ind:base"); break; case OPT_femit_struct_debug_detailed_: - set_struct_debug_option (arg); + set_struct_debug_option (&global_options, arg); break; case OPT_idirafter: diff -rupN --exclude=.svn gcc-mainline-1/gcc/common.opt gcc-mainline/gcc/common.opt --- gcc-mainline-1/gcc/common.opt 2010-11-17 12:38:37.000000000 -0800 +++ gcc-mainline/gcc/common.opt 2010-11-18 16:17:45.000000000 -0800 @@ -113,6 +113,19 @@ void *flag_instrument_functions_exclude_ Variable void *flag_instrument_functions_exclude_files +; Generic structs (e.g. templates not explicitly specialized) +; may not have a compilation unit associated with them, and so +; may need to be treated differently from ordinary structs. +; +; Structs only handled by reference (indirectly), will also usually +; not need as much debugging information. + +Variable +enum debug_struct_file debug_struct_ordinary[DINFO_USAGE_NUM_ENUMS] = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY } + +Variable +enum debug_struct_file debug_struct_generic[DINFO_USAGE_NUM_ENUMS] = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY } + ### Driver diff -rupN --exclude=.svn gcc-mainline-1/gcc/dwarf2out.c gcc-mainline/gcc/dwarf2out.c --- gcc-mainline-1/gcc/dwarf2out.c 2010-11-15 17:01:15.000000000 -0800 +++ gcc-mainline/gcc/dwarf2out.c 2010-11-18 16:33:59.000000000 -0800 @@ -546,6 +546,89 @@ static struct dw_loc_descr_struct *mem_l #define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) #endif +/* Match the base name of a file to the base name of a compilation unit. */ + +static int +matches_main_base (const char *path) +{ + /* Cache the last query. */ + static const char *last_path = NULL; + static int last_match = 0; + if (path != last_path) + { + const char *base; + int length = base_of_path (path, &base); + last_path = path; + last_match = (length == main_input_baselength + && memcmp (base, main_input_basename, length) == 0); + } + return last_match; +} + +#ifdef DEBUG_DEBUG_STRUCT + +static int +dump_struct_debug (tree type, enum debug_info_usage usage, + enum debug_struct_file criterion, int generic, + int matches, int result) +{ + /* Find the type name. */ + tree type_decl = TYPE_STUB_DECL (type); + tree t = type_decl; + const char *name = 0; + if (TREE_CODE (t) == TYPE_DECL) + t = DECL_NAME (t); + if (t) + name = IDENTIFIER_POINTER (t); + + fprintf (stderr, " struct %d %s %s %s %s %d %p %s\n", + criterion, + DECL_IN_SYSTEM_HEADER (type_decl) ? "sys" : "usr", + matches ? "bas" : "hdr", + generic ? "gen" : "ord", + usage == DINFO_USAGE_DFN ? ";" : + usage == DINFO_USAGE_DIR_USE ? "." : "*", + result, + (void*) type_decl, name); + return result; +} +#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ + dump_struct_debug (type, usage, criterion, generic, matches, result) + +#else + +#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ + (result) + +#endif + +static bool +should_emit_struct_debug (tree type, enum debug_info_usage usage) +{ + enum debug_struct_file criterion; + tree type_decl; + bool generic = lang_hooks.types.generic_p (type); + + if (generic) + criterion = debug_struct_generic[usage]; + else + criterion = debug_struct_ordinary[usage]; + + if (criterion == DINFO_STRUCT_FILE_NONE) + return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); + if (criterion == DINFO_STRUCT_FILE_ANY) + return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); + + type_decl = TYPE_STUB_DECL (type); + + if (criterion == DINFO_STRUCT_FILE_SYS && DECL_IN_SYSTEM_HEADER (type_decl)) + return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); + + if (matches_main_base (DECL_SOURCE_FILE (type_decl))) + return DUMP_GSTRUCT (type, usage, criterion, generic, true, true); + return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); +} + /* Hook used by __throw. */ rtx diff -rupN --exclude=.svn gcc-mainline-1/gcc/flag-types.h gcc-mainline/gcc/flag-types.h --- gcc-mainline-1/gcc/flag-types.h 2010-11-16 14:58:29.000000000 -0800 +++ gcc-mainline/gcc/flag-types.h 2010-11-18 16:16:19.000000000 -0800 @@ -58,6 +58,41 @@ enum debug_info_usage DINFO_USAGE_NUM_ENUMS /* The number of enumerators. */ }; +/* A major contribution to object and executable size is debug + information size. A major contribution to debug information size + is struct descriptions replicated in several object files. The + following flags attempt to reduce this information. The basic + idea is to not emit struct debugging information in the current + compilation unit when that information will be generated by + another compilation unit. + + Debug information for a struct defined in the current source + file should be generated in the object file. Likewise the + debug information for a struct defined in a header should be + generated in the object file of the corresponding source file. + Both of these case are handled when the base name of the file of + the struct definition matches the base name of the source file + of the current compilation unit. This matching emits minimal + struct debugging information. + + The base file name matching rule above will fail to emit debug + information for structs defined in system headers. So a second + category of files includes system headers in addition to files + with matching bases. + + The remaining types of files are library headers and application + headers. We cannot currently distinguish these two types. */ + +enum debug_struct_file +{ + DINFO_STRUCT_FILE_NONE, /* Debug no structs. */ + DINFO_STRUCT_FILE_BASE, /* Debug structs defined in files with the + same base name as the compilation unit. */ + DINFO_STRUCT_FILE_SYS, /* Also debug structs defined in system + header files. */ + DINFO_STRUCT_FILE_ANY /* Debug structs defined in all files. */ +}; + /* Enumerate visibility settings. This is deliberately ordered from most to least visibility. */ #ifndef SYMBOL_VISIBILITY_DEFINED diff -rupN --exclude=.svn gcc-mainline-1/gcc/flags.h gcc-mainline/gcc/flags.h --- gcc-mainline-1/gcc/flags.h 2010-11-17 12:42:47.000000000 -0800 +++ gcc-mainline/gcc/flags.h 2010-11-18 16:37:32.000000000 -0800 @@ -37,8 +37,9 @@ extern const char *const debug_type_name /* Specify how much debugging info to generate. */ extern enum debug_info_level debug_info_level; -extern bool should_emit_struct_debug (tree type_decl, enum debug_info_usage); -extern void set_struct_debug_option (const char *value); +extern int base_of_path (const char *path, const char **base_out); +extern void set_struct_debug_option (struct gcc_options *opts, + const char *value); /* Nonzero means use GNU-only extensions in the generated symbolic debugging information. */ diff -rupN --exclude=.svn gcc-mainline-1/gcc/optc-gen.awk gcc-mainline/gcc/optc-gen.awk --- gcc-mainline-1/gcc/optc-gen.awk 2010-10-12 04:23:31.000000000 -0700 +++ gcc-mainline/gcc/optc-gen.awk 2010-11-18 16:12:11.000000000 -0800 @@ -91,6 +91,7 @@ for (i = 0; i < n_extra_vars; i++) { sub(".*= *", "", init) sub(" *=.*", "", var) sub("^.*[ *]", "", var) + sub("\\[.*\\]$", "", var) } else { init = "0" } diff -rupN --exclude=.svn gcc-mainline-1/gcc/opth-gen.awk gcc-mainline/gcc/opth-gen.awk --- gcc-mainline-1/gcc/opth-gen.awk 2010-10-12 04:23:31.000000000 -0700 +++ gcc-mainline/gcc/opth-gen.awk 2010-11-18 16:11:38.000000000 -0800 @@ -86,13 +86,17 @@ for (i = 0; i < n_extra_vars; i++) { orig_var = var name = var type = var + type_after = var sub("^.*[ *]", "", name) + sub("\\[.*\\]$", "", name) + sub("\\[.*\\]$", "", type) sub(" *" name "$", "", type) + sub("^.*" name, "", type_after) var_seen[name] = 1 print "#ifdef GENERATOR_FILE" print "extern " orig_var ";" print "#else" - print " " type " x_" name ";" + print " " type " x_" name type_after ";" print "#define " name " global_options.x_" name print "#endif" } diff -rupN --exclude=.svn gcc-mainline-1/gcc/opts.c gcc-mainline/gcc/opts.c --- gcc-mainline-1/gcc/opts.c 2010-11-17 12:44:07.000000000 -0800 +++ gcc-mainline/gcc/opts.c 2010-11-18 16:53:19.000000000 -0800 @@ -53,53 +53,6 @@ enum debug_info_type write_symbols = NO_ the definitions of the different possible levels. */ enum debug_info_level debug_info_level = DINFO_LEVEL_NONE; -/* A major contribution to object and executable size is debug - information size. A major contribution to debug information size - is struct descriptions replicated in several object files. The - following flags attempt to reduce this information. The basic - idea is to not emit struct debugging information in the current - compilation unit when that information will be generated by - another compilation unit. - - Debug information for a struct defined in the current source - file should be generated in the object file. Likewise the - debug information for a struct defined in a header should be - generated in the object file of the corresponding source file. - Both of these case are handled when the base name of the file of - the struct definition matches the base name of the source file - of the current compilation unit. This matching emits minimal - struct debugging information. - - The base file name matching rule above will fail to emit debug - information for structs defined in system headers. So a second - category of files includes system headers in addition to files - with matching bases. - - The remaining types of files are library headers and application - headers. We cannot currently distinguish these two types. */ - -enum debug_struct_file -{ - DINFO_STRUCT_FILE_NONE, /* Debug no structs. */ - DINFO_STRUCT_FILE_BASE, /* Debug structs defined in files with the - same base name as the compilation unit. */ - DINFO_STRUCT_FILE_SYS, /* Also debug structs defined in system - header files. */ - DINFO_STRUCT_FILE_ANY /* Debug structs defined in all files. */ -}; - -/* Generic structs (e.g. templates not explicitly specialized) - may not have a compilation unit associated with them, and so - may need to be treated differently from ordinary structs. - - Structs only handled by reference (indirectly), will also usually - not need as much debugging information. */ - -static enum debug_struct_file debug_struct_ordinary[DINFO_USAGE_NUM_ENUMS] - = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY }; -static enum debug_struct_file debug_struct_generic[DINFO_USAGE_NUM_ENUMS] - = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY }; - /* Run the second compilation of -fcompare-debug. Not defined using Var in common.opt because this is used in Ada code and so must be an actual variable not a macro. */ @@ -113,7 +66,7 @@ int flag_compare_debug; ? ((string += sizeof prefix - 1), 1) : 0) void -set_struct_debug_option (const char *spec) +set_struct_debug_option (struct gcc_options *opts, const char *spec) { /* various labels for comparison */ static char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:"; @@ -158,27 +111,27 @@ set_struct_debug_option (const char *spe { if (ord) { - debug_struct_ordinary[DINFO_USAGE_DFN] = files; - debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files; - debug_struct_ordinary[DINFO_USAGE_IND_USE] = files; + opts->x_debug_struct_ordinary[DINFO_USAGE_DFN] = files; + opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files; + opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] = files; } if (gen) { - debug_struct_generic[DINFO_USAGE_DFN] = files; - debug_struct_generic[DINFO_USAGE_DIR_USE] = files; - debug_struct_generic[DINFO_USAGE_IND_USE] = files; + opts->x_debug_struct_generic[DINFO_USAGE_DFN] = files; + opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] = files; + opts->x_debug_struct_generic[DINFO_USAGE_IND_USE] = files; } } else { if (ord) - debug_struct_ordinary[usage] = files; + opts->x_debug_struct_ordinary[usage] = files; if (gen) - debug_struct_generic[usage] = files; + opts->x_debug_struct_generic[usage] = files; } if (*spec == ',') - set_struct_debug_option (spec+1); + set_struct_debug_option (opts, spec+1); else { /* No more -femit-struct-debug-detailed specifications. @@ -186,10 +139,10 @@ set_struct_debug_option (const char *spe if (*spec != '\0') error ("argument %qs to %<-femit-struct-debug-detailed%> unknown", spec); - if (debug_struct_ordinary[DINFO_USAGE_DIR_USE] - < debug_struct_ordinary[DINFO_USAGE_IND_USE] - || debug_struct_generic[DINFO_USAGE_DIR_USE] - < debug_struct_generic[DINFO_USAGE_IND_USE]) + if (opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] + < opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] + || opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] + < opts->x_debug_struct_generic[DINFO_USAGE_IND_USE]) error ("%<-femit-struct-debug-detailed=dir:...%> must allow at least" " as much as %<-femit-struct-debug-detailed=ind:...%>"); } @@ -197,7 +150,7 @@ set_struct_debug_option (const char *spe /* Find the base name of a path, stripping off both directories and a single final extension. */ -static int +int base_of_path (const char *path, const char **base_out) { const char *base = path; @@ -221,93 +174,6 @@ base_of_path (const char *path, const ch return dot - base; } -/* Match the base name of a file to the base name of a compilation unit. */ - -static const char *main_input_basename; -static int main_input_baselength; - -static int -matches_main_base (const char *path) -{ - /* Cache the last query. */ - static const char *last_path = NULL; - static int last_match = 0; - if (path != last_path) - { - const char *base; - int length = base_of_path (path, &base); - last_path = path; - last_match = (length == main_input_baselength - && memcmp (base, main_input_basename, length) == 0); - } - return last_match; -} - -#ifdef DEBUG_DEBUG_STRUCT - -static int -dump_struct_debug (tree type, enum debug_info_usage usage, - enum debug_struct_file criterion, int generic, - int matches, int result) -{ - /* Find the type name. */ - tree type_decl = TYPE_STUB_DECL (type); - tree t = type_decl; - const char *name = 0; - if (TREE_CODE (t) == TYPE_DECL) - t = DECL_NAME (t); - if (t) - name = IDENTIFIER_POINTER (t); - - fprintf (stderr, " struct %d %s %s %s %s %d %p %s\n", - criterion, - DECL_IN_SYSTEM_HEADER (type_decl) ? "sys" : "usr", - matches ? "bas" : "hdr", - generic ? "gen" : "ord", - usage == DINFO_USAGE_DFN ? ";" : - usage == DINFO_USAGE_DIR_USE ? "." : "*", - result, - (void*) type_decl, name); - return result; -} -#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ - dump_struct_debug (type, usage, criterion, generic, matches, result) - -#else - -#define DUMP_GSTRUCT(type, usage, criterion, generic, matches, result) \ - (result) - -#endif - - -bool -should_emit_struct_debug (tree type, enum debug_info_usage usage) -{ - enum debug_struct_file criterion; - tree type_decl; - bool generic = lang_hooks.types.generic_p (type); - - if (generic) - criterion = debug_struct_generic[usage]; - else - criterion = debug_struct_ordinary[usage]; - - if (criterion == DINFO_STRUCT_FILE_NONE) - return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); - if (criterion == DINFO_STRUCT_FILE_ANY) - return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); - - type_decl = TYPE_STUB_DECL (type); - - if (criterion == DINFO_STRUCT_FILE_SYS && DECL_IN_SYSTEM_HEADER (type_decl)) - return DUMP_GSTRUCT (type, usage, criterion, generic, false, true); - - if (matches_main_base (DECL_SOURCE_FILE (type_decl))) - return DUMP_GSTRUCT (type, usage, criterion, generic, true, true); - return DUMP_GSTRUCT (type, usage, criterion, generic, false, false); -} - /* Nonzero means use GNU-only extensions in the generated symbolic debugging information. Currently, this only has an effect when write_symbols is set to DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG. */ diff -rupN --exclude=.svn gcc-mainline-1/gcc/toplev.c gcc-mainline/gcc/toplev.c --- gcc-mainline-1/gcc/toplev.c 2010-11-17 12:28:27.000000000 -0800 +++ gcc-mainline/gcc/toplev.c 2010-11-18 16:33:14.000000000 -0800 @@ -136,6 +136,12 @@ unsigned int save_decoded_options_count; const char *main_input_filename; +/* Pointer to base name in main_input_filename, with directories and a + single final extension removed, and the length of this base + name. */ +const char *main_input_basename; +int main_input_baselength; + /* Used to enable -fvar-tracking, -fweb and -frename-registers according to optimize in process_options (). */ #define AUTODETECT_VALUE 2 diff -rupN --exclude=.svn gcc-mainline-1/gcc/toplev.h gcc-mainline/gcc/toplev.h --- gcc-mainline-1/gcc/toplev.h 2010-11-10 09:18:38.000000000 -0800 +++ gcc-mainline/gcc/toplev.h 2010-11-18 16:33:25.000000000 -0800 @@ -73,6 +73,8 @@ extern unsigned local_tick; /* Top-level source file. */ extern const char *main_input_filename; +extern const char *main_input_basename; +extern int main_input_baselength; extern const char *profile_data_prefix; extern bool exit_after_options;