This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]