summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1997-11-14 14:51:00 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1997-11-14 14:51:00 +0000
commit22278f3bc6f4d3551253f5493c0521882fe55697 (patch)
tree35e19146329addf80bfbc10fa38f7d78bfef3bf6
parent73fe3a568277dcea3ae5e83dc63b0f53e1b7e0af (diff)
downloadgcc-22278f3bc6f4d3551253f5493c0521882fe55697.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@16492 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/alpha/alpha.md21
-rw-r--r--gcc/expr.c7
-rw-r--r--gcc/stupid.c38
4 files changed, 56 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 61e6835318e..c7d4a414319 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
Fri Nov 14 07:24:20 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.
+
* alpha.c (output_prolog [*]): Prefix entry labels with '$' to
keep them from being propogated to the object file.
(alpha_write_linkage): Likewise.
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index bd4f43d0909..5a7218dbd4e 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -4683,12 +4683,15 @@
}
}")
-(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)
@@ -4696,6 +4699,18 @@
"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)
(use (reg:DI 1))
diff --git a/gcc/expr.c b/gcc/expr.c
index a18b09e9aba..7545c43ea8d 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8213,12 +8213,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])
diff --git a/gcc/stupid.c b/gcc/stupid.c
index b68b196bcaa..028539aa193 100644
--- a/gcc/stupid.c
+++ b/gcc/stupid.c
@@ -42,8 +42,8 @@ Boston, MA 02111-1307, USA. */
pseudo reg is computed. Then the pseudo regs are ordered by priority
and assigned hard regs in priority order. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "hard-reg-set.h"
#include "regs.h"
@@ -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
@@ -269,8 +282,11 @@ stupid_life_analysis (f, nregs, file)
register int r = reg_order[i];
/* Some regnos disappear from the rtl. Ignore them to avoid crash.
- Also don't allocate registers that cross a setjmp. */
- if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r])
+ Also don't allocate registers that cross a setjmp, or live across
+ a call if this function receives a nonlocal goto. */
+ if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r]
+ || (REG_N_CALLS_CROSSED (r) > 0
+ && current_function_has_nonlocal_label))
continue;
/* Now find the best hard-register class for this pseudo register */