diff --git a/config.lib b/config.lib index 09fadc1a89..26fa600f52 100644 --- a/config.lib +++ b/config.lib @@ -1914,6 +1914,29 @@ EOL CFLAGS="$CFLAGS -DWITH_BITMATH_BUILTINS" fi + log 2 "executing $cc_host $CFLAGS $LDFLAGS $STATIC_FLAGS -o tmp.config.overflow-builtins -x c++ -" + "$cc_host" $CFLAGS $LDFLAGS $STATIC_FLAGS -o tmp.config.overflow-builtins -x c++ - 2> /dev/null << EOL + #include + int main() { + int64_t a = 0; + int64_t b = 0; + int64_t c = 0; + bool res1 = __builtin_add_overflow(a, b, &c); + bool res2 = __builtin_sub_overflow(a, b, &c); + bool res3 = __builtin_mul_overflow(a, b, &c); + return (res1 || res2 || res3) ? 1 : 0; + } +EOL + ret=$? + rm -f tmp.config.overflow-builtins + log 2 " exit code $ret" + if [ $ret -ne 0 ]; then + log 1 "checking overflow builtins... no" + else + log 1 "checking overflow builtins... found" + CFLAGS="$CFLAGS -DWITH_OVERFLOW_BUILTINS" + fi + if [ "$os" != "CYGWIN" ] && [ "$os" != "HAIKU" ] && [ "$os" != "MORPHOS" ] && [ "$os" != "OSX" ] && [ "$os" != "DOS" ] && [ "$os" != "WINCE" ] && [ "$os" != "PSP" ] && [ "$os" != "OS2" ]; then log 2 "executing $cc_host $CFLAGS $CFLAGS_ENV $LDFLAGS $LDFLAGS_ENV -o tmp.config.demangle -x c++ - -lstdc++" "$cc_host" $CFLAGS $CFLAGS_ENV $LDFLAGS $LDFLAGS_ENV -o tmp.config.demangle -x c++ - -lstdc++ 2> /dev/null << EOL diff --git a/src/core/overflowsafe_type.hpp b/src/core/overflowsafe_type.hpp index eb920c2b26..45b8f48899 100644 --- a/src/core/overflowsafe_type.hpp +++ b/src/core/overflowsafe_type.hpp @@ -46,12 +46,30 @@ public: */ inline OverflowSafeInt& operator += (const OverflowSafeInt& other) { +#ifdef WITH_OVERFLOW_BUILTINS + if (unlikely(__builtin_add_overflow(this->m_value, other.m_value, &this->m_value))) { + this->m_value = (other.m_value < 0) ? T_MIN : T_MAX; + } +#else if ((T_MAX - abs(other.m_value)) < abs(this->m_value) && (this->m_value < 0) == (other.m_value < 0)) { this->m_value = (this->m_value < 0) ? T_MIN : T_MAX ; } else { this->m_value += other.m_value; } +#endif + return *this; + } + + inline OverflowSafeInt& operator -= (const OverflowSafeInt& other) + { +#ifdef WITH_OVERFLOW_BUILTINS + if (unlikely(__builtin_sub_overflow(this->m_value, other.m_value, &this->m_value))) { + this->m_value = (other.m_value < 0) ? T_MAX : T_MIN; + } +#else + *this += (-other); +#endif return *this; } @@ -59,7 +77,6 @@ public: inline OverflowSafeInt operator + (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result += other; return result; } inline OverflowSafeInt operator + (const int other) const { OverflowSafeInt result = *this; result += (int64)other; return result; } inline OverflowSafeInt operator + (const uint other) const { OverflowSafeInt result = *this; result += (int64)other; return result; } - inline OverflowSafeInt& operator -= (const OverflowSafeInt& other) { return *this += (-other); } inline OverflowSafeInt operator - (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result -= other; return result; } inline OverflowSafeInt operator - (const int other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; } inline OverflowSafeInt operator - (const uint other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; } @@ -77,11 +94,17 @@ public: */ inline OverflowSafeInt& operator *= (const int factor) { +#ifdef WITH_OVERFLOW_BUILTINS + if (unlikely(__builtin_mul_overflow(this->m_value, factor, &this->m_value))) { + this->m_value = ((this->m_value < 0) == (factor < 0)) ? T_MAX : T_MIN; + } +#else if (factor != 0 && (T_MAX / abs(factor)) < abs(this->m_value)) { this->m_value = ((this->m_value < 0) == (factor < 0)) ? T_MAX : T_MIN ; } else { this->m_value *= factor ; } +#endif return *this; }