From c959db3d3b344fa2e21fdd79768e2349d7c2db25 Mon Sep 17 00:00:00 2001 From: Ramana Radhakrishnan Date: Fri, 13 May 2016 09:32:29 +0000 Subject: [PATCH] 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 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 --- gcc/ChangeLog | 8 +++ gcc/config/arm/arm.c | 96 +++++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/inherit/thunk1.C | 3 +- 4 files changed, 106 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 87f5eaff15b..27deda6cc14 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-05-13 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. + 2016-05-13 Ramana Radhakrishnan * config/aarch64/aarch64.c (TARGET_OMIT_STRUCT_RETURN_REG): Set diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 58b04322d18..fbae1bcf5ea 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 333bec6c546..e3b0280a35d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-05-13 Ramana Radhakrishnan + + PR target/53440 + * g++.dg/inherit/thunk1.C: Support arm / aarch64. + 2016-05-13 Ramana Radhakrishnan * gcc.target/aarch64/struct_return.c: New test. diff --git a/gcc/testsuite/g++.dg/inherit/thunk1.C b/gcc/testsuite/g++.dg/inherit/thunk1.C index 3bbd05069df..e59586a14bd 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 -- 2.30.2