diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2018-01-12 11:29:30 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2018-01-12 11:29:30 +0000 |
commit | 46336a0eab790e4f94dd7e7ecf9339a884c44746 (patch) | |
tree | 51b16fb66a4da8d279c2e67e868a44edb627e20e /gcc/config/sparc | |
parent | 7dbf870757aa5a35d52a2e1a3c40ce488c898d14 (diff) | |
download | gcc-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.c | 104 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.h | 9 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 6 |
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; |