]> gcc.gnu.org Git - gcc.git/commitdiff
xtensa: gcc: implement MI thunk generation for call0 ABI
authorMax Filippov <jcmvbkbc@gmail.com>
Thu, 14 Jul 2022 09:39:59 +0000 (02:39 -0700)
committerMax Filippov <jcmvbkbc@gmail.com>
Thu, 22 Sep 2022 10:53:43 +0000 (03:53 -0700)
gcc/
* config/xtensa/xtensa.cc (xtensa_can_output_mi_thunk)
(xtensa_output_mi_thunk): New functions.
(TARGET_ASM_CAN_OUTPUT_MI_THUNK)
(TARGET_ASM_OUTPUT_MI_THUNK): New macro definitions.
(xtensa_prepare_expand_call): Use fixed register a8 as temporary
when called with reload_completed set to 1.

gcc/config/xtensa/xtensa.cc

index f1b3331ea558cb6bfa785608ee69a64f608ccef1..e5abd356a745340e7460afa75e6a69f8f6fa51b1 100644 (file)
@@ -191,6 +191,15 @@ static bool xtensa_can_eliminate (const int from ATTRIBUTE_UNUSED,
 static HOST_WIDE_INT xtensa_starting_frame_offset (void);
 static unsigned HOST_WIDE_INT xtensa_asan_shadow_offset (void);
 static bool xtensa_function_ok_for_sibcall (tree, tree);
+static bool xtensa_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
+                                       HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
+                                       HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
+                                       const_tree function ATTRIBUTE_UNUSED);
+static void xtensa_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+                                   HOST_WIDE_INT delta,
+                                   HOST_WIDE_INT vcall_offset,
+                                   tree function);
+
 static rtx xtensa_delegitimize_address (rtx);
 
 \f
@@ -351,6 +360,12 @@ static rtx xtensa_delegitimize_address (rtx);
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL xtensa_function_ok_for_sibcall
 
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK xtensa_can_output_mi_thunk
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK xtensa_output_mi_thunk
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 \f
@@ -2173,7 +2188,16 @@ xtensa_prepare_expand_call (int callop, rtx *operands)
     addr = gen_sym_PLT (addr);
 
   if (!call_insn_operand (addr, VOIDmode))
-    XEXP (operands[callop], 0) = copy_to_mode_reg (Pmode, addr);
+    {
+      /* This may be called while generating MI thunk when we pretend
+        that reload is over.  Use a8 as a temporary register in that case.  */
+      rtx reg = can_create_pseudo_p ()
+       ? copy_to_mode_reg (Pmode, addr)
+       : copy_to_suggested_reg (addr,
+                                gen_rtx_REG (Pmode, A8_REG),
+                                Pmode);
+      XEXP (operands[callop], 0) = reg;
+    }
 }
 
 
@@ -4983,6 +5007,96 @@ xtensa_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, tree exp ATTRIBUTE_U
   return true;
 }
 
+static bool
+xtensa_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
+                           HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
+                           HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
+                           const_tree function ATTRIBUTE_UNUSED)
+{
+  if (TARGET_WINDOWED_ABI)
+    return false;
+
+  return true;
+}
+
+/* Output code to add DELTA to the first argument, and then jump
+   to FUNCTION.  Used for C++ multiple inheritance.  */
+static void
+xtensa_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+                       HOST_WIDE_INT delta,
+                       HOST_WIDE_INT vcall_offset,
+                       tree function)
+{
+  rtx this_rtx;
+  rtx funexp;
+  rtx_insn *insn;
+  int this_reg_no;
+  rtx temp0 = gen_rtx_REG (Pmode, A9_REG);
+  const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
+
+  reload_completed = 1;
+
+  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
+    this_reg_no = 3;
+  else
+    this_reg_no = 2;
+
+  this_rtx = gen_rtx_REG (Pmode, A0_REG + this_reg_no);
+
+  if (delta)
+    {
+      if (xtensa_simm8 (delta))
+       emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta)));
+      else
+       {
+         emit_move_insn (temp0, GEN_INT (delta));
+         emit_insn (gen_addsi3 (this_rtx, this_rtx, temp0));
+       }
+    }
+
+  if (vcall_offset)
+    {
+      rtx temp1 = gen_rtx_REG (Pmode, A0_REG + 10);
+      rtx addr = temp1;
+
+      emit_move_insn (temp0, gen_rtx_MEM (Pmode, this_rtx));
+      if (xtensa_uimm8x4 (vcall_offset))
+       addr = plus_constant (Pmode, temp0, vcall_offset);
+      else if (xtensa_simm8 (vcall_offset))
+       emit_insn (gen_addsi3 (temp1, temp0, GEN_INT (vcall_offset)));
+      else
+       {
+         emit_move_insn (temp1, GEN_INT (vcall_offset));
+         emit_insn (gen_addsi3 (temp1, temp0, temp1));
+       }
+      emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr));
+      emit_insn (gen_add2_insn (this_rtx, temp1));
+    }
+
+  /* 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);
+  funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
+  insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
+  SIBLING_CALL_P (insn) = 1;
+
+  insn = get_insns ();
+  shorten_branches (insn);
+  assemble_start_function (thunk, fnname);
+  final_start_function (insn, file, 1);
+  final (insn, file, 1);
+  final_end_function ();
+  assemble_end_function (thunk, fnname);
+
+  /* Stop pretending to be a post-reload pass.  */
+  reload_completed = 0;
+}
+
 static rtx
 xtensa_delegitimize_address (rtx op)
 {
This page took 0.07492 seconds and 5 git commands to generate.