This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[1/6, committed] RTP PIC support for MIPS VxWorks
- From: Richard Sandiford <richard at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 12 Apr 2007 18:11:25 +0100
- Subject: [1/6, committed] RTP PIC support for MIPS VxWorks
I'm committing a series of patches to add VxWorks RTP PIC support
to the MIPS backend. The RTP PIC model is very different from the
SVR4 one, so a bit of reorganisation was needed.
Many parts of the backend use TARGET_ABICALLS and TARGET_*ABI
to check things like "are we using a GOT?", "is GP call-saved?"
and "do indirect calls need to use $25?". The answer is "yes"
for some forms of RTP code too, so this first patch introduces
four new macros:
TARGET_USE_GOT
TARGET_CALL_CLOBBERED_GP
TARGET_CALL_SAVED_GP
TARGET_USE_PIC_FN_ADDR_REG
and replaces existing checks where appropriate.
Most of the patch is mechanical. I should perhaps highlight the change
to exception_receiver though. The pattern exists specifically to restore
a call-clobbered GP, so I've made it conditional on TARGET_CALL_CLOBBERED_GP.
However, the implementation asserts TARGET_ABICALLS && TARGET_OLDABI
(the only combination for which TARGET_CALL_CLOBBERED_GP is currently
true). This difference is deliberate: if TARGET_CALL_CLOBBERED_GP is
ever true for another combination, the assert will highlight the fact
that the implementation of exception_receiver must change.
Tested on mips64-linux-gnu and mips-wrs-vxworks. I also compiled
gcc.c-torture, gcc.dg and g++.dg before and after the patch with these
options, using a mips64-linux-gnu compiler:
{-mshared/-mexplicit-relocs
-mno-shared/-mexplicit-relocs
-mno-explicit-relocs}
x {-mxgot,-mno-xgot}
x {-mabi=32 -mabi=n32 -mabi=64}
There were no differences. Applied to head.
Richard
gcc/
* config/mips/mips.h (TARGET_SPLIT_CALLS): Check
TARGET_CALL_CLOBBERED_GP.
(TARGET_SIBCALLS): Check TARGET_USE_GOT instead of TARGET_ABICALLS.
(TARGET_USE_GOT, TARGET_CALL_CLOBBERED_GP): New macros.
(TARGET_CALL_SAVED_GP, TARGET_USE_PIC_FN_ADDR_REG): Likewise.
(STARTING_FRAME_OFFSET): Check TARGET_CALL_CLOBBERED_GP instead
of TARGET_ABICALLS && !TARGET_NEWABI.
(MIPS_CALL): Check TARGET_USE_GOT instead of TARGET_ABICALLS.
* config/mips/mips.c (mips_load_call_address): Check
TARGET_CALL_SAVED_GP instead of TARGET_NEWABI.
(mips_global_pointer): Check TARGET_USE_GOT instead of TARGET_ABICALLS.
Check TARGET_CALL_SAVED_GP instead of TARGET_NEWABI.
(mips_save_reg_p): Check TARGET_CALL_SAVED_GP instead of
TARGET_ABICALLS && TARGET_NEWABI.
(mips_current_loadgp_style): Check TARGET_USE_GOT instead of
TARGET_ABICALLS.
(mips_expand_prologue): Check TARGET_OLDABI instead of !TARGET_NEWABI.
(mips_expand_epilogue): Check TARGET_CALL_SAVED_GP instead of
TARGET_ABICALLS && TARGET_NEWABI.
(mips_output_mi_thunk): Check TARGET_USE_GOT instead of
TARGET_ABICALLS. Check TARGET_CALL_SAVED_GP instead of
TARGET_NEWABI. Use TARGET_USE_PIC_FN_ADDR_REG to decide
whether indirect calls must use $25.
(mips_extra_live_on_entry): Check TARGET_GOT instead of
TARGET_ABICALLS.
* config/mips/mips.md (jal_macro): Check flag_pic and
TARGET_CALL_CLOBBERED_GP instead of TARGET_ABICALLS and TARGET_NEWABI.
(builtin_setjmp_setup, builtin_longjmp): Check TARGET_USE_GOT
instead of TARGET_ABICALLS.
(exception_receiver): Check TARGET_CALL_CLOBBERED_GP instead of
TARGET_ABICALLS && TARGET_OLDABI.
(load_call<mode>): Check TARGET_USE_GOT instead of TARGET_ABICALLS.
(sibcall): In the comment above the define_insn, mention
TARGET_USE_PIC_FN_ADDR_REG instead of TARGET_ABICALLS.
* config/mips/constraints.md (c): Check TARGET_USE_PIC_FN_ADDR_REG
instead of TARGET_ABICALLS.
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h 2007-03-23 15:46:06.000000000 +0000
+++ gcc/config/mips/mips.h 2007-04-12 09:40:37.000000000 +0100
@@ -144,12 +144,11 @@ #define BITMASK_LOWER16 ((unsigned long)
/* Run-time compilation parameters selecting different hardware subsets. */
/* True if the call patterns should be split into a jalr followed by
- an instruction to restore $gp. This is only ever true for SVR4 PIC,
- in which $gp is call-clobbered. It is only safe to split the load
+ an instruction to restore $gp. It is only safe to split the load
from the call when every use of $gp is explicit. */
#define TARGET_SPLIT_CALLS \
- (TARGET_EXPLICIT_RELOCS && TARGET_ABICALLS && !TARGET_NEWABI)
+ (TARGET_EXPLICIT_RELOCS && TARGET_CALL_CLOBBERED_GP)
/* True if we're generating a form of -mabicalls in which we can use
operators like %hi and %lo to refer to locally-binding symbols.
@@ -173,12 +172,22 @@ #define TARGET_ABSOLUTE_ABICALLS \
using sibling calls in this case anyway; they would usually
be longer than normal calls.
- - TARGET_ABICALLS && !TARGET_EXPLICIT_RELOCS. call_insn_operand
- accepts global constants, but "jr $25" is the only allowed
- sibcall. */
-
+ - TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS. call_insn_operand
+ accepts global constants, but all sibcalls must be indirect. */
#define TARGET_SIBCALLS \
- (!TARGET_MIPS16 && (!TARGET_ABICALLS || TARGET_EXPLICIT_RELOCS))
+ (!TARGET_MIPS16 && (!TARGET_USE_GOT || TARGET_EXPLICIT_RELOCS))
+
+/* True if we need to use a global offset table to access some symbols. */
+#define TARGET_USE_GOT TARGET_ABICALLS
+
+/* True if TARGET_USE_GOT and if $gp is a call-clobbered register. */
+#define TARGET_CALL_CLOBBERED_GP (TARGET_ABICALLS && TARGET_OLDABI)
+
+/* True if TARGET_USE_GOT and if $gp is a call-saved register. */
+#define TARGET_CALL_SAVED_GP (TARGET_USE_GOT && !TARGET_CALL_CLOBBERED_GP)
+
+/* True if indirect calls must use register class PIC_FN_ADDR_REG. */
+#define TARGET_USE_PIC_FN_ADDR_REG TARGET_ABICALLS
/* True if .gpword or .gpdword should be used for switch tables.
@@ -1746,8 +1755,7 @@ #define STARTING_FRAME_OFFSET \
((flag_profile_values && ! TARGET_64BIT \
? MAX (REG_PARM_STACK_SPACE(NULL), current_function_outgoing_args_size) \
: current_function_outgoing_args_size) \
- + (TARGET_ABICALLS && !TARGET_NEWABI \
- ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0))
+ + (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0))
#define RETURN_ADDR_RTX mips_return_addr
@@ -2301,13 +2309,13 @@ #define MIPS_BRANCH(OPCODE, OPERANDS) \
("j" or "jal"), OPERANDS are its operands, and OPNO is the operand number
of the target.
- When generating -mabicalls without explicit relocation operators,
+ When generating GOT code without explicit relocation operators,
all calls should use assembly macros. Otherwise, all indirect
calls should use "jr" or "jalr"; we will arrange to restore $gp
afterwards if necessary. Finally, we can only generate direct
calls for -mabicalls by temporarily switching to non-PIC mode. */
#define MIPS_CALL(INSN, OPERANDS, OPNO) \
- (TARGET_ABICALLS && !TARGET_EXPLICIT_RELOCS \
+ (TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS \
? "%*" INSN "\t%" #OPNO "%/" \
: REG_P (OPERANDS[OPNO]) \
? "%*" INSN "r\t%" #OPNO "%/" \
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c 2007-04-01 12:23:49.000000000 +0100
+++ gcc/config/mips/mips.c 2007-04-12 09:40:24.000000000 +0100
@@ -3354,10 +3354,10 @@ mips_load_call_address (rtx dest, rtx ad
{
/* If we're generating PIC, and this call is to a global function,
try to allow its address to be resolved lazily. This isn't
- possible for NewABI sibcalls since the value of $gp on entry
+ possible if TARGET_CALL_SAVED_GP since the value of $gp on entry
to the stub would be our caller's gp, not ours. */
if (TARGET_EXPLICIT_RELOCS
- && !(sibcall_p && TARGET_NEWABI)
+ && !(sibcall_p && TARGET_CALL_SAVED_GP)
&& global_got_operand (addr, VOIDmode))
{
rtx high, lo_sum_symbol;
@@ -6144,8 +6144,8 @@ mips_global_pointer (void)
{
unsigned int regno;
- /* $gp is always available in non-abicalls code. */
- if (!TARGET_ABICALLS)
+ /* $gp is always available unless we're using a GOT. */
+ if (!TARGET_USE_GOT)
return GLOBAL_POINTER_REGNUM;
/* We must always provide $gp when it is used implicitly. */
@@ -6182,7 +6182,7 @@ mips_global_pointer (void)
/* We need a global pointer, but perhaps we can use a call-clobbered
register instead of $gp. */
- if (TARGET_NEWABI && current_function_is_leaf)
+ if (TARGET_CALL_SAVED_GP && current_function_is_leaf)
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
if (!regs_ever_live[regno]
&& call_used_regs[regno]
@@ -6199,10 +6199,10 @@ mips_global_pointer (void)
static bool
mips_save_reg_p (unsigned int regno)
{
- /* We only need to save $gp for NewABI PIC. */
+ /* We only need to save $gp if TARGET_CALL_SAVED_GP and only then
+ if we have not chosen a call-clobbered substitute. */
if (regno == GLOBAL_POINTER_REGNUM)
- return (TARGET_ABICALLS && TARGET_NEWABI
- && cfun->machine->global_pointer == regno);
+ return TARGET_CALL_SAVED_GP && cfun->machine->global_pointer == regno;
/* Check call-saved registers. */
if (regs_ever_live[regno] && !call_used_regs[regno])
@@ -6546,7 +6546,7 @@ mips_output_cplocal (void)
enum mips_loadgp_style
mips_current_loadgp_style (void)
{
- if (!TARGET_ABICALLS || cfun->machine->global_pointer == 0)
+ if (!TARGET_USE_GOT || cfun->machine->global_pointer == 0)
return LOADGP_NONE;
if (TARGET_ABSOLUTE_ABICALLS)
@@ -6858,7 +6858,7 @@ mips_expand_prologue (void)
mips_emit_loadgp ();
/* If generating o32/o64 abicalls, save $gp on the stack. */
- if (TARGET_ABICALLS && !TARGET_NEWABI && !current_function_is_leaf)
+ if (TARGET_ABICALLS && TARGET_OLDABI && !current_function_is_leaf)
emit_insn (gen_cprestore (GEN_INT (current_function_outgoing_args_size)));
/* If we are profiling, make sure no instructions are scheduled before
@@ -6992,10 +6992,10 @@ mips_expand_epilogue (int sibcall_p)
if (target != stack_pointer_rtx)
emit_move_insn (stack_pointer_rtx, target);
- /* If we're using addressing macros for n32/n64 abicalls, $gp is
- implicitly used by all SYMBOL_REFs. We must emit a blockage
- insn before restoring it. */
- if (TARGET_ABICALLS && TARGET_NEWABI && !TARGET_EXPLICIT_RELOCS)
+ /* If we're using addressing macros, $gp is implicitly used by all
+ SYMBOL_REFs. We must emit a blockage insn before restoring $gp
+ from the stack. */
+ if (TARGET_CALL_SAVED_GP && !TARGET_EXPLICIT_RELOCS)
emit_insn (gen_blockage ());
/* Restore the registers. */
@@ -7086,12 +7086,12 @@ mips_output_mi_thunk (FILE *file, tree t
reload_completed = 1;
reset_block_changes ();
- /* Pick a global pointer for -mabicalls. Use $15 rather than $28
- for TARGET_NEWABI since the latter is a call-saved register. */
- if (TARGET_ABICALLS)
+ /* Pick a global pointer. Use a call-clobbered register if
+ TARGET_CALL_SAVED_GP, so that we can use a sibcall. */
+ if (TARGET_USE_GOT)
cfun->machine->global_pointer
= REGNO (pic_offset_table_rtx)
- = TARGET_NEWABI ? 15 : GLOBAL_POINTER_REGNUM;
+ = TARGET_CALL_SAVED_GP ? 15 : GLOBAL_POINTER_REGNUM;
/* Set up the global pointer for n32 or n64 abicalls. */
mips_emit_loadgp ();
@@ -7137,24 +7137,27 @@ mips_output_mi_thunk (FILE *file, tree t
/* Jump to the target function. Use a sibcall if direct jumps are
allowed, otherwise load the address into a register first. */
fnaddr = XEXP (DECL_RTL (function), 0);
- if (TARGET_MIPS16 || TARGET_ABICALLS || TARGET_LONG_CALLS)
+ if (TARGET_MIPS16 || TARGET_USE_GOT || TARGET_LONG_CALLS)
{
/* This is messy. gas treats "la $25,foo" as part of a call
sequence and may allow a global "foo" to be lazily bound.
The general move patterns therefore reject this combination.
- In this context, lazy binding would actually be OK for o32 and o64,
- but it's still wrong for n32 and n64; see mips_load_call_address.
- We must therefore load the address via a temporary register if
- mips_dangerous_for_la25_p.
+ In this context, lazy binding would actually be OK
+ for TARGET_CALL_CLOBBERED_GP, but it's still wrong for
+ TARGET_CALL_SAVED_GP; see mips_load_call_address.
+ We must therefore load the address via a temporary
+ register if mips_dangerous_for_la25_p.
If we jump to the temporary register rather than $25, the assembler
can use the move insn to fill the jump's delay slot. */
- if (TARGET_ABICALLS && !mips_dangerous_for_la25_p (fnaddr))
+ if (TARGET_USE_PIC_FN_ADDR_REG
+ && !mips_dangerous_for_la25_p (fnaddr))
temp1 = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
mips_load_call_address (temp1, fnaddr, true);
- if (TARGET_ABICALLS && REGNO (temp1) != PIC_FUNCTION_ADDR_REGNUM)
+ if (TARGET_USE_PIC_FN_ADDR_REG
+ && REGNO (temp1) != PIC_FUNCTION_ADDR_REGNUM)
emit_move_insn (gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM), temp1);
emit_jump_insn (gen_indirect_jump (temp1));
}
@@ -10878,13 +10881,13 @@ mips_encode_section_info (tree decl, rtx
}
}
-/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. PIC_FUNCTION_ADDR_REGNUM is live
- on entry to a function when generating -mshared abicalls code. */
+/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. Some code models use the incoming
+ value of PIC_FUNCTION_ADDR_REGNUM to set up the global pointer. */
static void
mips_extra_live_on_entry (bitmap regs)
{
- if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS)
+ if (TARGET_USE_GOT && !TARGET_ABSOLUTE_ABICALLS)
bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM);
}
Index: gcc/config/mips/mips.md
===================================================================
--- gcc/config/mips/mips.md 2007-04-10 10:18:19.000000000 +0100
+++ gcc/config/mips/mips.md 2007-04-12 09:40:24.000000000 +0100
@@ -221,15 +221,16 @@ (define_attr "jal" "unset,direct,indirec
;; This attribute is YES if the instruction is a jal macro (not a
;; real jal instruction).
;;
-;; jal is always a macro for o32 and o64 abicalls because it includes an
-;; instruction to restore $gp. Direct jals are also macros for -mshared
-;; abicalls because they first load the target address into $25.
+;; jal is always a macro for TARGET_CALL_CLOBBERED_GP because it includes
+;; an instruction to restore $gp. Direct jals are also macros for
+;; flag_pic && !TARGET_ABSOLUTE_ABICALLS because they first load
+;; the target address into a register.
(define_attr "jal_macro" "no,yes"
(cond [(eq_attr "jal" "direct")
- (symbol_ref "TARGET_ABICALLS
- && (TARGET_OLDABI || !TARGET_ABSOLUTE_ABICALLS)")
+ (symbol_ref "TARGET_CALL_CLOBBERED_GP
+ || (flag_pic && !TARGET_ABSOLUTE_ABICALLS)")
(eq_attr "jal" "indirect")
- (symbol_ref "TARGET_ABICALLS && TARGET_OLDABI")]
+ (symbol_ref "TARGET_CALL_CLOBBERED_GP")]
(const_string "no")))
;; Classification of each insn.
@@ -4947,14 +4948,14 @@ (define_insn "tablejump<mode>"
[(set_attr "type" "jump")
(set_attr "mode" "none")])
-;; For TARGET_ABICALLS, we save the gp in the jmp_buf as well.
+;; For TARGET_USE_GOT, we save the gp in the jmp_buf as well.
;; While it is possible to either pull it off the stack (in the
;; o32 case) or recalculate it given t9 and our target label,
;; it takes 3 or 4 insns to do so.
(define_expand "builtin_setjmp_setup"
[(use (match_operand 0 "register_operand"))]
- "TARGET_ABICALLS"
+ "TARGET_USE_GOT"
{
rtx addr;
@@ -4969,7 +4970,7 @@ (define_expand "builtin_setjmp_setup"
(define_expand "builtin_longjmp"
[(use (match_operand 0 "register_operand"))]
- "TARGET_ABICALLS"
+ "TARGET_USE_GOT"
{
/* The elements of the buffer are, in order: */
int W = GET_MODE_SIZE (Pmode);
@@ -5105,7 +5106,7 @@ (define_split
(define_insn_and_split "exception_receiver"
[(set (reg:SI 28)
(unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))]
- "TARGET_ABICALLS && TARGET_OLDABI"
+ "TARGET_CALL_CLOBBERED_GP"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -5143,7 +5144,7 @@ (define_insn "load_call<mode>"
(match_operand:P 2 "immediate_operand" "")
(reg:P FAKE_CALL_REGNO)]
UNSPEC_LOAD_CALL))]
- "TARGET_ABICALLS"
+ "TARGET_USE_GOT"
"<load>\t%0,%R2(%1)"
[(set_attr "type" "load")
(set_attr "mode" "<MODE>")
@@ -5157,9 +5158,10 @@ (define_insn "load_call<mode>"
;; constraints.
;; When we use an indirect jump, we need a register that will be
-;; preserved by the epilogue. Since TARGET_ABICALLS forces us to
-;; use $25 for this purpose -- and $25 is never clobbered by the
-;; epilogue -- we might as well use it for !TARGET_ABICALLS as well.
+;; preserved by the epilogue. Since TARGET_USE_PIC_FN_ADDR_REG forces
+;; us to use $25 for this purpose -- and $25 is never clobbered by the
+;; epilogue -- we might as well use it for !TARGET_USE_PIC_FN_ADDR_REG
+;; as well.
(define_expand "sibcall"
[(parallel [(call (match_operand 0 "")
Index: gcc/config/mips/constraints.md
===================================================================
--- gcc/config/mips/constraints.md 2006-11-27 22:55:04.000000000 +0000
+++ gcc/config/mips/constraints.md 2007-04-12 09:40:24.000000000 +0100
@@ -42,7 +42,7 @@ (define_register_constraint "x" "MD_REGS
(define_register_constraint "b" "ALL_REGS"
"@internal")
-(define_register_constraint "c" "TARGET_ABICALLS ? PIC_FN_ADDR_REG
+(define_register_constraint "c" "TARGET_USE_PIC_FN_ADDR_REG ? PIC_FN_ADDR_REG
: TARGET_MIPS16 ? M16_NA_REGS
: GR_REGS"
"A register suitable for use in an indirect jump. This will always be