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 crash compiling nonlocal gotos on ARM


The program below make GCC ICE when targetting ARM. The problem
showed in GNU Pascal (the program below is a C translation of
`fproc.pas' program from GPC testsuite). My finding was that 
on arm trampolines were created using library call (to 'memcpy').
That created additional basic block and requires calling 
`expand_end_target_temps' which calls `expand_nl_goto_receivers'. 
On all targets `expand_nl_goto_receivers' is called before creating
trampolines, so on arm it was called twice. Appearently, the second
call wiped some info gathered between first and second call to 
`expand_nl_goto_receivers' cousing crash. I avoid the problem forbiding
call to 'memcpy' (backend then generates inline loop).

On i386 trampolines are created without need for library call, so 
the patch does not chenge the code. I have checked that the patch fixes
3 crashes in GPC testsuite on ARM with no regression. ATM I not able
to test GCC on ARM.

The testcase:
-------------------------------<cut here>------------------------
extern int printf(const char *, ...);
int i;

typedef int (*ifun)(void);

void print(ifun frtn)
{
	printf("%3d   formal routine =", frtn());
}

void lvl1(ifun form)
{
   __label__ bar;
   int loc;

  int eval(void)
  {
     if (loc == 8) {
	printf(" non-local jump\n");
	goto bar;
     }
     return loc;
  }
  loc = i;
  i = i - 1;
  if ((loc == 4) || (loc == 8)) {
     lvl1(eval);
  } else if (loc > 0) {
     lvl1(form);
  }
 bar: printf("Stack frame:%3d   formal print =", loc);
  print(form);
  printf("%3d\n", form());
}
int geval(void)
{
   return i;
}

int main(void)
{
  printf("This should print levels 0-3, with formal values of 4.\n");
  printf("Level 4 should jump to level 8.\n");
  printf("Finally levels 8-10 should print with formal values of -1.\n");
  i = 10;
  lvl1(geval);
  return 0;
}
---------------------<cut here>-----------------------------------

ChangeLog:
        * functin.c (expand_function_end): pass BLOCK_OP_NO_LIBCALL
          option to `emit_block_move' to avoid crash on ARM.

The patch:

diff -ru ../gcc_t/gcc-3.3.1/gcc/function.c gcc-3.3.1/gcc/function.c
--- ../gcc_t/gcc-3.3.1/gcc/function.c	Wed Sep  3 00:05:10 2003
+++ gcc-3.3.1/gcc/function.c	Wed Oct  8 05:24:07 2003
@@ -6891,8 +6891,8 @@
       tramp = round_trampoline_addr (XEXP (tramp, 0));
 #ifdef TRAMPOLINE_TEMPLATE
       blktramp = replace_equiv_address (initial_trampoline, tramp);
       emit_block_move (blktramp, initial_trampoline,
-		       GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
+		       GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NO_LIBCALL);
 #endif
       INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context);
       seq = get_insns ();

-- 
                              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]