------- Comment #2 from jakub at gcc dot gnu dot org 2008-08-01 16:13 -------
I've managed to reproduce it, only happens with -mtune=i586 apparently.
Without my patch GCC doesn't ICE, just creates bad unwind info.
In *.greg dump we have (in uname__uname_lt):
(insn:HI 10 9 11 3 uname.adb:615 (parallel [
(set (reg/f:SI 7 sp)
(plus:SI (reg/f:SI 7 sp)
(const_int -12 [0xfffffffffffffff4])))
(clobber (reg:CC 17 flags))
]) 249 {*addsi_1} (nil))
(insn:HI 11 10 12 3 uname.adb:615 (set (mem/i:SI (pre_dec:SI (reg/f:SI 7 sp))
[0 S4 A32])
(reg/v:SI 0 ax [orig:70 left ] [70])) 40 {*pushsi2} (nil))
(call_insn:HI 12 11 13 3 uname.adb:615 (call (mem:QI (symbol_ref:SI
("namet__get_name_string") [flags 0x41] <function_decl 0x7fa5
(const_int 16 [0x10])) 601 {*call_0} (nil)
(nil))
(insn:HI 13 12 14 3 uname.adb:616 (parallel [
(set (reg/f:SI 5 di [88])
(plus:SI (reg/f:SI 7 sp)
(const_int 16 [0x10])))
(clobber (reg:CC 17 flags))
]) 249 {*addsi_1} (expr_list:REG_EQUIV (plus:SI (reg/f:SI 7 sp)
(const_int 16 [0x10]))
(nil)))
...
(insn:HI 16 15 173 3 uname.adb:616 (parallel [
(set (reg/f:SI 7 sp)
(plus:SI (reg/f:SI 7 sp)
(const_int 16 [0x10])))
(clobber (reg:CC 17 flags))
]) 249 {*addsi_1} (nil))
...
(insn:HI 26 155 27 3 uname.adb:616 (parallel [
(set (reg/f:SI 7 sp)
(plus:SI (reg/f:SI 7 sp)
(const_int -4 [0xfffffffffffffffc])))
(clobber (reg:CC 17 flags))
]) 249 {*addsi_1} (nil))
(insn:HI 27 26 28 3 uname.adb:616 (set (mem/i:SI (pre_dec:SI (reg/f:SI 7 sp))
[0 S4 A32])
(reg:SI 1 dx [73])) 40 {*pushsi2} (nil))
(insn:HI 28 27 29 3 uname.adb:616 (set (mem/f/i:SI (pre_dec:SI (reg/f:SI 7 sp))
[0 S4 A32])
(symbol_ref:SI ("namet__name_buffer") [flags 0x40] <var_decl
0x7fa51618a140 namet__name_buffer>)) 40 {*pushsi2} (nil))
(insn:HI 29 28 30 3 uname.adb:616 (set (mem/f/i:SI (pre_dec:SI (reg/f:SI 7 sp))
[0 S4 A32])
(reg/f:SI 5 di [88])) 40 {*pushsi2} (nil))
(call_insn:HI 30 29 33 3 uname.adb:616 (set (reg:SI 0 ax)
(call (mem:QI (symbol_ref:SI ("memcpy") [flags 0x41] <function_decl
0x7fa5161dc5b0 memcpy>) [0 S1 A8])
(const_int 16 [0x10]))) 839 {*call_value_0}
(expr_list:REG_EH_REGION (const_int 0 [0x0])
(nil))
(nil))
and no stack adjustments in between. The first insn listed above starts at
args_size 0 level, then the first call is at args_size 16 level, then we pop up
the stack back to args_size 0 level, decrease by 4 bytes again and push 3 * 4
bytes, so again memcpy is at args_size 16 level.
But *.postreload decides to change insn 16 into:
(insn:HI 16 15 173 3 uname.adb:616 (set (reg/f:SI 7 sp)
(reg/f:SI 5 di [88])) 47 {*movsi_1} (nil))
which is equivalent to the sp = sp + 16, but unfortunately is something
stack_adjust_offset doesn't track for the args_size adjustments. Which means
that args_size on the second call will be 32 instead of the correct 16, and
with my patch it ICEs because label 127 is reachable both from a place where
args_size is 0 (jump_insn 8) and from a place where gcc believes it is 16
(after the memcpy call).
Not sure what's the best way to fix this though. I can surely remove the
assert and let it silently generate invalid unwind info, but I don't think
that's a good idea. So, either reload is changed not to do this (pointless)
replacement,
or perhaps the dwarf2out.c could assume if sp is set to some register (rather
than sp + const), args_size should be reset to 0 (though, I really don't know
if
that would be a safe assumption). Tracking all registers that might ever
contain some pointers into the stack would be a nightmare.
--
jakub at gcc dot gnu dot org changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jason at gcc dot gnu dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36998