summaryrefslogtreecommitdiff
path: root/gcc/config/arm
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2017-02-21 08:42:54 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2017-02-21 08:42:54 +0000
commit28ac8d1b4697b2aae79c710516a8b8309ca78a03 (patch)
tree3a676c1f933a6c31fed21a5aa876e38b5f63efe4 /gcc/config/arm
parentd4a7abdaed16eb3a5add0e6be62d010252014ed8 (diff)
downloadgcc-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.c32
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