openMSX
unreachable.hh
Go to the documentation of this file.
1 #ifndef UNREACHABLE_HH
2 #define UNREACHABLE_HH
3 
4 // GCC targeting MIPS will generate bad code when marking certain code as
5 // unreachable. This is very noticeable in SDLVideoSystem::getWindowSize(),
6 // which does not seem to write the output arguments, making openMSX fail the
7 // creation of an SDL video mode since the requested size is rubbish.
8 //
9 // This compiler bug has been reported as:
10 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51861
11 //
12 // It turns out this was not a specific issue for MIPS, but it could affect all
13 // architectures which use branch delay slots (e.g. also AVR and SPARC).
14 //
15 // At this moment the bug in gcc has been fixed, but the most recent gcc-4.5.x
16 // and gcc-4.6.x releases still contain the bug.
17 //
18 // For openMSX, this UNREACHABLE-optimization is not very important (it does
19 // improve speed/code-size, but not in very critical locations). So we decided
20 // to only enable this optimization starting from gcc-4.7 or from gcc-4.5 for a
21 // few white-listed architectures that we know don't use delay slots.
22 
23 // Clang has a very convenient way of testing features, unfortunately (for now)
24 // it's clang-only so add a fallback for non-clang compilers.
25 #ifndef __has_builtin
26  #define __has_builtin(x) 0
27 #endif
28 
29 #if defined(NDEBUG)
30  // clang
31  #if __has_builtin(__builtin_unreachable)
32  #define UNREACHABLE __builtin_unreachable()
33 
34  // __builtin_unreachable() was introduced in gcc-4.5
35  #elif ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)))
36  // gcc-4.7 or above
37  #define UNREACHABLE __builtin_unreachable()
38 
39  #elif ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5) && (defined(__i386__) || defined(__x86_64__) || defined(__arm__)))
40  // gcc-4.5 or gcc-4.6 on x86, x86_64 or arm (all without delay slots)
41  #define UNREACHABLE __builtin_unreachable()
42 
43  #elif defined(_MSC_VER)
44  // visual studio
45  #define UNREACHABLE __assume(0)
46 
47  #else
48  // fall-back
49  #define UNREACHABLE /*nothing*/
50 
51  #endif
52 
53 #else
54  // asserts enabled
55  #include <cassert>
56  #define UNREACHABLE assert(false)
57 
58 #endif
59 
60 #endif // UNREACHABLE_HH