http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50191
--- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> 2011-09-05
08:23:56 UTC ---
The problem is that at var-tracking time the expression contains another
debug_expr (as at that point the register 12 which held the toc address is no
longer live):
(debug_insn 9141 9142 8803 4 (var_location:DI D#142 (mem/u/c:DI (lo_sum:DI
(debug_expr:DI D#146)
(const:DI (unspec:DI [
(symbol_ref/u:DI ("*.LC8") [flags 0x2])
] UNSPEC_TOCREL))) [23 S8 A8])) -1
(nil))
and rs6000_delegitimize_address only delegitimizes if it is a register:
&& ((GET_CODE (XEXP (x, 0)) == REG
&& (REGNO (XEXP (x, 0)) == TOC_REGISTER
|| TARGET_MINIMAL_TOC
|| TARGET_CMODEL != CMODEL_SMALL))
So this isn't delegitmized nor avoid_constant_pool_reference transformed at
var-tracking time. At dwarf2out.c, it is delegitimized, but mem_loc_descriptor
attempts to avoid_constant_pool_reference only if emitting a DW_OP_deref*
failed. I'll attach a patch which attempts avoid_constant_pool_reference there
first, which is one way of fixing this. Another would be to handle DEBUG_EXPR
the same as REG, i.e. add || (GET_CODE (XEXP (x, 0)) == DEBUG_EXPR &&
(TARGET_MINIMAL_TOC || TARGET_CMODEL != CMODEL_SMALL)) to the condition (and,
btw, the GET_CODE ... == REG should be replaced with REG_P (...)).
I'd say we want both, as while I can do this change in mem_loc_descriptor, I
can't do it in loc_descriptor where we strongly want to prefer a MEM over
avoid_constant_pool_reference.
That said, I doubt we can guarantee that gcc will never emit something like
that, even with both of the patches. So IMHO the linker needs to be fixed
nevertheless.