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
Ramana Radhakrishnan
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
Date: Fri Nov 20 13:49:12 2015 +
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,