Currently, Flang compiles its runtime (libFortranRuntime.a
) within the same CMake builddir as Flang itself. As a consequence, the runtime will only be built for the same target as flang-new
is built for.
As a workaround, one can build Flang again for any intended target triple and use only the runtime library out of it. The Flang runtime can also be built as a standalone project so one would not need to build the entirety of LLVM+Flang again.
LLVM’s other runtime libraries use the LLVM_ENABLE_RUNTIMES
and LLVM_RUNTIME_TARGETS
CMake variables as a more straightforward solution. It also uses the frehsly built Clang itself to build the runtime libraries.
I would like to make FortranRuntime use the same mechanism.
Since #95388, FortranRuntime uses Flang itself to build some of its parts, making things a bit more complicated.
For instance, the standalone build of FortranRuntime does not have access to flang-new and will just leave that part of it out of the runtime (#99737 (comment)).
Also, when building Flang itself as a cross-compiler, the LLVM build system confuses the triples of host, target (of the host compiler), and the default target (of Clang/Flang).
There are some design decisions to make which this RFC is for.
-
The name of the top-level directory.
The straightforward name would be “FortranRuntime”, the current name of the library, but it stands out among the other projects due to the use of PascalCase where others use kebab-case.
-
Subfolder structure
Non-runtime projects are consistently using include// for public headers and lib/ for translation units, but there is much less agreement in runtime projects.
- compiler-rt:
include/<component>
(no<projectname>
) andlib/<component>
- libc:
src/<component>
for headers and translation units, many more non-consistent subdirs - libcxx,libcxxabi:
include/
for std:: headers,src/
for translation units, andlib/
for ABI export lists - libunwind:
include/
for headers,src/
for translation units - offload:
include/
for headers,src/
andplugins-nextgen/
for translation units,DeviceRTL/include
andDeviceRTL/lib
for offload-target code - openmp:
runtime/src
for translation units,runtime/src/include
for headers - pstl:
include/
for headers
I propose to use
lib/<component>
(with<component>
= Runtime, Common, and Decimal as currently structured) for translation units (C++ and Fortran),module/
for the module files (currently inflang/module
), and potentially include/flang/ for header files shared with the Flang compiler (if needed, see below) - compiler-rt:
-
Shared code
The Flang compiler and the FortranRuntime library share some code, but the
LLVM_ENABLE_RUNTIMES
mechanism requires them in separate directories. This raises the question where these belong to. Generally, there are 4 options:
Copy the files, FortranRuntime references then in the flang/ directory, Flang references them in theFortranRuntime/
directory, or they are moved to a common location such as LLVMFrontend. Unless there are only headers, one cannot reuse the Flang-compiler version for the FlangRuntime library since they may not even share the same target triple.
- libDecimal (library for converting between floats and strings)
- include/flang/Runtime/freestanding-tools.h, c-or-cpp.h (used by libDecimal, one FortranRuntime translation unit is C)
- include/flang/Runtime/magic-numbers.h (runtime-ABI definition)
- include/flang/Common/variant.h, optional.h, reference-wrapper.h (According to its comments, required for using the FortranRuntime within CUDA. optional.h was copied over from the standalone version from compiler-rt, reference-wrapper.h from libcudacxx)
- include/flang/Common/api-attrs.h (Introspection macros like LLVM's compiler.h for compiling the runtime for CUDA)
- include/flang/Common/bit-population-count.h, constexpr-bitset.h, leading-zero-bit-count.h, fast-int-set.h (bit-manipulation tools)
- include/flang/Common/enum-class.h, enum-set.h, idioms.h, restorer.h, visit.h (General-purpose code pattern utilities)
- include/flang/Common/real.h (Characteristics of floating-point formats, like number of bits in mantissa)
- include/flang/Common/uint128.h (Implements 128-bit integers for compilers that do not implement (u)int128_t natively)
- include/flang/Common/float128.h (Introspection header for quad-precision support)
- include/flang/Common/format.h (format-string validator)
- include/flang/Common/Fortran.h (Fortran language concepts, mostly enums)
Except libDecimal and Fortran.h, all sources are header-only. FortranRuntime doesn’t seem to use the functions from Fortran.h that require the translation unit.
Some like b. or e. are only really used by the runtime if it wasn’t for libDecimal which is used by both.
For Clang’s runtime libraries, I don’t think there is any shared code between compiler and runtime. For instance, libc has its own minimal version of C++ headers so it can make use of C++ idioms. OpenMP has its own definitions in the runtime and compiler.
In a first iteration, I would just copy the files in question, it may turn out that there may be even less overlap of actual definitions.
-
LLVM_ENABLE_PROJECTS and standalone builds
Currently, FlangRuntime can be built as standalone (using
cmake -S llvm-project/flang/runtime
), but AFAIK the LLVM_ENABLE_RUNTIMES projects generally do not support this (I think OpenMP does, if it did not fall out of maintanance). Is it worth supporting it? Similarly, openmp can be specified in LLVM_ENABLE_PROJECTS, which yields an in-tree build like FortranRuntime does now.