Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- include/flang/Runtime/freestanding-tools.h --------------*- C++ -*-===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef FORTRAN_RUNTIME_FREESTANDING_TOOLS_H_ |
10 | #define FORTRAN_RUNTIME_FREESTANDING_TOOLS_H_ |
11 | |
12 | #include "flang/Common/api-attrs.h" |
13 | #include "flang/Runtime/c-or-cpp.h" |
14 | #include <algorithm> |
15 | #include <cctype> |
16 | #include <cstring> |
17 | |
18 | // The file defines a set of utilities/classes that might be |
19 | // used to get reduce the dependency on external libraries (e.g. libstdc++). |
20 | |
21 | #if !defined(STD_FILL_N_UNSUPPORTED) && \ |
22 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
23 | #define STD_FILL_N_UNSUPPORTED 1 |
24 | #endif |
25 | |
26 | #if !defined(STD_MEMMOVE_UNSUPPORTED) && \ |
27 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
28 | #define STD_MEMMOVE_UNSUPPORTED 1 |
29 | #endif |
30 | |
31 | #if !defined(STD_STRLEN_UNSUPPORTED) && \ |
32 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
33 | #define STD_STRLEN_UNSUPPORTED 1 |
34 | #endif |
35 | |
36 | #if !defined(STD_MEMCMP_UNSUPPORTED) && \ |
37 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
38 | #define STD_MEMCMP_UNSUPPORTED 1 |
39 | #endif |
40 | |
41 | #if !defined(STD_REALLOC_UNSUPPORTED) && \ |
42 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
43 | #define STD_REALLOC_UNSUPPORTED 1 |
44 | #endif |
45 | |
46 | #if !defined(STD_MEMCHR_UNSUPPORTED) && \ |
47 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
48 | #define STD_MEMCHR_UNSUPPORTED 1 |
49 | #endif |
50 | |
51 | #if !defined(STD_STRCPY_UNSUPPORTED) && \ |
52 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
53 | #define STD_STRCPY_UNSUPPORTED 1 |
54 | #endif |
55 | |
56 | #if !defined(STD_STRCMP_UNSUPPORTED) && \ |
57 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
58 | #define STD_STRCMP_UNSUPPORTED 1 |
59 | #endif |
60 | |
61 | #if !defined(STD_TOUPPER_UNSUPPORTED) && \ |
62 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
63 | #define STD_TOUPPER_UNSUPPORTED 1 |
64 | #endif |
65 | |
66 | namespace Fortran::runtime { |
67 | |
68 | #if STD_FILL_N_UNSUPPORTED |
69 | // Provides alternative implementation for std::fill_n(), if |
70 | // it is not supported. |
71 | template <typename A, typename B> |
72 | static inline RT_API_ATTRS std::enable_if_t<std::is_convertible_v<B, A>, void> |
73 | fill_n(A *start, std::size_t count, const B &value) { |
74 | for (std::size_t j{0}; j < count; ++j) { |
75 | start[j] = value; |
76 | } |
77 | } |
78 | #else // !STD_FILL_N_UNSUPPORTED |
79 | using std::fill_n; |
80 | #endif // !STD_FILL_N_UNSUPPORTED |
81 | |
82 | #if STD_MEMMOVE_UNSUPPORTED |
83 | // Provides alternative implementation for std::memmove(), if |
84 | // it is not supported. |
85 | static inline RT_API_ATTRS void memmove( |
86 | void *dest, const void *src, std::size_t count) { |
87 | char *to{reinterpret_cast<char *>(dest)}; |
88 | const char *from{reinterpret_cast<const char *>(src)}; |
89 | |
90 | if (to == from) { |
91 | return; |
92 | } |
93 | if (to + count <= from || from + count <= to) { |
94 | std::memcpy(dest, src, count); |
95 | } else if (to < from) { |
96 | while (count--) { |
97 | *to++ = *from++; |
98 | } |
99 | } else { |
100 | to += count; |
101 | from += count; |
102 | while (count--) { |
103 | *--to = *--from; |
104 | } |
105 | } |
106 | } |
107 | #else // !STD_MEMMOVE_UNSUPPORTED |
108 | using std::memmove; |
109 | #endif // !STD_MEMMOVE_UNSUPPORTED |
110 | |
111 | #if STD_STRLEN_UNSUPPORTED |
112 | // Provides alternative implementation for std::strlen(), if |
113 | // it is not supported. |
114 | static inline RT_API_ATTRS std::size_t strlen(const char *str) { |
115 | if (!str) { |
116 | // Return 0 for nullptr. |
117 | return 0; |
118 | } |
119 | const char *end = str; |
120 | for (; *end != '\0'; ++end) |
121 | ; |
122 | return end - str; |
123 | } |
124 | #else // !STD_STRLEN_UNSUPPORTED |
125 | using std::strlen; |
126 | #endif // !STD_STRLEN_UNSUPPORTED |
127 | |
128 | #if STD_MEMCMP_UNSUPPORTED |
129 | // Provides alternative implementation for std::memcmp(), if |
130 | // it is not supported. |
131 | static inline RT_API_ATTRS int memcmp( |
132 | const void *RESTRICT lhs, const void *RESTRICT rhs, std::size_t count) { |
133 | auto m1{reinterpret_cast<const unsigned char *>(lhs)}; |
134 | auto m2{reinterpret_cast<const unsigned char *>(rhs)}; |
135 | for (; count--; ++m1, ++m2) { |
136 | int diff = *m1 - *m2; |
137 | if (diff != 0) { |
138 | return diff; |
139 | } |
140 | } |
141 | return 0; |
142 | } |
143 | #else // !STD_MEMCMP_UNSUPPORTED |
144 | using std::memcmp; |
145 | #endif // !STD_MEMCMP_UNSUPPORTED |
146 | |
147 | #if STD_REALLOC_UNSUPPORTED |
148 | static inline RT_API_ATTRS void *realloc(void *ptr, std::size_t newByteSize) { |
149 | // Return nullptr and let the callers assert that. |
150 | // TODO: we can provide a straightforward implementation |
151 | // via malloc/memcpy/free. |
152 | return nullptr; |
153 | } |
154 | #else // !STD_REALLOC_UNSUPPORTED |
155 | using std::realloc; |
156 | #endif // !STD_REALLOC_UNSUPPORTED |
157 | |
158 | #if STD_MEMCHR_UNSUPPORTED |
159 | // Provides alternative implementation for std::memchr(), if |
160 | // it is not supported. |
161 | static inline RT_API_ATTRS const void *memchr( |
162 | const void *ptr, int ch, std::size_t count) { |
163 | auto buf{reinterpret_cast<const unsigned char *>(ptr)}; |
164 | auto c{static_cast<unsigned char>(ch)}; |
165 | for (; count--; ++buf) { |
166 | if (*buf == c) { |
167 | return buf; |
168 | } |
169 | } |
170 | return nullptr; |
171 | } |
172 | #else // !STD_MEMCMP_UNSUPPORTED |
173 | using std::memchr; |
174 | #endif // !STD_MEMCMP_UNSUPPORTED |
175 | |
176 | #if STD_STRCPY_UNSUPPORTED |
177 | // Provides alternative implementation for std::strcpy(), if |
178 | // it is not supported. |
179 | static inline RT_API_ATTRS char *strcpy(char *dest, const char *src) { |
180 | char *result{dest}; |
181 | do { |
182 | *dest++ = *src; |
183 | } while (*src++ != '\0'); |
184 | return result; |
185 | } |
186 | #else // !STD_STRCPY_UNSUPPORTED |
187 | using std::strcpy; |
188 | #endif // !STD_STRCPY_UNSUPPORTED |
189 | |
190 | #if STD_STRCMP_UNSUPPORTED |
191 | // Provides alternative implementation for std::strcmp(), if |
192 | // it is not supported. |
193 | static inline RT_API_ATTRS int strcmp(const char *lhs, const char *rhs) { |
194 | while (*lhs != '\0' && *lhs == *rhs) { |
195 | ++lhs; |
196 | ++rhs; |
197 | } |
198 | return static_cast<unsigned char>(*lhs) - static_cast<unsigned char>(*rhs); |
199 | } |
200 | #else // !STD_STRCMP_UNSUPPORTED |
201 | using std::strcmp; |
202 | #endif // !STD_STRCMP_UNSUPPORTED |
203 | |
204 | #if STD_TOUPPER_UNSUPPORTED |
205 | // Provides alternative implementation for std::toupper(), if |
206 | // it is not supported. |
207 | static inline RT_API_ATTRS int toupper(int ch) { |
208 | if (ch >= 'a' && ch <= 'z') { |
209 | return ch - 'a' + 'A'; |
210 | } |
211 | return ch; |
212 | } |
213 | #else // !STD_TOUPPER_UNSUPPORTED |
214 | using std::toupper; |
215 | #endif // !STD_TOUPPER_UNSUPPORTED |
216 | |
217 | } // namespace Fortran::runtime |
218 | #endif // FORTRAN_RUNTIME_FREESTANDING_TOOLS_H_ |
219 |
Warning: This file is not a C or C++ file. It does not have highlighting.