On Fri, May 18, 2018 at 9:43 AM Eric Botcazou <ebotca...@adacore.com> wrote:
> Hi, > the compiler has had built-in support for nested functions for a long time, > which makes it possible to support them in GNU C (as an extension) and in Ada; > Fortran uses them too but marginally. The support was entirely rewritten for > GCC 4 and a few rough edges have remained since then, which are quite visible > in languages where they are first-class citizens like Ada. > The first rough edge is the stack usage at -O0: it is twice as large as needed > for variables subject to up-level references. So you declare an array of 2KB > bytes on the stack, factor out some code that reads it into a child function > and then you suddenly need 4KB of stack instead of 2KB. Even at -O0 this can > be annoying for very embedded platforms. > The attached patch fixes it and also contains a tweak to use_pointer_in_frame > for the sake of consistency but with no functional changes in practice. > Tested on x86-64/Linux, OK for the mainline? + /* If the next declaration is a PARM_DECL pointing to the DECL, + we need to adjust its VALUE_EXPR directly, since chains of + VALUE_EXPRs run afoul of garbage collection. This occurs + in Ada for Out parameters that aren't copied in. */ + if (next + && TREE_CODE (next) == PARM_DECL + && DECL_HAS_VALUE_EXPR_P (next) + && DECL_VALUE_EXPR (next) == decl) + SET_DECL_VALUE_EXPR (next, x); maybe you can explain the GC issue a bit. I also think that you should adjust the next DECL_VALUE_EXRP before setting DECL_VALUE_EXPR on decl so we can do sth like the following to verify we do not face this very situation (it's of course incomplete verification, we could search for a suitable place in some of the IL verifiers but I'm not sure there is one early enough and catching all decls). diff --git a/gcc/tree.c b/gcc/tree.c index 68165f4deed..ded12782aea 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6340,7 +6340,14 @@ decl_value_expr_lookup (tree from) h = value_expr_for_decl->find_with_hash (&in, DECL_UID (from)); if (h) - return h->to; + { + /* Chains of value-exprs run afoul of garbage collection, make + sure we never end up with those. */ + gcc_checking_assert ((TREE_CODE (h->to) != PARM_DECL + && TREE_CODE (h->to) != VAR_DECL) + || !DECL_HAS_VALUE_EXPR_P (h->to)); + return h->to; + } return NULL_TREE; } @@ -6351,6 +6358,12 @@ decl_value_expr_insert (tree from, tree to) { struct tree_decl_map *h; + /* Chains of value-exprs run afoul of garbage collection, make + sure we never end up with those. */ + gcc_checking_assert ((TREE_CODE (to) != PARM_DECL + && TREE_CODE (to) != VAR_DECL) + || !DECL_HAS_VALUE_EXPR_P (to)); + h = ggc_alloc<tree_decl_map> (); h->base.from = from; h->to = to; > 2018-05-18 Eric Botcazou <ebotca...@adacore.com> > * tree-nested.c (use_pointer_in_frame): Tweak. > (lookup_field_for_decl): Add assertion and declare the transformation. > 2018-05-18 Eric Botcazou <ebotca...@adacore.com> > * gnat.dg/stack_usage5.adb: New test. > -- > Eric Botcazou