123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- // Copyright © 2018-2019 Ariadne Devos
- /* sHT -- architecture-independent compiler magic */
- #ifndef _sHT_COMPILER_H
- #define _sHT_COMPILER_H
- /* Clang or GCC is assumed, see Bug #3 */
- #define sHT_likely(b) (__builtin_expect(!!(b), 1))
- #define sHT_unlikely(b) (__builtin_expect(!!(b), 0))
- /** Can the compiler prove @var{u} is a constant?
- There may be false negatives. */
- #define sHT_constant_p(u) __builtin_constant_p(u)
- /* Let the compiler forget the value of the variable var.
- This does not avoid speculation by the processor.
- For Spectre mitigations, consider sHT_despeculate.
- @var{var} must not be const-qualified. */
- #define sHT_hide_var(var) \
- do { \
- __asm__("" : "=r" (var) : "0" (var)); \
- } while (0)
- /** Let the compiler believe that value of the variable @var{var} depends upon
- @var{dependency}.
- Afterwards, the value of @var{var} will be supposedly-dependant upon the
- value of @var{dependency}.
- @var{var} and @var{dependency} must not be const-qualified. */
- #define sHT_depend(var, dependency) \
- do { \
- __asm__("" : "=X" (var) : "X" (var), "X" (dependency)); \
- } while (0)
- /** Return @var{val} unchanged, supposedly-dependant upon the value of
- @var{dependency}.
- Afterwards, the value of @var{var} will be supposedly-dependant upon the
- value of @var{dependency}.
- @var{var} and @var{dependency} must not be const-qualified. */
- #define sHT_depending(val, dependency) \
- ({ __typeof__(val) _sHT_dep_val = (val); \
- sHT_depend(_sHT_dep_val, dependency); \
- _sHT_dep_val; })
- /** Evaluate the boolean expression @var{cond}.
- @var{cond}: a boolean expression variable in @var{var}
- @var{var}: a variable to test, may not be const-qualified
- In contrast to a plain C @code{if}, the compiler will not
- assume the correct branch is taken on a speculative execution.
- Its speculative value will be returned. */
- #define sHT_test_hidden(var, cond) \
- ((cond) ? ({ sHT_hide_var(var); (_Bool) 1; }) \
- : ({ sHT_hide_var(var); (_Bool) 0; }))
- /** Evaluate the boolean expression @var{cond}
- @var{cond}: a boolean expression variable in @var{var}
- @var{x}: a variable to test, may not be const-qualified
- @var{y}: another variable to test, may not be const-qualified
- In contrast to a plain C @code{if}, the compiler will not
- assume the correct branch is taken on a speculative execution.
- Its speculative value will be returned. */
- #define sHT_test_hidden2(x, y, cond) \
- ({\
- _Bool _sHT_test_hidden2_ret = (cond); \
- sHT_hide_var(x); \
- sHT_hide_var(y); \
- _sHT_test_hidden2_ret; \
- })
- /** Reverse taking a pointer to a member.
- @var{ptr}: a valid pointer, pointing to an instance of the member
- denoted by @var{member}.
- @var{type}: a C union or struct type, possibly as a typedef
- @var{member}: the name of a member of @var{type}
- This concept is taken from Linux.
- TODO: compatibility with Intel MMX and other pointer bounds checkers.
- Return a pointer to the @var{type} structure, of which a pointer to its
- field @var{member} is equal to @var{ptr}. */
- #define sHT_container_of(ptr, type, member) \
- ((type *) (((char *) ptr) - offsetof(type, member)))
- /** Something has gone wrong, stop the current process.
- This is only for catching bugs. In particular, it may speculatively
- be ignored. (Replacing a possibly repeating bug with a crashing
- speculation bug is, from a security perspective, probably fine.)
- @var{msg}: a literal string, describing what should have been the case. */
- #define sHT_halt(msg) __builtin_trap();
- #endif
|