aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sparc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2018-01-12 11:29:30 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2018-01-12 11:29:30 +0000
commit46336a0eab790e4f94dd7e7ecf9339a884c44746 (patch)
tree51b16fb66a4da8d279c2e67e868a44edb627e20e /gcc/config/sparc
parent7dbf870757aa5a35d52a2e1a3c40ce488c898d14 (diff)
downloadgcc-46336a0eab790e4f94dd7e7ecf9339a884c44746.zip
gcc-46336a0eab790e4f94dd7e7ecf9339a884c44746.tar.gz
gcc-46336a0eab790e4f94dd7e7ecf9339a884c44746.tar.bz2
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
Diffstat (limited to 'gcc/config/sparc')
-rw-r--r--gcc/config/sparc/sparc.c104
-rw-r--r--gcc/config/sparc/sparc.h9
-rw-r--r--gcc/config/sparc/sparc.md6
3 files changed, 81 insertions, 38 deletions
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 668ccad..48669f1 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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.
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 1d10199..4199954 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -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.
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index ea75cf2..3255e5c 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -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;