1351282Sdim//===-- internal_defs.h -----------------------------------------*- C++ -*-===//
2351282Sdim//
3351282Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4351282Sdim// See https://llvm.org/LICENSE.txt for license information.
5351282Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6351282Sdim//
7351282Sdim//===----------------------------------------------------------------------===//
8351282Sdim
9351282Sdim#ifndef SCUDO_INTERNAL_DEFS_H_
10351282Sdim#define SCUDO_INTERNAL_DEFS_H_
11351282Sdim
12351282Sdim#include "platform.h"
13351282Sdim
14351282Sdim#include <stdint.h>
15351282Sdim
16351282Sdim#ifndef SCUDO_DEBUG
17351282Sdim#define SCUDO_DEBUG 0
18351282Sdim#endif
19351282Sdim
20351282Sdim#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
21351282Sdim
22351282Sdim// String related macros.
23351282Sdim
24351282Sdim#define STRINGIFY_(S) #S
25351282Sdim#define STRINGIFY(S) STRINGIFY_(S)
26351282Sdim#define CONCATENATE_(S, C) S##C
27351282Sdim#define CONCATENATE(S, C) CONCATENATE_(S, C)
28351282Sdim
29351282Sdim// Attributes & builtins related macros.
30351282Sdim
31351282Sdim#define INTERFACE __attribute__((visibility("default")))
32351282Sdim#define WEAK __attribute__((weak))
33351282Sdim#define ALWAYS_INLINE inline __attribute__((always_inline))
34351282Sdim#define ALIAS(X) __attribute__((alias(X)))
35351282Sdim// Please only use the ALIGNED macro before the type. Using ALIGNED after the
36351282Sdim// variable declaration is not portable.
37351282Sdim#define ALIGNED(X) __attribute__((aligned(X)))
38351282Sdim#define FORMAT(F, A) __attribute__((format(printf, F, A)))
39351282Sdim#define NOINLINE __attribute__((noinline))
40351282Sdim#define NORETURN __attribute__((noreturn))
41351282Sdim#define THREADLOCAL __thread
42351282Sdim#define LIKELY(X) __builtin_expect(!!(X), 1)
43351282Sdim#define UNLIKELY(X) __builtin_expect(!!(X), 0)
44351282Sdim#if defined(__i386__) || defined(__x86_64__)
45351282Sdim// __builtin_prefetch(X) generates prefetchnt0 on x86
46351282Sdim#define PREFETCH(X) __asm__("prefetchnta (%0)" : : "r"(X))
47351282Sdim#else
48351282Sdim#define PREFETCH(X) __builtin_prefetch(X)
49351282Sdim#endif
50351282Sdim#define UNUSED __attribute__((unused))
51351282Sdim#define USED __attribute__((used))
52351282Sdim#define NOEXCEPT noexcept
53351282Sdim
54351282Sdimnamespace scudo {
55351282Sdim
56351282Sdimtypedef unsigned long uptr;
57351282Sdimtypedef unsigned char u8;
58351282Sdimtypedef unsigned short u16;
59351282Sdimtypedef unsigned int u32;
60351282Sdimtypedef unsigned long long u64;
61360784Sdimtypedef signed long sptr;
62351282Sdimtypedef signed char s8;
63351282Sdimtypedef signed short s16;
64351282Sdimtypedef signed int s32;
65351282Sdimtypedef signed long long s64;
66351282Sdim
67351282Sdim// The following two functions have platform specific implementations.
68351282Sdimvoid outputRaw(const char *Buffer);
69351282Sdimvoid NORETURN die();
70351282Sdim
71351282Sdim#define RAW_CHECK_MSG(Expr, Msg)                                               \
72351282Sdim  do {                                                                         \
73351282Sdim    if (UNLIKELY(!(Expr))) {                                                   \
74351282Sdim      outputRaw(Msg);                                                          \
75351282Sdim      die();                                                                   \
76351282Sdim    }                                                                          \
77351282Sdim  } while (false)
78351282Sdim
79351282Sdim#define RAW_CHECK(Expr) RAW_CHECK_MSG(Expr, #Expr)
80351282Sdim
81351282Sdimvoid NORETURN reportCheckFailed(const char *File, int Line,
82351282Sdim                                const char *Condition, u64 Value1, u64 Value2);
83351282Sdim
84351282Sdim#define CHECK_IMPL(C1, Op, C2)                                                 \
85351282Sdim  do {                                                                         \
86360784Sdim    scudo::u64 V1 = (scudo::u64)(C1);                                          \
87360784Sdim    scudo::u64 V2 = (scudo::u64)(C2);                                          \
88351282Sdim    if (UNLIKELY(!(V1 Op V2))) {                                               \
89360784Sdim      scudo::reportCheckFailed(__FILE__, __LINE__,                             \
90360784Sdim                               "(" #C1 ") " #Op " (" #C2 ")", V1, V2);         \
91360784Sdim      scudo::die();                                                            \
92351282Sdim    }                                                                          \
93351282Sdim  } while (false)
94351282Sdim
95351282Sdim#define CHECK(A) CHECK_IMPL((A), !=, 0)
96351282Sdim#define CHECK_EQ(A, B) CHECK_IMPL((A), ==, (B))
97351282Sdim#define CHECK_NE(A, B) CHECK_IMPL((A), !=, (B))
98351282Sdim#define CHECK_LT(A, B) CHECK_IMPL((A), <, (B))
99351282Sdim#define CHECK_LE(A, B) CHECK_IMPL((A), <=, (B))
100351282Sdim#define CHECK_GT(A, B) CHECK_IMPL((A), >, (B))
101351282Sdim#define CHECK_GE(A, B) CHECK_IMPL((A), >=, (B))
102351282Sdim
103351282Sdim#if SCUDO_DEBUG
104351282Sdim#define DCHECK(A) CHECK(A)
105351282Sdim#define DCHECK_EQ(A, B) CHECK_EQ(A, B)
106351282Sdim#define DCHECK_NE(A, B) CHECK_NE(A, B)
107351282Sdim#define DCHECK_LT(A, B) CHECK_LT(A, B)
108351282Sdim#define DCHECK_LE(A, B) CHECK_LE(A, B)
109351282Sdim#define DCHECK_GT(A, B) CHECK_GT(A, B)
110351282Sdim#define DCHECK_GE(A, B) CHECK_GE(A, B)
111351282Sdim#else
112351282Sdim#define DCHECK(A)
113351282Sdim#define DCHECK_EQ(A, B)
114351282Sdim#define DCHECK_NE(A, B)
115351282Sdim#define DCHECK_LT(A, B)
116351282Sdim#define DCHECK_LE(A, B)
117351282Sdim#define DCHECK_GT(A, B)
118351282Sdim#define DCHECK_GE(A, B)
119351282Sdim#endif
120351282Sdim
121351282Sdim// The superfluous die() call effectively makes this macro NORETURN.
122351282Sdim#define UNREACHABLE(Msg)                                                       \
123351282Sdim  do {                                                                         \
124351282Sdim    CHECK(0 && Msg);                                                           \
125351282Sdim    die();                                                                     \
126351282Sdim  } while (0)
127351282Sdim
128351282Sdim} // namespace scudo
129351282Sdim
130351282Sdim#endif // SCUDO_INTERNAL_DEFS_H_
131