On Mon, Aug 18, 2014 at 12:46 PM, Richard Biener <richard.guent...@gmail.com> wrote: > On Fri, Aug 15, 2014 at 9:59 PM, Aldy Hernandez <al...@redhat.com> wrote: >> So... I've been getting my feet wet with LTO and debugging and I noticed a >> seemingly unrelated yet annoying problem. On x86-64, >> gcc.dg/guality/pr48437.c fails when run in LTO mode. >> >> I've compared the dwarf output with and without LTO, and I noticed that the >> DW_TAG_lexical_block is missing from the LTO case. >> >> The relevant bit is that without LTO, we have a DW_TAG_lexical_block for >> lines 3-6, which is not present in the LTO case: >> >> 1 volatile int i; >> 2 for (i = 3; i < 7; ++i) >> 3 { >> 4 extern int i; >> 5 asm volatile (NOP : : : "memory"); >> 6 } >> >> The reason this tag is not generated is because gen_block_die() unsets >> must_output_die because there are no BLOCK_VARS associated with the BLOCK. >> >> must_output_die = ((BLOCK_VARS (stmt) != NULL >> || BLOCK_NUM_NONLOCALIZED_VARS (stmt)) >> && (TREE_USED (stmt) >> || TREE_ASM_WRITTEN (stmt) >> || BLOCK_ABSTRACT (stmt))); >> >> And there is no block var because the streamer purposely avoided streaming >> an extern block var: >> >> /* We avoid outputting external vars or functions by reference >> to the global decls section as we do not want to have them >> enter decl merging. This is, of course, only for the call >> for streaming BLOCK_VARS, but other callers are safe. */ >> /* ??? FIXME wrt SCC streaming. Drop these for now. */ >> if (VAR_OR_FUNCTION_DECL_P (t) >> && DECL_EXTERNAL (t)) >> ; /* stream_write_tree_shallow_non_ref (ob, t, ref_p); */ >> else >> stream_write_tree (ob, t, ref_p); >> >> I naively tried to uncomment the offending line, but that brought about >> other problems in DFS assertions. >> >> I wasn't on the hunt for this, but I'm now curious. Can you (or anyone >> else) pontificate on this? Do we avoid streaming extern block variables by >> design? > > Apart from other comments about emitting DIEs early the commented > code above tried to "force" to not put 't' into the global decls table > but retain it as local tree to avoid (as Honza says) merging it with > other entities and thus screwing up DECL_CHAIN. > > With the SCC way this didn't work out (you can't simply do > stream_write_tree_shallow_non_ref here for reasons I don't remember). > The ??? comment means I've wanted to come back to this... ;) > "shallow non-ref" means treat 't' as !ref but not the trees it references. > > Note that the biggest "hack" wrt lexical scopes is that we don't stream > any abstract origins > > /* Write all pointer fields in the TS_BLOCK structure of EXPR to output > block OB. If REF_P is true, write a reference to EXPR's pointer > fields. */ > > static void > write_ts_block_tree_pointers (struct output_block *ob, tree expr, bool ref_p) > { > streamer_write_chain (ob, BLOCK_VARS (expr), ref_p); > > stream_write_tree (ob, BLOCK_SUPERCONTEXT (expr), ref_p); > > /* Stream BLOCK_ABSTRACT_ORIGIN for the limited cases we can handle - those > that represent inlined function scopes. > For the rest them on the floor instead of ICEing in dwarf2out.c. */ > if (inlined_function_outer_scope_p (expr)) > { > tree ultimate_origin = block_ultimate_origin (expr); > stream_write_tree (ob, ultimate_origin, ref_p); > } > else > stream_write_tree (ob, NULL_TREE, ref_p); > > which makes early inlined functions behave differently (?) in the > debugger with LTO than without (you still get blocks, but they > do not refer to the out-of-line copy by reference but get fully > re-created with DIEs for each inline instance). But maybe the > abstract origins are only a dwarf-size optimization here.
The following seems to fix it. In testing now. Richard. > Richard. > >> Thanks. >> Aldy
p5
Description: Binary data