diff options
author | Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> | 2016-05-13 09:32:29 +0000 |
---|---|---|
committer | Ramana Radhakrishnan <ramana@gcc.gnu.org> | 2016-05-13 09:32:29 +0000 |
commit | c959db3d3b344fa2e21fdd79768e2349d7c2db25 (patch) | |
tree | d5453fb8781fd3155de6a7028b49ec1db7df0b3e | |
parent | 43203dea1afa87140a0f045f2c2182943247065f (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 96 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/inherit/thunk1.C | 3 |
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> |