HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
platform.h
Go to the documentation of this file.
1 // Copyright 2008-present Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
4 
5 
6 /////////////////////////////////////////////////////////////////////////
7 // \file
8 // platform.h is where we put all the platform-specific macros.
9 // Things like:
10 //
11 // * Detecting which compiler is being used.
12 // * Detecting which C++ standard is being used and what features are
13 // available.
14 // * Various helpers that need to be defined differently per compiler,
15 // language version, OS, etc.
16 /////////////////////////////////////////////////////////////////////////
17 
18 // clang-format off
19 
20 #pragma once
21 
22 #include <cassert>
23 #include <cstdlib>
24 #include <type_traits>
25 #include <utility> // std::forward
26 
27 // Make sure all platforms have the explicit sized integer types
28 #ifndef __STDC_LIMIT_MACROS
29 # define __STDC_LIMIT_MACROS /* needed for some defs in stdint.h */
30 #endif
31 #include <cstdint>
32 
33 #if defined(__FreeBSD__)
34 # include <sys/param.h>
35 #endif
36 
37 #ifdef __MINGW32__
38 # include <malloc.h> // for alloca
39 #endif
40 
41 #if defined(_WIN32)
42 # ifndef WIN32_LEAN_AND_MEAN
43 # define WIN32_LEAN_AND_MEAN
44 # endif
45 # ifndef VC_EXTRALEAN
46 # define VC_EXTRALEAN
47 # endif
48 # ifndef NOMINMAX
49 # define NOMINMAX
50 # endif
51 # include <windows.h>
52 #endif
53 
54 #ifdef _MSC_VER
55 # include <intrin.h>
56 #endif
57 
59 #include <OpenImageIO/export.h>
60 
61 // Detect which C++ standard we're using, and handy macros.
62 // See https://en.cppreference.com/w/cpp/compiler_support
63 //
64 // OIIO_CPLUSPLUS_VERSION : which C++ standard is compiling (11, 14, ...)
65 // OIIO_CONSTEXPR14 :
66 // OIIO_CONSTEXPR17 :
67 // OIIO_CONSTEXPR20 : constexpr for C++ >= the designated version, otherwise
68 // nothing (this is useful for things that can only be
69 // constexpr for particular versions or greater).
70 // OIIO_INLINE_CONSTEXPR : inline constexpr variables, added in C++17. For
71 // older C++, just constexpr.
72 //
73 // Note: oiioversion.h defines OIIO_BUILD_CPP11, OIIO_BUILD_CPP14,
74 // OIIO_BUILD_CPP17, or OIIO_BUILD_CPP20 to be 1 if OIIO itself was *built*
75 // using C++11, C++14, C++17, or C++20, respectively. In contrast,
76 // OIIO_CPLUSPLUS_VERSION defined below will be set to the right number for
77 // the C++ standard being compiled RIGHT NOW. These two things may be the
78 // same when compiling OIIO, but they may not be the same if another
79 // package is compiling against OIIO and using these headers (OIIO may be
80 // C++11 but the client package may be newer, or vice versa -- use these two
81 // symbols to differentiate these cases, when important).
82 #if (__cplusplus >= 202001L)
83 # define OIIO_CPLUSPLUS_VERSION 20
84 # define OIIO_CONSTEXPR14 constexpr
85 # define OIIO_CONSTEXPR17 constexpr
86 # define OIIO_CONSTEXPR20 constexpr
87 # define OIIO_INLINE_CONSTEXPR inline constexpr
88 #elif (__cplusplus >= 201703L)
89 # define OIIO_CPLUSPLUS_VERSION 17
90 # define OIIO_CONSTEXPR14 constexpr
91 # define OIIO_CONSTEXPR17 constexpr
92 # define OIIO_CONSTEXPR20 /* not constexpr before C++20 */
93 # define OIIO_INLINE_CONSTEXPR inline constexpr
94 #elif (__cplusplus >= 201402L) || (defined(_MSC_VER) && _MSC_VER >= 1914)
95 # define OIIO_CPLUSPLUS_VERSION 14
96 # define OIIO_CONSTEXPR14 constexpr
97 # define OIIO_CONSTEXPR17 /* not constexpr before C++17 */
98 # define OIIO_CONSTEXPR20 /* not constexpr before C++20 */
99 # define OIIO_INLINE_CONSTEXPR constexpr
100 #elif (__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1900)
101 # define OIIO_CPLUSPLUS_VERSION 11
102 # define OIIO_CONSTEXPR14 /* not constexpr before C++14 */
103 # define OIIO_CONSTEXPR17 /* not constexpr before C++17 */
104 # define OIIO_CONSTEXPR20 /* not constexpr before C++20 */
105 # define OIIO_INLINE_CONSTEXPR constexpr
106 #else
107 # error "This version of OIIO is meant to work only with C++11 and above"
108 #endif
109 
110 // DEPRECATED(1.8): use C++11 constexpr
111 #define OIIO_CONSTEXPR constexpr
112 #define OIIO_CONSTEXPR_OR_CONST constexpr
113 
114 // DEPRECATED(1.8): use C++11 noexcept
115 #define OIIO_NOEXCEPT noexcept
116 
117 
118 // In C++20 (and some compilers before that), __has_cpp_attribute can
119 // test for understand of [[attr]] tests.
120 #ifndef __has_cpp_attribute
121 # define __has_cpp_attribute(x) 0
122 #endif
123 
124 // On gcc & clang, __has_attribute can test for __attribute__((attr))
125 #ifndef __has_attribute
126 # define __has_attribute(x) 0
127 #endif
128 
129 // In C++17 (and some compilers before that), __has_include("blah.h") or
130 // __has_include(<blah.h>) can test for presence of an include file.
131 #ifndef __has_include
132 # define __has_include(x) 0
133 #endif
134 
135 
136 
137 // Detect which compiler and version we're using
138 
139 // Notes:
140 // __GNUC__ is defined for gcc and all clang varieties
141 // __clang__ is defined for all clang varieties (generic and Apple)
142 // __apple_build_version__ is only defined for Apple clang
143 // __INTEL_COMPILER is defined only for icc
144 // _MSC_VER is defined for MSVS compiler (not gcc/clang/icc even on Windows)
145 // _WIN32 is defined on Windows regardless of compiler
146 // __CUDACC__ is defined for nvcc and clang during Cuda compilation.
147 
148 
149 // Define OIIO_GNUC_VERSION to hold an encoded gcc version (e.g. 40802 for
150 // 4.8.2), or 0 if not a GCC release. N.B.: This will be 0 for clang.
151 #if defined(__GNUC__) && !defined(__clang__)
152 # define OIIO_GNUC_VERSION (10000*__GNUC__ + 100*__GNUC_MINOR__ + __GNUC_PATCHLEVEL__)
153 #else
154 # define OIIO_GNUC_VERSION 0
155 #endif
156 
157 // Define OIIO_CLANG_VERSION to hold an encoded generic Clang version (e.g.
158 // 30402 for clang 3.4.2), or 0 if not a generic Clang release.
159 // N.B. This will be 0 for the clang Apple distributes (which has different
160 // version numbers entirely).
161 #if defined(__clang__) && !defined(__apple_build_version__)
162 # define OIIO_CLANG_VERSION (10000*__clang_major__ + 100*__clang_minor__ + __clang_patchlevel__)
163 #else
164 # define OIIO_CLANG_VERSION 0
165 #endif
166 
167 // Define OIIO_APPLE_CLANG_VERSION to hold an encoded Apple Clang version
168 // (e.g. 70002 for clang 7.0.2), or 0 if not an Apple Clang release.
169 #if defined(__clang__) && defined(__apple_build_version__)
170 # define OIIO_APPLE_CLANG_VERSION (10000*__clang_major__ + 100*__clang_minor__ + __clang_patchlevel__)
171 #else
172 # define OIIO_APPLE_CLANG_VERSION 0
173 #endif
174 
175 // Define OIIO_INTEL_COMPILER_VERSION to hold an encoded Intel compiler
176 // version (e.g. 1900), or 0 if not an Intel compiler.
177 #if defined(__INTEL_COMPILER)
178 # define OIIO_INTEL_COMPILER_VERSION __INTEL_COMPILER
179 #else
180 # define OIIO_INTEL_COMPILER_VERSION 0
181 #endif
182 
183 // Intel's compiler on OSX may still define __clang__ and we have need to
184 // know when using a true clang compiler.
185 #if !defined(__INTEL_COMPILER) && defined(__clang__)
186 # define OIIO_NON_INTEL_CLANG __clang__
187 #else
188 # define OIIO_NON_INTEL_CLANG 0
189 #endif
190 
191 // Tests for MSVS versions, always 0 if not MSVS at all.
192 #if defined(_MSC_VER)
193 # if _MSC_VER < 1900
194 # error "This version of OIIO is meant to work only with Visual Studio 2015 or later"
195 # endif
196 # define OIIO_MSVS_AT_LEAST_2013 (_MSC_VER >= 1800)
197 # define OIIO_MSVS_BEFORE_2013 (_MSC_VER < 1800)
198 # define OIIO_MSVS_AT_LEAST_2015 (_MSC_VER >= 1900)
199 # define OIIO_MSVS_BEFORE_2015 (_MSC_VER < 1900)
200 # define OIIO_MSVS_AT_LEAST_2017 (_MSC_VER >= 1910)
201 # define OIIO_MSVS_BEFORE_2017 (_MSC_VER < 1910)
202 #else
203 # define OIIO_MSVS_AT_LEAST_2013 0
204 # define OIIO_MSVS_BEFORE_2013 0
205 # define OIIO_MSVS_AT_LEAST_2015 0
206 # define OIIO_MSVS_BEFORE_2015 0
207 # define OIIO_MSVS_AT_LEAST_2017 0
208 # define OIIO_MSVS_BEFORE_2017 0
209 #endif
210 
211 
212 // Pragma control
213 //
214 // OIIO_PRAGMA(x) make a pragma for *unquoted* x
215 // OIIO_PRAGMA_WARNING_PUSH/POP -- push/pop warning state
216 // OIIO_VISIBILITY_PUSH/POP -- push/pop symbol visibility state
217 // OIIO_GCC_PRAGMA(x) -- pragma on gcc/clang/icc only
218 // OIIO_CLANG_PRAGMA(x) -- pragma on clang only (not gcc or icc)
219 // OIIO_MSVS_PRAGMA(x) -- pragma on MSVS only
220 
221 // Generic pragma definition
222 #if defined(_MSC_VER)
223  // Of course MS does it in a quirky way
224  #define OIIO_PRAGMA(UnQuotedPragma) __pragma(UnQuotedPragma)
225 #else
226  // All other compilers seem to support C99 _Pragma
227  #define OIIO_PRAGMA(UnQuotedPragma) _Pragma(#UnQuotedPragma)
228 #endif
229 
230 #if defined(__GNUC__) /* gcc, clang, icc */
231 # define OIIO_PRAGMA_WARNING_PUSH OIIO_PRAGMA(GCC diagnostic push)
232 # define OIIO_PRAGMA_WARNING_POP OIIO_PRAGMA(GCC diagnostic pop)
233 # define OIIO_PRAGMA_VISIBILITY_PUSH OIIO_PRAGMA(GCC visibility push(default))
234 # define OIIO_PRAGMA_VISIBILITY_POP OIIO_PRAGMA(GCC visibility pop)
235 # define OIIO_GCC_PRAGMA(UnQuotedPragma) OIIO_PRAGMA(UnQuotedPragma)
236 # if defined(__clang__)
237 # define OIIO_CLANG_PRAGMA(UnQuotedPragma) OIIO_PRAGMA(UnQuotedPragma)
238 # define OIIO_GCC_ONLY_PRAGMA(UnQuotedPragma)
239 # else
240 # define OIIO_CLANG_PRAGMA(UnQuotedPragma)
241 # define OIIO_GCC_ONLY_PRAGMA(UnQuotedPragma) OIIO_PRAGMA(UnQuotedPragma)
242 # endif
243 # define OIIO_MSVS_PRAGMA(UnQuotedPragma)
244 #elif defined(_MSC_VER)
245 # define OIIO_PRAGMA_WARNING_PUSH __pragma(warning(push))
246 # define OIIO_PRAGMA_WARNING_POP __pragma(warning(pop))
247 # define OIIO_PRAGMA_VISIBILITY_PUSH /* N/A on MSVS */
248 # define OIIO_PRAGMA_VISIBILITY_POP /* N/A on MSVS */
249 # define OIIO_GCC_PRAGMA(UnQuotedPragma)
250 # define OIIO_GCC_ONLY_PRAGMA(UnQuotedPragma)
251 # define OIIO_CLANG_PRAGMA(UnQuotedPragma)
252 # define OIIO_MSVS_PRAGMA(UnQuotedPragma) OIIO_PRAGMA(UnQuotedPragma)
253 #else
254 # define OIIO_PRAGMA_WARNING_PUSH
255 # define OIIO_PRAGMA_WARNING_POP
256 # define OIIO_PRAGMA_VISIBILITY_PUSH
257 # define OIIO_PRAGMA_VISIBILITY_POP
258 # define OIIO_GCC_PRAGMA(UnQuotedPragma)
259 # define OIIO_GCC_ONLY_PRAGMA(UnQuotedPragma)
260 # define OIIO_CLANG_PRAGMA(UnQuotedPragma)
261 # define OIIO_MSVS_PRAGMA(UnQuotedPragma)
262 #endif
263 
264 
265 
266 /// OIIO_ALLOCA is used to allocate smallish amount of memory on the stack,
267 /// equivalent of C99 type var_name[size].
268 ///
269 /// NOTE: in a debug build, this will assert for allocations >= 1MB, which
270 /// is much too big. Hopefully this will keep us from abusing alloca and
271 /// having stack overflows. The rule of thumb is that it's ok to use alloca
272 /// for small things of bounded size (like, one float per channel), but
273 /// not for anything that could be arbitrarily big (like a full scanline or
274 /// image, because sooner or later somebody will give you an image big
275 /// enough to cause trouble). Consider using the OIIO_ALLOCATE_STACK_OR_HEAP
276 /// idiom rather than a direct OIIO_ALLOCA if you aren't sure the item will
277 /// be small.
278 #if defined(__GNUC__)
279 # define OIIO_ALLOCA(type, size) (assert(size < (1<<20)), (size) != 0 ? ((type*)__builtin_alloca((size) * sizeof(type))) : nullptr)
280 #else
281 # define OIIO_ALLOCA(type, size) (assert(size < (1<<20)), (size) != 0 ? ((type*)alloca((size) * sizeof(type))) : nullptr)
282 #endif
283 
284 /// Deprecated (for namespace pollution reasons)
285 #define ALLOCA(type, size) OIIO_ALLOCA(type, size)
286 
287 
288 /// Try to allocate T* var to point to T[size] elements of temporary storage
289 /// that will automatically free when the local scope is exited. Allocate
290 /// the space on the stack with alloca if it's small, but if it's big (> 64
291 /// KB), allocate on the heap with a new[], stored as a std::unique_ptr. In
292 /// both cases, the memory will be freed automatically upon exit of scope.
293 /// That threshold is big enough for one scanline of a 4096 x 4 channel x
294 /// float image, or one 64x64 tile of a 4xfloat image.
295 #define OIIO_ALLOCATE_STACK_OR_HEAP(var, T, size) \
296  size_t var##___size = size_t(size); \
297  std::unique_ptr<T[]> var##___heap; \
298  if (var##___size * sizeof(T) <= (1 << 16)) { \
299  var = OIIO_ALLOCA(T, var##___size); \
300  } else { \
301  var##___heap.reset(new T[var##___size]); \
302  var = var##___heap.get(); \
303  }
304 
305 
306 // Define a macro that can be used for memory alignment.
307 // This macro is mostly obsolete and C++11 alignas() should be preferred
308 // for new code.
309 #if defined(__GNUC__) || __has_attribute(aligned)
310 # define OIIO_ALIGN(size) __attribute__((aligned(size)))
311 #elif defined(_MSC_VER)
312 # define OIIO_ALIGN(size) __declspec(align(size))
313 #elif defined(__INTEL_COMPILER)
314 # define OIIO_ALIGN(size) __declspec(align((size)))
315 #else
316 # define OIIO_ALIGN(size) alignas(size)
317 #endif
318 
319 // Cache line size is 64 on all modern x86 CPUs. If this changes or we
320 // anticipate ports to other architectures, we'll need to change this.
321 #define OIIO_CACHE_LINE_SIZE 64
322 
323 // Align the next declaration to be on its own cache line
324 #define OIIO_CACHE_ALIGN OIIO_ALIGN(OIIO_CACHE_LINE_SIZE)
325 
326 
327 
328 // gcc defines a special intrinsic to use in conditionals that can speed
329 // up extremely performance-critical spots if the conditional usually
330 // (or rarely) is true. You use it by replacing
331 // if (x) ...
332 // with
333 // if (OIIO_LIKELY(x)) ... // if you think x will usually be true
334 // or
335 // if (OIIO_UNLIKELY(x)) ... // if you think x will rarely be true
336 // Caveat: Programmers are notoriously bad at guessing this, so it
337 // should be used only with thorough benchmarking.
338 #if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)
339 # define OIIO_LIKELY(x) (__builtin_expect(bool(x), true))
340 # define OIIO_UNLIKELY(x) (__builtin_expect(bool(x), false))
341 #else
342 # define OIIO_LIKELY(x) (x)
343 # define OIIO_UNLIKELY(x) (x)
344 #endif
345 
346 
347 // OIIO_FORCELINE is a function attribute that attempts to make the function
348 // always inline. On many compilers regular 'inline' is only advisory. Put
349 // this attribute before the function return type, just like you would use
350 // 'inline'.
351 #if defined(__CUDACC__)
352 # define OIIO_FORCEINLINE __inline__
353 #elif defined(__GNUC__) || defined(__clang__) || __has_attribute(always_inline)
354 # define OIIO_FORCEINLINE inline __attribute__((always_inline))
355 #elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
356 # define OIIO_FORCEINLINE __forceinline
357 #else
358 # define OIIO_FORCEINLINE inline
359 #endif
360 
361 // OIIO_PURE_FUNC is a function attribute that assures the compiler that the
362 // function does not write to any non-local memory other than its return
363 // value and has no side effects. This can ebable additional compiler
364 // optimizations by knowing that calling the function cannot possibly alter
365 // any other memory. This declaration goes after the function declaration:
366 // int blah (int arg) OIIO_PURE_FUNC;
367 #if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) || __has_attribute(pure)
368 # define OIIO_PURE_FUNC __attribute__((pure))
369 #elif defined(_MSC_VER)
370 # define OIIO_PURE_FUNC /* seems not supported by MSVS */
371 #else
372 # define OIIO_PURE_FUNC
373 #endif
374 
375 // OIIO_CONST_FUNC is a function attribute that assures the compiler that
376 // the function does not examine (read) any values except for its arguments,
377 // does not write any non-local memory other than its return value, and has
378 // no side effects. This is even more strict than 'pure', and allows even
379 // more optimizations (such as eliminating multiple calls to the function
380 // that have the exact same argument values).
381 #if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) || __has_attribute(const)
382 # define OIIO_CONST_FUNC __attribute__((const))
383 #elif defined(_MSC_VER)
384 # define OIIO_CONST_FUNC /* seems not supported by MSVS */
385 #else
386 # define OIIO_CONST_FUNC
387 #endif
388 
389 // OIIO_MAYBE_UNUSED is a function or variable attribute that assures the
390 // compiler that it's fine for the item to appear to be unused.
391 #if OIIO_CPLUSPLUS_VERSION >= 17 || __has_cpp_attribute(maybe_unused)
392 # define OIIO_MAYBE_UNUSED [[maybe_unused]]
393 #elif defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) || __has_attribute(unused)
394 # define OIIO_MAYBE_UNUSED __attribute__((unused))
395 #else
396 # define OIIO_MAYBE_UNUSED
397 #endif
398 
399 // DEPRECATED(1.9) name:
400 #define OIIO_UNUSED_OK OIIO_MAYBE_UNUSED
401 
402 // OIIO_RESTRICT is a parameter attribute that indicates a promise that the
403 // parameter definitely will not alias any other parameters in such a way
404 // that creates a data dependency. Use with caution!
405 #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) || defined(__INTEL_COMPILER)
406 # define OIIO_RESTRICT __restrict
407 #else
408 # define OIIO_RESTRICT
409 #endif
410 
411 
412 // OIIO_DEPRECATED before a function declaration marks it as deprecated in
413 // a way that will generate compile warnings if it is called.
414 #if OIIO_CPLUSPLUS_VERSION >= 14 || __has_cpp_attribute(deprecated)
415 # define OIIO_DEPRECATED(msg) [[deprecated(msg)]]
416 #elif defined(__GNUC__) || defined(__clang__) || __has_attribute(deprecated)
417 # define OIIO_DEPRECATED(msg) __attribute__((deprecated(msg)))
418 #elif defined(_MSC_VER)
419 # define OIIO_DEPRECATED(msg) __declspec(deprecated(msg))
420 #else
421 # define OIIO_DEPRECATED(msg)
422 #endif
423 
424 
425 // OIIO_FALLTHROUGH at the end of a `case` label's statements documents that
426 // the switch statement case is intentionally falling through to the code
427 // for the next case.
428 #if OIIO_CPLUSPLUS_VERSION >= 17 || __has_cpp_attribute(fallthrough)
429 # define OIIO_FALLTHROUGH [[fallthrough]]
430 #else
431 # define OIIO_FALLTHROUGH
432 #endif
433 
434 
435 // OIIO_NODISCARD following a function declaration documents that the
436 // function's return value should never be ignored.
437 #if OIIO_CPLUSPLUS_VERSION >= 17 || __has_cpp_attribute(nodiscard)
438 # define OIIO_NODISCARD [[nodiscard]]
439 #else
440 # define OIIO_NODISCARD
441 #endif
442 
443 
444 // OIIO_NO_SANITIZE_ADDRESS can be used to mark a function that you don't
445 // want address sanitizer to catch. Only use this if you know there are
446 // false positives that you can't easily get rid of.
447 // This should work for any clang >= 3.3 and gcc >= 4.8, which are
448 // guaranteed by our minimum requirements.
449 #if defined(__clang__) || defined(__GNUC__) || __has_attribute(no_sanitize_address)
450 # define OIIO_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
451 #else
452 # define OIIO_NO_SANITIZE_ADDRESS
453 #endif
454 
455 
456 // OIIO_RETURNS_NONNULL following a function declaration of a function
457 // indicates that the pointer returned by the function is guaranteed to
458 // never be nullptr.
459 #if defined(__clang__) || defined(__GNUC__) || __has_attribute(returns_nonnull)
460 # define OIIO_RETURNS_NONNULL __attribute__((returns_nonnull))
461 #else
462 # define OIIO_RETURNS_NONNULL
463 #endif
464 
465 
466 // OIIO_HOSTDEVICE is used before a function declaration to supply the
467 // function decorators needed when compiling for CUDA devices.
468 #ifdef __CUDACC__
469 # define OIIO_HOSTDEVICE __host__ __device__
470 #else
471 # define OIIO_HOSTDEVICE
472 #endif
473 
474 
475 
476 // OIIO_PRETTY_FUNCTION gives a text string of the current function
477 // declaration.
478 #if defined(__PRETTY_FUNCTION__)
479 # define OIIO_PRETTY_FUNCTION __PRETTY_FUNCTION__ /* gcc, clang */
480 #elif defined(__FUNCSIG__)
481 # define OIIO_PRETTY_FUNCTION __FUNCSIG__ /* MS gotta be different */
482 #else
483 # define OIIO_PRETTY_FUNCTION __FUNCTION__
484 #endif
485 
486 
487 
489 
490 /// Class for describing endianness. Test for endianness as
491 /// `if (endian::native == endian::little)` or
492 /// `if (endian::native == endian::big)`.
493 /// This uses the same semantics as C++20's std::endian.
494 enum class endian {
495 #ifdef _WIN32 /* All Windows platforms are little endian */
496  little = 0,
497  big = 1,
498  native = little
499 #else /* gcc, clang, icc all define these macros */
500  little = __ORDER_LITTLE_ENDIAN__,
501  big = __ORDER_BIG_ENDIAN__,
502  native = __BYTE_ORDER__
503 #endif
504 };
505 
506 
507 /// Return true if the architecture we are running on is little endian.
508 OIIO_FORCEINLINE constexpr bool
509 littleendian(void) noexcept
510 {
511  return endian::native == endian::little;
512 }
513 
514 
515 /// Return true if the architecture we are running on is big endian.
516 OIIO_FORCEINLINE constexpr bool
517 bigendian(void) noexcept
518 {
519  return endian::native == endian::big;
520 }
521 
522 
523 
524 /// Retrieve cpuid flags into 'info'.
525 inline void cpuid (int info[4], int infoType, int extra)
526 {
527  // Implementation cribbed from Halide (http://halide-lang.org), which
528  // cribbed it from ISPC (https://github.com/ispc/ispc).
529 #if (defined(_WIN32) || defined(__i386__) || defined(__x86_64__))
530 # ifdef _MSC_VER
531  __cpuidex(info, infoType, extra);
532 # elif defined(__x86_64__)
533  __asm__ __volatile__ (
534  "cpuid \n\t"
535  : "=a" (info[0]), "=b" (info[1]), "=c" (info[2]), "=d" (info[3])
536  : "0" (infoType), "2" (extra));
537 # else
538  __asm__ __volatile__ (
539  "mov{l}\t{%%}ebx, %1 \n\t"
540  "cpuid \n\t"
541  "xchg{l}\t{%%}ebx, %1 \n\t"
542  : "=a" (info[0]), "=r" (info[1]), "=c" (info[2]), "=d" (info[3])
543  : "0" (infoType), "2" (extra));
544 # endif
545 #else
546  info[0] = 0; info[1] = 0; info[2] = 0; info[3] = 0;
547 #endif
548 }
549 
550 
551 inline bool cpu_has_sse2 () {int i[4]; cpuid(i,1,0); return (i[3] & (1<<26)) != 0; }
552 inline bool cpu_has_sse3 () {int i[4]; cpuid(i,1,0); return (i[2] & (1<<0)) != 0; }
553 inline bool cpu_has_ssse3 () {int i[4]; cpuid(i,1,0); return (i[2] & (1<<9)) != 0; }
554 inline bool cpu_has_fma () {int i[4]; cpuid(i,1,0); return (i[2] & (1<<12)) != 0; }
555 inline bool cpu_has_sse41 () {int i[4]; cpuid(i,1,0); return (i[2] & (1<<19)) != 0; }
556 inline bool cpu_has_sse42 () {int i[4]; cpuid(i,1,0); return (i[2] & (1<<20)) != 0; }
557 inline bool cpu_has_popcnt() {int i[4]; cpuid(i,1,0); return (i[2] & (1<<23)) != 0; }
558 inline bool cpu_has_avx () {int i[4]; cpuid(i,1,0); return (i[2] & (1<<28)) != 0; }
559 inline bool cpu_has_f16c () {int i[4]; cpuid(i,1,0); return (i[2] & (1<<29)) != 0; }
560 inline bool cpu_has_rdrand() {int i[4]; cpuid(i,1,0); return (i[2] & (1<<30)) != 0; }
561 inline bool cpu_has_avx2 () {int i[4]; cpuid(i,7,0); return (i[1] & (1<<5)) != 0; }
562 inline bool cpu_has_avx512f() {int i[4]; cpuid(i,7,0); return (i[1] & (1<<16)) != 0; }
563 inline bool cpu_has_avx512dq() {int i[4]; cpuid(i,7,0); return (i[1] & (1<<17)) != 0; }
564 inline bool cpu_has_avx512ifma() {int i[4]; cpuid(i,7,0); return (i[1] & (1<<21)) != 0; }
565 inline bool cpu_has_avx512pf() {int i[4]; cpuid(i,7,0); return (i[1] & (1<<26)) != 0; }
566 inline bool cpu_has_avx512er() {int i[4]; cpuid(i,7,0); return (i[1] & (1<<27)) != 0; }
567 inline bool cpu_has_avx512cd() {int i[4]; cpuid(i,7,0); return (i[1] & (1<<28)) != 0; }
568 inline bool cpu_has_avx512bw() {int i[4]; cpuid(i,7,0); return (i[1] & (1<<30)) != 0; }
569 inline bool cpu_has_avx512vl() {int i[4]; cpuid(i,7,0); return (i[1] & (0x80000000 /*1<<31*/)) != 0; }
570 
571 // portable aligned malloc
572 OIIO_API void* aligned_malloc(std::size_t size, std::size_t align);
573 OIIO_API void aligned_free(void* ptr);
574 
575 // basic wrappers to new/delete over-aligned types since this isn't guaranteed to be supported until C++17
576 template <typename T, class... Args>
577 inline T* aligned_new(Args&&... args) {
578  static_assert(alignof(T) > alignof(void*), "Type doesn't seem to be over-aligned, aligned_new is not required");
579  void* ptr = aligned_malloc(sizeof(T), alignof(T));
580  return ptr ? new (ptr) T(std::forward<Args>(args)...) : nullptr;
581 }
582 
583 template <typename T>
584 inline void aligned_delete(T* t) {
585  if (t) {
586  t->~T();
587  aligned_free(t);
588  }
589 }
590 
591 
592 
593 #if OIIO_CPLUSPLUS_VERSION >= 14
594  using std::enable_if_t; // Use C++14 std::enable_if_t
595 #else
596  // Define enable_if_t for C++11
597  template <bool B, class T = void>
599 #endif
600 
601 // An enable_if helper to be used in template parameters which results in
602 // much shorter symbols: https://godbolt.org/z/sWw4vP
603 // Borrowed from fmtlib.
604 #define OIIO_ENABLE_IF(...) OIIO::enable_if_t<(__VA_ARGS__), int> = 0
605 
606 
type
Definition: core.h:977
bool cpu_has_sse42()
Definition: platform.h:556
bool cpu_has_avx512ifma()
Definition: platform.h:564
void aligned_delete(T *t)
Definition: platform.h:584
#define OIIO_FORCEINLINE
Definition: platform.h:358
bool cpu_has_avx()
Definition: platform.h:558
bool cpu_has_avx512cd()
Definition: platform.h:567
OIIO_FORCEINLINE constexpr bool bigendian(void) noexcept
Return true if the architecture we are running on is big endian.
Definition: platform.h:517
bool cpu_has_avx2()
Definition: platform.h:561
bool cpu_has_fma()
Definition: platform.h:554
GLdouble GLdouble t
Definition: glew.h:1403
bool cpu_has_sse2()
Definition: platform.h:551
GLsizeiptr size
Definition: glcorearb.h:663
OIIO_API void aligned_free(void *ptr)
bool cpu_has_sse3()
Definition: platform.h:552
typename std::enable_if< B, T >::type enable_if_t
Definition: platform.h:598
bool cpu_has_avx512pf()
Definition: platform.h:565
bool cpu_has_avx512vl()
Definition: platform.h:569
OIIO_API void * aligned_malloc(std::size_t size, std::size_t align)
bool cpu_has_avx512bw()
Definition: platform.h:568
void cpuid(int info[4], int infoType, int extra)
Retrieve cpuid flags into 'info'.
Definition: platform.h:525
bool cpu_has_rdrand()
Definition: platform.h:560
const void * ptr(const T *p)
Definition: format.h:3603
bool cpu_has_f16c()
Definition: platform.h:559
endian
Definition: platform.h:494
OIIO_FORCEINLINE constexpr bool littleendian(void) noexcept
Return true if the architecture we are running on is little endian.
Definition: platform.h:509
**If you just want to fire and args
Definition: thread.h:615
typename std::enable_if< B, T >::type enable_if_t
Definition: core.h:259
bool cpu_has_avx512er()
Definition: platform.h:566
bool cpu_has_avx512dq()
Definition: platform.h:563
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:94
bool cpu_has_avx512f()
Definition: platform.h:562
bool cpu_has_popcnt()
Definition: platform.h:557
bool cpu_has_ssse3()
Definition: platform.h:553
bool cpu_has_sse41()
Definition: platform.h:555
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:93
#define OIIO_API
Definition: export.h:65
T * aligned_new(Args &&...args)
Definition: platform.h:577