I've had this in my tree for a few months now but never got
around to submitting it.

This partially fixes PR target/53440 atleast in ARM and
Thumb2 state. I haven't yet managed to get my head around
rewriting the Thumb1 support yet.

Tested on armhf with a bootstrap and regression test
with no regressions.

Queued for stage1 now as it isn't technically a regression.

regards
Ramana


<DATE>  Ramana Radhakrishnan  <ramana.radhakrish...@arm.com>

        PR target/53440
        * config/arm/arm.c (arm32_output_mi_thunk): New.
        (arm_output_mi_thunk): Rename to arm_thumb1_mi_thunk. Rework
        to split Thumb1 vs TARGET_32BIT functionality.
        (arm_thumb1_mi_thunk): New.


        * g++.dg/inherit/thunk1.C: Support arm / aarch64.
commit da356d8d7df8d958920c66bf18ae9c1473d98ec2
Author: Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Date:   Fri Nov 20 13:49:12 2015 +0000

    thunk

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 2075c41..cdecf29 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -300,6 +300,9 @@ static void arm_canonicalize_comparison (int *code, rtx 
*op0, rtx *op1,
 static unsigned HOST_WIDE_INT arm_asan_shadow_offset (void);
 
 static void arm_sched_fusion_priority (rtx_insn *, int, int *, int*);
+static bool arm_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT,
+                                    const_tree);
+
 
 /* Table of machine attributes.  */
 static const struct attribute_spec arm_attribute_table[] =
@@ -463,7 +466,7 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef  TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk
 #undef  TARGET_ASM_CAN_OUTPUT_MI_THUNK
-#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK arm_can_output_mi_thunk
 
 #undef  TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS arm_rtx_costs
@@ -26040,11 +26043,10 @@ arm_internal_label (FILE *stream, const char *prefix, 
unsigned long labelno)
 
 /* Output code to add DELTA to the first argument, and then jump
    to FUNCTION.  Used for C++ multiple inheritance.  */
+
 static void
-arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
-                    HOST_WIDE_INT delta,
-                    HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
-                    tree function)
+arm_thumb1_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
+                    HOST_WIDE_INT, tree function)
 {
   static int thunk_label = 0;
   char label[256];
@@ -26185,6 +26187,76 @@ arm_output_mi_thunk (FILE *file, tree thunk 
ATTRIBUTE_UNUSED,
   final_end_function ();
 }
 
+/* MI thunk handling for TARGET_32BIT.  */
+
+static void
+arm32_output_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
+                      HOST_WIDE_INT vcall_offset, tree function)
+{
+  /* On ARM, this_regno is R0 or R1 depending on
+     whether the function returns an aggregate or not.
+  */
+  int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)),
+                                      function)
+                   ? R1_REGNUM : R0_REGNUM);
+
+  rtx temp = gen_rtx_REG (Pmode, IP_REGNUM);
+  rtx this_rtx = gen_rtx_REG (Pmode, this_regno);
+  reload_completed = 1;
+  emit_note (NOTE_INSN_PROLOGUE_END);
+
+  /* Add DELTA to THIS_RTX.  */
+  if (delta != 0)
+    arm_split_constant (PLUS, Pmode, NULL_RTX,
+                       delta, this_rtx, this_rtx, false);
+
+  /* Add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX.  */
+  if (vcall_offset != 0)
+    {
+      /* Load *THIS_RTX.  */
+      emit_move_insn (temp, gen_rtx_MEM (Pmode, this_rtx));
+      /* Compute *THIS_RTX + VCALL_OFFSET.  */
+      arm_split_constant (PLUS, Pmode, NULL_RTX, vcall_offset, temp, temp,
+                         false);
+      /* Compute *(*THIS_RTX + VCALL_OFFSET).  */
+      emit_move_insn (temp, gen_rtx_MEM (Pmode, temp));
+      emit_insn (gen_add3_insn (this_rtx, this_rtx, temp));
+    }
+
+  /* Generate a tail call to the target function.  */
+  if (!TREE_USED (function))
+    {
+      assemble_external (function);
+      TREE_USED (function) = 1;
+    }
+  rtx funexp = XEXP (DECL_RTL (function), 0);
+  funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
+  rtx_insn * insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, 
NULL_RTX));
+  SIBLING_CALL_P (insn) = 1;
+
+  insn = get_insns ();
+  shorten_branches (insn);
+  final_start_function (insn, file, 1);
+  final (insn, file, 1);
+  final_end_function ();
+
+  /* Stop pretending this is a post-reload pass.  */
+  reload_completed = 0;
+}
+
+/* Output code to add DELTA to the first argument, and then jump
+   to FUNCTION.  Used for C++ multiple inheritance.  */
+
+static void
+arm_output_mi_thunk (FILE *file, tree thunk, HOST_WIDE_INT delta,
+                    HOST_WIDE_INT vcall_offset, tree function)
+{
+  if (TARGET_32BIT)
+    arm32_output_mi_thunk (file, thunk, delta, vcall_offset, function);
+  else
+    arm_thumb1_mi_thunk (file, thunk, delta, vcall_offset, function);
+}
+
 int
 arm_emit_vector_const (FILE *file, rtx x)
 {
@@ -30163,4 +30235,18 @@ arm_sched_fusion_priority (rtx_insn *insn, int max_pri,
   return;
 }
 
+/* Can output mi_thunk for all cases except for non-zero vcall_offset
+   in Thumb1.  */
+static bool
+arm_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT vcall_offset,
+                        const_tree)
+{
+  /* For now, we punt and not handle this for TARGET_THUMB1.  */
+  if (vcall_offset && TARGET_THUMB1)
+    return false;
+
+  /* Otherwise ok.  */
+  return true;
+}
+
 #include "gt-arm.h"
diff --git a/gcc/testsuite/g++.dg/inherit/thunk1.C 
b/gcc/testsuite/g++.dg/inherit/thunk1.C
index 3bbd050..e59586a 100644
--- a/gcc/testsuite/g++.dg/inherit/thunk1.C
+++ b/gcc/testsuite/g++.dg/inherit/thunk1.C
@@ -1,4 +1,5 @@
-// { dg-do run { target i?86-*-* x86_64-*-* s390*-*-* alpha*-*-* ia64-*-* 
sparc*-*-* } }
+// { dg-skip-if "" { arm_thumb1_ok } }
+// { dg-do run { target arm*-*-* aarch64*-*-* i?86-*-* x86_64-*-* s390*-*-* 
alpha*-*-* ia64-*-* sparc*-*-* } }
 
 #include <stdarg.h>
 

Reply via email to