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<int64_t> ExpressionValue::getSignedValue() const {
- if (Negative)
- return getAsSigned(Value);
-
- if (Value > (uint64_t)std::numeric_limits<int64_t>::max())
+ std::optional<int64_t> SignedValue = Value.trySExtValue();
+ if (!SignedValue)
return make_error<OverflowError>();
-
- // Value is in the representable range of int64_t so we can use cast.
- return static_cast<int64_t>(Value);
+ return *SignedValue;
}
Expected<uint64_t> ExpressionValue::getUnsignedValue() const {
- if (Negative)
+ std::optional<int64_t> UnsignedValue = Value.tryZExtValue();
+ if (!UnsignedValue)
return make_error<OverflowError>();
- return Value;
+ return *UnsignedValue;
}
ExpressionValue ExpressionValue::getAbsolute() const {
- if (!Negative)
- return *this;
-
- int64_t SignedValue = getAsSigned(Value);
- int64_t MaxInt64 = std::numeric_limits<int64_t>::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<ExpressionValue> llvm::operator+(const ExpressionValue &LeftOperand,
#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"
/// 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 <class T>
- 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 {
}
/// 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.