diff --git a/flang-rt/README.md b/flang-rt/README.md index 4fe66a85a269..d79ddcaf2063 100644 --- a/flang-rt/README.md +++ b/flang-rt/README.md @@ -91,12 +91,7 @@ can be any compiler supporting the same ABI. In addition to the compiler, the build must be able to find LLVM development tools such as `lit` and `FileCheck` that are not found in an LLVM's install directory. Use `CMAKE_BINARY_DIR` to point to directory where LLVM has -been built. When building Flang as part of a bootstrapping build -(`LLVM_ENABLE_PROJECTS=flang`), Flang-RT is automatically added -unless configured with `-DFLANG_ENABLE_FLANG_RT=OFF`. Add that option to avoid -having two conflicting versions of the same library. - -A simple build configuration might look like the following: +been built. A simple build configuration might look like the following: ```bash cmake -S /runtimes \ diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index 8cc35442d8a7..76eb13295eb0 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -23,6 +23,7 @@ if (LLVM_ENABLE_EH) endif() set(FLANG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(FLANG_RT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../flang-rt") # Python is needed for symbol extracting tool set(LLVM_MINIMUM_PYTHON_VERSION 3.8) @@ -258,10 +259,24 @@ else() include_directories(SYSTEM ${MLIR_TABLEGEN_OUTPUT_DIR}) endif() -if (FLANG_STANDALONE_BUILD) - message(STATUS "Not building Flang-RT. For a usable Fortran toolchain, compile a standalone Flang-RT.") -elseif (NOT "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES) - message(STATUS "Not building Flang-RT. For a usable Fortran toolchain, either set FLANG_ENABLE_FLANG_RT=ON, add LLVM_ENABLE_RUNTIMES=flang-rt, or compile a standalone Flang-RT.") +set(FLANG_INCLUDE_RUNTIME_default ON) +if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES) + set(FLANG_INCLUDE_RUNTIME_default OFF) +endif () +option(FLANG_INCLUDE_RUNTIME "Build the runtime in-tree (deprecated; to be replaced with LLVM_ENABLE_RUNTIMES=flang-rt)" ${FLANG_INCLUDE_RUNTIME_default}) +if (FLANG_INCLUDE_RUNTIME) + if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES) + message(WARNING "Building Flang-RT using LLVM_ENABLE_RUNTIMES. FLANG_INCLUDE_RUNTIME=${FLANG_INCLUDE_RUNTIME} ignored.") + set(FLANG_INCLUDE_RUNTIME OFF) + else () + message(STATUS "Building Flang-RT in-tree") + endif () +else () + if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES) + message(STATUS "Building Flang-RT using LLVM_ENABLE_RUNTIMES") + else () + message(STATUS "Not building Flang-RT. For a usable Fortran toolchain, either add LLVM_ENABLE_RUNTIMES=flang-rt, or compile a standalone Flang-RT.") + endif () endif () set(FLANG_TOOLS_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH @@ -486,6 +501,12 @@ if (FLANG_INCLUDE_TESTS) add_compile_definitions(FLANG_INCLUDE_TESTS=1) endif() +option(FLANG_CUF_RUNTIME + "Compile CUDA Fortran runtime sources" OFF) +if (FLANG_CUF_RUNTIME) + find_package(CUDAToolkit REQUIRED) +endif() + add_subdirectory(include) add_subdirectory(lib) add_subdirectory(cmake/modules) @@ -496,6 +517,10 @@ if (FLANG_BUILD_TOOLS) add_subdirectory(tools) endif() +if (FLANG_INCLUDE_RUNTIME) + add_subdirectory(runtime) +endif () + if (LLVM_INCLUDE_EXAMPLES) add_subdirectory(examples) endif() diff --git a/flang/cmake/modules/AddFlangOffloadRuntime.cmake b/flang/cmake/modules/AddFlangOffloadRuntime.cmake new file mode 100644 index 000000000000..eb0e964559ed --- /dev/null +++ b/flang/cmake/modules/AddFlangOffloadRuntime.cmake @@ -0,0 +1,146 @@ +option(FLANG_EXPERIMENTAL_CUDA_RUNTIME + "Compile Fortran runtime as CUDA sources (experimental)" OFF + ) + +option(FLANG_CUDA_RUNTIME_PTX_WITHOUT_GLOBAL_VARS + "Do not compile global variables' definitions when producing PTX library" OFF + ) + +set(FLANG_LIBCUDACXX_PATH "" CACHE PATH "Path to libcu++ package installation") + +set(FLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD "off" CACHE STRING + "Compile Fortran runtime as OpenMP target offload sources (experimental). Valid options are 'off', 'host_device', 'nohost'") + +set(FLANG_OMP_DEVICE_ARCHITECTURES "all" CACHE STRING + "List of OpenMP device architectures to be used to compile the Fortran runtime (e.g. 'gfx1103;sm_90')") + +macro(enable_cuda_compilation name files) + if (FLANG_EXPERIMENTAL_CUDA_RUNTIME) + if (BUILD_SHARED_LIBS) + message(FATAL_ERROR + "BUILD_SHARED_LIBS is not supported for CUDA build of Fortran runtime" + ) + endif() + + enable_language(CUDA) + + # TODO: figure out how to make target property CUDA_SEPARABLE_COMPILATION + # work, and avoid setting CMAKE_CUDA_SEPARABLE_COMPILATION. + set(CMAKE_CUDA_SEPARABLE_COMPILATION ON) + + # Treat all supported sources as CUDA files. + set_source_files_properties(${files} PROPERTIES LANGUAGE CUDA) + set(CUDA_COMPILE_OPTIONS) + if ("${CMAKE_CUDA_COMPILER_ID}" MATCHES "Clang") + # Allow varargs. + set(CUDA_COMPILE_OPTIONS + -Xclang -fcuda-allow-variadic-functions + ) + endif() + if ("${CMAKE_CUDA_COMPILER_ID}" MATCHES "NVIDIA") + set(CUDA_COMPILE_OPTIONS + --expt-relaxed-constexpr + # Disable these warnings: + # 'long double' is treated as 'double' in device code + -Xcudafe --diag_suppress=20208 + -Xcudafe --display_error_number + ) + endif() + set_source_files_properties(${files} PROPERTIES COMPILE_OPTIONS + "${CUDA_COMPILE_OPTIONS}" + ) + + if (EXISTS "${FLANG_LIBCUDACXX_PATH}/include") + # When using libcudacxx headers files, we have to use them + # for all files of F18 runtime. + include_directories(AFTER ${FLANG_LIBCUDACXX_PATH}/include) + add_compile_definitions(RT_USE_LIBCUDACXX=1) + endif() + + # Add an OBJECT library consisting of CUDA PTX. + llvm_add_library(${name}PTX OBJECT PARTIAL_SOURCES_INTENDED ${files}) + set_property(TARGET obj.${name}PTX PROPERTY CUDA_PTX_COMPILATION ON) + if (FLANG_CUDA_RUNTIME_PTX_WITHOUT_GLOBAL_VARS) + target_compile_definitions(obj.${name}PTX + PRIVATE FLANG_RUNTIME_NO_GLOBAL_VAR_DEFS + ) + endif() + endif() +endmacro() + +macro(enable_omp_offload_compilation files) + if (NOT FLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD STREQUAL "off") + # 'host_device' build only works with Clang compiler currently. + # The build is done with the CMAKE_C/CXX_COMPILER, i.e. it does not use + # the in-tree built Clang. We may have a mode that would use the in-tree + # built Clang. + # + # 'nohost' is supposed to produce an LLVM Bitcode library, + # and it has to be done with a C/C++ compiler producing LLVM Bitcode + # compatible with the LLVM toolchain version distributed with the Flang + # compiler. + # In general, the in-tree built Clang should be used for 'nohost' build. + # Note that 'nohost' build does not produce the host version of Flang + # runtime library, so there will be two separate distributable objects. + # 'nohost' build is a TODO. + + if (NOT FLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD STREQUAL "host_device") + message(FATAL_ERROR "Unsupported OpenMP offload build of Flang runtime") + endif() + if (BUILD_SHARED_LIBS) + message(FATAL_ERROR + "BUILD_SHARED_LIBS is not supported for OpenMP offload build of Fortran runtime" + ) + endif() + + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND + "${CMAKE_C_COMPILER_ID}" MATCHES "Clang") + + set(all_amdgpu_architectures + "gfx700;gfx701;gfx801;gfx803;gfx900;gfx902;gfx906" + "gfx908;gfx90a;gfx90c;gfx942;gfx950;gfx1010;gfx1030" + "gfx1031;gfx1032;gfx1033;gfx1034;gfx1035;gfx1036" + "gfx1100;gfx1101;gfx1102;gfx1103;gfx1150;gfx1151" + "gfx1152;gfx1153;gfx1200;gfx1201" + ) + set(all_nvptx_architectures + "sm_35;sm_37;sm_50;sm_52;sm_53;sm_60;sm_61;sm_62" + "sm_70;sm_72;sm_75;sm_80;sm_86;sm_89;sm_90" + ) + set(all_gpu_architectures + "${all_amdgpu_architectures};${all_nvptx_architectures}" + ) + # TODO: support auto detection on the build system. + if (FLANG_OMP_DEVICE_ARCHITECTURES STREQUAL "all") + set(FLANG_OMP_DEVICE_ARCHITECTURES ${all_gpu_architectures}) + endif() + list(REMOVE_DUPLICATES FLANG_OMP_DEVICE_ARCHITECTURES) + + string(REPLACE ";" "," compile_for_architectures + "${FLANG_OMP_DEVICE_ARCHITECTURES}" + ) + + set(OMP_COMPILE_OPTIONS + -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}" + ) + + # Enable "declare target" in the source code. + set_source_files_properties(${files} + PROPERTIES COMPILE_DEFINITIONS OMP_OFFLOAD_BUILD + ) + else() + message(FATAL_ERROR + "Flang runtime build is not supported for these compilers:\n" + "CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}\n" + "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}") + endif() + endif() +endmacro() diff --git a/flang/examples/CMakeLists.txt b/flang/examples/CMakeLists.txt index 746a6f23ae01..23c6e790791f 100644 --- a/flang/examples/CMakeLists.txt +++ b/flang/examples/CMakeLists.txt @@ -1,3 +1,6 @@ +if (FLANG_INCLUDE_RUNTIME) + add_subdirectory(ExternalHelloWorld) +endif () add_subdirectory(PrintFlangFunctionNames) add_subdirectory(FlangOmpReport) add_subdirectory(FeatureList) diff --git a/flang/examples/ExternalHelloWorld/CMakeLists.txt b/flang/examples/ExternalHelloWorld/CMakeLists.txt new file mode 100644 index 000000000000..dbb69475976d --- /dev/null +++ b/flang/examples/ExternalHelloWorld/CMakeLists.txt @@ -0,0 +1,9 @@ +# This test is not run by default as it requires input. +add_llvm_example(external-hello-world + ${FLANG_RT_SOURCE_DIR}/examples/ExternalHelloWorld/external-hello.cpp +) + +target_link_libraries(external-hello-world + PRIVATE + flang_rt.runtime + ) diff --git a/flang/runtime/CMakeLists.txt b/flang/runtime/CMakeLists.txt new file mode 100644 index 000000000000..f9378d4ed431 --- /dev/null +++ b/flang/runtime/CMakeLists.txt @@ -0,0 +1,385 @@ +#===-- runtime/CMakeLists.txt ----------------------------------------------===# +# +# 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 +# +#===------------------------------------------------------------------------===# + +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + cmake_minimum_required(VERSION 3.20.0) + + project(FlangRuntime C CXX) + + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED TRUE) + set(CMAKE_CXX_EXTENSIONS OFF) + + set(FLANG_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") + set(FLANG_RT_SOURCE_DIR "${FLANG_SOURCE_DIR}/../flang-rt") + + set(LLVM_COMMON_CMAKE_UTILS "${FLANG_SOURCE_DIR}/../cmake") + set(LLVM_CMAKE_UTILS "${FLANG_SOURCE_DIR}/../llvm/cmake") + set(CLANG_CMAKE_UTILS "${FLANG_SOURCE_DIR}/../clang/cmake") + + # Add path for custom modules + list(INSERT CMAKE_MODULE_PATH 0 + "${FLANG_SOURCE_DIR}/cmake" + "${FLANG_SOURCE_DIR}/cmake/modules" + "${LLVM_COMMON_CMAKE_UTILS}" + "${LLVM_COMMON_CMAKE_UTILS}/Modules" + "${LLVM_CMAKE_UTILS}" + "${LLVM_CMAKE_UTILS}/modules" + "${CLANG_CMAKE_UTILS}/modules" + ) + + include(AddClang) + include(AddLLVM) + include(AddFlang) + include(HandleLLVMOptions) + + include(TestBigEndian) + test_big_endian(IS_BIGENDIAN) + if (IS_BIGENDIAN) + add_compile_definitions(FLANG_BIG_ENDIAN=1) + else () + add_compile_definitions(FLANG_LITTLE_ENDIAN=1) + endif () + include_directories(BEFORE + ${FLANG_SOURCE_DIR}/include) + + # The out of tree builds of the compiler and the Fortran runtime + # must use the same setting of FLANG_RUNTIME_F128_MATH_LIB + # to be composable. Failure to synchronize this setting may result + # in linking errors or fatal failures in F128 runtime functions. + set(FLANG_RUNTIME_F128_MATH_LIB "" CACHE STRING + "Specifies the target library used for implementing IEEE-754 128-bit float \ + math in F18 runtime, e.g. it might be libquadmath for targets where \ + REAL(16) is mapped to __float128, or libm for targets where REAL(16) \ + is mapped to long double, etc." + ) + + option(FLANG_CUF_RUNTIME + "Compile CUDA Fortran runtime sources" OFF) + if (FLANG_CUF_RUNTIME) + find_package(CUDAToolkit REQUIRED) + endif() +endif() + +# Runtime files are in Flang-RT's source dir. +function (runtime_source_files outvar) + cmake_parse_arguments(ARG "" "SUBDIR" "" ${ARGN}) + + set(new_sources "") + foreach (source IN LISTS "${outvar}") + set(new_source "${FLANG_RT_SOURCE_DIR}/lib") + cmake_path(APPEND new_source "${ARG_SUBDIR}") + cmake_path(APPEND new_source "${source}") + list(APPEND new_sources "${new_source}") + endforeach () + set("${outvar}" ${new_sources} PARENT_SCOPE) +endfunction () + +# Runtime includes are in Flang-RT's source dir. +include_directories(BEFORE "${FLANG_RT_SOURCE_DIR}/include") + +set(linked_libraries "") + +# function checks +find_package(Backtrace) +set(HAVE_BACKTRACE ${Backtrace_FOUND}) +set(BACKTRACE_HEADER ${Backtrace_HEADER}) +if(HAVE_BACKTRACE) + list(APPEND linked_libraries ${Backtrace_LIBRARY}) +endif() + +include(CheckCXXSymbolExists) +include(CheckCXXSourceCompiles) +check_cxx_symbol_exists(strerror_r string.h HAVE_STRERROR_R) +# Can't use symbol exists here as the function is overloaded in C++ +check_cxx_source_compiles( + "#include + int main() { + char buf[4096]; + return strerror_s(buf, 4096, 0); + } + " + HAVE_DECL_STRERROR_S) + +# Check if 128-bit float computations can be done via long double. +check_cxx_source_compiles( + "#include + #if LDBL_MANT_DIG != 113 + #error LDBL_MANT_DIG != 113 + #endif + int main() { return 0; } + " + HAVE_LDBL_MANT_DIG_113) + +check_cxx_compiler_flag(-fno-lto FLANG_RUNTIME_HAS_FNO_LTO_FLAG) +if (FLANG_RUNTIME_HAS_FNO_LTO_FLAG) + set(NO_LTO_FLAGS "-fno-lto") +else() + set(NO_LTO_FLAGS "") +endif() + +# based on AddLLVM.cmake +if (LLVM_COMPILER_IS_GCC_COMPATIBLE) + set(NO_RTTI_FLAGS "-fno-exceptions -fno-rtti") +elseif (MSVC) + set(NO_RTTI_FLAGS "/EHs-c- /GR-") +elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL") + set(NO_RTTI_FLAGS "-qnoeh -qnortti") +endif () + +# When compiling LLVM_ENABLE_RUNTIMES=flang-rt, the build system looks for the +# full path of quadmath.h. In this non-runtimes build, preserve the old behavior +# of just including . +set(FLANG_RT_INCLUDE_QUADMATH_H "") +configure_file("${FLANG_RT_SOURCE_DIR}/cmake/quadmath_wrapper.h.in" "quadmath_wrapper.h") + +configure_file("${FLANG_RT_SOURCE_DIR}/cmake/config.h.cmake.in" config.h) +# include_directories is used here instead of target_include_directories +# because add_flang_library creates multiple objects (STATIC/SHARED, OBJECT) +# with different names +include_directories(AFTER ${CMAKE_CURRENT_BINARY_DIR}) + +append(${NO_LTO_FLAGS} CMAKE_C_FLAGS) +append(${NO_LTO_FLAGS} CMAKE_CXX_FLAGS) +append(${NO_RTTI_FLAGS} CMAKE_CXX_FLAGS) + +# Disable libstdc++/libc++ assertions, even in an LLVM_ENABLE_ASSERTIONS build, +# to avoid an unwanted dependency on libstdc++/libc++.so. +add_definitions(-U_GLIBCXX_ASSERTIONS) +add_definitions(-U_LIBCPP_ENABLE_ASSERTIONS) + +add_subdirectory(Float128Math) + +set(sources + ${FLANG_SOURCE_DIR}/lib/Decimal/binary-to-decimal.cpp + ${FLANG_SOURCE_DIR}/lib/Decimal/decimal-to-binary.cpp + ISO_Fortran_binding.cpp + allocator-registry.cpp + allocatable.cpp + array-constructor.cpp + assign.cpp + buffer.cpp + character.cpp + command.cpp + complex-powi.cpp + complex-reduction.c + connection.cpp + copy.cpp + derived-api.cpp + derived.cpp + descriptor-io.cpp + descriptor.cpp + dot-product.cpp + edit-input.cpp + edit-output.cpp + environment.cpp + exceptions.cpp + execute.cpp + extensions.cpp + external-unit.cpp + extrema.cpp + file.cpp + findloc.cpp + format.cpp + inquiry.cpp + internal-unit.cpp + io-api.cpp + io-api-minimal.cpp + io-error.cpp + io-stmt.cpp + iostat.cpp + main.cpp + matmul-transpose.cpp + matmul.cpp + memory.cpp + misc-intrinsic.cpp + namelist.cpp + non-tbp-dio.cpp + numeric.cpp + pointer.cpp + product.cpp + pseudo-unit.cpp + ragged.cpp + random.cpp + reduce.cpp + reduction.cpp + stat.cpp + stop.cpp + sum.cpp + support.cpp + temporary-stack.cpp + terminator.cpp + time-intrinsic.cpp + tools.cpp + transformational.cpp + type-code.cpp + type-info.cpp + unit-map.cpp + unit.cpp + utf.cpp + ${FORTRAN_MODULE_OBJECTS} +) + +include(AddFlangOffloadRuntime) + +# List of files that are buildable for all devices. +set(supported_files + ${FLANG_SOURCE_DIR}/lib/Decimal/binary-to-decimal.cpp + ${FLANG_SOURCE_DIR}/lib/Decimal/decimal-to-binary.cpp + ISO_Fortran_binding.cpp + allocatable.cpp + allocator-registry.cpp + array-constructor.cpp + assign.cpp + buffer.cpp + character.cpp + connection.cpp + copy.cpp + derived-api.cpp + derived.cpp + descriptor.cpp + descriptor-io.cpp + dot-product.cpp + edit-input.cpp + edit-output.cpp + environment.cpp + extrema.cpp + external-unit.cpp + file.cpp + findloc.cpp + format.cpp + inquiry.cpp + internal-unit.cpp + io-api.cpp + io-api-minimal.cpp + io-error.cpp + io-stmt.cpp + iostat.cpp + matmul-transpose.cpp + matmul.cpp + memory.cpp + misc-intrinsic.cpp + namelist.cpp + non-tbp-dio.cpp + numeric.cpp + pointer.cpp + product.cpp + pseudo-unit.cpp + ragged.cpp + stat.cpp + sum.cpp + support.cpp + terminator.cpp + tools.cpp + transformational.cpp + type-code.cpp + type-info.cpp + unit.cpp + utf.cpp + ) +runtime_source_files(supported_files SUBDIR "runtime") + +enable_cuda_compilation(flang_rt "${supported_files}") +enable_omp_offload_compilation("${supported_files}") + +if (NOT TARGET flang_rt.quadmath) + # If flang_rt.quadmath is not defined, then we are not building + # standalone flang_rt.quadmath library. Instead, include + # the relevant sources into flang_rt.runtime itself. + # The information is provided via FortranFloat128MathILib + # interface library. + get_target_property(f128_sources + FortranFloat128MathILib INTERFACE_SOURCES + ) + if (f128_sources) + # The interface may define special macros for Float128Math files, + # so we need to propagate them. + get_target_property(f128_defs + FortranFloat128MathILib INTERFACE_COMPILE_DEFINITIONS + ) + set_property(SOURCE ${f128_sources} + APPEND PROPERTY COMPILE_DEFINITIONS + ${f128_defs} + ) + get_target_property(f128_include_dirs + FortranFloat128MathILib INTERFACE_INCLUDE_DIRECTORIES + ) + set_property(SOURCE ${f128_sources} + APPEND PROPERTY INCLUDE_DIRECTORIES + ${f128_include_dirs} + ) + list(APPEND sources ${f128_sources}) + endif() +endif() +runtime_source_files(sources SUBDIR "runtime") + + +if (NOT DEFINED MSVC) + add_flang_library(flang_rt.runtime + ${sources} + LINK_LIBS + ${linked_libraries} + + INSTALL_WITH_TOOLCHAIN + ) +else() + add_flang_library(flang_rt.runtime + ${sources} + LINK_LIBS + ${linked_libraries} + ) + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded) + add_flang_library(flang_rt.runtime.static ${sources} + INSTALL_WITH_TOOLCHAIN) + set_target_properties(flang_rt.runtime.static PROPERTIES FOLDER "Flang/Runtime Libraries") + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL) + add_flang_library(flang_rt.runtime.dynamic ${sources} + INSTALL_WITH_TOOLCHAIN) + set_target_properties(flang_rt.runtime.dynamic PROPERTIES FOLDER "Flang/Runtime Libraries") + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug) + add_flang_library(flang_rt.runtime.static_dbg ${sources} + INSTALL_WITH_TOOLCHAIN) + set_target_properties(flang_rt.runtime.static_dbg PROPERTIES FOLDER "Flang/Runtime Libraries") + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebugDLL) + add_flang_library(flang_rt.runtime.dynamic_dbg ${sources} + INSTALL_WITH_TOOLCHAIN) + set_target_properties(flang_rt.runtime.dynamic_dbg PROPERTIES FOLDER "Flang/Runtime Libraries") + add_dependencies(flang_rt.runtime + flang_rt.runtime.static + flang_rt.runtime.dynamic + flang_rt.runtime.static_dbg + flang_rt.runtime.dynamic_dbg) +endif() +set_target_properties(flang_rt.runtime PROPERTIES FOLDER "Flang/Runtime Libraries") + +# If flang_rt is part of a Flang build (and not a separate build) then +# add dependency to make sure that Fortran runtime library is being built after +# we have the Flang compiler available. This also includes the MODULE files +# that compile when the 'flang' target is built. +# +# TODO: This is a workaround and should be updated when runtime build procedure +# is changed to a regular runtime build. See discussion in PR #95388. +if (TARGET flang AND TARGET module_files) + add_dependencies(flang_rt.runtime flang module_files) +endif() + +if (FLANG_CUF_RUNTIME) + add_subdirectory(CUDA) +endif() + +# Compatibility targets. +add_custom_target(flang-rt) +add_dependencies(flang-rt flang_rt.runtime) +if (TARGET flang_rt.quadmath) + add_dependencies(flang-rt flang_rt.quadmath) +endif () +if (TARGET flang_rt.cuda_${CUDAToolkit_VERSION_MAJOR}) + add_dependencies(flang-rt flang_rt.cuda_${CUDAToolkit_VERSION_MAJOR}) +endif () +add_custom_target(FortranRuntime) +add_dependencies(FortranRuntime flang_rt.runtime) diff --git a/flang/runtime/CUDA/CMakeLists.txt b/flang/runtime/CUDA/CMakeLists.txt new file mode 100644 index 000000000000..aac1f6266181 --- /dev/null +++ b/flang/runtime/CUDA/CMakeLists.txt @@ -0,0 +1,43 @@ +#===-- runtime/CUDA/CMakeLists.txt -----------------------------------------===# +# +# 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 +# +#===------------------------------------------------------------------------===# + +include_directories(${CUDAToolkit_INCLUDE_DIRS}) + +# libflang_rt.cuda depends on a certain version of CUDA. To be able to have +# multiple build of this library with different CUDA version, the version is +# added to the library name. +set(CUFRT_LIBNAME flang_rt.cuda_${CUDAToolkit_VERSION_MAJOR}) + +set(sources + allocator.cpp + allocatable.cpp + descriptor.cpp + init.cpp + kernel.cpp + memmove-function.cpp + memory.cpp + pointer.cpp + registration.cpp +) +runtime_source_files(sources SUBDIR "cuda") + +add_flang_library(${CUFRT_LIBNAME} + ${sources} +) + +if (BUILD_SHARED_LIBS) + set(CUDA_RT_TARGET CUDA::cudart) +else() + set(CUDA_RT_TARGET CUDA::cudart_static) +endif() + +target_link_libraries(${CUFRT_LIBNAME} + PRIVATE + flang_rt.runtime + ${CUDA_RT_TARGET} +) diff --git a/flang/runtime/Float128Math/CMakeLists.txt b/flang/runtime/Float128Math/CMakeLists.txt new file mode 100644 index 000000000000..cdac5f893cf9 --- /dev/null +++ b/flang/runtime/Float128Math/CMakeLists.txt @@ -0,0 +1,134 @@ +#===-- runtime/Float128Math/CMakeLists.txt ---------------------------------===# +# +# 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 +# +#===------------------------------------------------------------------------===# + +# FortranFloat128 implements IEEE-754 128-bit float math functions. +# It is a thin wapper and it currently relies on third-party +# libraries available for the target. +# It is distributed as a static library only. +# Fortran programs/libraries that end up linking any of the provided +# will have a dependency on the third-party library that is being +# used for building this flang_rt.quadmath library. + +include(CheckLibraryExists) + +set(sources + acos.cpp + acosh.cpp + asin.cpp + asinh.cpp + atan.cpp + atan2.cpp + atanh.cpp + ceil.cpp + complex-math.c + cos.cpp + cosh.cpp + erf.cpp + erfc.cpp + exp.cpp + exponent.cpp + floor.cpp + fma.cpp + fraction.cpp + hypot.cpp + j0.cpp + j1.cpp + jn.cpp + lgamma.cpp + llround.cpp + log.cpp + log10.cpp + lround.cpp + mod-real.cpp + modulo-real.cpp + nearest.cpp + nearbyint.cpp + norm2.cpp + pow.cpp + random.cpp + remainder.cpp + round.cpp + rrspacing.cpp + scale.cpp + set-exponent.cpp + sin.cpp + sinh.cpp + spacing.cpp + sqrt.cpp + tan.cpp + tanh.cpp + tgamma.cpp + trunc.cpp + y0.cpp + y1.cpp + yn.cpp + ) +runtime_source_files(sources SUBDIR "quadmath") + +include_directories(AFTER "${CMAKE_CURRENT_SOURCE_DIR}/..") +add_library(FortranFloat128MathILib INTERFACE) +target_include_directories(FortranFloat128MathILib INTERFACE + $ + ) + +if (FLANG_RUNTIME_F128_MATH_LIB) + if (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libquadmath") + check_include_file(quadmath.h FOUND_QUADMATH_HEADER) + if(FOUND_QUADMATH_HEADER) + add_compile_definitions(HAS_QUADMATHLIB) + else() + message(FATAL_ERROR + "FLANG_RUNTIME_F128_MATH_LIB setting requires quadmath.h " + "to be available: ${FLANG_RUNTIME_F128_MATH_LIB}" + ) + endif() + else() + message(FATAL_ERROR + "Unsupported third-party library for Fortran F128 math runtime: " + "${FLANG_RUNTIME_F128_MATH_LIB}" + ) + endif() + + add_flang_library(flang_rt.quadmath STATIC INSTALL_WITH_TOOLCHAIN + ${sources}) + + if (DEFINED MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded) + add_flang_library(flang_rt.quadmath.static STATIC INSTALL_WITH_TOOLCHAIN + ${sources} + ) + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug) + add_flang_library(flang_rt.quadmath.static_dbg STATIC INSTALL_WITH_TOOLCHAIN + ${sources} + ) + add_dependencies(flang_rt.quadmath flang_rt.quadmath.static + flang_rt.quadmath.static_dbg + ) + endif() +elseif (HAVE_LDBL_MANT_DIG_113) + # We can use 'long double' versions from libc. + check_library_exists(m sinl "" FOUND_LIBM) + if (FOUND_LIBM) + target_compile_definitions(FortranFloat128MathILib INTERFACE + HAS_LIBM + ) + target_sources(FortranFloat128MathILib INTERFACE ${sources}) + else() + message(FATAL_ERROR "flang_rt.quadmath cannot build without libm") + endif() +else() + # We can use '__float128' version from libc, if it has them. + check_library_exists(m sinf128 "" FOUND_LIBMF128) + if (FOUND_LIBMF128) + target_compile_definitions(FortranFloat128MathILib INTERFACE + HAS_LIBMF128 + ) + # Enable this, when math-entries.h and complex-math.h is ready. + # target_sources(FortranFloat128MathILib INTERFACE ${sources}) + endif() +endif() diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt index 263a786e84b5..17a7f58902dc 100644 --- a/flang/test/CMakeLists.txt +++ b/flang/test/CMakeLists.txt @@ -78,6 +78,10 @@ if (NOT FLANG_STANDALONE_BUILD) ) endif () +if (FLANG_INCLUDE_RUNTIME) + list(APPEND FLANG_TEST_DEPENDS flang_rt.runtime) +endif () + if (LLVM_ENABLE_PLUGINS AND NOT WIN32 AND NOT FLANG_STANDALONE_BUILD) list(APPEND FLANG_TEST_DEPENDS Bye) endif() @@ -128,3 +132,9 @@ if (DEFINED FLANG_TEST_TARGET_TRIPLE) "to use FLANG_TEST_TARGET_TRIPLE.") endif() endif() + +# Compatibility targets. +if (FLANG_INCLUDE_RUNTIME) + add_custom_target(check-flang-rt) + add_dependencies(check-flang-rt check-flang) +endif () diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py index aa27fdc2fe41..0ba80f9a03f2 100644 --- a/flang/test/lit.cfg.py +++ b/flang/test/lit.cfg.py @@ -163,6 +163,9 @@ else: ToolSubst("%not_todo_abort_cmd", command=FindTool("not"), unresolved="fatal") ) +if config.flang_include_runtime: + config.available_features.add("flang-rt") + # Add all the tools and their substitutions (if applicable). Use the search paths provided for # finding the tools. if config.flang_standalone_build: diff --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in index ae5144010bc8..5b66e592bcfe 100644 --- a/flang/test/lit.site.cfg.py.in +++ b/flang/test/lit.site.cfg.py.in @@ -30,6 +30,7 @@ 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@" +config.flang_include_runtime = lit.util.pythonize_bool("@FLANG_INCLUDE_RUNTIME@") import lit.llvm lit.llvm.initialize(lit_config, config) diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt index 817f3687dbcc..a66c8e36b332 100644 --- a/flang/tools/f18/CMakeLists.txt +++ b/flang/tools/f18/CMakeLists.txt @@ -4,9 +4,16 @@ set(LLVM_LINK_COMPONENTS Support ) +# Define the list of Fortran module files that need to be compiled +# to produce an object file for inclusion into the flang_rt.runtime +# library. +set(MODULES_WITH_IMPLEMENTATION + "iso_fortran_env_impl" +) + # Define the list of Fortran module files for which it is # sufficient to generate the module file via -fsyntax-only. -set(MODULES +set(MODULES_WITHOUT_IMPLEMENTATION "__fortran_builtins" "__fortran_ieee_exceptions" "__fortran_type_info" @@ -21,9 +28,10 @@ set(MODULES "ieee_features" "iso_c_binding" "iso_fortran_env" - "iso_fortran_env_impl" ) +set(MODULES ${MODULES_WITH_IMPLEMENTATION} ${MODULES_WITHOUT_IMPLEMENTATION}) + # Check if 128-bit float computations can be done via long double. check_cxx_source_compiles( "#include @@ -101,6 +109,11 @@ if (NOT CMAKE_CROSSCOMPILING) set(compile_with "-fsyntax-only") set(object_output "") set(include_in_link FALSE) + if(${filename} IN_LIST MODULES_WITH_IMPLEMENTATION AND FLANG_INCLUDE_RUNTIME) + set(object_output "${CMAKE_CURRENT_BINARY_DIR}/${filename}${CMAKE_CXX_OUTPUT_EXTENSION}") + set(compile_with -c -o ${object_output}) + set(include_in_link TRUE) + endif() 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 diff --git a/flang/unittests/CMakeLists.txt b/flang/unittests/CMakeLists.txt index b4e969c9426e..a02f791135f1 100644 --- a/flang/unittests/CMakeLists.txt +++ b/flang/unittests/CMakeLists.txt @@ -1,3 +1,5 @@ +include(AddFlangOffloadRuntime) + if (FLANG_EXPERIMENTAL_CUDA_RUNTIME) # If Fortran runtime is built as CUDA library, the linking # of targets that link flang_rt.runtime must be done @@ -10,8 +12,38 @@ endif() add_custom_target(FlangUnitTests) set_target_properties(FlangUnitTests PROPERTIES FOLDER "Flang/Tests") +include_directories("${FLANG_RT_SOURCE_DIR}/include") + +function(add_flang_unittest_offload_properties target) + # Do not apply runtime properties if not even compiling the runtime. + if (NOT FLANG_INCLUDE_RUNTIME) + return () + endif () + + # Set CUDA_RESOLVE_DEVICE_SYMBOLS. + if (FLANG_EXPERIMENTAL_CUDA_RUNTIME) + set_target_properties(${target} + PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON + ) + endif() + # Enable OpenMP offload during linking. We may need to replace + # LINK_OPTIONS with COMPILE_OPTIONS when there are OpenMP offload + # unittests. + # + # FIXME: replace 'native' in --offload-arch option with the list + # of targets that Fortran Runtime was built for. + # Common code must be moved from flang/runtime/CMakeLists.txt. + if (NOT FLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD STREQUAL "off") + set_target_properties(${target} + PROPERTIES LINK_OPTIONS + "-fopenmp;--offload-arch=native" + ) + endif() +endfunction() + function(add_flang_unittest test_dirname) add_unittest(FlangUnitTests ${test_dirname} ${ARGN}) + add_flang_unittest_offload_properties(${test_dirname}) endfunction() if (CXX_SUPPORTS_SUGGEST_OVERRIDE_FLAG) @@ -31,7 +63,11 @@ function(add_flang_nongtest_unittest test_name) set(suffix .test) endif() - set(test_filepath "${test_name}.cpp") + # Sources for runtime tests are in Flang-RT. + set(test_filepath "${FLANG_RT_SOURCE_DIR}/unittests/Evaluate/${test_name}.cpp") + if (NOT EXISTS "${test_filepath}") + set(test_filepath "${test_name}.cpp") + endif () add_executable(${test_name}${suffix} "${test_filepath}") set_target_properties(${test_name}${suffix} PROPERTIES FOLDER "Flang/Tests/Unit") @@ -46,10 +82,15 @@ function(add_flang_nongtest_unittest test_name) if(NOT ARG_SLOW_TEST) add_dependencies(FlangUnitTests ${test_name}${suffix}) endif() + + add_flang_unittest_offload_properties(${test_name}${suffix}) endfunction() add_subdirectory(Optimizer) add_subdirectory(Common) add_subdirectory(Decimal) add_subdirectory(Evaluate) +if (FLANG_INCLUDE_RUNTIME) + add_subdirectory(Runtime) +endif () add_subdirectory(Frontend) diff --git a/flang/unittests/Evaluate/CMakeLists.txt b/flang/unittests/Evaluate/CMakeLists.txt index ed012828a725..2278d61febcb 100644 --- a/flang/unittests/Evaluate/CMakeLists.txt +++ b/flang/unittests/Evaluate/CMakeLists.txt @@ -55,6 +55,22 @@ add_flang_nongtest_unittest(real ) llvm_update_compile_flags(real.test) +if (FLANG_INCLUDE_RUNTIME) + add_flang_nongtest_unittest(reshape + NonGTestTesting + FortranSemantics + FortranEvaluate + flang_rt.runtime + ) + + add_flang_nongtest_unittest(ISO-Fortran-binding + NonGTestTesting + FortranEvaluate + FortranSemantics + flang_rt.runtime + ) +endif () + add_flang_nongtest_unittest(folding FortranSupport NonGTestTesting diff --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt new file mode 100644 index 000000000000..40afec3e113f --- /dev/null +++ b/flang/unittests/Runtime/CMakeLists.txt @@ -0,0 +1,41 @@ +add_flang_unittest(FlangRuntimeTests + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/AccessTest.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Allocatable.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/ArrayConstructor.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/BufferTest.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/CharacterTest.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/CommandTest.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Complex.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/CrashHandlerFixture.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Derived.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/ExternalIOTest.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Format.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Inquiry.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/ListInputTest.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/LogicalFormatTest.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Matmul.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/MatmulTranspose.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/MiscIntrinsic.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Namelist.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Numeric.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/NumericalFormatTest.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Pointer.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Ragged.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Random.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Reduction.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/RuntimeCrashTest.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Stop.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Support.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Time.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/TemporaryStack.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/Transformational.cpp +) + +target_link_libraries(FlangRuntimeTests + PRIVATE + flang_rt.runtime +) + +target_compile_definitions(FlangRuntimeTests PRIVATE NOT_EXE="$") + +add_subdirectory(CUDA) diff --git a/flang/unittests/Runtime/CUDA/CMakeLists.txt b/flang/unittests/Runtime/CUDA/CMakeLists.txt new file mode 100644 index 000000000000..6901da3920a4 --- /dev/null +++ b/flang/unittests/Runtime/CUDA/CMakeLists.txt @@ -0,0 +1,24 @@ +if (FLANG_CUF_RUNTIME) + +add_flang_unittest(FlangCufRuntimeTests + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/CUDA/Allocatable.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/CUDA/AllocatorCUF.cpp + ${FLANG_RT_SOURCE_DIR}/unittests/Runtime/CUDA/Memory.cpp +) + +if (BUILD_SHARED_LIBS) + set(CUDA_RT_TARGET CUDA::cudart) +else() + set(CUDA_RT_TARGET CUDA::cudart_static) +endif() + +target_link_libraries(FlangCufRuntimeTests + PRIVATE + ${CUDA_RT_TARGET} + flang_rt.cuda_${CUDAToolkit_VERSION_MAJOR} + flang_rt.runtime +) + +target_include_directories(FlangCufRuntimeTests PRIVATE ${CUDAToolkit_INCLUDE_DIRS}) + +endif() diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index ec4e63d5ad24..9cf746853119 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -149,12 +149,6 @@ if ("flang" IN_LIST LLVM_ENABLE_PROJECTS) message(STATUS "Enabling clang as a dependency to flang") list(APPEND LLVM_ENABLE_PROJECTS "clang") endif() - - option(FLANG_ENABLE_FLANG_RT "Implicitly add LLVM_ENABLE_RUNTIMES=flang-rt when compiling Flang" ON) - if (FLANG_ENABLE_FLANG_RT AND NOT "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES) - message(STATUS "Enabling Flang-RT as a dependency of Flang") - list(APPEND LLVM_ENABLE_RUNTIMES "flang-rt") - endif () endif() if ("libc" IN_LIST LLVM_ENABLE_PROJECTS)