iains / gcc-darwin-arm64

GCC master branch for Darwin with experimental support for Arm64. Currently GCC-15.0.0 [September 2024]
GNU General Public License v2.0
269 stars 33 forks source link

Passing subroutine that accesses variable by host association causes segfault at -O1 or above #37

Closed rhdtownsend closed 2 years ago

rhdtownsend commented 3 years ago

Apologies for the long-winded title! Consider the following MWE:

module nested_crash_m

contains

  subroutine sub_mod (sub)
    interface
       subroutine sub()
       end subroutine sub
    end interface
    call sub()
  end subroutine sub_mod

end module nested_crash_m

program nested_crash

  use nested_crash_m

  implicit none

  real :: a

  a = 1.

  call sub_mod(sub)

contains

  subroutine sub()
    print *, a
  end subroutine sub

end program nested_crash

Compiled with -O0, runs fine and produces the intended result (1.000...). At -O1 or above, there is a segfault triggered by accessing a (via host association) in subroutine sub(). I'm guessing that on entry to sub(), the host scope isn't properly being exposed.

iains commented 3 years ago

I can repeat this (not analysed more yet).

fxcoudert commented 2 years ago

I can reproduce without the module, with a single nested routine:

meau /tmp/irun $ cat a.f90
program crash
  implicit none
  real :: a
  a = 1.
  call sub()
contains
  subroutine sub()
    print *, a
  end subroutine sub
end program crash
meau /tmp/irun $ ./bin/gfortran a.f90 -O0 && ./a.out
   1.00000000    
meau /tmp/irun $ ./bin/gfortran a.f90 -O2 && ./a.out
   1.44448779E+26

It doesn't crash, but after optimisation it does output a wrong (random) value.

iains commented 2 years ago

We have a prototype for a proper solution*** to nested functions on aarch64-darwin (the current branch implementation is noted to be a temporary hack). One of the higher things on my TODO is to swap the "proper solution prototype" in and the hack out.

I think spending any great effort on nested function bugs would be wasted in the short-term.

*** also posted upstream for review.

iains commented 2 years ago

this does not seem to be solely the nested implementation - the fault is still present with the revised one.

iains commented 2 years ago

it seems that when we optimise, the crash() routine is inlined into main() but the code that sets a = 1.0 is lost in the process. So the nested function sees an uninitialised variable.

.... so the question is why is part of the inlined code being dropped? (maybe for some reason it thinks the value is unused).

iains commented 2 years ago

O0

;; Function sub (sub.0, funcdef_no=1, decl_uid=2979, cgraph_uid=1, symbol_order=0)

__attribute__((fn spec (". ")))
void sub ()
{
  struct __st_parameter_dt dt_parm.0;
  real(kind=4) * a.2_1;

  <bb 2> :
  dt_parm.0.common.filename = &"t.f90"[1]{lb: 1 sz: 1};
  dt_parm.0.common.line = 8;
  dt_parm.0.common.flags = 128;
  dt_parm.0.common.unit = 6;
  _gfortran_st_write (&dt_parm.0);
  a.2_1 = &CHAIN.4_8(D)->a;
  _gfortran_transfer_real_write (&dt_parm.0, a.2_1, 4);
  _gfortran_st_write_done (&dt_parm.0);
  dt_parm.0 ={v} {CLOBBER};
  return;

}

;; Function crash (MAIN__, funcdef_no=0, decl_uid=2977, cgraph_uid=2, symbol_order=1)

__attribute__((fn spec (". ")))
void crash ()
{
  struct FRAME.crash FRAME.3;
  real(kind=4) a [value-expr: FRAME.3.a];
  real(kind=4) D.2991;
  real(kind=4) _3;

  <bb 2> :
  FRAME.3.FRAME_BASE.PARENT = 0B;
  _3 = 1.0e+0;
  FRAME.3.a = _3;
  sub (); [static-chain: &FRAME.3]
  GIMPLE_NOP
  return;

}

;; Function main (main, funcdef_no=2, decl_uid=2983, cgraph_uid=3, symbol_order=2)

__attribute__((externally_visible))
integer(kind=4) main (integer(kind=4) argc, character(kind=1) * * argv)
{
  static integer(kind=4) options.1[7] = {2116, 4095, 0, 1, 1, 0, 31};
  integer(kind=4) D.2993;
  integer(kind=4) _7;

  <bb 2> :
  _gfortran_set_args (argc_2(D), argv_3(D));
  _gfortran_set_options (7, &options.1[0]);
  crash ();
  _7 = 0;

  <bb 3> :
<L0>:
  return _7;

}

O1

;; Function sub (sub.0, funcdef_no=1, decl_uid=2979, cgraph_uid=1, symbol_order=0) (executed once)

__attribute__((fn spec (". ")))
void sub ()
{
  struct __st_parameter_dt dt_parm.0;
  real(kind=4) * a.2_1;

  <bb 2> [local count: 1073741824]:
  dt_parm.0.common.filename = &"t.f90"[1]{lb: 1 sz: 1};
  dt_parm.0.common.line = 8;
  dt_parm.0.common.flags = 128;
  dt_parm.0.common.unit = 6;
  _gfortran_st_write (&dt_parm.0);
  a.2_1 = &CHAIN.4_8(D)->a;
  _gfortran_transfer_real_write (&dt_parm.0, a.2_1, 4);
  _gfortran_st_write_done (&dt_parm.0);
  dt_parm.0 ={v} {CLOBBER};
  return;

}

;; Function main (main, funcdef_no=2, decl_uid=2983, cgraph_uid=3, symbol_order=2) (executed once)

__attribute__((externally_visible))
integer(kind=4) main (integer(kind=4) argc, character(kind=1) * * argv)
{
  struct FRAME.crash FRAME.3;
  static integer(kind=4) options.1[7] = {2116, 4095, 0, 1, 1, 0, 31};

  <bb 2> [local count: 1073741824]:
  _gfortran_set_args (argc_2(D), argv_3(D));
  _gfortran_set_options (7, &options.1[0]);
  sub (); [static-chain: &FRAME.3]
  return 0;
}
iains commented 2 years ago

actually, this fails for x86_64 darwin18 with current master; so it's not an aarch64 problem (we should move the PR to BZ)

iains commented 2 years ago

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103766

iains commented 2 years ago

should be fixed by upstream r12-6067-gfcbf94a5be9

rhdtownsend commented 2 years ago

I've done a 12.0 build with the upstream patch applied; now, while FX's reduced test case runs OK, I still get a segfault with my original test case.

iains commented 2 years ago

with the latest branch build (which includes FX's fix and the revised trampoline implementation.) on gcc304 (M1 mac mini with actually darwin21)

$ ~/aarch64-apple-darwin20/gcc-12-0-0/bin/gfortran issue-37.f90 -o ix bash-3.2$ ./ix 1.00000000
bash-3.2$ ~/aarch64-apple-darwin20/gcc-12-0-0/bin/gfortran issue-37.f90 -O -o ix bash-3.2$ ./ix 1.00000000
bash-3.2$ ~/aarch64-apple-darwin20/gcc-12-0-0/bin/gfortran issue-37.f90 -O2 -o ix bash-3.2$ ./ix 1.00000000
2$ ~/aarch64-apple-darwin20/gcc-12-0-0/bin/gfortran issue-37.f90 -O3 -flto -o ix bash-3.2$ ./ix 1.00000000

so - now I cannot repeat your crash.

rhdtownsend commented 2 years ago

Could be that I applied the patch to a slightly out of date branch. I’ll try again with the latest branch.

On Dec 27, 2021, at 12:02 PM, iains @.**@.>> wrote:

with the latest branch build (which includes FX's fix and the revised trampoline implementation.) on gcc304 (M1 mac mini with actually darwin21)

$ ~/aarch64-apple-darwin20/gcc-12-0-0/bin/gfortran issue-37.f90 -o ix bash-3.2$ ./ix 1.00000000 bash-3.2$ ~/aarch64-apple-darwin20/gcc-12-0-0/bin/gfortran issue-37.f90 -O -o ix bash-3.2$ ./ix 1.00000000 bash-3.2$ ~/aarch64-apple-darwin20/gcc-12-0-0/bin/gfortran issue-37.f90 -O2 -o ix bash-3.2$ ./ix 1.00000000 2$ ~/aarch64-apple-darwin20/gcc-12-0-0/bin/gfortran issue-37.f90 -O3 -flto -o ix bash-3.2$ ./ix 1.00000000

so - now I cannot repeat your crash.

— Reply to this email directly, view it on GitHubhttps://github.com/iains/gcc-darwin-arm64/issues/37#issuecomment-1001681492, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ADIYU4ELXSMHZY4C2YSS2PDUTCS3NANCNFSM4VQXZP4Q. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you authored the thread.Message ID: @.***>