1 // Copyright 2017 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef COMMON_COMPILER_H_ 16 #define COMMON_COMPILER_H_ 17 18 // Defines macros for compiler-specific functionality 19 // - DAWN_COMPILER_[CLANG|GCC|MSVC]: Compiler detection 20 // - DAWN_BREAKPOINT(): Raises an exception and breaks in the debugger 21 // - DAWN_BUILTIN_UNREACHABLE(): Hints the compiler that a code path is unreachable 22 // - DAWN_NO_DISCARD: An attribute that is C++17 [[nodiscard]] where available 23 // - DAWN_(UN)?LIKELY(EXPR): Where available, hints the compiler that the expression will be true 24 // (resp. false) to help it generate code that leads to better branch prediction. 25 // - DAWN_UNUSED(EXPR): Prevents unused variable/expression warnings on EXPR. 26 // - DAWN_UNUSED_FUNC(FUNC): Prevents unused function warnings on FUNC. 27 // - DAWN_DECLARE_UNUSED: Prevents unused function warnings a subsequent declaration. 28 // Both DAWN_UNUSED_FUNC and DAWN_DECLARE_UNUSED may be necessary, e.g. to suppress clang's 29 // unneeded-internal-declaration warning. 30 31 // Clang and GCC, check for __clang__ too to catch clang-cl masquarading as MSVC 32 #if defined(__GNUC__) || defined(__clang__) 33 # if defined(__clang__) 34 # define DAWN_COMPILER_CLANG 35 # else 36 # define DAWN_COMPILER_GCC 37 # endif 38 39 # if defined(__i386__) || defined(__x86_64__) 40 # define DAWN_BREAKPOINT() __asm__ __volatile__("int $3\n\t") 41 # else 42 // TODO(cwallez@chromium.org): Implement breakpoint on all supported architectures 43 # define DAWN_BREAKPOINT() 44 # endif 45 46 # define DAWN_BUILTIN_UNREACHABLE() __builtin_unreachable() 47 # define DAWN_LIKELY(x) __builtin_expect(!!(x), 1) 48 # define DAWN_UNLIKELY(x) __builtin_expect(!!(x), 0) 49 50 # if !defined(__has_cpp_attribute) 51 # define __has_cpp_attribute(name) 0 52 # endif 53 54 // Use warn_unused_result on clang otherwise we can a c++1z extension warning in C++14 mode 55 // Also avoid warn_unused_result with GCC because it is only a function attribute and not a type 56 // attribute. 57 # if __has_cpp_attribute(warn_unused_result) && defined(__clang__) 58 # define DAWN_NO_DISCARD __attribute__((warn_unused_result)) 59 # elif DAWN_CPP_VERSION >= 17 && __has_cpp_attribute(nodiscard) 60 # define DAWN_NO_DISCARD [[nodiscard]] 61 # endif 62 63 # define DAWN_DECLARE_UNUSED __attribute__((unused)) 64 # if defined(NDEBUG) 65 # define DAWN_FORCE_INLINE inline __attribute__((always_inline)) 66 # endif 67 # define DAWN_NOINLINE __attribute__((noinline)) 68 69 // MSVC 70 #elif defined(_MSC_VER) 71 # define DAWN_COMPILER_MSVC 72 73 extern void __cdecl __debugbreak(void); 74 # define DAWN_BREAKPOINT() __debugbreak() 75 76 # define DAWN_BUILTIN_UNREACHABLE() __assume(false) 77 78 // Visual Studio 2017 15.3 adds support for [[nodiscard]] 79 # if _MSC_VER >= 1911 && DAWN_CPP_VERSION >= 17 80 # define DAWN_NO_DISCARD [[nodiscard]] 81 # endif 82 83 # define DAWN_DECLARE_UNUSED 84 # if defined(NDEBUG) 85 # define DAWN_FORCE_INLINE __forceinline 86 # endif 87 # define DAWN_NOINLINE __declspec(noinline) 88 89 #else 90 # error "Unsupported compiler" 91 #endif 92 93 // It seems that (void) EXPR works on all compilers to silence the unused variable warning. 94 #define DAWN_UNUSED(EXPR) (void)EXPR 95 // Likewise using static asserting on sizeof(&FUNC) seems to make it tagged as used 96 #define DAWN_UNUSED_FUNC(FUNC) static_assert(sizeof(&FUNC) == sizeof(void (*)()), "") 97 98 // Add noop replacements for macros for features that aren't supported by the compiler. 99 #if !defined(DAWN_LIKELY) 100 # define DAWN_LIKELY(X) X 101 #endif 102 #if !defined(DAWN_UNLIKELY) 103 # define DAWN_UNLIKELY(X) X 104 #endif 105 #if !defined(DAWN_NO_DISCARD) 106 # define DAWN_NO_DISCARD 107 #endif 108 #if !defined(DAWN_FORCE_INLINE) 109 # define DAWN_FORCE_INLINE inline 110 #endif 111 #if !defined(DAWN_NOINLINE) 112 # define DAWN_NOINLINE 113 #endif 114 115 #if defined(__clang__) 116 # define DAWN_FALLTHROUGH [[clang::fallthrough]] 117 #else 118 # define DAWN_FALLTHROUGH 119 #endif 120 121 #endif // COMMON_COMPILER_H_ 122