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