xref: /aosp_15_r20/external/angle/src/common/base/anglebase/numerics/safe_math_clang_gcc_impl.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
6 #define BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
7 
8 #include <cassert>
9 #include <limits>
10 #include <type_traits>
11 
12 #include "anglebase/numerics/safe_conversions.h"
13 
14 #if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__))
15 #    include "anglebase/numerics/safe_math_arm_impl.h"
16 #    define BASE_HAS_ASSEMBLER_SAFE_MATH (1)
17 #else
18 #    define BASE_HAS_ASSEMBLER_SAFE_MATH (0)
19 #endif
20 
21 namespace angle
22 {
23 namespace base
24 {
25 namespace internal
26 {
27 
28 // These are the non-functioning boilerplate implementations of the optimized
29 // safe math routines.
30 #if !BASE_HAS_ASSEMBLER_SAFE_MATH
31 template <typename T, typename U>
32 struct CheckedMulFastAsmOp
33 {
34     static const bool is_supported = false;
35     template <typename V>
DoCheckedMulFastAsmOp36     static constexpr bool Do(T, U, V *)
37     {
38         // Force a compile failure if instantiated.
39         return CheckOnFailure::template HandleFailure<bool>();
40     }
41 };
42 
43 template <typename T, typename U>
44 struct ClampedAddFastAsmOp
45 {
46     static const bool is_supported = false;
47     template <typename V>
DoClampedAddFastAsmOp48     static constexpr V Do(T, U)
49     {
50         // Force a compile failure if instantiated.
51         return CheckOnFailure::template HandleFailure<V>();
52     }
53 };
54 
55 template <typename T, typename U>
56 struct ClampedSubFastAsmOp
57 {
58     static const bool is_supported = false;
59     template <typename V>
DoClampedSubFastAsmOp60     static constexpr V Do(T, U)
61     {
62         // Force a compile failure if instantiated.
63         return CheckOnFailure::template HandleFailure<V>();
64     }
65 };
66 
67 template <typename T, typename U>
68 struct ClampedMulFastAsmOp
69 {
70     static const bool is_supported = false;
71     template <typename V>
DoClampedMulFastAsmOp72     static constexpr V Do(T, U)
73     {
74         // Force a compile failure if instantiated.
75         return CheckOnFailure::template HandleFailure<V>();
76     }
77 };
78 #endif  // BASE_HAS_ASSEMBLER_SAFE_MATH
79 #undef BASE_HAS_ASSEMBLER_SAFE_MATH
80 
81 template <typename T, typename U>
82 struct CheckedAddFastOp
83 {
84     static const bool is_supported = true;
85     template <typename V>
DoCheckedAddFastOp86     __attribute__((always_inline)) static constexpr bool Do(T x, U y, V *result)
87     {
88         return !__builtin_add_overflow(x, y, result);
89     }
90 };
91 
92 template <typename T, typename U>
93 struct CheckedSubFastOp
94 {
95     static const bool is_supported = true;
96     template <typename V>
DoCheckedSubFastOp97     __attribute__((always_inline)) static constexpr bool Do(T x, U y, V *result)
98     {
99         return !__builtin_sub_overflow(x, y, result);
100     }
101 };
102 
103 template <typename T, typename U>
104 struct CheckedMulFastOp
105 {
106 #if defined(__clang__)
107     // TODO(jschuh): Get the Clang runtime library issues sorted out so we can
108     // support full-width, mixed-sign multiply builtins.
109     // https://crbug.com/613003
110     // We can support intptr_t, uintptr_t, or a smaller common type.
111     static const bool is_supported = (IsTypeInRangeForNumericType<intptr_t, T>::value &&
112                                       IsTypeInRangeForNumericType<intptr_t, U>::value) ||
113                                      (IsTypeInRangeForNumericType<uintptr_t, T>::value &&
114                                       IsTypeInRangeForNumericType<uintptr_t, U>::value);
115 #else
116     static const bool is_supported = true;
117 #endif
118     template <typename V>
DoCheckedMulFastOp119     __attribute__((always_inline)) static constexpr bool Do(T x, U y, V *result)
120     {
121         return CheckedMulFastAsmOp<T, U>::is_supported ? CheckedMulFastAsmOp<T, U>::Do(x, y, result)
122                                                        : !__builtin_mul_overflow(x, y, result);
123     }
124 };
125 
126 template <typename T, typename U>
127 struct ClampedAddFastOp
128 {
129     static const bool is_supported = ClampedAddFastAsmOp<T, U>::is_supported;
130     template <typename V>
DoClampedAddFastOp131     __attribute__((always_inline)) static V Do(T x, U y)
132     {
133         return ClampedAddFastAsmOp<T, U>::template Do<V>(x, y);
134     }
135 };
136 
137 template <typename T, typename U>
138 struct ClampedSubFastOp
139 {
140     static const bool is_supported = ClampedSubFastAsmOp<T, U>::is_supported;
141     template <typename V>
DoClampedSubFastOp142     __attribute__((always_inline)) static V Do(T x, U y)
143     {
144         return ClampedSubFastAsmOp<T, U>::template Do<V>(x, y);
145     }
146 };
147 
148 template <typename T, typename U>
149 struct ClampedMulFastOp
150 {
151     static const bool is_supported = ClampedMulFastAsmOp<T, U>::is_supported;
152     template <typename V>
DoClampedMulFastOp153     __attribute__((always_inline)) static V Do(T x, U y)
154     {
155         return ClampedMulFastAsmOp<T, U>::template Do<V>(x, y);
156     }
157 };
158 
159 template <typename T>
160 struct ClampedNegFastOp
161 {
162     static const bool is_supported = std::is_signed<T>::value;
DoClampedNegFastOp163     __attribute__((always_inline)) static T Do(T value)
164     {
165         // Use this when there is no assembler path available.
166         if (!ClampedSubFastAsmOp<T, T>::is_supported)
167         {
168             T result;
169             return !__builtin_sub_overflow(T(0), value, &result) ? result
170                                                                  : std::numeric_limits<T>::max();
171         }
172 
173         // Fallback to the normal subtraction path.
174         return ClampedSubFastOp<T, T>::template Do<T>(T(0), value);
175     }
176 };
177 
178 }  // namespace internal
179 }  // namespace base
180 }  // namespace angle
181 
182 #endif  // BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
183