forked from pytorch/executorch
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompiler.h
More file actions
286 lines (243 loc) · 8.3 KB
/
compiler.h
File metadata and controls
286 lines (243 loc) · 8.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @file
* Compiler utility macros.
*/
#pragma once
/*
* Compiler support checks. Follows the logic used by pytorch/c10/util/C++17.h
* but may support older versions.
*/
// https://gcc.gnu.org/projects/cxx-status.html#cxx17
#if !defined(__clang__) && !defined(_MSC_VER) && defined(__GNUC__) && \
__GNUC__ < 7
#error \
"You're trying to build ExecuTorch with a too old version of GCC. We need GCC 7 or later."
#endif
// https://clang.llvm.org/cxx_status.html#cxx17
#if defined(__clang__) && __clang_major__ < 5
#error \
"You're trying to build ExecuTorch with a too old version of Clang. We need Clang 5 or later."
#endif
#if (defined(_MSC_VER) && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)) || \
(!defined(_MSC_VER) && __cplusplus < 201703L)
#error "You need C++17 to compile ExecuTorch"
#endif
#if defined(_MSC_VER) && (defined(min) || defined(max))
#error \
"Macro clash with min and max -- define NOMINMAX when compiling your program on Windows"
#endif
/*
* Define annotations aliasing C++ declaration attributes.
* See all C++ declaration attributes here:
* https://en.cppreference.com/w/cpp/language/attributes
*
* Note that ExecuTorch supports a lower C++ standard version than all standard
* attributes. Therefore, some annotations are defined using their Clang/GNU
* counterparts.
*
* GNU attribute definitions:
* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
*/
#define ET_NORETURN [[noreturn]]
#define ET_NOINLINE __attribute__((noinline))
#define ET_INLINE __attribute__((always_inline)) inline
#define ET_INLINE_ATTRIBUTE __attribute__((always_inline))
#if defined(__GNUC__)
#define ET_UNREACHABLE() __builtin_unreachable()
#elif defined(_MSC_VER)
#define ET_UNREACHABLE() __assume(0)
#else // defined(__GNUC__)
#define ET_UNREACHABLE() \
while (1) \
;
#endif // defined(__GNUC__)
#define ET_DEPRECATED [[deprecated]]
#define ET_EXPERIMENTAL \
[[deprecated("This API is experimental and may change without notice.")]]
#define ET_FALLTHROUGH [[fallthrough]]
#define ET_NODISCARD [[nodiscard]]
#define ET_UNUSED [[maybe_unused]]
// UNLIKELY Macro
// example
// if ET_UNLIKELY(a > 10 && b < 5) {
// do something
// }
#if (__cplusplus) >= 202002L
#define ET_LIKELY(expr) (expr) [[likely]]
#define ET_UNLIKELY(expr) (expr) [[unlikely]]
#else
#define ET_LIKELY(expr) (expr)
#define ET_UNLIKELY(expr) (expr)
#endif // (__cplusplus) >= 202002L
/// Define a C symbol with weak linkage.
#ifdef _MSC_VER
// There currently doesn't seem to be a great way to do this in Windows and
// given that weak linkage is not really critical on Windows, we'll just leave
// it as a stub.
#define ET_WEAK
#else
#define ET_WEAK __attribute__((weak))
#endif
/**
* Annotation marking a function as printf-like, providing compiler support
* for format string argument checking.
*/
#ifdef _MSC_VER
#include <sal.h>
#define ET_PRINTFLIKE(_string_index, _va_index) _Printf_format_string_
#else
#define ET_PRINTFLIKE(_string_index, _va_index) \
__attribute__((format(printf, _string_index, _va_index)))
#endif
#ifndef __has_builtin
#define __has_builtin(x) (0)
#endif
#if __has_builtin(__builtin_strrchr)
/// Name of the source file without a directory string.
#define ET_SHORT_FILENAME (__builtin_strrchr("/" __FILE__, '/') + 1)
#else
#define ET_SHORT_FILENAME __FILE__
#endif
#if __has_builtin(__builtin_LINE)
/// Current line as an integer.
#define ET_LINE __builtin_LINE()
#else
#define ET_LINE __LINE__
#endif // __has_builtin(__builtin_LINE)
#if __has_builtin(__builtin_FUNCTION)
/// Name of the current function as a const char[].
#define ET_FUNCTION __builtin_FUNCTION()
#else
#define ET_FUNCTION __FUNCTION__
#endif // __has_builtin(__builtin_FUNCTION)
// As of G3 RJ-2024.3 toolchain, zu format specifier is not supported for Xtensa
#if defined(__XTENSA__)
#define ET_PRIsize_t "lu"
#else
#define ET_PRIsize_t "zu"
#endif
// Whether the compiler supports GNU statement expressions.
// https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
#ifndef ET_HAVE_GNU_STATEMENT_EXPRESSIONS
#if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__clang__)
#define ET_HAVE_GNU_STATEMENT_EXPRESSIONS 1
#else
#define ET_HAVE_GNU_STATEMENT_EXPRESSIONS 0
#endif
#endif // ifndef
// Define size_t and ssize_t.
#ifndef _MSC_VER
#include <sys/types.h>
#else
#include <stddef.h>
using ssize_t = ptrdiff_t;
#endif
/**
* Platform-specific aligned memory allocation and deallocation.
*
* Usage:
* void* ptr = ET_ALIGNED_ALLOC(alignment, size);
* // use ptr...
* ET_ALIGNED_FREE(ptr);
*
* Note: alignment must be a power of 2 and size must be an integral multiple of
* alignment.
*/
#if defined(_MSC_VER)
#include <malloc.h>
#define ET_ALIGNED_ALLOC(alignment, size) \
_aligned_malloc(((size + alignment - 1) & ~(alignment - 1)), (alignment))
#define ET_ALIGNED_FREE(ptr) _aligned_free(ptr)
#elif defined(__APPLE__)
#include <stdlib.h> // For posix_memalign and free
inline void* et_apple_aligned_alloc(size_t alignment, size_t size) {
void* ptr = nullptr;
// The address of the allocated memory must be a multiple of sizeof(void*).
if (alignment < sizeof(void*)) {
alignment = sizeof(void*);
}
if (posix_memalign(
&ptr, alignment, (size + alignment - 1) & ~(alignment - 1)) != 0) {
return nullptr;
}
return ptr;
}
#define ET_ALIGNED_ALLOC(alignment, size) \
et_apple_aligned_alloc((alignment), (size))
#define ET_ALIGNED_FREE(ptr) free(ptr)
#elif __has_builtin(__builtin_aligned_alloc) || defined(_ISOC11_SOURCE)
// Linux and posix systems that support aligned_alloc and are >= C++17.
#include <cstdlib>
#define ET_ALIGNED_ALLOC(alignment, size) \
::aligned_alloc(alignment, (size + alignment - 1) & ~(alignment - 1))
#define ET_ALIGNED_FREE(ptr) free(ptr)
#else
// If the platform doesn't support aligned_alloc, fallback to malloc.
#include <stdint.h>
#include <cstdlib>
inline void* et_aligned_malloc(size_t alignment, size_t size) {
// Place to store the offset to the original pointer.
size_t offset_size = sizeof(uint16_t);
// Malloc extra space for offset + alignment.
size_t alloc_size = size + offset_size + alignment - 1;
void* ptr = std::malloc(alloc_size);
if (ptr == nullptr) {
// Malloc failed.
return nullptr;
}
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
// Align the address past addr + offset_size bytes.
// This provides space to store the offset before the aligned pointer.
addr = addr + offset_size;
uintptr_t aligned_ptr = (addr + alignment - 1) & ~(alignment - 1);
// Check that alignment didn't overflow the buffer.
if (reinterpret_cast<uintptr_t>(aligned_ptr) + size >
reinterpret_cast<uintptr_t>(ptr) + alloc_size) {
std::free(ptr);
return nullptr;
}
// Store the offset to the original pointer.
// Used to free the original allocated buffer.
*(reinterpret_cast<uint16_t*>(aligned_ptr) - 1) =
(uint16_t)(reinterpret_cast<uintptr_t>(aligned_ptr) -
reinterpret_cast<uintptr_t>(ptr));
return reinterpret_cast<uint16_t*>(aligned_ptr);
}
inline void et_aligned_free(void* ptr) {
if (ptr == nullptr) {
return;
}
// Get the original pointer using the offset.
uint16_t* original_ptr = reinterpret_cast<uint16_t*>(
reinterpret_cast<uintptr_t>(ptr) -
*(reinterpret_cast<uint16_t*>(ptr) - 1));
std::free(original_ptr);
}
#define ET_ALIGNED_ALLOC(alignment, size) et_aligned_malloc((alignment), (size))
#define ET_ALIGNED_FREE(ptr) et_aligned_free(ptr)
#endif
// DEPRECATED: Use the non-underscore-prefixed versions instead.
// TODO(T199005537): Remove these once all users have stopped using them.
#define __ET_DEPRECATED ET_DEPRECATED
#define __ET_FALLTHROUGH ET_FALLTHROUGH
#define __ET_FUNCTION ET_FUNCTION
#define __ET_HAVE_GNU_STATEMENT_EXPRESSIONS ET_HAVE_GNU_STATEMENT_EXPRESSIONS
#define __ET_INLINE ET_INLINE
#define __ET_LIKELY ET_LIKELY
#define __ET_LINE ET_LINE
#define __ET_NODISCARD ET_NODISCARD
#define __ET_NOINLINE ET_NOINLINE
#define __ET_NORETURN ET_NORETURN
#define __ET_PRINTFLIKE ET_PRINTFLIKE
#define __ET_SHORT_FILENAME ET_SHORT_FILENAME
#define __ET_UNLIKELY ET_UNLIKELY
#define __ET_UNREACHABLE ET_UNREACHABLE
#define __ET_UNUSED ET_UNUSED
#define __ET_WEAK ET_WEAK