diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-02-21 08:42:54 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-02-21 08:42:54 +0000 |
commit | 28ac8d1b4697b2aae79c710516a8b8309ca78a03 (patch) | |
tree | 3a676c1f933a6c31fed21a5aa876e38b5f63efe4 /gcc/config/arm | |
parent | d4a7abdaed16eb3a5add0e6be62d010252014ed8 (diff) | |
download | gcc-28ac8d1b4697b2aae79c710516a8b8309ca78a03.tar.gz |
PR ada/67205
* config/arm/arm.c (TARGET_CUSTOM_FUNCTION_DESCRIPTORS): Define.
(arm_function_ok_for_sibcall): Return false for an indirect call by
descriptor if all the argument registers are used.
(arm_relayout_function): Use FUNCTION_ALIGNMENT macro to adjust the
alignment of the function.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@245621 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm')
-rw-r--r-- | gcc/config/arm/arm.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 3e482b55e74..b397a73052d 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -760,6 +760,11 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_C_EXCESS_PRECISION #define TARGET_C_EXCESS_PRECISION arm_excess_precision +/* Although the architecture reserves bits 0 and 1, only the former is + used for ARM/Thumb ISA selection in v7 and earlier versions. */ +#undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS +#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2 + struct gcc_target targetm = TARGET_INITIALIZER; /* Obstack for minipool constant handling. */ @@ -7173,6 +7178,29 @@ arm_function_ok_for_sibcall (tree decl, tree exp) && DECL_WEAK (decl)) return false; + /* We cannot do a tailcall for an indirect call by descriptor if all the + argument registers are used because the only register left to load the + address is IP and it will already contain the static chain. */ + if (!decl && CALL_EXPR_BY_DESCRIPTOR (exp) && !flag_trampolines) + { + tree fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp))); + CUMULATIVE_ARGS cum; + cumulative_args_t cum_v; + + arm_init_cumulative_args (&cum, fntype, NULL_RTX, NULL_TREE); + cum_v = pack_cumulative_args (&cum); + + for (tree t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t)) + { + tree type = TREE_VALUE (t); + if (!VOID_TYPE_P (type)) + arm_function_arg_advance (cum_v, TYPE_MODE (type), type, true); + } + + if (!arm_function_arg (cum_v, SImode, integer_type_node, true)) + return false; + } + /* Everything else is ok. */ return true; } @@ -30310,7 +30338,9 @@ arm_relayout_function (tree fndecl) callee_tree = target_option_default_node; struct cl_target_option *opts = TREE_TARGET_OPTION (callee_tree); - SET_DECL_ALIGN (fndecl, FUNCTION_BOUNDARY_P (opts->x_target_flags)); + SET_DECL_ALIGN + (fndecl, + FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY_P (opts->x_target_flags))); } /* Inner function to process the attribute((target(...))), take an argument and |