This is the mail archive of the gcc@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]

sjlj eh fixes


These patches fix the call-saved register problems for exception handling. 
I can now run eh29.C correctly on Linux/Alpha with and without optimization;
a full test is underway.


r~


Mon Nov 10 18:44:46 1997  Richard Henderson  <rth@cygnus.com>

	* expr.c (expand_builtin_setjmp): Set
	current_function_has_nonlocal_label.
	* stupid.c (stupid_life_analysis): If has_nonlocal_label, kill
	call-saved registers across calls.

	* alpha.md (exception_receiver): Remove.
	(nonlocal_goto_receiver_osf): New
	(nonlocal_goto_receiver_vms): Renamed from nonlocal_goto_receiver.
	(nonlocal_goto_receiver): New, select _osf or _vms.
	
Index: expr.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.16
diff -u -p -d -r1.16 expr.c
--- expr.c	1997/11/02 05:15:13	1.16
+++ expr.c	1997/11/11 02:38:38
@@ -8151,12 +8151,7 @@ expand_builtin_setjmp (buf_addr, target)
 #endif
     emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
 
-  /* Do we need to do something like:
-     
-     current_function_has_nonlocal_label = 1;
-
-     here?  It seems like we might have to, or some subset of that
-     functionality, but I am unsure.  (mrs) */
+  current_function_has_nonlocal_label = 1;
 
 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
   if (fixed_regs[ARG_POINTER_REGNUM])
Index: config/alpha/alpha.md
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/config/alpha/alpha.md,v
retrieving revision 1.12.2.1
diff -u -p -d -r1.12.2.1 alpha.md
--- alpha.md	1997/11/04 21:15:45	1.12.2.1
+++ alpha.md	1997/11/11 02:39:16
@@ -4523,18 +4525,33 @@
     }
 }")
 
-(define_insn "exception_receiver"
+;; Ideally we should be able to define nonlocal_goto and arrange
+;; for the pc to be in a known place.  Or perhaps branch back via
+;; br instead of jmp.
+(define_insn "nonlocal_goto_receiver_osf"
   [(unspec_volatile [(const_int 0)] 2)]
   "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
-  ".long 0xc3a00000\;ldgp $29,0($29)")
+  "br $29,$LGOTO%=\\n$LGOTO%=:\;ldgp $29,0($29)")
 
-(define_expand "nonlocal_goto_receiver"
+(define_expand "nonlocal_goto_receiver_vms"
   [(unspec_volatile [(const_int 0)] 1)
    (set (reg:DI 27) (mem:DI (reg:DI 29)))
    (unspec_volatile [(const_int 0)] 1)
    (use (reg:DI 27))]
   "TARGET_OPEN_VMS"
   "")
+
+(define_expand "nonlocal_goto_receiver"
+  [(unspec_volatile [(const_int 0)] 2)]
+  ""
+  "
+{
+  if (TARGET_OPEN_VMS)
+    emit_insn(gen_nonlocal_goto_receiver_vms ());
+  else if (!TARGET_WINDOWS_NT)
+    emit_insn(gen_nonlocal_goto_receiver_osf ());
+  DONE;
+}")
 
 (define_insn "arg_home"
   [(unspec [(const_int 0)] 0)
Index: stupid.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/stupid.c,v
retrieving revision 1.1.1.1
diff -u -p -d -r1.1.1.1 stupid.c
--- stupid.c	1997/08/11 15:57:13	1.1.1.1
+++ stupid.c	1997/11/11 02:43:37
@@ -230,21 +230,34 @@ stupid_life_analysis (f, nregs, file)
 	  && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
 	last_setjmp_suid = INSN_SUID (insn);
 
-      /* Mark all call-clobbered regs as live after each call insn
-	 so that a pseudo whose life span includes this insn
-	 will not go in one of them.
+      /* Mark all call-clobbered regs as dead after each call insn so that
+	 a pseudo whose life span includes this insn will not go in one of
+	 them.  If the function contains a non-local goto, mark all hard
+	 registers dead (except for stack related bits).
+
 	 Then mark those regs as all dead for the continuing scan
 	 of the insns before the call.  */
 
       if (GET_CODE (insn) == CALL_INSN)
 	{
 	  last_call_suid = INSN_SUID (insn);
-	  IOR_HARD_REG_SET (after_insn_hard_regs[last_call_suid],
-			    call_used_reg_set);
 
-	  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-	    if (call_used_regs[i])
-	      regs_live[i] = 0;
+	  if (current_function_has_nonlocal_label)
+	    {
+	      IOR_COMPL_HARD_REG_SET (after_insn_hard_regs[last_call_suid],
+				      fixed_reg_set);
+	      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+		if (! fixed_regs[i])
+	          regs_live[i] = 0;
+	    }
+	  else
+	    {
+	      IOR_HARD_REG_SET (after_insn_hard_regs[last_call_suid],
+				call_used_reg_set);
+	      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	        if (call_used_regs[i])
+	          regs_live[i] = 0;
+	    }
 
 	  /* It is important that this be done after processing the insn's
 	     pattern because we want the function result register to still


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