diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index cbe8f1186236a4..070c39eb6e9ab4 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -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} ) + diff --git a/flang/module/iso_fortran_env.f90 b/flang/module/iso_fortran_env.f90 index 6ca98e518aeac5..cc1f58e7feccb5 100644 --- a/flang/module/iso_fortran_env.f90 +++ b/flang/module/iso_fortran_env.f90 @@ -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) - - 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 :: selectedInt8, selectedInt16, selectedInt32, selectedInt64, selectedInt128, & + safeInt8, safeInt16, safeInt32, safeInt64, safeInt128, & + int8, int16, int32, int64, int128 - 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 :: logical8, logical16, logical32, logical64 - 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 :: selectedReal16, selectedBfloat16, selectedReal32, & + selectedReal64, selectedReal80, selectedReal64x2, & + selectedReal128, & + safeReal16, safeBfloat16, safeReal32, & + safeReal64, safeReal80, safeReal64x2, & + safeReal128, & + real16, bfloat16, real32, real64, & + real80, real64x2, real128 + + public :: integer_kinds, real_kinds, logical_kinds integer, parameter, public :: current_team = -1, & initial_team = -2, & diff --git a/flang/module/iso_fortran_env_impl.f90 b/flang/module/iso_fortran_env_impl.f90 new file mode 100644 index 00000000000000..4de54dda7bab1c --- /dev/null +++ b/flang/module/iso_fortran_env_impl.f90 @@ -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 diff --git a/flang/runtime/CMakeLists.txt b/flang/runtime/CMakeLists.txt index a826980e194114..8588af7e16eeca 100644 --- a/flang/runtime/CMakeLists.txt +++ b/flang/runtime/CMakeLists.txt @@ -169,6 +169,7 @@ set(sources unit-map.cpp unit.cpp utf.cpp + ${FORTRAN_MODULE_OBJECTS} ) include(AddFlangOffloadRuntime) diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt index 47711996516020..cec4e2d8107206 100644 --- a/flang/tools/f18/CMakeLists.txt +++ b/flang/tools/f18/CMakeLists.txt @@ -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. diff --git a/flang/tools/flang-driver/CMakeLists.txt b/flang/tools/flang-driver/CMakeLists.txt index ce30ecff028dcf..9f33cdfe3fa90f 100644 --- a/flang/tools/flang-driver/CMakeLists.txt +++ b/flang/tools/flang-driver/CMakeLists.txt @@ -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