1 2 // 3 // This source file is part of appleseed. 4 // Visit https://appleseedhq.net/ for additional information and resources. 5 // 6 // This software is released under the MIT license. 7 // 8 // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited 9 // Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization 10 // 11 // Permission is hereby granted, free of charge, to any person obtaining a copy 12 // of this software and associated documentation files (the "Software"), to deal 13 // in the Software without restriction, including without limitation the rights 14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 // copies of the Software, and to permit persons to whom the Software is 16 // furnished to do so, subject to the following conditions: 17 // 18 // The above copyright notice and this permission notice shall be included in 19 // all copies or substantial portions of the Software. 20 // 21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 // THE SOFTWARE. 28 // 29 30 #pragma once 31 32 // 33 // Quick reminder about Visual Studio versions: 34 // 35 // Visual Studio 2017 MSVC++ 14.1 _MSC_VER == 1910 36 // Visual Studio 2015 MSVC++ 14.0 _MSC_VER == 1900 37 // Visual Studio 2013 MSVC++ 12.0 _MSC_VER == 1800 38 // Visual Studio 2012 MSVC++ 11.0 _MSC_VER == 1700 (oldest supported version) 39 // Visual Studio 2010 MSVC++ 10.0 _MSC_VER == 1600 (unsupported) 40 // Visual Studio 2008 MSVC++ 9.0 _MSC_VER == 1500 (unsupported) 41 // Visual Studio 2005 MSVC++ 8.0 _MSC_VER == 1400 (unsupported) 42 // Visual Studio 2003 MSVC++ 7.1 _MSC_VER == 1310 (unsupported) 43 // 44 45 // appleseed.foundation headers. 46 #include "foundation/core/concepts/noncopyable.h" 47 #include "foundation/platform/compilerfeatures.h" 48 49 // appleseed.main headers. 50 #include "main/dllsymbol.h" 51 52 // Standard headers. 53 #include <cstdarg> 54 55 // Platform headers. 56 #if defined _MSC_VER 57 #include <sal.h> 58 #endif 59 60 namespace foundation 61 { 62 63 // 64 // Thread-local storage-class modifier. 65 // 66 67 // Visual C++ 2013 and earlier. 68 #if defined _MSC_VER && _MSC_VER < 1900 69 #define APPLESEED_TLS __declspec(thread) 70 71 // gcc. 72 #elif defined __GNUC__ 73 // On gcc we use __thread because it's faster than thread_local when dynamic 74 // initialization and destruction is not needed. 75 // It also fixes an internal compiler error in gcc 4.8.3 when using 76 // static thread local members in a template class. 77 #define APPLESEED_TLS __thread 78 79 // Other compilers: use C++11's thread_local keyword. 80 #else 81 #define APPLESEED_TLS thread_local 82 #endif 83 84 85 // 86 // A qualifier to force inlining of a function/method on supported compilers. 87 // 88 89 // Visual C++. 90 #if defined _MSC_VER 91 #define APPLESEED_FORCE_INLINE __forceinline 92 93 // gcc. 94 #elif defined __GNUC__ 95 #define APPLESEED_FORCE_INLINE inline __attribute__((always_inline)) 96 97 // CUDA. 98 #elif defined __CUDACC__ 99 #define APPLESEED_FORCE_INLINE __forceinline__ 100 101 // Other compilers: fall back to standard inlining. 102 #else 103 #define APPLESEED_FORCE_INLINE inline 104 #endif 105 106 107 // 108 // A qualifier to prevent inlining of a function/method on supported compilers. 109 // 110 111 // Visual C++. 112 #if defined _MSC_VER 113 #define APPLESEED_NO_INLINE __declspec(noinline) 114 115 // gcc. 116 #elif defined __GNUC__ 117 #define APPLESEED_NO_INLINE __attribute__((noinline)) 118 119 // CUDA. 120 #elif defined __CUDACC__ 121 #define APPLESEED_NO_INLINE __noinline__ 122 123 // Other compilers: ignore the qualifier. 124 #else 125 #define APPLESEED_NO_INLINE 126 #endif 127 128 129 // 130 // Qualifiers to specify the alignment of a variable, a structure member or a structure. 131 // 132 // APPLESEED_SIMD4_ALIGN aligns on a 16-byte boundary as required by SSE load/store instructions. 133 // APPLESEED_SIMD8_ALIGN aligns on a 32-byte boundary as required by AVX load/store instructions. 134 // 135 // Note that APPLESEED_SIMDx_ALIGN *always* performs the alignment, regardless of whether or not 136 // SSE is enabled in the build configuration. 137 // 138 139 // Visual C++. 140 #if defined _MSC_VER 141 #define APPLESEED_ALIGN(n) __declspec(align(n)) 142 #define APPLESEED_SIMD4_ALIGN APPLESEED_ALIGN(16) 143 #define APPLESEED_SIMD8_ALIGN APPLESEED_ALIGN(32) 144 145 // gcc. 146 #elif defined __GNUC__ 147 #define APPLESEED_ALIGN(n) __attribute__((aligned(n))) 148 #define APPLESEED_SIMD4_ALIGN APPLESEED_ALIGN(16) 149 #define APPLESEED_SIMD8_ALIGN APPLESEED_ALIGN(32) 150 151 // Other compilers: ignore the qualifier, and leave APPLESEED_SIMDX_ALIGN undefined. 152 #else 153 #define APPLESEED_ALIGN(n) 154 #endif 155 156 157 // 158 // Return the alignment requirement of a type. 159 // 160 161 // Visual C++. 162 #if defined _MSC_VER 163 #define APPLESEED_ALIGNOF(t) __alignof(t) 164 165 // gcc. 166 #elif defined __GNUC__ 167 #define APPLESEED_ALIGNOF(t) __alignof__(t) 168 169 // Other compilers: abort compilation. 170 #else 171 #error APPLESEED_ALIGNOF is not defined for this compiler. 172 #endif 173 174 175 // 176 // A qualifier similar to the 'restrict' keyword in C99. 177 // 178 179 // Visual C++. 180 #if defined _MSC_VER 181 #define APPLESEED_RESTRICT __restrict 182 183 // gcc, clang or CUDA. 184 #elif defined __GNUC__ || defined __clang__ || defined __CUDACC__ 185 #define APPLESEED_RESTRICT __restrict__ 186 187 // Other compilers: ignore the qualifier. 188 #else 189 #define APPLESEED_RESTRICT 190 #endif 191 192 193 // 194 // A qualifier to inform the compiler that code is unreachable. 195 // 196 197 // Visual C++. 198 #if defined _MSC_VER 199 #define APPLESEED_UNREACHABLE assert(!"This code was assumed to be unreachable."); __assume(0) 200 201 // gcc: supported since gcc 4.5. 202 #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 203 #define APPLESEED_UNREACHABLE assert(!"This code was assumed to be unreachable."); __builtin_unreachable() 204 205 // Other compilers: assert in debug, ignore in release. 206 #else 207 #define APPLESEED_UNREACHABLE assert(!"This code was assumed to be unreachable.") 208 #endif 209 210 211 // 212 // A macro to provide the compiler with branch prediction information. 213 // Usage: replace if (cond) with if (APPLESEED_LIKELY(cond)) 214 // Warning: programmers are notoriously bad at guessing this. 215 // It should only be used after profiling. 216 // 217 218 #if defined(__GNUC__) 219 #define APPLESEED_LIKELY(x) (__builtin_expect(bool(x), true)) 220 #define APPLESEED_UNLIKELY(x) (__builtin_expect(bool(x), false)) 221 #else 222 #define APPLESEED_LIKELY(x) (x) 223 #define APPLESEED_UNLIKELY(x) (x) 224 #endif 225 226 227 // 228 // A macro to mark a variable as unused. Useful in unit tests. 229 // 230 231 // gcc: supported since gcc 4.6. 232 #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))) 233 #define APPLESEED_UNUSED __attribute__((unused)) 234 235 // clang. 236 #elif defined(__clang__) 237 #define APPLESEED_UNUSED __attribute__((unused)) 238 239 // Other compilers: ignore. 240 #else 241 #define APPLESEED_UNUSED 242 #endif 243 244 245 // 246 // Utility macros converting their argument to a string literal: 247 // APPLESEED_TO_STRING_EVAL first expands the argument definition. 248 // APPLESEED_TO_STRING_NOEVAL does not expand the argument definition. 249 // 250 251 #define APPLESEED_TO_STRING_EVAL(x) APPLESEED_TO_STRING_NOEVAL(x) 252 #define APPLESEED_TO_STRING_NOEVAL(x) #x 253 254 255 // 256 // Utility macro representing an empty parameter to another macro. 257 // Omitting macro parameters is supported in C99, but not yet in C++98; 258 // using a macro expanding to nothing is a way to work around this limitation. 259 // Named APPLESEED_EMPTY instead of simply EMPTY to prevent possible name 260 // collisions. 261 // 262 263 #define APPLESEED_EMPTY 264 265 266 // 267 // Up to version 2012, Visual C++ doesn't provide the va_copy() macro 268 // introduced in C99. On Windows (32-bit and 64-bit) it is sufficient 269 // to use assignment between va_list variables. 270 // Starting with Visual C++ 2013, va_copy() is natively available. 271 // 272 273 #if defined _MSC_VER && _MSC_VER < 1800 274 #ifndef va_copy 275 #define va_copy(dst, src) ((dst) = (src)) 276 #endif 277 #endif 278 279 280 // 281 // Source code annotations. 282 // 283 // About APPLESEED_PRINTF_FMT and APPLESEED_PRINTF_FMT_ATTR() usage: 284 // 285 // From http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html: 286 // 287 // The parameter string_index specifies which argument is the format string argument 288 // (starting from 1), while first_to_check is the number of the first argument to 289 // check against the format string. For functions where the arguments are not 290 // available to be checked (such as vprintf), specify the third parameter as zero. 291 // In this case the compiler only checks the format string for consistency. [...] 292 // 293 // Since non-static C++ methods have an implicit 'this' argument, the arguments of 294 // such methods should be counted from two, not one, when giving values for 295 // string_index and first_to_check. 296 // 297 298 // Visual C++: Visual Studio 2008+ annotations. 299 #if defined _MSC_VER 300 #define APPLESEED_PRINTF_FMT _Printf_format_string_ 301 #define APPLESEED_PRINTF_FMT_ATTR(string_index, first_to_check) 302 303 // gcc. 304 #elif defined __GNUC__ 305 #define APPLESEED_PRINTF_FMT 306 #define APPLESEED_PRINTF_FMT_ATTR(string_index, first_to_check) __attribute__((format(printf, string_index, first_to_check))) 307 308 // Other compilers: annotations have no effect. 309 #else 310 #define APPLESEED_PRINTF_FMT 311 #define APPLESEED_PRINTF_FMT_ATTR(string_index, first_to_check) 312 #endif 313 314 315 // 316 // CUDA specific defines. 317 // 318 319 #ifdef __CUDACC__ 320 #define APPLESEED_HOST __host__ 321 #define APPLESEED_DEVICE __device__ 322 #define APPLESEED_HOST_DEVICE __host__ __device__ 323 #define APPLESEED_DEVICE_INLINE __forceinline__ __device__ 324 #define APPLESEED_HOST_DEVICE_INLINE __forceinline__ __host__ __device__ 325 #define APPLESEED_DEVICE_ALIGN(n) __align__(n) 326 #else 327 #define APPLESEED_HOST 328 #define APPLESEED_HOST_DEVICE 329 #define APPLESEED_HOST_DEVICE_INLINE inline 330 #define APPLESEED_DEVICE_ALIGN(n) 331 #endif 332 333 #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ > 0 334 #define APPLESEED_DEVICE_COMPILATION // defined when compiling CUDA device code 335 #endif 336 337 338 // 339 // The Compiler class provides information about the compiler used to build the library. 340 // 341 342 class APPLESEED_DLLSYMBOL Compiler 343 : public NonCopyable 344 { 345 public: 346 // Return the name of the compiler. 347 static const char* get_compiler_name(); 348 349 // Return the version of the compiler. 350 static const char* get_compiler_version(); 351 }; 352 353 } // namespace foundation 354