// 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 #include #include #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 struct CheckedMulFastAsmOp { static const bool is_supported = false; template static constexpr bool Do(T, U, V*) { // Force a compile failure if instantiated. return CheckOnFailure::template HandleFailure(); } }; template struct ClampedAddFastAsmOp { static const bool is_supported = false; template static constexpr V Do(T, U) { // Force a compile failure if instantiated. return CheckOnFailure::template HandleFailure(); } }; template struct ClampedSubFastAsmOp { static const bool is_supported = false; template static constexpr V Do(T, U) { // Force a compile failure if instantiated. return CheckOnFailure::template HandleFailure(); } }; template struct ClampedMulFastAsmOp { static const bool is_supported = false; template static constexpr V Do(T, U) { // Force a compile failure if instantiated. return CheckOnFailure::template HandleFailure(); } }; #endif // BASE_HAS_ASSEMBLER_SAFE_MATH #undef BASE_HAS_ASSEMBLER_SAFE_MATH template struct CheckedAddFastOp { static const bool is_supported = true; template __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) { return !__builtin_add_overflow(x, y, result); } }; template struct CheckedSubFastOp { static const bool is_supported = true; template __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) { return !__builtin_sub_overflow(x, y, result); } }; template 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::value && IsTypeInRangeForNumericType::value) || (IsTypeInRangeForNumericType::value && IsTypeInRangeForNumericType::value); #else static const bool is_supported = true; #endif template __attribute__((always_inline)) static constexpr bool Do(T x, U y, V* result) { return CheckedMulFastAsmOp::is_supported ? CheckedMulFastAsmOp::Do(x, y, result) : !__builtin_mul_overflow(x, y, result); } }; template struct ClampedAddFastOp { static const bool is_supported = ClampedAddFastAsmOp::is_supported; template __attribute__((always_inline)) static V Do(T x, U y) { return ClampedAddFastAsmOp::template Do(x, y); } }; template struct ClampedSubFastOp { static const bool is_supported = ClampedSubFastAsmOp::is_supported; template __attribute__((always_inline)) static V Do(T x, U y) { return ClampedSubFastAsmOp::template Do(x, y); } }; template struct ClampedMulFastOp { static const bool is_supported = ClampedMulFastAsmOp::is_supported; template __attribute__((always_inline)) static V Do(T x, U y) { return ClampedMulFastAsmOp::template Do(x, y); } }; template struct ClampedNegFastOp { static const bool is_supported = std::is_signed::value; __attribute__((always_inline)) static T Do(T value) { // Use this when there is no assembler path available. if (!ClampedSubFastAsmOp::is_supported) { T result; return !__builtin_sub_overflow(T(0), value, &result) ? result : std::numeric_limits::max(); } // Fallback to the normal subtraction path. return ClampedSubFastOp::template Do(T(0), value); } }; } // namespace internal } // namespace base #endif // BASE_NUMERICS_SAFE_MATH_CLANG_GCC_IMPL_H_