re PR target/11535 (__builtin_return_address may not work on ia64)

PR target/11535
        * config/ia64/ia64.c (ia64_initial_elimination_offset): Remove
        RETURN_ADDRESS_POINTER_REGNUM.
        (ia64_expand_prologue): Don't frob it.
        (ia64_output_function_epilogue): Likewise.
        (ia64_return_addr_rtx): New.
        (ia64_split_return_addr_rtx): New.
        * config/ia64/ia64-protos.h: Update.
        * config/ia64/ia64.h (FIRST_PSEUDO_REGISTER): Decrement.
        (RETURN_ADDRESS_POINTER_REGNUM): Remove.
        (GENERAL_REGNO_P): Don't check it.
        (AR_*_REGNUM): Renumber.
        (FIXED_REGISTERS): Remove RETURN_ADDRESS_POINTER_REGNUM.
        (CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Likewise.
        (REG_ALLOC_ORDER, REG_CLASS_CONTENTS): Likewise.
        (ELIMINABLE_REGS, REGISTER_NAMES): Likewise.
        (RETURN_ADDR_RTX): Use ia64_return_addr_rtx.
        * config/ia64/ia64.md (UNSPEC_RET_ADDR): New.
        (movdi_ret_addr): New.

From-SVN: r70263
This commit is contained in:
Richard Henderson 2003-08-08 16:49:57 -07:00 committed by Richard Henderson
parent 5dddb92059
commit af1e551876
5 changed files with 134 additions and 51 deletions

View File

@ -1,3 +1,25 @@
2003-08-08 Richard Henderson <rth@redhat.com>
PR target/11535
* config/ia64/ia64.c (ia64_initial_elimination_offset): Remove
RETURN_ADDRESS_POINTER_REGNUM.
(ia64_expand_prologue): Don't frob it.
(ia64_output_function_epilogue): Likewise.
(ia64_return_addr_rtx): New.
(ia64_split_return_addr_rtx): New.
* config/ia64/ia64-protos.h: Update.
* config/ia64/ia64.h (FIRST_PSEUDO_REGISTER): Decrement.
(RETURN_ADDRESS_POINTER_REGNUM): Remove.
(GENERAL_REGNO_P): Don't check it.
(AR_*_REGNUM): Renumber.
(FIXED_REGISTERS): Remove RETURN_ADDRESS_POINTER_REGNUM.
(CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Likewise.
(REG_ALLOC_ORDER, REG_CLASS_CONTENTS): Likewise.
(ELIMINABLE_REGS, REGISTER_NAMES): Likewise.
(RETURN_ADDR_RTX): Use ia64_return_addr_rtx.
* config/ia64/ia64.md (UNSPEC_RET_ADDR): New.
(movdi_ret_addr): New.
2003-08-08 Geoffrey Keating <geoffk@apple.com> 2003-08-08 Geoffrey Keating <geoffk@apple.com>
* config.gcc (powerpc-*-darwin*): Don't build a soft-float multilib. * config.gcc (powerpc-*-darwin*): Don't build a soft-float multilib.

View File

@ -139,6 +139,9 @@ extern void ia64_init_builtins PARAMS((void));
extern void ia64_override_options PARAMS((void)); extern void ia64_override_options PARAMS((void));
extern int ia64_dbx_register_number PARAMS((int)); extern int ia64_dbx_register_number PARAMS((int));
extern rtx ia64_return_addr_rtx PARAMS ((HOST_WIDE_INT, rtx));
extern void ia64_split_return_addr_rtx PARAMS ((rtx));
#ifdef SDATA_SECTION_ASM_OP #ifdef SDATA_SECTION_ASM_OP
extern void sdata_section PARAMS ((void)); extern void sdata_section PARAMS ((void));
#endif #endif

View File

@ -2197,10 +2197,6 @@ ia64_initial_elimination_offset (from, to)
abort (); abort ();
break; break;
case RETURN_ADDRESS_POINTER_REGNUM:
offset = 0;
break;
default: default:
abort (); abort ();
} }
@ -2551,17 +2547,6 @@ ia64_expand_prologue ()
reg_names[current_frame_info.reg_fp] = tmp; reg_names[current_frame_info.reg_fp] = tmp;
} }
/* Fix up the return address placeholder. */
/* ??? We can fail if __builtin_return_address is used, and we didn't
allocate a register in which to save b0. I can't think of a way to
eliminate RETURN_ADDRESS_POINTER_REGNUM to a local register and
then be sure that I got the right one. Further, reload doesn't seem
to care if an eliminable register isn't used, and "eliminates" it
anyway. */
if (regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM]
&& current_frame_info.reg_save_b0 != 0)
XINT (return_address_pointer_rtx, 0) = current_frame_info.reg_save_b0;
/* We don't need an alloc instruction if we've used no outputs or locals. */ /* We don't need an alloc instruction if we've used no outputs or locals. */
if (current_frame_info.n_local_regs == 0 if (current_frame_info.n_local_regs == 0
&& current_frame_info.n_output_regs == 0 && current_frame_info.n_output_regs == 0
@ -3118,6 +3103,72 @@ ia64_direct_return ()
return 0; return 0;
} }
/* Return the magic cookie that we use to hold the return address
during early compilation. */
rtx
ia64_return_addr_rtx (count, frame)
HOST_WIDE_INT count;
rtx frame ATTRIBUTE_UNUSED;
{
if (count != 0)
return NULL;
return gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_RET_ADDR);
}
/* Split this value after reload, now that we know where the return
address is saved. */
void
ia64_split_return_addr_rtx (dest)
rtx dest;
{
rtx src;
if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
{
if (current_frame_info.reg_save_b0 != 0)
src = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
else
{
HOST_WIDE_INT off;
unsigned int regno;
/* Compute offset from CFA for BR0. */
/* ??? Must be kept in sync with ia64_expand_prologue. */
off = (current_frame_info.spill_cfa_off
+ current_frame_info.spill_size);
for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
off -= 8;
/* Convert CFA offset to a register based offset. */
if (frame_pointer_needed)
src = hard_frame_pointer_rtx;
else
{
src = stack_pointer_rtx;
off += current_frame_info.total_size;
}
/* Load address into scratch register. */
if (CONST_OK_FOR_I (off))
emit_insn (gen_adddi3 (dest, src, GEN_INT (off)));
else
{
emit_move_insn (dest, GEN_INT (off));
emit_insn (gen_adddi3 (dest, src, dest));
}
src = gen_rtx_MEM (Pmode, dest);
}
}
else
src = gen_rtx_REG (DImode, BR_REG (0));
emit_move_insn (dest, src);
}
int int
ia64_hard_regno_rename_ok (from, to) ia64_hard_regno_rename_ok (from, to)
int from; int from;
@ -3267,9 +3318,6 @@ ia64_output_function_epilogue (file, size)
{ {
int i; int i;
/* Reset from the function's potential modifications. */
XINT (return_address_pointer_rtx, 0) = RETURN_ADDRESS_POINTER_REGNUM;
if (current_frame_info.reg_fp) if (current_frame_info.reg_fp)
{ {
const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM]; const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];

View File

@ -455,7 +455,7 @@ while (0)
64 predicate registers, 8 branch registers, one frame pointer, 64 predicate registers, 8 branch registers, one frame pointer,
and several "application" registers. */ and several "application" registers. */
#define FIRST_PSEUDO_REGISTER 335 #define FIRST_PSEUDO_REGISTER 334
/* Ranges for the various kinds of registers. */ /* Ranges for the various kinds of registers. */
#define ADDL_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 3) #define ADDL_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 3)
@ -464,9 +464,7 @@ while (0)
#define PR_REGNO_P(REGNO) ((REGNO) >= 256 && (REGNO) <= 319) #define PR_REGNO_P(REGNO) ((REGNO) >= 256 && (REGNO) <= 319)
#define BR_REGNO_P(REGNO) ((REGNO) >= 320 && (REGNO) <= 327) #define BR_REGNO_P(REGNO) ((REGNO) >= 320 && (REGNO) <= 327)
#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_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)
@ -476,11 +474,11 @@ while (0)
#define IN_REG(REGNO) ((REGNO) + 112) #define IN_REG(REGNO) ((REGNO) + 112)
#define LOC_REG(REGNO) ((REGNO) + 32) #define LOC_REG(REGNO) ((REGNO) + 32)
#define AR_CCV_REGNUM 330 #define AR_CCV_REGNUM 329
#define AR_UNAT_REGNUM 331 #define AR_UNAT_REGNUM 330
#define AR_PFS_REGNUM 332 #define AR_PFS_REGNUM 331
#define AR_LC_REGNUM 333 #define AR_LC_REGNUM 332
#define AR_EC_REGNUM 334 #define AR_EC_REGNUM 333
#define IN_REGNO_P(REGNO) ((REGNO) >= IN_REG (0) && (REGNO) <= IN_REG (7)) #define IN_REGNO_P(REGNO) ((REGNO) >= IN_REG (0) && (REGNO) <= IN_REG (7))
#define LOC_REGNO_P(REGNO) ((REGNO) >= LOC_REG (0) && (REGNO) <= LOC_REG (79)) #define LOC_REGNO_P(REGNO) ((REGNO) >= LOC_REG (0) && (REGNO) <= LOC_REG (79))
@ -543,8 +541,8 @@ while (0)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
/* Branch registers. */ \ /* Branch registers. */ \
0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, \
/*FP RA CCV UNAT PFS LC EC */ \ /*FP CCV UNAT PFS LC EC */ \
1, 1, 1, 1, 1, 0, 1 \ 1, 1, 1, 1, 0, 1 \
} }
/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered /* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered
@ -578,8 +576,8 @@ while (0)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
/* Branch registers. */ \ /* Branch registers. */ \
1, 0, 0, 0, 0, 0, 1, 1, \ 1, 0, 0, 0, 0, 0, 1, 1, \
/*FP RA CCV UNAT PFS LC EC */ \ /*FP CCV UNAT PFS LC EC */ \
1, 1, 1, 1, 1, 0, 1 \ 1, 1, 1, 1, 0, 1 \
} }
/* Like `CALL_USED_REGISTERS' but used to overcome a historical /* Like `CALL_USED_REGISTERS' but used to overcome a historical
@ -616,8 +614,8 @@ while (0)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
/* Branch registers. */ \ /* Branch registers. */ \
1, 0, 0, 0, 0, 0, 1, 1, \ 1, 0, 0, 0, 0, 0, 1, 1, \
/*FP RA CCV UNAT PFS LC EC */ \ /*FP CCV UNAT PFS LC EC */ \
0, 0, 1, 0, 1, 0, 0 \ 0, 1, 0, 1, 0, 0 \
} }
@ -763,7 +761,7 @@ while (0)
/* Special branch registers. */ \ /* Special branch registers. */ \
R_BR (0), \ R_BR (0), \
/* Other fixed registers. */ \ /* Other fixed registers. */ \
FRAME_POINTER_REGNUM, RETURN_ADDRESS_POINTER_REGNUM, \ FRAME_POINTER_REGNUM, \
AR_CCV_REGNUM, AR_UNAT_REGNUM, AR_PFS_REGNUM, AR_LC_REGNUM, \ AR_CCV_REGNUM, AR_UNAT_REGNUM, AR_PFS_REGNUM, AR_LC_REGNUM, \
AR_EC_REGNUM \ AR_EC_REGNUM \
} }
@ -892,11 +890,11 @@ enum reg_class
/* AR_M_REGS. */ \ /* AR_M_REGS. */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x0C00 }, \ 0x00000000, 0x00000000, 0x0600 }, \
/* AR_I_REGS. */ \ /* AR_I_REGS. */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x7000 }, \ 0x00000000, 0x00000000, 0x3800 }, \
/* ADDL_REGS. */ \ /* ADDL_REGS. */ \
{ 0x0000000F, 0x00000000, 0x00000000, 0x00000000, \ { 0x0000000F, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
@ -904,7 +902,7 @@ enum reg_class
/* GR_REGS. */ \ /* GR_REGS. */ \
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x0300 }, \ 0x00000000, 0x00000000, 0x0100 }, \
/* FR_REGS. */ \ /* FR_REGS. */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
@ -912,15 +910,15 @@ enum reg_class
/* GR_AND_BR_REGS. */ \ /* GR_AND_BR_REGS. */ \
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x03FF }, \ 0x00000000, 0x00000000, 0x01FF }, \
/* GR_AND_FR_REGS. */ \ /* GR_AND_FR_REGS. */ \
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0x00000000, 0x00000000, 0x0300 }, \ 0x00000000, 0x00000000, 0x0100 }, \
/* ALL_REGS. */ \ /* ALL_REGS. */ \
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0xFFFFFFFF, 0xFFFFFFFF, 0x7FFF }, \ 0xFFFFFFFF, 0xFFFFFFFF, 0x3FFF }, \
} }
/* A C expression whose value is a register class containing hard register /* A C expression whose value is a register class containing hard register
@ -1142,7 +1140,7 @@ enum reg_class
DYNAMIC_CHAIN_ADDRESS and SETUP_FRAME_ADDRESS (for the reg stack flush). */ DYNAMIC_CHAIN_ADDRESS and SETUP_FRAME_ADDRESS (for the reg stack flush). */
#define RETURN_ADDR_RTX(COUNT, FRAME) \ #define RETURN_ADDR_RTX(COUNT, FRAME) \
((COUNT) == 0 ? return_address_pointer_rtx : const0_rtx) ia64_return_addr_rtx (COUNT, FRAME)
/* 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
@ -1203,13 +1201,6 @@ enum reg_class
REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) = 64; \ REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) = 64; \
} while (0) } while (0)
/* The register number for the return address register. For IA-64, this
is not actually 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_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. */
/* ??? The ABI sez the static chain should be passed as a normal parameter. */ /* ??? The ABI sez the static chain should be passed as a normal parameter. */
#define STATIC_CHAIN_REGNUM 15 #define STATIC_CHAIN_REGNUM 15
@ -1233,7 +1224,6 @@ enum reg_class
{ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
{FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
{RETURN_ADDRESS_POINTER_REGNUM, BR_REG (0)}, \
} }
/* A C expression that returns nonzero if the compiler is allowed to try to /* A C expression that returns nonzero if the compiler is allowed to try to
@ -1879,8 +1869,8 @@ do { \
"p60", "p61", "p62", "p63", \ "p60", "p61", "p62", "p63", \
/* 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. Application registers. */ \
"sfp", "retaddr", "ar.ccv", "ar.unat", "ar.pfs", "ar.lc", "ar.ec", \ "sfp", "ar.ccv", "ar.unat", "ar.pfs", "ar.lc", "ar.ec", \
} }
/* 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

View File

@ -73,6 +73,7 @@
(UNSPEC_BUNDLE_SELECTOR 23) (UNSPEC_BUNDLE_SELECTOR 23)
(UNSPEC_ADDP4 24) (UNSPEC_ADDP4 24)
(UNSPEC_PROLOGUE_USE 25) (UNSPEC_PROLOGUE_USE 25)
(UNSPEC_RET_ADDR 26)
]) ])
(define_constants (define_constants
@ -410,6 +411,25 @@
operands[3] = pic_offset_table_rtx; operands[3] = pic_offset_table_rtx;
}) })
;; This is used as a placeholder for the return address during early
;; compilation. We won't know where we've placed this until during
;; reload, at which point it can wind up in b0, a general register,
;; or memory. The only safe destination under these conditions is a
;; general register.
(define_insn_and_split "*movdi_ret_addr"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(const_int 0)] UNSPEC_RET_ADDR))]
""
"#"
"reload_completed"
[(const_int 0)]
{
ia64_split_return_addr_rtx (operands[0]);
DONE;
}
[(set_attr "itanium_class" "ialu")])
(define_insn "*load_symptr_high" (define_insn "*load_symptr_high"
[(set (match_operand:DI 0 "register_operand" "=r") [(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (high:DI (match_operand 1 "got_symbolic_operand" "s")) (plus:DI (high:DI (match_operand 1 "got_symbolic_operand" "s"))