Bug 34879 - __builtin_setjmp / __builtin_longjmp fails stack frame address with O2, O3 and Os
Summary: __builtin_setjmp / __builtin_longjmp fails stack frame address with O2, O3 an...
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: 4.4.0
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2008-01-20 03:34 UTC by Paulo Marques
Modified: 2008-06-02 23:48 UTC (History)
3 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: avr-*-*
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2008-04-04 21:40:52

Setjmp patch for AVR (1.42 KB, patch)
2008-03-29 11:37 UTC, Andy Hutchinson
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Paulo Marques 2008-01-20 03:34:04 UTC
The test case is gcc.c-torture/execute/built-in-setjmp.c.

The __builtin_setjmp stores Y+1 in the setjmp buffer. With -O0 the first
instruction after the jmp does a "sbiw r28, 1" that restores the
original value, but for some reason, with higher optimization levels,
this instruction is optimized away, leaving R28 pointing to the wrong
address by one.

The __builtin_setjmp code:

  if (__builtin_setjmp (buf))
16a:	ce 01       	movw	r24, r28
16c:	01 96       	adiw	r24, 0x01	; 1
  Notice the increment here, before storing R28

16e:	90 93 07 01 	sts	0x0107, r25
172:	80 93 06 01 	sts	0x0106, r24
176:	8f ee       	ldi	r24, 0xEF	; 239
178:	90 e0       	ldi	r25, 0x00	; 0
17a:	90 93 09 01 	sts	0x0109, r25
17e:	80 93 08 01 	sts	0x0108, r24
182:	ed b7       	in	r30, 0x3d	; 61
184:	fe b7       	in	r31, 0x3e	; 62
186:	f0 93 0b 01 	sts	0x010B, r31
18a:	e0 93 0a 01 	sts	0x010A, r30

The __builtin_longjmp code:

  __builtin_longjmp (buf, 1);
10c:	e0 91 08 01 	lds	r30, 0x0108
110:	f0 91 09 01 	lds	r31, 0x0109
114:	c0 91 06 01 	lds	r28, 0x0106
118:	d0 91 07 01 	lds	r29, 0x0107
11c:	80 91 0a 01 	lds	r24, 0x010A
120:	90 91 0b 01 	lds	r25, 0x010B

no decrement, R28 is used "as is".
Comment 1 Andy Hutchinson 2008-03-29 11:37:05 UTC
Created attachment 15395 [details]
Setjmp patch for AVR

The attached patch is a fix for AVR target. MIPS does something similar to get around same issue.

The real problem is with gcc builin setjmp receiver being removed by optimizers.
Optimizers think that frame_pointer load in receiver is unneeded and remove it! 

The patch loads the frame pointer in the nonlocal_goto, making the receiver (where it jumps to) empty, so bad optimization cannot remove it. Additionally, it avoids the unnecessary arithmetic around frame pointer offsets.

This patch was tested and the testcase passes.

Further changes may be required in the future if AVR 24bit jumps are to be supported.
Comment 2 Andy Hutchinson 2008-06-02 22:09:07 UTC
Subject: Bug 34879

Author: hutchinsonandy
Date: Mon Jun  2 22:08:25 2008
New Revision: 136297

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=136297
PR target/34879
* config/avr/avr.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Redefine.
(avr_builtin_setjmp_frame_value): New function.
* config/avr/avr.md (nonlocal_goto_receiver): Define.
(nonlocal_goto): Define.


Comment 3 Eric Weddington 2008-06-02 23:48:31 UTC
Fixed in 4.4.0.