llvm / llvm-project

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

[Flang] Unexpected generic interface symbol reference causes error in mangling #93707

Open rofirrim opened 1 month ago

rofirrim commented 1 month ago

Consider the following module, simplified from a real module of OpenMPI

! mini_mpi.f90
module mini_mpi
  interface
    subroutine mpi_allreduce(sendbuf,recvbuf,count,datatype,op,comm,ierror)
      real(4),intent(in)::sendbuf(10)
      real(4)::recvbuf(10)
      integer(4),intent(in)::count
      integer(4),intent(in)::datatype
      integer(4),intent(in)::op
      integer(4),intent(in)::comm
      integer(4),intent(out)::ierror
    end subroutine mpi_allreduce
  end interface

  ! Generic interface
  interface mpi_allreduce
      procedure :: mpi_allreduce
  end interface
  contains
end module mini_mpi

And the following three modules, each one in a different file (stated in the first comment)

! comm.f90
module comm
  use mini_mpi

  contains
    subroutine my_sub_in_comm
      real(4)::sendbuf(10)
      real(4)::recvbuf(10)
      integer(4)::count
      integer(4)::datatype
      integer(4)::op
      integer(4)::comm
      integer(4)::ierror

      call mpi_allreduce(sendbuf, recvbuf, count, datatype, op, comm, ierror)
    end subroutine my_sub_in_comm

end module comm
! math.f90
module math
  use comm

  contains
    subroutine my_sub_in_math
      real(4)::sendbuf(10)
      real(4)::recvbuf(10)
      integer(4)::count
      integer(4)::datatype
      integer(4)::op
      integer(4)::comm
      integer(4)::ierror

      call mpi_allreduce(sendbuf, recvbuf, count, datatype, op, comm, ierror)
    end subroutine my_sub_in_math
end module math
! mesh.f90
module mesh
  use comm
  use math

  contains
    subroutine my_sub_in_mesh
      real(4)::sendbuf(10)
      real(4)::recvbuf(10)
      integer(4)::count
      integer(4)::datatype
      integer(4)::op
      integer(4)::comm
      integer(4)::ierror

      call mpi_allreduce(sendbuf, recvbuf, count, datatype, op, comm, ierror)
    end subroutine my_sub_in_mesh
end module mesh

If we compile them in the proper order

flang-new -c mini_mpi.f90
flang-new -c comm.f90
flang-new -c math.f90
flang-new -c mesh.f90

mesh.f90 fails to compile with the following error

LLVM ERROR: <path>/llvm-src/flang/lib/Lower/Mangler.cpp:174: not yet implemented: symbol mangling

We try to mangle a GenericDetails.

It seems the problem stems in the exported symbols my math (and mesh) in which we see repeated references to mpi_allreduce (this suggests we might be exporting both the generic interface name and the external name) from these modules.

$ grep -rw mpi_allreduce {mesh,math}.mod
mesh.mod:use comm,only:mpi_allreduce
mesh.mod:use math,only:comm$mini_mpi$mpi_allreduce
math.mod:use comm,only:mpi_allreduce
math.mod:use mini_mpi,only:comm$mini_mpi$mpi_allreduce=>mpi_allreduce

but somehow is not a problem for comm (which is hopefully exporting only the generic name?)

$ grep  mpi_allreduce comm.mod
use mini_mpi,only:mpi_allreduce

The problem seems related to the generic interface in mini_mpi.f90 because commenting it solves the problem. But modifying the OpenMPI module is a bit of an inconvenient workaround.

klausler commented 1 month ago

Fortran unfortunately allows one name to refer to multiple symbols in the same scope in a few cases. One of these cases is the use of a single name to refer to both a generic interface as well as one of its specific procedures. When this happens, it is not possible for a module to contain one and not the other.

f18's module files are just Fortran, so you can cat them and see this in action.

I suspect that the name mangling code isn't checking for this case. In the symbol table built by semantics, it is represented as a GenericDetails symbol in the scope's name map, and the GenericDetails has a specific() member function that points to the SubprogramDetails symbol of the same name that is not in the scope's name map.