nios2-protos.h (nios2_adjust_call_address): Adjust function parameter declaration.
authorChung-Lin Tang <cltang@codesourcery.com>
Sun, 22 Mar 2015 02:39:24 +0000 (02:39 +0000)
committerSandra Loosemore <sandra@gcc.gnu.org>
Sun, 22 Mar 2015 02:39:24 +0000 (22:39 -0400)
2015-03-21  Chung-Lin Tang  <cltang@codesourcery.com>
    Sandra Loosemore  <sandra@codesourcery.com>

gcc/
* config/nios2/nios2-protos.h (nios2_adjust_call_address): Adjust
function parameter declaration.
* config/nios2/nios2.md (call,call_value,sibcall,sibcall_value):
Update arguments to nios2_adjust_call_address().
(sibcall_internal): Rename from *sibcall.
(sibcall_value_internal): Rename from *sibcall_value.
* config/nios2/nios2.c (nios2_emit_add_constant): New function.
(nios2_large_got_address): Add target temp reg parameter.
(nios2_got_address): Adjust call to nios2_large_got_address, add
force_reg around it.
(nios2_load_pic_address): Add target temp reg parameter, replace call
to nios2_got_address with corresponding code.
(nios2_legitimize_constant_address): Update call to
nios2_load_pic_address.
(nios2_adjust_call_address): Add temp reg parameter, update PIC case
to use temp reg for PIC loading purposes.
(nios2_asm_output_mi_thunk): Implement TARGET_ASM_OUTPUT_MI_THUNK.
(TARGET_ASM_CAN_OUTPUT_MI_THUNK): Define.
(TARGET_ASM_OUTPUT_MI_THUNK): Likewise.

Co-Authored-By: Sandra Loosemore <sandra@codesourcery.com>
From-SVN: r221569

gcc/ChangeLog
gcc/config/nios2/nios2-protos.h
gcc/config/nios2/nios2.c
gcc/config/nios2/nios2.md

index d0ed566deb4313e39928f31482c7595be7b4ea6b..856438e42688ac61566f5b7a92bcaff7532f1290 100644 (file)
@@ -1,3 +1,26 @@
+2015-03-21  Chung-Lin Tang  <cltang@codesourcery.com>
+           Sandra Loosemore  <sandra@codesourcery.com>
+
+       * config/nios2/nios2-protos.h (nios2_adjust_call_address): Adjust
+       function parameter declaration.
+       * config/nios2/nios2.md (call,call_value,sibcall,sibcall_value):
+       Update arguments to nios2_adjust_call_address().
+       (sibcall_internal): Rename from *sibcall.
+       (sibcall_value_internal): Rename from *sibcall_value.
+       * config/nios2/nios2.c (nios2_emit_add_constant): New function.
+       (nios2_large_got_address): Add target temp reg parameter.
+       (nios2_got_address): Adjust call to nios2_large_got_address, add
+       force_reg around it.
+       (nios2_load_pic_address): Add target temp reg parameter, replace call
+       to nios2_got_address with corresponding code.
+       (nios2_legitimize_constant_address): Update call to
+       nios2_load_pic_address.
+       (nios2_adjust_call_address): Add temp reg parameter, update PIC case
+       to use temp reg for PIC loading purposes.
+       (nios2_asm_output_mi_thunk): Implement TARGET_ASM_OUTPUT_MI_THUNK.
+       (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Define.
+       (TARGET_ASM_OUTPUT_MI_THUNK): Likewise.
+
 2015-03-21  Sandra Loosemore  <sandra@codesourcery.com>
 
        * doc/invoke.texi (-fno-diagnostics-show-caret): Fix
index f33f52125854bd51830083f57fb9452f45e6197f..903a9fddf60391f4d9ef1aefebd9df2787481723 100644 (file)
@@ -31,7 +31,7 @@ extern void nios2_function_profiler (FILE *, int);
 #ifdef RTX_CODE
 extern int nios2_emit_move_sequence (rtx *, machine_mode);
 extern void nios2_emit_expensive_div (rtx *, machine_mode);
-extern void nios2_adjust_call_address (rtx *);
+extern void nios2_adjust_call_address (rtx *, rtx);
 
 extern rtx nios2_get_return_address (int);
 extern void nios2_set_return_address (rtx, rtx);
index df33077947c00b6bb687cca62585c8f8b349dc66..848cc513537d377381cd683d0e486d52c903b24c 100644 (file)
@@ -489,6 +489,21 @@ nios2_emit_stack_limit_check (void)
 /* Temp regno used inside prologue/epilogue.  */
 #define TEMP_REG_NUM 8
 
+static rtx
+nios2_emit_add_constant (rtx reg, HOST_WIDE_INT immed)
+{
+  rtx insn;
+  if (SMALL_INT (immed))
+    insn = emit_insn (gen_add2_insn (reg, gen_int_mode (immed, Pmode)));
+  else
+    {
+      rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+      emit_move_insn (tmp, gen_int_mode (immed, Pmode));
+      insn = emit_insn (gen_add2_insn (reg, tmp));
+    }
+  return insn;
+}
+
 void
 nios2_expand_prologue (void)
 {
@@ -1229,12 +1244,12 @@ nios2_unspec_offset (rtx loc, int unspec)
 
 /* Generate GOT pointer based address with large offset.  */
 static rtx
-nios2_large_got_address (rtx offset)
+nios2_large_got_address (rtx offset, rtx tmp)
 {
-  rtx addr = gen_reg_rtx (Pmode);
-  emit_insn (gen_add3_insn (addr, pic_offset_table_rtx,
-                           force_reg (Pmode, offset)));
-  return addr;
+  if (!tmp)
+    tmp = gen_reg_rtx (Pmode);
+  emit_move_insn (tmp, offset);
+  return gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);
 }
 
 /* Generate a GOT pointer based address.  */
@@ -1245,7 +1260,7 @@ nios2_got_address (rtx loc, int unspec)
   crtl->uses_pic_offset_table = 1;
 
   if (nios2_large_offset_p (unspec))
-    return nios2_large_got_address (offset);
+    return force_reg (Pmode, nios2_large_got_address (offset, NULL_RTX));
 
   return gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
 }
@@ -1784,13 +1799,17 @@ nios2_load_pic_register (void)
 
 /* Generate a PIC address as a MEM rtx.  */
 static rtx
-nios2_load_pic_address (rtx sym, int unspec)
+nios2_load_pic_address (rtx sym, int unspec, rtx tmp)
 {
   if (flag_pic == 2
       && GET_CODE (sym) == SYMBOL_REF
       && nios2_symbol_binds_local_p (sym))
     /* Under -fPIC, generate a GOTOFF address for local symbols.  */
-    return nios2_got_address (sym, UNSPEC_PIC_GOTOFF_SYM);
+    {
+      rtx offset = nios2_unspec_offset (sym, UNSPEC_PIC_GOTOFF_SYM);
+      crtl->uses_pic_offset_table = 1;
+      return nios2_large_got_address (offset, tmp);
+    }
 
   return gen_const_mem (Pmode, nios2_got_address (sym, unspec));
 }
@@ -1828,7 +1847,7 @@ nios2_legitimize_constant_address (rtx addr)
   if (nios2_tls_symbol_p (base))
     base = nios2_legitimize_tls_address (base);
   else if (flag_pic)
-    base = nios2_load_pic_address (base, UNSPEC_PIC_SYM);
+    base = nios2_load_pic_address (base, UNSPEC_PIC_SYM, NULL_RTX);
   else
     return addr;
 
@@ -1943,18 +1962,24 @@ nios2_emit_move_sequence (rtx *operands, machine_mode mode)
 
 /* The function with address *ADDR is being called.  If the address
    needs to be loaded from the GOT, emit the instruction to do so and
-   update *ADDR to point to the rtx for the loaded value.  */
+   update *ADDR to point to the rtx for the loaded value.
+   If REG != NULL_RTX, it is used as the target/scratch register in the
+   GOT address calculation.  */
 void
-nios2_adjust_call_address (rtx *call_op)
+nios2_adjust_call_address (rtx *call_op, rtx reg)
 {
-  rtx addr;
-  gcc_assert (MEM_P (*call_op));
-  addr = XEXP (*call_op, 0);
+  if (MEM_P (*call_op))
+    call_op = &XEXP (*call_op, 0);
+
+  rtx addr = *call_op;
   if (flag_pic && CONSTANT_P (addr))
     {
-      rtx reg = gen_reg_rtx (Pmode);
-      emit_move_insn (reg, nios2_load_pic_address (addr, UNSPEC_PIC_CALL_SYM));
-      XEXP (*call_op, 0) = reg;
+      rtx tmp = reg ? reg : NULL_RTX;
+      if (!reg)
+       reg = gen_reg_rtx (Pmode);
+      addr = nios2_load_pic_address (addr, UNSPEC_PIC_CALL_SYM, tmp);
+      emit_insn (gen_rtx_SET (VOIDmode, reg, addr));
+      *call_op = reg;
     }
 }
 
@@ -3319,6 +3344,73 @@ nios2_merge_decl_attributes (tree olddecl, tree newdecl)
                           DECL_ATTRIBUTES (newdecl));
 }
 
+/* Implement TARGET_ASM_OUTPUT_MI_THUNK.  */
+static void
+nios2_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+                          HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
+                          tree function)
+{
+  rtx this_rtx, funexp;
+  rtx_insn *insn;
+
+  /* Pretend to be a post-reload pass while generating rtl.  */
+  reload_completed = 1;
+
+  if (flag_pic)
+    nios2_load_pic_register ();
+
+  /* Mark the end of the (empty) prologue.  */
+  emit_note (NOTE_INSN_PROLOGUE_END);
+
+  /* Find the "this" pointer.  If the function returns a structure,
+     the structure return pointer is in $5.  */
+  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
+    this_rtx = gen_rtx_REG (Pmode, FIRST_ARG_REGNO + 1);
+  else
+    this_rtx = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
+
+  /* Add DELTA to THIS_RTX.  */
+  nios2_emit_add_constant (this_rtx, delta);
+
+  /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX.  */
+  if (vcall_offset)
+    {
+      rtx tmp;
+
+      tmp = gen_rtx_REG (Pmode, 2);
+      emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
+      nios2_emit_add_constant (tmp, vcall_offset);
+      emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
+      emit_insn (gen_add2_insn (this_rtx, tmp));
+    }
+
+  /* Generate a tail call to the target function.  */
+  if (!TREE_USED (function))
+    {
+      assemble_external (function);
+      TREE_USED (function) = 1;
+    }
+  funexp = XEXP (DECL_RTL (function), 0);
+  /* Function address needs to be constructed under PIC,
+     provide r2 to use here.  */
+  nios2_adjust_call_address (&funexp, gen_rtx_REG (Pmode, 2));
+  insn = emit_call_insn (gen_sibcall_internal (funexp, const0_rtx));
+  SIBLING_CALL_P (insn) = 1;
+
+  /* Run just enough of rest_of_compilation to get the insns emitted.
+     There's not really enough bulk here to make other passes such as
+     instruction scheduling worth while.  Note that use_thunk calls
+     assemble_start_function and assemble_end_function.  */
+  insn = get_insns ();
+  shorten_branches (insn);
+  final_start_function (insn, file, 1);
+  final (insn, file, 1);
+  final_end_function ();
+
+  /* Stop pretending to be a post-reload pass.  */
+  reload_completed = 0;
+}
+
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_FUNCTION_PROLOGUE
@@ -3439,6 +3531,13 @@ nios2_merge_decl_attributes (tree olddecl, tree newdecl)
 #undef TARGET_MERGE_DECL_ATTRIBUTES
 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
 
+#undef  TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
+  hook_bool_const_tree_hwi_hwi_const_tree_true
+
+#undef  TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK nios2_asm_output_mi_thunk
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-nios2.h"
index c13cf74ce05b450298b2b22e5e7552fee7da77c2..7b35d269c1c824e247c3aed06dfa22ea0ec55ef7 100644 (file)
                     (match_operand 1 "" ""))
               (clobber (reg:SI RA_REGNO))])]
   ""
-  "nios2_adjust_call_address (&operands[0]);")
+  "nios2_adjust_call_address (&operands[0], NULL_RTX);")
 
 (define_expand "call_value"
   [(parallel [(set (match_operand 0 "" "")
                          (match_operand 2 "" "")))
               (clobber (reg:SI RA_REGNO))])]
   ""
-  "nios2_adjust_call_address (&operands[1]);")
+  "nios2_adjust_call_address (&operands[1], NULL_RTX);")
 
 (define_insn "*call"
   [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
                     (match_operand 1 "" ""))
               (return)])]
   ""
-  "nios2_adjust_call_address (&operands[0]);")
+  "nios2_adjust_call_address (&operands[0], NULL_RTX);")
 
 (define_expand "sibcall_value"
   [(parallel [(set (match_operand 0 "" "")
                          (match_operand 2 "" "")))
               (return)])]
   ""
-  "nios2_adjust_call_address (&operands[1]);")
+  "nios2_adjust_call_address (&operands[1], NULL_RTX);")
 
-(define_insn "*sibcall"
+(define_insn "sibcall_internal"
  [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
         (match_operand 1 "" ""))
   (return)]
    jmp\\t%0"
   [(set_attr "type" "control")])
 
-(define_insn "*sibcall_value"
+(define_insn "sibcall_value_internal"
  [(set (match_operand 0 "register_operand" "")
        (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
              (match_operand 2 "" "")))