Skip to content

Commit 86fbaef

Browse files
authored
[Flang] Move builtin .mod generation into runtimes (#137828)
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. Most other modules have `#ifdef`-enclosed code as well. 2. 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. 3. 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. 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. 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 a11e734 commit 86fbaef

Some content is hidden

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

64 files changed

+705
-528
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
@@ -6082,7 +6082,7 @@ def prebind : Flag<["-"], "prebind">;
60826082
def preload : Flag<["-"], "preload">;
60836083
def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">,
60846084
HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">,
6085-
Visibility<[ClangOption, CLOption]>;
6085+
Visibility<[ClangOption, FlangOption, CLOption]>;
60866086
def print_ivar_layout : Flag<["-"], "print-ivar-layout">,
60876087
Visibility<[ClangOption, CC1Option]>,
60886088
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
@@ -6602,6 +6602,17 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
66026602
if (llvm::sys::fs::exists(Twine(P)))
66036603
return std::string(P);
66046604

6605+
// With Flang, also look for instrinsic modules
6606+
if (IsFlangMode()) {
6607+
if (std::optional<std::string> IntrPath =
6608+
TC.getDefaultIntrinsicModuleDir()) {
6609+
SmallString<128> P(*IntrPath);
6610+
llvm::sys::path::append(P, Name);
6611+
if (llvm::sys::fs::exists(Twine(P)))
6612+
return std::string(P);
6613+
}
6614+
}
6615+
66056616
SmallString<128> D(Dir);
66066617
llvm::sys::path::append(D, "..", Name);
66076618
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/Flang.cpp

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

1063+
// Default intrinsic module dirs must be added after any user-provided
1064+
// -fintrinsic-modules-path to have lower precedence
1065+
if (std::optional<std::string> IntrModPath =
1066+
TC.getDefaultIntrinsicModuleDir()) {
1067+
CmdArgs.push_back("-fintrinsic-modules-path");
1068+
CmdArgs.push_back(Args.MakeArgString(*IntrModPath));
1069+
}
1070+
10631071
// Offloading related options
10641072
addOffloadOptions(C, Inputs, JA, Args, CmdArgs);
10651073

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: 11 additions & 86 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,24 @@ 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)
50+
51+
flang_module_fortran_enable()
13152

13253

13354
#################
@@ -234,6 +155,10 @@ check_cxx_source_compiles(
234155
"
235156
HAVE_DECL_STRERROR_S)
236157

158+
# Look for support of REAL(16), if not already defined via command
159+
# line via -DFORTRAN_SUPPORTS_REAL16=YES/NO
160+
check_fortran_quadmath_support()
161+
237162
# Search for clang_rt.builtins library. Need in addition to msvcrt.
238163
if (WIN32)
239164
find_compiler_rt_library(builtins FLANG_RT_BUILTINS_LIBRARY)

flang-rt/cmake/modules/AddFlangRT.cmake

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,12 @@ function (add_flangrt_library name)
190190
endif ()
191191
endif ()
192192

193+
if (build_object)
194+
add_library(${name}.compile ALIAS "${name_object}")
195+
else ()
196+
add_library(${name}.compile ALIAS "${default_target}")
197+
endif ()
198+
193199
foreach (tgtname IN LISTS libtargets)
194200
if (NOT WIN32)
195201
# Use same stem name for .a and .so. Common in UNIX environments.
@@ -219,13 +225,28 @@ function (add_flangrt_library name)
219225
# Minimum required C++ version for Flang-RT, even if CMAKE_CXX_STANDARD is defined to something else.
220226
target_compile_features(${tgtname} PRIVATE cxx_std_17)
221227

228+
target_compile_options(${tgtname} PRIVATE
229+
# Always enable preprocessor regardless of file extention
230+
"$<$<COMPILE_LANGUAGE:Fortran>:-cpp>"
231+
232+
# Missing type descriptors are expected for intrinsic modules
233+
"$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-mmlir;SHELL:-ignore-missing-type-desc>"
234+
235+
# Flang bug workaround: Reformating of cooked token buffer causes identifier to be split between lines
236+
"$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-Xflang;SHELL:-fno-reformat>"
237+
)
238+
222239
# When building the flang runtime if LTO is enabled the archive file
223240
# contains LLVM IR rather than object code. Currently flang is not
224241
# LTO aware so cannot link this file to compiled Fortran code.
225242
if (FLANG_RT_HAS_FNO_LTO_FLAG)
226243
target_compile_options(${tgtname} PRIVATE -fno-lto)
227244
endif ()
228245

246+
if (FORTRAN_SUPPORTS_REAL16)
247+
target_compile_definitions(${tgtname} PRIVATE FLANG_SUPPORT_R16=1)
248+
endif ()
249+
229250
# Use compiler-specific options to disable exceptions and RTTI.
230251
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
231252
target_compile_options(${tgtname} PRIVATE
@@ -344,13 +365,13 @@ function (add_flangrt_library name)
344365
if (ARG_INSTALL_WITH_TOOLCHAIN)
345366
set_target_properties(${tgtname}
346367
PROPERTIES
347-
ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
348-
LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
368+
ARCHIVE_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
369+
LIBRARY_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
349370
)
350371

351372
install(TARGETS ${tgtname}
352-
ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
353-
LIBRARY DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
373+
ARCHIVE DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
374+
LIBRARY DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
354375
)
355376
endif ()
356377

flang-rt/cmake/modules/AddFlangRTOffload.cmake

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,23 +88,29 @@ macro(enable_omp_offload_compilation name files)
8888
"${FLANG_RT_DEVICE_ARCHITECTURES}"
8989
)
9090

91-
set(OMP_COMPILE_OPTIONS
91+
set(OMP_COMPILE_OPTIONS $<$<COMPILE_LANGUAGE:C,CXX>:
9292
-fopenmp
9393
-fvisibility=hidden
9494
-fopenmp-cuda-mode
9595
--offload-arch=${compile_for_architectures}
9696
# Force LTO for the device part.
9797
-foffload-lto
98-
)
99-
set_source_files_properties(${files} PROPERTIES COMPILE_OPTIONS
100-
"${OMP_COMPILE_OPTIONS}"
98+
>)
99+
set_property(SOURCE ${files} APPEND
100+
PROPERTY COMPILE_DEFINITIONS ${OMP_COMPILE_OPTIONS}
101101
)
102102
target_link_options(${name}.static PUBLIC ${OMP_COMPILE_OPTIONS})
103103

104104
# Enable "declare target" in the source code.
105105
set_source_files_properties(${files}
106106
PROPERTIES COMPILE_DEFINITIONS OMP_OFFLOAD_BUILD
107107
)
108+
109+
# If building flang-rt together with libomp, ensure that libomp is built first and found because -fopenmp will try to link it.
110+
if (TARGET omp)
111+
add_dependencies(${name} omp)
112+
target_link_options(${name}.static PUBLIC "-L$<TARGET_FILE_DIR:omp>")
113+
endif ()
108114
else()
109115
message(FATAL_ERROR
110116
"Flang-rt build with OpenMP offload is not supported for these compilers:\n"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#===-- cmake/modules/FlangRTIntrospection.cmake ----------------------------===#
2+
#
3+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
# See https://llvm.org/LICENSE.txt for license information.
5+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
#
7+
#===------------------------------------------------------------------------===#
8+
9+
10+
# Check whether the Fortran compiler supports real(16)/quadmath types
11+
#
12+
# Implementation notes:
13+
# * FORTRAN_SUPPORTS_REAL16 can be set externally in a bootstrapping-runtimes
14+
# build to ensure consistency of real(16) support between compiler and
15+
# runtime.
16+
#
17+
# * Does not work with Flang and CMake < 3.24
18+
#
19+
# * This is intentionally wrapped in a function to get its own namespace for
20+
# CMAKE_REQUIRED_FLAGS and CMAKE_TRY_COMPILE_TARGET_TYPE. In particular,
21+
# cmake_pop_check_state() does not reset CMAKE_TRY_COMPILE_TARGET_TYPE,
22+
# causing later try_compile invocations to fail. If you see
23+
# enable_language(CUDA) failing because CMAKE_RANLIB is empty, this is the
24+
# reason.
25+
function (check_fortran_quadmath_support)
26+
cmake_push_check_state(RESET)
27+
set(CMAKE_REQUIRED_FLAGS "-ffree-form")
28+
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") # Skip link step
29+
check_fortran_source_compiles([[
30+
subroutine test_quadmath
31+
real(16) :: var1
32+
end
33+
]]
34+
FORTRAN_SUPPORTS_REAL16
35+
)
36+
cmake_pop_check_state()
37+
endfunction ()

0 commit comments

Comments
 (0)