1 /** 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 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 16 #ifndef PANDA_LIBPANDABASE_PBASE_MACROS_H 17 #define PANDA_LIBPANDABASE_PBASE_MACROS_H 18 19 #include <cassert> 20 #include <iostream> 21 #include "os/stacktrace.h" 22 #include "utils/debug.h" 23 24 // Inline (disabled for DEBUG) 25 #ifndef NDEBUG 26 #define ALWAYS_INLINE // NOLINT(cppcoreguidelines-macro-usage) 27 #else // NDEBUG 28 #define ALWAYS_INLINE __attribute__((always_inline)) // NOLINT(cppcoreguidelines-macro-usage) 29 #endif // !NDEBUG 30 31 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 32 #define NO_INLINE __attribute__((noinline)) 33 34 #ifdef __clang__ 35 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 36 #define NO_OPTIMIZE [[clang::optnone]] 37 #else 38 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 39 #define NO_OPTIMIZE __attribute__((optimize("O0"))) 40 #endif 41 42 #ifdef __clang__ 43 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 44 #define FIELD_UNUSED __attribute__((__unused__)) 45 #else 46 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 47 #define FIELD_UNUSED 48 #endif 49 50 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 51 #define UNUSED_VAR(var) (void)(var) 52 53 #ifndef PANDA_TARGET_WINDOWS 54 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 55 #define PANDA_PUBLIC_API __attribute__((visibility("default"))) 56 #else 57 #define PANDA_PUBLIC_API __declspec(dllexport) 58 #endif 59 60 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 61 #define MEMBER_OFFSET(T, F) offsetof(T, F) 62 63 #if defined(__cplusplus) 64 65 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 66 #define NO_COPY_CTOR(TypeName) TypeName(const TypeName &) = delete 67 68 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 69 #define NO_COPY_OPERATOR(TypeName) void operator=(const TypeName &) = delete 70 71 // Disabling copy ctor and copy assignment operator. 72 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 73 #define NO_COPY_SEMANTIC(TypeName) \ 74 NO_COPY_CTOR(TypeName); \ 75 NO_COPY_OPERATOR(TypeName) 76 77 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 78 #define NO_MOVE_CTOR(TypeName) \ 79 /* NOLINTNEXTLINE(misc-macro-parentheses) */ \ 80 TypeName(TypeName &&) = delete 81 82 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 83 #define NO_MOVE_OPERATOR(TypeName) \ 84 /* NOLINTNEXTLINE(misc-macro-parentheses) */ \ 85 TypeName &operator=(TypeName &&) = delete 86 87 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 88 #define NO_MOVE_SEMANTIC(TypeName) \ 89 NO_MOVE_CTOR(TypeName); \ 90 NO_MOVE_OPERATOR(TypeName) 91 92 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 93 #define DEFAULT_MOVE_CTOR(TypeName) \ 94 /* NOLINTNEXTLINE(misc-macro-parentheses) */ \ 95 TypeName(TypeName &&) = default 96 97 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 98 #define DEFAULT_MOVE_OPERATOR(TypeName) \ 99 /* NOLINTNEXTLINE(misc-macro-parentheses) */ \ 100 TypeName &operator=(TypeName &&) = default 101 102 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 103 #define DEFAULT_MOVE_SEMANTIC(TypeName) \ 104 DEFAULT_MOVE_CTOR(TypeName); \ 105 DEFAULT_MOVE_OPERATOR(TypeName) 106 107 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 108 #define DEFAULT_COPY_CTOR(TypeName) TypeName(const TypeName &) = default 109 110 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 111 #define DEFAULT_COPY_OPERATOR(TypeName) \ 112 /* NOLINTNEXTLINE(misc-macro-parentheses) */ \ 113 TypeName &operator=(const TypeName &) = default 114 115 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 116 #define DEFAULT_COPY_SEMANTIC(TypeName) \ 117 DEFAULT_COPY_CTOR(TypeName); \ 118 DEFAULT_COPY_OPERATOR(TypeName) 119 120 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 121 #define DEFAULT_NOEXCEPT_MOVE_CTOR(TypeName) \ 122 /* NOLINTNEXTLINE(misc-macro-parentheses) */ \ 123 TypeName(TypeName &&) noexcept = default 124 125 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 126 #define DEFAULT_NOEXCEPT_MOVE_OPERATOR(TypeName) \ 127 /* NOLINTNEXTLINE(misc-macro-parentheses) */ \ 128 TypeName &operator=(TypeName &&) noexcept = default 129 130 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 131 #define DEFAULT_NOEXCEPT_MOVE_SEMANTIC(TypeName) \ 132 DEFAULT_NOEXCEPT_MOVE_CTOR(TypeName); \ 133 DEFAULT_NOEXCEPT_MOVE_OPERATOR(TypeName) 134 135 #endif // defined(__cplusplus) 136 137 #define LIKELY(exp) (__builtin_expect((exp) != 0, true)) // NOLINT(cppcoreguidelines-macro-usage) 138 #define UNLIKELY(exp) (__builtin_expect((exp) != 0, false)) // NOLINT(cppcoreguidelines-macro-usage) 139 140 #if !defined(NDEBUG) 141 142 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 143 #define ASSERT_FAIL(expr) ark::debug::AssertionFail(expr, __FILE__, __LINE__, __FUNCTION__) 144 145 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 146 #define ASSERT_OP(lhs, op, rhs) \ 147 do { \ 148 auto __lhs = lhs; \ 149 auto __rhs = rhs; \ 150 if (UNLIKELY(!(__lhs op __rhs))) { \ 151 std::cerr << "CHECK FAILED: " << #lhs << " " #op " " #rhs << std::endl; \ 152 std::cerr << " VALUES: " << __lhs << " " #op " " << __rhs << std::endl; \ 153 std::cerr << " IN: " << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION__ << std::endl; \ 154 ark::PrintStack(std::cerr); \ 155 std::abort(); \ 156 } \ 157 } while (0) 158 159 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 160 #define CHECK_LE(lhs, rhs) ASSERT_OP(lhs, <=, rhs) 161 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 162 #define CHECK_LT(lhs, rhs) ASSERT_OP(lhs, <, rhs) 163 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 164 #define CHECK_GE(lhs, rhs) ASSERT_OP(lhs, >=, rhs) 165 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 166 #define CHECK_GT(lhs, rhs) ASSERT_OP(lhs, >, rhs) 167 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 168 #define CHECK_EQ(lhs, rhs) ASSERT_OP(lhs, ==, rhs) 169 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 170 #define CHECK_NE(lhs, rhs) ASSERT_OP(lhs, !=, rhs) 171 172 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 173 #define ASSERT(cond) \ 174 if (UNLIKELY(!(cond))) { \ 175 ASSERT_FAIL(#cond); \ 176 } 177 178 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 179 #define ASSERT_DO(cond, func) \ 180 do { \ 181 if (auto cond_val = cond; UNLIKELY(!(cond_val))) { \ 182 func; \ 183 ASSERT_FAIL(#cond); \ 184 } \ 185 } while (0) 186 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 187 #define ASSERT_PRINT(cond, message) \ 188 do { \ 189 if (auto cond_val = cond; UNLIKELY(!(cond_val))) { \ 190 std::cerr << message << std::endl; \ 191 ASSERT_FAIL(#cond); \ 192 } \ 193 } while (0) 194 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 195 #define ASSERT_RETURN(cond) assert(cond) 196 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 197 #define UNREACHABLE() \ 198 do { \ 199 ASSERT_PRINT(false, "This line should be unreachable"); /* NOLINT(misc-static-assert) */ \ 200 __builtin_unreachable(); \ 201 } while (0) 202 #else // NDEBUG 203 #define ASSERT(cond) static_cast<void>(0) // NOLINT(cppcoreguidelines-macro-usage) 204 #define ASSERT_DO(cond, func) static_cast<void>(0) // NOLINT(cppcoreguidelines-macro-usage) 205 #define ASSERT_PRINT(cond, message) static_cast<void>(0) // NOLINT(cppcoreguidelines-macro-usage) 206 #define ASSERT_RETURN(cond) static_cast<void>(cond) // NOLINT(cppcoreguidelines-macro-usage) 207 #define UNREACHABLE __builtin_unreachable // NOLINT(cppcoreguidelines-macro-usage) 208 #define ASSERT_OP(lhs, op, rhs) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 209 #define CHECK_LE(lhs, rhs) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 210 #define CHECK_LT(lhs, rhs) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 211 #define CHECK_GE(lhs, rhs) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 212 #define CHECK_GT(lhs, rhs) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 213 #define CHECK_EQ(lhs, rhs) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 214 #define CHECK_NE(lhs, rhs) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 215 #endif // !NDEBUG 216 217 // Due to the impossibility of using asserts in constexpr methods 218 // we need an extra version of UNREACHABLE macro that can be used in such situations 219 #define UNREACHABLE_CONSTEXPR() __builtin_unreachable() // NOLINT(cppcoreguidelines-macro-usage) 220 221 #define MERGE_WORDS_X(A, B) A##B // NOLINT(cppcoreguidelines-macro-usage) 222 #define MERGE_WORDS(A, B) MERGE_WORDS_X(A, B) // NOLINT(cppcoreguidelines-macro-usage) 223 224 // for clang 225 #if defined(__has_feature) 226 #if __has_feature(thread_sanitizer) 227 #define USE_THREAD_SANITIZER 228 #endif 229 #endif 230 // for gnu compiler 231 #if defined(__SANITIZE_THREAD__) 232 #define USE_THREAD_SANITIZER 233 #endif 234 235 #if defined(USE_THREAD_SANITIZER) 236 #if __GNUC__ < 8 && !defined(__clang__) 237 // gcc < 8.0 has a bug with attributes: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78204 238 // Note, clang also defines __GNUC__ macro, so, check __clang also 239 #define NO_THREAD_SANITIZE __attribute__((no_sanitize_thread)) // NOLINT(cppcoreguidelines-macro-usage) 240 #else 241 #define NO_THREAD_SANITIZE __attribute__((no_sanitize("thread"))) // NOLINT(cppcoreguidelines-macro-usage) 242 #endif 243 // Do not inline no_sanitize functions to avoid gcc bug with missed annotations 244 #define ALWAYS_INLINE_NO_TSAN NO_THREAD_SANITIZE 245 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 246 #define TSAN_ANNOTATE_HAPPENS_BEFORE(addr) AnnotateHappensBefore(__FILE__, __LINE__, reinterpret_cast<void *>(addr)) 247 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 248 #define TSAN_ANNOTATE_HAPPENS_AFTER(addr) AnnotateHappensAfter(__FILE__, __LINE__, reinterpret_cast<void *>(addr)) 249 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 250 #define TSAN_ANNOTATE_IGNORE_WRITES_BEGIN() AnnotateIgnoreWritesBegin(__FILE__, __LINE__) 251 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 252 #define TSAN_ANNOTATE_IGNORE_WRITES_END() AnnotateIgnoreWritesEnd(__FILE__, __LINE__) 253 extern "C" void AnnotateHappensBefore(const char *file, int line, const volatile void *cv); 254 extern "C" void AnnotateHappensAfter(const char *file, int line, const volatile void *cv); 255 extern "C" void AnnotateIgnoreWritesBegin(const char *file, int line); 256 extern "C" void AnnotateIgnoreWritesEnd(const char *file, int line); 257 // Attribute works in clang 14 or higher versions, currently used only for INTRUSIVE_TESTING 258 #define DISABLE_THREAD_SANITIZER_INSTRUMENTATION __attribute__((disable_sanitizer_instrumentation)) 259 #else 260 #define NO_THREAD_SANITIZE 261 #define ALWAYS_INLINE_NO_TSAN ALWAYS_INLINE 262 #define TSAN_ANNOTATE_HAPPENS_BEFORE(addr) 263 #define TSAN_ANNOTATE_HAPPENS_AFTER(addr) 264 #define TSAN_ANNOTATE_IGNORE_WRITES_BEGIN() 265 #define TSAN_ANNOTATE_IGNORE_WRITES_END() 266 #define DISABLE_THREAD_SANITIZER_INSTRUMENTATION 267 #endif // USE_THREAD_SANITIZER 268 269 // for clang 270 #if defined(__has_feature) 271 #if __has_feature(undefined_behavior_sanitizer) 272 #define USE_UB_SANITIZER 273 #endif 274 #endif 275 // for gnu compiler 276 #if defined(__SANITIZE_UNDEFINED__) 277 #define USE_UB_SANITIZER 278 #endif 279 280 #if defined(USE_UB_SANITIZER) 281 #if __GNUC__ < 8 && !defined(__clang__) 282 // gcc < 8.0 has a bug with attributes: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78204 283 // Note, clang also defines __GNUC__ macro, so, check __clang also 284 #define NO_UB_SANITIZE __attribute__((no_sanitize_undefined)) // NOLINT(cppcoreguidelines-macro-usage) 285 #else 286 #define NO_UB_SANITIZE __attribute__((no_sanitize("undefined"))) // NOLINT(cppcoreguidelines-macro-usage) 287 #endif 288 #else 289 #define NO_UB_SANITIZE 290 #endif // USE_UB_SANITIZER 291 292 // for clang 293 #if defined(__has_feature) 294 #if __has_feature(address_sanitizer) 295 #define USE_ADDRESS_SANITIZER 296 #endif 297 #endif 298 // for gnu compiler 299 #if defined(__SANITIZE_ADDRESS__) 300 #define USE_ADDRESS_SANITIZER 301 #endif 302 303 #if defined(USE_ADDRESS_SANITIZER) 304 #if __GNUC__ < 8 && !defined(__clang__) 305 // gcc < 8.0 has a bug with attributes: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78204 306 // Note, clang also defines __GNUC__ macro, so, check __clang also 307 #define NO_ADDRESS_SANITIZE __attribute__((no_sanitize_address)) // NOLINT(cppcoreguidelines-macro-usage) 308 #else 309 #define NO_ADDRESS_SANITIZE __attribute__((no_sanitize("address"))) // NOLINT(cppcoreguidelines-macro-usage) 310 #endif 311 #else 312 #define NO_ADDRESS_SANITIZE 313 #endif // USE_ADDRESS_SANITIZER 314 315 #if defined(__has_include) 316 #if __has_include(<filesystem>) 317 #define USE_STD_FILESYSTEM 318 #endif 319 #endif 320 321 // WEAK_SYMBOLS_FOR_LTO is defined if compiling arkbase_lto and unset otherwise 322 #ifdef WEAK_SYMBOLS_FOR_LTO 323 #define WEAK_FOR_LTO_START _Pragma("clang attribute push(__attribute__((weak)), apply_to = function)") 324 #define WEAK_FOR_LTO_END _Pragma("clang attribute pop") 325 #else 326 #define WEAK_FOR_LTO_START 327 #define WEAK_FOR_LTO_END 328 #endif 329 330 #ifndef NDEBUG 331 #define CONSTEXPR_IN_RELEASE 332 #else 333 #define CONSTEXPR_IN_RELEASE constexpr 334 #endif 335 336 #endif // PANDA_LIBPANDABASE_PBASE_MACROS_H 337