[flang-commits] [flang] [flang][runtime] Build ISO_FORTRAN_ENV to export kind arrays as linkable symbols (PR #95388)

Michael Klemm via flang-commits flang-commits at lists.llvm.org
Thu Jun 13 03:46:50 PDT 2024


https://github.com/mjklemm created https://github.com/llvm/llvm-project/pull/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 

>From 5c864eed944ec825aeee64ab912316cd0e1b3ed9 Mon Sep 17 00:00:00 2001
From: Michael Klemm <michael.klemm at amd.com>
Date: Thu, 13 Jun 2024 12:42:58 +0200
Subject: [PATCH] Fixes #89403

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.
---
 flang/CMakeLists.txt                     |   1 +
 flang/module/__fortran_builtin_kinds.f90 | 110 +++++++++++++++++++++
 flang/module/iso_fortran_env.f90         | 118 ++++++-----------------
 flang/runtime/CMakeLists.txt             |   1 +
 flang/tools/f18/CMakeLists.txt           |  42 +++++++-
 flang/tools/flang-driver/CMakeLists.txt  |   2 -
 6 files changed, 182 insertions(+), 92 deletions(-)
 create mode 100644 flang/module/__fortran_builtin_kinds.f90

diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt
index cbe8f1186236a..070c39eb6e9ab 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/__fortran_builtin_kinds.f90 b/flang/module/__fortran_builtin_kinds.f90
new file mode 100644
index 0000000000000..189055dc26c0c
--- /dev/null
+++ b/flang/module/__fortran_builtin_kinds.f90
@@ -0,0 +1,110 @@
+!===-- module/__fortran_bultin_kinds.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
+!
+!===------------------------------------------------------------------------===!
+
+module __fortran_builtin_kinds
+  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 __fortran_builtin_kinds
\ No newline at end of file
diff --git a/flang/module/iso_fortran_env.f90 b/flang/module/iso_fortran_env.f90
index 6ca98e518aeac..f751ba03f7bac 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 __fortran_builtin_kinds, 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/runtime/CMakeLists.txt b/flang/runtime/CMakeLists.txt
index a826980e19411..c3bec4043e760 100644
--- a/flang/runtime/CMakeLists.txt
+++ b/flang/runtime/CMakeLists.txt
@@ -260,6 +260,7 @@ if (NOT DEFINED MSVC)
 
     INSTALL_WITH_TOOLCHAIN
   )
+  target_link_libraries(FortranRuntime PRIVATE ${FORTRAN_MODULE_OBJECTS})
 else()
   add_flang_library(FortranRuntime
     ${sources}
diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt
index 4771199651602..5f4c49e42c36e 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
+  "__fortran_builtin_kinds"
+)
+
+# 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.
+unset(FORTRAN_MODULE_OBJECTS CACHE)
+
 # 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}/__fortran_builtin_kinds.mod)
+      endif()
       if(${filename} STREQUAL "ieee_arithmetic" OR
          ${filename} STREQUAL "ieee_exceptions")
         set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_ieee_exceptions.mod)
@@ -58,16 +76,34 @@ 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(compile_with "-c")
+      set(object_output "${CMAKE_CURRENT_BINARY_DIR}/${filename}${CMAKE_CXX_OUTPUT_EXTENSION}")
+      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)
+      set(FORTRAN_MODULE_OBJECTS "${FORTRAN_MODULE_OBJECTS}" "${object_output}" CACHE INTERNAL "")
+    endif()
   endforeach()
 
   # Special case for omp_lib.mod, because its source comes from openmp/runtime/src/include.
diff --git a/flang/tools/flang-driver/CMakeLists.txt b/flang/tools/flang-driver/CMakeLists.txt
index ce30ecff028dc..5bf535b18ad78 100644
--- a/flang/tools/flang-driver/CMakeLists.txt
+++ b/flang/tools/flang-driver/CMakeLists.txt
@@ -19,8 +19,6 @@ add_flang_tool(flang-new
   # 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



More information about the flang-commits mailing list