diff --git a/llvm/lib/FileCheck/FileCheck.cpp b/llvm/lib/FileCheck/FileCheck.cpp --- a/llvm/lib/FileCheck/FileCheck.cpp +++ b/llvm/lib/FileCheck/FileCheck.cpp @@ -155,48 +155,25 @@ return ExpressionValue(UnsignedValue); } -static int64_t getAsSigned(uint64_t UnsignedValue) { - // Use memcpy to reinterpret the bitpattern in Value since casting to - // signed is implementation-defined if the unsigned value is too big to be - // represented in the signed type and using an union violates type aliasing - // rules. - int64_t SignedValue; - memcpy(&SignedValue, &UnsignedValue, sizeof(SignedValue)); - return SignedValue; -} - Expected ExpressionValue::getSignedValue() const { - if (Negative) - return getAsSigned(Value); - - if (Value > (uint64_t)std::numeric_limits::max()) + std::optional SignedValue = Value.trySExtValue(); + if (!SignedValue) return make_error(); - - // Value is in the representable range of int64_t so we can use cast. - return static_cast(Value); + return *SignedValue; } Expected ExpressionValue::getUnsignedValue() const { - if (Negative) + std::optional UnsignedValue = Value.tryZExtValue(); + if (!UnsignedValue) return make_error(); - return Value; + return *UnsignedValue; } ExpressionValue ExpressionValue::getAbsolute() const { - if (!Negative) - return *this; - - int64_t SignedValue = getAsSigned(Value); - int64_t MaxInt64 = std::numeric_limits::max(); - // Absolute value can be represented as int64_t. - if (SignedValue >= -MaxInt64) - return ExpressionValue(-getAsSigned(Value)); - - // -X == -(max int64_t + Rem), negate each component independently. - SignedValue += MaxInt64; - uint64_t RemainingValueAbsolute = -SignedValue; - return ExpressionValue(MaxInt64 + RemainingValueAbsolute); + unsigned bitwidth = Value.getBitWidth(); + assert(!Value.isNegative() || Value.isSignedIntN(bitwidth - 1)); + return ExpressionValue(Value.abs().getZExtValue()); } Expected llvm::operator+(const ExpressionValue &LeftOperand, diff --git a/llvm/lib/FileCheck/FileCheckImpl.h b/llvm/lib/FileCheck/FileCheckImpl.h --- a/llvm/lib/FileCheck/FileCheckImpl.h +++ b/llvm/lib/FileCheck/FileCheckImpl.h @@ -15,6 +15,7 @@ #ifndef LLVM_LIB_FILECHECK_FILECHECKIMPL_H #define LLVM_LIB_FILECHECK_FILECHECKIMPL_H +#include "llvm/ADT/APInt.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/FileCheck/FileCheck.h" @@ -120,15 +121,15 @@ /// Class representing a numeric value. class ExpressionValue { private: - uint64_t Value; - bool Negative; + APInt Value; public: + // Store signed and unsigned 64-bit integers in a signed 65-bit APInt. template - explicit ExpressionValue(T Val) : Value(Val), Negative(Val < 0) {} + explicit ExpressionValue(T Val) : Value(65, Val, /*isSigned=*/Val < 0) {} bool operator==(const ExpressionValue &Other) const { - return Value == Other.Value && isNegative() == Other.isNegative(); + return Value == Other.Value; } bool operator!=(const ExpressionValue &Other) const { @@ -136,10 +137,7 @@ } /// Returns true if value is signed and negative, false otherwise. - bool isNegative() const { - assert((Value != 0 || !Negative) && "Unexpected negative zero!"); - return Negative; - } + bool isNegative() const { return Value.isNegative(); } /// \returns the value as a signed integer or an error if the value is out of /// range.