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>