//===- FixedPoint.h - Fixed point constant handling -------------*- C++ -*-===//
|
//
|
// The LLVM Compiler Infrastructure
|
//
|
// This file is distributed under the University of Illinois Open Source
|
// License. See LICENSE.TXT for details.
|
//
|
//===----------------------------------------------------------------------===//
|
//
|
/// \file
|
/// Defines the fixed point number interface.
|
/// This is a class for abstracting various operations performed on fixed point
|
/// types described in ISO/IEC JTC1 SC22 WG14 N1169 starting at clause 4.
|
//
|
//===----------------------------------------------------------------------===//
|
|
#ifndef LLVM_CLANG_BASIC_FIXEDPOINT_H
|
#define LLVM_CLANG_BASIC_FIXEDPOINT_H
|
|
#include "llvm/ADT/APSInt.h"
|
|
namespace clang {
|
|
class ASTContext;
|
class QualType;
|
|
/// The fixed point semantics work similarly to llvm::fltSemantics. The width
|
/// specifies the whole bit width of the underlying scaled integer (with padding
|
/// if any). The scale represents the number of fractional bits in this type.
|
/// When HasUnsignedPadding is true and this type is signed, the first bit
|
/// in the value this represents is treaded as padding.
|
class FixedPointSemantics {
|
public:
|
FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned,
|
bool IsSaturated, bool HasUnsignedPadding)
|
: Width(Width), Scale(Scale), IsSigned(IsSigned),
|
IsSaturated(IsSaturated), HasUnsignedPadding(HasUnsignedPadding) {
|
assert(Width >= Scale && "Not enough room for the scale");
|
}
|
|
unsigned getWidth() const { return Width; }
|
unsigned getScale() const { return Scale; }
|
bool isSigned() const { return IsSigned; }
|
bool isSaturated() const { return IsSaturated; }
|
bool hasUnsignedPadding() const { return HasUnsignedPadding; }
|
|
void setSaturated(bool Saturated) { IsSaturated = Saturated; }
|
|
unsigned getIntegralBits() const {
|
if (IsSigned || (!IsSigned && HasUnsignedPadding))
|
return Width - Scale - 1;
|
else
|
return Width - Scale;
|
}
|
|
private:
|
unsigned Width;
|
unsigned Scale;
|
bool IsSigned;
|
bool IsSaturated;
|
bool HasUnsignedPadding;
|
};
|
|
/// The APFixedPoint class works similarly to APInt/APSInt in that it is a
|
/// functional replacement for a scaled integer. It is meant to replicate the
|
/// fixed point types proposed in ISO/IEC JTC1 SC22 WG14 N1169. The class carries
|
/// info about the fixed point type's width, sign, scale, and saturation, and
|
/// provides different operations that would normally be performed on fixed point
|
/// types.
|
///
|
/// Semantically this does not represent any existing C type other than fixed
|
/// point types and should eventually be moved to LLVM if fixed point types gain
|
/// native IR support.
|
class APFixedPoint {
|
public:
|
APFixedPoint(const llvm::APInt &Val, const FixedPointSemantics &Sema)
|
: Val(Val, !Sema.isSigned()), Sema(Sema) {
|
assert(Val.getBitWidth() == Sema.getWidth() &&
|
"The value should have a bit width that matches the Sema width");
|
}
|
|
APFixedPoint(uint64_t Val, const FixedPointSemantics &Sema)
|
: APFixedPoint(llvm::APInt(Sema.getWidth(), Val, Sema.isSigned()),
|
Sema) {}
|
|
llvm::APSInt getValue() const { return llvm::APSInt(Val, !Sema.isSigned()); }
|
inline unsigned getWidth() const { return Sema.getWidth(); }
|
inline unsigned getScale() const { return Sema.getScale(); }
|
inline bool isSaturated() const { return Sema.isSaturated(); }
|
inline bool isSigned() const { return Sema.isSigned(); }
|
inline bool hasPadding() const { return Sema.hasUnsignedPadding(); }
|
|
// Convert this number to match the semantics provided.
|
APFixedPoint convert(const FixedPointSemantics &DstSema) const;
|
|
APFixedPoint shr(unsigned Amt) const {
|
return APFixedPoint(Val >> Amt, Sema);
|
}
|
|
APFixedPoint shl(unsigned Amt) const {
|
return APFixedPoint(Val << Amt, Sema);
|
}
|
|
llvm::APSInt getIntPart() const {
|
if (Val < 0 && Val != -Val) // Cover the case when we have the min val
|
return -(-Val >> getScale());
|
else
|
return Val >> getScale();
|
}
|
|
// If LHS > RHS, return 1. If LHS == RHS, return 0. If LHS < RHS, return -1.
|
int compare(const APFixedPoint &Other) const;
|
bool operator==(const APFixedPoint &Other) const {
|
return compare(Other) == 0;
|
}
|
bool operator!=(const APFixedPoint &Other) const {
|
return compare(Other) != 0;
|
}
|
bool operator>(const APFixedPoint &Other) const { return compare(Other) > 0; }
|
bool operator<(const APFixedPoint &Other) const { return compare(Other) < 0; }
|
bool operator>=(const APFixedPoint &Other) const {
|
return compare(Other) >= 0;
|
}
|
bool operator<=(const APFixedPoint &Other) const {
|
return compare(Other) <= 0;
|
}
|
|
static APFixedPoint getMax(const FixedPointSemantics &Sema);
|
static APFixedPoint getMin(const FixedPointSemantics &Sema);
|
|
private:
|
llvm::APSInt Val;
|
FixedPointSemantics Sema;
|
};
|
|
} // namespace clang
|
|
#endif
|