mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 08:16:09 +03:00
158 lines
4.8 KiB
C++
158 lines
4.8 KiB
C++
// Copyright 2017 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
|
|
#define BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
|
|
|
|
#include <cassert>
|
|
#include <limits>
|
|
#include <type_traits>
|
|
|
|
#include "base/numerics/safe_conversions.h"
|
|
|
|
#if !defined(__native_client__) && (defined(__ARMEL__) || defined(__arch64__))
|
|
#include "base/numerics/safe_math_arm_impl.h"
|
|
#define BASE_HAS_ASSEMBLER_SAFE_MATH (1)
|
|
#else
|
|
#define BASE_HAS_ASSEMBLER_SAFE_MATH (0)
|
|
#endif
|
|
|
|
namespace base {
|
|
namespace internal {
|
|
|
|
// These are the non-functioning boilerplate implementations of the optimized
|
|
// safe math routines.
|
|
#if !BASE_HAS_ASSEMBLER_SAFE_MATH
|
|
template <typename T, typename U>
|
|
struct CheckedMulFastAsmOp {
|
|
static const bool is_supported = false;
|
|
template <typename V>
|
|
static constexpr bool Do(T, U, V*) {
|
|
// Force a compile failure if instantiated.
|
|
return CheckOnFailure::template HandleFailure<bool>();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
struct ClampedAddFastAsmOp {
|
|
static const bool is_supported = false;
|
|
template <typename V>
|
|
static constexpr V Do(T, U) {
|
|
// Force a compile failure if instantiated.
|
|
return CheckOnFailure::template HandleFailure<V>();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
struct ClampedSubFastAsmOp {
|
|
static const bool is_supported = false;
|
|
template <typename V>
|
|
static constexpr V Do(T, U) {
|
|
// Force a compile failure if instantiated.
|
|
return CheckOnFailure::template HandleFailure<V>();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
struct ClampedMulFastAsmOp {
|
|
static const bool is_supported = false;
|
|
template <typename V>
|
|
static constexpr V Do(T, U) {
|
|
// Force a compile failure if instantiated.
|
|
return CheckOnFailure::template HandleFailure<V>();
|
|
}
|
|
};
|
|
#endif // BASE_HAS_ASSEMBLER_SAFE_MATH
|
|
#undef BASE_HAS_ASSEMBLER_SAFE_MATH
|
|
|
|
template <typename T, typename U>
|
|
struct CheckedAddFastOp {
|
|
static const bool is_supported = true;
|
|
template <typename V>
|
|
__attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
|
|
return !__builtin_add_overflow(x, y, result);
|
|
}
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
struct CheckedSubFastOp {
|
|
static const bool is_supported = true;
|
|
template <typename V>
|
|
__attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
|
|
return !__builtin_sub_overflow(x, y, result);
|
|
}
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
struct CheckedMulFastOp {
|
|
#if defined(__clang__)
|
|
// TODO(jschuh): Get the Clang runtime library issues sorted out so we can
|
|
// support full-width, mixed-sign multiply builtins.
|
|
// https://crbug.com/613003
|
|
// We can support intptr_t, uintptr_t, or a smaller common type.
|
|
static const bool is_supported =
|
|
(IsTypeInRangeForNumericType<intptr_t, T>::value &&
|
|
IsTypeInRangeForNumericType<intptr_t, U>::value) ||
|
|
(IsTypeInRangeForNumericType<uintptr_t, T>::value &&
|
|
IsTypeInRangeForNumericType<uintptr_t, U>::value);
|
|
#else
|
|
static const bool is_supported = true;
|
|
#endif
|
|
template <typename V>
|
|
__attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) {
|
|
return CheckedMulFastAsmOp<T, U>::is_supported
|
|
? CheckedMulFastAsmOp<T, U>::Do(x, y, result)
|
|
: !__builtin_mul_overflow(x, y, result);
|
|
}
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
struct ClampedAddFastOp {
|
|
static const bool is_supported = ClampedAddFastAsmOp<T, U>::is_supported;
|
|
template <typename V>
|
|
__attribute__((always_inline)) static V Do(T x, U y) {
|
|
return ClampedAddFastAsmOp<T, U>::template Do<V>(x, y);
|
|
}
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
struct ClampedSubFastOp {
|
|
static const bool is_supported = ClampedSubFastAsmOp<T, U>::is_supported;
|
|
template <typename V>
|
|
__attribute__((always_inline)) static V Do(T x, U y) {
|
|
return ClampedSubFastAsmOp<T, U>::template Do<V>(x, y);
|
|
}
|
|
};
|
|
|
|
template <typename T, typename U>
|
|
struct ClampedMulFastOp {
|
|
static const bool is_supported = ClampedMulFastAsmOp<T, U>::is_supported;
|
|
template <typename V>
|
|
__attribute__((always_inline)) static V Do(T x, U y) {
|
|
return ClampedMulFastAsmOp<T, U>::template Do<V>(x, y);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct ClampedNegFastOp {
|
|
static const bool is_supported = std::is_signed<T>::value;
|
|
__attribute__((always_inline)) static T Do(T value) {
|
|
// Use this when there is no assembler path available.
|
|
if (!ClampedSubFastAsmOp<T, T>::is_supported) {
|
|
T result;
|
|
return !__builtin_sub_overflow(T(0), value, &result)
|
|
? result
|
|
: std::numeric_limits<T>::max();
|
|
}
|
|
|
|
// Fallback to the normal subtraction path.
|
|
return ClampedSubFastOp<T, T>::template Do<T>(T(0), value);
|
|
}
|
|
};
|
|
|
|
} // namespace internal
|
|
} // namespace base
|
|
|
|
#endif // BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_
|