FortranCInterface: Add support for Cray module mangling

Cray Fortran uses mangling of the form `my_sub$my_module_` with the
subroutine name first.  Teach FortranCInterface to detect this case.
Add `FortranCInterface_MODULE_{,_}ORDER` result variables to report it.

With optimizations on, Cray Fortran inlines the module subroutine into
the calling object, so our symbol with the `INFO` string is not used.
Add a directive to suppress inlining to avoid this.
This commit is contained in:
Victor Brunini 2025-03-12 16:11:50 -07:00 committed by Brad King
parent 7e2a1994f8
commit ce45045d50
7 changed files with 61 additions and 6 deletions

View File

@ -59,6 +59,19 @@ to reference them and can use the `Module Functions`_ below.
The case for a module symbol without an underscore,
either ``UPPER`` or ``LOWER``.
``FortranCInterface_MODULE_ORDER``
.. versionadded:: 4.1
Order of components for module symbols without an underscore:
``MODULE_THEN_SYMBOL``
The module name appears *before* the symbol name, i.e.,
``<PREFIX><module><MIDDLE><symbol><SUFFIX>``.
``SYMBOL_THEN_MODULE``
The module name appears *after* the symbol name, i.e.,
``<PREFIX><symbol><MIDDLE><module><SUFFIX>``.
``FortranCInterface_MODULE__PREFIX``
Prefix for a module symbol with an underscore.
@ -73,6 +86,19 @@ to reference them and can use the `Module Functions`_ below.
The case for a module symbol with an underscore,
either ``UPPER`` or ``LOWER``.
``FortranCInterface_MODULE__ORDER``
.. versionadded:: 4.1
Order of components for module symbols with an underscore:
``MODULE_THEN_SYMBOL``
The module name appears *before* the symbol name, i.e.,
``<PREFIX><module><MIDDLE><symbol><SUFFIX>``.
``SYMBOL_THEN_MODULE``
The module name appears *after* the symbol name, i.e.,
``<PREFIX><symbol><MIDDLE><module><SUFFIX>``.
Module Functions
^^^^^^^^^^^^^^^^

View File

@ -39,6 +39,8 @@ set(module_symbols
my_module_my_sub_ # PGI
my_module_MP_my_sub # NAG
mymodule$mysub # HP
mysub$mymodule_ # Cray
my_sub$my_module_ # Cray
mymodule_mp_mysub_ # Intel
MYMODULE_mp_MYSUB # Intel on Windows
mymodule_mysub_ # PGI
@ -64,14 +66,13 @@ endif()
# Generate C symbol sources.
set(symbol_sources)
if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "^(PathScale|Cray)$")
if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "^(PathScale)$")
# Provide mymodule_ and my_module_ init symbols because:
# - PGI Fortran uses module init symbols
# - Cray Fortran >= 7.3.2 uses module init symbols
# but not for:
# - PathScale Fortran uses module init symbols but module symbols
# use '.in.' so we cannot provide them anyway.
# - Cray Fortran >= 7.3.2 uses module init symbols but module symbols
# use 'mysub$mymodule_' so we cannot provide them anyway.
list(APPEND symbol_sources mymodule_.c my_module_.c MY_MODULE.c MYMODULE.c)
endif()
foreach(symbol IN LISTS global_symbols module_symbols)

View File

@ -92,6 +92,8 @@ set(_global_regex "^(_*)(mysub|MYSUB)([_$]*)$")
set(_global__regex "^(_*)(my_sub|MY_SUB)([_$]*)$")
set(_module_regex "^([A-Za-z_$]*)(mymodule|MYMODULE)([A-Za-z_$]*)(mysub|MYSUB)([_$]*)$")
set(_module__regex "^([A-Za-z_$]*)(my_module|MY_MODULE)([A-Za-z_$]*)(my_sub|MY_SUB)([_$]*)$")
set(_module_reverse_regex "^([A-Za-z_$]*)(mysub|MYSUB)([A-Za-z_$]*)(mymodule|MYMODULE)([_$]*)$")
set(_module_reverse__regex "^([A-Za-z_$]*)(my_sub|MY_SUB)([A-Za-z_$]*)(my_module|MY_MODULE)([_$]*)$")
# Parse the symbol names.
foreach(symbol ${FortranCInterface_SYMBOLS})
@ -120,7 +122,24 @@ foreach(symbol ${FortranCInterface_SYMBOLS})
list(GET pieces 3 name)
list(GET pieces 4 FortranCInterface_MODULE_${form}SUFFIX)
set(FortranCInterface_MODULE_${form}CASE "${_case_${name}}")
set(FortranCInterface_MODULE_${form}ORDER "MODULE_THEN_SYMBOL")
endif()
# Look for module symbols with subroutine name first.
string(REGEX REPLACE "${_module_reverse_${form}regex}"
"\\1;\\2;\\3;\\4;\\5" pieces "${symbol}")
list(LENGTH pieces len)
if(len EQUAL 5)
set(FortranCInterface_MODULE_${form}SYMBOL "${symbol}")
list(GET pieces 0 FortranCInterface_MODULE_${form}PREFIX)
list(GET pieces 1 name)
list(GET pieces 2 FortranCInterface_MODULE_${form}MIDDLE)
list(GET pieces 3 module)
list(GET pieces 4 FortranCInterface_MODULE_${form}SUFFIX)
set(FortranCInterface_MODULE_${form}CASE "${_case_${name}}")
set(FortranCInterface_MODULE_${form}ORDER "SYMBOL_THEN_MODULE")
endif()
endforeach()
endforeach()
@ -156,8 +175,13 @@ foreach(form "" "_")
endif()
set(_name "${_name_${FortranCInterface_MODULE_${form}CASE}}")
set(_middle "##${FortranCInterface_MODULE_${form}MIDDLE}##")
set(FortranCInterface_MODULE${form}_MACRO
"(mod_name,name, mod_NAME,NAME) ${_prefix}mod_${_name}${_middle}${_name}${_suffix}")
if(FortranCInterface_MODULE_${form}ORDER STREQUAL "SYMBOL_THEN_MODULE")
set(FortranCInterface_MODULE${form}_MACRO
"(mod_name,name, mod_NAME,NAME) ${_prefix}${_name}${_middle}mod_${_name}${_suffix}")
else()
set(FortranCInterface_MODULE${form}_MACRO
"(mod_name,name, mod_NAME,NAME) ${_prefix}mod_${_name}${_middle}${_name}${_suffix}")
endif()
endif()
endforeach()

View File

@ -18,6 +18,7 @@ set(FortranCInterface_MODULE_PREFIX "@FortranCInterface_MODULE_PREFIX@")
set(FortranCInterface_MODULE_MIDDLE "@FortranCInterface_MODULE_MIDDLE@")
set(FortranCInterface_MODULE_SUFFIX "@FortranCInterface_MODULE_SUFFIX@")
set(FortranCInterface_MODULE_CASE "@FortranCInterface_MODULE_CASE@")
set(FortranCInterface_MODULE_ORDER "@FortranCInterface_MODULE_ORDER@")
set(FortranCInterface_MODULE_MACRO "@FortranCInterface_MODULE_MACRO@")
# Module symbol with underscore.
@ -26,6 +27,7 @@ set(FortranCInterface_MODULE__PREFIX "@FortranCInterface_MODULE__PREFIX@")
set(FortranCInterface_MODULE__MIDDLE "@FortranCInterface_MODULE__MIDDLE@")
set(FortranCInterface_MODULE__SUFFIX "@FortranCInterface_MODULE__SUFFIX@")
set(FortranCInterface_MODULE__CASE "@FortranCInterface_MODULE__CASE@")
set(FortranCInterface_MODULE__ORDER "@FortranCInterface_MODULE__ORDER@")
set(FortranCInterface_MODULE__MACRO "@FortranCInterface_MODULE__MACRO@")
# Summarize what was found.

View File

@ -1,4 +1,5 @@
subroutine call_mod
!DIR$ NOINLINE
use mymodule
use my_module
call mysub()

View File

@ -1,4 +1,5 @@
subroutine call_sub
!DIR$ NOINLINE
call mysub()
call my_sub()
end

View File

@ -127,7 +127,7 @@ endfunction()
# if the id's match or the compilers are compatible, then
# call the test_fortran_c_interface_module function
if("${CMAKE_Fortran_COMPILER_ID}:${CMAKE_C_COMPILER_ID}" MATCHES
"(Intel(LLVM)?:MSVC|Absoft:GNU|(LLVMFlang|LFortran):(GNU|Clang))"
"(Intel(LLVM)?:MSVC|Absoft:GNU|(LLVMFlang|LFortran):(GNU|Clang)|Cray:CrayClang)"
OR ("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "${CMAKE_C_COMPILER_ID}" ))
test_fortran_c_interface_module()
else()