[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=...`.
This commit is contained in:
Michael Kruse
2025-11-25 10:33:58 +01:00
committed by GitHub
parent a11e7347fb
commit 86fbaef99a
64 changed files with 704 additions and 527 deletions

View File

@@ -538,6 +538,10 @@ public:
// 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;

View File

@@ -6082,7 +6082,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">,

View File

@@ -6602,6 +6602,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)))

View File

@@ -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");

View File

@@ -1060,6 +1060,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);

View File

@@ -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)

View File

@@ -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,24 @@ 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)
# Fortran compiler not optional for building Flang-RT
enable_language(Fortran)
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)
flang_module_fortran_enable()
#################
@@ -234,6 +155,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)

View File

@@ -190,6 +190,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 +225,17 @@ 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 extention
"$<$<COMPILE_LANGUAGE:Fortran>:-cpp>"
# Missing type descriptors are expected for intrinsic modules
"$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-mmlir;SHELL:-ignore-missing-type-desc>"
# Flang bug workaround: Reformating of cooked token buffer causes identifier to be split between lines
"$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-Xflang;SHELL:-fno-reformat>"
)
# 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 +243,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 +365,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 ()

View File

@@ -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,12 @@ 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 libomp is built first and found because -fopenmp will try to link it.
if (TARGET omp)
add_dependencies(${name} omp)
target_link_options(${name}.static PUBLIC "-L$<TARGET_FILE_DIR:omp>")
endif ()
else()
message(FATAL_ERROR
"Flang-rt build with OpenMP offload is not supported for these compilers:\n"

View File

@@ -0,0 +1,37 @@
#===-- cmake/modules/FlangRTIntrospection.cmake ----------------------------===#
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===------------------------------------------------------------------------===#
# Check whether the Fortran compiler supports real(16)/quadmath types
#
# Implementation notes:
# * FORTRAN_SUPPORTS_REAL16 can be set externally in a bootstrapping-runtimes
# build to ensure consistency of real(16) support between compiler and
# runtime.
#
# * Does not work with Flang and CMake < 3.24
#
# * This is intentionally wrapped in a function to get its own namespace for
# CMAKE_REQUIRED_FLAGS and CMAKE_TRY_COMPILE_TARGET_TYPE. In particular,
# cmake_pop_check_state() does not reset CMAKE_TRY_COMPILE_TARGET_TYPE,
# causing later try_compile invocations to fail. If you see
# enable_language(CUDA) failing because CMAKE_RANLIB is empty, this is the
# reason.
function (check_fortran_quadmath_support)
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_FLAGS "-ffree-form")
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") # Skip link step
check_fortran_source_compiles([[
subroutine test_quadmath
real(16) :: var1
end
]]
FORTRAN_SUPPORTS_REAL16
)
cmake_pop_check_state()
endfunction ()

View File

@@ -12,6 +12,13 @@ find_package(Backtrace)
set(HAVE_BACKTRACE ${Backtrace_FOUND})
set(BACKTRACE_HEADER ${Backtrace_HEADER})
# Module sources that are required by other modules
set(intrinsics_sources
__fortran_builtins.f90
__cuda_builtins.f90
)
# List of files that are buildable for all devices.
set(supported_sources
${FLANG_SOURCE_DIR}/lib/Decimal/binary-to-decimal.cpp
@@ -73,7 +80,16 @@ set(supported_sources
# List of source not used for GPU offloading.
set(host_sources
${FLANG_SOURCE_DIR}/module/iso_fortran_env_impl.f90
__fortran_ieee_exceptions.f90
__fortran_type_info.f90
iso_fortran_env.f90
ieee_arithmetic.f90
ieee_exceptions.f90
ieee_features.f90
iso_c_binding.f90
iso_fortran_env_impl.f90
iso_fortran_env.f90
command.cpp
complex-powi.cpp
complex-reduction.c
@@ -88,8 +104,32 @@ set(host_sources
temporary-stack.cpp
time-intrinsic.cpp
unit-map.cpp
__cuda_device.f90
cooperative_groups.f90
cudadevice.f90
)
if (LLVM_TARGET_TRIPLE MATCHES "^ppc|^powerpc")
list(APPEND intrinsics_sources
__ppc_types.f90
)
list(APPEND host_sources
__ppc_intrinsics.f90
mma.f90
)
endif ()
# Compile as CUDA-Fortran, not directly supported by CMake
set_property(SOURCE
__cuda_device.f90
cooperative_groups.f90
cudadevice.f90
APPEND PROPERTY
COMPILE_OPTIONS --offload-host-only -xcuda
)
# Sources that can be compiled directly for the GPU.
set(gpu_sources
${FLANG_SOURCE_DIR}/lib/Decimal/binary-to-decimal.cpp
@@ -175,19 +215,42 @@ else ()
set(f128_sources "")
endif ()
if ("${LLVM_RUNTIMES_TARGET}" MATCHES "^amdgcn|^nvptx")
if (LLVM_RUNTIMES_TARGET MATCHES "^amdgcn|^nvptx")
set(sources ${gpu_sources})
elseif(FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "CUDA")
set(sources ${supported_sources})
else ()
set(sources ${supported_sources} ${host_sources} ${f128_sources})
endif ()
# check-flang depends on this to build intrinsic modules
if (NOT TARGET flang-rt-mod)
add_custom_target(flang-rt-mod)
endif ()
if (NOT WIN32)
# CMake ignores intrinsic USE dependencies
# CMake has an option Fortran_BUILDING_INSTRINSIC_MODULES/Fortran_BUILDING_INTRINSIC_MODULES
# to disable this behavior, unfortunately it does not work with Ninja
# (https://gitlab.kitware.com/cmake/cmake/-/issues/26803)
# As a workaround, we build those intrinsic modules first such that the main
# runtime can depend on it.
add_flangrt_library(flang_rt.intrinsics.obj OBJECT
${intrinsics_sources}
)
# This barrier exists to force all of the intrinsic modules of
# flang_rt.intrinsics.obj to be built before anything that depends on it.
# Without it, CMake/Ninja seem to think that the modules of
# flang_rt.intrinsics.obj can be built concurrently to those in
# flang_rt.runtime.
add_custom_target(flang_rt.intrinsics
COMMENT "Intrinsic module dependency barrier"
)
add_dependencies(flang_rt.intrinsics flang_rt.intrinsics.obj)
add_flangrt_library(flang_rt.runtime STATIC SHARED
${sources}
LINK_LIBRARIES ${Backtrace_LIBRARY}
${sources} $<TARGET_OBJECTS:flang_rt.intrinsics.obj>
LINK_LIBRARIES flang_rt.intrinsics.obj ${Backtrace_LIBRARY}
INSTALL_WITH_TOOLCHAIN
ADDITIONAL_HEADERS ${public_headers} ${private_headers}
)
@@ -198,6 +261,13 @@ if (NOT WIN32)
# Select a default runtime, which is used for unit and regression tests.
get_target_property(default_target flang_rt.runtime.default ALIASED_TARGET)
add_library(flang_rt.runtime.unittest ALIAS "${default_target}")
# Select a target that compiles the sources to build the public module files.
get_target_property(compile_target flang_rt.runtime.compile ALIASED_TARGET)
flang_module_target(flang_rt.intrinsics.obj PUBLIC)
flang_module_target(${compile_target} PUBLIC)
add_dependencies(${compile_target} flang_rt.intrinsics)
add_dependencies(flang-rt-mod flang_rt.intrinsics ${compile_target})
else()
# Target for building all versions of the runtime
add_custom_target(flang_rt.runtime)
@@ -205,12 +275,23 @@ else()
function (add_win_flangrt_runtime libtype suffix msvc_lib)
set(name "flang_rt.runtime.${suffix}")
add_flangrt_library(${name}.intrinsics.obj OBJECT
${intrinsics_sources}
)
add_custom_target(${name}.intrinsics
COMMAND echo "${name} Dependency barrier"
COMMENT "Intrinsic module dependency barrier"
)
add_dependencies(${name}.intrinsics ${name}.intrinsics.obj)
add_flangrt_library(${name} ${libtype}
${sources}
${sources} $<TARGET_OBJECTS:${name}.intrinsics.obj>
${ARGN}
LINK_LIBRARIES ${Backtrace_LIBRARY}
LINK_LIBRARIES ${name}.intrinsics.obj ${Backtrace_LIBRARY}
ADDITIONAL_HEADERS ${public_headers} ${private_headers}
)
get_target_property(compile_target ${name}.compile ALIASED_TARGET)
if (msvc_lib)
set_target_properties(${name}
@@ -220,11 +301,19 @@ else()
endif ()
# Setting an unique Fortran_MODULE_DIRECTORY is required for each variant to
# write a different .mod file.
set_target_properties(${name}
PROPERTIES
Fortran_MODULE_DIRECTORY "module.${suffix}"
)
# write a different .mod file. One of them has to be selected to be the
# public module that is to be installed. We select the first.
if (_has_public_intrinsics)
set(is_public "")
else ()
set(is_public PUBLIC)
add_dependencies(flang-rt-mod ${name}.intrinsics ${compile_target})
set(_has_public_intrinsics "YES" PARENT_SCOPE)
endif ()
flang_module_target(${name}.intrinsics.obj ${is_public})
flang_module_target(${compile_target} ${is_public})
add_dependencies(${compile_target} ${name}.intrinsics)
enable_cuda_compilation(${name} "${supported_sources}")
enable_omp_offload_compilation(${name} "${supported_sources}")

View File

@@ -6,7 +6,7 @@
!
!===------------------------------------------------------------------------===!
#include '../include/flang/Runtime/magic-numbers.h'
#include '../../../flang/include/flang/Runtime/magic-numbers.h'
! These naming shenanigans prevent names from Fortran intrinsic modules
! from being usable on INTRINSIC statements, and force the program

View File

@@ -11,6 +11,7 @@
module cooperative_groups
use, intrinsic :: __fortran_builtins, only: c_devptr => __builtin_c_devptr
use :: cudadevice ! implicit dependency, made explicit for CMake
implicit none

View File

@@ -8,7 +8,7 @@
! Fortran 2018 Clause 17
#include '../include/flang/Runtime/magic-numbers.h'
#include '../../../flang/include/flang/Runtime/magic-numbers.h'
module ieee_arithmetic
! F18 Clause 17.1p1:

View File

@@ -6,7 +6,7 @@ config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
config.flang_source_dir = "@FLANG_SOURCE_DIR@"
config.flang_rt_source_dir = "@FLANG_RT_SOURCE_DIR@"
config.flang_rt_binary_test_dir = os.path.dirname(__file__)
config.flang_rt_output_resource_lib_dir = "@FLANG_RT_OUTPUT_RESOURCE_LIB_DIR@"
config.flang_rt_output_resource_lib_dir = "@RUNTIMES_OUTPUT_RESOURCE_LIB_DIR@"
config.flang_rt_experimental_offload_support = "@FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT@"
config.cc = "@CMAKE_C_COMPILER@"
config.flang = "@CMAKE_Fortran_COMPILER@"

View File

@@ -49,9 +49,8 @@ function(add_flangrt_unittest_offload_properties target)
# FIXME: replace 'native' in --offload-arch option with the list
# of targets that Fortran Runtime was built for.
if (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "OpenMP")
set_target_properties(${target}
PROPERTIES LINK_OPTIONS
"-fopenmp;--offload-arch=native"
set_property(TARGET ${target} APPEND
PROPERTY LINK_OPTIONS -fopenmp --offload-arch=native
)
endif()
endfunction()

View File

@@ -273,7 +273,6 @@ set(FLANG_TOOLS_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH
"Path for binary subdirectory (defaults to '${CMAKE_INSTALL_BINDIR}')")
mark_as_advanced(FLANG_TOOLS_INSTALL_DIR)
set(FLANG_INTRINSIC_MODULES_DIR ${CMAKE_BINARY_DIR}/include/flang)
set(FLANG_INCLUDE_DIR ${FLANG_BINARY_DIR}/include)
# TODO: Remove when libclangDriver is lifted out of Clang

View File

@@ -92,6 +92,10 @@ class CompilerInvocation : public CompilerInvocationBase {
// intrinsic of iso_fortran_env.
std::string allCompilerInvocOpts;
/// Location of the resource directory containing files specific to this
/// instance/version of Flang.
std::string resourceDir;
/// Semantic options
// TODO: Merge with or translate to frontendOpts. We shouldn't need two sets
// of options.
@@ -177,6 +181,9 @@ public:
getSemanticsCtx(Fortran::parser::AllCookedSources &allCookedSources,
const llvm::TargetMachine &);
std::string &getResourceDir() { return resourceDir; }
const std::string &getResourceDir() const { return resourceDir; }
std::string &getModuleDir() { return moduleDir; }
const std::string &getModuleDir() const { return moduleDir; }

View File

@@ -885,16 +885,6 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
return diags.getNumErrors() == numErrorsBefore;
}
// Generate the path to look for intrinsic modules
static std::string getIntrinsicDir(const char *argv) {
// TODO: Find a system independent API
llvm::SmallString<128> driverPath;
driverPath.assign(llvm::sys::fs::getMainExecutable(argv, nullptr));
llvm::sys::path::remove_filename(driverPath);
driverPath.append("/../include/flang/");
return std::string(driverPath);
}
// Generate the path to look for OpenMP headers
static std::string getOpenMPHeadersDir(const char *argv) {
llvm::SmallString<128> includePath;
@@ -1568,6 +1558,14 @@ bool CompilerInvocation::createFromArgs(
success = false;
}
// User-specified or default resource dir
if (const llvm::opt::Arg *a =
args.getLastArg(clang::options::OPT_resource_dir))
invoc.resourceDir = a->getValue();
else
invoc.resourceDir = clang::driver::Driver::GetResourcesPath(
llvm::sys::fs::getMainExecutable(argv0, nullptr));
// -flang-experimental-hlfir
if (args.hasArg(clang::options::OPT_flang_experimental_hlfir) ||
args.hasArg(clang::options::OPT_emit_hlfir)) {
@@ -1834,9 +1832,11 @@ void CompilerInvocation::setFortranOpts() {
preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
preprocessorOptions.searchDirectoriesFromIntrModPath.end());
// Add the default intrinsic module directory
fortranOptions.intrinsicModuleDirectories.emplace_back(
getIntrinsicDir(getArgv0()));
// Add the ordered list of -fintrinsic-modules-path
fortranOptions.intrinsicModuleDirectories.insert(
fortranOptions.intrinsicModuleDirectories.end(),
preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
preprocessorOptions.searchDirectoriesFromIntrModPath.end());
// Add the directory supplied through -J/-module-dir to the list of search
// directories

View File

@@ -621,12 +621,15 @@ bool Semantics::Perform() {
const auto *frontModule{std::get_if<common::Indirection<parser::Module>>(
&program_.v.front().u)};
if (frontModule &&
(std::get<parser::Statement<parser::ModuleStmt>>(frontModule->value().t)
.statement.v.source == "__fortran_builtins" ||
std::get<parser::Statement<parser::ModuleStmt>>(
frontModule->value().t)
.statement.v.source == "__ppc_types")) {
std::get<parser::Statement<parser::ModuleStmt>>(frontModule->value().t)
.statement.v.source == "__fortran_builtins") {
// Don't try to read the builtins module when we're actually building it.
} else if (frontModule &&
std::get<parser::Statement<parser::ModuleStmt>>(frontModule->value().t)
.statement.v.source == "__ppc_types") {
// Don't try to read the UsePPCBuiltinTypesModule() we are currently
// building, but __fortran_builtins is needed to build it.
context_.UseFortranBuiltinsModule();
} else if (frontModule &&
(std::get<parser::Statement<parser::ModuleStmt>>(frontModule->value().t)
.statement.v.source == "__ppc_intrinsics" ||

View File

@@ -1 +0,0 @@
DisableFormat: true

View File

@@ -2,11 +2,31 @@
# for use by Lit, and delegates to LLVM's lit test handlers.
add_subdirectory(lib)
set(FLANG_TEST_Fortran_FLAGS "" CACHE STRING "Additional Fortran flags for running tests, such as -fintrinsic-modules-path=<path>")
if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
set(FLANG_TEST_ENABLE_MODULES_default ON)
else ()
set(FLANG_TEST_ENABLE_MODULES_default OFF)
endif ()
option(FLANG_TEST_ENABLE_MODULES "Force-enable tests that require intrinsic modules from Flang-RT" "${FLANG_TEST_ENABLE_MODULES_default}")
if ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES AND FLANG_TEST_ENABLE_MODULES AND NOT FLANG_STANDALONE_BUILD)
set(FLANG_TEST_ENABLE_OPENMP_default ON)
else ()
set(FLANG_TEST_ENABLE_OPENMP_default OFF)
endif ()
option(FLANG_TEST_ENABLE_OPENMP "Force-enable tests that require modules from OpenMP" "${FLANG_TEST_ENABLE_OPENMP_default}")
llvm_canonicalize_cmake_booleans(
FLANG_STANDALONE_BUILD
LLVM_BUILD_EXAMPLES
LLVM_BYE_LINK_INTO_TOOLS
LLVM_ENABLE_PLUGINS
FLANG_TEST_ENABLE_MODULES
FLANG_TEST_ENABLE_OPENMP
)
set(FLANG_TOOLS_DIR ${FLANG_BINARY_DIR}/bin)
@@ -59,7 +79,6 @@ set(FLANG_TEST_PARAMS
set(FLANG_TEST_DEPENDS
flang
module_files
fir-opt
tco
bbc
@@ -101,8 +120,14 @@ if (LLVM_BUILD_EXAMPLES)
)
endif ()
if ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES AND NOT FLANG_STANDALONE_BUILD)
list(APPEND FLANG_TEST_DEPENDS "libomp-mod")
if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES AND NOT FLANG_STANDALONE_BUILD)
# For intrinsic module files (in flang-rt/)
list(APPEND FLANG_TEST_DEPENDS "flang-rt-mod")
if ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES)
# For omplib.mod and omplib_kinds.mod (in openmp/)
list(APPEND FLANG_TEST_DEPENDS "libomp-mod")
endif ()
endif ()
add_custom_target(flang-test-depends DEPENDS ${FLANG_TEST_DEPENDS})

View File

@@ -1,5 +1,6 @@
! DUMMY module
! Added for testing purposes. The contents of this file are currently not relevant.
! Using this file will cause an error because of missing checksum
module ieee_arithmetic
type::ieee_round_type
integer(1),private::mode=0_1

View File

@@ -1,5 +1,6 @@
! DUMMY module
! Added for testing purposes. The contents of this file are currently not relevant.
! Using this file will cause an error because of missing checksum
module iso_fortran_env
use __fortran_builtins,only:event_type=>__builtin_event_type
use __fortran_builtins,only:lock_type=>__builtin_lock_type

View File

@@ -0,0 +1,55 @@
! Ensure argument -fintrinsic-modules-path works as expected.
!-----------------------------------------
! FLANG DRIVER
!-----------------------------------------
! NOTE: Depending on how Flang is built, the default intrinsics may have higher
! or lower priority than -fintrinsic-modules-path added here. Using
! basictestmoduleone.mod from Inputs/module-dir/ will trigger an error.
! RUN: %flang -fsyntax-only -### %s 2>&1 | FileCheck %s --check-prefix=DEFAULTPATH
! RUN: %flang -fsyntax-only -DINTRINSICS_DEFAULT %s
! RUN: not %flang -fsyntax-only -DINTRINSICS_INPUTONE %s 2>&1 | FileCheck %s --check-prefix=NOINPUTONE
! RUN: not %flang -fsyntax-only -DINTRINSICS_INPUTTWO %s 2>&1 | FileCheck %s --check-prefix=NOINPUTTWO
! RUN: %flang -fsyntax-only -DINTRINSICS_DEFAULT -DINTRINSICS_INPUTTWO -fintrinsic-modules-path=%S/Inputs/module-dir/ %s
! RUN: %flang -fsyntax-only -DINTRINSICS_INPUTONE -fintrinsic-modules-path=%S/Inputs/ %s
! RUN: %flang -fsyntax-only -DINTRINSICS_INPUTONE -DINTRINSICS_INPUTTWO -fintrinsic-modules-path=%S/Inputs/ -fintrinsic-modules-path=%S/Inputs/module-dir/ %s
! RUN: not %flang -fsyntax-only -DINTRINSICS_INPUTONE -DINTRINSICS_INPUTTWO -fintrinsic-modules-path=%S/Inputs/module-dir/ -fintrinsic-modules-path=%S/Inputs/ %s 2>&1 | FileCheck %s --check-prefix=WRONGINPUTONE
!-----------------------------------------
! FLANG FRONTEND (flang -fc1)
!-----------------------------------------
! NOTE: %flang_cc1 the default intrinsics path always has higher priority than
! -fintrinsic-modules-path added here. Accidentally using
! ieee_arithmetic/iso_fortran_env from the Inputs/ directory will trigger
! an error (e.g. when the default intrinsics dir is empty).
! RUN: %flang_fc1 -fsyntax-only -DINTRINSICS_DEFAULT %s
! RUN: not %flang_fc1 -fsyntax-only -DINTRINSICS_DEFAULT -DINTRINSICS_INPUTONE %s 2>&1 | FileCheck %s --check-prefix=NOINPUTONE
! RUN: not %flang_fc1 -fsyntax-only -DINTRINSICS_DEFAULT -DINTRINSICS_INPUTTWO %s 2>&1 | FileCheck %s --check-prefix=NOINPUTTWO
! RUN: %flang_fc1 -fsyntax-only -DINTRINSICS_DEFAULT -DINTRINSICS_INPUTTWO -fintrinsic-modules-path=%S/Inputs/module-dir %s
! RUN: %flang_fc1 -fsyntax-only -DINTRINSICS_DEFAULT -DINTRINSICS_INPUTONE -fintrinsic-modules-path=%S/Inputs/ %s
! RUN: %flang_fc1 -fsyntax-only -DINTRINSICS_DEFAULT -DINTRINSICS_INPUTONE -DINTRINSICS_INPUTTWO -fintrinsic-modules-path=%S/Inputs/ -fintrinsic-modules-path=%S/Inputs/module-dir/ %s
! RUN: not %flang_fc1 -fsyntax-only -DINTRINSICS_DEFAULT -DINTRINSICS_INPUTONE -DINTRINSICS_INPUTTWO -fintrinsic-modules-path=%S/Inputs/module-dir -fintrinsic-modules-path=%S/Inputs/ %s 2>&1 | FileCheck %s --check-prefix=WRONGINPUTONE
! DEFAULTPATH: flang{{.*}}-fc1{{.*}}-fintrinsic-modules-path
! NOINPUTONE: Source file 'basictestmoduleone.mod' was not found
! NOINPUTTWO: Source file 'basictestmoduletwo.mod' was not found
! WRONGINPUTONE: 't1' not found in module 'basictestmoduleone'
program test_intrinsic_module_path
#ifdef INTRINSICS_DEFAULT
use ieee_arithmetic, only: ieee_round_type
use iso_fortran_env, only: team_type, event_type, lock_type
#endif
#ifdef INTRINSICS_INPUTONE
use basictestmoduleone, only: t1
#endif
#ifdef INTRINSICS_INPUTTWO
use basictestmoduletwo, only: t2
#endif
end program

View File

@@ -1,23 +0,0 @@
! Ensure argument -fintrinsic-modules-path works as expected.
! WITHOUT the option, the default location for the module is checked and no error generated.
! With the option GIVEN, the module with the same name is PREPENDED, and considered over the
! default one, causing a CHECKSUM error.
!-----------------------------------------
! FRONTEND FLANG DRIVER (flang -fc1)
!-----------------------------------------
! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT
! RUN: not %flang_fc1 -fsyntax-only -fintrinsic-modules-path %S/Inputs/ %s 2>&1 | FileCheck %s --check-prefix=GIVEN
! RUN: not %flang_fc1 -fsyntax-only -fintrinsic-modules-path=%S/Inputs/ %s 2>&1 | FileCheck %s --check-prefix=GIVEN
! WITHOUT-NOT: 'ieee_arithmetic.mod' was not found
! WITHOUT-NOT: 'iso_fortran_env.mod' was not found
! GIVEN: error: Cannot use module file for module 'ieee_arithmetic': File has invalid checksum
! GIVEN: error: Cannot use module file for module 'iso_fortran_env': File has invalid checksum
program test_intrinsic_module_path
use ieee_arithmetic, only: ieee_round_type
use iso_fortran_env, only: team_type, event_type, lock_type
end program

View File

@@ -1,7 +1,7 @@
! REQUIRES: x86-registered-target
! checks fatlto objects: that valid bitcode is included in the object file generated.
! RUN: %flang -fc1 -triple x86_64-unknown-linux-gnu -flto -ffat-lto-objects -emit-obj %s -o %t.o
! RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -flto -ffat-lto-objects -emit-obj %s -o %t.o
! RUN: llvm-readelf -S %t.o | FileCheck %s --check-prefixes=ELF
! RUN: llvm-objcopy --dump-section=.llvm.lto=%t.bc %t.o
! RUN: llvm-dis %t.bc -o - | FileCheck %s --check-prefixes=DIS
@@ -11,7 +11,7 @@
! DIS-NEXT: ret void
! DIS-NEXT: }
! RUN: %flang -fc1 -triple x86_64-unknown-linux-gnu -flto -ffat-lto-objects -S %s -o - | FileCheck %s --check-prefixes=ASM
! RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -flto -ffat-lto-objects -S %s -o - | FileCheck %s --check-prefixes=ASM
! ASM: .section .llvm.lto,"e",@llvm_lto
! ASM-NEXT: .Lllvm.embedded.object:

View File

@@ -8,12 +8,12 @@ FIXED-NEXT: "-fc1" {{.*}} "-ffixed-form" {{.*}} "-x" "f95-cpp-input" "fixed-form
!RUN: %flang -save-temps -### -ffree-form %S/Inputs/free-form-test.f90 2>&1 | FileCheck %s --check-prefix=FREE-FLAG
FREE-FLAG: "-fc1" {{.*}} "-o" "free-form-test.i" {{.*}} "-x" "f95" "{{.*}}/free-form-test.f90"
FREE-FLAG-NEXT: "-fc1" {{.*}} "-emit-llvm-bc" "-ffree-form"
FREE-FLAG-NEXT: "-fc1" {{.*}} "-emit-llvm-bc" {{.*}}"-ffree-form"
FREE-FLAG-NOT: "-ffixed-form"
FREE-FLAG-SAME: "-x" "f95-cpp-input" "free-form-test.i"
!RUN: %flang -save-temps -### -ffixed-form %S/Inputs/fixed-form-test.f 2>&1 | FileCheck %s --check-prefix=FIXED-FLAG
FIXED-FLAG: "-fc1" {{.*}} "-o" "fixed-form-test.i" {{.*}} "-x" "f95" "{{.*}}/fixed-form-test.f"
FIXED-FLAG-NEXT: "-fc1" {{.*}} "-emit-llvm-bc" "-ffixed-form"
FIXED-FLAG-NEXT: "-fc1" {{.*}} "-emit-llvm-bc" {{.*}}"-ffixed-form"
FIXED-FLAG-NOT: "-ffixed-form"
FIXED-FLAG-SAME: "-x" "f95-cpp-input" "fixed-form-test.i"

View File

@@ -1,6 +1,6 @@
! Test interface that lowering handles small interface mismatch with
! type bound procedures.
! RUN: bbc -emit-hlfir %s -o - -I nw | FileCheck %s
! RUN: %bbc_bare -emit-hlfir %s -o - -I nw | FileCheck %s
module dispatch_mismatch
type t

View File

@@ -1,6 +1,11 @@
! Tests for 2.9.3.1 Simd and target dependent defult alignment for AArch64
! Tests for 2.9.3.1 Simd and target dependent default alignment for AArch64
! The default alignment for AARCH64 is 0 so we do not emit aligned clause
! REQUIRES: aarch64-registered-target
! Requires aarch64 iso_c_binding.mod which currently is only available if your host is also aarch64
! FIXME: Make flang a cross-compiler
! UNSUPPORTED: true
! RUN: %flang_fc1 -triple aarch64-unknown-linux-gnu -emit-hlfir -fopenmp %s -o - | FileCheck %s
subroutine simdloop_aligned_cptr(A)
use iso_c_binding

View File

@@ -1,7 +1,7 @@
! This test checks the lowering and application of default map types for the target enter/exit data constructs and map clauses
!RUN: %flang -fc1 -emit-fir -fopenmp -fopenmp-version=52 -o - %s | FileCheck %s --check-prefix=CHECK-52
!RUN: not %flang -fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-51
!RUN: %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -o - %s | FileCheck %s --check-prefix=CHECK-52
!RUN: not %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-51
module test
real, allocatable :: A

View File

@@ -1,5 +1,5 @@
!RUN: %flang -E %s 2>&1 | FileCheck %s
!RUN: %flang -fc1 -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
!RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
!CHECK-NOT: dir$
!CHECK-NOT: error:
!dir$ fixed

View File

@@ -1,4 +1,4 @@
!RUN: %flang -fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
!RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
!CHECK-NOT: ERROR STOP
!CHECK: CONTINUE
#if defined UNDEFINED

View File

@@ -1,4 +1,4 @@
!RUN: %flang -fc1 -fsyntax-only %s | FileCheck --allow-empty %s
!RUN: %flang_fc1 -fsyntax-only %s | FileCheck --allow-empty %s
!CHECK-NOT: error:
character(0), allocatable :: ch
allocate(character(-1) :: ch)

View File

@@ -1,4 +1,4 @@
!RUN: %flang -fc1 -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
!RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
module foo_mod
use, intrinsic :: iso_fortran_env
use, intrinsic :: iso_c_binding

View File

@@ -139,18 +139,95 @@ config.substitutions.append(("%isysroot", " ".join(isysroot_flag)))
if config.default_sysroot:
config.available_features.add("default_sysroot")
flang_exe = lit.util.which("flang", config.flang_llvm_tools_dir)
if not flang_exe:
lit_config.fatal(f"Could not identify flang executable")
# Intrinsic paths that are added implicitly by the `flang` driver, but have to be added manually when invoking the frontend `flang -fc1`.
flang_driver_search_args = []
# Intrinsic paths that are added to `flang` as well as `flang -fc1`.
flang_extra_search_args = list(config.flang_test_fortran_flags)
def get_resource_module_intrinsic_dir(modfile):
# Determine the intrinsic module search path that is added by the driver. If
# skipping the driver using -fc1, we need to append the path manually.
flang_intrinsics_dir = subprocess.check_output(
[flang_exe, *config.flang_test_fortran_flags, f"-print-file-name={modfile}"],
text=True,
).strip()
flang_intrinsics_dir = os.path.dirname(flang_intrinsics_dir)
return flang_intrinsics_dir or None
intrinsics_mod_path = get_resource_module_intrinsic_dir("__fortran_builtins.mod")
if intrinsics_mod_path:
flang_driver_search_args += [f"-fintrinsic-modules-path={intrinsics_mod_path}"]
openmp_mod_path = get_resource_module_intrinsic_dir("omp_lib.mod")
if openmp_mod_path and openmp_mod_path != intrinsics_mod_path:
flang_driver_search_args += [f"-fintrinsic-modules-path={openmp_mod_path}"]
# If intrinsic modules are not available, disable tests unless they are marked as 'module-independent'.
config.available_features.add("module-independent")
if config.flang_test_enable_modules or intrinsics_mod_path:
config.available_features.add("flangrt-modules")
else:
lit_config.warning(
f"Intrinsic modules not in driver default paths: disabling most tests; Use FLANG_TEST_ENABLE_MODULES=ON to force-enable"
)
config.limit_to_features.add("module-independent")
# Determine if OpenMP runtime was built (enable OpenMP tests via REQUIRES in test file)
if config.flang_test_enable_openmp or openmp_mod_path:
config.available_features.add("openmp_runtime")
# Search path for omp_lib.h with LLVM_ENABLE_RUNTIMES=openmp
# FIXME: openmp should write this file into the resource directory
flang_extra_search_args += [
"-I",
f"{config.flang_obj_root}/../../runtimes/runtimes-bins/openmp/runtime/src",
]
else:
lit_config.warning(
f"OpenMP modules found not in driver default paths: OpenMP tests disabled; Use FLANG_TEST_ENABLE_OPENMP=ON to force-enable"
)
lit_config.note(f"using flang: {flang_exe}")
lit_config.note(
f"using flang implicit search paths: {' '.join(flang_driver_search_args)}"
)
lit_config.note(f"using flang extra search paths: {' '.join(flang_extra_search_args)}")
# For each occurrence of a flang tool name, replace it with the full path to
# the build directory holding that tool.
tools = [
ToolSubst(
"bbc",
command=FindTool("bbc"),
extra_args=flang_driver_search_args + flang_extra_search_args,
unresolved="fatal",
),
ToolSubst(
"%flang",
command=FindTool("flang"),
command=flang_exe,
extra_args=flang_extra_search_args,
unresolved="fatal",
),
ToolSubst(
"%flang_fc1",
command=FindTool("flang"),
extra_args=["-fc1"],
command=flang_exe,
extra_args=["-fc1"] + flang_driver_search_args + flang_extra_search_args,
unresolved="fatal",
),
# Variant that does not implicitly add intrinsic search paths
ToolSubst(
"%bbc_bare",
command=FindTool("bbc"),
unresolved="fatal",
),
]
@@ -193,16 +270,7 @@ result = lit_config.params.get("LIBPGMATH")
if result:
config.environment["LIBPGMATH"] = True
# Determine if OpenMP runtime was built (enable OpenMP tests via REQUIRES in test file)
openmp_flags_substitution = "-fopenmp"
if config.have_openmp_rtl:
config.available_features.add("openmp_runtime")
# For the enabled OpenMP tests, add a substitution that is needed in the tests to find
# the omp_lib.{h,mod} files, depending on whether the OpenMP runtime was built as a
# project or runtime.
if config.openmp_module_dir:
openmp_flags_substitution += f" -J {config.openmp_module_dir}"
config.substitutions.append(("%openmp_flags", openmp_flags_substitution))
config.substitutions.append(("%openmp_flags", "-fopenmp"))
# Add features and substitutions to test F128 math support.
# %f128-lib substitution may be used to generate check prefixes

View File

@@ -13,10 +13,12 @@ config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@"
config.flang_obj_root = "@FLANG_BINARY_DIR@"
config.flang_tools_dir = lit_config.substitute("@FLANG_TOOLS_DIR@")
config.flang_intrinsic_modules_dir = "@FLANG_INTRINSIC_MODULES_DIR@"
config.flang_headers_dir = "@HEADER_BINARY_DIR@"
config.flang_llvm_tools_dir = "@CMAKE_BINARY_DIR@/bin"
config.flang_test_triple = "@FLANG_TEST_TARGET_TRIPLE@"
config.flang_test_fortran_flags = "@FLANG_TEST_Fortran_FLAGS@".split()
config.flang_test_enable_modules = @FLANG_TEST_ENABLE_MODULES@
config.flang_test_enable_openmp = @FLANG_TEST_ENABLE_OPENMP@
config.flang_examples = @LLVM_BUILD_EXAMPLES@
config.python_executable = "@PYTHON_EXECUTABLE@"
config.flang_standalone_build = @FLANG_STANDALONE_BUILD@
@@ -25,11 +27,6 @@ config.linked_bye_extension = @LLVM_BYE_LINK_INTO_TOOLS@
config.osx_sysroot = path(r"@CMAKE_OSX_SYSROOT@")
config.targets_to_build = "@TARGETS_TO_BUILD@"
config.default_sysroot = "@DEFAULT_SYSROOT@"
config.have_openmp_rtl = ("@LLVM_TOOL_OPENMP_BUILD@" == "TRUE") or ("openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"))
if "openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"):
config.openmp_module_dir = "@CMAKE_BINARY_DIR@/runtimes/runtimes-bins/openmp/runtime/src"
else:
config.openmp_module_dir = None
config.flang_runtime_f128_math_lib = "@FLANG_RUNTIME_F128_MATH_LIB@"
config.have_ldbl_mant_dig_113 = "@HAVE_LDBL_MANT_DIG_113@"

View File

@@ -7,7 +7,6 @@
#===------------------------------------------------------------------------===#
add_subdirectory(bbc)
add_subdirectory(f18)
add_subdirectory(flang-driver)
add_subdirectory(tco)
add_subdirectory(f18-parse-demo)

View File

@@ -98,6 +98,11 @@ static llvm::cl::alias
llvm::cl::desc("intrinsic module directory"),
llvm::cl::aliasopt(intrinsicIncludeDirs));
static llvm::cl::alias
intrinsicModulePath("fintrinsic-modules-path",
llvm::cl::desc("intrinsic module search paths"),
llvm::cl::aliasopt(intrinsicIncludeDirs));
static llvm::cl::opt<std::string>
moduleDir("module", llvm::cl::desc("module output directory (default .)"),
llvm::cl::init("."));
@@ -574,14 +579,6 @@ int main(int argc, char **argv) {
if (includeDirs.size() == 0) {
includeDirs.push_back(".");
// Default Fortran modules should be installed in include/flang (a sibling
// to the bin) directory.
intrinsicIncludeDirs.push_back(
llvm::sys::path::parent_path(
llvm::sys::path::parent_path(
llvm::sys::fs::getMainExecutable(argv[0], nullptr)))
.str() +
"/include/flang");
}
Fortran::parser::Options options;

View File

@@ -1,170 +0,0 @@
set(LLVM_LINK_COMPONENTS
FrontendOpenACC
FrontendOpenMP
Support
)
# Define the list of Fortran module files for which it is
# sufficient to generate the module file via -fsyntax-only.
set(MODULES
"__fortran_builtins"
"__fortran_ieee_exceptions"
"__fortran_type_info"
"__ppc_types"
"__ppc_intrinsics"
"mma"
"__cuda_builtins"
"__cuda_device"
"cooperative_groups"
"cudadevice"
"ieee_arithmetic"
"ieee_exceptions"
"ieee_features"
"iso_c_binding"
"iso_fortran_env"
"iso_fortran_env_impl"
)
# Check if 128-bit float computations can be done via long double.
check_cxx_source_compiles(
"#include <cfloat>
#if LDBL_MANT_DIG != 113
#error LDBL_MANT_DIG != 113
#endif
int main() { return 0; }
"
HAVE_LDBL_MANT_DIG_113)
# Figure out whether we can support REAL(KIND=16)
if (FLANG_RUNTIME_F128_MATH_LIB)
set(FLANG_SUPPORT_R16 "1")
elseif (HAVE_LDBL_MANT_DIG_113)
set(FLANG_SUPPORT_R16 "1")
else()
set(FLANG_SUPPORT_R16 "0")
endif()
# Init variable to hold extra object files coming from the Fortran modules;
# these module files will be contributed from the CMakeLists in flang/tools/f18.
set(module_objects "")
# Create module files directly from the top-level module source directory.
# If CMAKE_CROSSCOMPILING, then the newly built flang executable was
# cross compiled, and thus can't be executed on the build system and thus
# can't be used for generating module files.
if (NOT CMAKE_CROSSCOMPILING)
foreach(filename ${MODULES})
set(depends "")
set(opts "")
if(${filename} STREQUAL "__fortran_builtins" OR
${filename} STREQUAL "__ppc_types")
elseif(${filename} STREQUAL "__ppc_intrinsics" OR
${filename} STREQUAL "mma")
set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__ppc_types.mod)
elseif(${filename} STREQUAL "__cuda_device" OR
${filename} STREQUAL "cudadevice" OR
${filename} STREQUAL "cooperative_groups")
set(opts -fc1 -xcuda)
if(${filename} STREQUAL "__cuda_device")
set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__cuda_builtins.mod)
elseif(${filename} STREQUAL "cudadevice")
set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__cuda_device.mod)
elseif(${filename} STREQUAL "cooperative_groups")
set(depends ${FLANG_INTRINSIC_MODULES_DIR}/cudadevice.mod)
endif()
else()
set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_builtins.mod)
if(${filename} STREQUAL "iso_fortran_env")
set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/iso_fortran_env_impl.mod)
endif()
if(${filename} STREQUAL "ieee_arithmetic" OR
${filename} STREQUAL "ieee_exceptions")
set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_ieee_exceptions.mod)
endif()
endif()
if(NOT ${filename} STREQUAL "__fortran_type_info" AND NOT ${filename} STREQUAL "__fortran_builtins")
set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_type_info.mod)
endif()
# The module contains PPC vector types that needs the PPC target.
if(${filename} STREQUAL "__ppc_intrinsics" OR
${filename} STREQUAL "mma")
if (PowerPC IN_LIST LLVM_TARGETS_TO_BUILD)
set(opts "--target=ppc64le")
else()
# Do not compile PPC module if the target is not available.
continue()
endif()
endif()
set(decls "")
if (FLANG_SUPPORT_R16)
set(decls "-DFLANG_SUPPORT_R16")
endif()
# Some modules have an implementation part that needs to be added to the
# flang_rt.runtime library.
set(compile_with "-fsyntax-only")
set(object_output "")
set(include_in_link FALSE)
set(base ${FLANG_INTRINSIC_MODULES_DIR}/${filename})
# TODO: We may need to flag this with conditional, in case Flang is built w/o OpenMP support
add_custom_command(OUTPUT ${base}.mod ${object_output}
COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR}
COMMAND flang ${opts} ${decls} -cpp ${compile_with} -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
${FLANG_SOURCE_DIR}/module/${filename}.f90
DEPENDS flang ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${FLANG_SOURCE_DIR}/module/__fortran_builtins.f90 ${depends}
)
list(APPEND MODULE_FILES ${base}.mod)
install(FILES ${base}.mod DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang" COMPONENT flang-module-interfaces)
# If a module has been compiled into an object file, add the file to
# the link line for the flang_rt.runtime library.
if(include_in_link)
list(APPEND module_objects ${object_output})
endif()
endforeach()
# Set a CACHE variable that is visible to the CMakeLists.txt in runtime/, so that
# the compiled Fortran modules can be added to the link line of the flang_rt.runtime
# library.
set(FORTRAN_MODULE_OBJECTS ${module_objects} CACHE INTERNAL "" FORCE)
# Special case for omp_lib.mod, because its source comes from openmp/runtime/src/include.
# It also produces two module files: omp_lib.mod and omp_lib_kinds.mod. Compile these
# files only if OpenMP support has been configured.
if (LLVM_TOOL_OPENMP_BUILD)
message(STATUS "OpenMP runtime support enabled via LLVM_ENABLE_PROJECTS, building omp_lib.mod")
set(base ${FLANG_INTRINSIC_MODULES_DIR}/omp_lib)
add_custom_command(OUTPUT ${base}.mod ${base}_kinds.mod
COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR}
COMMAND flang -cpp -fsyntax-only ${opts} -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
${CMAKE_BINARY_DIR}/projects/openmp/runtime/src/omp_lib.F90
DEPENDS flang ${FLANG_INTRINSIC_MODULES_DIR}/iso_c_binding.mod ${CMAKE_BINARY_DIR}/projects/openmp/runtime/src/omp_lib.F90 ${depends}
)
list(APPEND MODULE_FILES ${base}.mod ${base}_kinds.mod)
install(FILES ${base}.mod ${base}_kinds.mod DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang" COMPONENT flang-module-interfaces)
elseif ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES)
message(STATUS "OpenMP runtime support enabled via LLVM_ENABLE_RUNTIMES, assuming omp_lib.mod is built there")
else()
message(WARNING "Not building omp_lib.mod, no OpenMP runtime in either LLVM_ENABLE_PROJECTS or LLVM_ENABLE_RUNTIMES")
endif()
add_llvm_install_targets(install-flang-module-interfaces
COMPONENT flang-module-interfaces)
endif()
add_custom_target(module_files ALL DEPENDS ${MODULE_FILES})
set_target_properties(module_files PROPERTIES FOLDER "Flang/Resources")
# TODO Move this to a more suitable location
# Copy the generated omp_lib.h header file, if OpenMP support has been configured.
if (LLVM_TOOL_OPENMP_BUILD)
message(STATUS "OpenMP runtime support enabled via LLVM_ENABLE_PROJECTS, building omp_lib.h")
file(COPY ${CMAKE_BINARY_DIR}/projects/openmp/runtime/src/omp_lib.h DESTINATION "${CMAKE_BINARY_DIR}/include/flang/OpenMP/" FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
install(FILES ${CMAKE_BINARY_DIR}/include/flang/OpenMP/omp_lib.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang/OpenMP")
elseif ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES)
message(STATUS "OpenMP runtime support enabled via LLVM_ENABLE_RUNTIMES, assuming omp_lib.h is built there")
else()
message(STATUS "Not copying omp_lib.h, no OpenMP runtime in either LLVM_ENABLE_PROJECTS or LLVM_ENABLE_RUNTIMES")
endif()

View File

@@ -1,42 +0,0 @@
//===-- tools/f18/dump.cpp ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This file defines Dump routines available for calling from the debugger.
// Each is based on operator<< for that type. There are overloadings for
// reference and pointer, and for dumping to a provided raw_ostream or errs().
#ifdef DEBUGF18
#include "llvm/Support/raw_ostream.h"
#define DEFINE_DUMP(ns, name) \
namespace ns { \
class name; \
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const name &); \
} \
void Dump(llvm::raw_ostream &os, const ns::name &x) { os << x << '\n'; } \
void Dump(llvm::raw_ostream &os, const ns::name *x) { \
if (x == nullptr) \
os << "null\n"; \
else \
Dump(os, *x); \
} \
void Dump(const ns::name &x) { Dump(llvm::errs(), x); } \
void Dump(const ns::name *x) { Dump(llvm::errs(), *x); }
namespace Fortran {
DEFINE_DUMP(parser, Name)
DEFINE_DUMP(parser, CharBlock)
DEFINE_DUMP(semantics, Symbol)
DEFINE_DUMP(semantics, Scope)
DEFINE_DUMP(semantics, IntrinsicTypeSpec)
DEFINE_DUMP(semantics, DerivedTypeSpec)
DEFINE_DUMP(semantics, DeclTypeSpec)
} // namespace Fortran
#endif

View File

@@ -252,6 +252,11 @@ function(runtime_default_target)
# OpenMP tests
list(APPEND extra_targets "libomp-mod")
endif ()
if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
# The target flang-rt-mod is a dependee of check-flang needed to run its
# tests.
list(APPEND extra_targets "flang-rt-mod")
endif ()
if(LLVM_INCLUDE_TESTS)
set_property(GLOBAL APPEND PROPERTY LLVM_ALL_LIT_TESTSUITES "@${LLVM_BINARY_DIR}/runtimes/runtimes-bins/lit.tests")
@@ -536,18 +541,15 @@ if(build_runtimes)
if ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES AND "flang" IN_LIST LLVM_ENABLE_PROJECTS)
list(APPEND extra_args ENABLE_FORTRAN)
endif()
if("openmp" IN_LIST LLVM_ENABLE_RUNTIMES OR "offload" IN_LIST LLVM_ENABLE_RUNTIMES)
if (${LLVM_TOOL_FLANG_BUILD})
message(STATUS "Configuring build of omp_lib.mod and omp_lib_kinds.mod via flang")
set(LIBOMP_FORTRAN_MODULES_COMPILER "${CMAKE_BINARY_DIR}/bin/flang")
set(LIBOMP_MODULES_INSTALL_PATH "${CMAKE_INSTALL_INCLUDEDIR}/flang")
# TODO: This is a workaround until flang becomes a first-class project
# in llvm/CMakeList.txt. Until then, this line ensures that flang is
# built before "openmp" is built as a runtime project. Besides "flang"
# to build the compiler, we also need to add "module_files" to make sure
# that all .mod files are also properly build.
list(APPEND extra_deps "flang" "module_files")
if("flang" IN_LIST LLVM_ENABLE_PROJECTS)
# Ensure REAL(16) support in runtimes to be consistent with compiler
if(FLANG_RUNTIME_F128_MATH_LIB OR HAVE_LDBL_MANT_DIG_113)
list(APPEND extra_cmake_args "-DFORTRAN_SUPPORTS_REAL16=TRUE")
else()
list(APPEND extra_cmake_args "-DFORTRAN_SUPPORTS_REAL16=FALSE")
endif()
endif()
if("openmp" IN_LIST LLVM_ENABLE_RUNTIMES OR "offload" IN_LIST LLVM_ENABLE_RUNTIMES)
foreach(dep opt llvm-link llvm-extract clang llvm-offload-binary clang-nvlink-wrapper)
if(TARGET ${dep})
list(APPEND extra_deps ${dep})

View File

@@ -111,6 +111,12 @@ set(OPENMP_TEST_FLAGS "" CACHE STRING
"Extra compiler flags to send to the test compiler.")
set(OPENMP_TEST_OPENMP_FLAGS ${OPENMP_TEST_COMPILER_OPENMP_FLAGS} CACHE STRING
"OpenMP compiler flag to use for testing OpenMP runtime libraries.")
set(OPENMP_TEST_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" CACHE STRING
"Additional compiler flags to use for testing Fortran programs.")
if (LLVM_RUNTIMES_BUILD)
flang_module_fortran_enable()
endif ()
set(ENABLE_LIBOMPTARGET ON)
# Currently libomptarget cannot be compiled on Windows or MacOS X.

View File

@@ -109,7 +109,7 @@ set(LIBOMP_MIC_ARCH knc CACHE STRING
if("${LIBOMP_ARCH}" STREQUAL "mic")
libomp_check_variable(LIBOMP_MIC_ARCH knf knc)
endif()
set(LIBOMP_FORTRAN_MODULES FALSE CACHE BOOL
set(LIBOMP_FORTRAN_MODULES "${RUNTIMES_FLANG_MODULES_ENABLED}" CACHE BOOL
"Create Fortran module files? (requires fortran compiler)")
# - Support for universal fat binary builds on Mac
@@ -147,8 +147,6 @@ else()
set(LIBOMP_LIBFLAGS "" CACHE STRING
"Appended user specified linked libs flags. (e.g., -lm)")
endif()
set(LIBOMP_FFLAGS "" CACHE STRING
"Appended user specified Fortran compiler flags. These are only used if LIBOMP_FORTRAN_MODULES==TRUE.")
# Should the libomp library and generated headers be copied into the original source exports/ directory
# Turning this to FALSE aids parallel builds to not interfere with each other.
@@ -272,10 +270,6 @@ set(LIBOMP_TOOLS_DIR ${LIBOMP_BASE_DIR}/tools)
set(LIBOMP_INC_DIR ${LIBOMP_SRC_DIR}/include)
set(LIBOMP_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
# Enabling Fortran if it is needed
if(${LIBOMP_FORTRAN_MODULES})
enable_language(Fortran)
endif()
# Enable MASM Compiler if it is needed (Windows only)
if(WIN32)
enable_language(ASM_MASM)

View File

@@ -1,29 +0,0 @@
#
#//===----------------------------------------------------------------------===//
#//
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
# Checking a fortran compiler flag
# There is no real trivial way to do this in CMake, so we implement it here
# this will have ${boolean} = TRUE if the flag succeeds, otherwise false.
function(libomp_check_fortran_flag flag boolean)
if(NOT DEFINED "${boolean}")
set(retval TRUE)
set(fortran_source
" program hello
print *, \"Hello World!\"
end program hello")
# Compiling as a part of runtimes introduces ARCH-unknown-linux-gnu as a
# part of a working directory. So adding a guard for unknown.
set(failed_regexes "[Ee]rror;[Uu]nknown[^-];[Ss]kipping")
include(CheckFortranSourceCompiles)
check_fortran_source_compiles("${fortran_source}" ${boolean} FAIL_REGEX "${failed_regexes}")
set(${boolean} ${${boolean}} PARENT_SCOPE)
endif()
endfunction()

View File

@@ -156,17 +156,6 @@ function(libomp_get_libflags libflags)
set(${libflags} ${libflags_local_list} PARENT_SCOPE)
endfunction()
# Fortran flags
function(libomp_get_fflags fflags)
set(fflags_local)
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
libomp_append(fflags_local -m32 LIBOMP_HAVE_M32_FORTRAN_FLAG)
endif()
set(fflags_local ${fflags_local} ${LIBOMP_FFLAGS})
libomp_setup_flags(fflags_local)
set(${fflags} ${fflags_local} PARENT_SCOPE)
endfunction()
# Python generate-defs.py flags (For Windows only)
function(libomp_get_gdflags gdflags)
set(gdflags_local)

View File

@@ -16,7 +16,6 @@ include(CheckIncludeFile)
include(CheckLibraryExists)
include(CheckIncludeFiles)
include(CheckSymbolExists)
include(LibompCheckFortranFlag)
include(LLVMCheckCompilerLinkerFlag)
# Check for versioned symbols
@@ -97,9 +96,6 @@ if(WIN32)
endforeach()
endforeach()
endif()
if(${LIBOMP_FORTRAN_MODULES})
libomp_check_fortran_flag(-m32 LIBOMP_HAVE_M32_FORTRAN_FLAG)
endif()
# Check non-posix pthread API here before CMAKE_REQUIRED_DEFINITIONS gets messed up
check_symbol_exists(pthread_setname_np "pthread.h" LIBOMP_HAVE_PTHREAD_SETNAME_NP)

View File

@@ -382,46 +382,6 @@ endif()
configure_file(${LIBOMP_INC_DIR}/omp_lib.h.var omp_lib.h @ONLY)
configure_file(${LIBOMP_INC_DIR}/omp_lib.F90.var omp_lib.F90 @ONLY)
set(BUILD_FORTRAN_MODULES False)
if (NOT ${LIBOMP_FORTRAN_MODULES_COMPILER} STREQUAL "")
# If libomp is built as an LLVM runtime and the flang compiler is available,
# compile the Fortran module files.
message(STATUS "configuring openmp to build Fortran module files using ${LIBOMP_FORTRAN_MODULES_COMPILER}")
set(LIBOMP_FORTRAN_SOURCE_FILE omp_lib.F90)
add_custom_target(libomp-mod ALL DEPENDS omp_lib.mod omp_lib_kinds.mod)
add_custom_command(
OUTPUT omp_lib.mod omp_lib_kinds.mod
COMMAND ${LIBOMP_FORTRAN_MODULES_COMPILER} -cpp -fsyntax-only ${LIBOMP_FORTRAN_SOURCE_FILE}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${LIBOMP_FORTRAN_SOURCE_FILE}
${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h
)
set(BUILD_FORTRAN_MODULES True)
elseif(${LIBOMP_FORTRAN_MODULES})
# The following requests explicit building of the Fortran module files
# Workaround for gfortran to build modules with the
# omp_sched_monotonic integer parameter
if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
set(ADDITIONAL_Fortran_FLAGS "-fno-range-check")
endif()
add_custom_target(libomp-mod ALL DEPENDS omp_lib.mod omp_lib_kinds.mod)
set_target_properties(libomp-mod PROPERTIES FOLDER "OpenMP/Misc")
libomp_get_fflags(LIBOMP_CONFIGURED_FFLAGS)
if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
set(LIBOMP_FORTRAN_SOURCE_FILE omp_lib.F90)
else()
message(FATAL_ERROR "Fortran module build requires Fortran 90 compiler")
endif()
add_custom_command(
OUTPUT omp_lib.mod omp_lib_kinds.mod
COMMAND ${CMAKE_Fortran_COMPILER} -c ${ADDITIONAL_Fortran_FLAGS}
${LIBOMP_CONFIGURED_FFLAGS} ${LIBOMP_FORTRAN_SOURCE_FILE}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${LIBOMP_FORTRAN_SOURCE_FILE}
${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h
)
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES omp_lib${CMAKE_C_OUTPUT_EXTENSION})
set(BUILD_FORTRAN_MODULES True)
endif()
# Move files to exports/ directory if requested
if(${LIBOMP_COPY_EXPORTS})
include(LibompExports)
@@ -502,15 +462,32 @@ if(${LIBOMP_OMPT_SUPPORT})
install(FILES ${LIBOMP_HEADERS_INTDIR}/omp-tools.h DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH} RENAME ompt.h)
set(LIBOMP_OMP_TOOLS_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
endif()
if(${BUILD_FORTRAN_MODULES})
# Build the modules files if a Fortran compiler is available.
# Only LLVM_ENABLE_RUNTIMES=openmp is supported, LLVM_ENABLE_PROJECTS=openmp
# has been deprecated.
if(LIBOMP_FORTRAN_MODULES)
add_library(libomp-mod OBJECT
omp_lib.F90
)
set_target_properties(libomp-mod PROPERTIES FOLDER "OpenMP/Fortran Modules")
if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
target_compile_options(libomp-mod PRIVATE -fno-range-check)
endif()
flang_module_target(libomp-mod PUBLIC)
if (FORTRAN_MODULE_DEPS)
add_dependencies(libomp-mod ${FORTRAN_MODULE_DEPS})
endif ()
set (destination ${LIBOMP_HEADERS_INSTALL_PATH})
if (NOT ${LIBOMP_MODULES_INSTALL_PATH} STREQUAL "")
set (destination ${LIBOMP_MODULES_INSTALL_PATH})
endif()
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h
${CMAKE_CURRENT_BINARY_DIR}/omp_lib.mod
${CMAKE_CURRENT_BINARY_DIR}/omp_lib_kinds.mod
DESTINATION ${destination}
)
endif()

View File

@@ -48,6 +48,7 @@ if config.test_fortran_compiler:
ToolSubst(
"%flang",
command=config.test_fortran_compiler,
extra_args=config.test_fortran_flags.split(),
unresolved="fatal",
),
], [config.llvm_tools_dir])

View File

@@ -8,6 +8,7 @@ config.test_compiler_has_omp_h = @OPENMP_TEST_COMPILER_HAS_OMP_H@
config.test_filecheck = "@OPENMP_FILECHECK_EXECUTABLE@"
config.test_not = "@OPENMP_NOT_EXECUTABLE@"
config.test_openmp_flags = "@OPENMP_TEST_OPENMP_FLAGS@"
config.test_fortran_flags = "@OPENMP_TEST_Fortran_FLAGS@"
config.test_extra_flags = "@OPENMP_TEST_FLAGS@"
config.libomp_obj_root = "@CMAKE_CURRENT_BINARY_DIR@"
config.library_dir = "@LIBOMP_LIBRARY_DIR@"

View File

@@ -85,6 +85,42 @@ include(CheckLibraryExists)
include(LLVMCheckCompilerLinkerFlag)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
include(ExtendPath)
# 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 used.
if (CMAKE_VERSION VERSION_LESS "3.24" AND CMAKE_Fortran_COMPILER)
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 ()
# Determine whether we are in the runtimes/runtimes-bins directory of a
@@ -94,17 +130,6 @@ if (LLVM_LIBRARY_DIR AND LLVM_TOOLS_BINARY_DIR AND PACKAGE_VERSION)
set(LLVM_TREE_AVAILABLE ON)
endif()
if(LLVM_TREE_AVAILABLE)
# Setting these variables will allow the sub-build to put their outputs into
# the library and bin directories of the top-level build.
set(LLVM_LIBRARY_OUTPUT_INTDIR ${LLVM_LIBRARY_DIR})
set(LLVM_RUNTIME_OUTPUT_INTDIR ${LLVM_TOOLS_BINARY_DIR})
else()
# Use own build directory for artifact output.
set(LLVM_LIBRARY_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}")
set(LLVM_RUNTIME_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin")
endif()
# CMake omits default compiler include paths, but in runtimes build, we use
# -nostdinc and -nostdinc++ and control include paths manually so this behavior
# is undesirable. Filtering CMAKE_{LANG}_IMPLICIT_INCLUDE_DIRECTORIES to remove
@@ -217,6 +242,61 @@ message(STATUS "LLVM default target triple: ${LLVM_DEFAULT_TARGET_TRIPLE}")
set(LLVM_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}")
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.
# LLVM_LIBRARY_OUTPUT_INTDIR/LLVM_RUNTIME_OUTPUT_INTDIR is used by
# AddLLVM.cmake as artifact output locations.
set(LLVM_LIBRARY_OUTPUT_INTDIR ${LLVM_LIBRARY_DIR})
set(LLVM_RUNTIME_OUTPUT_INTDIR ${LLVM_TOOLS_BINARY_DIR})
# 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(RUNTIMES_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
get_clang_resource_dir(RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT)
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. Use own build directory for artifact output.
set(LLVM_LIBRARY_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}")
set(LLVM_RUNTIME_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin")
# 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(RUNTIMES_OUTPUT_RESOURCE_DIR "${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
set(RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
endif()
# 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.
# FIXME: For shared libraries, 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>/lib<name>.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.
include(GetToolchainDirs)
get_toolchain_library_subdir(toolchain_lib_subdir)
extend_path(RUNTIMES_OUTPUT_RESOURCE_LIB_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}")
set(RUNTIMES_INSTALL_RESOURCE_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT}" CACHE PATH "Path to install headers, runtime libraries, and Fortran modules to (default: Clang resource dir)")
extend_path(RUNTIMES_INSTALL_RESOURCE_LIB_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}")
cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_DIR)
cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_PATH)
cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_LIB_DIR)
cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_LIB_PATH)
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(option_prefix "")
if (CMAKE_C_SIMULATE_ID MATCHES "MSVC")
@@ -328,6 +408,127 @@ if(LLVM_INCLUDE_TESTS)
umbrella_lit_testsuite_begin(check-runtimes)
endif()
include(CheckFortranSourceCompiles)
# Enable building Fortran modules
# * Set up the Fortran compiler
# * Determine files location in the Clang/Flang resource dir
# * Install module files
macro (flang_module_fortran_enable)
# Assume flang modules are enabled until all tests pass
set(FORTRAN_MODULE_DEPS "")
set(RUNTIMES_FLANG_MODULES_ENABLED_default OFF)
include(CheckLanguage)
check_language(Fortran)
if (CMAKE_Fortran_COMPILER)
enable_language(Fortran)
if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
# In a bootstrapping build, the intrinsic modules are not built yet.
# Targets can depend on flang-rt-mod to ensure they are built before.
set(FORTRAN_MODULE_DEPS flang-rt-mod)
set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
message(STATUS "${LLVM_SUBPROJECT_TITLE}: Building Fortran modules for Flang bootstrapping itself")
else ()
# Check whether building modules works, avoid causing the entire build to fail because of Fortran.
# The primary situation we want to support here is Flang or its intrinsic modules were built separately in a non-bootstrapping build.
cmake_push_check_state(RESET)
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
check_fortran_source_compiles("
subroutine testroutine
use iso_c_binding
end subroutine
" HAVE_FORTRAN_INTRINSIC_MODS SRC_EXT F90)
cmake_pop_check_state()
if (HAVE_FORTRAN_INTRINSIC_MODS)
set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
message(STATUS "${LLVM_SUBPROJECT_TITLE}: Non-bootstrapping Fortran modules build (${CMAKE_Fortran_COMPILER_ID} located at ${CMAKE_Fortran_COMPILER})")
else ()
message(STATUS "Not compiling Flang modules: Not passing smoke check")
endif ()
endif ()
else ()
message(STATUS "Not compiling Flang modules: Fortran not enabled")
endif ()
option(RUNTIMES_FLANG_MODULES_ENABLED "Build Fortran modules" "${RUNTIMES_FLANG_MODULES_ENABLED_default}")
if (RUNTIMES_FLANG_MODULES_ENABLED)
if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
get_toolchain_module_subdir(toolchain_mod_subdir)
extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_mod_subdir}")
extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_mod_subdir}")
else ()
# For non-Flang compilers, avoid the risk of Flang accidentally picking them up.
extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
endif ()
cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR)
cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
# Avoid module files to be installed multiple times if this macro is called multiple times
get_property(is_installed GLOBAL PROPERTY RUNTIMES_MODS_INSTALLED)
if (NOT is_installed)
# No way to find out which mod files built by target individually, so install the entire output directory
# https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
cmake_path(NORMAL_PATH destination)
install(DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
DESTINATION "${destination}"
)
set_property(GLOBAL PROPERTY RUNTIMES_MODS_INSTALLED TRUE)
endif ()
endif ()
endmacro ()
# Set options to compile Fortran module files.
#
# Usage:
#
# flang_module_target(name
# PUBLIC
# Modules files are to be used by other Fortran sources. If a library is
# compiled multiple times (e.g. static/shared, or msvcrt variants), only
# one of those can be public module files; non-public modules are still
# generated but to be forgotten deep inside the build directory to not
# conflict with each other.
# Also, installs the module with the toolchain.
# )
function (flang_module_target tgtname)
set(options PUBLIC)
cmake_parse_arguments(ARG
"${options}"
""
""
${ARGN})
if (NOT RUNTIMES_FLANG_MODULES_ENABLED)
return ()
endif ()
# Let it find the other public module files
target_compile_options(${tgtname} PRIVATE
"$<$<COMPILE_LANGUAGE:Fortran>:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>"
)
if (ARG_PUBLIC)
set_target_properties(${tgtname}
PROPERTIES
Fortran_MODULE_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
)
else ()
set_target_properties(${tgtname}
PROPERTIES
Fortran_MODULE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${tgtname}.mod"
)
endif ()
endfunction ()
# We do this in two loops so that HAVE_* is set for each runtime before the
# other runtimes are added.
foreach(entry ${runtimes})