Commit 2268453b by Alan Modra Committed by Alan Modra

re PR target/45807 (Lying eh_frame r2 save info causes crashes with static libgcc_eh and libstdc++)

	PR target/45807
	* config/rs6000/aix.h (SETUP_FRAME_ADDRESSES): Delete.
	* config/rs6000/linux64.h (SETUP_FRAME_ADDRESSES): Delete.
	* config/rs6000/rs6000-protos.h (rs6000_aix_emit_builtin_unwind_init):
	Delete.
	* config/rs6000/rs6000.c (rs6000_aix_emit_builtin_unwind_init): Delete.
	(rs6000_emit_prologue): Don't just create frame save info for r2,
	actually save r2.

From-SVN: r164685
parent 4d508d59
2010-09-29 Alan Modra <amodra@gmail.com>
PR target/45807
* config/rs6000/aix.h (SETUP_FRAME_ADDRESSES): Delete.
* config/rs6000/linux64.h (SETUP_FRAME_ADDRESSES): Delete.
* config/rs6000/rs6000-protos.h (rs6000_aix_emit_builtin_unwind_init):
Delete.
* config/rs6000/rs6000.c (rs6000_aix_emit_builtin_unwind_init): Delete.
(rs6000_emit_prologue): Don't just create frame save info for r2,
actually save r2.
2010-09-28 Richard Henderson <rth@redhat.com>
* config/i386/cygming.h (ASM_OUTPUT_DWARF_OFFSET): Output 8 bytes
......@@ -207,13 +207,6 @@
/* And similarly for general purpose registers. */
#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32)
/* __throw will restore its own return address to be the same as the
return address of the function that the throw is being made to.
This is unfortunate, because we want to check the original
return address to see if we need to restore the TOC.
So we have to squirrel it away with this. */
#define SETUP_FRAME_ADDRESSES() rs6000_aix_emit_builtin_unwind_init ()
/* If the current unwind info (FS) does not contain explicit info
saving R2, then we have to do a minor amount of code reading to
figure out if it was saved. The big problem here is that the
......
......@@ -305,14 +305,6 @@ extern enum rs6000_cmodel cmodel;
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
(!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
/* __throw will restore its own return address to be the same as the
return address of the function that the throw is being made to.
This is unfortunate, because we want to check the original
return address to see if we need to restore the TOC.
So we have to squirrel it away with this. */
#define SETUP_FRAME_ADDRESSES() \
do { if (TARGET_64BIT) rs6000_aix_emit_builtin_unwind_init (); } while (0)
/* Override svr4.h */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
......
......@@ -163,7 +163,6 @@ extern int rs6000_trampoline_size (void);
extern alias_set_type get_TOC_alias_set (void);
extern void rs6000_emit_prologue (void);
extern void rs6000_emit_load_toc_table (int);
extern void rs6000_aix_emit_builtin_unwind_init (void);
extern unsigned int rs6000_dbx_register_number (unsigned int);
extern void rs6000_emit_epilogue (int);
extern void rs6000_emit_eh_reg_restore (rtx, rtx);
......
......@@ -18917,42 +18917,6 @@ rs6000_aix_asm_output_dwarf_table_ref (char * frame_table_label)
TARGET_STRIP_NAME_ENCODING (frame_table_label));
}
/* If _Unwind_* has been called from within the same module,
toc register is not guaranteed to be saved to 40(1) on function
entry. Save it there in that case. */
void
rs6000_aix_emit_builtin_unwind_init (void)
{
rtx mem;
rtx stack_top = gen_reg_rtx (Pmode);
rtx opcode_addr = gen_reg_rtx (Pmode);
rtx opcode = gen_reg_rtx (SImode);
rtx tocompare = gen_reg_rtx (SImode);
rtx no_toc_save_needed = gen_label_rtx ();
mem = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
emit_move_insn (stack_top, mem);
mem = gen_frame_mem (Pmode,
gen_rtx_PLUS (Pmode, stack_top,
GEN_INT (2 * GET_MODE_SIZE (Pmode))));
emit_move_insn (opcode_addr, mem);
emit_move_insn (opcode, gen_rtx_MEM (SImode, opcode_addr));
emit_move_insn (tocompare, gen_int_mode (TARGET_32BIT ? 0x80410014
: 0xE8410028, SImode));
do_compare_rtx_and_jump (opcode, tocompare, EQ, 1,
SImode, NULL_RTX, NULL_RTX,
no_toc_save_needed, -1);
mem = gen_frame_mem (Pmode,
gen_rtx_PLUS (Pmode, stack_top,
GEN_INT (5 * GET_MODE_SIZE (Pmode))));
emit_move_insn (mem, gen_rtx_REG (Pmode, 2));
emit_label (no_toc_save_needed);
}
/* This ties together stack memory (MEM with an alias set of frame_alias_set)
and the change to the stack pointer. */
......@@ -20237,22 +20201,6 @@ rs6000_emit_prologue (void)
{
unsigned int i, regno;
/* In AIX ABI we need to pretend we save r2 here. */
if (TARGET_AIX)
{
rtx addr, reg, mem;
reg = gen_rtx_REG (reg_mode, 2);
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (sp_offset + 5 * reg_size));
mem = gen_frame_mem (reg_mode, addr);
insn = emit_move_insn (mem, reg);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
PATTERN (insn) = gen_blockage ();
}
for (i = 0; ; ++i)
{
regno = EH_RETURN_DATA_REGNO (i);
......@@ -20266,6 +20214,53 @@ rs6000_emit_prologue (void)
}
}
/* In AIX ABI we need to make sure r2 is really saved. */
if (TARGET_AIX && crtl->calls_eh_return)
{
rtx tmp_reg, tmp_reg_si, compare_result, toc_save_done, jump;
long toc_restore_insn;
gcc_assert (frame_reg_rtx == frame_ptr_rtx
|| frame_reg_rtx == sp_reg_rtx);
tmp_reg = gen_rtx_REG (Pmode, 11);
tmp_reg_si = gen_rtx_REG (SImode, 11);
if (using_static_chain_p)
emit_move_insn (gen_rtx_REG (Pmode, 0), tmp_reg);
gcc_assert (saving_GPRs_inline && saving_FPRs_inline);
emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, LR_REGNO));
/* Peek at instruction to which this function returns. If it's
restoring r2, then we know we've already saved r2. We can't
unconditionally save r2 because the value we have will already
be updated if we arrived at this function via a plt call or
toc adjusting stub. */
emit_move_insn (tmp_reg_si, gen_rtx_MEM (SImode, tmp_reg));
toc_restore_insn = ((TARGET_32BIT ? 0x80410014 : 0xE8410028)
^ 0x80000000) - 0x80000000;
emit_insn (gen_xorsi3 (tmp_reg_si, tmp_reg_si,
GEN_INT (toc_restore_insn & ~0xffff)));
compare_result = gen_rtx_REG (CCUNSmode, CR0_REGNO);
validate_condition_mode (EQ, CCUNSmode);
emit_insn (gen_rtx_SET (VOIDmode, compare_result,
gen_rtx_COMPARE (CCUNSmode, tmp_reg_si,
GEN_INT (toc_restore_insn
& 0xffff))));
toc_save_done = gen_label_rtx ();
jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
gen_rtx_EQ (VOIDmode, compare_result,
const0_rtx),
gen_rtx_LABEL_REF (VOIDmode, toc_save_done),
pc_rtx);
jump = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, jump));
JUMP_LABEL (jump) = toc_save_done;
LABEL_NUSES (toc_save_done) += 1;
emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, 2,
sp_offset + 5 * reg_size, info->total_size);
emit_label (toc_save_done);
if (using_static_chain_p)
emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, 0));
}
/* Save CR if we use any that must be preserved. */
if (!WORLD_SAVE_P (info) && info->cr_save_p)
{
......
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