Created attachment 36179 [details] trampoline.adb The attached example requires generation of trampolines. This may be due to bug 57999, but I think a front-end fix would be more reliable. As an additional surprise, pragma Restrictions (No_Implicit_Dynamic_Code) does not cause compilation to fail. The error is only detected at binding time, and -Wtrampolines is needed to find the culprit.
Confirmed.
> The attached example requires generation of trampolines. This may be due to > bug 57999, but I think a front-end fix would be more reliable. Please clarify "front-end fix". The language requires pointers to nested functions in this case and you cannot reasonably change that, nested functions being first-class citizens in Ada. More generally, trampolines can indeed be eliminated, but you need changes in the entire compiler to do it. > As an additional surprise, pragma Restrictions (No_Implicit_Dynamic_Code) > does not cause compilation to fail. The error is only detected at binding > time, and -Wtrampolines is needed to find the culprit. Yes, the violation is detected but the error is not issued, probably because it's the instantiation of a run-time unit.
(In reply to Eric Botcazou from comment #2) > > The attached example requires generation of trampolines. This may be due to > > bug 57999, but I think a front-end fix would be more reliable. > > Please clarify "front-end fix". The language requires pointers to nested > functions in this case and you cannot reasonably change that, nested > functions being first-class citizens in Ada. > > More generally, trampolines can indeed be eliminated, but you need changes > in the entire compiler to do it. Couldn't you put the static chain for the dispatching subprograms into the vtable of the tagged type? In some examples (including this one, and those I recently submitted as a GNAT tools patch), it seems rather straightforward to float the generic instantiation out of the nested subprogram. Some care is necessary to make sure the transformation is in fact valid, but I had hoped this would be a more localized change in the compiler.
> Couldn't you put the static chain for the dispatching subprograms into the > vtable of the tagged type? Presumably not, the vtable layout is constrained by the C++ compatibility and this extends to local tagged types since Ada 2005. In any case, see below. > In some examples (including this one, and those I recently submitted as a > GNAT tools patch), it seems rather straightforward to float the generic > instantiation out of the nested subprogram. Some care is necessary to make > sure the transformation is in fact valid, but I had hoped this would be a > more localized change in the compiler. The truth is, the versions of GNAT released by AdaCore use a general scheme to eliminate (almost) all trampolines, at least on native platforms, so there is no incentive for small tricks like this. We could submit the scheme if there is some interest from the community.
(In reply to Eric Botcazou from comment #4) > The truth is, the versions of GNAT released by AdaCore use a general scheme > to eliminate (almost) all trampolines, at least on native platforms, so > there is no incentive for small tricks like this. We could submit the > scheme if there is some interest from the community. Fedora has policies against executable stack, and fewer off them are always welcome. Are your changes restricted to gcc/ada, or would you need reviewers frm other parts of GCC?
> Fedora has policies against executable stack, and fewer off them are always > welcome. Are your changes restricted to gcc/ada, or would you need > reviewers frm other parts of GCC? The latter, although the changes are localized (nested functions decomposition pass, RTL expander and bits in a few back-ends). Mostly straightforward, but only helps Ada and we already have a slew of such patches pending review, so we have started to prioritize. I'll give it a try though.
As far as I can see 5.1.0 (and 5.2.0) are happy that the trampolines should be *generated* in the presence of pragma Restrictions (No_Implicit_Dynamic_Code); trampoline.adb compiles and builds without problem. The problem arises when the trampolines are invoked; with Ada.Containers.Vectors; procedure Trampoline is package Vectors is new Ada.Containers.Vectors (Positive, Integer); type Capacity_P is access function (Container : Vectors.Vector) return Ada.Containers.Count_Type; P : Capacity_P; begin P := Vectors.Capacity'Access; end Trampoline; results in the expected 'violation of restriction “No_Implicit_Dynamic_Code”’ error at compile time.
Let's reclassify this PR as an enhancement to eliminate trampolines.
I'll submit the AdaCore patch for GCC 7.
Author: ebotcazou Date: Sun Oct 16 20:13:32 2016 New Revision: 241222 URL: https://gcc.gnu.org/viewcvs?rev=241222&root=gcc&view=rev Log: PR ada/37139 PR ada/67205 * common.opt (-ftrampolines): New option. * doc/invoke.texi (Code Gen Options): Document it. * doc/tm.texi.in (Trampolines): Add TARGET_CUSTOM_FUNCTION_DESCRIPTORS. * doc/tm.texi: Regenerate. * builtins.def: Add init_descriptor and adjust_descriptor. * builtins.c (expand_builtin_init_trampoline): Do not issue a warning on platforms with descriptors. (expand_builtin_init_descriptor): New function. (expand_builtin_adjust_descriptor): Likewise. (expand_builtin) <BUILT_IN_INIT_DESCRIPTOR>: New case. <BUILT_IN_ADJUST_DESCRIPTOR>: Likewise. * calls.c (prepare_call_address): Remove SIBCALLP parameter and add FLAGS parameter. Deal with indirect calls by descriptor and adjust. Set STATIC_CHAIN_REG_P on the static chain register, if any. (call_expr_flags): Set ECF_BY_DESCRIPTOR for calls by descriptor. (expand_call): Likewise. Move around call to prepare_call_address and pass all flags to it. * cfgexpand.c (expand_call_stmt): Reinstate CALL_EXPR_BY_DESCRIPTOR. * gimple.h (enum gf_mask): New GF_CALL_BY_DESCRIPTOR value. (gimple_call_set_by_descriptor): New setter. (gimple_call_by_descriptor_p): New getter. * gimple.c (gimple_build_call_from_tree): SetCALL_EXPR_BY_DESCRIPTOR. (gimple_call_flags): Deal with GF_CALL_BY_DESCRIPTOR. * langhooks.h (struct lang_hooks): Add custom_function_descriptors. * langhooks-def.h (LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS): Define. (LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS. * rtl.h (STATIC_CHAIN_REG_P): New macro. * rtlanal.c (find_first_parameter_load): Skip static chain registers. * target.def (custom_function_descriptors): New POD hook. * tree.h (FUNC_ADDR_BY_DESCRIPTOR): New flag on ADDR_EXPR. (CALL_EXPR_BY_DESCRIPTOR): New flag on CALL_EXPR. * tree-core.h (ECF_BY_DESCRIPTOR): New mask. Document FUNC_ADDR_BY_DESCRIPTOR and CALL_EXPR_BY_DESCRIPTOR. * tree.c (make_node_stat) <tcc_declaration>: Use FUNCTION_ALIGNMENT. (build_common_builtin_nodes): Initialize init_descriptor and adjust_descriptor. * tree-nested.c: Include target.h. (struct nesting_info): Add 'any_descr_created' field. (get_descriptor_type): New function. (lookup_element_for_decl): New function extracted from... (create_field_for_decl): Likewise. (lookup_tramp_for_decl): ...here. Adjust. (lookup_descr_for_decl): New function. (convert_tramp_reference_op): Deal with descriptors. (build_init_call_stmt): New function extracted from... (finalize_nesting_tree_1): ...here. Adjust and deal withdescriptors. * defaults.h (FUNCTION_ALIGNMENT): Define. (TRAMPOLINE_ALIGNMENT): Set to above instead of FUNCTION_BOUNDARY. * config/i386/i386.h (TARGET_CUSTOM_FUNCTION_DESCRIPTORS): Define. * config/ia64/ia64.h (TARGET_CUSTOM_FUNCTION_DESCRIPTORS): Likewise. * config/rs6000/rs6000.h (TARGET_CUSTOM_FUNCTION_DESCRIPTORS):Likewise. * config/sparc/sparc.h (TARGET_CUSTOM_FUNCTION_DESCRIPTORS): Likewise. ada/ * gcc-interface/misc.c (LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS):Define. * gcc-interface/trans.c (Attribute_to_gnu) <Attr_Access>: Deal with a zero TARGET_CUSTOM_FUNCTION_DESCRIPTORS specially for Code_Address. Otherwise, if TARGET_CUSTOM_FUNCTION_DESCRIPTORS is positive, set FUNC_ADDR_BY_DESCRIPTOR for 'Access/'Unrestricted_Access of nested subprograms if the type can use an internal representation. (call_to_gnu): Likewise, but set CALL_EXPR_BY_DESCRIPTOR on indirect calls if the type can use an internal representation. Added: trunk/gcc/testsuite/gnat.dg/trampoline3.adb trunk/gcc/testsuite/gnat.dg/trampoline4.adb Modified: trunk/gcc/ChangeLog trunk/gcc/ada/ChangeLog trunk/gcc/ada/gcc-interface/misc.c trunk/gcc/ada/gcc-interface/trans.c trunk/gcc/builtins.c trunk/gcc/builtins.def trunk/gcc/calls.c trunk/gcc/cfgexpand.c trunk/gcc/common.opt trunk/gcc/config/i386/i386.h trunk/gcc/config/ia64/ia64.h trunk/gcc/config/rs6000/rs6000.h trunk/gcc/config/sparc/sparc.h trunk/gcc/defaults.h trunk/gcc/doc/invoke.texi trunk/gcc/doc/tm.texi trunk/gcc/doc/tm.texi.in trunk/gcc/gimple.c trunk/gcc/gimple.h trunk/gcc/langhooks-def.h trunk/gcc/langhooks.h trunk/gcc/rtl.h trunk/gcc/rtlanal.c trunk/gcc/target.def trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-core.h trunk/gcc/tree-nested.c trunk/gcc/tree.c trunk/gcc/tree.h
Trampolines are gone on x86, PowerPC and SPARC. AArch64 and ARM are the next ones on the list.
Author: ebotcazou Date: Fri Nov 25 09:59:45 2016 New Revision: 242868 URL: https://gcc.gnu.org/viewcvs?rev=242868&root=gcc&view=rev Log: PR ada/67205 * config/mips/mips.c (TARGET_CUSTOM_FUNCTION_DESCRIPTORS): Define. Modified: trunk/gcc/ChangeLog trunk/gcc/config/mips/mips.c
Author: ebotcazou Date: Tue Jan 17 18:02:55 2017 New Revision: 244543 URL: https://gcc.gnu.org/viewcvs?rev=244543&root=gcc&view=rev Log: PR ada/67205 * config/aarch64/aarch64.c (TARGET_CUSTOM_FUNCTION_DESCRIPTORS): Define Modified: trunk/gcc/ChangeLog trunk/gcc/config/aarch64/aarch64.c
The ARM patch is waiting for approval at: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg01254.html
Author: ebotcazou Date: Tue Feb 21 08:42:54 2017 New Revision: 245621 URL: https://gcc.gnu.org/viewcvs?rev=245621&root=gcc&view=rev Log: 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. Modified: trunk/gcc/ChangeLog trunk/gcc/config/arm/arm.c
Trampolines are gone on ARM, Aarch64 and MIPS too.
And s390 as per PR ada/79421.