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
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to