Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
safe_math_clang_gcc_impl.h
Go to the documentation of this file.
1// Copyright 2024 The PDFium Authors
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 CORE_FXCRT_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
6#define CORE_FXCRT_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
7
8#include <cassert>
9#include <limits>
10#include <type_traits>
11
12#include "core/fxcrt/numerics/safe_conversions.h"
13
14#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__))
15#include "core/fxcrt/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
21namespace pdfium {
22namespace internal {
23
24// These are the non-functioning boilerplate implementations of the optimized
25// safe math routines.
27template <typename T, typename U>
29 static const bool is_supported = false;
30 template <typename V>
31 static constexpr bool Do(T, U, V*) {
32 // Force a compile failure if instantiated.
33 return CheckOnFailure::template HandleFailure<bool>();
34 }
35};
36
37template <typename T, typename U>
39 static const bool is_supported = false;
40 template <typename V>
41 static constexpr V Do(T, U) {
42 // Force a compile failure if instantiated.
43 return CheckOnFailure::template HandleFailure<V>();
44 }
45};
46
47template <typename T, typename U>
49 static const bool is_supported = false;
50 template <typename V>
51 static constexpr V Do(T, U) {
52 // Force a compile failure if instantiated.
53 return CheckOnFailure::template HandleFailure<V>();
54 }
55};
56
57template <typename T, typename U>
59 static const bool is_supported = false;
60 template <typename V>
61 static constexpr V Do(T, U) {
62 // Force a compile failure if instantiated.
63 return CheckOnFailure::template HandleFailure<V>();
64 }
65};
66#endif // BASE_HAS_ASSEMBLER_SAFE_MATH
67#undef BASE_HAS_ASSEMBLER_SAFE_MATH
68
69template <typename T, typename U>
70struct CheckedAddFastOp {
71 static const bool is_supported = true;
72 template <typename V>
73 __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
74 return !__builtin_add_overflow(x, y, result);
75 }
76};
77
78template <typename T, typename U>
79struct CheckedSubFastOp {
80 static const bool is_supported = true;
81 template <typename V>
82 __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
83 return !__builtin_sub_overflow(x, y, result);
84 }
85};
86
87template <typename T, typename U>
88struct CheckedMulFastOp {
89#if defined(__clang__)
90 // TODO(jschuh): Get the Clang runtime library issues sorted out so we can
91 // support full-width, mixed-sign multiply builtins.
92 // https://crbug.com/613003
93 // We can support intptr_t, uintptr_t, or a smaller common type.
94 static const bool is_supported =
95 (IsTypeInRangeForNumericType<intptr_t, T>::value &&
96 IsTypeInRangeForNumericType<intptr_t, U>::value) ||
97 (IsTypeInRangeForNumericType<uintptr_t, T>::value &&
98 IsTypeInRangeForNumericType<uintptr_t, U>::value);
99#else
100 static const bool is_supported = true;
101#endif
102 template <typename V>
103 __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
104 return CheckedMulFastAsmOp<T, U>::is_supported
105 ? CheckedMulFastAsmOp<T, U>::Do(x, y, result)
106 : !__builtin_mul_overflow(x, y, result);
107 }
108};
109
110template <typename T, typename U>
111struct ClampedAddFastOp {
112 static const bool is_supported = ClampedAddFastAsmOp<T, U>::is_supported;
113 template <typename V>
114 __attribute__((always_inline)) static V Do(T x, U y) {
115 return ClampedAddFastAsmOp<T, U>::template Do<V>(x, y);
116 }
117};
118
119template <typename T, typename U>
120struct ClampedSubFastOp {
121 static const bool is_supported = ClampedSubFastAsmOp<T, U>::is_supported;
122 template <typename V>
123 __attribute__((always_inline)) static V Do(T x, U y) {
124 return ClampedSubFastAsmOp<T, U>::template Do<V>(x, y);
125 }
126};
127
128template <typename T, typename U>
129struct ClampedMulFastOp {
130 static const bool is_supported = ClampedMulFastAsmOp<T, U>::is_supported;
131 template <typename V>
132 __attribute__((always_inline)) static V Do(T x, U y) {
133 return ClampedMulFastAsmOp<T, U>::template Do<V>(x, y);
134 }
135};
136
137template <typename T>
138struct ClampedNegFastOp {
139 static const bool is_supported = std::is_signed<T>::value;
140 __attribute__((always_inline)) static T Do(T value) {
141 // Use this when there is no assembler path available.
142 if (!ClampedSubFastAsmOp<T, T>::is_supported) {
143 T result;
144 return !__builtin_sub_overflow(T(0), value, &result)
145 ? result
146 : std::numeric_limits<T>::max();
147 }
148
149 // Fallback to the normal subtraction path.
150 return ClampedSubFastOp<T, T>::template Do<T>(T(0), value);
151 }
152};
153
154} // namespace internal
155} // namespace pdfium
156
157#endif // CORE_FXCRT_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
#define BASE_HAS_ASSEMBLER_SAFE_MATH
__attribute__((always_inline)) static const expr bool Do(T x
static constexpr bool Do(T x, U y, V *result)
__attribute__((always_inline)) static const expr bool Do(T x
__attribute__((always_inline)) static const expr bool Do(T x
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static T Do(T value)
__attribute__((always_inline)) static V Do(T x
__attribute__((always_inline)) static V Do(T x