Skip to content

Conversation

@Meinersbur
Copy link
Member

Reapplication of #137828 and #169638

Move building the .mod files from openmp/flang to openmp/flang-rt using a shared mechanism. Motivations to do so are:

  1. Most modules are target-dependent and need to be re-compiled for each target separately, which is something the LLVM_ENABLE_RUNTIMES system already does. Prime example is iso_c_binding.mod which encodes the target's ABI. Constants such as c_long_double also have different values. Most other modules have #ifdef-enclosed code as well. For instance this caused offload targets nvptx64-nvidia-cuda/amdgpu-amd-amdhsa to use the modules files compiled for the host which may contrain uses of the types REAL(10) or REAL(16) not available for nvptx/amdgpu.

#146876
#128015
#129742
#158790

  1. CMake has support for Fortran that we should use. Among other things, it automatically determines module dependencies so there is no need to hardcode them in the CMakeLists.txt.

  2. It allows using Fortran itself to implement Flang-RT. Currently, only iso_fortran_env_impl.f90 emits object files that are needed by Fortran applications ([flang] Linker for non-constant accesses to kind arrays (integer_kind, logical_kind, real_kind) #89403). The workaround of [flang][runtime] Build ISO_FORTRAN_ENV to export kind arrays as linkable symbols #95388 could be reverted (PR [Flang-RT] Remerge iso_fortran_env and iso_fortran_env_impl #169525).

If using Flang for cross-compilation or target-offloading, flang-rt must now be compiled for each target not only for the library, but also to get the target-specific module files. For instance in a bootstrapping runtime build, this can be done by adding: -DLLVM_RUNTIME_TARGETS=default;nvptx64-nvidia-cuda;amdgpu-amd-amdhsa.

Some new dependencies come into play:

  • openmp depends on flang-rt for building lib_omp.mod and lib_omp_kinds.mod. Currently, if flang-rt is not found then the modules are not built.
  • check-flang depends on flang-rt: If not found, the majority of tests are disabled. If not building in a bootstrpping build, the location of the module files can be pointed to using -DFLANG_INTRINSIC_MODULES_DIR=<path>, e.g. in a flang-standalone build. Alternatively, the test needing any of the intrinsic modules could be marked with REQUIRES: flangrt-modules.
  • check-flang depends on openmp: Not a change; tests requiring lib_omp.mod and lib_omp_kinds.mod those are already marked with openmp_runtime.

As intrinsic are now specific to the target, their location is moved from include/flang to <resource-dir>/finclude/flang/<triple>. The mechnism to compute the location have been moved from flang-rt (previously used to compute the location of libflang_rt.*.a) to common locations in cmake/GetToolchainDirs.cmake and runtimes/CMakeLists.txt so they can be used by both, openmp and flang-rt. Potentially the mechnism could also be shared by other libraries such as compiler-rt.

finclude was chosen because gfortran uses it as well and avoids misuse such as #include <flang/iso_c_binding.mod>. The search location is now determined by ToolChain in the driver, instead of by the frontend. Another subdirectory flang avoid accidental inclusion of gfortran-modules which due to compression would result in user-unfriendly errors. Now the driver adds -fintrinsic-module-path for that location to the frontend call (Just like gfortran does). -fintrinsic-module-path had to be fixed for this because ironically it was only added to searchDirectories, but not intrinsicModuleDirectories_. Since the driver determines the location, tests invoking flang -fc1 and bbc must also be passed the location by llvm-lit. This works like llvm-lit does for finding the include dirs for Clang using -print-file-name=....

@Meinersbur Meinersbur requested a review from petrhosek December 9, 2025 21:54
@Meinersbur Meinersbur requested a review from a team as a code owner December 9, 2025 21:54
@llvmbot llvmbot added cmake Build system in general and CMake in particular backend:AMDGPU clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' flang:driver flang Flang issues not falling into any other category flang:fir-hlfir flang:openmp flang:semantics openmp:libomp OpenMP host runtime labels Dec 9, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 9, 2025

@llvm/pr-subscribers-flang-fir-hlfir

@llvm/pr-subscribers-flang-driver

Author: Michael Kruse (Meinersbur)

Changes

Reapplication of #137828 and #169638

Move building the .mod files from openmp/flang to openmp/flang-rt using a shared mechanism. Motivations to do so are:

  1. Most modules are target-dependent and need to be re-compiled for each target separately, which is something the LLVM_ENABLE_RUNTIMES system already does. Prime example is iso_c_binding.mod which encodes the target's ABI. Constants such as c_long_double also have different values. Most other modules have #ifdef-enclosed code as well. For instance this caused offload targets nvptx64-nvidia-cuda/amdgpu-amd-amdhsa to use the modules files compiled for the host which may contrain uses of the types REAL(10) or REAL(16) not available for nvptx/amdgpu.

#146876
#128015
#129742
#158790

  1. CMake has support for Fortran that we should use. Among other things, it automatically determines module dependencies so there is no need to hardcode them in the CMakeLists.txt.

  2. It allows using Fortran itself to implement Flang-RT. Currently, only iso_fortran_env_impl.f90 emits object files that are needed by Fortran applications (#89403). The workaround of #95388 could be reverted (PR #169525).

If using Flang for cross-compilation or target-offloading, flang-rt must now be compiled for each target not only for the library, but also to get the target-specific module files. For instance in a bootstrapping runtime build, this can be done by adding: -DLLVM_RUNTIME_TARGETS=default;nvptx64-nvidia-cuda;amdgpu-amd-amdhsa.

Some new dependencies come into play:

  • openmp depends on flang-rt for building lib_omp.mod and lib_omp_kinds.mod. Currently, if flang-rt is not found then the modules are not built.
  • check-flang depends on flang-rt: If not found, the majority of tests are disabled. If not building in a bootstrpping build, the location of the module files can be pointed to using -DFLANG_INTRINSIC_MODULES_DIR=&lt;path&gt;, e.g. in a flang-standalone build. Alternatively, the test needing any of the intrinsic modules could be marked with REQUIRES: flangrt-modules.
  • check-flang depends on openmp: Not a change; tests requiring lib_omp.mod and lib_omp_kinds.mod those are already marked with openmp_runtime.

As intrinsic are now specific to the target, their location is moved from include/flang to &lt;resource-dir&gt;/finclude/flang/&lt;triple&gt;. The mechnism to compute the location have been moved from flang-rt (previously used to compute the location of libflang_rt.*.a) to common locations in cmake/GetToolchainDirs.cmake and runtimes/CMakeLists.txt so they can be used by both, openmp and flang-rt. Potentially the mechnism could also be shared by other libraries such as compiler-rt.

finclude was chosen because gfortran uses it as well and avoids misuse such as #include &lt;flang/iso_c_binding.mod&gt;. The search location is now determined by ToolChain in the driver, instead of by the frontend. Another subdirectory flang avoid accidental inclusion of gfortran-modules which due to compression would result in user-unfriendly errors. Now the driver adds -fintrinsic-module-path for that location to the frontend call (Just like gfortran does). -fintrinsic-module-path had to be fixed for this because ironically it was only added to searchDirectories, but not intrinsicModuleDirectories_. Since the driver determines the location, tests invoking flang -fc1 and bbc must also be passed the location by llvm-lit. This works like llvm-lit does for finding the include dirs for Clang using -print-file-name=....


Patch is 104.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/171515.diff

70 Files Affected:

  • (modified) clang/include/clang/Driver/ToolChain.h (+4)
  • (modified) clang/include/clang/Options/Options.td (+1-1)
  • (modified) clang/lib/Driver/Driver.cpp (+11)
  • (modified) clang/lib/Driver/ToolChain.cpp (+6)
  • (modified) clang/lib/Driver/ToolChains/AMDGPU.cpp (+2-1)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+8)
  • (modified) clang/lib/Driver/ToolChains/HIPAMD.cpp (+2-1)
  • (modified) clang/lib/Driver/ToolChains/HIPSPV.cpp (+2-1)
  • (renamed) cmake/Modules/GetToolchainDirs.cmake (+11)
  • (modified) flang-rt/CMakeLists.txt (+27-95)
  • (modified) flang-rt/cmake/modules/AddFlangRT.cmake (+32-6)
  • (modified) flang-rt/cmake/modules/AddFlangRTOffload.cmake (+11-4)
  • (added) flang-rt/cmake/modules/FlangRTIntrospection.cmake (+36)
  • (modified) flang-rt/lib/CMakeLists.txt (+10-5)
  • (modified) flang-rt/lib/runtime/CMakeLists.txt (+135-38)
  • (renamed) flang-rt/lib/runtime/__cuda_builtins.f90 ()
  • (renamed) flang-rt/lib/runtime/__cuda_device.f90 ()
  • (renamed) flang-rt/lib/runtime/__fortran_builtins.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/__fortran_ieee_exceptions.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/__fortran_type_info.f90 ()
  • (renamed) flang-rt/lib/runtime/__ppc_intrinsics.f90 ()
  • (renamed) flang-rt/lib/runtime/__ppc_types.f90 ()
  • (renamed) flang-rt/lib/runtime/cooperative_groups.f90 (+1)
  • (renamed) flang-rt/lib/runtime/cudadevice.f90 ()
  • (renamed) flang-rt/lib/runtime/flang_debug.f90 ()
  • (renamed) flang-rt/lib/runtime/ieee_arithmetic.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/ieee_exceptions.f90 ()
  • (renamed) flang-rt/lib/runtime/ieee_features.f90 ()
  • (renamed) flang-rt/lib/runtime/iso_c_binding.f90 ()
  • (renamed) flang-rt/lib/runtime/iso_fortran_env.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/iso_fortran_env_impl.f90 ()
  • (renamed) flang-rt/lib/runtime/mma.f90 ()
  • (modified) flang-rt/test/lit.site.cfg.py.in (+1-1)
  • (modified) flang-rt/unittests/CMakeLists.txt (+2-3)
  • (modified) flang/CMakeLists.txt (-1)
  • (modified) flang/include/flang/Frontend/CompilerInvocation.h (+7)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+13-13)
  • (modified) flang/lib/Semantics/semantics.cpp (+8-5)
  • (removed) flang/module/.clang-format (-1)
  • (modified) flang/test/CMakeLists.txt (+28-3)
  • (modified) flang/test/Driver/Inputs/ieee_arithmetic.mod (+1)
  • (modified) flang/test/Driver/Inputs/iso_fortran_env.mod (+1)
  • (added) flang/test/Driver/intrinsic-module-path.F90 (+55)
  • (removed) flang/test/Driver/intrinsic-module-path.f90 (-23)
  • (modified) flang/test/Driver/lto-fatlto.f90 (+2-2)
  • (modified) flang/test/Driver/pp-fixed-form.f90 (+2-2)
  • (modified) flang/test/Lower/HLFIR/type-bound-call-mismatch.f90 (+1-1)
  • (modified) flang/test/Lower/OpenMP/simd_aarch64.f90 (+6-1)
  • (modified) flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90 (+2-2)
  • (modified) flang/test/Preprocessing/fixed-free.f (+1-1)
  • (modified) flang/test/Preprocessing/no-pp-if.f90 (+1-1)
  • (modified) flang/test/Semantics/bug163242.f90 (+1-1)
  • (modified) flang/test/Semantics/bug164303.f90 (+1-1)
  • (modified) flang/test/lit.cfg.py (+81-13)
  • (modified) flang/test/lit.site.cfg.py.in (+3-6)
  • (modified) flang/tools/CMakeLists.txt (-1)
  • (modified) flang/tools/bbc/bbc.cpp (+5-8)
  • (removed) flang/tools/f18/CMakeLists.txt (-171)
  • (removed) flang/tools/f18/dump.cpp (-42)
  • (modified) llvm/runtimes/CMakeLists.txt (+13-11)
  • (modified) openmp/CMakeLists.txt (+9-2)
  • (modified) openmp/README.rst (+2-5)
  • (removed) openmp/cmake/modules/LibompCheckFortranFlag.cmake (-29)
  • (modified) openmp/cmake/modules/LibompHandleFlags.cmake (-11)
  • (modified) openmp/module/CMakeLists.txt (+28-61)
  • (modified) openmp/runtime/CMakeLists.txt (+1-1)
  • (modified) openmp/runtime/cmake/LibompExports.cmake (+5-5)
  • (modified) openmp/runtime/test/lit.cfg (+1)
  • (modified) openmp/runtime/test/lit.site.cfg.in (+1)
  • (modified) runtimes/CMakeLists.txt (+292-11)
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 1425714d34110..26af88242eb3e 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -538,6 +538,10 @@ class ToolChain {
   // Returns Triple without the OSs version.
   llvm::Triple getTripleWithoutOSVersion() const;
 
+  /// Returns the target-specific path for Flang's intrinsic modules in the
+  /// resource directory if it exists.
+  std::optional<std::string> getDefaultIntrinsicModuleDir() const;
+
   // Returns the target specific runtime path if it exists.
   std::optional<std::string> getRuntimePath() const;
 
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index cac122d296624..90fc78db45d05 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6124,7 +6124,7 @@ def prebind : Flag<["-"], "prebind">;
 def preload : Flag<["-"], "preload">;
 def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">,
   HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">,
-  Visibility<[ClangOption, CLOption]>;
+  Visibility<[ClangOption, FlangOption, CLOption]>;
 def print_ivar_layout : Flag<["-"], "print-ivar-layout">,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable Objective-C Ivar layout bitmap print trace">,
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 8644a271a04b5..6f0d8078825de 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -6607,6 +6607,17 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
   if (llvm::sys::fs::exists(Twine(P)))
     return std::string(P);
 
+  // With Flang, also look for instrinsic modules
+  if (IsFlangMode()) {
+    if (std::optional<std::string> IntrPath =
+            TC.getDefaultIntrinsicModuleDir()) {
+      SmallString<128> P(*IntrPath);
+      llvm::sys::path::append(P, Name);
+      if (llvm::sys::fs::exists(Twine(P)))
+        return std::string(P);
+    }
+  }
+
   SmallString<128> D(Dir);
   llvm::sys::path::append(D, "..", Name);
   if (llvm::sys::fs::exists(Twine(D)))
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 77a2c73f0d446..f8520725b9b03 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1020,6 +1020,12 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
   return {};
 }
 
+std::optional<std::string> ToolChain::getDefaultIntrinsicModuleDir() const {
+  SmallString<128> P(D.ResourceDir);
+  llvm::sys::path::append(P, "finclude", "flang");
+  return getTargetSubDirPath(P);
+}
+
 std::optional<std::string> ToolChain::getRuntimePath() const {
   SmallString<128> P(D.ResourceDir);
   llvm::sys::path::append(P, "lib");
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 87ccd40372681..d3515c8fa2362 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -858,7 +858,8 @@ void AMDGPUToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat)) {
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode()) {
     CC1Args.push_back("-fvisibility=hidden");
     CC1Args.push_back("-fapply-global-visibility-to-externs");
   }
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 2f5e93d139858..2c7a06f2893b9 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -1069,6 +1069,14 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
   CmdArgs.push_back("-resource-dir");
   CmdArgs.push_back(D.ResourceDir.c_str());
 
+  // Default intrinsic module dirs must be added after any user-provided
+  // -fintrinsic-modules-path to have lower precedence
+  if (std::optional<std::string> IntrModPath =
+          TC.getDefaultIntrinsicModuleDir()) {
+    CmdArgs.push_back("-fintrinsic-modules-path");
+    CmdArgs.push_back(Args.MakeArgString(*IntrModPath));
+  }
+
   // Offloading related options
   addOffloadOptions(C, Inputs, JA, Args, CmdArgs);
 
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index f2f64922cb404..8bfd3c887452c 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -274,7 +274,8 @@ void HIPAMDToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat)) {
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode()) {
     CC1Args.append({"-fvisibility=hidden"});
     CC1Args.push_back("-fapply-global-visibility-to-externs");
   }
diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp
index be0f49d8e1497..261adc2b1c440 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp
+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -143,7 +143,8 @@ void HIPSPVToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat))
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode())
     CC1Args.append(
         {"-fvisibility=hidden", "-fapply-global-visibility-to-externs"});
 
diff --git a/flang-rt/cmake/modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
similarity index 94%
rename from flang-rt/cmake/modules/GetToolchainDirs.cmake
rename to cmake/Modules/GetToolchainDirs.cmake
index fba12502b5946..ce2f8c294b2bc 100644
--- a/flang-rt/cmake/modules/GetToolchainDirs.cmake
+++ b/cmake/Modules/GetToolchainDirs.cmake
@@ -47,6 +47,17 @@ function (get_toolchain_library_subdir outvar)
 endfunction ()
 
 
+# Corresponds to Flang's ToolChain::getDefaultIntrinsicModuleDir().
+function (get_toolchain_module_subdir outvar)
+  set(outval "finclude/flang")
+
+  get_toolchain_arch_dirname(arch_dirname)
+  set(outval "${outval}/${arch_dirname}")
+
+  set(${outvar} "${outval}" PARENT_SCOPE)
+endfunction ()
+
+
 # Corresponds to Clang's ToolChain::getOSLibName(). Adapted from Compiler-RT.
 function (get_toolchain_os_dirname outvar)
   if (ANDROID)
diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index 50b8e834776fb..20ca6dc7124bc 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)
-
 
 list(APPEND CMAKE_MODULE_PATH
     "${FLANG_RT_SOURCE_DIR}/cmake/modules"
@@ -65,69 +31,22 @@ list(APPEND CMAKE_MODULE_PATH
 include(AddFlangRT)
 include(GetToolchainDirs)
 include(FlangCommon)
+include(FlangRTIntrospection)
 include(HandleCompilerRT)
 include(ExtendPath)
+include(CheckFortranSourceCompiles)
+include(CMakePushCheckState)
 
 
 ############################
 # Build Mode Introspection #
 ############################
 
-# Determine whether we are in the runtimes/runtimes-bins directory of a
-# bootstrap build.
-set(LLVM_TREE_AVAILABLE OFF)
-if (LLVM_LIBRARY_OUTPUT_INTDIR AND LLVM_RUNTIME_OUTPUT_INTDIR AND PACKAGE_VERSION)
-  set(LLVM_TREE_AVAILABLE ON)
-endif()
-
 # Path to LLVM development tools (FileCheck, llvm-lit, not, ...)
 set(LLVM_TOOLS_DIR "${LLVM_BINARY_DIR}/bin")
 
-# Determine build and install paths.
-# The build path is absolute, but the install dir is relative, CMake's install
-# command has to apply CMAKE_INSTALL_PREFIX itself.
-get_toolchain_library_subdir(toolchain_lib_subdir)
-if (LLVM_TREE_AVAILABLE)
-  # In a bootstrap build emit the libraries into a default search path in the
-  # build directory of the just-built compiler. This allows using the
-  # just-built compiler without specifying paths to runtime libraries.
-  #
-  # Despite Clang in the name, get_clang_resource_dir does not depend on Clang
-  # being added to the build. Flang uses the same resource dir as clang.
-  include(GetClangResourceDir)
-  get_clang_resource_dir(FLANG_RT_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
-  get_clang_resource_dir(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT)
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}")
-else ()
-  # In a standalone runtimes build, do not write into LLVM_BINARY_DIR. It may be
-  # read-only and/or shared by multiple runtimes with different build
-  # configurations (e.g. Debug/Release). Use the runtime's own lib dir like any
-  # non-toolchain library.
-  # For the install prefix, still use the resource dir assuming that Flang will
-  # be installed there using the same prefix. This is to not have a difference
-  # between bootstrap and standalone runtimes builds.
-  set(FLANG_RT_OUTPUT_RESOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
-  set(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "lib${LLVM_LIBDIR_SUFFIX}")
-endif ()
-set(FLANG_RT_INSTALL_RESOURCE_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT}"
-    CACHE PATH "Path to install runtime libraries to (default: clang resource dir)")
-extend_path(FLANG_RT_INSTALL_RESOURCE_LIB_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}")
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_PATH)
-# FIXME: For the libflang_rt.so, the toolchain resource lib dir is not a good
-#        destination because it is not a ld.so default search path.
-#        The machine where the executable is eventually executed may not be the
-#        machine where the Flang compiler and its resource dir is installed, so
-#        setting RPath by the driver is not an solution. It should belong into
-#        /usr/lib/<triple>/libflang_rt.so, like e.g. libgcc_s.so.
-#        But the linker as invoked by the Flang driver also requires
-#        libflang_rt.so to be found when linking and the resource lib dir is
-#        the only reliable location.
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_LIB_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
+# Fortran compiler not optional for building Flang-RT
+enable_language(Fortran)
 
 
 #################
@@ -137,8 +56,6 @@ cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
 # Important: flang-rt user options must be prefixed with "FLANG_RT_". Variables
 # with this prefix will be forwarded in bootstrap builds.
 
-option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
-
 # Provide an interface to link against the LLVM libc/libc++ projects directly.
 set(FLANG_RT_SUPPORTED_PROVIDERS system llvm)
 set(FLANG_RT_LIBC_PROVIDER "system" CACHE STRING "Specify C library to use. Supported values are ${FLANG_RT_SUPPORTED_PROVIDERS}.")
@@ -151,7 +68,14 @@ if (NOT "${FLANG_RT_LIBCXX_PROVIDER}" IN_LIST FLANG_RT_SUPPORTED_PROVIDERS)
   message(FATAL_ERROR "Unsupported library: '${FLANG_RT_LIBCXX_PROVIDER}'. Supported values are ${FLANG_RT_SUPPORTED_PROVIDERS}.")
 endif ()
 
-option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." ON)
+if (LLVM_RUNTIMES_TARGET MATCHES "^amdgcn|^nvptx")
+  # Compiling libraries for offload targets is currently experimental;
+  # Only build the builtin modules by default.
+  set(FLANG_RT_ENABLE_STATIC_default OFF)
+else ()
+  set(FLANG_RT_ENABLE_STATIC_default ON)
+endif ()
+option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." "${FLANG_RT_ENABLE_STATIC_default}")
 if (WIN32)
   # Windows DLL currently not implemented.
   set(FLANG_RT_ENABLE_SHARED OFF)
@@ -164,11 +88,14 @@ else ()
   #       breaking change unless the driver is changed.
   option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." OFF)
 endif ()
-if (NOT FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED)
-  message(FATAL_ERROR "
-      Must build at least one type of library
-      (FLANG_RT_ENABLE_STATIC=ON, FLANG_RT_ENABLE_SHARED=ON, or both)
-    ")
+
+
+if (FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED)
+  option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
+else ()
+  # Tests require at least one of the libraries
+  message(STATUS "Flang-RT testing disabled without either FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED")
+  set(FLANG_RT_INCLUDE_TESTS OFF)
 endif ()
 
 
@@ -186,7 +113,7 @@ elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "CUDA")
   option(FLANG_RT_CUDA_RUNTIME_PTX_WITHOUT_GLOBAL_VARS "Do not compile global variables' definitions when producing PTX library" OFF)
 elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "OpenMP")
   # Support for OpenMP offloading
-  set(FLANG_RT_DEVICE_ARCHITECTURES "all" CACHE STRING
+  set(FLANG_RT_DEVICE_ARCHITECTURES "${RUNTIMES_DEVICE_ARCHITECTURES}" CACHE STRING
       "List of OpenMP device architectures to be used to compile the Fortran runtime (e.g. 'gfx1103;sm_90')"
     )
 
@@ -234,6 +161,10 @@ check_cxx_source_compiles(
   "
   HAVE_DECL_STRERROR_S)
 
+# Look for support of REAL(16), if not already defined via command
+# line via -DFORTRAN_SUPPORTS_REAL16=YES/NO
+check_fortran_quadmath_support()
+
 # Search for clang_rt.builtins library. Need in addition to msvcrt.
 if (WIN32)
   find_compiler_rt_library(builtins FLANG_RT_BUILTINS_LIBRARY)
@@ -331,6 +262,7 @@ else ()
   add_custom_target(check-flang-rt)
 endif()
 
+
 ###################
 # Install headers #
 ###################
diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index 923507764d691..0ba485a79beb8 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -94,6 +94,10 @@ function (add_flangrt_library name)
     set(build_object ON)
   elseif (build_static AND build_shared)
     set(build_object ON)
+  elseif (NOT build_static AND NOT build_shared)
+    # If not building a library, still build the object files
+    # Needed to generate the .mod files as byproduct
+    set(build_object ON)
   endif ()
 
   # srctargets: targets that contain source files
@@ -168,14 +172,18 @@ function (add_flangrt_library name)
     if (BUILD_SHARED_LIBS)
       if (build_shared)
         set(default_target "${name_shared}")
-      else ()
+      elseif (build_static)
         set(default_target "${name_static}")
+      else ()
+        set(default_target "${name_object}")
       endif ()
     else ()
       if (build_static)
         set(default_target "${name_static}")
-      else ()
+      elseif (build_shared)
         set(default_target "${name_shared}")
+      else ()
+        set(default_target "${name_object}")
       endif ()
     endif ()
     add_library(${name}.default ALIAS "${default_target}")
@@ -190,6 +198,12 @@ function (add_flangrt_library name)
     endif ()
   endif ()
 
+  if (build_object)
+    add_library(${name}.compile ALIAS "${name_object}")
+  else ()
+    add_library(${name}.compile ALIAS "${default_target}")
+  endif ()
+
   foreach (tgtname IN LISTS libtargets)
     if (NOT WIN32)
       # Use same stem name for .a and .so. Common in UNIX environments.
@@ -219,6 +233,14 @@ function (add_flangrt_library name)
     # Minimum required C++ version for Flang-RT, even if CMAKE_CXX_STANDARD is defined to something else.
     target_compile_features(${tgtname} PRIVATE cxx_std_17)
 
+    target_compile_options(${tgtname} PRIVATE
+      # Always enable preprocessor regardless of file extension
+      "$<$<COMPILE_LANGUAGE:Fortran>:-cpp>"
+
+      # Missing type descriptors are expected for intrinsic modules
+      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-mmlir;SHELL:-ignore-missing-type-desc>"
+    )
+
     # When building the flang runtime if LTO is enabled the archive file
     # contains LLVM IR rather than object code. Currently flang is not
     # LTO aware so cannot link this file to compiled Fortran code.
@@ -226,6 +248,10 @@ function (add_flangrt_library name)
       target_compile_options(${tgtname} PRIVATE -fno-lto)
     endif ()
 
+    if (FORTRAN_SUPPORTS_REAL16)
+      target_compile_definitions(${tgtname} PRIVATE FLANG_SUPPORT_R16=1)
+    endif ()
+
     # Use compiler-specific options to disable exceptions and RTTI.
     if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
       target_compile_options(${tgtname} PRIVATE
@@ -344,13 +370,13 @@ function (add_flangrt_library name)
     if (ARG_INSTALL_WITH_TOOLCHAIN)
       set_target_properties(${tgtname}
         PROPERTIES
-          ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
-          LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
+          ARCHIVE_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
+          LIBRARY_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
         )
 
       install(TARGETS ${tgtname}
-          ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
-          LIBRARY DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
+          ARCHIVE DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
+          LIBRARY DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
         )
     endif ()
 
diff --git a/flang-rt/cmake/modules/AddFlangRTOffload.cmake b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
index cbc69f3a9656a..5b6464741c9c9 100644
--- a/flang-rt/cmake/modules/AddFlangRTOffload.cmake
+++ b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
@@ -88,16 +88,16 @@ macro(enable_omp_offload_compilation name files)
         "${FLANG_RT_DEVICE_ARCHITECTURES}"
         )
 
-      set(OMP_COMPILE_OPTIONS
+      set(OMP_COMPILE_OPTIONS $<$<COMPILE_LANGUAGE:C,CXX>:
         -fopenmp
         -fvisibility=hidden
         -fopenmp-cuda-mode
         --offload-arch=${compile_for_architectures}
         # Force LTO for the device part.
         -foffload-lto
-        )
-      set_source_files_properties(${files} PROPERTIES COMPILE_OPTIONS
-        "${OMP_COMPILE_OPTIONS}"
+        >)
+      set_property(SOURCE ${files} APPEND
+        PROPERTY COMPILE_DEFINITIONS ${OMP_COMPILE_OPTIONS}
         )
       target_link_options(${name}.static PUBLIC ${OMP_COMPILE_OPTIONS})
 
@@ -105,6 +105,13 @@ macro(enable_omp_offload_compilation name files)
       set_source_files_properties(${files}
         PROPERTIES COMPILE_DEFINITIONS OMP_OFFLOAD_BUILD
         )
+
+     # If building flang-rt together with libomp, ensure that libom...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Dec 9, 2025

@llvm/pr-subscribers-clang-driver

Author: Michael Kruse (Meinersbur)

Changes

Reapplication of #137828 and #169638

Move building the .mod files from openmp/flang to openmp/flang-rt using a shared mechanism. Motivations to do so are:

  1. Most modules are target-dependent and need to be re-compiled for each target separately, which is something the LLVM_ENABLE_RUNTIMES system already does. Prime example is iso_c_binding.mod which encodes the target's ABI. Constants such as c_long_double also have different values. Most other modules have #ifdef-enclosed code as well. For instance this caused offload targets nvptx64-nvidia-cuda/amdgpu-amd-amdhsa to use the modules files compiled for the host which may contrain uses of the types REAL(10) or REAL(16) not available for nvptx/amdgpu.

#146876
#128015
#129742
#158790

  1. CMake has support for Fortran that we should use. Among other things, it automatically determines module dependencies so there is no need to hardcode them in the CMakeLists.txt.

  2. It allows using Fortran itself to implement Flang-RT. Currently, only iso_fortran_env_impl.f90 emits object files that are needed by Fortran applications (#89403). The workaround of #95388 could be reverted (PR #169525).

If using Flang for cross-compilation or target-offloading, flang-rt must now be compiled for each target not only for the library, but also to get the target-specific module files. For instance in a bootstrapping runtime build, this can be done by adding: -DLLVM_RUNTIME_TARGETS=default;nvptx64-nvidia-cuda;amdgpu-amd-amdhsa.

Some new dependencies come into play:

  • openmp depends on flang-rt for building lib_omp.mod and lib_omp_kinds.mod. Currently, if flang-rt is not found then the modules are not built.
  • check-flang depends on flang-rt: If not found, the majority of tests are disabled. If not building in a bootstrpping build, the location of the module files can be pointed to using -DFLANG_INTRINSIC_MODULES_DIR=&lt;path&gt;, e.g. in a flang-standalone build. Alternatively, the test needing any of the intrinsic modules could be marked with REQUIRES: flangrt-modules.
  • check-flang depends on openmp: Not a change; tests requiring lib_omp.mod and lib_omp_kinds.mod those are already marked with openmp_runtime.

As intrinsic are now specific to the target, their location is moved from include/flang to &lt;resource-dir&gt;/finclude/flang/&lt;triple&gt;. The mechnism to compute the location have been moved from flang-rt (previously used to compute the location of libflang_rt.*.a) to common locations in cmake/GetToolchainDirs.cmake and runtimes/CMakeLists.txt so they can be used by both, openmp and flang-rt. Potentially the mechnism could also be shared by other libraries such as compiler-rt.

finclude was chosen because gfortran uses it as well and avoids misuse such as #include &lt;flang/iso_c_binding.mod&gt;. The search location is now determined by ToolChain in the driver, instead of by the frontend. Another subdirectory flang avoid accidental inclusion of gfortran-modules which due to compression would result in user-unfriendly errors. Now the driver adds -fintrinsic-module-path for that location to the frontend call (Just like gfortran does). -fintrinsic-module-path had to be fixed for this because ironically it was only added to searchDirectories, but not intrinsicModuleDirectories_. Since the driver determines the location, tests invoking flang -fc1 and bbc must also be passed the location by llvm-lit. This works like llvm-lit does for finding the include dirs for Clang using -print-file-name=....


Patch is 104.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/171515.diff

70 Files Affected:

  • (modified) clang/include/clang/Driver/ToolChain.h (+4)
  • (modified) clang/include/clang/Options/Options.td (+1-1)
  • (modified) clang/lib/Driver/Driver.cpp (+11)
  • (modified) clang/lib/Driver/ToolChain.cpp (+6)
  • (modified) clang/lib/Driver/ToolChains/AMDGPU.cpp (+2-1)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+8)
  • (modified) clang/lib/Driver/ToolChains/HIPAMD.cpp (+2-1)
  • (modified) clang/lib/Driver/ToolChains/HIPSPV.cpp (+2-1)
  • (renamed) cmake/Modules/GetToolchainDirs.cmake (+11)
  • (modified) flang-rt/CMakeLists.txt (+27-95)
  • (modified) flang-rt/cmake/modules/AddFlangRT.cmake (+32-6)
  • (modified) flang-rt/cmake/modules/AddFlangRTOffload.cmake (+11-4)
  • (added) flang-rt/cmake/modules/FlangRTIntrospection.cmake (+36)
  • (modified) flang-rt/lib/CMakeLists.txt (+10-5)
  • (modified) flang-rt/lib/runtime/CMakeLists.txt (+135-38)
  • (renamed) flang-rt/lib/runtime/__cuda_builtins.f90 ()
  • (renamed) flang-rt/lib/runtime/__cuda_device.f90 ()
  • (renamed) flang-rt/lib/runtime/__fortran_builtins.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/__fortran_ieee_exceptions.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/__fortran_type_info.f90 ()
  • (renamed) flang-rt/lib/runtime/__ppc_intrinsics.f90 ()
  • (renamed) flang-rt/lib/runtime/__ppc_types.f90 ()
  • (renamed) flang-rt/lib/runtime/cooperative_groups.f90 (+1)
  • (renamed) flang-rt/lib/runtime/cudadevice.f90 ()
  • (renamed) flang-rt/lib/runtime/flang_debug.f90 ()
  • (renamed) flang-rt/lib/runtime/ieee_arithmetic.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/ieee_exceptions.f90 ()
  • (renamed) flang-rt/lib/runtime/ieee_features.f90 ()
  • (renamed) flang-rt/lib/runtime/iso_c_binding.f90 ()
  • (renamed) flang-rt/lib/runtime/iso_fortran_env.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/iso_fortran_env_impl.f90 ()
  • (renamed) flang-rt/lib/runtime/mma.f90 ()
  • (modified) flang-rt/test/lit.site.cfg.py.in (+1-1)
  • (modified) flang-rt/unittests/CMakeLists.txt (+2-3)
  • (modified) flang/CMakeLists.txt (-1)
  • (modified) flang/include/flang/Frontend/CompilerInvocation.h (+7)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+13-13)
  • (modified) flang/lib/Semantics/semantics.cpp (+8-5)
  • (removed) flang/module/.clang-format (-1)
  • (modified) flang/test/CMakeLists.txt (+28-3)
  • (modified) flang/test/Driver/Inputs/ieee_arithmetic.mod (+1)
  • (modified) flang/test/Driver/Inputs/iso_fortran_env.mod (+1)
  • (added) flang/test/Driver/intrinsic-module-path.F90 (+55)
  • (removed) flang/test/Driver/intrinsic-module-path.f90 (-23)
  • (modified) flang/test/Driver/lto-fatlto.f90 (+2-2)
  • (modified) flang/test/Driver/pp-fixed-form.f90 (+2-2)
  • (modified) flang/test/Lower/HLFIR/type-bound-call-mismatch.f90 (+1-1)
  • (modified) flang/test/Lower/OpenMP/simd_aarch64.f90 (+6-1)
  • (modified) flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90 (+2-2)
  • (modified) flang/test/Preprocessing/fixed-free.f (+1-1)
  • (modified) flang/test/Preprocessing/no-pp-if.f90 (+1-1)
  • (modified) flang/test/Semantics/bug163242.f90 (+1-1)
  • (modified) flang/test/Semantics/bug164303.f90 (+1-1)
  • (modified) flang/test/lit.cfg.py (+81-13)
  • (modified) flang/test/lit.site.cfg.py.in (+3-6)
  • (modified) flang/tools/CMakeLists.txt (-1)
  • (modified) flang/tools/bbc/bbc.cpp (+5-8)
  • (removed) flang/tools/f18/CMakeLists.txt (-171)
  • (removed) flang/tools/f18/dump.cpp (-42)
  • (modified) llvm/runtimes/CMakeLists.txt (+13-11)
  • (modified) openmp/CMakeLists.txt (+9-2)
  • (modified) openmp/README.rst (+2-5)
  • (removed) openmp/cmake/modules/LibompCheckFortranFlag.cmake (-29)
  • (modified) openmp/cmake/modules/LibompHandleFlags.cmake (-11)
  • (modified) openmp/module/CMakeLists.txt (+28-61)
  • (modified) openmp/runtime/CMakeLists.txt (+1-1)
  • (modified) openmp/runtime/cmake/LibompExports.cmake (+5-5)
  • (modified) openmp/runtime/test/lit.cfg (+1)
  • (modified) openmp/runtime/test/lit.site.cfg.in (+1)
  • (modified) runtimes/CMakeLists.txt (+292-11)
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 1425714d34110..26af88242eb3e 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -538,6 +538,10 @@ class ToolChain {
   // Returns Triple without the OSs version.
   llvm::Triple getTripleWithoutOSVersion() const;
 
+  /// Returns the target-specific path for Flang's intrinsic modules in the
+  /// resource directory if it exists.
+  std::optional<std::string> getDefaultIntrinsicModuleDir() const;
+
   // Returns the target specific runtime path if it exists.
   std::optional<std::string> getRuntimePath() const;
 
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index cac122d296624..90fc78db45d05 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6124,7 +6124,7 @@ def prebind : Flag<["-"], "prebind">;
 def preload : Flag<["-"], "preload">;
 def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">,
   HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">,
-  Visibility<[ClangOption, CLOption]>;
+  Visibility<[ClangOption, FlangOption, CLOption]>;
 def print_ivar_layout : Flag<["-"], "print-ivar-layout">,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable Objective-C Ivar layout bitmap print trace">,
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 8644a271a04b5..6f0d8078825de 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -6607,6 +6607,17 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
   if (llvm::sys::fs::exists(Twine(P)))
     return std::string(P);
 
+  // With Flang, also look for instrinsic modules
+  if (IsFlangMode()) {
+    if (std::optional<std::string> IntrPath =
+            TC.getDefaultIntrinsicModuleDir()) {
+      SmallString<128> P(*IntrPath);
+      llvm::sys::path::append(P, Name);
+      if (llvm::sys::fs::exists(Twine(P)))
+        return std::string(P);
+    }
+  }
+
   SmallString<128> D(Dir);
   llvm::sys::path::append(D, "..", Name);
   if (llvm::sys::fs::exists(Twine(D)))
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 77a2c73f0d446..f8520725b9b03 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1020,6 +1020,12 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
   return {};
 }
 
+std::optional<std::string> ToolChain::getDefaultIntrinsicModuleDir() const {
+  SmallString<128> P(D.ResourceDir);
+  llvm::sys::path::append(P, "finclude", "flang");
+  return getTargetSubDirPath(P);
+}
+
 std::optional<std::string> ToolChain::getRuntimePath() const {
   SmallString<128> P(D.ResourceDir);
   llvm::sys::path::append(P, "lib");
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 87ccd40372681..d3515c8fa2362 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -858,7 +858,8 @@ void AMDGPUToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat)) {
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode()) {
     CC1Args.push_back("-fvisibility=hidden");
     CC1Args.push_back("-fapply-global-visibility-to-externs");
   }
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 2f5e93d139858..2c7a06f2893b9 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -1069,6 +1069,14 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
   CmdArgs.push_back("-resource-dir");
   CmdArgs.push_back(D.ResourceDir.c_str());
 
+  // Default intrinsic module dirs must be added after any user-provided
+  // -fintrinsic-modules-path to have lower precedence
+  if (std::optional<std::string> IntrModPath =
+          TC.getDefaultIntrinsicModuleDir()) {
+    CmdArgs.push_back("-fintrinsic-modules-path");
+    CmdArgs.push_back(Args.MakeArgString(*IntrModPath));
+  }
+
   // Offloading related options
   addOffloadOptions(C, Inputs, JA, Args, CmdArgs);
 
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index f2f64922cb404..8bfd3c887452c 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -274,7 +274,8 @@ void HIPAMDToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat)) {
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode()) {
     CC1Args.append({"-fvisibility=hidden"});
     CC1Args.push_back("-fapply-global-visibility-to-externs");
   }
diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp
index be0f49d8e1497..261adc2b1c440 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp
+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -143,7 +143,8 @@ void HIPSPVToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat))
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode())
     CC1Args.append(
         {"-fvisibility=hidden", "-fapply-global-visibility-to-externs"});
 
diff --git a/flang-rt/cmake/modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
similarity index 94%
rename from flang-rt/cmake/modules/GetToolchainDirs.cmake
rename to cmake/Modules/GetToolchainDirs.cmake
index fba12502b5946..ce2f8c294b2bc 100644
--- a/flang-rt/cmake/modules/GetToolchainDirs.cmake
+++ b/cmake/Modules/GetToolchainDirs.cmake
@@ -47,6 +47,17 @@ function (get_toolchain_library_subdir outvar)
 endfunction ()
 
 
+# Corresponds to Flang's ToolChain::getDefaultIntrinsicModuleDir().
+function (get_toolchain_module_subdir outvar)
+  set(outval "finclude/flang")
+
+  get_toolchain_arch_dirname(arch_dirname)
+  set(outval "${outval}/${arch_dirname}")
+
+  set(${outvar} "${outval}" PARENT_SCOPE)
+endfunction ()
+
+
 # Corresponds to Clang's ToolChain::getOSLibName(). Adapted from Compiler-RT.
 function (get_toolchain_os_dirname outvar)
   if (ANDROID)
diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index 50b8e834776fb..20ca6dc7124bc 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)
-
 
 list(APPEND CMAKE_MODULE_PATH
     "${FLANG_RT_SOURCE_DIR}/cmake/modules"
@@ -65,69 +31,22 @@ list(APPEND CMAKE_MODULE_PATH
 include(AddFlangRT)
 include(GetToolchainDirs)
 include(FlangCommon)
+include(FlangRTIntrospection)
 include(HandleCompilerRT)
 include(ExtendPath)
+include(CheckFortranSourceCompiles)
+include(CMakePushCheckState)
 
 
 ############################
 # Build Mode Introspection #
 ############################
 
-# Determine whether we are in the runtimes/runtimes-bins directory of a
-# bootstrap build.
-set(LLVM_TREE_AVAILABLE OFF)
-if (LLVM_LIBRARY_OUTPUT_INTDIR AND LLVM_RUNTIME_OUTPUT_INTDIR AND PACKAGE_VERSION)
-  set(LLVM_TREE_AVAILABLE ON)
-endif()
-
 # Path to LLVM development tools (FileCheck, llvm-lit, not, ...)
 set(LLVM_TOOLS_DIR "${LLVM_BINARY_DIR}/bin")
 
-# Determine build and install paths.
-# The build path is absolute, but the install dir is relative, CMake's install
-# command has to apply CMAKE_INSTALL_PREFIX itself.
-get_toolchain_library_subdir(toolchain_lib_subdir)
-if (LLVM_TREE_AVAILABLE)
-  # In a bootstrap build emit the libraries into a default search path in the
-  # build directory of the just-built compiler. This allows using the
-  # just-built compiler without specifying paths to runtime libraries.
-  #
-  # Despite Clang in the name, get_clang_resource_dir does not depend on Clang
-  # being added to the build. Flang uses the same resource dir as clang.
-  include(GetClangResourceDir)
-  get_clang_resource_dir(FLANG_RT_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
-  get_clang_resource_dir(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT)
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}")
-else ()
-  # In a standalone runtimes build, do not write into LLVM_BINARY_DIR. It may be
-  # read-only and/or shared by multiple runtimes with different build
-  # configurations (e.g. Debug/Release). Use the runtime's own lib dir like any
-  # non-toolchain library.
-  # For the install prefix, still use the resource dir assuming that Flang will
-  # be installed there using the same prefix. This is to not have a difference
-  # between bootstrap and standalone runtimes builds.
-  set(FLANG_RT_OUTPUT_RESOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
-  set(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "lib${LLVM_LIBDIR_SUFFIX}")
-endif ()
-set(FLANG_RT_INSTALL_RESOURCE_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT}"
-    CACHE PATH "Path to install runtime libraries to (default: clang resource dir)")
-extend_path(FLANG_RT_INSTALL_RESOURCE_LIB_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}")
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_PATH)
-# FIXME: For the libflang_rt.so, the toolchain resource lib dir is not a good
-#        destination because it is not a ld.so default search path.
-#        The machine where the executable is eventually executed may not be the
-#        machine where the Flang compiler and its resource dir is installed, so
-#        setting RPath by the driver is not an solution. It should belong into
-#        /usr/lib/<triple>/libflang_rt.so, like e.g. libgcc_s.so.
-#        But the linker as invoked by the Flang driver also requires
-#        libflang_rt.so to be found when linking and the resource lib dir is
-#        the only reliable location.
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_LIB_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
+# Fortran compiler not optional for building Flang-RT
+enable_language(Fortran)
 
 
 #################
@@ -137,8 +56,6 @@ cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
 # Important: flang-rt user options must be prefixed with "FLANG_RT_". Variables
 # with this prefix will be forwarded in bootstrap builds.
 
-option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
-
 # Provide an interface to link against the LLVM libc/libc++ projects directly.
 set(FLANG_RT_SUPPORTED_PROVIDERS system llvm)
 set(FLANG_RT_LIBC_PROVIDER "system" CACHE STRING "Specify C library to use. Supported values are ${FLANG_RT_SUPPORTED_PROVIDERS}.")
@@ -151,7 +68,14 @@ if (NOT "${FLANG_RT_LIBCXX_PROVIDER}" IN_LIST FLANG_RT_SUPPORTED_PROVIDERS)
   message(FATAL_ERROR "Unsupported library: '${FLANG_RT_LIBCXX_PROVIDER}'. Supported values are ${FLANG_RT_SUPPORTED_PROVIDERS}.")
 endif ()
 
-option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." ON)
+if (LLVM_RUNTIMES_TARGET MATCHES "^amdgcn|^nvptx")
+  # Compiling libraries for offload targets is currently experimental;
+  # Only build the builtin modules by default.
+  set(FLANG_RT_ENABLE_STATIC_default OFF)
+else ()
+  set(FLANG_RT_ENABLE_STATIC_default ON)
+endif ()
+option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." "${FLANG_RT_ENABLE_STATIC_default}")
 if (WIN32)
   # Windows DLL currently not implemented.
   set(FLANG_RT_ENABLE_SHARED OFF)
@@ -164,11 +88,14 @@ else ()
   #       breaking change unless the driver is changed.
   option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." OFF)
 endif ()
-if (NOT FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED)
-  message(FATAL_ERROR "
-      Must build at least one type of library
-      (FLANG_RT_ENABLE_STATIC=ON, FLANG_RT_ENABLE_SHARED=ON, or both)
-    ")
+
+
+if (FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED)
+  option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
+else ()
+  # Tests require at least one of the libraries
+  message(STATUS "Flang-RT testing disabled without either FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED")
+  set(FLANG_RT_INCLUDE_TESTS OFF)
 endif ()
 
 
@@ -186,7 +113,7 @@ elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "CUDA")
   option(FLANG_RT_CUDA_RUNTIME_PTX_WITHOUT_GLOBAL_VARS "Do not compile global variables' definitions when producing PTX library" OFF)
 elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "OpenMP")
   # Support for OpenMP offloading
-  set(FLANG_RT_DEVICE_ARCHITECTURES "all" CACHE STRING
+  set(FLANG_RT_DEVICE_ARCHITECTURES "${RUNTIMES_DEVICE_ARCHITECTURES}" CACHE STRING
       "List of OpenMP device architectures to be used to compile the Fortran runtime (e.g. 'gfx1103;sm_90')"
     )
 
@@ -234,6 +161,10 @@ check_cxx_source_compiles(
   "
   HAVE_DECL_STRERROR_S)
 
+# Look for support of REAL(16), if not already defined via command
+# line via -DFORTRAN_SUPPORTS_REAL16=YES/NO
+check_fortran_quadmath_support()
+
 # Search for clang_rt.builtins library. Need in addition to msvcrt.
 if (WIN32)
   find_compiler_rt_library(builtins FLANG_RT_BUILTINS_LIBRARY)
@@ -331,6 +262,7 @@ else ()
   add_custom_target(check-flang-rt)
 endif()
 
+
 ###################
 # Install headers #
 ###################
diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index 923507764d691..0ba485a79beb8 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -94,6 +94,10 @@ function (add_flangrt_library name)
     set(build_object ON)
   elseif (build_static AND build_shared)
     set(build_object ON)
+  elseif (NOT build_static AND NOT build_shared)
+    # If not building a library, still build the object files
+    # Needed to generate the .mod files as byproduct
+    set(build_object ON)
   endif ()
 
   # srctargets: targets that contain source files
@@ -168,14 +172,18 @@ function (add_flangrt_library name)
     if (BUILD_SHARED_LIBS)
       if (build_shared)
         set(default_target "${name_shared}")
-      else ()
+      elseif (build_static)
         set(default_target "${name_static}")
+      else ()
+        set(default_target "${name_object}")
       endif ()
     else ()
       if (build_static)
         set(default_target "${name_static}")
-      else ()
+      elseif (build_shared)
         set(default_target "${name_shared}")
+      else ()
+        set(default_target "${name_object}")
       endif ()
     endif ()
     add_library(${name}.default ALIAS "${default_target}")
@@ -190,6 +198,12 @@ function (add_flangrt_library name)
     endif ()
   endif ()
 
+  if (build_object)
+    add_library(${name}.compile ALIAS "${name_object}")
+  else ()
+    add_library(${name}.compile ALIAS "${default_target}")
+  endif ()
+
   foreach (tgtname IN LISTS libtargets)
     if (NOT WIN32)
       # Use same stem name for .a and .so. Common in UNIX environments.
@@ -219,6 +233,14 @@ function (add_flangrt_library name)
     # Minimum required C++ version for Flang-RT, even if CMAKE_CXX_STANDARD is defined to something else.
     target_compile_features(${tgtname} PRIVATE cxx_std_17)
 
+    target_compile_options(${tgtname} PRIVATE
+      # Always enable preprocessor regardless of file extension
+      "$<$<COMPILE_LANGUAGE:Fortran>:-cpp>"
+
+      # Missing type descriptors are expected for intrinsic modules
+      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-mmlir;SHELL:-ignore-missing-type-desc>"
+    )
+
     # When building the flang runtime if LTO is enabled the archive file
     # contains LLVM IR rather than object code. Currently flang is not
     # LTO aware so cannot link this file to compiled Fortran code.
@@ -226,6 +248,10 @@ function (add_flangrt_library name)
       target_compile_options(${tgtname} PRIVATE -fno-lto)
     endif ()
 
+    if (FORTRAN_SUPPORTS_REAL16)
+      target_compile_definitions(${tgtname} PRIVATE FLANG_SUPPORT_R16=1)
+    endif ()
+
     # Use compiler-specific options to disable exceptions and RTTI.
     if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
       target_compile_options(${tgtname} PRIVATE
@@ -344,13 +370,13 @@ function (add_flangrt_library name)
     if (ARG_INSTALL_WITH_TOOLCHAIN)
       set_target_properties(${tgtname}
         PROPERTIES
-          ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
-          LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
+          ARCHIVE_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
+          LIBRARY_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
         )
 
       install(TARGETS ${tgtname}
-          ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
-          LIBRARY DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
+          ARCHIVE DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
+          LIBRARY DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
         )
     endif ()
 
diff --git a/flang-rt/cmake/modules/AddFlangRTOffload.cmake b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
index cbc69f3a9656a..5b6464741c9c9 100644
--- a/flang-rt/cmake/modules/AddFlangRTOffload.cmake
+++ b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
@@ -88,16 +88,16 @@ macro(enable_omp_offload_compilation name files)
         "${FLANG_RT_DEVICE_ARCHITECTURES}"
         )
 
-      set(OMP_COMPILE_OPTIONS
+      set(OMP_COMPILE_OPTIONS $<$<COMPILE_LANGUAGE:C,CXX>:
         -fopenmp
         -fvisibility=hidden
         -fopenmp-cuda-mode
         --offload-arch=${compile_for_architectures}
         # Force LTO for the device part.
         -foffload-lto
-        )
-      set_source_files_properties(${files} PROPERTIES COMPILE_OPTIONS
-        "${OMP_COMPILE_OPTIONS}"
+        >)
+      set_property(SOURCE ${files} APPEND
+        PROPERTY COMPILE_DEFINITIONS ${OMP_COMPILE_OPTIONS}
         )
       target_link_options(${name}.static PUBLIC ${OMP_COMPILE_OPTIONS})
 
@@ -105,6 +105,13 @@ macro(enable_omp_offload_compilation name files)
       set_source_files_properties(${files}
         PROPERTIES COMPILE_DEFINITIONS OMP_OFFLOAD_BUILD
         )
+
+     # If building flang-rt together with libomp, ensure that libom...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Dec 9, 2025

@llvm/pr-subscribers-flang-openmp

Author: Michael Kruse (Meinersbur)

Changes

Reapplication of #137828 and #169638

Move building the .mod files from openmp/flang to openmp/flang-rt using a shared mechanism. Motivations to do so are:

  1. Most modules are target-dependent and need to be re-compiled for each target separately, which is something the LLVM_ENABLE_RUNTIMES system already does. Prime example is iso_c_binding.mod which encodes the target's ABI. Constants such as c_long_double also have different values. Most other modules have #ifdef-enclosed code as well. For instance this caused offload targets nvptx64-nvidia-cuda/amdgpu-amd-amdhsa to use the modules files compiled for the host which may contrain uses of the types REAL(10) or REAL(16) not available for nvptx/amdgpu.

#146876
#128015
#129742
#158790

  1. CMake has support for Fortran that we should use. Among other things, it automatically determines module dependencies so there is no need to hardcode them in the CMakeLists.txt.

  2. It allows using Fortran itself to implement Flang-RT. Currently, only iso_fortran_env_impl.f90 emits object files that are needed by Fortran applications (#89403). The workaround of #95388 could be reverted (PR #169525).

If using Flang for cross-compilation or target-offloading, flang-rt must now be compiled for each target not only for the library, but also to get the target-specific module files. For instance in a bootstrapping runtime build, this can be done by adding: -DLLVM_RUNTIME_TARGETS=default;nvptx64-nvidia-cuda;amdgpu-amd-amdhsa.

Some new dependencies come into play:

  • openmp depends on flang-rt for building lib_omp.mod and lib_omp_kinds.mod. Currently, if flang-rt is not found then the modules are not built.
  • check-flang depends on flang-rt: If not found, the majority of tests are disabled. If not building in a bootstrpping build, the location of the module files can be pointed to using -DFLANG_INTRINSIC_MODULES_DIR=&lt;path&gt;, e.g. in a flang-standalone build. Alternatively, the test needing any of the intrinsic modules could be marked with REQUIRES: flangrt-modules.
  • check-flang depends on openmp: Not a change; tests requiring lib_omp.mod and lib_omp_kinds.mod those are already marked with openmp_runtime.

As intrinsic are now specific to the target, their location is moved from include/flang to &lt;resource-dir&gt;/finclude/flang/&lt;triple&gt;. The mechnism to compute the location have been moved from flang-rt (previously used to compute the location of libflang_rt.*.a) to common locations in cmake/GetToolchainDirs.cmake and runtimes/CMakeLists.txt so they can be used by both, openmp and flang-rt. Potentially the mechnism could also be shared by other libraries such as compiler-rt.

finclude was chosen because gfortran uses it as well and avoids misuse such as #include &lt;flang/iso_c_binding.mod&gt;. The search location is now determined by ToolChain in the driver, instead of by the frontend. Another subdirectory flang avoid accidental inclusion of gfortran-modules which due to compression would result in user-unfriendly errors. Now the driver adds -fintrinsic-module-path for that location to the frontend call (Just like gfortran does). -fintrinsic-module-path had to be fixed for this because ironically it was only added to searchDirectories, but not intrinsicModuleDirectories_. Since the driver determines the location, tests invoking flang -fc1 and bbc must also be passed the location by llvm-lit. This works like llvm-lit does for finding the include dirs for Clang using -print-file-name=....


Patch is 104.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/171515.diff

70 Files Affected:

  • (modified) clang/include/clang/Driver/ToolChain.h (+4)
  • (modified) clang/include/clang/Options/Options.td (+1-1)
  • (modified) clang/lib/Driver/Driver.cpp (+11)
  • (modified) clang/lib/Driver/ToolChain.cpp (+6)
  • (modified) clang/lib/Driver/ToolChains/AMDGPU.cpp (+2-1)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+8)
  • (modified) clang/lib/Driver/ToolChains/HIPAMD.cpp (+2-1)
  • (modified) clang/lib/Driver/ToolChains/HIPSPV.cpp (+2-1)
  • (renamed) cmake/Modules/GetToolchainDirs.cmake (+11)
  • (modified) flang-rt/CMakeLists.txt (+27-95)
  • (modified) flang-rt/cmake/modules/AddFlangRT.cmake (+32-6)
  • (modified) flang-rt/cmake/modules/AddFlangRTOffload.cmake (+11-4)
  • (added) flang-rt/cmake/modules/FlangRTIntrospection.cmake (+36)
  • (modified) flang-rt/lib/CMakeLists.txt (+10-5)
  • (modified) flang-rt/lib/runtime/CMakeLists.txt (+135-38)
  • (renamed) flang-rt/lib/runtime/__cuda_builtins.f90 ()
  • (renamed) flang-rt/lib/runtime/__cuda_device.f90 ()
  • (renamed) flang-rt/lib/runtime/__fortran_builtins.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/__fortran_ieee_exceptions.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/__fortran_type_info.f90 ()
  • (renamed) flang-rt/lib/runtime/__ppc_intrinsics.f90 ()
  • (renamed) flang-rt/lib/runtime/__ppc_types.f90 ()
  • (renamed) flang-rt/lib/runtime/cooperative_groups.f90 (+1)
  • (renamed) flang-rt/lib/runtime/cudadevice.f90 ()
  • (renamed) flang-rt/lib/runtime/flang_debug.f90 ()
  • (renamed) flang-rt/lib/runtime/ieee_arithmetic.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/ieee_exceptions.f90 ()
  • (renamed) flang-rt/lib/runtime/ieee_features.f90 ()
  • (renamed) flang-rt/lib/runtime/iso_c_binding.f90 ()
  • (renamed) flang-rt/lib/runtime/iso_fortran_env.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/iso_fortran_env_impl.f90 ()
  • (renamed) flang-rt/lib/runtime/mma.f90 ()
  • (modified) flang-rt/test/lit.site.cfg.py.in (+1-1)
  • (modified) flang-rt/unittests/CMakeLists.txt (+2-3)
  • (modified) flang/CMakeLists.txt (-1)
  • (modified) flang/include/flang/Frontend/CompilerInvocation.h (+7)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+13-13)
  • (modified) flang/lib/Semantics/semantics.cpp (+8-5)
  • (removed) flang/module/.clang-format (-1)
  • (modified) flang/test/CMakeLists.txt (+28-3)
  • (modified) flang/test/Driver/Inputs/ieee_arithmetic.mod (+1)
  • (modified) flang/test/Driver/Inputs/iso_fortran_env.mod (+1)
  • (added) flang/test/Driver/intrinsic-module-path.F90 (+55)
  • (removed) flang/test/Driver/intrinsic-module-path.f90 (-23)
  • (modified) flang/test/Driver/lto-fatlto.f90 (+2-2)
  • (modified) flang/test/Driver/pp-fixed-form.f90 (+2-2)
  • (modified) flang/test/Lower/HLFIR/type-bound-call-mismatch.f90 (+1-1)
  • (modified) flang/test/Lower/OpenMP/simd_aarch64.f90 (+6-1)
  • (modified) flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90 (+2-2)
  • (modified) flang/test/Preprocessing/fixed-free.f (+1-1)
  • (modified) flang/test/Preprocessing/no-pp-if.f90 (+1-1)
  • (modified) flang/test/Semantics/bug163242.f90 (+1-1)
  • (modified) flang/test/Semantics/bug164303.f90 (+1-1)
  • (modified) flang/test/lit.cfg.py (+81-13)
  • (modified) flang/test/lit.site.cfg.py.in (+3-6)
  • (modified) flang/tools/CMakeLists.txt (-1)
  • (modified) flang/tools/bbc/bbc.cpp (+5-8)
  • (removed) flang/tools/f18/CMakeLists.txt (-171)
  • (removed) flang/tools/f18/dump.cpp (-42)
  • (modified) llvm/runtimes/CMakeLists.txt (+13-11)
  • (modified) openmp/CMakeLists.txt (+9-2)
  • (modified) openmp/README.rst (+2-5)
  • (removed) openmp/cmake/modules/LibompCheckFortranFlag.cmake (-29)
  • (modified) openmp/cmake/modules/LibompHandleFlags.cmake (-11)
  • (modified) openmp/module/CMakeLists.txt (+28-61)
  • (modified) openmp/runtime/CMakeLists.txt (+1-1)
  • (modified) openmp/runtime/cmake/LibompExports.cmake (+5-5)
  • (modified) openmp/runtime/test/lit.cfg (+1)
  • (modified) openmp/runtime/test/lit.site.cfg.in (+1)
  • (modified) runtimes/CMakeLists.txt (+292-11)
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 1425714d34110..26af88242eb3e 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -538,6 +538,10 @@ class ToolChain {
   // Returns Triple without the OSs version.
   llvm::Triple getTripleWithoutOSVersion() const;
 
+  /// Returns the target-specific path for Flang's intrinsic modules in the
+  /// resource directory if it exists.
+  std::optional<std::string> getDefaultIntrinsicModuleDir() const;
+
   // Returns the target specific runtime path if it exists.
   std::optional<std::string> getRuntimePath() const;
 
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index cac122d296624..90fc78db45d05 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6124,7 +6124,7 @@ def prebind : Flag<["-"], "prebind">;
 def preload : Flag<["-"], "preload">;
 def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">,
   HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">,
-  Visibility<[ClangOption, CLOption]>;
+  Visibility<[ClangOption, FlangOption, CLOption]>;
 def print_ivar_layout : Flag<["-"], "print-ivar-layout">,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable Objective-C Ivar layout bitmap print trace">,
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 8644a271a04b5..6f0d8078825de 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -6607,6 +6607,17 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
   if (llvm::sys::fs::exists(Twine(P)))
     return std::string(P);
 
+  // With Flang, also look for instrinsic modules
+  if (IsFlangMode()) {
+    if (std::optional<std::string> IntrPath =
+            TC.getDefaultIntrinsicModuleDir()) {
+      SmallString<128> P(*IntrPath);
+      llvm::sys::path::append(P, Name);
+      if (llvm::sys::fs::exists(Twine(P)))
+        return std::string(P);
+    }
+  }
+
   SmallString<128> D(Dir);
   llvm::sys::path::append(D, "..", Name);
   if (llvm::sys::fs::exists(Twine(D)))
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 77a2c73f0d446..f8520725b9b03 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1020,6 +1020,12 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
   return {};
 }
 
+std::optional<std::string> ToolChain::getDefaultIntrinsicModuleDir() const {
+  SmallString<128> P(D.ResourceDir);
+  llvm::sys::path::append(P, "finclude", "flang");
+  return getTargetSubDirPath(P);
+}
+
 std::optional<std::string> ToolChain::getRuntimePath() const {
   SmallString<128> P(D.ResourceDir);
   llvm::sys::path::append(P, "lib");
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 87ccd40372681..d3515c8fa2362 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -858,7 +858,8 @@ void AMDGPUToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat)) {
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode()) {
     CC1Args.push_back("-fvisibility=hidden");
     CC1Args.push_back("-fapply-global-visibility-to-externs");
   }
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 2f5e93d139858..2c7a06f2893b9 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -1069,6 +1069,14 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
   CmdArgs.push_back("-resource-dir");
   CmdArgs.push_back(D.ResourceDir.c_str());
 
+  // Default intrinsic module dirs must be added after any user-provided
+  // -fintrinsic-modules-path to have lower precedence
+  if (std::optional<std::string> IntrModPath =
+          TC.getDefaultIntrinsicModuleDir()) {
+    CmdArgs.push_back("-fintrinsic-modules-path");
+    CmdArgs.push_back(Args.MakeArgString(*IntrModPath));
+  }
+
   // Offloading related options
   addOffloadOptions(C, Inputs, JA, Args, CmdArgs);
 
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index f2f64922cb404..8bfd3c887452c 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -274,7 +274,8 @@ void HIPAMDToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat)) {
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode()) {
     CC1Args.append({"-fvisibility=hidden"});
     CC1Args.push_back("-fapply-global-visibility-to-externs");
   }
diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp
index be0f49d8e1497..261adc2b1c440 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp
+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -143,7 +143,8 @@ void HIPSPVToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat))
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode())
     CC1Args.append(
         {"-fvisibility=hidden", "-fapply-global-visibility-to-externs"});
 
diff --git a/flang-rt/cmake/modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
similarity index 94%
rename from flang-rt/cmake/modules/GetToolchainDirs.cmake
rename to cmake/Modules/GetToolchainDirs.cmake
index fba12502b5946..ce2f8c294b2bc 100644
--- a/flang-rt/cmake/modules/GetToolchainDirs.cmake
+++ b/cmake/Modules/GetToolchainDirs.cmake
@@ -47,6 +47,17 @@ function (get_toolchain_library_subdir outvar)
 endfunction ()
 
 
+# Corresponds to Flang's ToolChain::getDefaultIntrinsicModuleDir().
+function (get_toolchain_module_subdir outvar)
+  set(outval "finclude/flang")
+
+  get_toolchain_arch_dirname(arch_dirname)
+  set(outval "${outval}/${arch_dirname}")
+
+  set(${outvar} "${outval}" PARENT_SCOPE)
+endfunction ()
+
+
 # Corresponds to Clang's ToolChain::getOSLibName(). Adapted from Compiler-RT.
 function (get_toolchain_os_dirname outvar)
   if (ANDROID)
diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index 50b8e834776fb..20ca6dc7124bc 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)
-
 
 list(APPEND CMAKE_MODULE_PATH
     "${FLANG_RT_SOURCE_DIR}/cmake/modules"
@@ -65,69 +31,22 @@ list(APPEND CMAKE_MODULE_PATH
 include(AddFlangRT)
 include(GetToolchainDirs)
 include(FlangCommon)
+include(FlangRTIntrospection)
 include(HandleCompilerRT)
 include(ExtendPath)
+include(CheckFortranSourceCompiles)
+include(CMakePushCheckState)
 
 
 ############################
 # Build Mode Introspection #
 ############################
 
-# Determine whether we are in the runtimes/runtimes-bins directory of a
-# bootstrap build.
-set(LLVM_TREE_AVAILABLE OFF)
-if (LLVM_LIBRARY_OUTPUT_INTDIR AND LLVM_RUNTIME_OUTPUT_INTDIR AND PACKAGE_VERSION)
-  set(LLVM_TREE_AVAILABLE ON)
-endif()
-
 # Path to LLVM development tools (FileCheck, llvm-lit, not, ...)
 set(LLVM_TOOLS_DIR "${LLVM_BINARY_DIR}/bin")
 
-# Determine build and install paths.
-# The build path is absolute, but the install dir is relative, CMake's install
-# command has to apply CMAKE_INSTALL_PREFIX itself.
-get_toolchain_library_subdir(toolchain_lib_subdir)
-if (LLVM_TREE_AVAILABLE)
-  # In a bootstrap build emit the libraries into a default search path in the
-  # build directory of the just-built compiler. This allows using the
-  # just-built compiler without specifying paths to runtime libraries.
-  #
-  # Despite Clang in the name, get_clang_resource_dir does not depend on Clang
-  # being added to the build. Flang uses the same resource dir as clang.
-  include(GetClangResourceDir)
-  get_clang_resource_dir(FLANG_RT_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
-  get_clang_resource_dir(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT)
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}")
-else ()
-  # In a standalone runtimes build, do not write into LLVM_BINARY_DIR. It may be
-  # read-only and/or shared by multiple runtimes with different build
-  # configurations (e.g. Debug/Release). Use the runtime's own lib dir like any
-  # non-toolchain library.
-  # For the install prefix, still use the resource dir assuming that Flang will
-  # be installed there using the same prefix. This is to not have a difference
-  # between bootstrap and standalone runtimes builds.
-  set(FLANG_RT_OUTPUT_RESOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
-  set(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "lib${LLVM_LIBDIR_SUFFIX}")
-endif ()
-set(FLANG_RT_INSTALL_RESOURCE_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT}"
-    CACHE PATH "Path to install runtime libraries to (default: clang resource dir)")
-extend_path(FLANG_RT_INSTALL_RESOURCE_LIB_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}")
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_PATH)
-# FIXME: For the libflang_rt.so, the toolchain resource lib dir is not a good
-#        destination because it is not a ld.so default search path.
-#        The machine where the executable is eventually executed may not be the
-#        machine where the Flang compiler and its resource dir is installed, so
-#        setting RPath by the driver is not an solution. It should belong into
-#        /usr/lib/<triple>/libflang_rt.so, like e.g. libgcc_s.so.
-#        But the linker as invoked by the Flang driver also requires
-#        libflang_rt.so to be found when linking and the resource lib dir is
-#        the only reliable location.
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_LIB_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
+# Fortran compiler not optional for building Flang-RT
+enable_language(Fortran)
 
 
 #################
@@ -137,8 +56,6 @@ cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
 # Important: flang-rt user options must be prefixed with "FLANG_RT_". Variables
 # with this prefix will be forwarded in bootstrap builds.
 
-option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
-
 # Provide an interface to link against the LLVM libc/libc++ projects directly.
 set(FLANG_RT_SUPPORTED_PROVIDERS system llvm)
 set(FLANG_RT_LIBC_PROVIDER "system" CACHE STRING "Specify C library to use. Supported values are ${FLANG_RT_SUPPORTED_PROVIDERS}.")
@@ -151,7 +68,14 @@ if (NOT "${FLANG_RT_LIBCXX_PROVIDER}" IN_LIST FLANG_RT_SUPPORTED_PROVIDERS)
   message(FATAL_ERROR "Unsupported library: '${FLANG_RT_LIBCXX_PROVIDER}'. Supported values are ${FLANG_RT_SUPPORTED_PROVIDERS}.")
 endif ()
 
-option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." ON)
+if (LLVM_RUNTIMES_TARGET MATCHES "^amdgcn|^nvptx")
+  # Compiling libraries for offload targets is currently experimental;
+  # Only build the builtin modules by default.
+  set(FLANG_RT_ENABLE_STATIC_default OFF)
+else ()
+  set(FLANG_RT_ENABLE_STATIC_default ON)
+endif ()
+option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." "${FLANG_RT_ENABLE_STATIC_default}")
 if (WIN32)
   # Windows DLL currently not implemented.
   set(FLANG_RT_ENABLE_SHARED OFF)
@@ -164,11 +88,14 @@ else ()
   #       breaking change unless the driver is changed.
   option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." OFF)
 endif ()
-if (NOT FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED)
-  message(FATAL_ERROR "
-      Must build at least one type of library
-      (FLANG_RT_ENABLE_STATIC=ON, FLANG_RT_ENABLE_SHARED=ON, or both)
-    ")
+
+
+if (FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED)
+  option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
+else ()
+  # Tests require at least one of the libraries
+  message(STATUS "Flang-RT testing disabled without either FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED")
+  set(FLANG_RT_INCLUDE_TESTS OFF)
 endif ()
 
 
@@ -186,7 +113,7 @@ elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "CUDA")
   option(FLANG_RT_CUDA_RUNTIME_PTX_WITHOUT_GLOBAL_VARS "Do not compile global variables' definitions when producing PTX library" OFF)
 elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "OpenMP")
   # Support for OpenMP offloading
-  set(FLANG_RT_DEVICE_ARCHITECTURES "all" CACHE STRING
+  set(FLANG_RT_DEVICE_ARCHITECTURES "${RUNTIMES_DEVICE_ARCHITECTURES}" CACHE STRING
       "List of OpenMP device architectures to be used to compile the Fortran runtime (e.g. 'gfx1103;sm_90')"
     )
 
@@ -234,6 +161,10 @@ check_cxx_source_compiles(
   "
   HAVE_DECL_STRERROR_S)
 
+# Look for support of REAL(16), if not already defined via command
+# line via -DFORTRAN_SUPPORTS_REAL16=YES/NO
+check_fortran_quadmath_support()
+
 # Search for clang_rt.builtins library. Need in addition to msvcrt.
 if (WIN32)
   find_compiler_rt_library(builtins FLANG_RT_BUILTINS_LIBRARY)
@@ -331,6 +262,7 @@ else ()
   add_custom_target(check-flang-rt)
 endif()
 
+
 ###################
 # Install headers #
 ###################
diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index 923507764d691..0ba485a79beb8 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -94,6 +94,10 @@ function (add_flangrt_library name)
     set(build_object ON)
   elseif (build_static AND build_shared)
     set(build_object ON)
+  elseif (NOT build_static AND NOT build_shared)
+    # If not building a library, still build the object files
+    # Needed to generate the .mod files as byproduct
+    set(build_object ON)
   endif ()
 
   # srctargets: targets that contain source files
@@ -168,14 +172,18 @@ function (add_flangrt_library name)
     if (BUILD_SHARED_LIBS)
       if (build_shared)
         set(default_target "${name_shared}")
-      else ()
+      elseif (build_static)
         set(default_target "${name_static}")
+      else ()
+        set(default_target "${name_object}")
       endif ()
     else ()
       if (build_static)
         set(default_target "${name_static}")
-      else ()
+      elseif (build_shared)
         set(default_target "${name_shared}")
+      else ()
+        set(default_target "${name_object}")
       endif ()
     endif ()
     add_library(${name}.default ALIAS "${default_target}")
@@ -190,6 +198,12 @@ function (add_flangrt_library name)
     endif ()
   endif ()
 
+  if (build_object)
+    add_library(${name}.compile ALIAS "${name_object}")
+  else ()
+    add_library(${name}.compile ALIAS "${default_target}")
+  endif ()
+
   foreach (tgtname IN LISTS libtargets)
     if (NOT WIN32)
       # Use same stem name for .a and .so. Common in UNIX environments.
@@ -219,6 +233,14 @@ function (add_flangrt_library name)
     # Minimum required C++ version for Flang-RT, even if CMAKE_CXX_STANDARD is defined to something else.
     target_compile_features(${tgtname} PRIVATE cxx_std_17)
 
+    target_compile_options(${tgtname} PRIVATE
+      # Always enable preprocessor regardless of file extension
+      "$<$<COMPILE_LANGUAGE:Fortran>:-cpp>"
+
+      # Missing type descriptors are expected for intrinsic modules
+      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-mmlir;SHELL:-ignore-missing-type-desc>"
+    )
+
     # When building the flang runtime if LTO is enabled the archive file
     # contains LLVM IR rather than object code. Currently flang is not
     # LTO aware so cannot link this file to compiled Fortran code.
@@ -226,6 +248,10 @@ function (add_flangrt_library name)
       target_compile_options(${tgtname} PRIVATE -fno-lto)
     endif ()
 
+    if (FORTRAN_SUPPORTS_REAL16)
+      target_compile_definitions(${tgtname} PRIVATE FLANG_SUPPORT_R16=1)
+    endif ()
+
     # Use compiler-specific options to disable exceptions and RTTI.
     if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
       target_compile_options(${tgtname} PRIVATE
@@ -344,13 +370,13 @@ function (add_flangrt_library name)
     if (ARG_INSTALL_WITH_TOOLCHAIN)
       set_target_properties(${tgtname}
         PROPERTIES
-          ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
-          LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
+          ARCHIVE_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
+          LIBRARY_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
         )
 
       install(TARGETS ${tgtname}
-          ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
-          LIBRARY DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
+          ARCHIVE DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
+          LIBRARY DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
         )
     endif ()
 
diff --git a/flang-rt/cmake/modules/AddFlangRTOffload.cmake b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
index cbc69f3a9656a..5b6464741c9c9 100644
--- a/flang-rt/cmake/modules/AddFlangRTOffload.cmake
+++ b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
@@ -88,16 +88,16 @@ macro(enable_omp_offload_compilation name files)
         "${FLANG_RT_DEVICE_ARCHITECTURES}"
         )
 
-      set(OMP_COMPILE_OPTIONS
+      set(OMP_COMPILE_OPTIONS $<$<COMPILE_LANGUAGE:C,CXX>:
         -fopenmp
         -fvisibility=hidden
         -fopenmp-cuda-mode
         --offload-arch=${compile_for_architectures}
         # Force LTO for the device part.
         -foffload-lto
-        )
-      set_source_files_properties(${files} PROPERTIES COMPILE_OPTIONS
-        "${OMP_COMPILE_OPTIONS}"
+        >)
+      set_property(SOURCE ${files} APPEND
+        PROPERTY COMPILE_DEFINITIONS ${OMP_COMPILE_OPTIONS}
         )
       target_link_options(${name}.static PUBLIC ${OMP_COMPILE_OPTIONS})
 
@@ -105,6 +105,13 @@ macro(enable_omp_offload_compilation name files)
       set_source_files_properties(${files}
         PROPERTIES COMPILE_DEFINITIONS OMP_OFFLOAD_BUILD
         )
+
+     # If building flang-rt together with libomp, ensure that libom...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Dec 9, 2025

@llvm/pr-subscribers-backend-amdgpu

Author: Michael Kruse (Meinersbur)

Changes

Reapplication of #137828 and #169638

Move building the .mod files from openmp/flang to openmp/flang-rt using a shared mechanism. Motivations to do so are:

  1. Most modules are target-dependent and need to be re-compiled for each target separately, which is something the LLVM_ENABLE_RUNTIMES system already does. Prime example is iso_c_binding.mod which encodes the target's ABI. Constants such as c_long_double also have different values. Most other modules have #ifdef-enclosed code as well. For instance this caused offload targets nvptx64-nvidia-cuda/amdgpu-amd-amdhsa to use the modules files compiled for the host which may contrain uses of the types REAL(10) or REAL(16) not available for nvptx/amdgpu.

#146876
#128015
#129742
#158790

  1. CMake has support for Fortran that we should use. Among other things, it automatically determines module dependencies so there is no need to hardcode them in the CMakeLists.txt.

  2. It allows using Fortran itself to implement Flang-RT. Currently, only iso_fortran_env_impl.f90 emits object files that are needed by Fortran applications (#89403). The workaround of #95388 could be reverted (PR #169525).

If using Flang for cross-compilation or target-offloading, flang-rt must now be compiled for each target not only for the library, but also to get the target-specific module files. For instance in a bootstrapping runtime build, this can be done by adding: -DLLVM_RUNTIME_TARGETS=default;nvptx64-nvidia-cuda;amdgpu-amd-amdhsa.

Some new dependencies come into play:

  • openmp depends on flang-rt for building lib_omp.mod and lib_omp_kinds.mod. Currently, if flang-rt is not found then the modules are not built.
  • check-flang depends on flang-rt: If not found, the majority of tests are disabled. If not building in a bootstrpping build, the location of the module files can be pointed to using -DFLANG_INTRINSIC_MODULES_DIR=&lt;path&gt;, e.g. in a flang-standalone build. Alternatively, the test needing any of the intrinsic modules could be marked with REQUIRES: flangrt-modules.
  • check-flang depends on openmp: Not a change; tests requiring lib_omp.mod and lib_omp_kinds.mod those are already marked with openmp_runtime.

As intrinsic are now specific to the target, their location is moved from include/flang to &lt;resource-dir&gt;/finclude/flang/&lt;triple&gt;. The mechnism to compute the location have been moved from flang-rt (previously used to compute the location of libflang_rt.*.a) to common locations in cmake/GetToolchainDirs.cmake and runtimes/CMakeLists.txt so they can be used by both, openmp and flang-rt. Potentially the mechnism could also be shared by other libraries such as compiler-rt.

finclude was chosen because gfortran uses it as well and avoids misuse such as #include &lt;flang/iso_c_binding.mod&gt;. The search location is now determined by ToolChain in the driver, instead of by the frontend. Another subdirectory flang avoid accidental inclusion of gfortran-modules which due to compression would result in user-unfriendly errors. Now the driver adds -fintrinsic-module-path for that location to the frontend call (Just like gfortran does). -fintrinsic-module-path had to be fixed for this because ironically it was only added to searchDirectories, but not intrinsicModuleDirectories_. Since the driver determines the location, tests invoking flang -fc1 and bbc must also be passed the location by llvm-lit. This works like llvm-lit does for finding the include dirs for Clang using -print-file-name=....


Patch is 104.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/171515.diff

70 Files Affected:

  • (modified) clang/include/clang/Driver/ToolChain.h (+4)
  • (modified) clang/include/clang/Options/Options.td (+1-1)
  • (modified) clang/lib/Driver/Driver.cpp (+11)
  • (modified) clang/lib/Driver/ToolChain.cpp (+6)
  • (modified) clang/lib/Driver/ToolChains/AMDGPU.cpp (+2-1)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+8)
  • (modified) clang/lib/Driver/ToolChains/HIPAMD.cpp (+2-1)
  • (modified) clang/lib/Driver/ToolChains/HIPSPV.cpp (+2-1)
  • (renamed) cmake/Modules/GetToolchainDirs.cmake (+11)
  • (modified) flang-rt/CMakeLists.txt (+27-95)
  • (modified) flang-rt/cmake/modules/AddFlangRT.cmake (+32-6)
  • (modified) flang-rt/cmake/modules/AddFlangRTOffload.cmake (+11-4)
  • (added) flang-rt/cmake/modules/FlangRTIntrospection.cmake (+36)
  • (modified) flang-rt/lib/CMakeLists.txt (+10-5)
  • (modified) flang-rt/lib/runtime/CMakeLists.txt (+135-38)
  • (renamed) flang-rt/lib/runtime/__cuda_builtins.f90 ()
  • (renamed) flang-rt/lib/runtime/__cuda_device.f90 ()
  • (renamed) flang-rt/lib/runtime/__fortran_builtins.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/__fortran_ieee_exceptions.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/__fortran_type_info.f90 ()
  • (renamed) flang-rt/lib/runtime/__ppc_intrinsics.f90 ()
  • (renamed) flang-rt/lib/runtime/__ppc_types.f90 ()
  • (renamed) flang-rt/lib/runtime/cooperative_groups.f90 (+1)
  • (renamed) flang-rt/lib/runtime/cudadevice.f90 ()
  • (renamed) flang-rt/lib/runtime/flang_debug.f90 ()
  • (renamed) flang-rt/lib/runtime/ieee_arithmetic.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/ieee_exceptions.f90 ()
  • (renamed) flang-rt/lib/runtime/ieee_features.f90 ()
  • (renamed) flang-rt/lib/runtime/iso_c_binding.f90 ()
  • (renamed) flang-rt/lib/runtime/iso_fortran_env.f90 (+1-1)
  • (renamed) flang-rt/lib/runtime/iso_fortran_env_impl.f90 ()
  • (renamed) flang-rt/lib/runtime/mma.f90 ()
  • (modified) flang-rt/test/lit.site.cfg.py.in (+1-1)
  • (modified) flang-rt/unittests/CMakeLists.txt (+2-3)
  • (modified) flang/CMakeLists.txt (-1)
  • (modified) flang/include/flang/Frontend/CompilerInvocation.h (+7)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+13-13)
  • (modified) flang/lib/Semantics/semantics.cpp (+8-5)
  • (removed) flang/module/.clang-format (-1)
  • (modified) flang/test/CMakeLists.txt (+28-3)
  • (modified) flang/test/Driver/Inputs/ieee_arithmetic.mod (+1)
  • (modified) flang/test/Driver/Inputs/iso_fortran_env.mod (+1)
  • (added) flang/test/Driver/intrinsic-module-path.F90 (+55)
  • (removed) flang/test/Driver/intrinsic-module-path.f90 (-23)
  • (modified) flang/test/Driver/lto-fatlto.f90 (+2-2)
  • (modified) flang/test/Driver/pp-fixed-form.f90 (+2-2)
  • (modified) flang/test/Lower/HLFIR/type-bound-call-mismatch.f90 (+1-1)
  • (modified) flang/test/Lower/OpenMP/simd_aarch64.f90 (+6-1)
  • (modified) flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90 (+2-2)
  • (modified) flang/test/Preprocessing/fixed-free.f (+1-1)
  • (modified) flang/test/Preprocessing/no-pp-if.f90 (+1-1)
  • (modified) flang/test/Semantics/bug163242.f90 (+1-1)
  • (modified) flang/test/Semantics/bug164303.f90 (+1-1)
  • (modified) flang/test/lit.cfg.py (+81-13)
  • (modified) flang/test/lit.site.cfg.py.in (+3-6)
  • (modified) flang/tools/CMakeLists.txt (-1)
  • (modified) flang/tools/bbc/bbc.cpp (+5-8)
  • (removed) flang/tools/f18/CMakeLists.txt (-171)
  • (removed) flang/tools/f18/dump.cpp (-42)
  • (modified) llvm/runtimes/CMakeLists.txt (+13-11)
  • (modified) openmp/CMakeLists.txt (+9-2)
  • (modified) openmp/README.rst (+2-5)
  • (removed) openmp/cmake/modules/LibompCheckFortranFlag.cmake (-29)
  • (modified) openmp/cmake/modules/LibompHandleFlags.cmake (-11)
  • (modified) openmp/module/CMakeLists.txt (+28-61)
  • (modified) openmp/runtime/CMakeLists.txt (+1-1)
  • (modified) openmp/runtime/cmake/LibompExports.cmake (+5-5)
  • (modified) openmp/runtime/test/lit.cfg (+1)
  • (modified) openmp/runtime/test/lit.site.cfg.in (+1)
  • (modified) runtimes/CMakeLists.txt (+292-11)
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 1425714d34110..26af88242eb3e 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -538,6 +538,10 @@ class ToolChain {
   // Returns Triple without the OSs version.
   llvm::Triple getTripleWithoutOSVersion() const;
 
+  /// Returns the target-specific path for Flang's intrinsic modules in the
+  /// resource directory if it exists.
+  std::optional<std::string> getDefaultIntrinsicModuleDir() const;
+
   // Returns the target specific runtime path if it exists.
   std::optional<std::string> getRuntimePath() const;
 
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index cac122d296624..90fc78db45d05 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6124,7 +6124,7 @@ def prebind : Flag<["-"], "prebind">;
 def preload : Flag<["-"], "preload">;
 def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">,
   HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">,
-  Visibility<[ClangOption, CLOption]>;
+  Visibility<[ClangOption, FlangOption, CLOption]>;
 def print_ivar_layout : Flag<["-"], "print-ivar-layout">,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable Objective-C Ivar layout bitmap print trace">,
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 8644a271a04b5..6f0d8078825de 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -6607,6 +6607,17 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
   if (llvm::sys::fs::exists(Twine(P)))
     return std::string(P);
 
+  // With Flang, also look for instrinsic modules
+  if (IsFlangMode()) {
+    if (std::optional<std::string> IntrPath =
+            TC.getDefaultIntrinsicModuleDir()) {
+      SmallString<128> P(*IntrPath);
+      llvm::sys::path::append(P, Name);
+      if (llvm::sys::fs::exists(Twine(P)))
+        return std::string(P);
+    }
+  }
+
   SmallString<128> D(Dir);
   llvm::sys::path::append(D, "..", Name);
   if (llvm::sys::fs::exists(Twine(D)))
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 77a2c73f0d446..f8520725b9b03 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1020,6 +1020,12 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
   return {};
 }
 
+std::optional<std::string> ToolChain::getDefaultIntrinsicModuleDir() const {
+  SmallString<128> P(D.ResourceDir);
+  llvm::sys::path::append(P, "finclude", "flang");
+  return getTargetSubDirPath(P);
+}
+
 std::optional<std::string> ToolChain::getRuntimePath() const {
   SmallString<128> P(D.ResourceDir);
   llvm::sys::path::append(P, "lib");
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 87ccd40372681..d3515c8fa2362 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -858,7 +858,8 @@ void AMDGPUToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat)) {
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode()) {
     CC1Args.push_back("-fvisibility=hidden");
     CC1Args.push_back("-fapply-global-visibility-to-externs");
   }
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 2f5e93d139858..2c7a06f2893b9 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -1069,6 +1069,14 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
   CmdArgs.push_back("-resource-dir");
   CmdArgs.push_back(D.ResourceDir.c_str());
 
+  // Default intrinsic module dirs must be added after any user-provided
+  // -fintrinsic-modules-path to have lower precedence
+  if (std::optional<std::string> IntrModPath =
+          TC.getDefaultIntrinsicModuleDir()) {
+    CmdArgs.push_back("-fintrinsic-modules-path");
+    CmdArgs.push_back(Args.MakeArgString(*IntrModPath));
+  }
+
   // Offloading related options
   addOffloadOptions(C, Inputs, JA, Args, CmdArgs);
 
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index f2f64922cb404..8bfd3c887452c 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -274,7 +274,8 @@ void HIPAMDToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat)) {
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode()) {
     CC1Args.append({"-fvisibility=hidden"});
     CC1Args.push_back("-fapply-global-visibility-to-externs");
   }
diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp
index be0f49d8e1497..261adc2b1c440 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp
+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -143,7 +143,8 @@ void HIPSPVToolChain::addClangTargetOptions(
   // Default to "hidden" visibility, as object level linking will not be
   // supported for the foreseeable future.
   if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
-                         options::OPT_fvisibility_ms_compat))
+                         options::OPT_fvisibility_ms_compat) &&
+      !getDriver().IsFlangMode())
     CC1Args.append(
         {"-fvisibility=hidden", "-fapply-global-visibility-to-externs"});
 
diff --git a/flang-rt/cmake/modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
similarity index 94%
rename from flang-rt/cmake/modules/GetToolchainDirs.cmake
rename to cmake/Modules/GetToolchainDirs.cmake
index fba12502b5946..ce2f8c294b2bc 100644
--- a/flang-rt/cmake/modules/GetToolchainDirs.cmake
+++ b/cmake/Modules/GetToolchainDirs.cmake
@@ -47,6 +47,17 @@ function (get_toolchain_library_subdir outvar)
 endfunction ()
 
 
+# Corresponds to Flang's ToolChain::getDefaultIntrinsicModuleDir().
+function (get_toolchain_module_subdir outvar)
+  set(outval "finclude/flang")
+
+  get_toolchain_arch_dirname(arch_dirname)
+  set(outval "${outval}/${arch_dirname}")
+
+  set(${outvar} "${outval}" PARENT_SCOPE)
+endfunction ()
+
+
 # Corresponds to Clang's ToolChain::getOSLibName(). Adapted from Compiler-RT.
 function (get_toolchain_os_dirname outvar)
   if (ANDROID)
diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index 50b8e834776fb..20ca6dc7124bc 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)
-
 
 list(APPEND CMAKE_MODULE_PATH
     "${FLANG_RT_SOURCE_DIR}/cmake/modules"
@@ -65,69 +31,22 @@ list(APPEND CMAKE_MODULE_PATH
 include(AddFlangRT)
 include(GetToolchainDirs)
 include(FlangCommon)
+include(FlangRTIntrospection)
 include(HandleCompilerRT)
 include(ExtendPath)
+include(CheckFortranSourceCompiles)
+include(CMakePushCheckState)
 
 
 ############################
 # Build Mode Introspection #
 ############################
 
-# Determine whether we are in the runtimes/runtimes-bins directory of a
-# bootstrap build.
-set(LLVM_TREE_AVAILABLE OFF)
-if (LLVM_LIBRARY_OUTPUT_INTDIR AND LLVM_RUNTIME_OUTPUT_INTDIR AND PACKAGE_VERSION)
-  set(LLVM_TREE_AVAILABLE ON)
-endif()
-
 # Path to LLVM development tools (FileCheck, llvm-lit, not, ...)
 set(LLVM_TOOLS_DIR "${LLVM_BINARY_DIR}/bin")
 
-# Determine build and install paths.
-# The build path is absolute, but the install dir is relative, CMake's install
-# command has to apply CMAKE_INSTALL_PREFIX itself.
-get_toolchain_library_subdir(toolchain_lib_subdir)
-if (LLVM_TREE_AVAILABLE)
-  # In a bootstrap build emit the libraries into a default search path in the
-  # build directory of the just-built compiler. This allows using the
-  # just-built compiler without specifying paths to runtime libraries.
-  #
-  # Despite Clang in the name, get_clang_resource_dir does not depend on Clang
-  # being added to the build. Flang uses the same resource dir as clang.
-  include(GetClangResourceDir)
-  get_clang_resource_dir(FLANG_RT_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
-  get_clang_resource_dir(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT)
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}")
-else ()
-  # In a standalone runtimes build, do not write into LLVM_BINARY_DIR. It may be
-  # read-only and/or shared by multiple runtimes with different build
-  # configurations (e.g. Debug/Release). Use the runtime's own lib dir like any
-  # non-toolchain library.
-  # For the install prefix, still use the resource dir assuming that Flang will
-  # be installed there using the same prefix. This is to not have a difference
-  # between bootstrap and standalone runtimes builds.
-  set(FLANG_RT_OUTPUT_RESOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
-  set(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "lib${LLVM_LIBDIR_SUFFIX}")
-endif ()
-set(FLANG_RT_INSTALL_RESOURCE_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT}"
-    CACHE PATH "Path to install runtime libraries to (default: clang resource dir)")
-extend_path(FLANG_RT_INSTALL_RESOURCE_LIB_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}")
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_PATH)
-# FIXME: For the libflang_rt.so, the toolchain resource lib dir is not a good
-#        destination because it is not a ld.so default search path.
-#        The machine where the executable is eventually executed may not be the
-#        machine where the Flang compiler and its resource dir is installed, so
-#        setting RPath by the driver is not an solution. It should belong into
-#        /usr/lib/<triple>/libflang_rt.so, like e.g. libgcc_s.so.
-#        But the linker as invoked by the Flang driver also requires
-#        libflang_rt.so to be found when linking and the resource lib dir is
-#        the only reliable location.
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_LIB_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
+# Fortran compiler not optional for building Flang-RT
+enable_language(Fortran)
 
 
 #################
@@ -137,8 +56,6 @@ cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
 # Important: flang-rt user options must be prefixed with "FLANG_RT_". Variables
 # with this prefix will be forwarded in bootstrap builds.
 
-option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
-
 # Provide an interface to link against the LLVM libc/libc++ projects directly.
 set(FLANG_RT_SUPPORTED_PROVIDERS system llvm)
 set(FLANG_RT_LIBC_PROVIDER "system" CACHE STRING "Specify C library to use. Supported values are ${FLANG_RT_SUPPORTED_PROVIDERS}.")
@@ -151,7 +68,14 @@ if (NOT "${FLANG_RT_LIBCXX_PROVIDER}" IN_LIST FLANG_RT_SUPPORTED_PROVIDERS)
   message(FATAL_ERROR "Unsupported library: '${FLANG_RT_LIBCXX_PROVIDER}'. Supported values are ${FLANG_RT_SUPPORTED_PROVIDERS}.")
 endif ()
 
-option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." ON)
+if (LLVM_RUNTIMES_TARGET MATCHES "^amdgcn|^nvptx")
+  # Compiling libraries for offload targets is currently experimental;
+  # Only build the builtin modules by default.
+  set(FLANG_RT_ENABLE_STATIC_default OFF)
+else ()
+  set(FLANG_RT_ENABLE_STATIC_default ON)
+endif ()
+option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." "${FLANG_RT_ENABLE_STATIC_default}")
 if (WIN32)
   # Windows DLL currently not implemented.
   set(FLANG_RT_ENABLE_SHARED OFF)
@@ -164,11 +88,14 @@ else ()
   #       breaking change unless the driver is changed.
   option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." OFF)
 endif ()
-if (NOT FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED)
-  message(FATAL_ERROR "
-      Must build at least one type of library
-      (FLANG_RT_ENABLE_STATIC=ON, FLANG_RT_ENABLE_SHARED=ON, or both)
-    ")
+
+
+if (FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED)
+  option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
+else ()
+  # Tests require at least one of the libraries
+  message(STATUS "Flang-RT testing disabled without either FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED")
+  set(FLANG_RT_INCLUDE_TESTS OFF)
 endif ()
 
 
@@ -186,7 +113,7 @@ elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "CUDA")
   option(FLANG_RT_CUDA_RUNTIME_PTX_WITHOUT_GLOBAL_VARS "Do not compile global variables' definitions when producing PTX library" OFF)
 elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "OpenMP")
   # Support for OpenMP offloading
-  set(FLANG_RT_DEVICE_ARCHITECTURES "all" CACHE STRING
+  set(FLANG_RT_DEVICE_ARCHITECTURES "${RUNTIMES_DEVICE_ARCHITECTURES}" CACHE STRING
       "List of OpenMP device architectures to be used to compile the Fortran runtime (e.g. 'gfx1103;sm_90')"
     )
 
@@ -234,6 +161,10 @@ check_cxx_source_compiles(
   "
   HAVE_DECL_STRERROR_S)
 
+# Look for support of REAL(16), if not already defined via command
+# line via -DFORTRAN_SUPPORTS_REAL16=YES/NO
+check_fortran_quadmath_support()
+
 # Search for clang_rt.builtins library. Need in addition to msvcrt.
 if (WIN32)
   find_compiler_rt_library(builtins FLANG_RT_BUILTINS_LIBRARY)
@@ -331,6 +262,7 @@ else ()
   add_custom_target(check-flang-rt)
 endif()
 
+
 ###################
 # Install headers #
 ###################
diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index 923507764d691..0ba485a79beb8 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -94,6 +94,10 @@ function (add_flangrt_library name)
     set(build_object ON)
   elseif (build_static AND build_shared)
     set(build_object ON)
+  elseif (NOT build_static AND NOT build_shared)
+    # If not building a library, still build the object files
+    # Needed to generate the .mod files as byproduct
+    set(build_object ON)
   endif ()
 
   # srctargets: targets that contain source files
@@ -168,14 +172,18 @@ function (add_flangrt_library name)
     if (BUILD_SHARED_LIBS)
       if (build_shared)
         set(default_target "${name_shared}")
-      else ()
+      elseif (build_static)
         set(default_target "${name_static}")
+      else ()
+        set(default_target "${name_object}")
       endif ()
     else ()
       if (build_static)
         set(default_target "${name_static}")
-      else ()
+      elseif (build_shared)
         set(default_target "${name_shared}")
+      else ()
+        set(default_target "${name_object}")
       endif ()
     endif ()
     add_library(${name}.default ALIAS "${default_target}")
@@ -190,6 +198,12 @@ function (add_flangrt_library name)
     endif ()
   endif ()
 
+  if (build_object)
+    add_library(${name}.compile ALIAS "${name_object}")
+  else ()
+    add_library(${name}.compile ALIAS "${default_target}")
+  endif ()
+
   foreach (tgtname IN LISTS libtargets)
     if (NOT WIN32)
       # Use same stem name for .a and .so. Common in UNIX environments.
@@ -219,6 +233,14 @@ function (add_flangrt_library name)
     # Minimum required C++ version for Flang-RT, even if CMAKE_CXX_STANDARD is defined to something else.
     target_compile_features(${tgtname} PRIVATE cxx_std_17)
 
+    target_compile_options(${tgtname} PRIVATE
+      # Always enable preprocessor regardless of file extension
+      "$<$<COMPILE_LANGUAGE:Fortran>:-cpp>"
+
+      # Missing type descriptors are expected for intrinsic modules
+      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-mmlir;SHELL:-ignore-missing-type-desc>"
+    )
+
     # When building the flang runtime if LTO is enabled the archive file
     # contains LLVM IR rather than object code. Currently flang is not
     # LTO aware so cannot link this file to compiled Fortran code.
@@ -226,6 +248,10 @@ function (add_flangrt_library name)
       target_compile_options(${tgtname} PRIVATE -fno-lto)
     endif ()
 
+    if (FORTRAN_SUPPORTS_REAL16)
+      target_compile_definitions(${tgtname} PRIVATE FLANG_SUPPORT_R16=1)
+    endif ()
+
     # Use compiler-specific options to disable exceptions and RTTI.
     if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
       target_compile_options(${tgtname} PRIVATE
@@ -344,13 +370,13 @@ function (add_flangrt_library name)
     if (ARG_INSTALL_WITH_TOOLCHAIN)
       set_target_properties(${tgtname}
         PROPERTIES
-          ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
-          LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
+          ARCHIVE_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
+          LIBRARY_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
         )
 
       install(TARGETS ${tgtname}
-          ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
-          LIBRARY DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
+          ARCHIVE DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
+          LIBRARY DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
         )
     endif ()
 
diff --git a/flang-rt/cmake/modules/AddFlangRTOffload.cmake b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
index cbc69f3a9656a..5b6464741c9c9 100644
--- a/flang-rt/cmake/modules/AddFlangRTOffload.cmake
+++ b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
@@ -88,16 +88,16 @@ macro(enable_omp_offload_compilation name files)
         "${FLANG_RT_DEVICE_ARCHITECTURES}"
         )
 
-      set(OMP_COMPILE_OPTIONS
+      set(OMP_COMPILE_OPTIONS $<$<COMPILE_LANGUAGE:C,CXX>:
         -fopenmp
         -fvisibility=hidden
         -fopenmp-cuda-mode
         --offload-arch=${compile_for_architectures}
         # Force LTO for the device part.
         -foffload-lto
-        )
-      set_source_files_properties(${files} PROPERTIES COMPILE_OPTIONS
-        "${OMP_COMPILE_OPTIONS}"
+        >)
+      set_property(SOURCE ${files} APPEND
+        PROPERTY COMPILE_DEFINITIONS ${OMP_COMPILE_OPTIONS}
         )
       target_link_options(${name}.static PUBLIC ${OMP_COMPILE_OPTIONS})
 
@@ -105,6 +105,13 @@ macro(enable_omp_offload_compilation name files)
       set_source_files_properties(${files}
         PROPERTIES COMPILE_DEFINITIONS OMP_OFFLOAD_BUILD
         )
+
+     # If building flang-rt together with libomp, ensure that libom...
[truncated]

@petrhosek
Copy link
Member

Would it be possible to break up this change into multiple PRs? Specifically, I believe the Clang driver changes, moving of GetToolchainDirs.cmake to cmake/Modules, and changes to runtimes/CMakeLists.txt would ideally be split into separate PRs and merged first to reduce the size of this change which is quite large to review as is.

@Meinersbur
Copy link
Member Author

The changes to the Clang driver implement looking for the new location of the module files. Committing either one without the other will result in those modules not being found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:AMDGPU clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' cmake Build system in general and CMake in particular flang:driver flang:fir-hlfir flang:openmp flang:semantics flang Flang issues not falling into any other category openmp:libomp OpenMP host runtime

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants