[flang-commits] [flang] [llvm] [flang-rt] Remove dependency on flang and implement iso file in C++ (PR #197687)

Joseph Huber via flang-commits flang-commits at lists.llvm.org
Thu May 14 07:00:50 PDT 2026


https://github.com/jhuber6 created https://github.com/llvm/llvm-project/pull/197687

Summary:
Right now we have a very heavy dependency on `flang` for a single module
file. The flang build will handle creating the actual module file, we
just need to export the symbols. This PR ports the source file from the
flang .f90 to equivalent C++. This allows us to build `flang-rt`
standalone without bringing in the entire flang infrastructure, which is
by far the heaviest build in the entire LLVM project.

I verified the symbols and values against a previous build, so they are
identical.


>From 1dae0b5b2055c0e913d78ef4a48263c95e9baa98 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Thu, 14 May 2026 08:56:32 -0500
Subject: [PATCH] [flang-rt] Remove dependency on flang and implement iso file
 in C++

Summary:
Right now we have a very heavy dependency on `flang` for a single module
file. The flang build will handle creating the actual module file, we
just need to export the symbols. This PR ports the source file from the
flang .f90 to equivalent C++. This allows us to build `flang-rt`
standalone without bringing in the entire flang infrastructure, which is
by far the heaviest build in the entire LLVM project.

I verified the symbols and values against a previous build, so they are
identical.
---
 flang-rt/CMakeLists.txt                       |  34 --
 flang-rt/README.md                            |  22 +-
 flang-rt/lib/runtime/CMakeLists.txt           |  15 +-
 flang-rt/lib/runtime/iso_fortran_env_impl.cpp | 308 ++++++++++++++++++
 flang/module/iso_fortran_env_impl.f90         |   5 +-
 runtimes/CMakeLists.txt                       |   9 +-
 runtimes/cmake/config-Fortran.cmake           |  25 +-
 7 files changed, 334 insertions(+), 84 deletions(-)
 create mode 100644 flang-rt/lib/runtime/iso_fortran_env_impl.cpp

diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index cd1fc8cfbcff9..e875d11cd349e 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -23,40 +23,6 @@ set(FLANG_RT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
 set(FLANG_RT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
 set(FLANG_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../flang")
 
-# CMake 3.24 is the first version of CMake that directly recognizes Flang.
-# LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang.
-if (CMAKE_VERSION VERSION_LESS "3.24")
-  cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
-  if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
-    include(CMakeForceCompiler)
-    CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
-
-    set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
-    set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
-
-    set(CMAKE_Fortran_SUBMODULE_SEP "-")
-    set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
-
-    set(CMAKE_Fortran_PREPROCESS_SOURCE
-      "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
-
-    set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
-    set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
-
-    set(CMAKE_Fortran_MODDIR_FLAG "-module-dir")
-
-    set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
-    set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
-    set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
-
-    set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
-
-    set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
-    set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
-  endif ()
-endif ()
-enable_language(Fortran)
-
 # Try to include the RPC utilities from the `libc` project for GPU I/O support.
 include(FindLibcCommonUtils)
 
diff --git a/flang-rt/README.md b/flang-rt/README.md
index 68bc9c9f60574..8b88a3bab4761 100644
--- a/flang-rt/README.md
+++ b/flang-rt/README.md
@@ -81,12 +81,10 @@ $ ninja install
 ### Standalone Runtimes Build
 
 Instead of building Clang and Flang from scratch, the standalone Runtime build
-uses CMake's environment introspection to find a C, C++, and Fortran compiler.
+uses CMake's environment introspection to find a C and C++ compiler.
 The compiler to be used can be controlled using CMake's standard mechanisms such
-as `CMAKE_CXX_COMPILER`, `CMAKE_CXX_COMPILER`, and `CMAKE_Fortran_COMPILER`.
-`CMAKE_Fortran_COMPILER` must be `flang` built from the same Git commit as
-Flang-RT to ensure they are using the same ABI. The C and C++ compiler
-can be any compiler supporting the same ABI.
+as `CMAKE_C_COMPILER` and `CMAKE_CXX_COMPILER`. The C and C++ compiler
+can be any compiler supporting the same ABI. A Fortran compiler is not required.
 
 In addition to the compiler, the build must be able to find LLVM development
 tools such as `lit` and `FileCheck` that are not found in an LLVM's install
@@ -99,19 +97,13 @@ having two conflicting versions of the same library.
 A simple build configuration might look like the following:
 
 ```bash
-cmake -S <path-to-llvm-project-source>/runtimes              \
-  -GNinja                                                    \
-  -DLLVM_BINARY_DIR=<path-to-llvm-builddir>                  \
-  -DCMAKE_Fortran_COMPILER=<path-to-llvm-builddir>/bin/flang \
-  -DCMAKE_Fortran_COMPILER_WORKS=yes                         \
-  -DLLVM_ENABLE_RUNTIMES=flang-rt                            \
+cmake -S <path-to-llvm-project-source>/runtimes \
+  -GNinja                                       \
+  -DLLVM_BINARY_DIR=<path-to-llvm-builddir>     \
+  -DLLVM_ENABLE_RUNTIMES=flang-rt               \
   ...
 ```
 
-The `CMAKE_Fortran_COMPILER_WORKS` parameter must be set because otherwise CMake
-will test whether the Fortran compiler can compile and link programs which will
-obviously fail without a runtime library available yet.
-
 Building Flang-RT for cross-compilation triple, the target triple can be
 selected using `LLVM_DEFAULT_TARGET_TRIPLE`. Of course, Flang-RT can be built
 multiple times with different build configurations, but have to be located
diff --git a/flang-rt/lib/runtime/CMakeLists.txt b/flang-rt/lib/runtime/CMakeLists.txt
index cc5d88e985329..1169fefe7ce9a 100644
--- a/flang-rt/lib/runtime/CMakeLists.txt
+++ b/flang-rt/lib/runtime/CMakeLists.txt
@@ -75,7 +75,7 @@ set(supported_sources
 
 # List of source not used for GPU offloading.
 set(host_sources
-  ${FLANG_SOURCE_DIR}/module/iso_fortran_env_impl.f90
+  iso_fortran_env_impl.cpp
   command.cpp
   complex-powi.cpp
   complex-reduction.c
@@ -233,13 +233,6 @@ else()
         )
     endif ()
 
-    # Setting an unique Fortran_MODULE_DIRECTORY is required for each variant to
-    # write a different .mod file.
-    set_target_properties(${name}
-        PROPERTIES
-          Fortran_MODULE_DIRECTORY "module.${suffix}"
-      )
-
     enable_cuda_compilation(${name} "${supported_sources}")
     add_dependencies(flang_rt.runtime ${name})
   endfunction ()
@@ -251,10 +244,8 @@ else()
   # FIXME: Generating actual runtime DLLs is currently not possible. There are
   # two roadblocks:
   #
-  #  * Flang emits /DEFAULTLIB:flang_rt.dynamic.lib into
-  #    iso_fortran_env_impl.f90.obj. Because that file is itself part of
-  #    flang_rt.dynamic, this results in a recursive dependency when invoking
-  #    the linker.
+  #  * iso_fortran_env_impl.cpp.obj is itself part of flang_rt.dynamic,
+  #    which can result in a recursive dependency when invoking the linker.
   #
   #  * The externally-visible functions must either be annotated with
   #    __declspec(dllexport), or listed in an exports file. A possible workaround
diff --git a/flang-rt/lib/runtime/iso_fortran_env_impl.cpp b/flang-rt/lib/runtime/iso_fortran_env_impl.cpp
new file mode 100644
index 0000000000000..6f8e046b22d34
--- /dev/null
+++ b/flang-rt/lib/runtime/iso_fortran_env_impl.cpp
@@ -0,0 +1,308 @@
+//===-- lib/runtime/iso_fortran_env_impl.cpp --------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides linkable symbols for the iso_fortran_env_impl module constants. It
+// replaces the Fortran source (flang/module/iso_fortran_env_impl.f90) to remove
+// the runtime library's build dependency on the Fortran compiler.
+//
+// The values here must stay in sync with the Fortran module source which
+// generates the .mod file during the flang compiler build.
+//
+// Symbol naming follows Flang's module variable mangling:
+//   _QM<module_name>EC<constant_name>
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Common/float128.h"
+#include "flang/Common/real.h"
+#include <cstdint>
+
+// Real kind 10 (x87 extended) is only available on x86-64.
+#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
+#define FLANG_RT_HAS_REAL_10 1
+#else
+#define FLANG_RT_HAS_REAL_10 0
+#endif
+
+// Real kind 16 (IEEE quad) requires a float128 runtime math library.
+// Must match the logic in flang/include/flang/Tools/TargetSetup.h.
+#if defined(FLANG_RUNTIME_F128_MATH_LIB) || HAS_LDBL128
+#define FLANG_RT_HAS_REAL_16 1
+#else
+#define FLANG_RT_HAS_REAL_16 0
+#endif
+
+// Fortran merge(tsource, fsource, mask) to match the source module style.
+static constexpr std::int32_t Merge(
+    std::int32_t tsource, std::int32_t fsource, bool mask) {
+  return mask ? tsource : fsource;
+}
+
+// Fortran selected_int_kind(R) returns the smallest integer kind with range >=
+// R digits. Flang integer kinds and their decimal ranges are fixed.
+static constexpr std::int32_t SelectedIntKind(int range) {
+  struct {
+    int kind, range;
+  } constexpr intKinds[]{{1, 2}, {2, 4}, {4, 9}, {8, 18}, {16, 38}};
+  for (auto [k, r] : intKinds) {
+    if (r >= range)
+      return k;
+  }
+  return -1;
+}
+
+// Fortran selected_real_kind(P, R) returns the smallest real kind with decimal
+// precision >= P and decimal range >= R. Returns negative per Fortran
+// 2023 16.9.170 when no kind qualifies.
+static constexpr std::int32_t SelectedRealKind(int p, int r) {
+  constexpr int realKinds[]{
+      2,
+      3,
+      4,
+      8,
+#if FLANG_RT_HAS_REAL_10
+      10,
+#endif
+#if FLANG_RT_HAS_REAL_16
+      16,
+#endif
+  };
+  for (int k : realKinds) {
+    Fortran::common::RealCharacteristics rc{
+        Fortran::common::PrecisionOfRealKind(k)};
+    if (rc.decimalPrecision >= p && rc.decimalRange >= r)
+      return k;
+  }
+  bool pOK{false}, rOK{false};
+  for (int k : realKinds) {
+    Fortran::common::RealCharacteristics rc{
+        Fortran::common::PrecisionOfRealKind(k)};
+    if (rc.decimalPrecision >= p)
+      pOK = true;
+    if (rc.decimalRange >= r)
+      rOK = true;
+  }
+  if (pOK)
+    return rOK ? -4 : -2;
+  return rOK ? -1 : -3;
+}
+
+// Fortran digits() for integer kind K returns 8*K - 1 (excludes sign bit).
+static constexpr int IntDigits(int kind) { return 8 * kind - 1; }
+
+// Fortran digits() for unsigned kind K returns 8*K (no sign bit).
+static constexpr int UintDigits(int kind) { return 8 * kind; }
+
+// Fortran digits() for real kind K returns the binary precision.
+static constexpr int RealDigits(int kind) {
+  return Fortran::common::PrecisionOfRealKind(kind);
+}
+
+// The smallest valid real kind, used as a safe fallback when a selected
+// real kind is unavailable (so digits() can be called without error).
+static constexpr std::int32_t safeRealFallback{SelectedRealKind(0, 0)};
+
+// Integer kinds, selected -> safe -> validated.
+static constexpr std::int32_t selectedInt8{SelectedIntKind(2)};
+static constexpr std::int32_t selectedInt16{SelectedIntKind(4)};
+static constexpr std::int32_t selectedInt32{SelectedIntKind(9)};
+static constexpr std::int32_t selectedInt64{SelectedIntKind(18)};
+static constexpr std::int32_t selectedInt128{SelectedIntKind(38)};
+
+static constexpr std::int32_t safeInt8{
+    Merge(selectedInt8, SelectedIntKind(0), selectedInt8 >= 0)};
+static constexpr std::int32_t safeInt16{
+    Merge(selectedInt16, SelectedIntKind(0), selectedInt16 >= 0)};
+static constexpr std::int32_t safeInt32{
+    Merge(selectedInt32, SelectedIntKind(0), selectedInt32 >= 0)};
+static constexpr std::int32_t safeInt64{
+    Merge(selectedInt64, SelectedIntKind(0), selectedInt64 >= 0)};
+static constexpr std::int32_t safeInt128{
+    Merge(selectedInt128, SelectedIntKind(0), selectedInt128 >= 0)};
+
+static constexpr std::int32_t int8{Merge(
+    selectedInt8, Merge(-2, -1, selectedInt8 >= 0), IntDigits(safeInt8) == 7)};
+static constexpr std::int32_t int16{Merge(selectedInt16,
+    Merge(-2, -1, selectedInt16 >= 0), IntDigits(safeInt16) == 15)};
+static constexpr std::int32_t int32{Merge(selectedInt32,
+    Merge(-2, -1, selectedInt32 >= 0), IntDigits(safeInt32) == 31)};
+static constexpr std::int32_t int64{Merge(selectedInt64,
+    Merge(-2, -1, selectedInt64 >= 0), IntDigits(safeInt64) == 63)};
+static constexpr std::int32_t int128{Merge(selectedInt128,
+    Merge(-2, -1, selectedInt128 >= 0), IntDigits(safeInt128) == 127)};
+
+// Unsigned kinds, same selection as integer, validated with unsigned digits.
+static constexpr std::int32_t selectedUInt8{selectedInt8};
+static constexpr std::int32_t selectedUInt16{selectedInt16};
+static constexpr std::int32_t selectedUInt32{selectedInt32};
+static constexpr std::int32_t selectedUInt64{selectedInt64};
+static constexpr std::int32_t selectedUInt128{selectedInt128};
+
+static constexpr std::int32_t safeUInt8{safeInt8};
+static constexpr std::int32_t safeUInt16{safeInt16};
+static constexpr std::int32_t safeUInt32{safeInt32};
+static constexpr std::int32_t safeUInt64{safeInt64};
+static constexpr std::int32_t safeUInt128{safeInt128};
+
+static constexpr std::int32_t uint8{Merge(selectedUInt8,
+    Merge(-2, -1, selectedUInt8 >= 0), UintDigits(safeUInt8) == 8)};
+static constexpr std::int32_t uint16{Merge(selectedUInt16,
+    Merge(-2, -1, selectedUInt16 >= 0), UintDigits(safeUInt16) == 16)};
+static constexpr std::int32_t uint32{Merge(selectedUInt32,
+    Merge(-2, -1, selectedUInt32 >= 0), UintDigits(safeUInt32) == 32)};
+static constexpr std::int32_t uint64{Merge(selectedUInt64,
+    Merge(-2, -1, selectedUInt64 >= 0), UintDigits(safeUInt64) == 64)};
+static constexpr std::int32_t uint128{Merge(selectedUInt128,
+    Merge(-2, -1, selectedUInt128 >= 0), UintDigits(safeUInt128) == 128)};
+
+// Logical kinds mirror integer kinds.
+static constexpr std::int32_t logical8{int8};
+static constexpr std::int32_t logical16{int16};
+static constexpr std::int32_t logical32{int32};
+static constexpr std::int32_t logical64{int64};
+
+// Real kinds, selected -> safe -> validated.
+static constexpr std::int32_t selectedReal16{SelectedRealKind(3, 4)};
+static constexpr std::int32_t selectedBfloat16{SelectedRealKind(2, 37)};
+static constexpr std::int32_t selectedReal32{SelectedRealKind(6, 37)};
+static constexpr std::int32_t selectedReal64{SelectedRealKind(15, 307)};
+static constexpr std::int32_t selectedReal80{SelectedRealKind(18, 4931)};
+static constexpr std::int32_t selectedReal64x2{SelectedRealKind(31, 307)};
+static constexpr std::int32_t selectedReal128{SelectedRealKind(33, 4931)};
+
+static constexpr std::int32_t safeReal16{
+    Merge(selectedReal16, safeRealFallback, selectedReal16 >= 0)};
+static constexpr std::int32_t safeBfloat16{
+    Merge(selectedBfloat16, safeRealFallback, selectedBfloat16 >= 0)};
+static constexpr std::int32_t safeReal32{
+    Merge(selectedReal32, safeRealFallback, selectedReal32 >= 0)};
+static constexpr std::int32_t safeReal64{
+    Merge(selectedReal64, safeRealFallback, selectedReal64 >= 0)};
+static constexpr std::int32_t safeReal80{
+    Merge(selectedReal80, safeRealFallback, selectedReal80 >= 0)};
+static constexpr std::int32_t safeReal64x2{
+    Merge(selectedReal64x2, safeRealFallback, selectedReal64x2 >= 0)};
+static constexpr std::int32_t safeReal128{
+    Merge(selectedReal128, safeRealFallback, selectedReal128 >= 0)};
+
+static constexpr std::int32_t real16{Merge(selectedReal16,
+    Merge(-2, -1, selectedReal16 >= 0), RealDigits(safeReal16) == 11)};
+static constexpr std::int32_t bfloat16{Merge(selectedBfloat16,
+    Merge(-2, -1, selectedBfloat16 >= 0), RealDigits(safeBfloat16) == 8)};
+static constexpr std::int32_t real32{Merge(selectedReal32,
+    Merge(-2, -1, selectedReal32 >= 0), RealDigits(safeReal32) == 24)};
+static constexpr std::int32_t real64{Merge(selectedReal64,
+    Merge(-2, -1, selectedReal64 >= 0), RealDigits(safeReal64) == 53)};
+static constexpr std::int32_t real80{Merge(selectedReal80,
+    Merge(-2, -1, selectedReal80 >= 0), RealDigits(safeReal80) == 64)};
+static constexpr std::int32_t real64x2{Merge(selectedReal64x2,
+    Merge(-2, -1, selectedReal64x2 >= 0), RealDigits(safeReal64x2) == 106)};
+static constexpr std::int32_t real128{Merge(selectedReal128,
+    Merge(-2, -1, selectedReal128 >= 0), RealDigits(safeReal128) == 113)};
+
+// Exported symbols with Flang module-variable mangling.
+#define FORTRAN_NAMED_CONST(name) _QMiso_fortran_env_implEC##name
+
+extern "C" {
+
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedint8){selectedInt8};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedint16){selectedInt16};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedint32){selectedInt32};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedint64){selectedInt64};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedint128){selectedInt128};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(safeint8){safeInt8};
+extern const std::int32_t FORTRAN_NAMED_CONST(safeint16){safeInt16};
+extern const std::int32_t FORTRAN_NAMED_CONST(safeint32){safeInt32};
+extern const std::int32_t FORTRAN_NAMED_CONST(safeint64){safeInt64};
+extern const std::int32_t FORTRAN_NAMED_CONST(safeint128){safeInt128};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(int8){int8};
+extern const std::int32_t FORTRAN_NAMED_CONST(int16){int16};
+extern const std::int32_t FORTRAN_NAMED_CONST(int32){int32};
+extern const std::int32_t FORTRAN_NAMED_CONST(int64){int64};
+extern const std::int32_t FORTRAN_NAMED_CONST(int128){int128};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(selecteduint8){selectedUInt8};
+extern const std::int32_t FORTRAN_NAMED_CONST(selecteduint16){selectedUInt16};
+extern const std::int32_t FORTRAN_NAMED_CONST(selecteduint32){selectedUInt32};
+extern const std::int32_t FORTRAN_NAMED_CONST(selecteduint64){selectedUInt64};
+extern const std::int32_t FORTRAN_NAMED_CONST(selecteduint128){selectedUInt128};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(safeuint8){safeUInt8};
+extern const std::int32_t FORTRAN_NAMED_CONST(safeuint16){safeUInt16};
+extern const std::int32_t FORTRAN_NAMED_CONST(safeuint32){safeUInt32};
+extern const std::int32_t FORTRAN_NAMED_CONST(safeuint64){safeUInt64};
+extern const std::int32_t FORTRAN_NAMED_CONST(safeuint128){safeUInt128};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(uint8){uint8};
+extern const std::int32_t FORTRAN_NAMED_CONST(uint16){uint16};
+extern const std::int32_t FORTRAN_NAMED_CONST(uint32){uint32};
+extern const std::int32_t FORTRAN_NAMED_CONST(uint64){uint64};
+extern const std::int32_t FORTRAN_NAMED_CONST(uint128){uint128};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(logical8){logical8};
+extern const std::int32_t FORTRAN_NAMED_CONST(logical16){logical16};
+extern const std::int32_t FORTRAN_NAMED_CONST(logical32){logical32};
+extern const std::int32_t FORTRAN_NAMED_CONST(logical64){logical64};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedreal16){selectedReal16};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedbfloat16){
+    selectedBfloat16};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedreal32){selectedReal32};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedreal64){selectedReal64};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedreal80){selectedReal80};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedreal64x2){
+    selectedReal64x2};
+extern const std::int32_t FORTRAN_NAMED_CONST(selectedreal128){selectedReal128};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(safereal16){safeReal16};
+extern const std::int32_t FORTRAN_NAMED_CONST(safebfloat16){safeBfloat16};
+extern const std::int32_t FORTRAN_NAMED_CONST(safereal32){safeReal32};
+extern const std::int32_t FORTRAN_NAMED_CONST(safereal64){safeReal64};
+extern const std::int32_t FORTRAN_NAMED_CONST(safereal80){safeReal80};
+extern const std::int32_t FORTRAN_NAMED_CONST(safereal64x2){safeReal64x2};
+extern const std::int32_t FORTRAN_NAMED_CONST(safereal128){safeReal128};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(real16){real16};
+extern const std::int32_t FORTRAN_NAMED_CONST(bfloat16){bfloat16};
+extern const std::int32_t FORTRAN_NAMED_CONST(real32){real32};
+extern const std::int32_t FORTRAN_NAMED_CONST(real64){real64};
+extern const std::int32_t FORTRAN_NAMED_CONST(real80){real80};
+extern const std::int32_t FORTRAN_NAMED_CONST(real64x2){real64x2};
+extern const std::int32_t FORTRAN_NAMED_CONST(real128){real128};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(__builtin_integer_kinds)[]{
+    1,
+    2,
+    4,
+    8,
+    16,
+};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(__builtin_logical_kinds)[]{
+    1,
+    2,
+    4,
+    8,
+};
+
+extern const std::int32_t FORTRAN_NAMED_CONST(__builtin_real_kinds)[]{
+    2,
+    3,
+    4,
+    8,
+#if FLANG_RT_HAS_REAL_10
+    10,
+#endif
+#if FLANG_RT_HAS_REAL_16
+    16,
+#endif
+};
+
+} // extern "C"
diff --git a/flang/module/iso_fortran_env_impl.f90 b/flang/module/iso_fortran_env_impl.f90
index 5408e7de37001..d0726e621bbd1 100644
--- a/flang/module/iso_fortran_env_impl.f90
+++ b/flang/module/iso_fortran_env_impl.f90
@@ -1,4 +1,4 @@
-!===-- module/iso_fortran_env_impl.f90 --=--------------------------------===!
+!===-- 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.
@@ -9,6 +9,9 @@
 ! This MODULE implements part of the ISO_FORTRAN_ENV module file, which
 ! partially requires linkable symbols for some entities defined
 ! (e.g., real_kinds).
+!
+! The runtime symbols are in flang-rt/lib/runtime/iso_fortran_env_impl.cpp and
+! must be kept up-to-date.
 
 module iso_fortran_env_impl
   implicit none
diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index fd4230b15f72e..da3360d47081c 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -272,15 +272,14 @@ cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_LIB_PATH)
 
 # Code for Fortran support.
 #
-# Currently, only flang-rt and openmp contain Fortran sources. We assume that
-# none of the public CMake variables defined in config-Fortran are used unless
-# we enable one of these runtimes. Other runtimes would make used of undefined
-# variables.
+# Currently, only openmp contains Fortran sources. We assume that none of the
+# public CMake variables defined in config-Fortran are used unless we enable one
+# of these runtimes. Other runtimes would make use of undefined variables.
 #
 # config-Fortran.cmake makes use of
 # RUNTIMES_OUTPUT_RESOURCE_DIR, RUNTIMES_INSTALL_RESOURCE_PATH,
 # hence must be included after those variables are defined.
-if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES OR "openmp" IN_LIST LLVM_ENABLE_RUNTIMES)
+if ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES)
   include(config-Fortran)
 endif ()
 
diff --git a/runtimes/cmake/config-Fortran.cmake b/runtimes/cmake/config-Fortran.cmake
index f5cea1fc67e29..f03fd75df5877 100644
--- a/runtimes/cmake/config-Fortran.cmake
+++ b/runtimes/cmake/config-Fortran.cmake
@@ -154,25 +154,16 @@ if (CMAKE_Fortran_COMPILER)
   enable_language(Fortran)
   include(CheckFortranSourceCompiles)
 
-  if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
-    # In a bootstrapping build (or any runtimes-build that includes flang-rt),
-    # the intrinsic modules are not built yet. Targets can depend on
-    # flang-rt-mod to ensure that flang-rt's modules are built first.
-    list(APPEND RUNTIMES_FORTRAN_BUILD_DEPS flang-rt-mod)
+  # Check whether building modules works, avoid causing the entire build to
+  # fail because of Fortran. The primary situation we want to support here
+  # is Flang, or its intrinsic modules were built separately in a
+  # non-bootstrapping build.
+  check_fortran_builtins_available()
+  if (HAVE_FORTRAN_INTRINSIC_MODS)
     set(RUNTIMES_ENABLE_FORTRAN ON)
-    message(STATUS "Fortran support enabled using just-built Flang-RT builtin modules")
+    message(STATUS "Fortran support enabled using compiler's own modules")
   else ()
-    # Check whether building modules works, avoid causing the entire build to
-    # fail because of Fortran. The primary situation we want to support here
-    # is Flang, or its intrinsic modules were built separately in a
-    # non-bootstrapping build.
-    check_fortran_builtins_available()
-    if (HAVE_FORTRAN_INTRINSIC_MODS)
-      set(RUNTIMES_ENABLE_FORTRAN ON)
-      message(STATUS "Fortran support enabled using compiler's own modules")
-    else ()
-      message(STATUS "Fortran support disabled: Not passing smoke check")
-    endif ()
+    message(STATUS "Fortran support disabled: Not passing smoke check")
   endif ()
 else ()
   message(STATUS "Fortran support disabled: not enabled in CMake; Use CMAKE_Fortran_COMPILER_WORKS=yes if the issues is missing builtin modules")



More information about the flang-commits mailing list