compiler.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* s2 - architecture-independent compiler magic
  2. Copyright (C) 2018 Ariadne Devos
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. #ifndef _sHT_COMPILER_H
  14. #define _sHT_COMPILER_H
  15. /* Clang or GCC is assumed, see Bug #3 */
  16. #define sHT_likely(b) (__builtin_expect(!!(b), 1))
  17. #define sHT_unlikely(b) (__builtin_expect(!!(b), 0))
  18. /* Let the compiler forget the value of the variable var.
  19. This does not avoid speculation by the processor.
  20. For Spectre mitigations, consider sHT_despeculate.
  21. @var{var} must not be const-qualified. */
  22. #define sHT_hide_var(var) \
  23. do { \
  24. __asm__("" : "=r" (var) : "0" (var)); \
  25. } while (0)
  26. /** Let the compiler believe that value of the variable @var{var} depends upon
  27. @var{dependency}.
  28. Afterwards, the value of @var{var} will be supposedly-dependant upon the
  29. value of @var{dependency}.
  30. @var{var} and @var{dependency} must not be const-qualified. */
  31. #define sHT_depend(var, dependency) \
  32. do { \
  33. __asm__("" : "=X" (var) : "X" (var), "X" (dependency)); \
  34. } while (0)
  35. /** Return @var{val} unchanged, supposedly-dependant upon the value of
  36. @var{dependency}.
  37. Afterwards, the value of @var{var} will be supposedly-dependant upon the
  38. value of @var{dependency}.
  39. @var{var} and @var{dependency} must not be const-qualified. */
  40. #define sHT_depending(val, dependency) \
  41. ({ __typeof__(val) _sHT_dep_val = (val); \
  42. sHT_depend(_sHT_dep_val, dependency); \
  43. _sHT_dep_val; })
  44. /** Evaluate the boolean expression @var{cond}.
  45. @var{cond}: a boolean expression variable in @var{var}
  46. @var{var}: a variable to test, may not be const-qualified
  47. In contrast to a plain C @code{if}, the compiler will not
  48. assume the correct branch is taken on a speculative execution.
  49. Its speculative value will be returned. */
  50. #define sHT_test_hidden(var, cond) \
  51. ((cond) ? ({ sHT_hide_var(var); (_Bool) 1; }) \
  52. : ({ sHT_hide_var(var); (_Bool) 0; }))
  53. /** Evaluate the boolean expression @var{cond}
  54. @var{cond}: a boolean expression variable in @var{var}
  55. @var{x}: a variable to test, may not be const-qualified
  56. @var{y}: another variable to test, may not be const-qualified
  57. In contrast to a plain C @code{if}, the compiler will not
  58. assume the correct branch is taken on a speculative execution.
  59. Its speculative value will be returned. */
  60. #define sHT_test_hidden2(x, y, cond) \
  61. ({\
  62. _Bool _sHT_test_hidden2_ret = (cond); \
  63. sHT_hide_var(x); \
  64. sHT_hide_var(y); \
  65. _sHT_test_hidden2_ret; \
  66. })
  67. /** Reverse taking a pointer to a member.
  68. @var{ptr}: a valid pointer, pointing to an instance of the member
  69. denoted by @var{member}.
  70. @var{type}: a C union or struct type, possibly as a typedef
  71. @var{member}: the name of a member of @var{type}
  72. This concept is taken from Linux.
  73. TODO: compatibility with Intel MMX and other pointer bounds checkers.
  74. Return a pointer to the @var{type} structure, of which a pointer to its
  75. field @var{member} is equal to @var{ptr}. */
  76. #define sHT_container_of(ptr, type, member) \
  77. ((type *) (((char *) ptr) - offsetof(type, member)))
  78. /** Something has gone wrong, stop the current process.
  79. This is only for catching bugs. In particular, it may speculatively
  80. be ignored. (Replacing a possibly repeating bug with a crashing
  81. speculation bug is, from a security perspective, probably fine.)
  82. @var{msg}: a literal string, describing what should have been the case. */
  83. #define sHT_halt(msg) __builtin_trap();
  84. #endif