Commit 46327bc5 by Richard Henderson Committed by Richard Henderson

libgcc2.c (ia64_throw_helper): Use __builtin_return_address.

        * libgcc2.c (ia64_throw_helper): Use __builtin_return_address.
        (__throw): Don't pass the address of a label.

        * config/ia64/ia64.c (ia64_compute_frame_size): Use
        current_function_is_leaf.
        (ia64_expand_prologue): Likewise.  Modify return_address_pointer_rtx
        instead of reg_names[RETURN_ADDRESS_REGNUM].
        (ia64_init_machine_status): Reset return_address_pointer_rtx.
        * config/ia64/ia64.h (RETURN_ADDRESS_POINTER_REGNUM): Rename
        from RETURN_ADDRESS_REGNUM.  Update all uses.
        (RETURN_ADDR_RTX): Use return_address_pointer_rtx; return
        zero instead of null on failure.
        (ELIMINABLE_REGS): Add ra->b0 elimination.
        (CAN_ELIMINATE): Update accordingly.
        (INITIAL_ELIMINATION_OFFSET): Likewise.
        (REGISTER_NAMES): Use an illegal assembler name for
        RETURN_ADDRESS_POINTER_REGNUM.

From-SVN: r34531
parent 13da91fd
2000-06-13 Richard Henderson <rth@cygnus.com> 2000-06-13 Richard Henderson <rth@cygnus.com>
* libgcc2.c (ia64_throw_helper): Use __builtin_return_address.
(__throw): Don't pass the address of a label.
* config/ia64/ia64.c (ia64_compute_frame_size): Use
current_function_is_leaf.
(ia64_expand_prologue): Likewise. Modify return_address_pointer_rtx
instead of reg_names[RETURN_ADDRESS_REGNUM].
(ia64_init_machine_status): Reset return_address_pointer_rtx.
* config/ia64/ia64.h (RETURN_ADDRESS_POINTER_REGNUM): Rename
from RETURN_ADDRESS_REGNUM. Update all uses.
(RETURN_ADDR_RTX): Use return_address_pointer_rtx; return
zero instead of null on failure.
(ELIMINABLE_REGS): Add ra->b0 elimination.
(CAN_ELIMINATE): Update accordingly.
(INITIAL_ELIMINATION_OFFSET): Likewise.
(REGISTER_NAMES): Use an illegal assembler name for
RETURN_ADDRESS_POINTER_REGNUM.
2000-06-13 Richard Henderson <rth@cygnus.com>
* config/ia64/ia64.h (enum reg_class): Remove FR_INT_REGS, FR_FP_REGS, * config/ia64/ia64.h (enum reg_class): Remove FR_INT_REGS, FR_FP_REGS,
GR_AND_FR_INT_REGS, GR_AND_FR_FP_REGS. GR_AND_FR_INT_REGS, GR_AND_FR_FP_REGS.
(REG_CLASS_NAMES): Likewise. (REG_CLASS_NAMES): Likewise.
......
...@@ -607,10 +607,9 @@ ia64_compute_frame_size (size) ...@@ -607,10 +607,9 @@ ia64_compute_frame_size (size)
total_size = IA64_STACK_ALIGN (tmp); total_size = IA64_STACK_ALIGN (tmp);
extra_size = total_size - tmp + 16; extra_size = total_size - tmp + 16;
/* If this is a leaf routine (BR_REG (0) is not live), and if there is no /* If this is a leaf routine, and if there is no stack space needed for
stack space needed for register saves, then don't allocate the 16 byte register saves, then don't allocate the 16 byte scratch area. */
scratch area. */ if (total_size == 16 && current_function_is_leaf)
if (total_size == 16 && ! regs_ever_live[BR_REG (0)])
{ {
total_size = 0; total_size = 0;
extra_size = 0; extra_size = 0;
...@@ -812,18 +811,9 @@ ia64_expand_prologue () ...@@ -812,18 +811,9 @@ ia64_expand_prologue ()
rtx insn, offset; rtx insn, offset;
int i, locals, inputs, outputs, rotates; int i, locals, inputs, outputs, rotates;
int frame_size = ia64_compute_frame_size (get_frame_size ()); int frame_size = ia64_compute_frame_size (get_frame_size ());
int leaf_function;
int epilogue_p; int epilogue_p;
edge e; edge e;
/* ??? This seems like a leaf_function_p bug. It calls get_insns which
returns the first insn of the current sequence, not the first insn
of the function. We work around this by pushing to the topmost
sequence first. */
push_topmost_sequence ();
leaf_function = leaf_function_p ();
pop_topmost_sequence ();
/* If there is no epilogue, then we don't need some prologue insns. We /* If there is no epilogue, then we don't need some prologue insns. We
need to avoid emitting the dead prologue insns, because flow will complain need to avoid emitting the dead prologue insns, because flow will complain
about them. */ about them. */
...@@ -941,7 +931,7 @@ ia64_expand_prologue () ...@@ -941,7 +931,7 @@ ia64_expand_prologue ()
locals and outputs are both zero sized. Since we have already allocated locals and outputs are both zero sized. Since we have already allocated
two locals for rp and ar.pfs, we check for two locals. */ two locals for rp and ar.pfs, we check for two locals. */
/* Leaf functions can use output registers as call-clobbered temporaries. */ /* Leaf functions can use output registers as call-clobbered temporaries. */
if (locals == 2 && outputs == 0 && leaf_function) if (locals == 2 && outputs == 0 && current_function_is_leaf)
{ {
/* If there is no alloc, but there are input registers used, then we /* If there is no alloc, but there are input registers used, then we
need a .regstk directive. */ need a .regstk directive. */
...@@ -966,13 +956,11 @@ ia64_expand_prologue () ...@@ -966,13 +956,11 @@ ia64_expand_prologue ()
/* Emit a save of BR_REG (0) if we call other functions. /* Emit a save of BR_REG (0) if we call other functions.
Do this even if this function doesn't return, as EH Do this even if this function doesn't return, as EH
depends on this to be able to unwind the stack. */ depends on this to be able to unwind the stack. */
if (! leaf_function) if (! current_function_is_leaf)
{ {
rtx ia64_rp_reg; rtx ia64_rp_reg;
ia64_rp_regno = LOC_REG (locals - 2); ia64_rp_regno = LOC_REG (locals - 2);
reg_names[RETURN_ADDRESS_REGNUM] = reg_names[ia64_rp_regno];
ia64_rp_reg = gen_rtx_REG (DImode, ia64_rp_regno); ia64_rp_reg = gen_rtx_REG (DImode, ia64_rp_regno);
insn = emit_move_insn (ia64_rp_reg, gen_rtx_REG (DImode, insn = emit_move_insn (ia64_rp_reg, gen_rtx_REG (DImode,
BR_REG (0))); BR_REG (0)));
...@@ -984,6 +972,10 @@ ia64_expand_prologue () ...@@ -984,6 +972,10 @@ ia64_expand_prologue ()
appear dead and will elicit a warning from flow. */ appear dead and will elicit a warning from flow. */
emit_insn (gen_rtx_USE (VOIDmode, ia64_rp_reg)); emit_insn (gen_rtx_USE (VOIDmode, ia64_rp_reg));
} }
/* Fix up the return address placeholder. */
if (regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM])
XINT (return_address_pointer_rtx, 0) = ia64_rp_regno;
} }
else else
ia64_rp_regno = 0; ia64_rp_regno = 0;
...@@ -2113,6 +2105,9 @@ ia64_init_machine_status (p) ...@@ -2113,6 +2105,9 @@ ia64_init_machine_status (p)
{ {
p->machine = p->machine =
(struct machine_function *) xcalloc (1, sizeof (struct machine_function)); (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
/* Reset from the previous function's potential modifications. */
XINT (return_address_pointer_rtx, 0) = RETURN_ADDRESS_POINTER_REGNUM;
} }
static void static void
......
...@@ -551,7 +551,7 @@ while (0) ...@@ -551,7 +551,7 @@ while (0)
#define GENERAL_REGNO_P(REGNO) \ #define GENERAL_REGNO_P(REGNO) \
(GR_REGNO_P (REGNO) \ (GR_REGNO_P (REGNO) \
|| (REGNO) == FRAME_POINTER_REGNUM \ || (REGNO) == FRAME_POINTER_REGNUM \
|| (REGNO) == RETURN_ADDRESS_REGNUM) || (REGNO) == RETURN_ADDRESS_POINTER_REGNUM)
#define GR_REG(REGNO) ((REGNO) + 0) #define GR_REG(REGNO) ((REGNO) + 0)
#define FR_REG(REGNO) ((REGNO) + 128) #define FR_REG(REGNO) ((REGNO) + 128)
...@@ -788,7 +788,7 @@ while (0) ...@@ -788,7 +788,7 @@ while (0)
/* Special branch registers. */ \ /* Special branch registers. */ \
R_BR (0), \ R_BR (0), \
/* Frame pointer. Return address. */ \ /* Frame pointer. Return address. */ \
FRAME_POINTER_REGNUM, RETURN_ADDRESS_REGNUM, \ FRAME_POINTER_REGNUM, RETURN_ADDRESS_POINTER_REGNUM, \
} }
...@@ -1110,13 +1110,8 @@ enum reg_class ...@@ -1110,13 +1110,8 @@ enum reg_class
unwind info, so we don't try to support them. We would also need to define unwind info, so we don't try to support them. We would also need to define
DYNAMIC_CHAIN_ADDRESS and SETUP_FRAME_ADDRESS (for the reg stack flush). */ DYNAMIC_CHAIN_ADDRESS and SETUP_FRAME_ADDRESS (for the reg stack flush). */
/* ??? This only works for non-leaf functions. In a leaf function, the return #define RETURN_ADDR_RTX(COUNT, FRAME) \
address would be in b0 (rp). */ ((COUNT) == 0 ? return_address_pointer_rtx : const0_rtx)
#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) \
(((COUNT) == 0) \
? gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM) \
: (rtx) 0)
/* A C expression whose value is RTL representing the location of the incoming /* A C expression whose value is RTL representing the location of the incoming
return address at the beginning of any function, before the prologue. This return address at the beginning of any function, before the prologue. This
...@@ -1177,10 +1172,12 @@ extern int ia64_local_regs; ...@@ -1177,10 +1172,12 @@ extern int ia64_local_regs;
in it. */ in it. */
#define ARG_POINTER_REGNUM R_GR(0) #define ARG_POINTER_REGNUM R_GR(0)
/* The register number for the return address register. This is modified by /* The register number for the return address register. This is not actually
ia64_expand_prologue to point to the real return address save register. */ a pointer as the name suggests, but that's a name that gen_rtx_REG
already takes care to keep unique. We modify return_address_pointer_rtx
in ia64_expand_prologue to reference the final output regnum. */
#define RETURN_ADDRESS_REGNUM 329 #define RETURN_ADDRESS_POINTER_REGNUM 329
/* Register numbers used for passing a function's static chain pointer. */ /* Register numbers used for passing a function's static chain pointer. */
...@@ -1202,14 +1199,15 @@ extern int ia64_local_regs; ...@@ -1202,14 +1199,15 @@ extern int ia64_local_regs;
{ \ { \
{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
{FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{RETURN_ADDRESS_POINTER_REGNUM, BR_REG (0)} \
} }
/* A C expression that returns non-zero if the compiler is allowed to try to /* A C expression that returns non-zero if the compiler is allowed to try to
replace register number FROM with register number TO. There are no ia64 replace register number FROM with register number TO. */
specific restrictions. */
#define CAN_ELIMINATE(FROM, TO) 1 #define CAN_ELIMINATE(FROM, TO) \
(TO == BR_REG (0) ? current_function_is_leaf : 1)
/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the /* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the
initial difference between the specified pair of registers. This macro must initial difference between the specified pair of registers. This macro must
...@@ -1238,6 +1236,8 @@ extern int ia64_local_regs; ...@@ -1238,6 +1236,8 @@ extern int ia64_local_regs;
abort (); \ abort (); \
} \ } \
} \ } \
else if ((TO) == BR_REG (0)) \
(OFFSET) = 0; \
else \ else \
abort (); \ abort (); \
} }
...@@ -2324,7 +2324,7 @@ do { \ ...@@ -2324,7 +2324,7 @@ do { \
/* Branch registers. */ \ /* Branch registers. */ \
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \ "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \
/* Frame pointer. Return address. */ \ /* Frame pointer. Return address. */ \
"fp", "ra" \ "sfp", "retaddr" \
} }
/* If defined, a C initializer for an array of structures containing a name and /* If defined, a C initializer for an array of structures containing a name and
......
...@@ -4043,12 +4043,12 @@ __ia64_personality_v1 (void *pc, old_exception_table *table) ...@@ -4043,12 +4043,12 @@ __ia64_personality_v1 (void *pc, old_exception_table *table)
} }
static void static void
ia64_throw_helper (throw_pc, throw_frame, caller, throw_bsp) ia64_throw_helper (throw_frame, caller, throw_bsp)
void *throw_pc;
ia64_frame_state *throw_frame; ia64_frame_state *throw_frame;
ia64_frame_state *caller; ia64_frame_state *caller;
void *throw_bsp; void *throw_bsp;
{ {
void *throw_pc = __builtin_return_address (0);
unwind_info_ptr *info; unwind_info_ptr *info;
void *pc, *handler = NULL; void *pc, *handler = NULL;
void *pc_base; void *pc_base;
...@@ -4146,7 +4146,6 @@ __throw () ...@@ -4146,7 +4146,6 @@ __throw ()
__terminate (); __terminate ();
__builtin_unwind_init (); __builtin_unwind_init ();
label_ia64:
/* We have to call another routine to actually process the frame /* We have to call another routine to actually process the frame
information, which will force all of __throw's local registers into information, which will force all of __throw's local registers into
backing store. */ backing store. */
...@@ -4154,7 +4153,7 @@ label_ia64: ...@@ -4154,7 +4153,7 @@ label_ia64:
/* Get the value of ar.bsp while we're here. */ /* Get the value of ar.bsp while we're here. */
bsp = __builtin_ia64_bsp (); bsp = __builtin_ia64_bsp ();
ia64_throw_helper (&&label_ia64, &my_frame, &originator, bsp); ia64_throw_helper (&my_frame, &originator, bsp);
/* Now we have to fudge the bsp by the amount in our (__throw) /* Now we have to fudge the bsp by the amount in our (__throw)
frame marker, since the return is going to adjust it by that much. */ frame marker, since the return is going to adjust it by that much. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment