FixedPoint.cpp 3.5 KB

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