1 //===- FixedPoint.h - Fixed point constant handling -------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// Defines the fixed point number interface. 12 /// This is a class for abstracting various operations performed on fixed point 13 /// types described in ISO/IEC JTC1 SC22 WG14 N1169 starting at clause 4. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_CLANG_BASIC_FIXEDPOINT_H 18 #define LLVM_CLANG_BASIC_FIXEDPOINT_H 19 20 #include "llvm/ADT/APSInt.h" 21 22 namespace clang { 23 24 class ASTContext; 25 class QualType; 26 27 /// The fixed point semantics work similarly to llvm::fltSemantics. The width 28 /// specifies the whole bit width of the underlying scaled integer (with padding 29 /// if any). The scale represents the number of fractional bits in this type. 30 /// When HasUnsignedPadding is true and this type is signed, the first bit 31 /// in the value this represents is treaded as padding. 32 class FixedPointSemantics { 33 public: FixedPointSemantics(unsigned Width,unsigned Scale,bool IsSigned,bool IsSaturated,bool HasUnsignedPadding)34 FixedPointSemantics(unsigned Width, unsigned Scale, bool IsSigned, 35 bool IsSaturated, bool HasUnsignedPadding) 36 : Width(Width), Scale(Scale), IsSigned(IsSigned), 37 IsSaturated(IsSaturated), HasUnsignedPadding(HasUnsignedPadding) { 38 assert(Width >= Scale && "Not enough room for the scale"); 39 } 40 getWidth()41 unsigned getWidth() const { return Width; } getScale()42 unsigned getScale() const { return Scale; } isSigned()43 bool isSigned() const { return IsSigned; } isSaturated()44 bool isSaturated() const { return IsSaturated; } hasUnsignedPadding()45 bool hasUnsignedPadding() const { return HasUnsignedPadding; } 46 setSaturated(bool Saturated)47 void setSaturated(bool Saturated) { IsSaturated = Saturated; } 48 getIntegralBits()49 unsigned getIntegralBits() const { 50 if (IsSigned || (!IsSigned && HasUnsignedPadding)) 51 return Width - Scale - 1; 52 else 53 return Width - Scale; 54 } 55 56 private: 57 unsigned Width; 58 unsigned Scale; 59 bool IsSigned; 60 bool IsSaturated; 61 bool HasUnsignedPadding; 62 }; 63 64 /// The APFixedPoint class works similarly to APInt/APSInt in that it is a 65 /// functional replacement for a scaled integer. It is meant to replicate the 66 /// fixed point types proposed in ISO/IEC JTC1 SC22 WG14 N1169. The class carries 67 /// info about the fixed point type's width, sign, scale, and saturation, and 68 /// provides different operations that would normally be performed on fixed point 69 /// types. 70 /// 71 /// Semantically this does not represent any existing C type other than fixed 72 /// point types and should eventually be moved to LLVM if fixed point types gain 73 /// native IR support. 74 class APFixedPoint { 75 public: APFixedPoint(const llvm::APInt & Val,const FixedPointSemantics & Sema)76 APFixedPoint(const llvm::APInt &Val, const FixedPointSemantics &Sema) 77 : Val(Val, !Sema.isSigned()), Sema(Sema) { 78 assert(Val.getBitWidth() == Sema.getWidth() && 79 "The value should have a bit width that matches the Sema width"); 80 } 81 APFixedPoint(uint64_t Val,const FixedPointSemantics & Sema)82 APFixedPoint(uint64_t Val, const FixedPointSemantics &Sema) 83 : APFixedPoint(llvm::APInt(Sema.getWidth(), Val, Sema.isSigned()), 84 Sema) {} 85 getValue()86 llvm::APSInt getValue() const { return llvm::APSInt(Val, !Sema.isSigned()); } getWidth()87 inline unsigned getWidth() const { return Sema.getWidth(); } getScale()88 inline unsigned getScale() const { return Sema.getScale(); } isSaturated()89 inline bool isSaturated() const { return Sema.isSaturated(); } isSigned()90 inline bool isSigned() const { return Sema.isSigned(); } hasPadding()91 inline bool hasPadding() const { return Sema.hasUnsignedPadding(); } 92 93 // Convert this number to match the semantics provided. 94 APFixedPoint convert(const FixedPointSemantics &DstSema) const; 95 shr(unsigned Amt)96 APFixedPoint shr(unsigned Amt) const { 97 return APFixedPoint(Val >> Amt, Sema); 98 } 99 shl(unsigned Amt)100 APFixedPoint shl(unsigned Amt) const { 101 return APFixedPoint(Val << Amt, Sema); 102 } 103 getIntPart()104 llvm::APSInt getIntPart() const { 105 if (Val < 0 && Val != -Val) // Cover the case when we have the min val 106 return -(-Val >> getScale()); 107 else 108 return Val >> getScale(); 109 } 110 111 // If LHS > RHS, return 1. If LHS == RHS, return 0. If LHS < RHS, return -1. 112 int compare(const APFixedPoint &Other) const; 113 bool operator==(const APFixedPoint &Other) const { 114 return compare(Other) == 0; 115 } 116 bool operator!=(const APFixedPoint &Other) const { 117 return compare(Other) != 0; 118 } 119 bool operator>(const APFixedPoint &Other) const { return compare(Other) > 0; } 120 bool operator<(const APFixedPoint &Other) const { return compare(Other) < 0; } 121 bool operator>=(const APFixedPoint &Other) const { 122 return compare(Other) >= 0; 123 } 124 bool operator<=(const APFixedPoint &Other) const { 125 return compare(Other) <= 0; 126 } 127 128 static APFixedPoint getMax(const FixedPointSemantics &Sema); 129 static APFixedPoint getMin(const FixedPointSemantics &Sema); 130 131 private: 132 llvm::APSInt Val; 133 FixedPointSemantics Sema; 134 }; 135 136 } // namespace clang 137 138 #endif 139