compiler.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. // Copyright © 2018-2019 Ariadne Devos
  3. /* sHT -- architecture-independent compiler magic */
  4. #ifndef _sHT_COMPILER_H
  5. #define _sHT_COMPILER_H
  6. /* Clang or GCC is assumed, see Bug #3 */
  7. #define sHT_likely(b) (__builtin_expect(!!(b), 1))
  8. #define sHT_unlikely(b) (__builtin_expect(!!(b), 0))
  9. /** Can the compiler prove @var{u} is a constant?
  10. There may be false negatives. */
  11. #define sHT_constant_p(u) __builtin_constant_p(u)
  12. /* Let the compiler forget the value of the variable var.
  13. This does not avoid speculation by the processor.
  14. For Spectre mitigations, consider sHT_despeculate.
  15. @var{var} must not be const-qualified. */
  16. #define sHT_hide_var(var) \
  17. do { \
  18. __asm__("" : "=r" (var) : "0" (var)); \
  19. } while (0)
  20. /** Let the compiler believe that value of the variable @var{var} depends upon
  21. @var{dependency}.
  22. Afterwards, the value of @var{var} will be supposedly-dependant upon the
  23. value of @var{dependency}.
  24. @var{var} and @var{dependency} must not be const-qualified. */
  25. #define sHT_depend(var, dependency) \
  26. do { \
  27. __asm__("" : "=X" (var) : "X" (var), "X" (dependency)); \
  28. } while (0)
  29. /** Return @var{val} unchanged, supposedly-dependant upon the value of
  30. @var{dependency}.
  31. Afterwards, the value of @var{var} will be supposedly-dependant upon the
  32. value of @var{dependency}.
  33. @var{var} and @var{dependency} must not be const-qualified. */
  34. #define sHT_depending(val, dependency) \
  35. ({ __typeof__(val) _sHT_dep_val = (val); \
  36. sHT_depend(_sHT_dep_val, dependency); \
  37. _sHT_dep_val; })
  38. /** Evaluate the boolean expression @var{cond}.
  39. @var{cond}: a boolean expression variable in @var{var}
  40. @var{var}: a variable to test, may not be const-qualified
  41. In contrast to a plain C @code{if}, the compiler will not
  42. assume the correct branch is taken on a speculative execution.
  43. Its speculative value will be returned. */
  44. #define sHT_test_hidden(var, cond) \
  45. ((cond) ? ({ sHT_hide_var(var); (_Bool) 1; }) \
  46. : ({ sHT_hide_var(var); (_Bool) 0; }))
  47. /** Evaluate the boolean expression @var{cond}
  48. @var{cond}: a boolean expression variable in @var{var}
  49. @var{x}: a variable to test, may not be const-qualified
  50. @var{y}: another variable to test, may not be const-qualified
  51. In contrast to a plain C @code{if}, the compiler will not
  52. assume the correct branch is taken on a speculative execution.
  53. Its speculative value will be returned. */
  54. #define sHT_test_hidden2(x, y, cond) \
  55. ({\
  56. _Bool _sHT_test_hidden2_ret = (cond); \
  57. sHT_hide_var(x); \
  58. sHT_hide_var(y); \
  59. _sHT_test_hidden2_ret; \
  60. })
  61. /** Reverse taking a pointer to a member.
  62. @var{ptr}: a valid pointer, pointing to an instance of the member
  63. denoted by @var{member}.
  64. @var{type}: a C union or struct type, possibly as a typedef
  65. @var{member}: the name of a member of @var{type}
  66. This concept is taken from Linux.
  67. TODO: compatibility with Intel MMX and other pointer bounds checkers.
  68. Return a pointer to the @var{type} structure, of which a pointer to its
  69. field @var{member} is equal to @var{ptr}. */
  70. #define sHT_container_of(ptr, type, member) \
  71. ((type *) (((char *) ptr) - offsetof(type, member)))
  72. /** Something has gone wrong, stop the current process.
  73. This is only for catching bugs. In particular, it may speculatively
  74. be ignored. (Replacing a possibly repeating bug with a crashing
  75. speculation bug is, from a security perspective, probably fine.)
  76. @var{msg}: a literal string, describing what should have been the case. */
  77. #define sHT_halt(msg) __builtin_trap();
  78. #endif