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