Commit 46336a0e by Eric Botcazou Committed by Eric Botcazou

re PR target/83368 (alloca after setjmp breaks PIC base reg)

	PR target/83368
	* config/sparc/sparc.h (PIC_OFFSET_TABLE_REGNUM): Set to INVALID_REGNUM
	in PIC mode except for TARGET_VXWORKS_RTP.
	* config/sparc/sparc.c: Include cfgrtl.h.
	(TARGET_INIT_PIC_REG): Define.
	(TARGET_USE_PSEUDO_PIC_REG): Likewise.
	(sparc_pic_register_p): New predicate.
	(sparc_legitimate_address_p): Use it.
	(sparc_legitimize_pic_address): Likewise.
	(sparc_delegitimize_address): Likewise.
	(sparc_mode_dependent_address_p): Likewise.
	(gen_load_pcrel_sym): Remove 4th parameter.
	(load_got_register): Adjust call to above.  Remove obsolete stuff.
	(sparc_expand_prologue): Do not call load_got_register here.
	(sparc_flat_expand_prologue): Likewise.
	(sparc_output_mi_thunk): Set the pic_offset_table_rtx object.
	(sparc_use_pseudo_pic_reg): New function.
	(sparc_init_pic_reg): Likewise.
	* config/sparc/sparc.md (vxworks_load_got): Set the GOT register.
	(builtin_setjmp_receiver): Enable only for TARGET_VXWORKS_RTP.

From-SVN: r256575
parent 7dbf8707
2018-01-12 Eric Botcazou <ebotcazou@adacore.com>
PR target/83368
* config/sparc/sparc.h (PIC_OFFSET_TABLE_REGNUM): Set to INVALID_REGNUM
in PIC mode except for TARGET_VXWORKS_RTP.
* config/sparc/sparc.c: Include cfgrtl.h.
(TARGET_INIT_PIC_REG): Define.
(TARGET_USE_PSEUDO_PIC_REG): Likewise.
(sparc_pic_register_p): New predicate.
(sparc_legitimate_address_p): Use it.
(sparc_legitimize_pic_address): Likewise.
(sparc_delegitimize_address): Likewise.
(sparc_mode_dependent_address_p): Likewise.
(gen_load_pcrel_sym): Remove 4th parameter.
(load_got_register): Adjust call to above. Remove obsolete stuff.
(sparc_expand_prologue): Do not call load_got_register here.
(sparc_flat_expand_prologue): Likewise.
(sparc_output_mi_thunk): Set the pic_offset_table_rtx object.
(sparc_use_pseudo_pic_reg): New function.
(sparc_init_pic_reg): Likewise.
* config/sparc/sparc.md (vxworks_load_got): Set the GOT register.
(builtin_setjmp_receiver): Enable only for TARGET_VXWORKS_RTP.
2018-01-12 Christophe Lyon <christophe.lyon@linaro.org>
* doc/sourcebuild.texi (Effective-Target Keywords, Other attributes):
......
......@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "explow.h"
#include "expr.h"
#include "debug.h"
#include "cfgrtl.h"
#include "common/common-target.h"
#include "gimplify.h"
#include "langhooks.h"
......@@ -662,6 +663,8 @@ static bool sparc_frame_pointer_required (void);
static bool sparc_can_eliminate (const int, const int);
static rtx sparc_builtin_setjmp_frame_value (void);
static void sparc_conditional_register_usage (void);
static bool sparc_use_pseudo_pic_reg (void);
static void sparc_init_pic_reg (void);
#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
static const char *sparc_mangle_type (const_tree);
#endif
......@@ -877,6 +880,12 @@ char sparc_hard_reg_printed[8];
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE sparc_conditional_register_usage
#undef TARGET_INIT_PIC_REG
#define TARGET_INIT_PIC_REG sparc_init_pic_reg
#undef TARGET_USE_PSEUDO_PIC_REG
#define TARGET_USE_PSEUDO_PIC_REG sparc_use_pseudo_pic_reg
#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE sparc_mangle_type
......@@ -4361,6 +4370,25 @@ legitimate_pic_operand_p (rtx x)
return true;
}
/* Return true if X is a representation of the PIC register. */
static bool
sparc_pic_register_p (rtx x)
{
if (!REG_P (x) || !pic_offset_table_rtx)
return false;
if (x == pic_offset_table_rtx)
return true;
if (!HARD_REGISTER_P (pic_offset_table_rtx)
&& (HARD_REGISTER_P (x) || lra_in_progress)
&& ORIGINAL_REGNO (x) == REGNO (pic_offset_table_rtx))
return true;
return false;
}
#define RTX_OK_FOR_OFFSET_P(X, MODE) \
(CONST_INT_P (X) \
&& INTVAL (X) >= -0x1000 \
......@@ -4401,7 +4429,7 @@ sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
}
if ((flag_pic == 1
&& rs1 == pic_offset_table_rtx
&& sparc_pic_register_p (rs1)
&& !REG_P (rs2)
&& GET_CODE (rs2) != SUBREG
&& GET_CODE (rs2) != LO_SUM
......@@ -4796,7 +4824,7 @@ sparc_legitimize_pic_address (rtx orig, rtx reg)
rtx base, offset;
if (GET_CODE (XEXP (orig, 0)) == PLUS
&& XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
&& sparc_pic_register_p (XEXP (XEXP (orig, 0), 0)))
return orig;
if (reg == 0)
......@@ -4901,8 +4929,7 @@ sparc_delegitimize_address (rtx x)
/* This is generated by mov{si,di}_pic_label_ref in PIC mode. */
if (GET_CODE (x) == MINUS
&& REG_P (XEXP (x, 0))
&& REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM
&& sparc_pic_register_p (XEXP (x, 0))
&& GET_CODE (XEXP (x, 1)) == LO_SUM
&& GET_CODE (XEXP (XEXP (x, 1), 1)) == UNSPEC
&& XINT (XEXP (XEXP (x, 1), 1), 1) == UNSPEC_MOVE_PIC_LABEL)
......@@ -4981,14 +5008,10 @@ static bool
sparc_mode_dependent_address_p (const_rtx addr,
addr_space_t as ATTRIBUTE_UNUSED)
{
if (flag_pic && GET_CODE (addr) == PLUS)
{
rtx op0 = XEXP (addr, 0);
rtx op1 = XEXP (addr, 1);
if (op0 == pic_offset_table_rtx
&& symbolic_operand (op1, VOIDmode))
return true;
}
if (GET_CODE (addr) == PLUS
&& sparc_pic_register_p (XEXP (addr, 0))
&& symbolic_operand (XEXP (addr, 1), VOIDmode))
return true;
return false;
}
......@@ -5017,7 +5040,7 @@ get_pc_thunk_name (char name[32], unsigned int regno)
/* Wrapper around the load_pcrel_sym{si,di} patterns. */
static rtx
gen_load_pcrel_sym (rtx op0, rtx op1, rtx op2, rtx op3)
gen_load_pcrel_sym (rtx op0, rtx op1, rtx op2)
{
int orig_flag_pic = flag_pic;
rtx insn;
......@@ -5025,9 +5048,9 @@ gen_load_pcrel_sym (rtx op0, rtx op1, rtx op2, rtx op3)
/* The load_pcrel_sym{si,di} patterns require absolute addressing. */
flag_pic = 0;
if (TARGET_ARCH64)
insn = gen_load_pcrel_symdi (op0, op1, op2, op3);
insn = gen_load_pcrel_symdi (op0, op1, op2, GEN_INT (REGNO (op0)));
else
insn = gen_load_pcrel_symsi (op0, op1, op2, op3);
insn = gen_load_pcrel_symsi (op0, op1, op2, GEN_INT (REGNO (op0)));
flag_pic = orig_flag_pic;
return insn;
......@@ -5038,7 +5061,6 @@ gen_load_pcrel_sym (rtx op0, rtx op1, rtx op2, rtx op3)
void
load_got_register (void)
{
/* In PIC mode, this will retrieve pic_offset_table_rtx. */
if (!global_offset_table_rtx)
global_offset_table_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
......@@ -5056,15 +5078,8 @@ load_got_register (void)
}
emit_insn (gen_load_pcrel_sym (global_offset_table_rtx, sparc_got (),
got_helper_rtx,
GEN_INT (GLOBAL_OFFSET_TABLE_REGNUM)));
got_helper_rtx));
}
/* Need to emit this whether or not we obey regdecls,
since setjmp/longjmp can cause life info to screw up.
??? In the case where we don't obey regdecls, this is not sufficient
since we may not fall out the bottom. */
emit_use (global_offset_table_rtx);
}
/* Emit a call instruction with the pattern given by PAT. ADDR is the
......@@ -6039,10 +6054,6 @@ sparc_expand_prologue (void)
- sparc_apparent_frame_size,
SORR_SAVE);
/* Load the GOT register if needed. */
if (crtl->uses_pic_offset_table)
load_got_register ();
/* Advertise that the data calculated just above are now valid. */
sparc_prologue_data_valid_p = true;
}
......@@ -6161,10 +6172,6 @@ sparc_flat_expand_prologue (void)
- sparc_apparent_frame_size,
SORR_SAVE);
/* Load the GOT register if needed. */
if (crtl->uses_pic_offset_table)
load_got_register ();
/* Advertise that the data calculated just above are now valid. */
sparc_prologue_data_valid_p = true;
}
......@@ -12305,6 +12312,8 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
spill_reg = gen_rtx_REG (word_mode, 15); /* %o7 */
start_sequence ();
load_got_register (); /* clobbers %o7 */
if (!TARGET_VXWORKS_RTP)
pic_offset_table_rtx = global_offset_table_rtx;
scratch = sparc_legitimize_pic_address (funexp, scratch);
seq = get_insns ();
end_sequence ();
......@@ -12950,6 +12959,37 @@ sparc_conditional_register_usage (void)
global_regs[SPARC_GSR_REG] = 1;
}
/* Implement TARGET_USE_PSEUDO_PIC_REG. */
static bool
sparc_use_pseudo_pic_reg (void)
{
return !TARGET_VXWORKS_RTP && flag_pic;
}
/* Implement TARGET_INIT_PIC_REG. */
static void
sparc_init_pic_reg (void)
{
edge entry_edge;
rtx_insn *seq;
if (!crtl->uses_pic_offset_table)
return;
start_sequence ();
load_got_register ();
if (!TARGET_VXWORKS_RTP)
emit_move_insn (pic_offset_table_rtx, global_offset_table_rtx);
seq = get_insns ();
end_sequence ();
entry_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
insert_insn_on_edge (seq, entry_edge);
commit_one_edge_insertion (entry_edge);
}
/* Implement TARGET_PREFERRED_RELOAD_CLASS:
- We can't load constants into FP registers.
......
......@@ -808,11 +808,14 @@ extern enum cmodel sparc_cmodel;
#define GLOBAL_OFFSET_TABLE_REGNUM 23
/* Register which holds offset table for position-independent
data references. */
/* Register which holds offset table for position-independent data references.
The original SPARC ABI imposes no requirement on the choice of the register
so we use a pseudo-register to make sure it is properly saved and restored
around calls to setjmp. Now the ABI of VxWorks RTP makes it live on entry
to PLT entries so we use the canonical GOT register in this case. */
#define PIC_OFFSET_TABLE_REGNUM \
(flag_pic ? GLOBAL_OFFSET_TABLE_REGNUM : INVALID_REGNUM)
(TARGET_VXWORKS_RTP && flag_pic ? GLOBAL_OFFSET_TABLE_REGNUM : INVALID_REGNUM)
/* Pick a default value we can notice from override_options:
!v9: Default is on.
......
......@@ -1797,7 +1797,7 @@
"flag_pic"
"or\t%1, %%lo(%a3-(%a2-.)), %0")
;; Set up the PIC register for VxWorks.
;; Set up the GOT register for VxWorks.
(define_expand "vxworks_load_got"
[(set (match_dup 0)
......@@ -1808,7 +1808,7 @@
(mem:SI (lo_sum:SI (match_dup 0) (match_dup 2))))]
"TARGET_VXWORKS_RTP"
{
operands[0] = pic_offset_table_rtx;
operands[0] = global_offset_table_rtx;
operands[1] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_BASE);
operands[2] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_INDEX);
})
......@@ -7475,7 +7475,7 @@ visl")
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"flag_pic"
"TARGET_VXWORKS_RTP && flag_pic"
{
load_got_register ();
DONE;
......
/* PR target/83368 */
/* Testcase written by James Clarke <jrtc27@jrtc27.com> */
/* { dg-do run { target *-*-solaris2.* *-*-linux* *-*-*bsd* } } */
/* { dg-require-effective-target fpic } */
/* { dg-options "-fPIC" } */
#include <stdio.h>
#include <alloca.h>
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>
jmp_buf jb;
int foo = 99;
int c = 0;
void bar (void)
{
c++;
longjmp (jb, 1);
}
int main (void)
{
setjmp (jb);
char *p = alloca (256);
memset (p, 0, 256);
sprintf (p, "%d\n", foo);
if (c < 10)
bar();
return 0;
}
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