I have realised that part of the problem is that the receiver block has no incoming edges so cfgcleanup removes it as unreachable block - right?

So any target that need a non trivial receiver for builtin_setjmp will not work? That would mean any that have an offset between stack and pointers?

I guess the same problem exists for non-local goto?

I am not convinced it could be this wrong. So please comment and suggest solution - I'm sure I can write target handler but it seems so wrong to leave this as issue open.


Andy



Andrew Hutchinson wrote:
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











Reply via email to