|  | 
| 10 | 10 | #ifndef LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H | 
| 11 | 11 | #define LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H | 
| 12 | 12 | 
 | 
|  | 13 | +#include "named_pair.h" | 
| 13 | 14 | #include "src/__support/CPP/type_traits.h" | 
| 14 | 15 | 
 | 
| 15 | 16 | namespace __llvm_libc { | 
| @@ -67,59 +68,131 @@ template <typename T> static inline int unsafe_clz(T val) { | 
| 67 | 68 | } | 
| 68 | 69 | 
 | 
| 69 | 70 | // Add with carry | 
|  | 71 | +DEFINE_NAMED_PAIR_TEMPLATE(SumCarry, sum, carry); | 
|  | 72 | + | 
| 70 | 73 | template <typename T> | 
| 71 | 74 | inline constexpr cpp::enable_if_t< | 
| 72 |  | -    cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, T> | 
| 73 |  | -add_with_carry(T a, T b, T carry_in, T &carry_out) { | 
|  | 75 | +    cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, SumCarry<T>> | 
|  | 76 | +add_with_carry(T a, T b, T carry_in) { | 
| 74 | 77 |   T tmp = a + carry_in; | 
| 75 | 78 |   T sum = b + tmp; | 
| 76 |  | -  carry_out = (sum < b) || (tmp < a); | 
| 77 |  | -  return sum; | 
|  | 79 | +  T carry_out = (sum < b) || (tmp < a); | 
|  | 80 | +  return {sum, carry_out}; | 
| 78 | 81 | } | 
| 79 | 82 | 
 | 
| 80 | 83 | #if __has_builtin(__builtin_addc) | 
| 81 | 84 | // https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins | 
| 82 | 85 | 
 | 
| 83 | 86 | template <> | 
| 84 |  | -inline unsigned char add_with_carry<unsigned char>(unsigned char a, | 
| 85 |  | -                                                   unsigned char b, | 
| 86 |  | -                                                   unsigned char carry_in, | 
| 87 |  | -                                                   unsigned char &carry_out) { | 
| 88 |  | -  return __builtin_addcb(a, b, carry_in, &carry_out); | 
|  | 87 | +inline SumCarry<unsigned char> | 
|  | 88 | +add_with_carry<unsigned char>(unsigned char a, unsigned char b, | 
|  | 89 | +                              unsigned char carry_in) { | 
|  | 90 | +  SumCarry<unsigned char> result{0, 0}; | 
|  | 91 | +  result.sum = __builtin_addcb(a, b, carry_in, &result.carry); | 
|  | 92 | +  return result; | 
| 89 | 93 | } | 
| 90 | 94 | 
 | 
| 91 | 95 | template <> | 
| 92 |  | -inline unsigned short | 
|  | 96 | +inline SumCarry<unsigned short> | 
| 93 | 97 | add_with_carry<unsigned short>(unsigned short a, unsigned short b, | 
| 94 |  | -                               unsigned short carry_in, | 
| 95 |  | -                               unsigned short &carry_out) { | 
| 96 |  | -  return __builtin_addcs(a, b, carry_in, &carry_out); | 
|  | 98 | +                               unsigned short carry_in) { | 
|  | 99 | +  SumCarry<unsigned short> result{0, 0}; | 
|  | 100 | +  result.sum = __builtin_addcs(a, b, carry_in, &result.carry); | 
|  | 101 | +  return result; | 
| 97 | 102 | } | 
| 98 | 103 | 
 | 
| 99 | 104 | template <> | 
| 100 |  | -inline unsigned int add_with_carry<unsigned int>(unsigned int a, unsigned int b, | 
| 101 |  | -                                                 unsigned int carry_in, | 
| 102 |  | -                                                 unsigned int &carry_out) { | 
| 103 |  | -  return __builtin_addc(a, b, carry_in, &carry_out); | 
|  | 105 | +inline SumCarry<unsigned int> | 
|  | 106 | +add_with_carry<unsigned int>(unsigned int a, unsigned int b, | 
|  | 107 | +                             unsigned int carry_in) { | 
|  | 108 | +  SumCarry<unsigned int> result{0, 0}; | 
|  | 109 | +  result.sum = __builtin_addc(a, b, carry_in, &result.carry); | 
|  | 110 | +  return result; | 
| 104 | 111 | } | 
| 105 | 112 | 
 | 
| 106 | 113 | template <> | 
| 107 |  | -inline unsigned long add_with_carry<unsigned long>(unsigned long a, | 
| 108 |  | -                                                   unsigned long b, | 
| 109 |  | -                                                   unsigned long carry_in, | 
| 110 |  | -                                                   unsigned long &carry_out) { | 
| 111 |  | -  return __builtin_addcl(a, b, carry_in, &carry_out); | 
|  | 114 | +inline SumCarry<unsigned long> | 
|  | 115 | +add_with_carry<unsigned long>(unsigned long a, unsigned long b, | 
|  | 116 | +                              unsigned long carry_in) { | 
|  | 117 | +  SumCarry<unsigned long> result{0, 0}; | 
|  | 118 | +  result.sum = __builtin_addcl(a, b, carry_in, &result.carry); | 
|  | 119 | +  return result; | 
| 112 | 120 | } | 
| 113 | 121 | 
 | 
| 114 | 122 | template <> | 
| 115 |  | -inline unsigned long long | 
|  | 123 | +inline SumCarry<unsigned long long> | 
| 116 | 124 | add_with_carry<unsigned long long>(unsigned long long a, unsigned long long b, | 
| 117 |  | -                                   unsigned long long carry_in, | 
| 118 |  | -                                   unsigned long long &carry_out) { | 
| 119 |  | -  return __builtin_addcll(a, b, carry_in, &carry_out); | 
|  | 125 | +                                   unsigned long long carry_in) { | 
|  | 126 | +  SumCarry<unsigned long long> result{0, 0}; | 
|  | 127 | +  result.sum = __builtin_addcll(a, b, carry_in, &result.carry); | 
|  | 128 | +  return result; | 
| 120 | 129 | } | 
|  | 130 | + | 
| 121 | 131 | #endif // __has_builtin(__builtin_addc) | 
| 122 | 132 | 
 | 
|  | 133 | +// Subtract with borrow | 
|  | 134 | +DEFINE_NAMED_PAIR_TEMPLATE(DiffBorrow, diff, borrow); | 
|  | 135 | + | 
|  | 136 | +template <typename T> | 
|  | 137 | +inline constexpr cpp::enable_if_t< | 
|  | 138 | +    cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, DiffBorrow<T>> | 
|  | 139 | +sub_with_borrow(T a, T b, T borrow_in) { | 
|  | 140 | +  T tmp = a - b; | 
|  | 141 | +  T diff = tmp - borrow_in; | 
|  | 142 | +  T borrow_out = (diff > tmp) || (tmp > a); | 
|  | 143 | +  return {diff, borrow_out}; | 
|  | 144 | +} | 
|  | 145 | + | 
|  | 146 | +#if __has_builtin(__builtin_subc) | 
|  | 147 | +// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins | 
|  | 148 | + | 
|  | 149 | +template <> | 
|  | 150 | +inline DiffBorrow<unsigned char> | 
|  | 151 | +sub_with_borrow<unsigned char>(unsigned char a, unsigned char b, | 
|  | 152 | +                               unsigned char borrow_in) { | 
|  | 153 | +  DiffBorrow<unsigned char> result{0, 0}; | 
|  | 154 | +  result.diff = __builtin_subcb(a, b, borrow_in, &result.borrow); | 
|  | 155 | +  return result; | 
|  | 156 | +} | 
|  | 157 | + | 
|  | 158 | +template <> | 
|  | 159 | +inline DiffBorrow<unsigned short> | 
|  | 160 | +sub_with_borrow<unsigned short>(unsigned short a, unsigned short b, | 
|  | 161 | +                                unsigned short borrow_in) { | 
|  | 162 | +  DiffBorrow<unsigned short> result{0, 0}; | 
|  | 163 | +  result.diff = __builtin_subcs(a, b, borrow_in, &result.borrow); | 
|  | 164 | +  return result; | 
|  | 165 | +} | 
|  | 166 | + | 
|  | 167 | +template <> | 
|  | 168 | +inline DiffBorrow<unsigned int> | 
|  | 169 | +sub_with_borrow<unsigned int>(unsigned int a, unsigned int b, | 
|  | 170 | +                              unsigned int borrow_in) { | 
|  | 171 | +  DiffBorrow<unsigned int> result{0, 0}; | 
|  | 172 | +  result.diff = __builtin_subc(a, b, borrow_in, &result.borrow); | 
|  | 173 | +  return result; | 
|  | 174 | +} | 
|  | 175 | + | 
|  | 176 | +template <> | 
|  | 177 | +inline DiffBorrow<unsigned long> | 
|  | 178 | +sub_with_borrow<unsigned long>(unsigned long a, unsigned long b, | 
|  | 179 | +                               unsigned long borrow_in) { | 
|  | 180 | +  DiffBorrow<unsigned long> result{0, 0}; | 
|  | 181 | +  result.diff = __builtin_subcl(a, b, borrow_in, &result.borrow); | 
|  | 182 | +  return result; | 
|  | 183 | +} | 
|  | 184 | + | 
|  | 185 | +template <> | 
|  | 186 | +inline DiffBorrow<unsigned long long> | 
|  | 187 | +sub_with_borrow<unsigned long long>(unsigned long long a, unsigned long long b, | 
|  | 188 | +                                    unsigned long long borrow_in) { | 
|  | 189 | +  DiffBorrow<unsigned long long> result{0, 0}; | 
|  | 190 | +  result.diff = __builtin_subcll(a, b, borrow_in, &result.borrow); | 
|  | 191 | +  return result; | 
|  | 192 | +} | 
|  | 193 | + | 
|  | 194 | +#endif // __has_builtin(__builtin_subc) | 
|  | 195 | + | 
| 123 | 196 | } // namespace __llvm_libc | 
| 124 | 197 | 
 | 
| 125 | 198 | #endif // LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H | 
0 commit comments