Similarly to x86, PowerPC and SPARC, this enables the use of custom run-time
descriptors in Ada, thus eliminating the need for trampolines and executable
stack in presence of pointers to nested functions.
This still uses bit 1 for the run-time identification scheme because bumping
the function alignment to 64 bits seems undesirable in Thumb mode.
Tested on ARM/Linux, OK for the mainline?
2016-11-13 Eric Botcazou <ebotca...@adacore.com>
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.
--
Eric Botcazou
Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c (revision 242334)
+++ config/arm/arm.c (working copy)
@@ -738,6 +738,11 @@ static const struct attribute_spec arm_a
#undef TARGET_EXPAND_DIVMOD_LIBFUNC
#define TARGET_EXPAND_DIVMOD_LIBFUNC arm_expand_divmod_libfunc
+/* 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. */
@@ -6810,6 +6815,29 @@ arm_function_ok_for_sibcall (tree decl,
&& 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;
}
@@ -29101,7 +29129,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