On Fri, 11 Dec 2009, Richard Guenther wrote: > > The following draft patch disables the debuginfo disabling when using > -flto or -fwhopr and fixes up things so that for C debugging (mostly) > works. > > The main question I have is how to proceed further here (with the > goal that simple debugging should be possible in 4.5). If we > apply this patch then we expose ICEs when -flto is used in > conjunction with -g because the patch doesn't fix all clashes > between free-lang-data and dwarf2out. Now I was thinking of > instead of ICEing to sorry () if we ICE, have debuginfo enabled > and had run free-lang-data. Or to keep -g non-operational for > LTO and add a -glto or -fi-really-want-to-debug option. > > Or of course hope I can reasonably fix the ICEs I run into and > deal with the remaining cases as bugs?
The following variant of the patch with only one non-mergeable hunk (the gen_member_die one) allows me to build all of SPEC2006 with LTO and debug information enabled. Running the C++ testsuite with -g still reveals many ICEs mainly because we free too many TYPE/DECL_CONTEXTs. But even in its current state it will probably be useful to many people (not Fortran without the hack though - I'll see to add support for streaming TYPE_DECLs). Richard. 2009-12-12 Richard Guenther <rguent...@suse.de> * tree.c (free_lang_data_in_binfo): Do not free BINFO_OFFSET and BINFO_VPTR_FIELD. (free_lang_data_in_decl): Do not free DECL_SIZE_UNIT, DECL_SIZE, DECL_FIELD_OFFSET and DECL_FCONTEXT. (free_lang_data): Do not disable debuginfo. * lto-streamer-out.c (write_symbol_vec): Deal with non-constant DECL_SIZE. (pack_ts_base_value_fields): Write types with false TREE_ASM_WRITTEN. * dwarf2out.c (add_pure_or_virtual_attribute): Check for DECL_CONTEXT. (gen_type_die_for_member): Test for TYPE_STUB_DECL. * opts.c (decode_options): Do not disable var-tracking for lto. * dwarf2out.c (gen_member_die): Work around us not streaming TYPE_STUB_DECL. lto/ * lto.c (lto_fixup_field_decl): Fixup DECL_FIELD_OFFSET. (lto_post_options): Do not disable debuginfo. Index: gcc/tree.c =================================================================== *** gcc/tree.c.orig 2009-12-12 01:14:07.000000000 +0100 --- gcc/tree.c 2009-12-12 02:14:01.000000000 +0100 *************** free_lang_data_in_binfo (tree binfo) *** 4152,4164 **** gcc_assert (TREE_CODE (binfo) == TREE_BINFO); - BINFO_OFFSET (binfo) = NULL_TREE; BINFO_VTABLE (binfo) = NULL_TREE; - BINFO_VPTR_FIELD (binfo) = NULL_TREE; BINFO_BASE_ACCESSES (binfo) = NULL; BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE; BINFO_SUBVTT_INDEX (binfo) = NULL_TREE; - BINFO_VPTR_FIELD (binfo) = NULL_TREE; for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (binfo), i, t); i++) free_lang_data_in_binfo (t); --- 4152,4161 ---- *************** free_lang_data_in_decl (tree decl) *** 4380,4408 **** } } ! if (TREE_CODE (decl) == PARM_DECL ! || TREE_CODE (decl) == FIELD_DECL ! || TREE_CODE (decl) == RESULT_DECL) ! { ! tree unit_size = DECL_SIZE_UNIT (decl); ! tree size = DECL_SIZE (decl); ! if ((unit_size && TREE_CODE (unit_size) != INTEGER_CST) ! || (size && TREE_CODE (size) != INTEGER_CST)) ! { ! DECL_SIZE_UNIT (decl) = NULL_TREE; ! DECL_SIZE (decl) = NULL_TREE; ! } ! ! if (TREE_CODE (decl) == FIELD_DECL ! && DECL_FIELD_OFFSET (decl) ! && TREE_CODE (DECL_FIELD_OFFSET (decl)) != INTEGER_CST) ! DECL_FIELD_OFFSET (decl) = NULL_TREE; ! ! /* DECL_FCONTEXT is only used for debug info generation. */ ! if (TREE_CODE (decl) == FIELD_DECL) ! DECL_FCONTEXT (decl) = NULL_TREE; ! } ! else if (TREE_CODE (decl) == FUNCTION_DECL) { if (gimple_has_body_p (decl)) { --- 4377,4383 ---- } } ! if (TREE_CODE (decl) == FUNCTION_DECL) { if (gimple_has_body_p (decl)) { *************** free_lang_data (void) *** 4977,4989 **** diagnostic_finalizer (global_dc) = default_diagnostic_finalizer; diagnostic_format_decoder (global_dc) = default_tree_printer; - /* FIXME. We remove sufficient language data that the debug - info writer gets completely confused. Disable debug information - for now. */ - debug_info_level = DINFO_LEVEL_NONE; - write_symbols = NO_DEBUG; - debug_hooks = &do_nothing_debug_hooks; - return 0; } --- 4952,4957 ---- Index: gcc/lto-streamer-out.c =================================================================== *** gcc/lto-streamer-out.c.orig 2009-12-12 01:14:07.000000000 +0100 --- gcc/lto-streamer-out.c 2009-12-12 14:58:07.000000000 +0100 *************** pack_ts_base_value_fields (struct bitpac *** 342,348 **** bp_pack_value (bp, DECL_UNSIGNED (expr), 1); else if (TYPE_P (expr)) bp_pack_value (bp, TYPE_UNSIGNED (expr), 1); ! bp_pack_value (bp, TREE_ASM_WRITTEN (expr), 1); bp_pack_value (bp, TREE_NO_WARNING (expr), 1); bp_pack_value (bp, TREE_USED (expr), 1); bp_pack_value (bp, TREE_NOTHROW (expr), 1); --- 342,349 ---- bp_pack_value (bp, DECL_UNSIGNED (expr), 1); else if (TYPE_P (expr)) bp_pack_value (bp, TYPE_UNSIGNED (expr), 1); ! /* We write debug info two times, do not confuse the second one. */ ! bp_pack_value (bp, TYPE_P (expr) ? 0 : TREE_ASM_WRITTEN (expr), 1); bp_pack_value (bp, TREE_NO_WARNING (expr), 1); bp_pack_value (bp, TREE_USED (expr), 1); bp_pack_value (bp, TREE_NOTHROW (expr), 1); *************** write_symbol_vec (struct lto_streamer_ca *** 2335,2341 **** break; } ! if (kind == GCCPK_COMMON && DECL_SIZE (t)) size = (((uint64_t) TREE_INT_CST_HIGH (DECL_SIZE (t))) << 32) | TREE_INT_CST_LOW (DECL_SIZE (t)); else --- 2336,2344 ---- break; } ! if (kind == GCCPK_COMMON ! && DECL_SIZE (t) ! && TREE_CODE (DECL_SIZE (t)) == INTEGER_CST) size = (((uint64_t) TREE_INT_CST_HIGH (DECL_SIZE (t))) << 32) | TREE_INT_CST_LOW (DECL_SIZE (t)); else Index: gcc/dwarf2out.c =================================================================== *** gcc/dwarf2out.c.orig 2009-12-12 01:14:07.000000000 +0100 --- gcc/dwarf2out.c 2009-12-12 15:05:38.000000000 +0100 *************** add_pure_or_virtual_attribute (dw_die_re *** 16476,16482 **** 0)); /* GNU extension: Record what type this method came from originally. */ ! if (debug_info_level > DINFO_LEVEL_TERSE) add_AT_die_ref (die, DW_AT_containing_type, lookup_type_die (DECL_CONTEXT (func_decl))); } --- 16476,16483 ---- 0)); /* GNU extension: Record what type this method came from originally. */ ! if (debug_info_level > DINFO_LEVEL_TERSE ! && DECL_CONTEXT (func_decl)) add_AT_die_ref (die, DW_AT_containing_type, lookup_type_die (DECL_CONTEXT (func_decl))); } *************** gen_type_die_for_member (tree type, tree *** 17396,17402 **** /* If we're trying to avoid duplicate debug info, we may not have emitted the member decl for this function. Emit it now. */ ! if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) && ! lookup_decl_die (member)) { dw_die_ref type_die; --- 17397,17404 ---- /* If we're trying to avoid duplicate debug info, we may not have emitted the member decl for this function. Emit it now. */ ! if (TYPE_STUB_DECL (type) ! && TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) && ! lookup_decl_die (member)) { dw_die_ref type_die; *************** gen_member_die (tree type, dw_die_ref co *** 18537,18542 **** --- 18539,18554 ---- may have already been defined. Don't define them again, but do put them in the right order. */ + /* The Fortran FE creates non-variant copies of array descriptors + and uses TYPE_STUB_DECL to avoid ICEing here because the + FIELD_DECLs do not have the their type as DECL_CONTEXT. + ??? With LTO we free TYPE_STUB_DECL so we have to avoid ICEing + in other ways. At the same time we can end up with types + without a location set which we need to avoid as well. */ + if (DECL_CONTEXT (member) != type + || DECL_SOURCE_LOCATION (member) == UNKNOWN_LOCATION) + continue; + child = lookup_decl_die (member); if (child) splice_child_die (context_die, child); Index: gcc/opts.c =================================================================== *** gcc/opts.c.orig 2009-12-12 01:14:07.000000000 +0100 --- gcc/opts.c 2009-12-12 02:14:01.000000000 +0100 *************** decode_options (unsigned int argc, const *** 1129,1138 **** Otherwise, symbols will be privatized too early, causing link errors later. */ flag_whole_program = 0; - - /* FIXME lto. Disable var-tracking until debug information - is properly handled in free_lang_data. */ - flag_var_tracking = 0; #else error ("LTO support has not been enabled in this configuration"); #endif --- 1129,1134 ---- Index: gcc/lto/lto.c =================================================================== *** gcc/lto/lto.c.orig 2009-12-12 01:14:07.000000000 +0100 --- gcc/lto/lto.c 2009-12-12 02:14:01.000000000 +0100 *************** static void *** 1376,1382 **** lto_fixup_field_decl (tree t, void *data) { lto_fixup_decl_common (t, data); ! gcc_assert (no_fixup_p (DECL_FIELD_OFFSET (t))); LTO_FIXUP_SUBTREE (DECL_BIT_FIELD_TYPE (t)); LTO_FIXUP_SUBTREE (DECL_QUALIFIER (t)); gcc_assert (no_fixup_p (DECL_FIELD_BIT_OFFSET (t))); --- 1376,1382 ---- lto_fixup_field_decl (tree t, void *data) { lto_fixup_decl_common (t, data); ! LTO_FIXUP_SUBTREE (DECL_FIELD_OFFSET (t)); LTO_FIXUP_SUBTREE (DECL_BIT_FIELD_TYPE (t)); LTO_FIXUP_SUBTREE (DECL_QUALIFIER (t)); gcc_assert (no_fixup_p (DECL_FIELD_BIT_OFFSET (t))); Index: gcc/lto/lto-lang.c =================================================================== *** gcc/lto/lto-lang.c.orig 2009-12-12 01:14:07.000000000 +0100 --- gcc/lto/lto-lang.c 2009-12-12 02:14:01.000000000 +0100 *************** lto_handle_option (size_t scode, const c *** 646,661 **** static bool lto_post_options (const char **pfilename ATTRIBUTE_UNUSED) { - /* FIXME lto: We have stripped enough type and other - debugging information out of the IR that it may - appear ill-formed to dwarf2out, etc. We must not - attempt to generate debug info in lto1. A more - graceful solution would disable the option flags - rather than ignoring them, but we'd also have to - worry about default debugging options. */ - write_symbols = NO_DEBUG; - debug_info_level = DINFO_LEVEL_NONE; - /* -fltrans and -fwpa are mutually exclusive. Check for that here. */ if (flag_wpa && flag_ltrans) error ("-fwpa and -fltrans are mutually exclusive"); --- 646,651 ----