I've committed a patch to the Go frontend that fixes this problem.
Thanks for the analysis.

Ian

On Thu, May 20, 2021 at 1:59 AM guojiufu <guoji...@linux.ibm.com> wrote:
>
> On 2021-05-18 14:58, Richard Biener wrote:
> > On Mon, 17 May 2021, Ian Lance Taylor wrote:
> >
> >> On Mon, May 17, 2021 at 1:17 AM Richard Biener via Gcc-patches
> >> <gcc-patches@gcc.gnu.org> wrote:
> >> >
> >> > On Fri, May 14, 2021 at 11:19 AM guojiufu via Gcc-patches
> >> > <gcc-patches@gcc.gnu.org> wrote:
> >> > >
> >> > > On 2021-05-14 15:39, guojiufu via Gcc-patches wrote:
> >> > > > On 2021-05-14 15:15, Richard Biener wrote:
> >> > > >> On May 14, 2021 4:52:56 AM GMT+02:00, Jiufu Guo
> >> > > >> <guoji...@linux.ibm.com> wrote:
> >> > > >>> As discussed in the PR, Richard mentioned the method to
> >> > > >>> figure out which VAR was not set TREE_ADDRESSABLE, and
> >> > > >>> then cause this failure.  It is address_expression which
> >> > > >>> build addr_expr (build_fold_addr_expr_loc), but not set
> >> > > >>> TREE_ADDRESSABLE.
> >> > > >>>
> >> > > >>> I drafted this patch with reference the comments from Richard
> >> > > >>> in this PR, while I'm not quite sure if more thing need to do.
> >> > > >>> So, please have review, thanks!
> >> > > >>>
> >> > > >>> Bootstrap and regtest pass on ppc64le. Is this ok for trunk?
> >> > > >>
> >> > > >> I suggest to use mark_addresssable unless we're sure expr is always 
> >> > > >> an
> >> > > >> entity where TREE_ADDRESSABLE has the desired meaning.
> >> > >
> >> > > Thanks, Richard!
> >> > > You point out the root concern, I'm not sure ;)
> >> > >
> >> > > With looking at code "mark_addresssable" and code around
> >> > > tree-ssa.c:1013,
> >> > > VAR_P, PARM_DECL, and RESULT_DECL are checked before accessing
> >> > > TREE_ADDRESSABLE.
> >> > > So, just wondering if these entities need to be marked as
> >> > > TREE_ADDRESSABLE?
> >> > >
> >> > > diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
> >> > > index 5d9dbb5d068..85d324a92cc 100644
> >> > > --- a/gcc/go/go-gcc.cc
> >> > > +++ b/gcc/go/go-gcc.cc
> >> > > @@ -1680,6 +1680,11 @@ Gcc_backend::address_expression(Bexpression*
> >> > > bexpr, Location location)
> >> > >     if (expr == error_mark_node)
> >> > >       return this->error_expression();
> >> > >
> >> > > +  if ((VAR_P(expr)
> >> > > +       || TREE_CODE(expr) == PARM_DECL
> >> > > +       || TREE_CODE(expr) == RESULT_DECL)
> >> > > +    TREE_ADDRESSABLE (expr) = 1;
> >> > > +
> >> >
> >> > The root concern is that mark_addressable does
> >> >
> >> >   while (handled_component_p (x))
> >> >     x = TREE_OPERAND (x, 0);
> >> >
> >> > and I do not know the constraints on 'expr' as passed to
> >> > Gcc_backend::address_expression.
> >> >
> >> > I think we need input from Ian here.  Most FEs have their own 
> >> > *_mark_addressable
> >> > function where they also emit diagnostics (guess this is handled in
> >> > the actual Go frontend).
> >> > Since Gcc_backend does lowering to GENERIC using a middle-end is 
> >> > probably OK.
> >>
> >> I doubt I understand all the issues here.
> >>
> >> In general the Go frontend only takes the addresses of VAR_DECLs or
> >> PARM_DECLs.  It doesn't bother to set TREE_ADDRESSABLE for global
> >> variables for which TREE_STATIC or DECL_EXTERNAL is true.  For local
> >> variables it sets TREE_ADDRESSABLE based on the is_address_taken
> >> parameter to Gcc_backend::local_variable, and similarly for PARM_DECLs
> >> and Gcc_backend::parameter_variable.
> >>
> >> The name in the bug report is for a string initializer, which should
> >> be TREE_STATIC == 1 and TREE_PUBLIC == 0.  Perhaps the fix is simply
> >> to set TREE_ADDRESSABLE in Gcc_backend::immutable_struct and
> >> Gcc_backend::implicit_variable.  I can't see how it would hurt to set
> >> TREE_ADDRESSABLE unnecessarily for a TREE_STATIC variable.
> >>
> >> But, again, I doubt I understand all the issues here.
> >
> > GENERIC requires TREE_ADDRESSABLE to be set on all address-taken
> > VAR_DECLs, PARM_DECLs and RESULT_DECLs - the gimplifier is the
> > first to require this for correctness.  Setting TREE_ADDRESSABLE
> > when the address is not taken is harmless and at most results in
> > missed optimizations (on most entities we are able to clear the
> > flag later).
> >
> > We're currently quite forgiving with this though (still the
> > gimplifier can generate wrong-code).  The trigger of the current
> > failure removed one "forgiveness", I do plan to remove a few more.
> >
> > guojiufu's patch works for me but as said I'm not sure if there's
> > a better place to set TREE_ADDRESSABLE for entities that have
> > their address taken - definitely catching the places where
> > you build an ADDR_EXPR are the most obvious ones.
> >
> > Richard.
>
> I tested below patch As Ian said, bootstrap pass.
>
> ----------------------------------------
> diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
> index 5d9dbb5d068..529f657598a 100644
> --- a/gcc/go/go-gcc.cc
> +++ b/gcc/go/go-gcc.cc
> @@ -2943,6 +2943,7 @@ Gcc_backend::implicit_variable(const std::string&
> name,
>     TREE_STATIC(decl) = 1;
>     TREE_USED(decl) = 1;
>     DECL_ARTIFICIAL(decl) = 1;
> +  TREE_ADDRESSABLE(decl) = 1;
>     if (is_common)
>       {
>         DECL_COMMON(decl) = 1;
> @@ -3053,6 +3054,7 @@ Gcc_backend::immutable_struct(const std::string&
> name,
>     TREE_READONLY(decl) = 1;
>     TREE_CONSTANT(decl) = 1;
>     DECL_ARTIFICIAL(decl) = 1;
> +  TREE_ADDRESSABLE(decl) = 1;
>     if (!is_hidden)
>       TREE_PUBLIC(decl) = 1;
>     if (! asm_name.empty())
> ----------------------------------------
> While, I hacked a patch for OPERATOR_AND. I'm thinking it may be
> acceptable.
>
> BR.
> Jiufu Guo.
> ----------------------------------------
> Bootstrap failure go [PR100537]
>
> In general the Go frontend only takes the addresses of VAR_DECLs or
> PARM_DECLs.  It doesn't bother to set TREE_ADDRESSABLE for global
> variables for which TREE_STATIC or DECL_EXTERNAL is true.
>
> This patch sets TREE_ADDRESSABLE for those symbols which is under
> OPERATOR_AND (&).  Since, I feel, we may able to treat
> "Unary_expression:OPERATOR_AND" as address_taken operation.
>
> Bootstra pass on ppc64le. Is this ok for trunk?
>
>
> gcc/ChangeLog:
> 2021-05-20  Richard Biener  <rguent...@suse.de>
>             Jiufu Guo <guoji...@linux.ibm.com>
>
>         PR go/100537
>         * gimple-expr.c (mark_addressable): Check cfun.
>
> gcc/go/ChangeLog:
> 2021-05-20  Richard Biener  <rguent...@suse.de>
>             Jiufu Guo <guoji...@linux.ibm.com>
>
>         PR go/100537
>         * go-gcc.cc (class Gcc_backend): New mark_addresstaken function.
>         (Gcc_backend::mark_addresstaken): New function.
>         * gofrontend/backend.h (class Backend): New mark_addresstaken 
> function.
>         * gofrontend/expressions.cc
>         (Unary_expression::do_get_backend): Call mark_addresstaken.
> ---
>   gcc/gimple-expr.c                |  1 +
>   gcc/go/go-gcc.cc                 | 13 +++++++++++++
>   gcc/go/gofrontend/backend.h      |  4 ++++
>   gcc/go/gofrontend/expressions.cc |  1 +
>   4 files changed, 19 insertions(+)
>
> diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
> index b8c732b632a..f682841391b 100644
> --- a/gcc/gimple-expr.c
> +++ b/gcc/gimple-expr.c
> @@ -915,6 +915,7 @@ mark_addressable (tree x)
>     if (TREE_CODE (x) == VAR_DECL
>         && !DECL_EXTERNAL (x)
>         && !TREE_STATIC (x)
> +      && cfun != NULL
>         && cfun->gimple_df != NULL
>         && cfun->gimple_df->decls_to_pointers != NULL)
>       {
> diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
> index 5d9dbb5d068..fdbc72a2c75 100644
> --- a/gcc/go/go-gcc.cc
> +++ b/gcc/go/go-gcc.cc
> @@ -319,6 +319,9 @@ class Gcc_backend : public Backend
>     Bexpression*
>     address_expression(Bexpression*, Location);
>
> +  void
> +  mark_addresstaken(Bexpression*);
> +
>     Bexpression*
>     struct_field_expression(Bexpression*, size_t, Location);
>
> @@ -1684,6 +1687,16 @@ Gcc_backend::address_expression(Bexpression*
> bexpr, Location location)
>     return this->make_expression(ret);
>   }
>
> +void
> +Gcc_backend::mark_addresstaken(Bexpression* bexpr)
> +{
> +  tree expr = bexpr->get_tree();
> +  if (expr == error_mark_node)
> +    return;
> +
> +  mark_addressable(expr);
> +}
> +
>   // Return an expression for the field at INDEX in BSTRUCT.
>
>   Bexpression*
> diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h
> index c5b5d8f2054..45284ed2f0a 100644
> --- a/gcc/go/gofrontend/backend.h
> +++ b/gcc/go/gofrontend/backend.h
> @@ -315,6 +315,10 @@ class Backend
>     virtual Bexpression*
>     address_expression(Bexpression*, Location) = 0;
>
> +  // Mark an expression that takes the address of an expression.
> +  virtual void
> +  mark_addresstaken(Bexpression*) = 0;
> +
>     // Return an expression for the field at INDEX in BSTRUCT.
>     virtual Bexpression*
>     struct_field_expression(Bexpression* bstruct, size_t index, Location)
> = 0;
> diff --git a/gcc/go/gofrontend/expressions.cc
> b/gcc/go/gofrontend/expressions.cc
> index 5409d269ebf..4e52c8eafba 100644
> --- a/gcc/go/gofrontend/expressions.cc
> +++ b/gcc/go/gofrontend/expressions.cc
> @@ -5327,6 +5327,7 @@
> Unary_expression::do_get_backend(Translate_context* context)
>           }
>
>         go_assert(!this->create_temp_ ||
> this->expr_->is_multi_eval_safe());
> +      gogo->backend()->mark_addresstaken(bexpr);
>         ret = gogo->backend()->address_expression(bexpr, loc);
>         break;
>
> --
> 2.17.1
>
>

Reply via email to