aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamana Radhakrishnan <ramana.radhakrishnan@arm.com>2016-05-13 09:32:29 +0000
committerRamana Radhakrishnan <ramana@gcc.gnu.org>2016-05-13 09:32:29 +0000
commitc959db3d3b344fa2e21fdd79768e2349d7c2db25 (patch)
treed5453fb8781fd3155de6a7028b49ec1db7df0b3e
parent43203dea1afa87140a0f045f2c2182943247065f (diff)
downloadgcc-c959db3d3b344fa2e21fdd79768e2349d7c2db25.zip
gcc-c959db3d3b344fa2e21fdd79768e2349d7c2db25.tar.gz
gcc-c959db3d3b344fa2e21fdd79768e2349d7c2db25.tar.bz2
Fix PR target/53440 - handle generic thunks better for TARGET_32BIT.
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 2016-05-13 Ramana Radhakrishnan <ramana.radhakrishnan@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. From-SVN: r236198
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/arm/arm.c96
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/inherit/thunk1.C3
4 files changed, 106 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 87f5eaf..27deda6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2016-05-13 Ramana Radhakrishnan <ramana.radhakrishnan@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.
+
+2016-05-13 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
* config/aarch64/aarch64.c (TARGET_OMIT_STRUCT_RETURN_REG): Set
to true.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 58b0432..fbae1bc 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
@@ -26132,11 +26135,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];
@@ -26277,6 +26279,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)
{
@@ -30381,4 +30453,18 @@ arm_simd_check_vect_par_cnst_half_p (rtx op, machine_mode mode,
return true;
}
+/* 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/ChangeLog b/gcc/testsuite/ChangeLog
index 333bec6..e3b0280 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2016-05-13 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+ PR target/53440
+ * g++.dg/inherit/thunk1.C: Support arm / aarch64.
+
+2016-05-13 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
* gcc.target/aarch64/struct_return.c: New test.
2016-05-12 Marek Polacek <polacek@redhat.com>
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>