This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Avoid wrong code with nonlocal gotos on ARM
- From: Waldek Hebisch <hebisch at math dot uni dot wroc dot pl>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 23 Nov 2003 16:12:54 +0100 (MET)
- Subject: [PATCH] Avoid wrong code with nonlocal gotos on ARM
At least on ARM gcc may generate wrong code for nonlocal gotos.
The program below shows the problem. Compile as:
gcc -O2 nlgpp.c
When compiled at `-O' the program prints `OK'. At `-O2' the
program prints `failed 3'.
Note that the compiler crashes on the program, to compile one need
first to apply patch from:
http://gcc.gnu.org/ml/gcc-patches/2003-11/msg01276.html
After applying the above mentioned patch the program compiles,
but gives incorrect result. AFAIKS the scheduler exchanged
instructions so one instruction was executed before restoring
neccesary registers (static chain and frame pointer) were restored.
My solution is to copy code from `expand_builtin_setjmp_receiver'
to `expand_nl_goto_receiver' -- the code appearently corresponds to:
2001-02-07 Bernd Schmidt <bernds@redhat.com>
* builtins.c (expand_builtin_setjmp_receiver): Emit an ASM_INPUT as
a scheduling barrier at the end.
Comment in `builtins.c' says that builtin_setjmp/longjmp code is mostly
copied from nonlocal goto handling, and appearently the fix was not
propagated back.
I have bootstraped gcc-3.3.2 and gcc-3.4-20031015 (the latest snapshot where
I am able to build Ada) on i386-linux (Debian Woody on Athlon XP). I ran the
testsuite and I saw no new failures.
If OK please apply, I have no CVS write access.
The testcase:
------------------------<cut here>-------------------
extern int printf(char * fmt, ...);
void Fail(void)
{
printf ("failed\n");
}
typedef void (*pfun)(void);
void Recursive (int n, pfun Proc)
{
__label__ l1;
/* __label__ l2; */
void DoGoto(void)
{
goto l1;
}
if (n==3) {
Recursive (n - 1, DoGoto);
} else if (n>0) {
Recursive (n - 1, Proc);
} else {
(*Proc)();
}
goto l2;
l1:
if (n==3) {
printf("OK\n");
} else {
printf("failed %d\n", n);
}
l2:;
}
int main(void)
{
Recursive (10, Fail);
return 0;
}
----------------------------<cut here>---------------
The patch:
diff -ru ../gcc_t/gcc-3.3.1/gcc/stmt.c gcc-3.3.1/gcc/stmt.c
--- ../gcc_t/gcc-3.3.1/gcc/stmt.c Thu Jun 12 03:05:45 2003
+++ gcc-3.3.1/gcc/stmt.c Thu Oct 9 00:26:01 2003
@@ -3557,6 +3557,14 @@
static void
expand_nl_goto_receiver ()
{
+ /* Clobber the FP when we get here, so we have to make sure it's
+ marked as used by this function. */
+ emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+
+ /* Mark the static chain as clobbered here so life information
+ doesn't get messed up for it. */
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
+
#ifdef HAVE_nonlocal_goto
if (! HAVE_nonlocal_goto)
#endif
@@ -3605,6 +3613,12 @@
if (HAVE_nonlocal_goto_receiver)
emit_insn (gen_nonlocal_goto_receiver ());
#endif
+ /* @@@ This is a kludge. Not all machine descriptions define a blockage
+ insn, but we must not allow the code we just generated to be reordered
+ by scheduling. Specifically, the update of the frame pointer must
+ happen immediately, not later. So emit an ASM_INPUT to act as blockage
+ insn. */
+ emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
}
/* Make handlers for nonlocal gotos taking place in the function calls in
--
Waldek Hebisch
hebisch@math.uni.wroc.pl