diff options
author | Leonard Chan <leonardchan@google.com> | 2019-01-16 18:13:59 +0000 |
---|---|---|
committer | Leonard Chan <leonardchan@google.com> | 2019-01-16 18:13:59 +0000 |
commit | 2044ac89aa5203398048b38b6e53e33f682f507d (patch) | |
tree | 0876179a140b7bfbdafbe871657660b1940feb40 /clang/lib/Sema/SemaExpr.cpp | |
parent | 07d8b321b3da50e75fbad1b23253dd3646fd6033 (diff) | |
download | bcm5719-llvm-2044ac89aa5203398048b38b6e53e33f682f507d.tar.gz bcm5719-llvm-2044ac89aa5203398048b38b6e53e33f682f507d.zip |
[Fixed Point Arithmetic] Fixed Point Addition
This patch covers addition between fixed point types and other fixed point
types or integers, using the conversion rules described in 4.1.4 of N1169.
Usual arithmetic rules do not apply to binary operations when one of the
operands is a fixed point type, and the result of the operation must be
calculated with the full precision of the operands, so we should not perform
any casting to a common type.
This patch does not include constant expression evaluation for addition of
fixed point types. That will be addressed in another patch since I think this
one is already big enough.
Differential Revision: https://reviews.llvm.org/D53738
llvm-svn: 351364
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d5416d4d057..533b3b7da9f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1250,6 +1250,93 @@ static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS, return ComplexType; } +/// Return the rank of a given fixed point or integer type. The value itself +/// doesn't matter, but the values must be increasing with proper increasing +/// rank as described in N1169 4.1.1. +static unsigned GetFixedPointRank(QualType Ty) { + const auto *BTy = Ty->getAs<BuiltinType>(); + assert(BTy && "Expected a builtin type."); + + switch (BTy->getKind()) { + case BuiltinType::ShortFract: + case BuiltinType::UShortFract: + case BuiltinType::SatShortFract: + case BuiltinType::SatUShortFract: + return 1; + case BuiltinType::Fract: + case BuiltinType::UFract: + case BuiltinType::SatFract: + case BuiltinType::SatUFract: + return 2; + case BuiltinType::LongFract: + case BuiltinType::ULongFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatULongFract: + return 3; + case BuiltinType::ShortAccum: + case BuiltinType::UShortAccum: + case BuiltinType::SatShortAccum: + case BuiltinType::SatUShortAccum: + return 4; + case BuiltinType::Accum: + case BuiltinType::UAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatUAccum: + return 5; + case BuiltinType::LongAccum: + case BuiltinType::ULongAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatULongAccum: + return 6; + default: + if (BTy->isInteger()) + return 0; + llvm_unreachable("Unexpected fixed point or integer type"); + } +} + +/// handleFixedPointConversion - Fixed point operations between fixed +/// point types and integers or other fixed point types do not fall under +/// usual arithmetic conversion since these conversions could result in loss +/// of precsision (N1169 4.1.4). These operations should be calculated with +/// the full precision of their result type (N1169 4.1.6.2.1). +static QualType handleFixedPointConversion(Sema &S, QualType LHSTy, + QualType RHSTy) { + assert((LHSTy->isFixedPointType() || RHSTy->isFixedPointType()) && + "Expected at least one of the operands to be a fixed point type"); + assert((LHSTy->isFixedPointOrIntegerType() || + RHSTy->isFixedPointOrIntegerType()) && + "Special fixed point arithmetic operation conversions are only " + "applied to ints or other fixed point types"); + + // If one operand has signed fixed-point type and the other operand has + // unsigned fixed-point type, then the unsigned fixed-point operand is + // converted to its corresponding signed fixed-point type and the resulting + // type is the type of the converted operand. + if (RHSTy->isSignedFixedPointType() && LHSTy->isUnsignedFixedPointType()) + LHSTy = S.Context.getCorrespondingSignedFixedPointType(LHSTy); + else if (RHSTy->isUnsignedFixedPointType() && LHSTy->isSignedFixedPointType()) + RHSTy = S.Context.getCorrespondingSignedFixedPointType(RHSTy); + + // The result type is the type with the highest rank, whereby a fixed-point + // conversion rank is always greater than an integer conversion rank; if the + // type of either of the operands is a saturating fixedpoint type, the result + // type shall be the saturating fixed-point type corresponding to the type + // with the highest rank; the resulting value is converted (taking into + // account rounding and overflow) to the precision of the resulting type. + // Same ranks between signed and unsigned types are resolved earlier, so both + // types are either signed or both unsigned at this point. + unsigned LHSTyRank = GetFixedPointRank(LHSTy); + unsigned RHSTyRank = GetFixedPointRank(RHSTy); + + QualType ResultTy = LHSTyRank > RHSTyRank ? LHSTy : RHSTy; + + if (LHSTy->isSaturatedFixedPointType() || RHSTy->isSaturatedFixedPointType()) + ResultTy = S.Context.getCorrespondingSaturatedType(ResultTy); + + return ResultTy; +} + /// UsualArithmeticConversions - Performs various conversions that are common to /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this /// routine returns the first non-arithmetic type found. The client is @@ -1322,12 +1409,14 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS, return handleComplexIntConversion(*this, LHS, RHS, LHSType, RHSType, IsCompAssign); + if (LHSType->isFixedPointType() || RHSType->isFixedPointType()) + return handleFixedPointConversion(*this, LHSType, RHSType); + // Finally, we have two differing integer types. return handleIntegerConversion<doIntegralCast, doIntegralCast> (*this, LHS, RHS, LHSType, RHSType, IsCompAssign); } - //===----------------------------------------------------------------------===// // Semantic Analysis for various Expression Types //===----------------------------------------------------------------------===// |