llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.05k stars 11.98k forks source link

[Flang] execution error when an intrinsic function name declared in an intrinsic statement is specified as an argument of a subroutine #72084

Closed ohno-fj closed 10 months ago

ohno-fj commented 1 year ago
Version of flang-new : 18.0.0(1c876ff5155c4feeb2b2885eb3e6abda17c4b7f4)

When an intrinsic function name declared in an intrinsic statement is specified as an argument of a subroutine, the function cannot be used at the callee.

The following lines terminate abnormally at runtime..

  or(i)=func(arg(i))    ! Segmentation fault

The following are the test program, Flang-new, Gfortran and ifort compilation/execution result.

ie500_dcos.f90:

module moris
  intrinsic DCOS
  parameter(K=8)
  parameter(N=100)
  real(kind=8)::e=1.0d-14
  real(kind=K),dimension(N) :: arg,ir,or
  real(kind=4),dimension(N) :: tmp
end module moris

program main
  use  moris
  call random
  call outline(DCOS)
  call inline
  do i=1,n
     if(abs(ir(i)-or(i)).gt.e) then
        print*,"ng"
        print*,ir(i),or(i),abs(ir(i)-or(i))
     endif
  enddo
  print*,"DCOS ok"
end program main

subroutine random
  use moris
  INTEGER seed(33)/33*0/
  call random_seed(get=seed)
  do i=1,33
     seed(i)=seed(i)*5 /2  + 2
  enddo
  call random_seed(put=seed)
  call random_number(tmp)
  arg = tmp
end subroutine random

subroutine outline(func)
  use moris
  real(kind=k) :: func
  do i=1,n
     or(i)=func(arg(i))    ! Segmentation fault
  enddo
end subroutine outline

subroutine inline
  use  moris
  do i=1,n
     ir(i)=DCOS(arg(i))
  enddo
end subroutine inline
$ flang-new ie500_dcos_.f90; ./a.out
./ie500_dcos_.f90:13:3: warning: If the procedure's interface were explicit, this reference would be in error
    call outline(DCOS)
    ^^^^^^^^^^^^^^^^^^
./ie500_dcos_.f90:13:16: because: Actual argument associated with procedure dummy argument 'func=' is not a procedure
    call outline(DCOS)
                 ^^^^
Segmentation fault (core dumped)
$
$ gfortran ie500_dcos_.f90; ./a.out
 DCOS ok
$
$ ifort ie500_dcos_.f90; ./a.out
 DCOS ok
$
llvmbot commented 1 year ago

@llvm/issue-subscribers-flang-frontend

Author: None (ohno-fj)

``` Version of flang-new : 18.0.0(1c876ff5155c4feeb2b2885eb3e6abda17c4b7f4) ``` When an intrinsic function name declared in an `intrinsic` statement is specified as an argument of a subroutine, the function cannot be used at the callee. The following lines terminate abnormally at runtime.. ``` or(i)=func(arg(i)) ! Segmentation fault ``` The following are the test program, Flang-new, Gfortran and ifort compilation/execution result. ie500_dcos.f90: ```fortran module moris intrinsic DCOS parameter(K=8) parameter(N=100) real(kind=8)::e=1.0d-14 real(kind=K),dimension(N) :: arg,ir,or real(kind=4),dimension(N) :: tmp end module moris program main use moris call random call outline(DCOS) call inline do i=1,n if(abs(ir(i)-or(i)).gt.e) then print*,"ng" print*,ir(i),or(i),abs(ir(i)-or(i)) endif enddo print*,"DCOS ok" end program main subroutine random use moris INTEGER seed(33)/33*0/ call random_seed(get=seed) do i=1,33 seed(i)=seed(i)*5 /2 + 2 enddo call random_seed(put=seed) call random_number(tmp) arg = tmp end subroutine random subroutine outline(func) use moris real(kind=k) :: func do i=1,n or(i)=func(arg(i)) ! Segmentation fault enddo end subroutine outline subroutine inline use moris do i=1,n ir(i)=DCOS(arg(i)) enddo end subroutine inline ``` ``` $ flang-new ie500_dcos_.f90; ./a.out ./ie500_dcos_.f90:13:3: warning: If the procedure's interface were explicit, this reference would be in error call outline(DCOS) ^^^^^^^^^^^^^^^^^^ ./ie500_dcos_.f90:13:16: because: Actual argument associated with procedure dummy argument 'func=' is not a procedure call outline(DCOS) ^^^^ Segmentation fault (core dumped) $ ``` ``` $ gfortran ie500_dcos_.f90; ./a.out DCOS ok $ ``` ``` $ ifort ie500_dcos_.f90; ./a.out DCOS ok $ ```
llvmbot commented 12 months ago

@llvm/issue-subscribers-bug

Author: None (ohno-fj)

``` Version of flang-new : 18.0.0(1c876ff5155c4feeb2b2885eb3e6abda17c4b7f4) ``` When an intrinsic function name declared in an `intrinsic` statement is specified as an argument of a subroutine, the function cannot be used at the callee. The following lines terminate abnormally at runtime.. ``` or(i)=func(arg(i)) ! Segmentation fault ``` The following are the test program, Flang-new, Gfortran and ifort compilation/execution result. ie500_dcos.f90: ```fortran module moris intrinsic DCOS parameter(K=8) parameter(N=100) real(kind=8)::e=1.0d-14 real(kind=K),dimension(N) :: arg,ir,or real(kind=4),dimension(N) :: tmp end module moris program main use moris call random call outline(DCOS) call inline do i=1,n if(abs(ir(i)-or(i)).gt.e) then print*,"ng" print*,ir(i),or(i),abs(ir(i)-or(i)) endif enddo print*,"DCOS ok" end program main subroutine random use moris INTEGER seed(33)/33*0/ call random_seed(get=seed) do i=1,33 seed(i)=seed(i)*5 /2 + 2 enddo call random_seed(put=seed) call random_number(tmp) arg = tmp end subroutine random subroutine outline(func) use moris real(kind=k) :: func do i=1,n or(i)=func(arg(i)) ! Segmentation fault enddo end subroutine outline subroutine inline use moris do i=1,n ir(i)=DCOS(arg(i)) enddo end subroutine inline ``` ``` $ flang-new ie500_dcos_.f90; ./a.out ./ie500_dcos_.f90:13:3: warning: If the procedure's interface were explicit, this reference would be in error call outline(DCOS) ^^^^^^^^^^^^^^^^^^ ./ie500_dcos_.f90:13:16: because: Actual argument associated with procedure dummy argument 'func=' is not a procedure call outline(DCOS) ^^^^ Segmentation fault (core dumped) $ ``` ``` $ gfortran ie500_dcos_.f90; ./a.out DCOS ok $ ``` ``` $ ifort ie500_dcos_.f90; ./a.out DCOS ok $ ```
ceseo commented 10 months ago

The problem here is not the intrinsic, it's the nested call. Here is a smaller reproducer:

program main
    call bar(foo)
end program main

subroutine foo(x)
    x=x+1
end subroutine foo

subroutine bar(func)
    call func(1.0)
end subroutine bar

I'll take a look at this.

jeanPerier commented 10 months ago

The problem here is not the intrinsic, it's the nested call. Here is a smaller reproducer:

In your reproducer, call bar(foo) passes the address of an implicit local object variable foo on the stack, hence the segfault. You should add external :: foo, and then it does not segfault.

ceseo commented 10 months ago

Oh, correct! I'll keep digging the original testcase then. Thanks!

ceseo commented 10 months ago

The problem here is not the intrinsic, it's the nested call. Here is a smaller reproducer:

In your reproducer, call bar(foo) passes the address of an implicit local object variable foo on the stack, hence the segfault. You should add external :: foo, and then it does not segfault.

Btw, shouldn't Flang be emitting an error in this case? In addition to your observation, there is also a type mismatch, no?

jeanPerier commented 10 months ago

The problem here is not the intrinsic, it's the nested call. Here is a smaller reproducer:

In your reproducer, call bar(foo) passes the address of an implicit local object variable foo on the stack, hence the segfault. You should add external :: foo, and then it does not segfault.

Btw, shouldn't Flang be emitting an error in this case? In addition to your observation, there is also a type mismatch, no?

It is emitting a warning: If the procedure's interface were explicit, this reference would be in error. The reason it is only a warning is that some very old Fortran code out there is happy propagating procedures as data dummy and back to procedure dummy. Being very strict with implicit interface checks would break a lot of old code where the compiler did not checked against the actual definitions. But flang-new has option to turn warnings into errors.

BTW, the same waring is occurring in your original test case, which points that the INTRINSIC attribute of DCOS was somehow lost/ignored in the main program (flang-new -fc1 -debug-dump-symbols tells DCOS in main is an implicit object and not the one from the module: dcos (Implicit) size=4 offset=0: ObjectEntity type: REAL(4)). Unless there is some Fortran rules that justify this, this could be a name resolution bug. @klausler.

ceseo commented 10 months ago

@jeanPerier I think I have an idea of what's going on. The original reproducer declares a language standard intrinsic inside a module. If I understand correctly how genIntrinsicRef works, it will never process this correctly because intrinsic won't be null in this particular case. Does that make sense?

klausler commented 10 months ago

There is indeed a bug here in name resolution with an explicit INTRINSIC statement in a module. It's happening because the Fortran language is unclear about what should happen in a related case. Should COS be viewed as part of the module, or not, in the following:

module m
  real :: one.= cos(0.)
end
program t
  use m
  real :: cos = 2. ! error or not?
end

gfortran and others do NOT use-associate COS from the module; Intel and other do. f18 is trying to follow the gfortran precedent, and does so by not importing any intrinsics from modules. But clearly we should import intrinsic procedures with explicit INTRINSIC attributes. Will fix.

klausler commented 10 months ago

https://github.com/llvm/llvm-project/pull/76199

klausler commented 10 months ago

Patch has been merged into llvm-project/main, and the original test case above now compiles cleanly and runs successfully. Closing this bug report.