duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

language.hpp (10136B)


      1 #ifndef _C4_LANGUAGE_HPP_
      2 #define _C4_LANGUAGE_HPP_
      3 
      4 /** @file language.hpp Provides language standard information macros and
      5  * compiler agnostic utility macros: namespace facilities, function attributes,
      6  * variable attributes, etc.
      7  * @ingroup basic_headers */
      8 
      9 #include "c4/preprocessor.hpp"
     10 #include "c4/compiler.hpp"
     11 
     12 /* Detect C++ standard.
     13  * @see http://stackoverflow.com/a/7132549/5875572 */
     14 #ifndef C4_CPP
     15 #   if defined(_MSC_VER) && !defined(__clang__)
     16 #       if _MSC_VER >= 1910  // >VS2015: VS2017, VS2019
     17 #           if (!defined(_MSVC_LANG))
     18 #               error _MSVC not defined
     19 #           endif
     20 #           if _MSVC_LANG >= 201705L
     21 #               define C4_CPP 20
     22 #               define C4_CPP20
     23 #           elif _MSVC_LANG == 201703L
     24 #               define C4_CPP 17
     25 #               define C4_CPP17
     26 #           elif _MSVC_LANG >= 201402L
     27 #               define C4_CPP 14
     28 #               define C4_CPP14
     29 #           elif _MSVC_LANG >= 201103L
     30 #               define C4_CPP 11
     31 #               define C4_CPP11
     32 #           else
     33 #               error C++ lesser than C++11 not supported
     34 #           endif
     35 #       else
     36 #           if _MSC_VER == 1900
     37 #               define C4_CPP 14  // VS2015 is c++14 https://devblogs.microsoft.com/cppblog/c111417-features-in-vs-2015-rtm/
     38 #               define C4_CPP14
     39 #           elif _MSC_VER == 1800 // VS2013
     40 #               define C4_CPP 11
     41 #               define C4_CPP11
     42 #           else
     43 #               error C++ lesser than C++11 not supported
     44 #           endif
     45 #       endif
     46 #   elif defined(__INTEL_COMPILER) // https://software.intel.com/en-us/node/524490
     47 #       ifdef __INTEL_CXX20_MODE__ // not sure about this
     48 #           define C4_CPP 20
     49 #           define C4_CPP20
     50 #       elif defined __INTEL_CXX17_MODE__ // not sure about this
     51 #           define C4_CPP 17
     52 #           define C4_CPP17
     53 #       elif defined __INTEL_CXX14_MODE__ // not sure about this
     54 #           define C4_CPP 14
     55 #           define C4_CPP14
     56 #       elif defined __INTEL_CXX11_MODE__
     57 #           define C4_CPP 11
     58 #           define C4_CPP11
     59 #       else
     60 #           error C++ lesser than C++11 not supported
     61 #       endif
     62 #   else
     63 #       ifndef __cplusplus
     64 #           error __cplusplus is not defined?
     65 #       endif
     66 #       if __cplusplus == 1
     67 #           error cannot handle __cplusplus==1
     68 #       elif __cplusplus >= 201709L
     69 #           define C4_CPP 20
     70 #           define C4_CPP20
     71 #       elif __cplusplus >= 201703L
     72 #           define C4_CPP 17
     73 #           define C4_CPP17
     74 #       elif __cplusplus >= 201402L
     75 #           define C4_CPP 14
     76 #           define C4_CPP14
     77 #       elif __cplusplus >= 201103L
     78 #           define C4_CPP 11
     79 #           define C4_CPP11
     80 #       elif __cplusplus >= 199711L
     81 #           error C++ lesser than C++11 not supported
     82 #       endif
     83 #   endif
     84 #else
     85 #   ifdef C4_CPP == 20
     86 #       define C4_CPP20
     87 #   elif C4_CPP == 17
     88 #       define C4_CPP17
     89 #   elif C4_CPP == 14
     90 #       define C4_CPP14
     91 #   elif C4_CPP == 11
     92 #       define C4_CPP11
     93 #   elif C4_CPP == 98
     94 #       define C4_CPP98
     95 #       error C++ lesser than C++11 not supported
     96 #   else
     97 #       error C4_CPP must be one of 20, 17, 14, 11, 98
     98 #   endif
     99 #endif
    100 
    101 #ifdef C4_CPP20
    102 #   define C4_CPP17
    103 #   define C4_CPP14
    104 #   define C4_CPP11
    105 #elif defined(C4_CPP17)
    106 #   define C4_CPP14
    107 #   define C4_CPP11
    108 #elif defined(C4_CPP14)
    109 #   define C4_CPP11
    110 #endif
    111 
    112 /** lifted from this answer: http://stackoverflow.com/a/20170989/5875572 */
    113 #if defined(_MSC_VER) && !defined(__clang__)
    114 #  if _MSC_VER < 1900
    115 #    define C4_CONSTEXPR11
    116 #    define C4_CONSTEXPR14
    117 #  elif _MSC_VER < 2000
    118 #    define C4_CONSTEXPR11 constexpr
    119 #    define C4_CONSTEXPR14
    120 #  else
    121 #    define C4_CONSTEXPR11 constexpr
    122 #    define C4_CONSTEXPR14 constexpr
    123 #  endif
    124 #else
    125 #  if __cplusplus < 201103
    126 #    define C4_CONSTEXPR11
    127 #    define C4_CONSTEXPR14
    128 #  elif __cplusplus == 201103
    129 #    define C4_CONSTEXPR11 constexpr
    130 #    define C4_CONSTEXPR14
    131 #  else
    132 #    define C4_CONSTEXPR11 constexpr
    133 #    define C4_CONSTEXPR14 constexpr
    134 #  endif
    135 #endif  // _MSC_VER
    136 
    137 
    138 #if C4_CPP < 17
    139 #define C4_IF_CONSTEXPR
    140 #define C4_INLINE_CONSTEXPR constexpr
    141 #else
    142 #define C4_IF_CONSTEXPR constexpr
    143 #define C4_INLINE_CONSTEXPR inline constexpr
    144 #endif
    145 
    146 #if defined(_MSC_VER) && !defined(__clang__)
    147 #  if (defined(_CPPUNWIND) && (_CPPUNWIND == 1))
    148 #    define C4_EXCEPTIONS
    149 #  endif
    150 #else
    151 #  if defined(__EXCEPTIONS) || defined(__cpp_exceptions)
    152 #    define C4_EXCEPTIONS
    153 #  endif
    154 #endif
    155 
    156 #ifdef C4_EXCEPTIONS
    157 #  define C4_IF_EXCEPTIONS_(exc_code, setjmp_code) exc_code
    158 #  define C4_IF_EXCEPTIONS(exc_code, setjmp_code) do { exc_code } while(0)
    159 #else
    160 #  define C4_IF_EXCEPTIONS_(exc_code, setjmp_code) setjmp_code
    161 #  define C4_IF_EXCEPTIONS(exc_code, setjmp_code) do { setjmp_code } while(0)
    162 #endif
    163 
    164 #if defined(_MSC_VER) && !defined(__clang__)
    165 #  if defined(_CPPRTTI)
    166 #    define C4_RTTI
    167 #  endif
    168 #else
    169 #  if defined(__GXX_RTTI)
    170 #    define C4_RTTI
    171 #  endif
    172 #endif
    173 
    174 #ifdef C4_RTTI
    175 #  define C4_IF_RTTI_(code_rtti, code_no_rtti) code_rtti
    176 #  define C4_IF_RTTI(code_rtti, code_no_rtti) do { code_rtti } while(0)
    177 #else
    178 #  define C4_IF_RTTI_(code_rtti, code_no_rtti) code_no_rtti
    179 #  define C4_IF_RTTI(code_rtti, code_no_rtti) do { code_no_rtti } while(0)
    180 #endif
    181 
    182 
    183 //------------------------------------------------------------
    184 
    185 #define _C4_BEGIN_NAMESPACE(ns) namespace ns {
    186 #define _C4_END_NAMESPACE(ns)   }
    187 
    188 // MSVC cant handle the C4_FOR_EACH macro... need to fix this
    189 //#define C4_BEGIN_NAMESPACE(...) C4_FOR_EACH_SEP(_C4_BEGIN_NAMESPACE, , __VA_ARGS__)
    190 //#define C4_END_NAMESPACE(...) C4_FOR_EACH_SEP(_C4_END_NAMESPACE, , __VA_ARGS__)
    191 #define C4_BEGIN_NAMESPACE(ns) namespace ns {
    192 #define C4_END_NAMESPACE(ns) }
    193 
    194 #define C4_BEGIN_HIDDEN_NAMESPACE namespace /*hidden*/ {
    195 #define C4_END_HIDDEN_NAMESPACE } /* namespace hidden */
    196 
    197 //------------------------------------------------------------
    198 
    199 #ifndef C4_API
    200 #   if defined(_MSC_VER) && !defined(__clang__)
    201 #       if defined(C4_EXPORT)
    202 #           define C4_API __declspec(dllexport)
    203 #       elif defined(C4_IMPORT)
    204 #           define C4_API __declspec(dllimport)
    205 #       else
    206 #           define C4_API
    207 #       endif
    208 #   else
    209 #       define C4_API
    210 #   endif
    211 #endif
    212 
    213 #if defined(_MSC_VER) && !defined(__clang__)
    214 #   define C4_RESTRICT __restrict
    215 #   define C4_RESTRICT_FN __declspec(restrict)
    216 #   define C4_NO_INLINE __declspec(noinline)
    217 #   define C4_ALWAYS_INLINE inline __forceinline
    218 /** these are not available in VS AFAIK */
    219 #   define C4_CONST
    220 #   define C4_PURE
    221 #   define C4_FLATTEN
    222 #   define C4_HOT         /** @todo */
    223 #   define C4_COLD        /** @todo */
    224 #   define C4_EXPECT(x, y) x /** @todo */
    225 #   define C4_LIKELY(x)   x /** @todo */
    226 #   define C4_UNLIKELY(x) x /** @todo */
    227 #   define C4_UNREACHABLE() /** @todo */
    228 #   define C4_ATTR_FORMAT(...) /** */
    229 #   define C4_NORETURN /** @todo */
    230 #else
    231     ///< @todo assuming gcc-like compiler. check it is actually so.
    232 /** for function attributes in GCC,
    233  * @see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes */
    234 /** for __builtin functions in GCC,
    235  * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */
    236 #   define C4_RESTRICT __restrict__
    237 #   define C4_RESTRICT_FN __attribute__((restrict))
    238 #   define C4_NO_INLINE __attribute__((noinline))
    239 #   define C4_ALWAYS_INLINE inline __attribute__((always_inline))
    240 #   define C4_CONST __attribute__((const))
    241 #   define C4_PURE __attribute__((pure))
    242 /** force inlining of every callee function */
    243 #   define C4_FLATTEN __atribute__((flatten))
    244 /** mark a function as hot, ie as having a visible impact in CPU time
    245  * thus making it more likely to inline, etc
    246  * @see http://stackoverflow.com/questions/15028990/semantics-of-gcc-hot-attribute */
    247 #   define C4_HOT __attribute__((hot))
    248 /** mark a function as cold, ie as NOT having a visible impact in CPU time
    249  * @see http://stackoverflow.com/questions/15028990/semantics-of-gcc-hot-attribute */
    250 #   define C4_COLD __attribute__((cold))
    251 #   define C4_EXPECT(x, y) __builtin_expect(x, y) ///< @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
    252 #   define C4_LIKELY(x)   __builtin_expect(x, 1)
    253 #   define C4_UNLIKELY(x) __builtin_expect(x, 0)
    254 #   define C4_UNREACHABLE() __builtin_unreachable()
    255 #   define C4_ATTR_FORMAT(...) //__attribute__((format (__VA_ARGS__))) ///< @see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
    256 #   define C4_NORETURN __attribute__((noreturn))
    257 #endif
    258 
    259 #ifdef _MSC_VER
    260 #   define C4_FUNC __FUNCTION__
    261 #   define C4_PRETTY_FUNC __FUNCSIG__
    262 #else /// @todo assuming gcc-like compiler. check it is actually so.
    263 #   define C4_FUNC __FUNCTION__
    264 #   define C4_PRETTY_FUNC __PRETTY_FUNCTION__
    265 #endif
    266 
    267 /** prevent compiler warnings about a specific var being unused */
    268 #define C4_UNUSED(var) (void)var
    269 
    270 #if C4_CPP >= 17
    271 #define C4_STATIC_ASSERT(cond) static_assert(cond)
    272 #else
    273 #define C4_STATIC_ASSERT(cond) static_assert((cond), #cond)
    274 #endif
    275 #define C4_STATIC_ASSERT_MSG(cond, msg) static_assert((cond), #cond ": " msg)
    276 
    277 /** @def C4_DONT_OPTIMIZE idea lifted from GoogleBenchmark.
    278  * @see https://github.com/google/benchmark/blob/master/include/benchmark/benchmark_api.h */
    279 namespace c4 {
    280 namespace detail {
    281 #ifdef __GNUC__
    282 #   define C4_DONT_OPTIMIZE(var) c4::detail::dont_optimize(var)
    283 template< class T >
    284 C4_ALWAYS_INLINE void dont_optimize(T const& value) { asm volatile("" : : "g"(value) : "memory"); }
    285 #else
    286 #   define C4_DONT_OPTIMIZE(var) c4::detail::use_char_pointer(reinterpret_cast< const char* >(&var))
    287 void use_char_pointer(char const volatile*);
    288 #endif
    289 } // namespace detail
    290 } // namespace c4
    291 
    292 /** @def C4_KEEP_EMPTY_LOOP prevent an empty loop from being optimized out.
    293  * @see http://stackoverflow.com/a/7084193/5875572 */
    294 #if defined(_MSC_VER) && !defined(__clang__)
    295 #   define C4_KEEP_EMPTY_LOOP { char c; C4_DONT_OPTIMIZE(c); }
    296 #else
    297 #   define C4_KEEP_EMPTY_LOOP { asm(""); }
    298 #endif
    299 
    300 /** @def C4_VA_LIST_REUSE_MUST_COPY
    301  * @todo <jpmag> I strongly suspect that this is actually only in UNIX platforms. revisit this. */
    302 #ifdef __GNUC__
    303 #   define C4_VA_LIST_REUSE_MUST_COPY
    304 #endif
    305 
    306 #endif /* _C4_LANGUAGE_HPP_ */