Does this patch have a change? This version seems risk-free and
is a clear improvement from simply doing nothing for
'-fno-trampolines'. Also it is useful in situations where
one cannot have an executable stack.
I am currently thinking about working
around this problem by calling nested functions with the
following macro (x86_64 only):
#define NESTED_CALL(p, args) ({ \
_auto_type __p = (p); \
struct { unsigned short mov1; void* addr; unsigned short mov2; void* chain;
unsigned int jmp; } \
__attribute__((packed))* __t = (void*)p; \
assert((0xbb49 == __t->mov1) && (0xba49 == __t->mov2) && (0x90e3ff49 ==
__t->jmp)); \
__builtin_call_with_static_chain(((__typeof__(__p))(__t->addr))args,
__t->chain); \
})
(the 'assert' could be replaced with an 'if' to call
regular functions when pointers to nested functions
and regular functions are mixed)
But I would rather have a proper solution...
Best,
Martin
Am Freitag, den 21.12.2018, 07:46 +0100 schrieb Martin Uecker:
> Am Montag, den 17.12.2018, 10:28 -0700 schrieb Jeff Law:
>
> > > But the alignment increase itself on 'i386' and 'aarch64'
> > > might be unacceptable. In this case, the only safe change
> > > is to make the higher alignment also depend on
> > > "-fno-trampolines". Would this be acceptable?
> >
> > Unclear at this point.
>
> Hi Jeff,
>
> in any case, here is another revision of this patch for
> consideration which implements just this.
>
> The lang hook is not activated for C anymore which means
> that this patch is a no-op when -fno-trampolines is not
> given. So the test about achieving the minimum alignment on
> i386 does not fail anymore.
>
> With -fno-trampolines the minimum alignment is increased
> as needed on platforms which support descriptors.
> For C and Ada (where it is the default) function
> descriptors are created instead of trampolines.
>
> If -fno-trampolines is given on platforms which do not
> support descriptors a warning is given (before the flag
> was silently ignored.)
>
> I also made the existing warnings about the ABI change
> more visible (similar to -freg-struct-return or similar
> flags).
>
> I consider the current behavior broken, where the flag
> is a silent no-op for most languages and on some targets
> while the documentation implies otherwise.
>
> Bootstrapped and regression tested on x86.
>
> I also tested -fno-trampolines on a project of mine which
> uses nested functions and has a test suite and there it
> works perfectly and removes the need for the executable stack.
>
> Finally, this patch is a tiny and self-contained change which
> could easily be reverted if there should be any unanticipated
> failures.
>
> Best,
> Martin
>
>
>
> diff --git a/gcc/ChangeLog b/gcc/ChangeLog
> index 4be16c15f86..8825d87b44f 100644
> --- a/gcc/ChangeLog
> +++ b/gcc/ChangeLog
> @@ -1,3 +1,16 @@
> +2018-12-20 Martin Uecker <[email protected]>
> +
> + * common.opt (flag_trampolines): Change default.
> + * calls.c (prepare_call_address): Remove check for
> + flag_trampolines. Decision is now made in FEs.
> + * defaults.h (FUNCTION_ALIGNMENT): Add test for flag_trampolines.
> + * tree-nested.c (convert_tramp_reference_op): Likewise.
> + * toplev.c (process_options): Add warning for -fno-trampolines on
> + unsupported targets.
> + * doc/invoke.texi (-fno-trampolines): Document support for C.
> + * doc/sourcebuild.texi (target attributes): Document new
> + "notrampolines" effective target keyword.
> +
> 2018-12-20 Vladimir Makarov <[email protected]>
>
> PR target/88457
> diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
> index ba974cdcb03..c2f3d0db281 100644
> --- a/gcc/ada/ChangeLog
> +++ b/gcc/ada/ChangeLog
> @@ -1,3 +1,8 @@
> +2018-12-20 Martin Uecker <[email protected]>
> +
> + * gcc-interface/trans.c (Attribute_to_gnu): Add check for
> + flag_trampolines.
> +
> 2018-12-14 Eric Botcazou <[email protected]>
>
> * gcc-interface/decl.c (rm_size): Take into account the padding in
> diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
> index 620dbd3d36d..ae4139e9b84 100644
> --- a/gcc/ada/gcc-interface/trans.c
> +++ b/gcc/ada/gcc-interface/trans.c
> @@ -2239,7 +2239,8 @@ Attribute_to_gnu (Node_Id gnat_node, tree
> *gnu_result_type_p, int attribute)
> if ((attribute == Attr_Access
> || attribute == Attr_Unrestricted_Access)
> && targetm.calls.custom_function_descriptors > 0
> - && Can_Use_Internal_Rep (Etype (gnat_node)))
> + && Can_Use_Internal_Rep (Etype (gnat_node))
> + && flag_trampolines != 1)
> FUNC_ADDR_BY_DESCRIPTOR (gnu_expr) = 1;
>
> /* Otherwise, we need to check that we are not violating the
> @@ -5050,7 +5051,8 @@ Call_to_gnu (Node_Id gnat_node, tree
> *gnu_result_type_p, tree gnu_target,
> /* If the access type doesn't require foreign-compatible
> representation,
> be prepared for descriptors. */
> if (targetm.calls.custom_function_descriptors > 0
> - && Can_Use_Internal_Rep (Etype (Prefix (Name (gnat_node)))))
> + && Can_Use_Internal_Rep (Etype (Prefix (Name (gnat_node))))
> + && flag_trampolines != 1)
> by_descriptor = true;
> }
> else if (Nkind (Name (gnat_node)) == N_Attribute_Reference)
> diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
> index 6e12dda2331..71443846799 100644
> --- a/gcc/c/ChangeLog
> +++ b/gcc/c/ChangeLog
> @@ -1,3 +1,9 @@
> +2018-12-20 Martin Uecker <[email protected]>
> +
> + * c-typeck.c (function_to_pointer_conversion): If using descriptors
> + instead of trampolines, amend function address with
> + FUNC_ADDR_BY_DESCRIPTOR and calls with ALL_EXPR_BY_DESCRIPTOR.
> +
> 2018-12-19 Segher Boessenkool <[email protected]>
>
> * c-parser.c (c_parser_asm_statement) <RID_CONST, RID_RESTRICT>: Give
> diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
> index 1ae5ede81e6..6363dfda3b8 100644
> --- a/gcc/c/c-typeck.c
> +++ b/gcc/c/c-typeck.c
> @@ -1913,7 +1913,14 @@ function_to_pointer_conversion (location_t loc, tree
> exp)
> if (TREE_NO_WARNING (orig_exp))
> TREE_NO_WARNING (exp) = 1;
>
> - return build_unary_op (loc, ADDR_EXPR, exp, false);
> + tree r = build_unary_op (loc, ADDR_EXPR, exp, false);
> +
> + if (TREE_CODE(r) == ADDR_EXPR
> + && targetm.calls.custom_function_descriptors > 0
> + && flag_trampolines == 0)
> + FUNC_ADDR_BY_DESCRIPTOR (r) = 1;
> +
> + return r;
> }
>
> /* Mark EXP as read, not just set, for set but not used -Wunused
> @@ -3135,6 +3142,12 @@ build_function_call_vec (location_t loc,
> vec<location_t> arg_loc,
> else
> result = build_call_array_loc (loc, TREE_TYPE (fntype),
> function, nargs, argarray);
> +
> + if (TREE_CODE (result) == CALL_EXPR
> + && targetm.calls.custom_function_descriptors > 0
> + && flag_trampolines == 0)
> + CALL_EXPR_BY_DESCRIPTOR (result) = 1;
> +
> /* If -Wnonnull warning has been diagnosed, avoid diagnosing it again
> later. */
> if (warned_p && TREE_CODE (result) == CALL_EXPR)
> diff --git a/gcc/calls.c b/gcc/calls.c
> index e3b4ef80e51..1b977c231ea 100644
> --- a/gcc/calls.c
> +++ b/gcc/calls.c
> @@ -230,7 +230,7 @@ prepare_call_address (tree fndecl_or_type, rtx funexp,
> rtx static_chain_value,
> {
> /* If it's an indirect call by descriptor, generate code to perform
> runtime identification of the pointer and load the descriptor. */
> - if ((flags & ECF_BY_DESCRIPTOR) && !flag_trampolines)
> + if (flags & ECF_BY_DESCRIPTOR)
> {
> const int bit_val = targetm.calls.custom_function_descriptors;
> rtx call_lab = gen_label_rtx ();
> diff --git a/gcc/common.opt b/gcc/common.opt
> index 45d7f6189e5..d85d77b5b91 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -2546,7 +2546,7 @@ Common Report Var(flag_tracer) Optimization
> Perform superblock formation via tail duplication.
>
> ftrampolines
> -Common Report Var(flag_trampolines) Init(0)
> +Common Report Var(flag_trampolines) Init(-1)
> For targets that normally need trampolines for nested functions, always
> generate them instead of using descriptors.
>
> diff --git a/gcc/defaults.h b/gcc/defaults.h
> index 9035b333be8..66de347edef 100644
> --- a/gcc/defaults.h
> +++ b/gcc/defaults.h
> @@ -1050,7 +1050,8 @@ see the files COPYING3 and COPYING.RUNTIME
> respectively. If not, see
> /* Force minimum alignment to be able to use the least significant bits
> for distinguishing descriptor addresses from code addresses. */
> #define FUNCTION_ALIGNMENT(ALIGN) \
> - (lang_hooks.custom_function_descriptors \
> + (( lang_hooks.custom_function_descriptors
> \
> + || flag_trampolines == 0)
> \
> && targetm.calls.custom_function_descriptors > 0 \
> ? MAX ((ALIGN), \
> 2 * targetm.calls.custom_function_descriptors * BITS_PER_UNIT)\
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index ac2ee59d92c..5662abd1b97 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -14030,9 +14030,10 @@ made executable in order for the program to work
> properly.
> basis to let the compiler avoid generating them, if it computes that this
> is safe, and replace them with descriptors. Descriptors are made up of data
> only, but the generated code must be prepared to deal with them. As of this
> -writing, @option{-fno-trampolines} is enabled by default only for Ada.
> +writing, @option{-fno-trampolines} is supported only for C and Ada and
> +enabled by default only for Ada.
>
> -Moreover, code compiled with @option{-ftrampolines} and code compiled with
> +@strong{Warning:} Code compiled with @option{-ftrampolines} and code
> compiled with
> @option{-fno-trampolines} are not binary compatible if nested functions are
> present. This option must therefore be used on a program-wide basis and be
> manipulated with extreme care.
> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
> index 29c693b9644..d645d1def92 100644
> --- a/gcc/doc/sourcebuild.texi
> +++ b/gcc/doc/sourcebuild.texi
> @@ -2162,6 +2162,9 @@ Target supports Newlib.
> GCC was configured with @code{--enable-newlib-nano-formatted-io}, which
> reduces
> the code size of Newlib formatted I/O functions.
>
> +@item notrampolines
> +Target supports option @option{-fno-trampolines}.
> +
> @item pow10
> Target provides @code{pow10} function.
>
> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
> index 33a4776b921..24f443bb26f 100644
> --- a/gcc/testsuite/ChangeLog
> +++ b/gcc/testsuite/ChangeLog
> @@ -1,3 +1,9 @@
> +2018-12-20 Martin Uecker <[email protected]>
> +
> + * gcc.dg/trampoline-2.c: New test.
> + * lib/target-supports.exp
> + (check_effective_target_notrampolines): New.
> +
> 2018-12-20 Vladimir Makarov <[email protected]>
>
> PR target/88457
> diff --git a/gcc/testsuite/gcc.dg/trampoline-2.c
> b/gcc/testsuite/gcc.dg/trampoline-2.c
> new file mode 100644
> index 00000000000..06c1cf4f647
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/trampoline-2.c
> @@ -0,0 +1,23 @@
> +/* test that nested function work without trampolines for -fno-trampolines */
> +/* Origin: Martin Uecker <[email protected]> */
> +/* { dg-require-effective-target notrampolines } */
> +/* { dg-options "-std=gnu11 -O2 -Wtrampolines -fno-trampolines" } */
> +
> +static int p(void) { return +1; }
> +static int m(void) { return -1; }
> +static int z(void) { return 0; }
> +
> +typedef int (*funptr_t)(void);
> +
> +static int A(int k, funptr_t a1, funptr_t a2, funptr_t a3, funptr_t a4,
> funptr_t a5)
> +{
> + int B(void) { return A(--k, B, a1, a2, a3, a4); }
> +
> + return (k <= 0) ? (a4() + a5()) : (B());
> +}
> +
> +int main(void)
> +{
> + return (0 == A(5, p, m, m, p, z)) ? 0 : 1;
> +}
> +
> diff --git a/gcc/testsuite/lib/target-supports.exp
> b/gcc/testsuite/lib/target-supports.exp
> index 7dec43233e0..43f9bb3891f 100644
> --- a/gcc/testsuite/lib/target-supports.exp
> +++ b/gcc/testsuite/lib/target-supports.exp
> @@ -924,6 +924,14 @@ proc check_effective_target_scheduling {} {
> } "-fschedule-insns"]
> }
>
> +# Return 1 if it is possible to use function descriptors instead of
> trampolines, 0 otherwise.
> +
> +proc check_effective_target_notrampolines {} {
> + return [check_no_compiler_messages notrampolines assembly {
> + void foo (void) { }
> + } "-fno-trampolines"]
> +}
> +
> # Return 1 if trapping arithmetic is available, 0 otherwise.
>
> proc check_effective_target_trapping {} {
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index ab20cd98969..765ce347172 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -1698,6 +1698,12 @@ process_options (void)
> flag_prefetch_loop_arrays = 0;
> }
>
> + if (flag_trampolines == 0 && targetm.calls.custom_function_descriptors ==
> -1)
> + {
> + warning_at (UNKNOWN_LOCATION, 0,
> + "-fno-trampolines not supported for this target");
> + }
> +
> /* This combination of options isn't handled for i386 targets and doesn't
> make much sense anyway, so don't allow it. */
> if (flag_prefetch_loop_arrays > 0 && optimize_size)
> diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
> index 0ad469ada49..eb9bccb7a9d 100644
> --- a/gcc/tree-nested.c
> +++ b/gcc/tree-nested.c
> @@ -2544,7 +2544,7 @@ convert_tramp_reference_op (tree *tp, int
> *walk_subtrees, void *data)
> continue;
>
> /* Decide whether to generate a descriptor or a trampoline. */
> - descr = FUNC_ADDR_BY_DESCRIPTOR (t) && !flag_trampolines;
> + descr = FUNC_ADDR_BY_DESCRIPTOR (t);
>
> if (descr)
> x = lookup_descr_for_decl (i, decl, INSERT);