1
2//
3// This source file is part of appleseed.
4// Visit http://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-2017 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#ifndef APPLESEED_FOUNDATION_PLATFORM_COMPILER_H
31#define APPLESEED_FOUNDATION_PLATFORM_COMPILER_H
32
33//
34// Quick reminder about Visual Studio versions:
35//
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
39// Visual Studio 2010 MSVC++ 10.0 _MSC_VER == 1600
40// Visual Studio 2008 MSVC++ 9.0 _MSC_VER == 1500
41// Visual Studio 2005 MSVC++ 8.0 _MSC_VER == 1400
42// Visual Studio 2003 MSVC++ 7.1 _MSC_VER == 1310
43//
44
45// appleseed.foundation headers.
46#include "foundation/core/concepts/noncopyable.h"
47
48// appleseed.main headers.
49#include "main/dllsymbol.h"
50
51// Standard headers.
52#include <cstdarg>
53
54// Source code annotations are available starting with Visual Studio 2005.
55#if _MSC_VER >= 1400
56#include <sal.h>
57#endif
58
59namespace foundation
60{
61
62//
63// A qualifier to force inlining of a function/method on supported compilers.
64//
65
66// Visual C++.
67#if defined _MSC_VER
68 #define APPLESEED_FORCE_INLINE __forceinline
69
70// gcc.
71#elif defined __GNUC__
72 #define APPLESEED_FORCE_INLINE inline __attribute__((always_inline))
73
74// Other compilers: fall back to standard inlining.
75#else
76 #define APPLESEED_FORCE_INLINE inline
77#endif
78
79
80//
81// A qualifier to prevent inlining of a function/method on supported compilers.
82//
83
84// Visual C++.
85#if defined _MSC_VER
86 #define APPLESEED_NO_INLINE __declspec(noinline)
87
88// gcc.
89#elif defined __GNUC__
90 #define APPLESEED_NO_INLINE __attribute__((noinline))
91
92// Other compilers: ignore the qualifier.
93#else
94 #define APPLESEED_NO_INLINE
95#endif
96
97
98//
99// Qualifiers to specify the alignment of a variable, a structure member or a structure.
100//
101// APPLESEED_SIMD4_ALIGN aligns on a 16-byte boundary as required by SSE load/store instructions.
102// APPLESEED_SIMD8_ALIGN aligns on a 32-byte boundary as required by AVX load/store instructions.
103//
104// Note that APPLESEED_SIMDX_ALIGN *always* performs the alignment, regardless of whether or not
105// SSE is enabled in the build configuration.
106//
107
108// Visual C++.
109#if defined _MSC_VER
110 #define APPLESEED_ALIGN(n) __declspec(align(n))
111 #define APPLESEED_SIMD4_ALIGN APPLESEED_ALIGN(16)
112 #define APPLESEED_SIMD8_ALIGN APPLESEED_ALIGN(32)
113
114// gcc.
115#elif defined __GNUC__
116 #define APPLESEED_ALIGN(n) __attribute__((aligned(n)))
117 #define APPLESEED_SIMD4_ALIGN APPLESEED_ALIGN(16)
118 #define APPLESEED_SIMD8_ALIGN APPLESEED_ALIGN(32)
119
120// Other compilers: ignore the qualifier, and leave APPLESEED_SIMDX_ALIGN undefined.
121#else
122 #define APPLESEED_ALIGN(n)
123#endif
124
125
126//
127// Return the alignment requirement of a type.
128//
129
130// Visual C++.
131#if defined _MSC_VER
132 #define APPLESEED_ALIGNOF(t) __alignof(t)
133
134// gcc.
135#elif defined __GNUC__
136 #define APPLESEED_ALIGNOF(t) __alignof__(t)
137
138// Other compilers: abort compilation.
139#else
140 #error APPLESEED_ALIGNOF is not defined for this compiler.
141#endif
142
143
144//
145// A qualifier similar to the 'restrict' keyword in C99.
146//
147
148#define APPLESEED_RESTRICT __restrict
149
150
151//
152// A qualifier to inform the compiler that code is unreachable.
153//
154
155// Visual C++.
156#if defined _MSC_VER
157 #define APPLESEED_UNREACHABLE assert(!"This code was assumed to be unreachable."); __assume(0)
158
159// gcc: supported since gcc 4.5.
160#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
161 #define APPLESEED_UNREACHABLE assert(!"This code was assumed to be unreachable."); __builtin_unreachable()
162
163// Other compilers: assert in debug, ignore in release.
164#else
165 #define APPLESEED_UNREACHABLE assert(!"This code was assumed to be unreachable.")
166#endif
167
168
169//
170// Define the APPLESEED_OVERRIDE qualifer as a synonym for the 'override' keyword in C++11.
171//
172
173// Visual C++: supported since Visual Studio 2010.
174#if _MSC_VER >= 1600
175 #define APPLESEED_OVERRIDE override
176
177// gcc: supported since gcc 4.7 when C++11 mode is enabled.
178#elif defined __GNUC__ && __cplusplus >= 201103
179 #define APPLESEED_OVERRIDE override
180
181// Other compilers: the APPLESEED_OVERRIDE qualifier has no effect.
182#else
183 #define APPLESEED_OVERRIDE
184#endif
185
186
187//
188// Define the APPLESEED_FINAL qualifier as a synonym for the 'final' keyword in C++11.
189//
190
191// Visual C++: supported since Visual Studio 2012.
192#if _MSC_VER >= 1700
193 #define APPLESEED_FINAL final
194
195// gcc: supported since gcc 4.7 when C++11 mode is enabled.
196#elif defined __GNUC__ && __cplusplus >= 201103
197 #define APPLESEED_FINAL final
198
199// Other compilers: the APPLESEED_FINAL qualifier has no effect.
200#else
201 #define APPLESEED_OVERRIDE
202#endif
203
204
205//
206// A macro to provide the compiler with branch prediction information.
207// Usage: replace if (cond) with if (APPLESEED_LIKELY(cond))
208// Warning: programmers are notoriously bad at guessing this.
209// It should only be used after profiling.
210//
211
212#if defined(__GNUC__)
213 #define APPLESEED_LIKELY(x) (__builtin_expect(bool(x), true))
214 #define APPLESEED_UNLIKELY(x) (__builtin_expect(bool(x), false))
215#else
216 #define APPLESEED_LIKELY(x) (x)
217 #define APPLESEED_UNLIKELY(x) (x)
218#endif
219
220
221//
222// A macro to mark a variable as unused. Useful in unit tests.
223//
224
225#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)))
226 #define APPLESEED_UNUSED __attribute__((unused))
227#elif defined(__clang__)
228 #define APPLESEED_UNUSED __attribute__((unused))
229#else
230 #define APPLESEED_UNUSED
231#endif
232
233
234//
235// Utility macros converting their argument to a string literal:
236// APPLESEED_TO_STRING_EVAL first expands the argument definition.
237// APPLESEED_TO_STRING_NOEVAL does not expand the argument definition.
238//
239
240#define APPLESEED_TO_STRING_EVAL(x) APPLESEED_TO_STRING_NOEVAL(x)
241#define APPLESEED_TO_STRING_NOEVAL(x) #x
242
243
244//
245// Utility macro representing an empty parameter to another macro.
246// Omitting macro parameters is supported in C99, but not yet in C++98;
247// using a macro expanding to nothing is a way to work around this limitation.
248// Named APPLESEED_EMPTY instead of simply EMPTY to prevent possible name
249// collisions.
250//
251
252#define APPLESEED_EMPTY
253
254
255//
256// Up to version 2012, Visual C++ doesn't provide the va_copy() macro
257// introduced in C99. On Windows (32-bit and 64-bit) it is sufficient
258// to use assignment between va_list variables.
259// Starting with Visual C++ 2013, va_copy() is natively available.
260//
261
262#if defined _MSC_VER && _MSC_VER < 1800
263 #ifndef va_copy
264 #define va_copy(dst, src) ((dst) = (src))
265 #endif
266#endif
267
268
269//
270// From https://ceres-solver.googlesource.com/ceres-solver/+/master/internal/ceres/stringprintf.cc:
271//
272// va_copy() was defined in the C99 standard. However, it did not appear in the
273// C++ standard until C++11. This means that if Ceres is being compiled with a
274// strict pre-C++11 standard (e.g. -std=c++03), va_copy() will NOT be defined,
275// as we are using the C++ compiler (it would however be defined if we were
276// using the C compiler). Note however that both GCC & Clang will in fact
277// define va_copy() when compiling for C++ if the C++ standard is not explicitly
278// specified (i.e. no -std=c++<XX> arg), even though it should not strictly be
279// defined unless -std=c++11 (or greater) was passed.
280//
281
282#if defined(__GNUC__) && !defined(va_copy)
283 #define va_copy(d, s) __va_copy(d, s)
284#endif
285
286
287//
288// Source code annotations.
289//
290// About APPLESEED_PRINTF_FMT and APPLESEED_PRINTF_FMT_ATTR() usage:
291//
292// From http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html:
293//
294// The parameter string_index specifies which argument is the format string argument
295// (starting from 1), while first_to_check is the number of the first argument to
296// check against the format string. For functions where the arguments are not
297// available to be checked (such as vprintf), specify the third parameter as zero.
298// In this case the compiler only checks the format string for consistency. [...]
299//
300// Since non-static C++ methods have an implicit 'this' argument, the arguments of
301// such methods should be counted from two, not one, when giving values for
302// string_index and first_to_check.
303//
304
305// Visual C++: Visual Studio 2008+ annotations.
306#if _MSC_VER >= 1500
307 #define APPLESEED_PRINTF_FMT _Printf_format_string_
308 #define APPLESEED_PRINTF_FMT_ATTR(string_index, first_to_check)
309
310// Visual C++: Visual Studio 2005 annotations.
311#elif _MSC_VER >= 1400
312 #define APPLESEED_PRINTF_FMT __format_string
313 #define APPLESEED_PRINTF_FMT_ATTR(string_index, first_to_check)
314
315// gcc.
316#elif defined __GNUC__
317 #define APPLESEED_PRINTF_FMT
318 #define APPLESEED_PRINTF_FMT_ATTR(string_index, first_to_check) __attribute__((format(printf, string_index, first_to_check)))
319
320// Other compilers: annotations have no effect.
321#else
322 #define APPLESEED_PRINTF_FMT
323 #define APPLESEED_PRINTF_FMT_ATTR(string_index, first_to_check)
324#endif
325
326
327//
328// The Compiler class provides information about the compiler used to build the library.
329//
330
331class APPLESEED_DLLSYMBOL Compiler
332 : public NonCopyable
333{
334 public:
335 // Return the name of the compiler.
336 static const char* get_compiler_name();
337
338 // Return the version of the compiler.
339 static const char* get_compiler_version();
340};
341
342} // namespace foundation
343
344#endif // !APPLESEED_FOUNDATION_PLATFORM_COMPILER_H
345