------- 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