This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]