I have real problems trying to get to the root of bug in
builtin_setjmp implementation and seek anyones wisdom on what I have
found and a way forward.
Sometimes it's not always clear which part is wrong - when presented
with mismatches.
I will post a bug report when I have got a little closer.
The problem I was looking at is the frame pointer being wrong on the AVR
target. (Stack and PC are ok)
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21078 - but ANY
setjmp/longjump has the problem.
I traced this down to the handling of the frame pointer: by the receiver
- (which is the code the longjmp will jump back to)
Setjmp: - save pointer
Buf[0] = Virtual_stack_var
Longjmp: get pointer
Hard_Frame_pointer=buf[0]
Receiver: put back in frame pointer
Virtual_stack_var = Hard_Frame_pointer
The uniqueness on AVR is that Frame_pointer (and stack pointer) are 1
byte different from the first stack element. So the Virtual_stack_var is
1 different from the frame_pointer
i.e.
#define STACK_GROWS_DOWNWARD
#define STARTING_FRAME_OFFSET 1
#define STACK_POINTER_OFFSET 1
That's ok as this is recognized by instantiate_virtual_regs, which
makes the replacements later. In this case
Buf[0] = Frame_pointer+1
..
..
Frame_pointer = Virtual_stack_var - 1
However, what is happening is that an earlier pass noted in RTL dump
file "sibling" eliminates the receiver code block. So the frane point
is not reset correctly, and ends up being 1 out (which is bad). Other
targets may survive if they don't have offset between stack and pointers.
So where do I look to find out why this is happening? Does the RTL have
something missing or is the other pass not checking?
The RTL that gets eliminated is:
;; Start of basic block () -> 5
(code_label/s 13 12 14 5 4 "" [2 uses])
(note 14 13 15 5 [bb 5] NOTE_INSN_BASIC_BLOCK)
(insn 15 14 16 5 built-in-setjmp.c:17 (use (reg/f:HI 28 r28)) -1 (nil))
(insn 16 15 17 5 built-in-setjmp.c:17 (clobber (reg:HI 2 r2)) -1 (nil))
(insn 17 16 18 5 built-in-setjmp.c:17 (set (reg/f:HI 37 virtual-stack-vars)
(reg/f:HI 28 r28)) -1 (nil))
(insn 18 17 19 5 built-in-setjmp.c:17 (clobber (reg/f:HI 28 r28)) -1 (nil))
(insn 19 18 20 5 built-in-setjmp.c:17 (asm_input/v ("") 0) -1 (nil))
;; End of basic block 5 -> ( 6)
The second PROBLEM I noted is that gcc creates RTL for TWO receivers for
a setjmp. One is naturally from "expand_builtin_setjmp_receiver" but
there is then another one just after created by
"expand_nl_goto_receiver" in stmt.c- whats all this about?
Despite having two, both get optimised out!
Andy