1 //===- FixedPoint.cpp - 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 implementation for the fixed point number interface. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/Basic/FixedPoint.h" 16 17 namespace clang { 18 19 APFixedPoint APFixedPoint::convert(const FixedPointSemantics &DstSema) const { 20 llvm::APSInt NewVal = Val; 21 unsigned DstWidth = DstSema.getWidth(); 22 unsigned DstScale = DstSema.getScale(); 23 bool Upscaling = DstScale > getScale(); 24 25 if (Upscaling) { 26 NewVal = NewVal.extend(NewVal.getBitWidth() + DstScale - getScale()); 27 NewVal <<= (DstScale - getScale()); 28 } else { 29 NewVal >>= (getScale() - DstScale); 30 } 31 32 if (DstSema.isSaturated()) { 33 auto Mask = llvm::APInt::getBitsSetFrom( 34 NewVal.getBitWidth(), 35 std::min(DstScale + DstSema.getIntegralBits(), NewVal.getBitWidth())); 36 llvm::APInt Masked(NewVal & Mask); 37 38 // Change in the bits above the sign 39 if (!(Masked == Mask || Masked == 0)) 40 NewVal = NewVal.isNegative() ? Mask : ~Mask; 41 42 if (!DstSema.isSigned() && NewVal.isNegative()) 43 NewVal = 0; 44 } 45 46 NewVal = NewVal.extOrTrunc(DstWidth); 47 NewVal.setIsSigned(DstSema.isSigned()); 48 return APFixedPoint(NewVal, DstSema); 49 } 50 51 int APFixedPoint::compare(const APFixedPoint &Other) const { 52 llvm::APSInt ThisVal = getValue(); 53 llvm::APSInt OtherVal = Other.getValue(); 54 bool ThisSigned = Val.isSigned(); 55 bool OtherSigned = OtherVal.isSigned(); 56 unsigned OtherScale = Other.getScale(); 57 unsigned OtherWidth = OtherVal.getBitWidth(); 58 59 unsigned CommonWidth = std::max(Val.getBitWidth(), OtherWidth); 60 61 // Prevent overflow in the event the widths are the same but the scales differ 62 CommonWidth += getScale() >= OtherScale ? getScale() - OtherScale 63 : OtherScale - getScale(); 64 65 ThisVal = ThisVal.extOrTrunc(CommonWidth); 66 OtherVal = OtherVal.extOrTrunc(CommonWidth); 67 68 unsigned CommonScale = std::max(getScale(), OtherScale); 69 ThisVal = ThisVal.shl(CommonScale - getScale()); 70 OtherVal = OtherVal.shl(CommonScale - OtherScale); 71 72 if (ThisSigned && OtherSigned) { 73 if (ThisVal.sgt(OtherVal)) 74 return 1; 75 else if (ThisVal.slt(OtherVal)) 76 return -1; 77 } else if (!ThisSigned && !OtherSigned) { 78 if (ThisVal.ugt(OtherVal)) 79 return 1; 80 else if (ThisVal.ult(OtherVal)) 81 return -1; 82 } else if (ThisSigned && !OtherSigned) { 83 if (ThisVal.isSignBitSet()) 84 return -1; 85 else if (ThisVal.ugt(OtherVal)) 86 return 1; 87 else if (ThisVal.ult(OtherVal)) 88 return -1; 89 } else { 90 // !ThisSigned && OtherSigned 91 if (OtherVal.isSignBitSet()) 92 return 1; 93 else if (ThisVal.ugt(OtherVal)) 94 return 1; 95 else if (ThisVal.ult(OtherVal)) 96 return -1; 97 } 98 99 return 0; 100 } 101 102 APFixedPoint APFixedPoint::getMax(const FixedPointSemantics &Sema) { 103 bool IsUnsigned = !Sema.isSigned(); 104 auto Val = llvm::APSInt::getMaxValue(Sema.getWidth(), IsUnsigned); 105 if (IsUnsigned && Sema.hasUnsignedPadding()) 106 Val = Val.lshr(1); 107 return APFixedPoint(Val, Sema); 108 } 109 110 APFixedPoint APFixedPoint::getMin(const FixedPointSemantics &Sema) { 111 auto Val = llvm::APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()); 112 return APFixedPoint(Val, Sema); 113 } 114 115 } // namespace clang 116