[RFC][flang] Experimental device build of Flang runtime.
These are initial changes to experiment with building the Fortran runtime
as a CUDA or OpenMP target offload library.
The initial patch defines a set of macros that have to be used consistently
in Flang runtime source code so that it can be built for different
offload devices using different programming models (CUDA, HIP, OpenMP target
offload). Currently supported modes are:
* CUDA: Flang runtime may be built as a fatlib for the host and a set
of CUDA architectures specified during the build. The packaging
of the device code is done by the CUDA toolchain and may differ
from toolchan to toolchain.
* OpenMP offload:
- host_device mode: Flang runtime may be built as a fatlib for the host
and a set of OpenMP offload architectures. The packaging
of the device code is done by the OpenMP offload compiler and may differ
from compiler to compiler.
OpenMP offload 'nohost' mode is a TODO to match the build setup
of libomptarget/DeviceRTL. Flang runtime will be built as LLVM Bitcode
library using Clang/LLVM toolchain. The host part of the library
will be "empty", so there will be two distributable object: the host
Flang runtime and dummy host library with device Flang runtime pieces
packaged using clang-offload-packager and clang.
In all supported modes, enabling parts of Flang runtime for the device
compilation can be done iteratively to make the patches observable.
Note that at any point in time the resulting library may have unresolved
references to not yet enabled parts of Flang runtime.
Example cmake/make commands for building with Clang for NVPTX target:
cmake \
-DFLANG_EXPERIMENTAL_CUDA_RUNTIME=ON \
-DCMAKE_CUDA_ARCHITECTURES=80 \
-DCMAKE_C_COMPILER=/clang_nvptx/bin/clang \
-DCMAKE_CXX_COMPILER=/clang_nvptx/bin/clang++ \
-DCMAKE_CUDA_COMPILER=/clang_nvptx/bin/clang \
/llvm-project/flang/runtime/
make -j FortranRuntime
Example cmake/make commands for building with Clang OpenMP offload:
cmake \
-DFLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD="host_device" \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DFLANG_OMP_DEVICE_ARCHITECTURES="sm_80" \
../flang/runtime/
make -j FortranRuntime
Differential Revision: https://reviews.llvm.org/D151173
diff --git a/flang/runtime/tools.h b/flang/runtime/tools.h
index d96d848..d22093a 100644
--- a/flang/runtime/tools.h
+++ b/flang/runtime/tools.h
@@ -9,6 +9,7 @@
#ifndef FORTRAN_RUNTIME_TOOLS_H_
#define FORTRAN_RUNTIME_TOOLS_H_
+#include "freestanding-tools.h"
#include "terminator.h"
#include "flang/Runtime/cpp-type.h"
#include "flang/Runtime/descriptor.h"
@@ -39,7 +40,7 @@
char *to, std::size_t toLength, const char *from);
// Utility for dealing with elemental LOGICAL arguments
-inline bool IsLogicalElementTrue(
+inline RT_API_ATTRS bool IsLogicalElementTrue(
const Descriptor &logical, const SubscriptValue at[]) {
// A LOGICAL value is false if and only if all of its bytes are zero.
const char *p{logical.Element<char>(at)};
@@ -52,7 +53,7 @@
}
// Check array conformability; a scalar 'x' conforms. Crashes on error.
-void CheckConformability(const Descriptor &to, const Descriptor &x,
+RT_API_ATTRS void CheckConformability(const Descriptor &to, const Descriptor &x,
Terminator &, const char *funcName, const char *toName,
const char *fromName);
@@ -66,7 +67,8 @@
};
// Validate a KIND= argument
-void CheckIntegerKind(Terminator &, int kind, const char *intrinsic);
+RT_API_ATTRS void CheckIntegerKind(
+ Terminator &, int kind, const char *intrinsic);
template <typename TO, typename FROM>
inline void PutContiguousConverted(TO *to, FROM *from, std::size_t count) {
@@ -75,7 +77,7 @@
}
}
-static inline std::int64_t GetInt64(
+static inline RT_API_ATTRS std::int64_t GetInt64(
const char *p, std::size_t bytes, Terminator &terminator) {
switch (bytes) {
case 1:
@@ -116,7 +118,7 @@
// arguments.
template <template <TypeCategory, int> class FUNC, typename RESULT,
typename... A>
-inline RESULT ApplyType(
+inline RT_API_ATTRS RESULT ApplyType(
TypeCategory cat, int kind, Terminator &terminator, A &&...x) {
switch (cat) {
case TypeCategory::Integer:
@@ -217,7 +219,8 @@
// Maps a runtime INTEGER kind value to the appropriate instantiation of
// a function object template and calls it with the supplied arguments.
template <template <int KIND> class FUNC, typename RESULT, typename... A>
-inline RESULT ApplyIntegerKind(int kind, Terminator &terminator, A &&...x) {
+inline RT_API_ATTRS RESULT ApplyIntegerKind(
+ int kind, Terminator &terminator, A &&...x) {
switch (kind) {
case 1:
return FUNC<1>{}(std::forward<A>(x)...);
@@ -237,7 +240,7 @@
}
template <template <int KIND> class FUNC, typename RESULT, typename... A>
-inline RESULT ApplyFloatingPointKind(
+inline RT_API_ATTRS RESULT ApplyFloatingPointKind(
int kind, Terminator &terminator, A &&...x) {
switch (kind) {
#if 0 // TODO: REAL/COMPLEX (2 & 3)
@@ -265,7 +268,8 @@
}
template <template <int KIND> class FUNC, typename RESULT, typename... A>
-inline RESULT ApplyCharacterKind(int kind, Terminator &terminator, A &&...x) {
+inline RT_API_ATTRS RESULT ApplyCharacterKind(
+ int kind, Terminator &terminator, A &&...x) {
switch (kind) {
case 1:
return FUNC<1>{}(std::forward<A>(x)...);
@@ -279,7 +283,8 @@
}
template <template <int KIND> class FUNC, typename RESULT, typename... A>
-inline RESULT ApplyLogicalKind(int kind, Terminator &terminator, A &&...x) {
+inline RT_API_ATTRS RESULT ApplyLogicalKind(
+ int kind, Terminator &terminator, A &&...x) {
switch (kind) {
case 1:
return FUNC<1>{}(std::forward<A>(x)...);