public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
From: Harald Anlauf <anlauf@gmx.de>
To: Rimvydas Jasinskas <rimvydasjas@gmail.com>
Cc: Thomas Schwinge <thomas@codesourcery.com>,
	Rimvydas Jasinskas via Fortran <fortran@gcc.gnu.org>,
	fortran <fortran@gcc.gnu.org>
Subject: Re: Support for WEAK attribute, part 2
Date: Thu, 16 Feb 2023 22:50:21 +0100	[thread overview]
Message-ID: <trinity-bb49b3d4-7455-4c7b-89d9-a9a857e68651-1676584221172@3c-app-gmx-bs44> (raw)
In-Reply-To: <CAFmAMQ04TtgTu1oZnzFSWw9pkgK0tRmt8ptpx1Xz4K0gjDCaag@mail.gmail.com>

Hi Rimvydas,

> Gesendet: Mittwoch, 15. Februar 2023 um 21:58 Uhr
> Von: "Rimvydas Jasinskas" <rimvydasjas@gmail.com>
>
> On Tue, Feb 14, 2023 at 9:55 PM Harald Anlauf <anlauf@gmx.de> wrote:
> > >>> There is one thing I cannot test, which is the handling of weak symbols
> > >>> on other platforms.  A quick glance at the C testcases suggests that
> > >>> someone with access to either an NVPTX or MingGW target might tell
> > >>> whether that particular target should be excluded.
> While working on part 2 patch for weak variables I noticed that MingGW
> has quite different handling of weak symbols as weak externals between
> 32/64.  I think adding "! { dg-skip-if "" { x86-64-*-mingw*} }" is
> needed to weak-1.f90 testcase, but I decided to wait for testsuite
> failure reports.

there are some MinGW users that will hopefully report back here soon.

> > > And, orthogonally: is '!GCC$ ATTRIBUTES weak' meant to be used only for
> > > subroutines (like in 'gfortran.dg/weak-1.f90') and also functions (I
> > > suppose; test case?), or also for weak "data" in some way (which, for
> > > example, in the C world then evaluates to a zero-address unless actually
> > > defined)?
> Weak zero-addressed "data" is more complicated between targets,  I do
> not see a need for it.
> Functions are handled the same as subroutines, I had testcase for it,
> but decided to deal with fallout from weak-1.f90 first:
> $ cat gcc/testsuite/gfortran.dg/weak-2.f90
> ! { dg-do compile }
> ! { dg-require-weak "" }
> ! { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?impl" } }
> integer function impl()
> implicit none
> !GCC$ ATTRIBUTES weak :: impl
> end function

Yes, this works.  I tried that before pushing.

> > Syntax and use of the WEAK directive.
> > !DIR$ WEAK procedure_name[, procedure_name] ...
> > !DIR$ WEAK procedure_name= stub_name[, procedure_name1= stub_name1] ...
> > stub_name
> >      A stub procedure that exists in the code. The stub_name will be
> > called if a strong reference does not exist for procedure_name. The
> > stub_name procedure must have the same name and dummy argument list as
> > procedure_name.
> I think the same for procedure_name=stub_name can be achieved with
> bind(c,'sym') already without caring about symbol name mangling:
> $ cat gcc/testsuite/gfortran.dg/weak-6.f90
> ! { dg-do compile }
> ! { dg-require-weak "" }
> ! { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?bar__" } }
> integer function impl() bind(c,name='bar__')
> implicit none
> !GCC$ ATTRIBUTES weak :: impl
> end function

This does work indeed.  It would be good to add these examples to
the documentation for reference in a subsequent patch.

> > I'm not sure whether we need to support weak symbols other than
> > procedures in gfortran.  Maybe Rimvydas can comment on this.
> In 2nd part patch I was thinking to add support for weak global
> variables (like in modules):
> --- a/gcc/fortran/trans-decl.cc
> +++ b/gcc/fortran/trans-decl.cc
> @@ -814,6 +814,10 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
>        && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
>      set_decl_tls_model (decl, decl_default_tls_model (decl));
>
> +  /* Mark weak variables.  */
> +  if (sym->attr.ext_attr & (1 << EXT_ATTR_WEAK))
> +    declare_weak (decl);
> +
>    gfc_finish_decl_attrs (decl, &sym->attr);
>  }
>
> $ cat gcc/testsuite/gfortran.dg/weak-3.f90
> ! { dg-do compile }
> ! { dg-require-weak "" }
> ! { dg-skip-if "" { x86_64-*-mingw* } }
> ! { dg-skip-if "" { nvptx-*-* } }
> ! { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?__foo_MOD_abc" } }
> module foo
> implicit none
> !GCC$ ATTRIBUTES weak :: abc
> real :: abc(7)
> end module
>
> The catch is again scan-assembler issues with various symbol name
> manglings.  Maybe just to add testcase without scan-assembler to check
> if testcase is not rejected?

Either that, or restricting those testcases by adding:

! { dg-skip-if "" { nvptx-*-* } }
! { dg-skip-if "" { x86_64-*-mingw* } }

> Currently already rejected are:
> $ cat gcc/testsuite/gfortran.dg/weak-4.f90
> ! { dg-do compile }
> ! { dg-require-weak "" }
> program foo  ! { dg-error "weak declaration of 'foo' must be public" "" }
> implicit none
> !GCC$ ATTRIBUTES weak :: foo
> end program

Yes.

> $ cat gcc/testsuite/gfortran.dg/weak-9.f90
> ! { dg-do compile }
> ! { dg-require-weak "" }
> subroutine foo
> implicit none
> real :: abc     ! { dg-error "weak declaration of 'abc' must be public" "" }
> !GCC$ ATTRIBUTES weak :: abc
> print *, abc
> contains
>  subroutine bar ! { dg-error "weak declaration of 'bar' must be public" "" }
> !GCC$ ATTRIBUTES weak :: bar
>  end subroutine
> end subroutine
>
> However error is not given if 'abc' is made a dummy argument or is not
> used, any ideas why?

At least for a dummy argument one can generate an error in
gfc_get_symbol_decl():

@@ -1549,6 +1552,14 @@ gfc_get_symbol_decl (gfc_symbol * sym)
              || (sym->module && sym->attr.if_source != IFSRC_DECL
                  && sym->backend_decl));

+  if (sym->attr.dummy && (sym->attr.ext_attr & (1 << EXT_ATTR_WEAK)))
+    {
+      if (!sym->error)
+       gfc_error ("Symbol %qs at %L has the WEAK attribute but is a dummy "
+                  "argument", sym->name, &sym->declared_at);
+      sym->error = 1;
+    }
+
   if (sym->attr.dummy && sym->ns->proc_name->attr.is_bind_c
       && is_CFI_desc (sym, NULL))
     {

(The setting of sym->error is done to suppress multiple errors
for the same line.  Not sure if this is the best solution, but
it works.)

> $ cat gcc/testsuite/gfortran.dg/weak-8.f90
> ! { dg-do compile }
> ! { dg-require-weak "" }
> module foo
> implicit none
> real :: a,b
> common /c/ a,b
> !GCC$ ATTRIBUTES weak :: c
> ! { dg-error "has no IMPLICIT type" "common" {target *-*-*} .-1 }
> end module

Well, here 'c' is an undeclared variable.
(The syntax would be different anyway, see e.g. SAVE).

> I suspect declaring common blocks weak should be explicitly rejected
> somewhere in resolve.cc, since .comm + .weak (should?) be illegal:
> $ cat cweak.s
> .comm c_,8,16
> .weak c_
> $ as cweak.s
> cweak.s: Assembler messages:
> cweak.s: Error: symbol `c_' can not be both weak and common
> However in weak-8.f90 error depends if "implicit none" is given.

Commenting out the "implicit none", I see in the assembler:

        .comm   c_,8,16
        .weak   __foo_MOD_c

which confirms that variable "c" and common /c/ are different beasts.

> Also what to do with declarations like:
> $ cat gcc/testsuite/gfortran.dg/weak-7.f90
> ! { dg-do compile }
> ! { dg-require-weak "" }
> module foo
> implicit none
> !GCC$ ATTRIBUTES weak :: foo
> integer :: ijk
> end module
>
> Currently it is silently accepted and has no effect.  I would see it
> useful if such a declaration would make all publicly visible variables
> and procedures to be marked as weak (as a shorthand, instead of
> declaring each variable/procedure as weak).  But I have not looked up
> how to do this yet.

Yes, it makes sense to either diagnose it or apply it
to publicly visible variables and procedures.  This
appears to be more work.

> Similar issue is with other attributes too:
> module aaa
> !GCC$ ATTRIBUTES fastcall :: aaa
> !GCC$ ATTRIBUTES deprecated :: aaa
> !GCC$ ATTRIBUTES noinline :: aaa
> integer :: ijk
> end module
>
> If such declarations to be explicitly rejected/diagnosed (say under
> -Wattributes) some kind of table like in
> gcc/c-family/c-attribs.cc:c_common_attribute_table[] would be needed,
> where false/true indicate if attribute could be applied for a given
> use case.
> On a side note, could someone check if cdecl/stdcall/fastcall actually
> affect code generation on windows targets?

Could you please open a PR for handling and tracking this?
This mail has already gotten quite long.

> In the end, the most problematic issue is useability of GCC directives
> in user codes.  As more and more attributes or other directives get
> supported it tends to create chaos in how users (try to) make use of
> these attributes.  The NO_ARGS_CHECK is/was a good example.  The mpi
> libraries generate bindings on the fly after checking if this
> attribute is supported.  Other projects use cpp preprocessor "#if
> __GNUC__ > 8", sometimes even in wrong ways like "#if __GFORTRAN__ >
> 10" or explicit rules like "cc -E -P -traditional -xc foo.F90 >
> foo.f90 && $(FC) -c foo.f90" while not suspecting that system cc(1)
> and say gfortran-10 could be of different versions on given host
> environment (or even not gfortran), specially on systems where cc(1)
> is 4.8.5.  The __GFORTRAN__ macro defined to '1' seems like a lost
> opportunity to use it as a compiler version major or maybe even
> currently active Fortran standard level.
> Issue is that unlike C frontends, gfortran hard rejects compilation
> units containing unknown attributes or slightly expanded new syntax:
> $ cat cold.f90
> subroutine foo
> !GCC$ ATTRIBUTES cold :: foo
> end subroutine
> $ gfortran -c cold.f90
> Error: Unknown attribute in !GCC$ ATTRIBUTES statement at (1)

Same here: please open a PR on this.

> I have a patch that adds -fallow-ignored-directive to demote such
> errors to warnings, but it looks too ugly and does not solve the
> useability issues by itself.
> What about adding support for conditional directives based on the
> compiler version?  Simple "!GCC$ if(13+) ATTRIBUTES weak :: foo" would
> in theory allow to keep the same sourcecode with different compiler
> versions and not require cpp preprocessor tricks once this feature
> "age" enough.

This does look a bit strange to me, and I do not see the real
point.  It is possible to use the accompanying preprocessor to
generate gcc/gfortran version dependent stuff (works for me):

#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 1300
#define GCC_ATTRIBUTES_WEAK GCC$ ATTRIBUTES weak
#endif
!GCC_ATTRIBUTES_WEAK :: foo

(The system gcc/cpp version is lower).

Cheers,
Harald

> Any thoughts?
>
> Regards,
> Rimvydas
>

  reply	other threads:[~2023-02-16 21:50 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-10  5:42 Support for NOINLINE attribute Rimvydas Jasinskas
2023-02-10  8:24 ` Steve Kargl
2023-02-10  8:38   ` Rimvydas Jasinskas
2023-02-10 18:53     ` Steve Kargl
2023-02-10 21:07 ` Harald Anlauf
2023-02-10 21:16   ` Steve Kargl
2023-02-10 22:16   ` Rimvydas Jasinskas
2023-02-11 21:26     ` Harald Anlauf
2023-02-12  6:59       ` Rimvydas Jasinskas
2023-02-12 21:28         ` Harald Anlauf
2023-02-13 17:50           ` Harald Anlauf
2023-02-14  9:35             ` nvptx: Adjust 'scan-assembler' in 'gfortran.dg/weak-1.f90' (was: Support for NOINLINE attribute) Thomas Schwinge
2023-02-14 19:55               ` Harald Anlauf
2023-02-15 20:58                 ` Support for WEAK attribute, part 2 Rimvydas Jasinskas
2023-02-16 21:50                   ` Harald Anlauf [this message]
2023-02-23 13:55                     ` Rimvydas Jasinskas
2023-02-23 20:53                       ` Harald Anlauf
2023-02-24  5:16                         ` Rimvydas Jasinskas
2023-02-24 22:03                           ` Harald Anlauf
2023-03-28 21:06                           ` Enable 'gfortran.dg/weak-2.f90' for nvptx target (was: Support for WEAK attribute, part 2) Thomas Schwinge
2023-02-18 20:35 ` Support for NOINLINE attribute Bernhard Reutner-Fischer
2023-02-24  7:19   ` Bernhard Reutner-Fischer
2023-02-24 12:02     ` Rimvydas Jasinskas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=trinity-bb49b3d4-7455-4c7b-89d9-a9a857e68651-1676584221172@3c-app-gmx-bs44 \
    --to=anlauf@gmx.de \
    --cc=fortran@gcc.gnu.org \
    --cc=rimvydasjas@gmail.com \
    --cc=thomas@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).