gooderp18绿色标准版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 line
6.9KB

  1. /*-------------------------------------------------------------------------
  2. *
  3. * int.h
  4. * Routines to perform integer math, while checking for overflows.
  5. *
  6. * The routines in this file are intended to be well defined C, without
  7. * relying on compiler flags like -fwrapv.
  8. *
  9. * To reduce the overhead of these routines try to use compiler intrinsics
  10. * where available. That's not that important for the 16, 32 bit cases, but
  11. * the 64 bit cases can be considerably faster with intrinsics. In case no
  12. * intrinsics are available 128 bit math is used where available.
  13. *
  14. * Copyright (c) 2017-2019, PostgreSQL Global Development Group
  15. *
  16. * src/include/common/int.h
  17. *
  18. *-------------------------------------------------------------------------
  19. */
  20. #ifndef COMMON_INT_H
  21. #define COMMON_INT_H
  22. /*
  23. * If a + b overflows, return true, otherwise store the result of a + b into
  24. * *result. The content of *result is implementation defined in case of
  25. * overflow.
  26. */
  27. static inline bool
  28. pg_add_s16_overflow(int16 a, int16 b, int16 *result)
  29. {
  30. #if defined(HAVE__BUILTIN_OP_OVERFLOW)
  31. return __builtin_add_overflow(a, b, result);
  32. #else
  33. int32 res = (int32) a + (int32) b;
  34. if (res > PG_INT16_MAX || res < PG_INT16_MIN)
  35. {
  36. *result = 0x5EED; /* to avoid spurious warnings */
  37. return true;
  38. }
  39. *result = (int16) res;
  40. return false;
  41. #endif
  42. }
  43. /*
  44. * If a - b overflows, return true, otherwise store the result of a - b into
  45. * *result. The content of *result is implementation defined in case of
  46. * overflow.
  47. */
  48. static inline bool
  49. pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
  50. {
  51. #if defined(HAVE__BUILTIN_OP_OVERFLOW)
  52. return __builtin_sub_overflow(a, b, result);
  53. #else
  54. int32 res = (int32) a - (int32) b;
  55. if (res > PG_INT16_MAX || res < PG_INT16_MIN)
  56. {
  57. *result = 0x5EED; /* to avoid spurious warnings */
  58. return true;
  59. }
  60. *result = (int16) res;
  61. return false;
  62. #endif
  63. }
  64. /*
  65. * If a * b overflows, return true, otherwise store the result of a * b into
  66. * *result. The content of *result is implementation defined in case of
  67. * overflow.
  68. */
  69. static inline bool
  70. pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
  71. {
  72. #if defined(HAVE__BUILTIN_OP_OVERFLOW)
  73. return __builtin_mul_overflow(a, b, result);
  74. #else
  75. int32 res = (int32) a * (int32) b;
  76. if (res > PG_INT16_MAX || res < PG_INT16_MIN)
  77. {
  78. *result = 0x5EED; /* to avoid spurious warnings */
  79. return true;
  80. }
  81. *result = (int16) res;
  82. return false;
  83. #endif
  84. }
  85. /*
  86. * If a + b overflows, return true, otherwise store the result of a + b into
  87. * *result. The content of *result is implementation defined in case of
  88. * overflow.
  89. */
  90. static inline bool
  91. pg_add_s32_overflow(int32 a, int32 b, int32 *result)
  92. {
  93. #if defined(HAVE__BUILTIN_OP_OVERFLOW)
  94. return __builtin_add_overflow(a, b, result);
  95. #else
  96. int64 res = (int64) a + (int64) b;
  97. if (res > PG_INT32_MAX || res < PG_INT32_MIN)
  98. {
  99. *result = 0x5EED; /* to avoid spurious warnings */
  100. return true;
  101. }
  102. *result = (int32) res;
  103. return false;
  104. #endif
  105. }
  106. /*
  107. * If a - b overflows, return true, otherwise store the result of a - b into
  108. * *result. The content of *result is implementation defined in case of
  109. * overflow.
  110. */
  111. static inline bool
  112. pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
  113. {
  114. #if defined(HAVE__BUILTIN_OP_OVERFLOW)
  115. return __builtin_sub_overflow(a, b, result);
  116. #else
  117. int64 res = (int64) a - (int64) b;
  118. if (res > PG_INT32_MAX || res < PG_INT32_MIN)
  119. {
  120. *result = 0x5EED; /* to avoid spurious warnings */
  121. return true;
  122. }
  123. *result = (int32) res;
  124. return false;
  125. #endif
  126. }
  127. /*
  128. * If a * b overflows, return true, otherwise store the result of a * b into
  129. * *result. The content of *result is implementation defined in case of
  130. * overflow.
  131. */
  132. static inline bool
  133. pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
  134. {
  135. #if defined(HAVE__BUILTIN_OP_OVERFLOW)
  136. return __builtin_mul_overflow(a, b, result);
  137. #else
  138. int64 res = (int64) a * (int64) b;
  139. if (res > PG_INT32_MAX || res < PG_INT32_MIN)
  140. {
  141. *result = 0x5EED; /* to avoid spurious warnings */
  142. return true;
  143. }
  144. *result = (int32) res;
  145. return false;
  146. #endif
  147. }
  148. /*
  149. * If a + b overflows, return true, otherwise store the result of a + b into
  150. * *result. The content of *result is implementation defined in case of
  151. * overflow.
  152. */
  153. static inline bool
  154. pg_add_s64_overflow(int64 a, int64 b, int64 *result)
  155. {
  156. #if defined(HAVE__BUILTIN_OP_OVERFLOW)
  157. return __builtin_add_overflow(a, b, result);
  158. #elif defined(HAVE_INT128)
  159. int128 res = (int128) a + (int128) b;
  160. if (res > PG_INT64_MAX || res < PG_INT64_MIN)
  161. {
  162. *result = 0x5EED; /* to avoid spurious warnings */
  163. return true;
  164. }
  165. *result = (int64) res;
  166. return false;
  167. #else
  168. if ((a > 0 && b > 0 && a > PG_INT64_MAX - b) ||
  169. (a < 0 && b < 0 && a < PG_INT64_MIN - b))
  170. {
  171. *result = 0x5EED; /* to avoid spurious warnings */
  172. return true;
  173. }
  174. *result = a + b;
  175. return false;
  176. #endif
  177. }
  178. /*
  179. * If a - b overflows, return true, otherwise store the result of a - b into
  180. * *result. The content of *result is implementation defined in case of
  181. * overflow.
  182. */
  183. static inline bool
  184. pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
  185. {
  186. #if defined(HAVE__BUILTIN_OP_OVERFLOW)
  187. return __builtin_sub_overflow(a, b, result);
  188. #elif defined(HAVE_INT128)
  189. int128 res = (int128) a - (int128) b;
  190. if (res > PG_INT64_MAX || res < PG_INT64_MIN)
  191. {
  192. *result = 0x5EED; /* to avoid spurious warnings */
  193. return true;
  194. }
  195. *result = (int64) res;
  196. return false;
  197. #else
  198. if ((a < 0 && b > 0 && a < PG_INT64_MIN + b) ||
  199. (a > 0 && b < 0 && a > PG_INT64_MAX + b))
  200. {
  201. *result = 0x5EED; /* to avoid spurious warnings */
  202. return true;
  203. }
  204. *result = a - b;
  205. return false;
  206. #endif
  207. }
  208. /*
  209. * If a * b overflows, return true, otherwise store the result of a * b into
  210. * *result. The content of *result is implementation defined in case of
  211. * overflow.
  212. */
  213. static inline bool
  214. pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
  215. {
  216. #if defined(HAVE__BUILTIN_OP_OVERFLOW)
  217. return __builtin_mul_overflow(a, b, result);
  218. #elif defined(HAVE_INT128)
  219. int128 res = (int128) a * (int128) b;
  220. if (res > PG_INT64_MAX || res < PG_INT64_MIN)
  221. {
  222. *result = 0x5EED; /* to avoid spurious warnings */
  223. return true;
  224. }
  225. *result = (int64) res;
  226. return false;
  227. #else
  228. /*
  229. * Overflow can only happen if at least one value is outside the range
  230. * sqrt(min)..sqrt(max) so check that first as the division can be quite a
  231. * bit more expensive than the multiplication.
  232. *
  233. * Multiplying by 0 or 1 can't overflow of course and checking for 0
  234. * separately avoids any risk of dividing by 0. Be careful about dividing
  235. * INT_MIN by -1 also, note reversing the a and b to ensure we're always
  236. * dividing it by a positive value.
  237. *
  238. */
  239. if ((a > PG_INT32_MAX || a < PG_INT32_MIN ||
  240. b > PG_INT32_MAX || b < PG_INT32_MIN) &&
  241. a != 0 && a != 1 && b != 0 && b != 1 &&
  242. ((a > 0 && b > 0 && a > PG_INT64_MAX / b) ||
  243. (a > 0 && b < 0 && b < PG_INT64_MIN / a) ||
  244. (a < 0 && b > 0 && a < PG_INT64_MIN / b) ||
  245. (a < 0 && b < 0 && a < PG_INT64_MAX / b)))
  246. {
  247. *result = 0x5EED; /* to avoid spurious warnings */
  248. return true;
  249. }
  250. *result = a * b;
  251. return false;
  252. #endif
  253. }
  254. #endif /* COMMON_INT_H */
上海开阖软件有限公司 沪ICP备12045867号-1