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]

Re: on non-local gotos and computed jumps


On Wed, Dec 20, 2000 at 12:53:01PM -0200, Alexandre Oliva wrote:
> [WRT a new port] gcc.c-torture/execute/920501-7.c has uncovered what
> I believe to be a generic problem...

In summary of what Alex deduced, we cannot tell the difference between
a non-local goto and a computed goto when it comes time to construct the
CFG.  If there exists exactly one computed goto target in a function,
we'll create incorrect edges leading to the function being miscompiled.

Modified test case attached.

Fixed thus.


r~
#ifdef STACK_SIZE
#define DEPTH ((STACK_SIZE) / 512 + 1)
#else
#define DEPTH 1000
#endif

#if ! defined (NO_LABEL_VALUES) && !defined (NO_TRAMPOLINES)
x(a)
{
  __label__ xlab;
  void y(a)
    {
      void *x = &&llab;
      if (a==-1)
	goto *x;
      if (a==0)
	goto xlab;
    llab:
      y (a-1);
    }
  y (a);
 xlab:;
  return a;
}
#endif

main ()
{
#if ! defined (NO_LABEL_VALUES) && !defined (NO_TRAMPOLINES)
  if (x (DEPTH) != DEPTH)
    abort ();
#endif
  exit (0);
}
        * rtl.h (REG_NON_LOCAL_GOTO): New.
        * rtl.c (reg_note_name): Update.
        * stmt.c (expand_goto): Emit a REG_NON_LOCAL_GOTO note.
        * builtins.c (expand_builtin_longjmp): Likewise.
        * flow.c (make_edges): Check for REG_NON_LOCAL_GOTO and do
        not emit an edge.

Index: builtins.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/builtins.c,v
retrieving revision 1.80
diff -c -p -d -r1.80 builtins.c
*** builtins.c	2000/12/06 03:09:49	1.80
--- builtins.c	2000/12/21 01:08:25
*************** void
*** 649,655 ****
  expand_builtin_longjmp (buf_addr, value)
       rtx buf_addr, value;
  {
!   rtx fp, lab, stack;
    enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
  
    if (setjmp_alias_set == -1)
--- 649,655 ----
  expand_builtin_longjmp (buf_addr, value)
       rtx buf_addr, value;
  {
!   rtx fp, lab, stack, insn;
    enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
  
    if (setjmp_alias_set == -1)
*************** expand_builtin_longjmp (buf_addr, value)
*** 706,711 ****
--- 706,723 ----
  	  emit_indirect_jump (lab);
  	}
      }
+ 
+   /* Search backwards and mark the jump insn as a non-local goto.
+      Note that this precludes the use of __builtin_longjmp to a
+      __builtin_setjmp target in the same function.  However, we've
+      already cautioned the user that these functions are for
+      internal exception handling use only.  */
+   for (insn = get_last_insn ();
+        GET_CODE (insn) != JUMP_INSN;
+        insn = PREV_INSN (insn))
+     continue;
+   REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
+ 				      REG_NOTES (insn));
  }
  
  /* Get a MEM rtx for expression EXP which is the address of an operand
Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.361
diff -c -p -d -r1.361 flow.c
*** flow.c	2000/12/20 15:48:26	1.361
--- flow.c	2000/12/21 01:08:25
*************** make_edges (label_value_list)
*** 1094,1105 ****
  	{
  	  rtx tmp;
  
  	  /* ??? Recognize a tablejump and do the right thing.  */
! 	  if ((tmp = JUMP_LABEL (insn)) != NULL_RTX
! 	      && (tmp = NEXT_INSN (tmp)) != NULL_RTX
! 	      && GET_CODE (tmp) == JUMP_INSN
! 	      && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
! 		  || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
  	    {
  	      rtvec vec;
  	      int j;
--- 1094,1110 ----
  	{
  	  rtx tmp;
  
+ 	  /* Recognize a non-local goto as a branch outside the
+ 	     current function.  */
+ 	  if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
+ 	    ;
+ 
  	  /* ??? Recognize a tablejump and do the right thing.  */
! 	  else if ((tmp = JUMP_LABEL (insn)) != NULL_RTX
! 		   && (tmp = NEXT_INSN (tmp)) != NULL_RTX
! 		   && GET_CODE (tmp) == JUMP_INSN
! 		   && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
! 		       || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
  	    {
  	      rtvec vec;
  	      int j;
Index: rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.c,v
retrieving revision 1.84
diff -c -p -d -r1.84 rtl.c
*** rtl.c	2000/11/22 01:22:02	1.84
--- rtl.c	2000/12/21 01:08:25
*************** const char * const reg_note_name[] =
*** 288,294 ****
    "REG_LABEL", "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
    "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
    "REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION",
!   "REG_EH_RETHROW", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN"
  };
  
  static htab_t md_constants;
--- 288,295 ----
    "REG_LABEL", "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
    "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
    "REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION",
!   "REG_EH_RETHROW", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN",
!   "REG_NON_LOCAL_GOTO"
  };
  
  static htab_t md_constants;
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.h,v
retrieving revision 1.232
diff -c -p -d -r1.232 rtl.h
*** rtl.h	2000/12/20 17:19:39	1.232
--- rtl.h	2000/12/21 01:08:25
*************** enum reg_note
*** 549,555 ****
    REG_MAYBE_DEAD,
  
    /* Indicates that a call does not return.  */
!   REG_NORETURN
  };
  
  /* The base value for branch probability notes.  */
--- 549,559 ----
    REG_MAYBE_DEAD,
  
    /* Indicates that a call does not return.  */
!   REG_NORETURN,
! 
!   /* Indicates that an indirect jump is a non-local goto instead of a 
!      computed goto.  */
!   REG_NON_LOCAL_GOTO
  };
  
  /* The base value for branch probability notes.  */
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/stmt.c,v
retrieving revision 1.179
diff -c -p -d -r1.179 stmt.c
*** stmt.c	2000/12/05 08:16:15	1.179
--- stmt.c	2000/12/21 01:08:25
*************** expand_goto (label)
*** 783,789 ****
      {
        struct function *p = find_function_data (context);
        rtx label_ref = gen_rtx_LABEL_REF (Pmode, label_rtx (label));
!       rtx handler_slot, static_chain, save_area;
        tree link;
  
        /* Find the corresponding handler slot for this label.  */
--- 783,789 ----
      {
        struct function *p = find_function_data (context);
        rtx label_ref = gen_rtx_LABEL_REF (Pmode, label_rtx (label));
!       rtx handler_slot, static_chain, save_area, insn;
        tree link;
  
        /* Find the corresponding handler slot for this label.  */
*************** expand_goto (label)
*** 836,841 ****
--- 836,850 ----
  	  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
  	  emit_indirect_jump (handler_slot);
  	}
+ 
+       /* Search backwards to the jump insn and mark it as a 
+ 	 non-local goto.  */
+       for (insn = get_last_insn ();
+ 	   GET_CODE (insn) != JUMP_INSN; 
+ 	   insn = PREV_INSN (insn))
+ 	continue;
+       REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
+ 					  REG_NOTES (insn));
      }
    else
      expand_goto_internal (label, label_rtx (label), NULL_RTX);

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