diff options
author | Leonard Chan <leonardchan@google.com> | 2019-01-16 18:53:05 +0000 |
---|---|---|
committer | Leonard Chan <leonardchan@google.com> | 2019-01-16 18:53:05 +0000 |
commit | 86285d2e17ea669fe53853215759c554ad101d31 (patch) | |
tree | bbedc37df9ec3971359b80ed5b9c5503f576b213 | |
parent | 8265e390e740f0fb7464f7c20bd38d55ee145dd4 (diff) |
[Fixed Point Arithmetic] Add APFixedPoint to APValue
This adds APFixedPoint to the union of values that can be represented with an APValue.
Differential Revision: https://reviews.llvm.org/D56746
llvm-svn: 351368
-rw-r--r-- | clang/include/clang/AST/APValue.h | 23 | ||||
-rw-r--r-- | clang/include/clang/AST/Type.h | 2 | ||||
-rw-r--r-- | clang/include/clang/Basic/FixedPoint.h | 22 | ||||
-rw-r--r-- | clang/lib/AST/APValue.cpp | 15 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 3 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Basic/FixedPoint.cpp | 27 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 1 |
9 files changed, 99 insertions, 22 deletions
diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index d4057c9da5f3..f540ad739835 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_APVALUE_H #define LLVM_CLANG_AST_APVALUE_H +#include "clang/Basic/FixedPoint.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" @@ -43,6 +44,7 @@ public: Uninitialized, Int, Float, + FixedPoint, ComplexInt, ComplexFloat, LValue, @@ -175,6 +177,9 @@ public: explicit APValue(APFloat F) : Kind(Uninitialized) { MakeFloat(); setFloat(std::move(F)); } + explicit APValue(APFixedPoint FX) : Kind(Uninitialized) { + MakeFixedPoint(std::move(FX)); + } explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) { MakeVector(); setVector(E, N); } @@ -233,6 +238,7 @@ public: bool isUninit() const { return Kind == Uninitialized; } bool isInt() const { return Kind == Int; } bool isFloat() const { return Kind == Float; } + bool isFixedPoint() const { return Kind == FixedPoint; } bool isComplexInt() const { return Kind == ComplexInt; } bool isComplexFloat() const { return Kind == ComplexFloat; } bool isLValue() const { return Kind == LValue; } @@ -265,6 +271,14 @@ public: return const_cast<APValue*>(this)->getFloat(); } + APFixedPoint &getFixedPoint() { + assert(isFixedPoint() && "Invalid accessor"); + return *(APFixedPoint *)(char *)Data.buffer; + } + const APFixedPoint &getFixedPoint() const { + return const_cast<APValue *>(this)->getFixedPoint(); + } + APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); return ((ComplexAPSInt*)(char*)Data.buffer)->Real; @@ -406,6 +420,10 @@ public: assert(isFloat() && "Invalid accessor"); *(APFloat *)(char *)Data.buffer = std::move(F); } + void setFixedPoint(APFixedPoint FX) { + assert(isFixedPoint() && "Invalid accessor"); + *(APFixedPoint *)(char *)Data.buffer = std::move(FX); + } void setVector(const APValue *E, unsigned N) { assert(isVector() && "Invalid accessor"); ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; @@ -465,6 +483,11 @@ private: new ((void*)(char*)Data.buffer) APFloat(0.0); Kind = Float; } + void MakeFixedPoint(APFixedPoint &&FX) { + assert(isUninit() && "Bad state change"); + new ((void *)(char *)Data.buffer) APFixedPoint(std::move(FX)); + Kind = FixedPoint; + } void MakeVector() { assert(isUninit() && "Bad state change"); new ((void*)(char*)Data.buffer) Vec(); diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 4c48473d2e00..0ebd2bc86fe6 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -6848,6 +6848,8 @@ QualType DecayedType::getPointeeType() const { // Get the decimal string representation of a fixed point type, represented // as a scaled integer. +// TODO: At some point, we should change the arguments to instead just accept an +// APFixedPoint instead of APSInt and scale. void FixedPointValueToString(SmallVectorImpl<char> &Str, llvm::APSInt Val, unsigned Scale); diff --git a/clang/include/clang/Basic/FixedPoint.h b/clang/include/clang/Basic/FixedPoint.h index bfba55a04103..174f7cc7d0fc 100644 --- a/clang/include/clang/Basic/FixedPoint.h +++ b/clang/include/clang/Basic/FixedPoint.h @@ -18,6 +18,7 @@ #define LLVM_CLANG_BASIC_FIXEDPOINT_H #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" namespace clang { @@ -104,19 +105,25 @@ class APFixedPoint { : APFixedPoint(llvm::APInt(Sema.getWidth(), Val, Sema.isSigned()), Sema) {} + // Zero initialization. + APFixedPoint(const FixedPointSemantics &Sema) : APFixedPoint(0, 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(); } + FixedPointSemantics getSemantics() const { return Sema; } + + bool getBoolValue() const { return Val.getBoolValue(); } // 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); @@ -129,6 +136,13 @@ class APFixedPoint { return Val >> getScale(); } + void toString(llvm::SmallVectorImpl<char> &Str) const; + std::string toString() const { + llvm::SmallString<40> S; + toString(S); + return S.str(); + } + // 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 { @@ -154,6 +168,12 @@ private: FixedPointSemantics Sema; }; +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const APFixedPoint &FX) { + OS << FX.toString(); + return OS; +} + } // namespace clang #endif diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index c05b160b8e3d..c5f5fae50c8e 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -176,6 +176,11 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { MakeFloat(); setFloat(RHS.getFloat()); break; + case FixedPoint: { + APFixedPoint FXCopy = RHS.getFixedPoint(); + MakeFixedPoint(std::move(FXCopy)); + break; + } case Vector: MakeVector(); setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, @@ -233,6 +238,8 @@ void APValue::DestroyDataAndMakeUninit() { ((APSInt*)(char*)Data.buffer)->~APSInt(); else if (Kind == Float) ((APFloat*)(char*)Data.buffer)->~APFloat(); + else if (Kind == FixedPoint) + ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint(); else if (Kind == Vector) ((Vec*)(char*)Data.buffer)->~Vec(); else if (Kind == ComplexInt) @@ -268,6 +275,8 @@ bool APValue::needsCleanup() const { return getInt().needsCleanup(); case Float: return getFloat().needsCleanup(); + case FixedPoint: + return getFixedPoint().getValue().needsCleanup(); case ComplexFloat: assert(getComplexFloatImag().needsCleanup() == getComplexFloatReal().needsCleanup() && @@ -321,6 +330,9 @@ void APValue::dump(raw_ostream &OS) const { case Float: OS << "Float: " << GetApproxValue(getFloat()); return; + case FixedPoint: + OS << "FixedPoint : " << getFixedPoint(); + return; case Vector: OS << "Vector: "; getVectorElt(0).dump(OS); @@ -397,6 +409,9 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ case APValue::Float: Out << GetApproxValue(getFloat()); return; + case APValue::FixedPoint: + Out << getFixedPoint(); + return; case APValue::Vector: { Out << '{'; QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index da093ff22c12..6fced9648419 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2027,6 +2027,9 @@ static bool HandleConversionToBool(const APValue &Val, bool &Result) { case APValue::Int: Result = Val.getInt().getBoolValue(); return true; + case APValue::FixedPoint: + Result = Val.getFixedPoint().getBoolValue(); + return true; case APValue::Float: Result = !Val.getFloat().isZero(); return true; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 0dbc88c04521..74c19c32f31c 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -4016,25 +4016,8 @@ CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { void clang::FixedPointValueToString(SmallVectorImpl<char> &Str, llvm::APSInt Val, unsigned Scale) { - if (Val.isSigned() && Val.isNegative() && Val != -Val) { - Val = -Val; - Str.push_back('-'); - } - - llvm::APSInt IntPart = Val >> Scale; - - // Add 4 digits to hold the value after multiplying 10 (the radix) - unsigned Width = Val.getBitWidth() + 4; - llvm::APInt FractPart = Val.zextOrTrunc(Scale).zext(Width); - llvm::APInt FractPartMask = llvm::APInt::getAllOnesValue(Scale).zext(Width); - llvm::APInt RadixInt = llvm::APInt(Width, 10); - - IntPart.toString(Str, /*radix=*/10); - Str.push_back('.'); - do { - (FractPart * RadixInt) - .lshr(Scale) - .toString(Str, /*radix=*/10, Val.isSigned()); - FractPart = (FractPart * RadixInt) & FractPartMask; - } while (FractPart != 0); + FixedPointSemantics FXSema(Val.getBitWidth(), Scale, Val.isSigned(), + /*isSaturated=*/false, + /*hasUnsignedPadding=*/false); + APFixedPoint(Val, FXSema).toString(Str); } diff --git a/clang/lib/Basic/FixedPoint.cpp b/clang/lib/Basic/FixedPoint.cpp index 0aaa9af191d5..e3cffe628fd0 100644 --- a/clang/lib/Basic/FixedPoint.cpp +++ b/clang/lib/Basic/FixedPoint.cpp @@ -137,4 +137,31 @@ FixedPointSemantics FixedPointSemantics::getCommonSemantics( ResultIsSaturated, ResultHasUnsignedPadding); } +void APFixedPoint::toString(llvm::SmallVectorImpl<char> &Str) const { + llvm::APSInt Val = getValue(); + unsigned Scale = getScale(); + + if (Val.isSigned() && Val.isNegative() && Val != -Val) { + Val = -Val; + Str.push_back('-'); + } + + llvm::APSInt IntPart = Val >> Scale; + + // Add 4 digits to hold the value after multiplying 10 (the radix) + unsigned Width = Val.getBitWidth() + 4; + llvm::APInt FractPart = Val.zextOrTrunc(Scale).zext(Width); + llvm::APInt FractPartMask = llvm::APInt::getAllOnesValue(Scale).zext(Width); + llvm::APInt RadixInt = llvm::APInt(Width, 10); + + IntPart.toString(Str, /*radix=*/10); + Str.push_back('.'); + do { + (FractPart * RadixInt) + .lshr(Scale) + .toString(Str, /*radix=*/10, Val.isSigned()); + FractPart = (FractPart * RadixInt) & FractPartMask; + } while (FractPart != 0); +} + } // namespace clang diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index c9475840aeeb..5cd3e8565a95 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1873,6 +1873,9 @@ llvm::Constant *ConstantEmitter::tryEmitPrivate(const APValue &Value, return ConstantLValueEmitter(*this, Value, DestType).tryEmit(); case APValue::Int: return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt()); + case APValue::FixedPoint: + return llvm::ConstantInt::get(CGM.getLLVMContext(), + Value.getFixedPoint().getValue()); case APValue::ComplexInt: { llvm::Constant *Complex[2]; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3f9dc989103f..ab40e4dfd053 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6342,6 +6342,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } case APValue::AddrLabelDiff: return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff); + case APValue::FixedPoint: case APValue::Float: case APValue::ComplexInt: case APValue::ComplexFloat: |