[flang][runtime] Build ISO_FORTRAN_ENV to export kind arrays as linkable symbols (#95388)
Moves definitions of the kind arrays into a Fortran MODULE to not only emit the MOD file, but also compile that MODULE file into an object file. This file is then linked into libFortranRuntime.so. Eventually this workaround PR shoud be redone and a proper runtime build should be setup that will then also compile Fortran MODULE files. Fixes #89403 --------- Co-authored-by: Valentin Clement (バレンタイン クレメン) <clementval@gmail.com> Co-authored-by: Michael Kruse <github@meinersbur.de>
This commit is contained in:
@@ -538,3 +538,4 @@ get_clang_resource_dir(HEADER_INSTALL_DIR SUBDIR include)
|
||||
install(
|
||||
FILES include/flang/ISO_Fortran_binding.h
|
||||
DESTINATION ${HEADER_INSTALL_DIR} )
|
||||
|
||||
|
||||
@@ -22,6 +22,23 @@ module iso_fortran_env
|
||||
compiler_options => __builtin_compiler_options, &
|
||||
compiler_version => __builtin_compiler_version
|
||||
|
||||
use iso_fortran_env_impl, only: &
|
||||
selectedInt8, selectedInt16, selectedInt32, selectedInt64, selectedInt128, &
|
||||
safeInt8, safeInt16, safeInt32, safeInt64, safeInt128, &
|
||||
int8, int16, int32, int64, int128, &
|
||||
logical8, logical16, logical32, logical64, &
|
||||
selectedReal16, selectedBfloat16, selectedReal32, &
|
||||
selectedReal64, selectedReal80, selectedReal64x2, &
|
||||
selectedReal128, &
|
||||
safeReal16, safeBfloat16, safeReal32, &
|
||||
safeReal64, safeReal80, safeReal64x2, &
|
||||
safeReal128, &
|
||||
real16, bfloat16, real32, real64, &
|
||||
real80, real64x2, real128, &
|
||||
integer_kinds => __builtin_integer_kinds, &
|
||||
real_kinds => __builtin_real_kinds, &
|
||||
logical_kinds => __builtin_logical_kinds
|
||||
|
||||
implicit none
|
||||
private
|
||||
|
||||
@@ -38,95 +55,22 @@ module iso_fortran_env
|
||||
pack([selectedUCS_2], selectedUCS_2 >= 0), &
|
||||
pack([selectedUnicode], selectedUnicode >= 0)]
|
||||
|
||||
integer, parameter :: &
|
||||
selectedInt8 = selected_int_kind(2), &
|
||||
selectedInt16 = selected_int_kind(4), &
|
||||
selectedInt32 = selected_int_kind(9), &
|
||||
selectedInt64 = selected_int_kind(18),&
|
||||
selectedInt128 = selected_int_kind(38), &
|
||||
safeInt8 = merge(selectedInt8, selected_int_kind(0), &
|
||||
selectedInt8 >= 0), &
|
||||
safeInt16 = merge(selectedInt16, selected_int_kind(0), &
|
||||
selectedInt16 >= 0), &
|
||||
safeInt32 = merge(selectedInt32, selected_int_kind(0), &
|
||||
selectedInt32 >= 0), &
|
||||
safeInt64 = merge(selectedInt64, selected_int_kind(0), &
|
||||
selectedInt64 >= 0), &
|
||||
safeInt128 = merge(selectedInt128, selected_int_kind(0), &
|
||||
selectedInt128 >= 0)
|
||||
integer, parameter, public :: &
|
||||
int8 = merge(selectedInt8, merge(-2, -1, selectedInt8 >= 0), &
|
||||
digits(int(0,kind=safeInt8)) == 7), &
|
||||
int16 = merge(selectedInt16, merge(-2, -1, selectedInt16 >= 0), &
|
||||
digits(int(0,kind=safeInt16)) == 15), &
|
||||
int32 = merge(selectedInt32, merge(-2, -1, selectedInt32 >= 0), &
|
||||
digits(int(0,kind=safeInt32)) == 31), &
|
||||
int64 = merge(selectedInt64, merge(-2, -1, selectedInt64 >= 0), &
|
||||
digits(int(0,kind=safeInt64)) == 63), &
|
||||
int128 = merge(selectedInt128, merge(-2, -1, selectedInt128 >= 0), &
|
||||
digits(int(0,kind=safeInt128)) == 127)
|
||||
public :: selectedInt8, selectedInt16, selectedInt32, selectedInt64, selectedInt128, &
|
||||
safeInt8, safeInt16, safeInt32, safeInt64, safeInt128, &
|
||||
int8, int16, int32, int64, int128
|
||||
|
||||
integer, parameter, public :: integer_kinds(*) = [ &
|
||||
selected_int_kind(0), &
|
||||
[(pack([selected_int_kind(k)], &
|
||||
selected_int_kind(k) >= 0 .and. &
|
||||
selected_int_kind(k) /= selected_int_kind(k-1)), &
|
||||
integer :: k=1, 39)]]
|
||||
public :: logical8, logical16, logical32, logical64
|
||||
|
||||
integer, parameter, public :: &
|
||||
logical8 = int8, logical16 = int16, logical32 = int32, logical64 = int64
|
||||
integer, parameter, public :: logical_kinds(*) = [ &
|
||||
pack([logical8], logical8 >= 0), &
|
||||
pack([logical16], logical16 >= 0), &
|
||||
pack([logical32], logical32 >= 0), &
|
||||
pack([logical64], logical64 >= 0)]
|
||||
public :: selectedReal16, selectedBfloat16, selectedReal32, &
|
||||
selectedReal64, selectedReal80, selectedReal64x2, &
|
||||
selectedReal128, &
|
||||
safeReal16, safeBfloat16, safeReal32, &
|
||||
safeReal64, safeReal80, safeReal64x2, &
|
||||
safeReal128, &
|
||||
real16, bfloat16, real32, real64, &
|
||||
real80, real64x2, real128
|
||||
|
||||
integer, parameter :: &
|
||||
selectedReal16 = selected_real_kind(3, 4), & ! IEEE half
|
||||
selectedBfloat16 = selected_real_kind(2, 37), & ! truncated IEEE single
|
||||
selectedReal32 = selected_real_kind(6, 37), & ! IEEE single
|
||||
selectedReal64 = selected_real_kind(15, 307), & ! IEEE double
|
||||
selectedReal80 = selected_real_kind(18, 4931), & ! 80x87 extended
|
||||
selectedReal64x2 = selected_real_kind(31, 307), & ! "double-double"
|
||||
selectedReal128 = selected_real_kind(33, 4931), & ! IEEE quad
|
||||
safeReal16 = merge(selectedReal16, selected_real_kind(0,0), &
|
||||
selectedReal16 >= 0), &
|
||||
safeBfloat16 = merge(selectedBfloat16, selected_real_kind(0,0), &
|
||||
selectedBfloat16 >= 0), &
|
||||
safeReal32 = merge(selectedReal32, selected_real_kind(0,0), &
|
||||
selectedReal32 >= 0), &
|
||||
safeReal64 = merge(selectedReal64, selected_real_kind(0,0), &
|
||||
selectedReal64 >= 0), &
|
||||
safeReal80 = merge(selectedReal80, selected_real_kind(0,0), &
|
||||
selectedReal80 >= 0), &
|
||||
safeReal64x2 = merge(selectedReal64x2, selected_real_kind(0,0), &
|
||||
selectedReal64x2 >= 0), &
|
||||
safeReal128 = merge(selectedReal128, selected_real_kind(0,0), &
|
||||
selectedReal128 >= 0)
|
||||
integer, parameter, public :: &
|
||||
real16 = merge(selectedReal16, merge(-2, -1, selectedReal16 >= 0), &
|
||||
digits(real(0,kind=safeReal16)) == 11), &
|
||||
bfloat16 = merge(selectedBfloat16, merge(-2, -1, selectedBfloat16 >= 0), &
|
||||
digits(real(0,kind=safeBfloat16)) == 8), &
|
||||
real32 = merge(selectedReal32, merge(-2, -1, selectedReal32 >= 0), &
|
||||
digits(real(0,kind=safeReal32)) == 24), &
|
||||
real64 = merge(selectedReal64, merge(-2, -1, selectedReal64 >= 0), &
|
||||
digits(real(0,kind=safeReal64)) == 53), &
|
||||
real80 = merge(selectedReal80, merge(-2, -1, selectedReal80 >= 0), &
|
||||
digits(real(0,kind=safeReal80)) == 64), &
|
||||
real64x2 = merge(selectedReal64x2, merge(-2, -1, selectedReal64x2 >= 0), &
|
||||
digits(real(0,kind=safeReal64x2)) == 106), &
|
||||
real128 = merge(selectedReal128, merge(-2, -1, selectedReal128 >= 0), &
|
||||
digits(real(0,kind=safeReal128)) == 113)
|
||||
|
||||
integer, parameter, public :: real_kinds(*) = [ &
|
||||
pack([real16], real16 >= 0), &
|
||||
pack([bfloat16], bfloat16 >= 0), &
|
||||
pack([real32], real32 >= 0), &
|
||||
pack([real64], real64 >= 0), &
|
||||
pack([real80], real80 >= 0), &
|
||||
pack([real64x2], real64x2 >= 0), &
|
||||
pack([real128], real128 >= 0)]
|
||||
public :: integer_kinds, real_kinds, logical_kinds
|
||||
|
||||
integer, parameter, public :: current_team = -1, &
|
||||
initial_team = -2, &
|
||||
|
||||
114
flang/module/iso_fortran_env_impl.f90
Normal file
114
flang/module/iso_fortran_env_impl.f90
Normal file
@@ -0,0 +1,114 @@
|
||||
!===-- module/iso_fortran_env_impl.f90 --=--------------------------------===!
|
||||
!
|
||||
! Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
! See https://llvm.org/LICENSE.txt for license information.
|
||||
! SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
!
|
||||
!===------------------------------------------------------------------------===!
|
||||
|
||||
! This MODULE implements part of the ISO_FORTRAN_ENV module file, which
|
||||
! partially requires linkable symbols for some entities defined
|
||||
! (e.g., real_kinds).
|
||||
|
||||
module iso_fortran_env_impl
|
||||
implicit none
|
||||
private
|
||||
|
||||
! INTEGER types
|
||||
integer, parameter, public :: &
|
||||
selectedInt8 = selected_int_kind(2), &
|
||||
selectedInt16 = selected_int_kind(4), &
|
||||
selectedInt32 = selected_int_kind(9), &
|
||||
selectedInt64 = selected_int_kind(18),&
|
||||
selectedInt128 = selected_int_kind(38), &
|
||||
safeInt8 = merge(selectedInt8, selected_int_kind(0), &
|
||||
selectedInt8 >= 0), &
|
||||
safeInt16 = merge(selectedInt16, selected_int_kind(0), &
|
||||
selectedInt16 >= 0), &
|
||||
safeInt32 = merge(selectedInt32, selected_int_kind(0), &
|
||||
selectedInt32 >= 0), &
|
||||
safeInt64 = merge(selectedInt64, selected_int_kind(0), &
|
||||
selectedInt64 >= 0), &
|
||||
safeInt128 = merge(selectedInt128, selected_int_kind(0), &
|
||||
selectedInt128 >= 0)
|
||||
|
||||
integer, parameter, public :: &
|
||||
int8 = merge(selectedInt8, merge(-2, -1, selectedInt8 >= 0), &
|
||||
digits(int(0,kind=safeInt8)) == 7), &
|
||||
int16 = merge(selectedInt16, merge(-2, -1, selectedInt16 >= 0), &
|
||||
digits(int(0,kind=safeInt16)) == 15), &
|
||||
int32 = merge(selectedInt32, merge(-2, -1, selectedInt32 >= 0), &
|
||||
digits(int(0,kind=safeInt32)) == 31), &
|
||||
int64 = merge(selectedInt64, merge(-2, -1, selectedInt64 >= 0), &
|
||||
digits(int(0,kind=safeInt64)) == 63), &
|
||||
int128 = merge(selectedInt128, merge(-2, -1, selectedInt128 >= 0), &
|
||||
digits(int(0,kind=safeInt128)) == 127)
|
||||
|
||||
integer, parameter, dimension(*), public :: __builtin_integer_kinds = [ &
|
||||
selected_int_kind(0), &
|
||||
[(pack([selected_int_kind(k)], &
|
||||
selected_int_kind(k) >= 0 .and. &
|
||||
selected_int_kind(k) /= selected_int_kind(k-1)), &
|
||||
integer :: k=1, 39)]]
|
||||
|
||||
! LOGICAL TYPES
|
||||
integer, parameter, public :: &
|
||||
logical8 = int8, logical16 = int16, logical32 = int32, logical64 = int64
|
||||
|
||||
integer, parameter, dimension(*), public :: __builtin_logical_kinds = [ &
|
||||
pack([logical8], logical8 >= 0), &
|
||||
pack([logical16], logical16 >= 0), &
|
||||
pack([logical32], logical32 >= 0), &
|
||||
pack([logical64], logical64 >= 0) &
|
||||
]
|
||||
|
||||
! REAL types
|
||||
integer, parameter, public :: &
|
||||
selectedReal16 = selected_real_kind(3, 4), & ! IEEE half
|
||||
selectedBfloat16 = selected_real_kind(2, 37), & ! truncated IEEE single
|
||||
selectedReal32 = selected_real_kind(6, 37), & ! IEEE single
|
||||
selectedReal64 = selected_real_kind(15, 307), & ! IEEE double
|
||||
selectedReal80 = selected_real_kind(18, 4931), & ! 80x87 extended
|
||||
selectedReal64x2 = selected_real_kind(31, 307), & ! "double-double"
|
||||
selectedReal128 = selected_real_kind(33, 4931), & ! IEEE quad
|
||||
safeReal16 = merge(selectedReal16, selected_real_kind(0,0), &
|
||||
selectedReal16 >= 0), &
|
||||
safeBfloat16 = merge(selectedBfloat16, selected_real_kind(0,0), &
|
||||
selectedBfloat16 >= 0), &
|
||||
safeReal32 = merge(selectedReal32, selected_real_kind(0,0), &
|
||||
selectedReal32 >= 0), &
|
||||
safeReal64 = merge(selectedReal64, selected_real_kind(0,0), &
|
||||
selectedReal64 >= 0), &
|
||||
safeReal80 = merge(selectedReal80, selected_real_kind(0,0), &
|
||||
selectedReal80 >= 0), &
|
||||
safeReal64x2 = merge(selectedReal64x2, selected_real_kind(0,0), &
|
||||
selectedReal64x2 >= 0), &
|
||||
safeReal128 = merge(selectedReal128, selected_real_kind(0,0), &
|
||||
selectedReal128 >= 0)
|
||||
|
||||
integer, parameter, public :: &
|
||||
real16 = merge(selectedReal16, merge(-2, -1, selectedReal16 >= 0), &
|
||||
digits(real(0,kind=safeReal16)) == 11), &
|
||||
bfloat16 = merge(selectedBfloat16, merge(-2, -1, selectedBfloat16 >= 0), &
|
||||
digits(real(0,kind=safeBfloat16)) == 8), &
|
||||
real32 = merge(selectedReal32, merge(-2, -1, selectedReal32 >= 0), &
|
||||
digits(real(0,kind=safeReal32)) == 24), &
|
||||
real64 = merge(selectedReal64, merge(-2, -1, selectedReal64 >= 0), &
|
||||
digits(real(0,kind=safeReal64)) == 53), &
|
||||
real80 = merge(selectedReal80, merge(-2, -1, selectedReal80 >= 0), &
|
||||
digits(real(0,kind=safeReal80)) == 64), &
|
||||
real64x2 = merge(selectedReal64x2, merge(-2, -1, selectedReal64x2 >= 0), &
|
||||
digits(real(0,kind=safeReal64x2)) == 106), &
|
||||
real128 = merge(selectedReal128, merge(-2, -1, selectedReal128 >= 0), &
|
||||
digits(real(0,kind=safeReal128)) == 113)
|
||||
|
||||
integer, parameter, dimension(*), public :: __builtin_real_kinds = [ &
|
||||
pack([real16], real16 >= 0), &
|
||||
pack([bfloat16], bfloat16 >= 0), &
|
||||
pack([real32], real32 >= 0), &
|
||||
pack([real64], real64 >= 0), &
|
||||
pack([real80], real80 >= 0), &
|
||||
pack([real64x2], real64x2 >= 0), &
|
||||
pack([real128], real128 >= 0) &
|
||||
]
|
||||
end module iso_fortran_env_impl
|
||||
@@ -169,6 +169,7 @@ set(sources
|
||||
unit-map.cpp
|
||||
unit.cpp
|
||||
utf.cpp
|
||||
${FORTRAN_MODULE_OBJECTS}
|
||||
)
|
||||
|
||||
include(AddFlangOffloadRuntime)
|
||||
|
||||
@@ -4,7 +4,16 @@ set(LLVM_LINK_COMPONENTS
|
||||
Support
|
||||
)
|
||||
|
||||
set(MODULES
|
||||
# Define the list of Fortran module files that need to be compiled
|
||||
# to produce an object file for inclusion into the FortranRuntime
|
||||
# library.
|
||||
set(MODULES_WITH_IMPLEMENTATION
|
||||
"iso_fortran_env_impl"
|
||||
)
|
||||
|
||||
# Define the list of Fortran module files for which it is
|
||||
# sufficient to generate the module file via -fsyntax-only.
|
||||
set(MODULES_WITHOUT_IMPLEMENTATION
|
||||
"__fortran_builtins"
|
||||
"__fortran_ieee_exceptions"
|
||||
"__fortran_type_info"
|
||||
@@ -20,6 +29,12 @@ set(MODULES
|
||||
"iso_fortran_env"
|
||||
)
|
||||
|
||||
set(MODULES ${MODULES_WITH_IMPLEMENTATION} ${MODULES_WITHOUT_IMPLEMENTATION})
|
||||
|
||||
# Init variable to hold extra object files coming from the Fortran modules;
|
||||
# these module files will be contributed from the CMakeLists in flang/tools/f18.
|
||||
set(module_objects "")
|
||||
|
||||
# Create module files directly from the top-level module source directory.
|
||||
# If CMAKE_CROSSCOMPILING, then the newly built flang-new executable was
|
||||
# cross compiled, and thus can't be executed on the build system and thus
|
||||
@@ -41,6 +56,9 @@ if (NOT CMAKE_CROSSCOMPILING)
|
||||
if(NOT ${filename} STREQUAL "__fortran_type_info")
|
||||
set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_type_info.mod)
|
||||
endif()
|
||||
if(${filename} STREQUAL "iso_fortran_env")
|
||||
set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/iso_fortran_env_impl.mod)
|
||||
endif()
|
||||
if(${filename} STREQUAL "ieee_arithmetic" OR
|
||||
${filename} STREQUAL "ieee_exceptions")
|
||||
set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_ieee_exceptions.mod)
|
||||
@@ -58,18 +76,41 @@ if (NOT CMAKE_CROSSCOMPILING)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
# Some modules have an implementation part that needs to be added to the
|
||||
# FortranRuntime library.
|
||||
set(compile_with "-fsyntax-only")
|
||||
set(object_output "")
|
||||
set(include_in_link FALSE)
|
||||
if(${filename} IN_LIST MODULES_WITH_IMPLEMENTATION)
|
||||
set(object_output "${CMAKE_CURRENT_BINARY_DIR}/${filename}${CMAKE_CXX_OUTPUT_EXTENSION}")
|
||||
set(compile_with -c -o ${object_output})
|
||||
set(include_in_link TRUE)
|
||||
endif()
|
||||
|
||||
set(base ${FLANG_INTRINSIC_MODULES_DIR}/${filename})
|
||||
# TODO: We may need to flag this with conditional, in case Flang is built w/o OpenMP support
|
||||
add_custom_command(OUTPUT ${base}.mod
|
||||
add_custom_command(OUTPUT ${base}.mod ${object_output}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR}
|
||||
COMMAND flang-new ${opts} -cpp -fsyntax-only -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
|
||||
COMMAND flang-new ${opts} -cpp ${compile_with} -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
|
||||
${FLANG_SOURCE_DIR}/module/${filename}.f90
|
||||
DEPENDS flang-new ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${FLANG_SOURCE_DIR}/module/__fortran_builtins.f90 ${depends}
|
||||
)
|
||||
list(APPEND MODULE_FILES ${base}.mod)
|
||||
install(FILES ${base}.mod DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang")
|
||||
|
||||
# If a module has been compiled into an object file, add the file to
|
||||
# the link line for the FortranRuntime library.
|
||||
if(include_in_link)
|
||||
list(APPEND module_objects ${object_output})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Set a CACHE variable that is visible to the CMakeLists.txt in runtime/, so that
|
||||
# the compiled Fortran modules can be added to the link line of the FortranRuntime
|
||||
# library.
|
||||
set(FORTRAN_MODULE_OBJECTS ${module_objects} CACHE INTERNAL "" FORCE)
|
||||
|
||||
# Special case for omp_lib.mod, because its source comes from openmp/runtime/src/include.
|
||||
# It also produces two module files: omp_lib.mod and omp_lib_kinds.mod. Compile these
|
||||
# files only if OpenMP support has been configured.
|
||||
|
||||
@@ -14,13 +14,6 @@ set( LLVM_LINK_COMPONENTS
|
||||
add_flang_tool(flang-new
|
||||
driver.cpp
|
||||
fc1_main.cpp
|
||||
|
||||
DEPENDS
|
||||
# These libraries are used in the linker invocation generated by the driver
|
||||
# (i.e. when constructing the linker job). Without them the driver would be
|
||||
# unable to generate executables.
|
||||
FortranRuntime
|
||||
FortranDecimal
|
||||
)
|
||||
|
||||
target_link_libraries(flang-new
|
||||
|
||||
Reference in New Issue
Block a user