1/**
2 * Copyright (c) 2021-2022 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 LIBPANDABASE_MACROS_H
17#define LIBPANDABASE_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#ifndef PANDA_TARGET_WINDOWS
51// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
52#define PANDA_PUBLIC_API __attribute__((visibility ("default")))
53#else
54#define PANDA_PUBLIC_API __declspec(dllexport)
55#endif
56
57// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
58#define MEMBER_OFFSET(T, F) offsetof(T, F)
59
60#if defined(__cplusplus)
61
62// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
63#define NO_COPY_CTOR(TypeName) \
64    TypeName(const TypeName&) = delete;
65
66// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
67#define NO_COPY_OPERATOR(TypeName) \
68    void operator=(const TypeName&) = delete
69
70// Disabling copy ctor and copy assignment operator.
71// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
72#define NO_COPY_SEMANTIC(TypeName) \
73    NO_COPY_CTOR(TypeName)         \
74    NO_COPY_OPERATOR(TypeName)
75
76// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
77#define NO_MOVE_CTOR(TypeName)                   \
78    /* NOLINTNEXTLINE(misc-macro-parentheses) */ \
79    TypeName(TypeName&&) = delete;
80
81// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
82#define NO_MOVE_OPERATOR(TypeName)               \
83    /* NOLINTNEXTLINE(misc-macro-parentheses) */ \
84    TypeName& operator=(TypeName&&) = delete
85
86// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
87#define NO_MOVE_SEMANTIC(TypeName) \
88    NO_MOVE_CTOR(TypeName)         \
89    NO_MOVE_OPERATOR(TypeName)
90
91// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
92#define DEFAULT_MOVE_CTOR(TypeName)              \
93    /* NOLINTNEXTLINE(misc-macro-parentheses) */ \
94    TypeName(TypeName&&) = default;
95
96// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
97#define DEFAULT_MOVE_OPERATOR(TypeName)          \
98    /* NOLINTNEXTLINE(misc-macro-parentheses) */ \
99    TypeName& operator=(TypeName&&) = default
100
101// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
102#define DEFAULT_MOVE_SEMANTIC(TypeName) \
103    DEFAULT_MOVE_CTOR(TypeName)         \
104    DEFAULT_MOVE_OPERATOR(TypeName)
105
106// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
107#define DEFAULT_COPY_CTOR(TypeName)      \
108    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// NOLINT(cppcoreguidelines-macro-usage)
141#define ABORT_AND_UNREACHABLE()                                      \
142    do {                                                             \
143        std::cerr << "This line should be unreachable" << std::endl; \
144        std::abort();                                                \
145        __builtin_unreachable();                                     \
146    } while (0)
147
148
149// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
150#define CHECK(expr) \
151    do { \
152        if (UNLIKELY(!(expr))) { \
153            std::cerr << "CHECK FAILED: " << #expr; \
154            std::cerr << "          IN: " << __FILE__ << ":" << __LINE__ << ":" << __FUNCTION__ << std::endl; \
155            panda::PrintStack(std::cerr); \
156            std::abort(); \
157        } \
158    } while (0)
159
160// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
161#define CHECK_NOT_NULL(ptr) CHECK((ptr) != nullptr)
162
163#if !defined(NDEBUG)
164
165// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
166#define ASSERT_FAIL(expr) panda::debug::AssertionFail(expr, __FILE__, __LINE__, __FUNCTION__)
167
168// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
169#define ASSERT_OP(lhs, op, rhs) do { \
170        auto __lhs = lhs; \
171        auto __rhs = rhs; \
172        if (UNLIKELY(!(__lhs op __rhs))) { \
173            std::cerr << "CHECK FAILED: " << #lhs << " " #op " " #rhs << std::endl; \
174            std::cerr << "      VALUES: " << __lhs << " " #op " " << __rhs << std::endl; \
175            std::cerr << "          IN: " << __FILE__ << ":" << __LINE__ << ": " << __FUNCTION__ << std::endl; \
176            panda::PrintStack(std::cerr); \
177            std::abort(); \
178        } \
179    } while (0)
180
181// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
182#define CHECK_LE(lhs, rhs) ASSERT_OP(lhs, <=, rhs)
183// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
184#define CHECK_LT(lhs, rhs) ASSERT_OP(lhs, <, rhs)
185// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
186#define CHECK_GE(lhs, rhs) ASSERT_OP(lhs, >=, rhs)
187// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
188#define CHECK_GT(lhs, rhs) ASSERT_OP(lhs, >, rhs)
189// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
190#define CHECK_EQ(lhs, rhs) ASSERT_OP(lhs, ==, rhs)
191// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
192#define CHECK_NE(lhs, rhs) ASSERT_OP(lhs, !=, rhs)
193
194// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
195#define ASSERT(cond) \
196    if (UNLIKELY(!(cond))) { \
197        ASSERT_FAIL(#cond); \
198    }
199
200// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
201#define ASSERT_DO(cond, func)                                  \
202    do {                                                       \
203        if (auto cond_val = cond; UNLIKELY(!(cond_val))) {     \
204            func;                                              \
205            ASSERT_FAIL(#cond);                                \
206        }                                                      \
207    } while (0)
208// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
209#define ASSERT_PRINT(cond, message)                         \
210    do {                                                    \
211        if (auto cond_val = cond; UNLIKELY(!(cond_val))) {  \
212            std::cerr << message << std::endl;              \
213            ASSERT_FAIL(#cond);                             \
214        }                                                   \
215    } while (0)
216// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
217#define ASSERT_RETURN(cond) assert(cond)
218// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
219#define UNREACHABLE()                                                                            \
220    do {                                                                                         \
221        ASSERT_PRINT(false, "This line should be unreachable"); /* NOLINT(misc-static-assert) */ \
222        __builtin_unreachable();                                                                 \
223    } while (0)
224#else  // NDEBUG
225#define ASSERT(cond) static_cast<void>(0) // NOLINT(cppcoreguidelines-macro-usage)
226#define ASSERT_DO(cond, func) static_cast<void>(0) // NOLINT(cppcoreguidelines-macro-usage)
227#define ASSERT_PRINT(cond, message) static_cast<void>(0) // NOLINT(cppcoreguidelines-macro-usage)
228#define ASSERT_RETURN(cond) static_cast<void>(cond) // NOLINT(cppcoreguidelines-macro-usage)
229#define UNREACHABLE() ABORT_AND_UNREACHABLE()  // NOLINT(cppcoreguidelines-macro-usage)
230#define ASSERT_OP(lhs, op, rhs)  // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
231#define CHECK_LE(lhs, rhs)  // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
232#define CHECK_LT(lhs, rhs)  // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
233#define CHECK_GE(lhs, rhs)  // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
234#define CHECK_GT(lhs, rhs)  // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
235#define CHECK_EQ(lhs, rhs)  // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
236#define CHECK_NE(lhs, rhs)  // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
237#endif  // !NDEBUG
238
239// Due to the impossibility of using asserts in constexpr methods
240// we need an extra version of UNREACHABLE macro that can be used in such situations
241#define UNREACHABLE_CONSTEXPR()  ABORT_AND_UNREACHABLE()  // NOLINT(cppcoreguidelines-macro-usage)
242
243#define MERGE_WORDS_X(A, B) A ## B  // NOLINT(cppcoreguidelines-macro-usage)
244#define MERGE_WORDS(A, B) MERGE_WORDS_X(A, B)  // NOLINT(cppcoreguidelines-macro-usage)
245
246#if defined(__has_feature)
247#  if __has_feature(thread_sanitizer)
248#define NO_THREAD_SANITIZE __attribute__((no_sanitize("thread"))) // NOLINT(cppcoreguidelines-macro-usage)
249// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
250#define TSAN_ANNOTATE_HAPPENS_BEFORE(addr) \
251    AnnotateHappensBefore(__FILE__, __LINE__, reinterpret_cast<void *>(addr))
252// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
253#define TSAN_ANNOTATE_HAPPENS_AFTER(addr) \
254    AnnotateHappensAfter(__FILE__, __LINE__, reinterpret_cast<void *>(addr))
255// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
256// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
257#define TSAN_ANNOTATE_IGNORE_WRITES_BEGIN() \
258    AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
259// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
260#define TSAN_ANNOTATE_IGNORE_WRITES_END() \
261    AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
262extern "C" void AnnotateHappensBefore(const char* f, int l, const volatile void* addr);
263extern "C" void AnnotateHappensAfter(const char* f, int l, const volatile void* addr);
264extern "C" void AnnotateIgnoreWritesBegin(const char* f, int l);
265extern "C" void AnnotateIgnoreWritesEnd(const char* f, int l);
266#  else
267#define NO_THREAD_SANITIZE
268#define TSAN_ANNOTATE_HAPPENS_BEFORE(addr)
269#define TSAN_ANNOTATE_HAPPENS_AFTER(addr)
270#define TSAN_ANNOTATE_IGNORE_WRITES_BEGIN()
271#define TSAN_ANNOTATE_IGNORE_WRITES_END()
272#  endif
273#else
274#   ifdef __SANITIZE_THREAD__
275#define NO_THREAD_SANITIZE __attribute__((no_sanitize("thread"))) // NOLINT(cppcoreguidelines-macro-usage)
276// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
277#define TSAN_ANNOTATE_HAPPENS_BEFORE(addr) \
278    AnnotateHappensBefore(__FILE__, __LINE__, reinterpret_cast<void *>(addr))
279// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
280#define TSAN_ANNOTATE_HAPPENS_AFTER(addr) \
281    AnnotateHappensAfter(__FILE__, __LINE__, reinterpret_cast<void *>(addr))
282// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
283// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
284#define TSAN_ANNOTATE_IGNORE_WRITES_BEGIN() \
285    AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
286// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
287#define TSAN_ANNOTATE_IGNORE_WRITES_END() \
288    AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
289extern "C" void AnnotateHappensBefore(const char* f, int l, void* addr);
290extern "C" void AnnotateHappensAfter(const char* f, int l, void* addr);
291extern "C" void AnnotateIgnoreWritesBegin(const char* f, int l);
292extern "C" void AnnotateIgnoreWritesEnd(const char* f, int l);
293#  else
294#define NO_THREAD_SANITIZE
295#define TSAN_ANNOTATE_HAPPENS_BEFORE(addr)
296#define TSAN_ANNOTATE_HAPPENS_AFTER(addr)
297#define TSAN_ANNOTATE_IGNORE_WRITES_BEGIN()
298#define TSAN_ANNOTATE_IGNORE_WRITES_END()
299#  endif
300#endif
301
302#if defined(__has_feature)
303#  if __has_feature(undefined_behavior_sanitizer)
304#define NO_UB_SANITIZE __attribute__((no_sanitize("undefined"))) // NOLINT(cppcoreguidelines-macro-usage)
305#  else
306#define NO_UB_SANITIZE
307#  endif
308#else
309#   ifdef __SANITIZE_UNDEFINED__
310#define NO_UB_SANITIZE __attribute__((no_sanitize("undefined"))) // NOLINT(cppcoreguidelines-macro-usage)
311#  else
312#define NO_UB_SANITIZE
313#  endif
314#endif
315
316#if defined(__has_feature)
317#  if __has_feature(address_sanitizer)
318#define USE_ADDRESS_SANITIZER
319#  endif
320#elif defined(__SANITIZE_ADDRESS__)
321#define USE_ADDRESS_SANITIZER
322#endif
323
324#ifdef USE_ADDRESS_SANITIZER
325#define NO_ADDRESS_SANITIZE __attribute__((no_sanitize("address"))) // NOLINT(cppcoreguidelines-macro-usage)
326#else
327#define NO_ADDRESS_SANITIZE
328#endif  // USE_ADDRESS_SANITIZER
329
330#if defined(__has_include)
331#if __has_include(<filesystem>)
332#define USE_STD_FILESYSTEM
333#endif
334#endif
335
336// WEAK_SYMBOLS_FOR_LTO is defined if compiling arkbase_lto and unset otherwise
337#ifdef WEAK_SYMBOLS_FOR_LTO
338#define WEAK_FOR_LTO_START _Pragma("clang attribute push(__attribute__((weak)), apply_to = function)")
339#define WEAK_FOR_LTO_END   _Pragma("clang attribute pop")
340#else
341#define WEAK_FOR_LTO_START
342#define WEAK_FOR_LTO_END
343#endif
344
345#endif  // LIBPANDABASE_MACROS_H
346