mypyc_util.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #ifndef MYPYC_UTIL_H
  2. #define MYPYC_UTIL_H
  3. #include <Python.h>
  4. #include <frameobject.h>
  5. #include <assert.h>
  6. #if defined(__clang__) || defined(__GNUC__)
  7. #define likely(x) __builtin_expect((x),1)
  8. #define unlikely(x) __builtin_expect((x),0)
  9. #define CPy_Unreachable() __builtin_unreachable()
  10. #else
  11. #define likely(x) (x)
  12. #define unlikely(x) (x)
  13. #define CPy_Unreachable() abort()
  14. #endif
  15. #if defined(__clang__) || defined(__GNUC__)
  16. #define CPy_NOINLINE __attribute__((noinline))
  17. #elif defined(_MSC_VER)
  18. #define CPy_NOINLINE __declspec(noinline)
  19. #else
  20. #define CPy_NOINLINE
  21. #endif
  22. // INCREF and DECREF that assert the pointer is not NULL.
  23. // asserts are disabled in release builds so there shouldn't be a perf hit.
  24. // I'm honestly kind of surprised that this isn't done by default.
  25. #define CPy_INCREF(p) do { assert(p); Py_INCREF(p); } while (0)
  26. #define CPy_DECREF(p) do { assert(p); Py_DECREF(p); } while (0)
  27. // Here just for consistency
  28. #define CPy_XDECREF(p) Py_XDECREF(p)
  29. // Tagged integer -- our representation of Python 'int' objects.
  30. // Small enough integers are represented as unboxed integers (shifted
  31. // left by 1); larger integers (larger than 63 bits on a 64-bit
  32. // platform) are stored as a tagged pointer (PyObject *)
  33. // representing a Python int object, with the lowest bit set.
  34. // Tagged integers are always normalized. A small integer *must not*
  35. // have the tag bit set.
  36. typedef size_t CPyTagged;
  37. typedef size_t CPyPtr;
  38. #define CPY_INT_BITS (CHAR_BIT * sizeof(CPyTagged))
  39. #define CPY_TAGGED_MAX (((Py_ssize_t)1 << (CPY_INT_BITS - 2)) - 1)
  40. #define CPY_TAGGED_MIN (-((Py_ssize_t)1 << (CPY_INT_BITS - 2)))
  41. #define CPY_TAGGED_ABS_MIN (0-(size_t)CPY_TAGGED_MIN)
  42. typedef PyObject CPyModule;
  43. // Tag bit used for long integers
  44. #define CPY_INT_TAG 1
  45. // Error value for signed fixed-width (low-level) integers
  46. #define CPY_LL_INT_ERROR -113
  47. // Error value for unsigned fixed-width (low-level) integers
  48. #define CPY_LL_UINT_ERROR 239
  49. // Error value for floats
  50. #define CPY_FLOAT_ERROR -113.0
  51. typedef void (*CPyVTableItem)(void);
  52. static inline CPyTagged CPyTagged_ShortFromInt(int x) {
  53. return x << 1;
  54. }
  55. static inline CPyTagged CPyTagged_ShortFromSsize_t(Py_ssize_t x) {
  56. return x << 1;
  57. }
  58. // Are we targeting Python 3.12 or newer?
  59. #define CPY_3_12_FEATURES (PY_VERSION_HEX >= 0x030c0000)
  60. #if CPY_3_12_FEATURES
  61. // Same as macros in CPython internal/pycore_long.h, but with a CPY_ prefix
  62. #define CPY_NON_SIZE_BITS 3
  63. #define CPY_SIGN_ZERO 1
  64. #define CPY_SIGN_NEGATIVE 2
  65. #define CPY_SIGN_MASK 3
  66. #define CPY_LONG_DIGIT(o, n) ((o)->long_value.ob_digit[n])
  67. // Only available on Python 3.12 and later
  68. #define CPY_LONG_TAG(o) ((o)->long_value.lv_tag)
  69. #define CPY_LONG_IS_NEGATIVE(o) (((o)->long_value.lv_tag & CPY_SIGN_MASK) == CPY_SIGN_NEGATIVE)
  70. // Only available on Python 3.12 and later
  71. #define CPY_LONG_SIZE(o) ((o)->long_value.lv_tag >> CPY_NON_SIZE_BITS)
  72. // Number of digits; negative for negative ints
  73. #define CPY_LONG_SIZE_SIGNED(o) (CPY_LONG_IS_NEGATIVE(o) ? -CPY_LONG_SIZE(o) : CPY_LONG_SIZE(o))
  74. // Number of digits, assuming int is non-negative
  75. #define CPY_LONG_SIZE_UNSIGNED(o) CPY_LONG_SIZE(o)
  76. static inline void CPyLong_SetUnsignedSize(PyLongObject *o, Py_ssize_t n) {
  77. if (n == 0)
  78. o->long_value.lv_tag = CPY_SIGN_ZERO;
  79. else
  80. o->long_value.lv_tag = n << CPY_NON_SIZE_BITS;
  81. }
  82. #else
  83. #define CPY_LONG_DIGIT(o, n) ((o)->ob_digit[n])
  84. #define CPY_LONG_IS_NEGATIVE(o) (((o)->ob_base.ob_size < 0)
  85. #define CPY_LONG_SIZE_SIGNED(o) ((o)->ob_base.ob_size)
  86. #define CPY_LONG_SIZE_UNSIGNED(o) ((o)->ob_base.ob_size)
  87. static inline void CPyLong_SetUnsignedSize(PyLongObject *o, Py_ssize_t n) {
  88. o->ob_base.ob_size = n;
  89. }
  90. #endif
  91. #endif