This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


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

IA-64 non-call exceptions


I've been trying to get non-call exceptions working on IA-64.

The biggest issue is that (unlike the DWARF 2 unwinder) the IA-64
unwinder can't cope with unwinding leaf functions.  There are several
reasons for this, but one is that such functions don't save a copy of
the return link but leave it in br0; the unwinder can't cope with
that.  In any case, the compiler/assembler outputs no unwind
information for leaf functions so the unwinder aborts.

The unwinder could be altered to unwind leaf functions if the compiler
could be persuaded to output minimal unwinder info, but as this would
require somewhat extensive changes I've taken another approach,
effectively to remove leaf function prologue/epilogue optimizations
when using -fnon-call-exceptions.  This obviously has a negative
performance impact, so perhaps something else is called for.

Also, I've written a MD_FALLBACK_FRAME_STATE_FOR for Linux.  This
restores the registers that seem to be necessary, but I may have
missed something.

This mechanism passes the gcj test suite, which is as far as I know
the only test we have for non-call exceptions.

Andrew.

2001-06-19  Andrew Haley  <aph@cambridge.redhat.com>

	* config/ia64/ia64.c (find_gr_spill): When using
	-fnon-call-exceptions, treat all functions as non-leaf.
	(ia64_compute_frame_size): Ditto.
	(ia64_initial_elimination_offset): Ditto.
	(ia64_expand_prologue): Ditto.
	(ia64_expand_epilogue): Ditto.
	(ia64_epilogue_uses): Ditto.

	* config/ia64/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.

Index: config/ia64/ia64.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.c,v
retrieving revision 1.72.2.15
diff -p -2 -c -r1.72.2.15 ia64.c
*** ia64.c	2001/05/22 20:04:11	1.72.2.15
--- ia64.c	2001/06/19 14:55:54
*************** find_gr_spill (try_locals)
*** 1202,1206 ****
    /* If this is a leaf function, first try an otherwise unused
       call-clobbered register.  */
!   if (current_function_is_leaf)
      {
        for (regno = GR_REG (1); regno <= GR_REG (31); regno++)
--- 1202,1207 ----
    /* If this is a leaf function, first try an otherwise unused
       call-clobbered register.  */
!   if (current_function_is_leaf
!       && ! flag_non_call_exceptions)
      {
        for (regno = GR_REG (1); regno <= GR_REG (31); regno++)
*************** ia64_compute_frame_size (size)
*** 1406,1410 ****
      }
  
!   if (! current_function_is_leaf)
      {
        /* Emit a save of BR0 if we call other functions.  Do this even
--- 1407,1412 ----
      }
  
!   if (! current_function_is_leaf
!       || flag_non_call_exceptions)
      {
        /* Emit a save of BR0 if we call other functions.  Do this even
*************** ia64_compute_frame_size (size)
*** 1513,1517 ****
       if we are a leaf function, there's no one to which we need to provide
       a scratch area.  */
!   if (current_function_is_leaf)
      total_size = MAX (0, total_size - 16);
  
--- 1515,1520 ----
       if we are a leaf function, there's no one to which we need to provide
       a scratch area.  */
!   if (current_function_is_leaf
!       && ! flag_non_call_exceptions)
      total_size = MAX (0, total_size - 16);
  
*************** ia64_initial_elimination_offset (from, t
*** 1539,1543 ****
        if (to == HARD_FRAME_POINTER_REGNUM)
  	{
! 	  if (current_function_is_leaf)
  	    offset = -current_frame_info.total_size;
  	  else
--- 1542,1547 ----
        if (to == HARD_FRAME_POINTER_REGNUM)
  	{
! 	  if (current_function_is_leaf
! 	      && ! flag_non_call_exceptions)
  	    offset = -current_frame_info.total_size;
  	  else
*************** ia64_initial_elimination_offset (from, t
*** 1547,1551 ****
        else if (to == STACK_POINTER_REGNUM)
  	{
! 	  if (current_function_is_leaf)
  	    offset = 0;
  	  else
--- 1551,1556 ----
        else if (to == STACK_POINTER_REGNUM)
  	{
! 	  if (current_function_is_leaf
! 	      && ! flag_non_call_exceptions)
  	    offset = 0;
  	  else
*************** ia64_expand_prologue ()
*** 2076,2080 ****
       if we'd not allocated a local register for the job.  */
    if (current_frame_info.reg_save_ar_pfs == 0
!       && ! current_function_is_leaf)
      {
        reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
--- 2081,2085 ----
       if we'd not allocated a local register for the job.  */
    if (current_frame_info.reg_save_ar_pfs == 0
!       && (! current_function_is_leaf || flag_non_call_exceptions))
      {
        reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
*************** ia64_expand_epilogue (sibcall_p)
*** 2258,2262 ****
        emit_move_insn (reg, alt_reg);
      }
!   else if (! current_function_is_leaf)
      {
        alt_regno = next_scratch_gr_reg ();
--- 2263,2268 ----
        emit_move_insn (reg, alt_reg);
      }
!   else if (! current_function_is_leaf
! 	   || flag_non_call_exceptions)
      {
        alt_regno = next_scratch_gr_reg ();
*************** ia64_epilogue_uses (regno)
*** 6235,6239 ****
    if (regs_ever_live[AR_LC_REGNUM] && regno == AR_LC_REGNUM)
      return 1;
!   if (! current_function_is_leaf && regno == AR_PFS_REGNUM)
      return 1;
    if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM)
--- 6241,6246 ----
    if (regs_ever_live[AR_LC_REGNUM] && regno == AR_LC_REGNUM)
      return 1;
!   if (regno == AR_PFS_REGNUM
!       && (! current_function_is_leaf || flag_non_call_exceptions))
      return 1;
    if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM)
Index: config/ia64/linux.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/linux.h,v
retrieving revision 1.8
diff -p -2 -c -r1.8 linux.h
*** linux.h	2000/11/02 23:29:10	1.8
--- linux.h	2001/06/19 14:55:54
*************** do {							\
*** 57,59 ****
--- 57,115 ----
  } while (0)
  
+ 
+ #include <signal.h>
+ #include <sys/ucontext.h>
+ 
+ #define IA64_GATE_AREA_START 0xa000000000000100LL
+ #define IA64_GATE_AREA_END   0xa000000000010000LL
+ 
+ #define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)		\
+   if ((CONTEXT)->rp >= IA64_GATE_AREA_START				\
+       && (CONTEXT)->rp < IA64_GATE_AREA_END)				\
+     {									\
+       struct sigframe {							\
+ 	unsigned char pad[16];						\
+ 	struct siginfo info;						\
+ 	struct sigcontext sc;						\
+       } *frame_ = (struct sigframe *)(CONTEXT)->psp;			\
+       struct sigcontext *sc_ = &frame_->sc;				\
+ 									\
+       /* Restore scratch registers in case the unwinder needs to	\
+ 	 refer to a value stored in one of them.  */			\
+       {									\
+ 	int i_;								\
+ 									\
+ 	for (i_ = 2; i_ < 4; i_++)					\
+ 	  (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];		\
+ 	for (i_ = 8; i_ < 12; i_++)					\
+ 	  (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];		\
+ 	for (i_ = 14; i_ < 32; i_++)					\
+ 	  (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_];		\
+       }	    								\
+ 	  								\
+       (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs);				\
+       (CONTEXT)->lc_loc = &(sc_->sc_ar_lc);				\
+       (CONTEXT)->unat_loc = &(sc_->sc_ar_unat);				\
+       (CONTEXT)->pr = sc_->sc_pr;					\
+       (CONTEXT)->psp = sc_->sc_gr[12];					\
+ 									\
+       /* Don't touch the branch registers.  The kernel doesn't		\
+ 	 pass the preserved branch registers in the sigcontext but	\
+ 	 leaves them intact, so there's no need to do anything		\
+ 	 with them here.  */						\
+ 									\
+       {									\
+ 	unsigned long sof = sc_->sc_cfm & 0x7f;				\
+ 	(CONTEXT)->bsp = (unsigned long)				\
+ 	  ia64_rse_skip_regs (sc_->sc_ar_bsp, -sof);			\
+       }									\
+ 									\
+       (FS)->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL;		\
+       (FS)->curr.reg[UNW_REG_RP].val 					\
+ 	= (unsigned long)&(sc_->sc_ip) - (CONTEXT)->psp;		\
+       (FS)->curr.reg[UNW_REG_RP].when = -1;				\
+ 									\
+       goto SUCCESS;							\
+     }
+ 
  /* End of linux.h */


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