Skip to content

Commit 7675fc7

Browse files
authored
[Flang] Move builtin .mod generation into runtimes (Reapply #137828) (#169638)
Reapplication of #137828, changes: * Workaround CMAKE_Fortran_PREPROCESS_SOURCE issue for CMake < 2.24: The issue is that `try_compile` does not forward manually-defined compiler flang variables to the test build environment; instead of just a negative test result, it aborts the configuration step itself. To be fair, manually defining these variables is deprecated since at least CMake 3.6. * Missing flang cmd line flags for CMake < 3.28 `-target=`, `-O2`, `-O3` * It is now possible to set FLANG_RT_ENABLED_STATIC=OFF and FLANG_RT_ENABLE_SHARED=OFF at the same and is the default for amdgpu and nvptx targets. In this mode, only the .mod files are compiled -- necessary for module files in lib/clang/22/finclude/flang/(nvptx64-nvidia-cuda|amdgpu-amd-amdhsa)/*.mod to be available. * For compiling omp_lib.mod for nvptx and amdgpu, the module build functionality must be hoisted out if openmp's runtime/ directory which is only included for host targets. This PR now requires #169909. 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](https://github.com/llvm/llvm-project/blob/d748c81218bee39dafb9cc0c00ed7831a3ed44c3/flang-rt/lib/runtime/iso_c_binding.f90#L77-L81). 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 3. 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. 4. 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=<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` avoids 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=...`.
1 parent d8e651f commit 7675fc7

File tree

70 files changed

+877
-595
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+877
-595
lines changed

clang/include/clang/Driver/ToolChain.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,10 @@ class ToolChain {
538538
// Returns Triple without the OSs version.
539539
llvm::Triple getTripleWithoutOSVersion() const;
540540

541+
/// Returns the target-specific path for Flang's intrinsic modules in the
542+
/// resource directory if it exists.
543+
std::optional<std::string> getDefaultIntrinsicModuleDir() const;
544+
541545
// Returns the target specific runtime path if it exists.
542546
std::optional<std::string> getRuntimePath() const;
543547

clang/include/clang/Options/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6124,7 +6124,7 @@ def prebind : Flag<["-"], "prebind">;
61246124
def preload : Flag<["-"], "preload">;
61256125
def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">,
61266126
HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">,
6127-
Visibility<[ClangOption, CLOption]>;
6127+
Visibility<[ClangOption, FlangOption, CLOption]>;
61286128
def print_ivar_layout : Flag<["-"], "print-ivar-layout">,
61296129
Visibility<[ClangOption, CC1Option]>,
61306130
HelpText<"Enable Objective-C Ivar layout bitmap print trace">,

clang/lib/Driver/Driver.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6607,6 +6607,17 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
66076607
if (llvm::sys::fs::exists(Twine(P)))
66086608
return std::string(P);
66096609

6610+
// With Flang, also look for instrinsic modules
6611+
if (IsFlangMode()) {
6612+
if (std::optional<std::string> IntrPath =
6613+
TC.getDefaultIntrinsicModuleDir()) {
6614+
SmallString<128> P(*IntrPath);
6615+
llvm::sys::path::append(P, Name);
6616+
if (llvm::sys::fs::exists(Twine(P)))
6617+
return std::string(P);
6618+
}
6619+
}
6620+
66106621
SmallString<128> D(Dir);
66116622
llvm::sys::path::append(D, "..", Name);
66126623
if (llvm::sys::fs::exists(Twine(D)))

clang/lib/Driver/ToolChain.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,12 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
10201020
return {};
10211021
}
10221022

1023+
std::optional<std::string> ToolChain::getDefaultIntrinsicModuleDir() const {
1024+
SmallString<128> P(D.ResourceDir);
1025+
llvm::sys::path::append(P, "finclude", "flang");
1026+
return getTargetSubDirPath(P);
1027+
}
1028+
10231029
std::optional<std::string> ToolChain::getRuntimePath() const {
10241030
SmallString<128> P(D.ResourceDir);
10251031
llvm::sys::path::append(P, "lib");

clang/lib/Driver/ToolChains/AMDGPU.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,8 @@ void AMDGPUToolChain::addClangTargetOptions(
858858
// Default to "hidden" visibility, as object level linking will not be
859859
// supported for the foreseeable future.
860860
if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
861-
options::OPT_fvisibility_ms_compat)) {
861+
options::OPT_fvisibility_ms_compat) &&
862+
!getDriver().IsFlangMode()) {
862863
CC1Args.push_back("-fvisibility=hidden");
863864
CC1Args.push_back("-fapply-global-visibility-to-externs");
864865
}

clang/lib/Driver/ToolChains/Flang.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,14 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
10691069
CmdArgs.push_back("-resource-dir");
10701070
CmdArgs.push_back(D.ResourceDir.c_str());
10711071

1072+
// Default intrinsic module dirs must be added after any user-provided
1073+
// -fintrinsic-modules-path to have lower precedence
1074+
if (std::optional<std::string> IntrModPath =
1075+
TC.getDefaultIntrinsicModuleDir()) {
1076+
CmdArgs.push_back("-fintrinsic-modules-path");
1077+
CmdArgs.push_back(Args.MakeArgString(*IntrModPath));
1078+
}
1079+
10721080
// Offloading related options
10731081
addOffloadOptions(C, Inputs, JA, Args, CmdArgs);
10741082

clang/lib/Driver/ToolChains/HIPAMD.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ void HIPAMDToolChain::addClangTargetOptions(
274274
// Default to "hidden" visibility, as object level linking will not be
275275
// supported for the foreseeable future.
276276
if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
277-
options::OPT_fvisibility_ms_compat)) {
277+
options::OPT_fvisibility_ms_compat) &&
278+
!getDriver().IsFlangMode()) {
278279
CC1Args.append({"-fvisibility=hidden"});
279280
CC1Args.push_back("-fapply-global-visibility-to-externs");
280281
}

clang/lib/Driver/ToolChains/HIPSPV.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ void HIPSPVToolChain::addClangTargetOptions(
143143
// Default to "hidden" visibility, as object level linking will not be
144144
// supported for the foreseeable future.
145145
if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
146-
options::OPT_fvisibility_ms_compat))
146+
options::OPT_fvisibility_ms_compat) &&
147+
!getDriver().IsFlangMode())
147148
CC1Args.append(
148149
{"-fvisibility=hidden", "-fapply-global-visibility-to-externs"});
149150

flang-rt/cmake/modules/GetToolchainDirs.cmake renamed to cmake/Modules/GetToolchainDirs.cmake

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ function (get_toolchain_library_subdir outvar)
4747
endfunction ()
4848

4949

50+
# Corresponds to Flang's ToolChain::getDefaultIntrinsicModuleDir().
51+
function (get_toolchain_module_subdir outvar)
52+
set(outval "finclude/flang")
53+
54+
get_toolchain_arch_dirname(arch_dirname)
55+
set(outval "${outval}/${arch_dirname}")
56+
57+
set(${outvar} "${outval}" PARENT_SCOPE)
58+
endfunction ()
59+
60+
5061
# Corresponds to Clang's ToolChain::getOSLibName(). Adapted from Compiler-RT.
5162
function (get_toolchain_os_dirname outvar)
5263
if (ANDROID)

flang-rt/CMakeLists.txt

Lines changed: 27 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -23,40 +23,6 @@ set(FLANG_RT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
2323
set(FLANG_RT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
2424
set(FLANG_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../flang")
2525

26-
# CMake 3.24 is the first version of CMake that directly recognizes Flang.
27-
# LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang.
28-
if (CMAKE_VERSION VERSION_LESS "3.24")
29-
cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
30-
if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
31-
include(CMakeForceCompiler)
32-
CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
33-
34-
set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
35-
set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
36-
37-
set(CMAKE_Fortran_SUBMODULE_SEP "-")
38-
set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
39-
40-
set(CMAKE_Fortran_PREPROCESS_SOURCE
41-
"<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
42-
43-
set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
44-
set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
45-
46-
set(CMAKE_Fortran_MODDIR_FLAG "-module-dir")
47-
48-
set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
49-
set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
50-
set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
51-
52-
set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
53-
54-
set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
55-
set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
56-
endif ()
57-
endif ()
58-
enable_language(Fortran)
59-
6026

6127
list(APPEND CMAKE_MODULE_PATH
6228
"${FLANG_RT_SOURCE_DIR}/cmake/modules"
@@ -65,69 +31,22 @@ list(APPEND CMAKE_MODULE_PATH
6531
include(AddFlangRT)
6632
include(GetToolchainDirs)
6733
include(FlangCommon)
34+
include(FlangRTIntrospection)
6835
include(HandleCompilerRT)
6936
include(ExtendPath)
37+
include(CheckFortranSourceCompiles)
38+
include(CMakePushCheckState)
7039

7140

7241
############################
7342
# Build Mode Introspection #
7443
############################
7544

76-
# Determine whether we are in the runtimes/runtimes-bins directory of a
77-
# bootstrap build.
78-
set(LLVM_TREE_AVAILABLE OFF)
79-
if (LLVM_LIBRARY_OUTPUT_INTDIR AND LLVM_RUNTIME_OUTPUT_INTDIR AND PACKAGE_VERSION)
80-
set(LLVM_TREE_AVAILABLE ON)
81-
endif()
82-
8345
# Path to LLVM development tools (FileCheck, llvm-lit, not, ...)
8446
set(LLVM_TOOLS_DIR "${LLVM_BINARY_DIR}/bin")
8547

86-
# Determine build and install paths.
87-
# The build path is absolute, but the install dir is relative, CMake's install
88-
# command has to apply CMAKE_INSTALL_PREFIX itself.
89-
get_toolchain_library_subdir(toolchain_lib_subdir)
90-
if (LLVM_TREE_AVAILABLE)
91-
# In a bootstrap build emit the libraries into a default search path in the
92-
# build directory of the just-built compiler. This allows using the
93-
# just-built compiler without specifying paths to runtime libraries.
94-
#
95-
# Despite Clang in the name, get_clang_resource_dir does not depend on Clang
96-
# being added to the build. Flang uses the same resource dir as clang.
97-
include(GetClangResourceDir)
98-
get_clang_resource_dir(FLANG_RT_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
99-
get_clang_resource_dir(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT)
100-
101-
extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}")
102-
else ()
103-
# In a standalone runtimes build, do not write into LLVM_BINARY_DIR. It may be
104-
# read-only and/or shared by multiple runtimes with different build
105-
# configurations (e.g. Debug/Release). Use the runtime's own lib dir like any
106-
# non-toolchain library.
107-
# For the install prefix, still use the resource dir assuming that Flang will
108-
# be installed there using the same prefix. This is to not have a difference
109-
# between bootstrap and standalone runtimes builds.
110-
set(FLANG_RT_OUTPUT_RESOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
111-
set(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
112-
113-
extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "lib${LLVM_LIBDIR_SUFFIX}")
114-
endif ()
115-
set(FLANG_RT_INSTALL_RESOURCE_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT}"
116-
CACHE PATH "Path to install runtime libraries to (default: clang resource dir)")
117-
extend_path(FLANG_RT_INSTALL_RESOURCE_LIB_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}")
118-
cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_DIR)
119-
cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_PATH)
120-
# FIXME: For the libflang_rt.so, the toolchain resource lib dir is not a good
121-
# destination because it is not a ld.so default search path.
122-
# The machine where the executable is eventually executed may not be the
123-
# machine where the Flang compiler and its resource dir is installed, so
124-
# setting RPath by the driver is not an solution. It should belong into
125-
# /usr/lib/<triple>/libflang_rt.so, like e.g. libgcc_s.so.
126-
# But the linker as invoked by the Flang driver also requires
127-
# libflang_rt.so to be found when linking and the resource lib dir is
128-
# the only reliable location.
129-
cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_LIB_DIR)
130-
cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
48+
# Fortran compiler not optional for building Flang-RT
49+
enable_language(Fortran)
13150

13251

13352
#################
@@ -137,8 +56,6 @@ cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
13756
# Important: flang-rt user options must be prefixed with "FLANG_RT_". Variables
13857
# with this prefix will be forwarded in bootstrap builds.
13958

140-
option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
141-
14259
# Provide an interface to link against the LLVM libc/libc++ projects directly.
14360
set(FLANG_RT_SUPPORTED_PROVIDERS system llvm)
14461
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)
15168
message(FATAL_ERROR "Unsupported library: '${FLANG_RT_LIBCXX_PROVIDER}'. Supported values are ${FLANG_RT_SUPPORTED_PROVIDERS}.")
15269
endif ()
15370

154-
option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." ON)
71+
if (LLVM_RUNTIMES_TARGET MATCHES "^amdgcn|^nvptx")
72+
# Compiling libraries for offload targets is currently experimental;
73+
# Only build the builtin modules by default.
74+
set(FLANG_RT_ENABLE_STATIC_default OFF)
75+
else ()
76+
set(FLANG_RT_ENABLE_STATIC_default ON)
77+
endif ()
78+
option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." "${FLANG_RT_ENABLE_STATIC_default}")
15579
if (WIN32)
15680
# Windows DLL currently not implemented.
15781
set(FLANG_RT_ENABLE_SHARED OFF)
@@ -164,11 +88,14 @@ else ()
16488
# breaking change unless the driver is changed.
16589
option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." OFF)
16690
endif ()
167-
if (NOT FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED)
168-
message(FATAL_ERROR "
169-
Must build at least one type of library
170-
(FLANG_RT_ENABLE_STATIC=ON, FLANG_RT_ENABLE_SHARED=ON, or both)
171-
")
91+
92+
93+
if (FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED)
94+
option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}")
95+
else ()
96+
# Tests require at least one of the libraries
97+
message(STATUS "Flang-RT testing disabled without either FLANG_RT_ENABLE_STATIC OR FLANG_RT_ENABLE_SHARED")
98+
set(FLANG_RT_INCLUDE_TESTS OFF)
17299
endif ()
173100

174101

@@ -186,7 +113,7 @@ elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "CUDA")
186113
option(FLANG_RT_CUDA_RUNTIME_PTX_WITHOUT_GLOBAL_VARS "Do not compile global variables' definitions when producing PTX library" OFF)
187114
elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "OpenMP")
188115
# Support for OpenMP offloading
189-
set(FLANG_RT_DEVICE_ARCHITECTURES "all" CACHE STRING
116+
set(FLANG_RT_DEVICE_ARCHITECTURES "${RUNTIMES_DEVICE_ARCHITECTURES}" CACHE STRING
190117
"List of OpenMP device architectures to be used to compile the Fortran runtime (e.g. 'gfx1103;sm_90')"
191118
)
192119

@@ -234,6 +161,10 @@ check_cxx_source_compiles(
234161
"
235162
HAVE_DECL_STRERROR_S)
236163

164+
# Look for support of REAL(16), if not already defined via command
165+
# line via -DFORTRAN_SUPPORTS_REAL16=YES/NO
166+
check_fortran_quadmath_support()
167+
237168
# Search for clang_rt.builtins library. Need in addition to msvcrt.
238169
if (WIN32)
239170
find_compiler_rt_library(builtins FLANG_RT_BUILTINS_LIBRARY)
@@ -331,6 +262,7 @@ else ()
331262
add_custom_target(check-flang-rt)
332263
endif()
333264

265+
334266
###################
335267
# Install headers #
336268
###################

0 commit comments

Comments
 (0)