9#ifndef FORTRAN_RUNTIME_FREESTANDING_TOOLS_H_
10#define FORTRAN_RUNTIME_FREESTANDING_TOOLS_H_
12#include "flang/Common/api-attrs.h"
13#include "flang/Runtime/c-or-cpp.h"
22#if !defined(STD_FILL_N_UNSUPPORTED) && \
23 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
24#define STD_FILL_N_UNSUPPORTED 1
27#if !defined(STD_MEMMOVE_UNSUPPORTED) && \
28 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
29#define STD_MEMMOVE_UNSUPPORTED 1
32#if !defined(STD_STRLEN_UNSUPPORTED) && \
33 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
34#define STD_STRLEN_UNSUPPORTED 1
37#if !defined(STD_MEMCMP_UNSUPPORTED) && \
38 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
39#define STD_MEMCMP_UNSUPPORTED 1
42#if !defined(STD_REALLOC_UNSUPPORTED) && \
43 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
44#define STD_REALLOC_UNSUPPORTED 1
47#if !defined(STD_MEMCHR_UNSUPPORTED) && \
48 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
49#define STD_MEMCHR_UNSUPPORTED 1
52#if !defined(STD_STRCPY_UNSUPPORTED) && \
53 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
54#define STD_STRCPY_UNSUPPORTED 1
57#if !defined(STD_STRCMP_UNSUPPORTED) && \
58 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
59#define STD_STRCMP_UNSUPPORTED 1
62#if !defined(STD_TOUPPER_UNSUPPORTED) && \
63 (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)
64#define STD_TOUPPER_UNSUPPORTED 1
67#if defined(OMP_OFFLOAD_BUILD) && defined(__clang__)
68#define STD_FILL_N_UNSUPPORTED 1
69#define STD_MEMSET_USE_BUILTIN 1
70#define STD_MEMSET_UNSUPPORTED 1
71#define STD_MEMCPY_USE_BUILTIN 1
72#define STD_MEMCPY_UNSUPPORTED 1
73#define STD_MEMMOVE_UNSUPPORTED 1
74#define STD_STRLEN_UNSUPPORTED 1
75#define STD_MEMCMP_UNSUPPORTED 1
76#define STD_REALLOC_UNSUPPORTED 1
77#define STD_MEMCHR_UNSUPPORTED 1
78#define STD_STRCPY_UNSUPPORTED 1
79#define STD_STRCMP_UNSUPPORTED 1
80#define STD_TOUPPER_UNSUPPORTED 1
81#define STD_ABORT_USE_BUILTIN 1
82#define STD_ABORT_UNSUPPORTED 1
85namespace Fortran::runtime {
87#if STD_FILL_N_UNSUPPORTED
90template <
typename A,
typename B>
91static inline RT_API_ATTRS std::enable_if_t<std::is_convertible_v<B, A>,
void>
92fill_n(A *start, std::size_t count,
const B &value) {
93 for (std::size_t j{0}; j < count; ++j) {
101#if STD_MEMSET_USE_BUILTIN
102static inline RT_API_ATTRS
void memset(
103 void *dest,
unsigned char value, std::size_t count) {
104 __builtin_memset(dest, value, count);
106#elif STD_MEMSET_UNSUPPORTED
107static inline RT_API_ATTRS
void memset(
108 void *dest,
unsigned char value, std::size_t count) {
109 char *to{
reinterpret_cast<char *
>(dest)};
119#if STD_MEMCPY_USE_BUILTIN
120static inline RT_API_ATTRS
void memcpy(
121 void *dest,
const void *src, std::size_t count) {
122 __builtin_memcpy(dest, src, count);
124#elif STD_MEMCPY_UNSUPPORTED
125static inline RT_API_ATTRS
void memcpy(
126 void *dest,
const void *src, std::size_t count) {
127 char *to{
reinterpret_cast<char *
>(dest)};
128 const char *from{
reinterpret_cast<const char *
>(src)};
140#if STD_MEMMOVE_USE_BUILTIN
141static inline RT_API_ATTRS
void memmove(
142 void *dest,
const void *src, std::size_t count) {
143 __builtin_memmove(dest, src, count);
145#elif STD_MEMMOVE_UNSUPPORTED
148static inline RT_API_ATTRS
void *memmove(
149 void *dest,
const void *src, std::size_t count) {
150 char *to{
reinterpret_cast<char *
>(dest)};
151 const char *from{
reinterpret_cast<const char *
>(src)};
156 if (to + count <= from || from + count <= to) {
157 memcpy(dest, src, count);
158 }
else if (to < from) {
175using MemmoveFct =
void *(*)(
void *,
const void *, std::size_t);
177#ifdef RT_DEVICE_COMPILATION
178[[maybe_unused]]
static RT_API_ATTRS
void *MemmoveWrapper(
179 void *dest,
const void *src, std::size_t count) {
180 return Fortran::runtime::memmove(dest, src, count);
184#if STD_STRLEN_USE_BUILTIN
185static inline RT_API_ATTRS std::size_t strlen(
const char *str) {
186 return __builtin_strlen(str);
188#elif STD_STRLEN_UNSUPPORTED
191static inline RT_API_ATTRS std::size_t strlen(
const char *str) {
196 const char *end = str;
197 for (; *end !=
'\0'; ++end)
205#if STD_MEMCMP_UNSUPPORTED
208static inline RT_API_ATTRS
int memcmp(
209 const void *RESTRICT lhs,
const void *RESTRICT rhs, std::size_t count) {
210 auto m1{
reinterpret_cast<const unsigned char *
>(lhs)};
211 auto m2{
reinterpret_cast<const unsigned char *
>(rhs)};
212 for (; count--; ++m1, ++m2) {
213 int diff = *m1 - *m2;
224#if STD_REALLOC_UNSUPPORTED
225static inline RT_API_ATTRS
void *realloc(
void *ptr, std::size_t newByteSize) {
235#if STD_MEMCHR_UNSUPPORTED
238static inline RT_API_ATTRS
const void *memchr(
239 const void *ptr,
int ch, std::size_t count) {
240 auto buf{
reinterpret_cast<const unsigned char *
>(ptr)};
241 auto c{
static_cast<unsigned char>(ch)};
242 for (; count--; ++buf) {
253#if STD_STRCPY_UNSUPPORTED
256static inline RT_API_ATTRS
char *strcpy(
char *dest,
const char *src) {
260 }
while (*src++ !=
'\0');
267#if STD_STRCMP_UNSUPPORTED
270static inline RT_API_ATTRS
int strcmp(
const char *lhs,
const char *rhs) {
271 while (*lhs !=
'\0' && *lhs == *rhs) {
275 return static_cast<unsigned char>(*lhs) -
static_cast<unsigned char>(*rhs);
281#if STD_TOUPPER_UNSUPPORTED
284static inline RT_API_ATTRS
int toupper(
int ch) {
285 if (ch >=
'a' && ch <=
'z') {
286 return ch -
'a' +
'A';