i386.c (general_no_elim_operand): Disallow virtual regs.

* config/i386/i386.c (general_no_elim_operand): Disallow virtual regs.
        (ix86_save_reg): If maybe_eh_return, true for EH_RETURN_DATA_REGNOs.
        True for pic register if current_function_calls_eh_return.
        (ix86_expand_epilogue): Change "emit_return" argument into "style".
        Handle eh_return requirements.
        * config/i386/i386.h (EH_RETURN_DATA_REGNO): New.
        (EH_RETURN_STACKADJ_RTX): New.
        * config/i386/i386.md (exception_receiver): Remove.
        (eh_return, eh_return_1): New.
        * config/i386/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.

From-SVN: r40926
This commit is contained in:
Richard Henderson 2001-03-28 03:14:40 -08:00 committed by Richard Henderson
parent 4573b4de23
commit 1020a5ab7e
5 changed files with 198 additions and 47 deletions

View File

@ -1,13 +1,24 @@
2001-03-28 Richard Henderson <rth@redhat.com> 2001-03-28 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.c (alpha_sa_mask): Add EH_RETURN_DATA_REGNOs. * config/i386/i386.c (general_no_elim_operand): Disallow virtual regs.
(alpha_mark_machine_status): No eh_epilogue_sp_ofs ... (ix86_save_reg): If maybe_eh_return, true for EH_RETURN_DATA_REGNOs.
(alpha_expand_epilogue): ... use EH_RETURN_STACKADJ_RTX instead. True for pic register if current_function_calls_eh_return.
* config/alpha/alpha.h (machine_function): Remove eh_epilogue_sp_ofs. (ix86_expand_epilogue): Change "emit_return" argument into "style".
(EH_RETURN_DATA_REGNO): New. Handle eh_return requirements.
(EH_RETURN_STACKADJ_RTX, EH_RETURN_HANDLER_RTX): New. * config/i386/i386.h (EH_RETURN_DATA_REGNO): New.
* config/alpha/alpha.md (eh_epilogue): Remove. (EH_RETURN_STACKADJ_RTX): New.
(exception_receiver): Use $26 for ldgp input. * config/i386/i386.md (exception_receiver): Remove.
(eh_return, eh_return_1): New.
* config/i386/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.
* config/alpha/alpha.c (alpha_sa_mask): Add EH_RETURN_DATA_REGNOs.
(alpha_mark_machine_status): No eh_epilogue_sp_ofs ...
(alpha_expand_epilogue): ... use EH_RETURN_STACKADJ_RTX instead.
* config/alpha/alpha.h (machine_function): Remove eh_epilogue_sp_ofs.
(EH_RETURN_DATA_REGNO): New.
(EH_RETURN_STACKADJ_RTX, EH_RETURN_HANDLER_RTX): New.
* config/alpha/alpha.md (eh_epilogue): Remove.
(exception_receiver): Use $26 for ldgp input.
* config/alpha/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New. * config/alpha/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.
2001-03-28 Richard Henderson <rth@redhat.com> 2001-03-28 Richard Henderson <rth@redhat.com>

View File

@ -566,7 +566,7 @@ static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
static int ix86_safe_length_prefix PARAMS ((rtx)); static int ix86_safe_length_prefix PARAMS ((rtx));
static int ix86_nsaved_regs PARAMS((void)); static int ix86_nsaved_regs PARAMS((void));
static void ix86_emit_save_regs PARAMS((void)); static void ix86_emit_save_regs PARAMS((void));
static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int)); static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int, bool));
static void ix86_emit_epilogue_esp_adjustment PARAMS((int)); static void ix86_emit_epilogue_esp_adjustment PARAMS((int));
static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx)); static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));
static void ix86_sched_reorder_pentium PARAMS((rtx *, rtx *)); static void ix86_sched_reorder_pentium PARAMS((rtx *, rtx *));
@ -606,7 +606,7 @@ static int ix86_fp_comparison_arithmetics_cost PARAMS ((enum rtx_code code));
static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code)); static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code));
static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code)); static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code));
static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code)); static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));
static int ix86_save_reg PARAMS ((int)); static int ix86_save_reg PARAMS ((int, bool));
static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *)); static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
/* Sometimes certain combinations of command options do not make /* Sometimes certain combinations of command options do not make
@ -1475,6 +1475,10 @@ general_no_elim_operand (op, mode)
|| t == virtual_incoming_args_rtx || t == virtual_stack_vars_rtx || t == virtual_incoming_args_rtx || t == virtual_stack_vars_rtx
|| t == virtual_stack_dynamic_rtx) || t == virtual_stack_dynamic_rtx)
return 0; return 0;
if (REG_P (t)
&& REGNO (t) >= FIRST_VIRTUAL_REGISTER
&& REGNO (t) <= LAST_VIRTUAL_REGISTER)
return 0;
return general_operand (op, mode); return general_operand (op, mode);
} }
@ -2249,17 +2253,35 @@ gen_push (arg)
/* Return 1 if we need to save REGNO. */ /* Return 1 if we need to save REGNO. */
static int static int
ix86_save_reg (regno) ix86_save_reg (regno, maybe_eh_return)
int regno; int regno;
bool maybe_eh_return;
{ {
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table if (flag_pic
|| current_function_uses_const_pool) && ! TARGET_64BIT
&& !TARGET_64BIT; && regno == PIC_OFFSET_TABLE_REGNUM
return ((regs_ever_live[regno] && !call_used_regs[regno] && (current_function_uses_pic_offset_table
&& !fixed_regs[regno] || current_function_uses_const_pool
&& (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed)) || current_function_calls_eh_return))
|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)); return 1;
if (current_function_calls_eh_return && maybe_eh_return)
{
unsigned i;
for (i = 0; ; i++)
{
unsigned test = EH_RETURN_DATA_REGNO(i);
if (test == INVALID_REGNUM)
break;
if (test == (unsigned) regno)
return 1;
}
}
return (regs_ever_live[regno]
&& !call_used_regs[regno]
&& !fixed_regs[regno]
&& (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed));
} }
/* Return number of registers to be saved on the stack. */ /* Return number of registers to be saved on the stack. */
@ -2271,7 +2293,7 @@ ix86_nsaved_regs ()
int regno; int regno;
for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
if (ix86_save_reg (regno)) if (ix86_save_reg (regno, true))
nregs++; nregs++;
return nregs; return nregs;
} }
@ -2423,7 +2445,7 @@ ix86_emit_save_regs ()
rtx insn; rtx insn;
for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
if (ix86_save_reg (regno)) if (ix86_save_reg (regno, true))
{ {
insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno))); insn = emit_insn (gen_push (gen_rtx_REG (Pmode, regno)));
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
@ -2535,14 +2557,15 @@ ix86_emit_epilogue_esp_adjustment (tsize)
/* Emit code to restore saved registers using MOV insns. First register /* Emit code to restore saved registers using MOV insns. First register
is restored from POINTER + OFFSET. */ is restored from POINTER + OFFSET. */
static void static void
ix86_emit_restore_regs_using_mov (pointer, offset) ix86_emit_restore_regs_using_mov (pointer, offset, maybe_eh_return)
rtx pointer; rtx pointer;
int offset; int offset;
bool maybe_eh_return;
{ {
int regno; int regno;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (ix86_save_reg (regno)) if (ix86_save_reg (regno, maybe_eh_return))
{ {
emit_move_insn (gen_rtx_REG (Pmode, regno), emit_move_insn (gen_rtx_REG (Pmode, regno),
adj_offsettable_operand (gen_rtx_MEM (Pmode, adj_offsettable_operand (gen_rtx_MEM (Pmode,
@ -2555,8 +2578,8 @@ ix86_emit_restore_regs_using_mov (pointer, offset)
/* Restore function stack, frame, and registers. */ /* Restore function stack, frame, and registers. */
void void
ix86_expand_epilogue (emit_return) ix86_expand_epilogue (style)
int emit_return; int style;
{ {
int regno; int regno;
int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging; int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
@ -2588,7 +2611,8 @@ ix86_expand_epilogue (emit_return)
if ((!sp_valid && frame.nregs <= 1) if ((!sp_valid && frame.nregs <= 1)
|| (frame_pointer_needed && !frame.nregs && frame.to_allocate) || (frame_pointer_needed && !frame.nregs && frame.to_allocate)
|| (frame_pointer_needed && TARGET_USE_LEAVE && !optimize_size || (frame_pointer_needed && TARGET_USE_LEAVE && !optimize_size
&& frame.nregs == 1)) && frame.nregs == 1)
|| style == 2)
{ {
/* Restore registers. We can use ebp or esp to address the memory /* Restore registers. We can use ebp or esp to address the memory
locations. If both are available, default to ebp, since offsets locations. If both are available, default to ebp, since offsets
@ -2597,12 +2621,41 @@ ix86_expand_epilogue (emit_return)
mode. */ mode. */
if (!frame_pointer_needed || (sp_valid && !frame.to_allocate)) if (!frame_pointer_needed || (sp_valid && !frame.to_allocate))
ix86_emit_restore_regs_using_mov (stack_pointer_rtx, frame.to_allocate); ix86_emit_restore_regs_using_mov (stack_pointer_rtx,
frame.to_allocate, style == 2);
else else
ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx, offset); ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx,
offset, style == 2);
if (!frame_pointer_needed) /* eh_return epilogues need %ecx added to the stack pointer. */
ix86_emit_epilogue_esp_adjustment (frame.to_allocate + frame.nregs * UNITS_PER_WORD); if (style == 2)
{
rtx tmp, sa = EH_RETURN_STACKADJ_RTX;
if (frame_pointer_needed)
{
tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa);
tmp = plus_constant (tmp, UNITS_PER_WORD);
emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
tmp = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
emit_move_insn (hard_frame_pointer_rtx, tmp);
emit_insn (gen_pro_epilogue_adjust_stack
(stack_pointer_rtx, sa, const0_rtx,
hard_frame_pointer_rtx));
}
else
{
tmp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, sa);
tmp = plus_constant (tmp, (frame.to_allocate
+ frame.nregs * UNITS_PER_WORD));
emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, tmp));
}
}
else if (!frame_pointer_needed)
ix86_emit_epilogue_esp_adjustment (frame.to_allocate
+ frame.nregs * UNITS_PER_WORD);
/* If not an i386, mov & pop is faster than "leave". */ /* If not an i386, mov & pop is faster than "leave". */
else if (TARGET_USE_LEAVE || optimize_size) else if (TARGET_USE_LEAVE || optimize_size)
emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ()); emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
@ -2635,7 +2688,7 @@ ix86_expand_epilogue (emit_return)
ix86_emit_epilogue_esp_adjustment (frame.to_allocate); ix86_emit_epilogue_esp_adjustment (frame.to_allocate);
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (ix86_save_reg (regno)) if (ix86_save_reg (regno, false))
{ {
if (TARGET_64BIT) if (TARGET_64BIT)
emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno))); emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno)));
@ -2652,7 +2705,7 @@ ix86_expand_epilogue (emit_return)
} }
/* Sibcall epilogues don't want a return instruction. */ /* Sibcall epilogues don't want a return instruction. */
if (! emit_return) if (style == 0)
return; return;
if (current_function_pops_args && current_function_args_size) if (current_function_pops_args && current_function_args_size)

View File

@ -2779,10 +2779,10 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM)) gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM))
/* After the prologue, RA is at -4(AP) in the current frame. */ /* After the prologue, RA is at -4(AP) in the current frame. */
#define RETURN_ADDR_RTX(COUNT, FRAME) \ #define RETURN_ADDR_RTX(COUNT, FRAME) \
((COUNT) == 0 \ ((COUNT) == 0 \
? gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, TARGET_64BIT ? -8 : -4))\ ? gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -UNITS_PER_WORD)) \
: gen_rtx_MEM (Pmode, plus_constant (FRAME, TARGET_64BIT ? 8 : 4))) : gen_rtx_MEM (Pmode, plus_constant (FRAME, UNITS_PER_WORD)))
/* PC is dbx register 8; let's use that column for RA. */ /* PC is dbx register 8; let's use that column for RA. */
#define DWARF_FRAME_RETURN_COLUMN (TARGET_64BIT ? 16 : 8) #define DWARF_FRAME_RETURN_COLUMN (TARGET_64BIT ? 16 : 8)
@ -2790,6 +2790,10 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
/* Before the prologue, the top of the frame is at 4(%esp). */ /* Before the prologue, the top of the frame is at 4(%esp). */
#define INCOMING_FRAME_SP_OFFSET UNITS_PER_WORD #define INCOMING_FRAME_SP_OFFSET UNITS_PER_WORD
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) : INVALID_REGNUM)
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 2)
/* This is how to output the definition of a user-level label named NAME, /* This is how to output the definition of a user-level label named NAME,
such as the label on a static function or variable NAME. */ such as the label on a static function or variable NAME. */

View File

@ -73,6 +73,7 @@
;; 10 This is a `sahf' operation. ;; 10 This is a `sahf' operation.
;; 11 This is a `fstcw' operation ;; 11 This is a `fstcw' operation
;; 12 This is behaviour of add when setting carry flag. ;; 12 This is behaviour of add when setting carry flag.
;; 13 This is a `eh_return' placeholder.
;; For SSE/MMX support: ;; For SSE/MMX support:
;; 30 This is `fix', guaranteed to be truncating. ;; 30 This is `fix', guaranteed to be truncating.
@ -13017,6 +13018,35 @@
"" ""
"ix86_expand_epilogue (0); DONE;") "ix86_expand_epilogue (0); DONE;")
(define_expand "eh_return"
[(use (match_operand 0 "register_operand" ""))
(use (match_operand 1 "register_operand" ""))]
""
"
{
rtx tmp, sa = operands[0], ra = operands[1];
/* Tricky bit: we write the address of the handler to which we will
be returning into someone else's stack frame, one word below the
stack address we wish to restore. */
tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa);
tmp = plus_constant (tmp, -UNITS_PER_WORD);
tmp = gen_rtx_MEM (Pmode, tmp);
emit_move_insn (tmp, ra);
emit_insn (gen_eh_return_1 (sa));
emit_barrier ();
DONE;
}")
(define_insn_and_split "eh_return_1"
[(unspec_volatile [(match_operand 0 "register_operand" "c")] 13)]
""
"#"
"reload_completed"
[(const_int 1)]
"ix86_expand_epilogue (2); DONE;")
(define_insn "leave" (define_insn "leave"
[(set (reg:SI 7) (reg:SI 6)) [(set (reg:SI 7) (reg:SI 6))
(set (reg:SI 6) (mem:SI (pre_dec:SI (reg:SI 7))))] (set (reg:SI 6) (mem:SI (pre_dec:SI (reg:SI 7))))]
@ -15754,15 +15784,6 @@
DONE; DONE;
}") }")
(define_expand "exception_receiver"
[(const_int 0)]
"flag_pic"
"
{
load_pic_register ();
DONE;
}")
(define_expand "builtin_setjmp_receiver" (define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))] [(label_ref (match_operand 0 "" ""))]
"flag_pic" "flag_pic"

View File

@ -188,3 +188,65 @@ Boston, MA 02111-1307, USA. */
} \ } \
while (0) while (0)
#endif #endif
/* Do code reading to identify a signal frame, and set the frame
state data appropriately. See unwind-dw2.c for the structs. */
#ifdef IN_LIBGCC2
#include <signal.h>
#include <sys/ucontext.h>
#endif
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
do { \
unsigned char *pc_ = (CONTEXT)->ra; \
struct sigcontext *sc_; \
long new_cfa_; \
\
/* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80 */ \
if (*(unsigned short *)(pc_+0) == 0xb858 \
&& *(unsigned int *)(pc_+2) == 119 \
&& *(unsigned short *)(pc_+6) == 0x80cd) \
sc_ = (CONTEXT)->cfa + 4; \
/* movl $__NR_rt_sigreturn,%eax ; int $0x80 */ \
else if (*(unsigned char *)(pc_+0) == 0xb8 \
&& *(unsigned int *)(pc_+1) == 173 \
&& *(unsigned short *)(pc_+5) == 0x80cd) \
{ \
struct rt_sigframe { \
int sig; \
struct siginfo *pinfo; \
void *puc; \
struct siginfo info; \
struct ucontext uc; \
} *rt_ = (CONTEXT)->cfa; \
sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext; \
} \
else \
break; \
\
new_cfa_ = sc_->esp; \
(FS)->cfa_how = CFA_REG_OFFSET; \
(FS)->cfa_reg = 4; \
(FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
\
/* The SVR4 register numbering macros aren't usable in libgcc. */ \
(FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[0].loc.offset = (long)&sc_->eax - new_cfa_; \
(FS)->regs.reg[3].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[3].loc.offset = (long)&sc_->ebx - new_cfa_; \
(FS)->regs.reg[1].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[1].loc.offset = (long)&sc_->ecx - new_cfa_; \
(FS)->regs.reg[2].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[2].loc.offset = (long)&sc_->edx - new_cfa_; \
(FS)->regs.reg[6].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[6].loc.offset = (long)&sc_->esi - new_cfa_; \
(FS)->regs.reg[7].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[7].loc.offset = (long)&sc_->edi - new_cfa_; \
(FS)->regs.reg[5].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[5].loc.offset = (long)&sc_->ebp - new_cfa_; \
(FS)->regs.reg[8].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_; \
(FS)->retaddr_column = 8; \
goto SUCCESS; \
} while (0)