leonardchan created this revision.
leonardchan added reviewers: phosek, mcgrathr, jakehehrlich.
leonardchan added a project: clang.
This patch has the implementation and tests for converting between fixed point
and floating point numbers.
The conversion process is simply dividing the fixed point value, as an integer,
by 2^(# of fractional bits) as a float.
This is a parent of https://reviews.llvm.org/D46925
Repository:
rC Clang
https://reviews.llvm.org/D46926
Files:
include/clang/AST/OperationKinds.def
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/Expr.cpp
lib/AST/ExprConstant.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprAgg.cpp
lib/CodeGen/CGExprComplex.cpp
lib/CodeGen/CGExprConstant.cpp
lib/CodeGen/CGExprScalar.cpp
lib/Edit/RewriteObjCFoundationAPI.cpp
lib/Sema/SemaCast.cpp
lib/Sema/SemaExpr.cpp
lib/StaticAnalyzer/Core/ExprEngineC.cpp
test/Frontend/fixed_point_validation.c
Index: test/Frontend/fixed_point_validation.c
===================================================================
--- test/Frontend/fixed_point_validation.c
+++ test/Frontend/fixed_point_validation.c
@@ -30,6 +30,7 @@
// Run simple validation tests
#define assert(b) if (!(b)) { return 1; }
+#define abs(x) x < 0 ? -x : x
int main(){
short _Accum s_accum = 0.0hk;
@@ -264,4 +265,18 @@
assert(5.0hk >> 2 == 1.25hk);
assert(-5.0hk >> 2 == -1.25k);
assert(0.0hr >> 2 == 0);
+
+ /**************** Float conversions ***************/
+
+ float f = (float)2.5k;
+ assert(f > 2.4999 && f < 2.5001); // High precision since the fractional value can be evenly
+ // represented.
+ assert((float)2.333hk != 2.333f);
+
+ float base = 2.333f;
+ float saccum_diff = abs(base - 2.333hk);
+ float accum_diff = abs(base - 2.333k);
+ float laccum_diff = abs(base - 2.333lk);
+ assert(accum_diff < saccum_diff);
+ assert(laccum_diff < accum_diff);
}
Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -321,6 +321,7 @@
const LocationContext *LCtx = Pred->getLocationContext();
switch (CastE->getCastKind()) {
+ case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
case CK_IntegralToFixedPoint: llvm_unreachable("ExprEngine::VisitCast CK_IntegralToFixedPoint"); // TODO
case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO
case CK_LValueToRValue:
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -1029,6 +1029,18 @@
return result;
}
+/// \brief Handle arithmetic conversion from fixed point to floating. Helper function
+/// of UsualArithmeticConversions()
+static QualType handleFixedPointToFloatConversion(Sema &S, ExprResult &FloatExpr,
+ ExprResult &FixedPointExpr,
+ QualType FloatTy, QualType FixedPointTy) {
+ assert(FloatTy->isFloatingType());
+ assert(FixedPointTy->isFixedPointType());
+
+ FixedPointExpr = S.ImpCastExprToType(FixedPointExpr.get(), FloatTy, CK_FixedPointToFloating);
+ return FloatTy;
+}
+
/// \brief Handle arithmethic conversion with floating point types. Helper
/// function of UsualArithmeticConversions()
static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
@@ -1057,11 +1069,22 @@
if (LHSType->isHalfType() && !S.getLangOpts().NativeHalfType)
LHSType = S.Context.FloatTy;
+ if (RHSType->isFixedPointType()) {
+ return handleFixedPointToFloatConversion(S, LHS, RHS, LHSType,
+ RHSType);
+ }
+
return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType,
/*convertFloat=*/!IsCompAssign,
/*convertInt=*/ true);
}
assert(RHSFloat);
+
+ if (LHSType->isFixedPointType()) {
+ return handleFixedPointToFloatConversion(S, RHS, LHS, RHSType,
+ LHSType);
+ }
+
return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType,
/*convertInt=*/ true,
/*convertFloat=*/!IsCompAssign);
@@ -1218,6 +1241,7 @@
CK_IntegralRealToComplex);
return ComplexType;
}
+
/// \brief Handle arithmetic conversion from integer to fixed point. Helper function
/// of UsualArithmeticConversions()
static QualType handleIntToFixedPointConversion(Sema &S, ExprResult &FixedPointExpr,
@@ -6028,7 +6052,14 @@
}
llvm_unreachable("Should have returned before this");
- case Type::STK_FixedPoint: llvm_unreachable("Sema::PrepareScalarCast from STK_FixedPoint to anything"); // TODO
+ case Type::STK_FixedPoint: {
+ switch (DestTy->getScalarTypeKind()) {
+ default: llvm_unreachable("Unable to convert from fixed point type");
+ case Type::STK_Integral: llvm_unreachable("Unimplemented scalar cast from fixed point to int"); // TODO
+ case Type::STK_Floating: return CK_FixedPointToFloating;
+ case Type::STK_FixedPoint: llvm_unreachable("Unimplemented scalar cast from fixed point to fixed point"); // TODO
+ }
+ }
case Type::STK_Bool: // casting from bool is like casting from an integer
case Type::STK_Integral:
Index: lib/Sema/SemaCast.cpp
===================================================================
--- lib/Sema/SemaCast.cpp
+++ lib/Sema/SemaCast.cpp
@@ -2601,6 +2601,20 @@
return;
}
}
+
+ if (SrcType->isFixedPointType()) {
+ switch (DestType->getScalarTypeKind()) {
+ default:
+ Self.Diag(SrcExpr.get()->getLocStart(),
+ diag::err_typecheck_fixed_point_cast)
+ << DestType;
+ return;
+ case Type::STK_Floating:
+ case Type::STK_Integral:
+ case Type::STK_FixedPoint:
+ break; // Allow
+ }
+ }
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
DiagnoseCallingConvCast(Self, SrcExpr, DestType, OpRange);
Index: lib/Edit/RewriteObjCFoundationAPI.cpp
===================================================================
--- lib/Edit/RewriteObjCFoundationAPI.cpp
+++ lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -1004,6 +1004,7 @@
switch (ICE->getCastKind()) {
case CK_IntegralToFixedPoint: llvm_unreachable("rewriteToNumericBoxedExpression CK_IntegralToFixedPoint"); // TODO
case CK_FixedPointCast: llvm_unreachable("rewriteToNumericBoxedExpression CK_FixedPointCast"); // TODO
+ case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
case CK_LValueToRValue:
case CK_NoOp:
case CK_UserDefinedConversion:
Index: lib/CodeGen/CGExprScalar.cpp
===================================================================
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -1851,6 +1851,14 @@
getFixedPointFBits(DestTy), "int_to_fixed");
}
+ case CK_FixedPointToFloating: {
+ assert(DestTy->isFloatingType());
+ assert(E->getType()->isFixedPointType());
+ unsigned fbits = getFixedPointFBits(E->getType());
+ return Builder.CreateFDiv(EmitScalarConversion(Visit(E), E->getType(), DestTy, CE->getExprLoc()),
+ llvm::ConstantFP::get(CGF.CGM.FloatTy, (1ULL << fbits) * 1.0));
+ }
+
case CK_IntegralCast:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
Index: lib/CodeGen/CGExprConstant.cpp
===================================================================
--- lib/CodeGen/CGExprConstant.cpp
+++ lib/CodeGen/CGExprConstant.cpp
@@ -686,6 +686,7 @@
Expr *subExpr = E->getSubExpr();
switch (E->getCastKind()) {
+ case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO
case CK_IntegralToFixedPoint: llvm_unreachable("VisitCastExpr CK_IntegralToFixedPoint"); // TODO
case CK_ToUnion: {
Index: lib/CodeGen/CGExprComplex.cpp
===================================================================
--- lib/CodeGen/CGExprComplex.cpp
+++ lib/CodeGen/CGExprComplex.cpp
@@ -448,6 +448,7 @@
switch (CK) {
case CK_IntegralToFixedPoint: llvm_unreachable("ComplexExprEmitter::EmitCast CK_IntegralToFixedPoint"); // TODO
case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO
+ case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
// Atomic to non-atomic casts may be more than a no-op for some platforms and
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp
+++ lib/CodeGen/CGExprAgg.cpp
@@ -671,6 +671,7 @@
if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
CGF.CGM.EmitExplicitCastExprType(ECE, &CGF);
switch (E->getCastKind()) {
+ case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO
case CK_IntegralToFixedPoint: llvm_unreachable("AggExprEmitter::VisitCastExpr CK_IntegralToFixedPoint"); // TODO
case CK_Dynamic: {
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -4044,6 +4044,7 @@
/// cast from scalar to union.
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
switch (E->getCastKind()) {
+ case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
case CK_IntegralToFixedPoint: llvm_unreachable("CodeGenFunction::EmitCastLValue CK_IntegralToFixedPoint"); // TODO
case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO
case CK_ToVoid:
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -9163,6 +9163,7 @@
QualType SrcType = SubExpr->getType();
switch (E->getCastKind()) {
+ case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO
case CK_IntegralToFixedPoint: llvm_unreachable("IntExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint"); // TODO
case CK_BaseToDerived:
@@ -9758,6 +9759,7 @@
bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
switch (E->getCastKind()) {
+ case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating");
case CK_IntegralToFixedPoint: llvm_unreachable("ComplexExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint"); // TODO
case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO
case CK_BitCast:
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -1653,6 +1653,7 @@
case CK_IntToOCLSampler:
case CK_IntegralToFixedPoint:
case CK_FixedPointCast:
+ case CK_FixedPointToFloating:
assert(!getType()->isBooleanType() && "unheralded conversion to bool");
goto CheckNoBasePath;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -7321,6 +7321,8 @@
"expression result unused; assign into a variable to force a volatile load">,
InGroup<DiagGroup<"unused-volatile-lvalue">>;
+def err_typecheck_fixed_point_cast : Error<"Cannot convert fixed point type to %0">;
+
def ext_cxx14_attr : Extension<
"use of the %0 attribute is a C++14 extension">, InGroup<CXX14>;
def ext_cxx17_attr : Extension<
Index: include/clang/AST/OperationKinds.def
===================================================================
--- include/clang/AST/OperationKinds.def
+++ include/clang/AST/OperationKinds.def
@@ -206,6 +206,10 @@
/// (short _Accum) i
CAST_OPERATION(IntegralToFixedPoint)
+/// CK_FixedPointToFloating - Fixed point to floating point.
+/// (float) 2.5hk
+CAST_OPERATION(FixedPointToFloating)
+
/// CK_FloatingToIntegral - Floating point to integral. Rounds
/// towards zero, discarding any fractional component.
/// (int) f
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits