]> granicus.if.org Git - clang/commitdiff
[Fixed Point Arithmetic] Fixed Point to Boolean Cast
authorLeonard Chan <leonardchan@google.com>
Tue, 23 Oct 2018 17:55:35 +0000 (17:55 +0000)
committerLeonard Chan <leonardchan@google.com>
Tue, 23 Oct 2018 17:55:35 +0000 (17:55 +0000)
This patch is a part of https://reviews.llvm.org/D48456 in an attempt to split
the casting logic up into smaller patches. This contains the code for casting
from fixed point types to boolean types.

Differential Revision: https://reviews.llvm.org/D53308

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@345063 91177308-0d34-0410-b5e6-96231b3b80d8

14 files changed:
include/clang/AST/OperationKinds.def
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/Sema.cpp
lib/Sema/SemaExpr.cpp
lib/StaticAnalyzer/Core/ExprEngineC.cpp
test/Frontend/fixed_point_to_bool.c [new file with mode: 0644]
test/Frontend/fixed_point_unknown_conversions.c

index 7fe9723365605366cd65e221fb728cc35823091e..cd19091e31d6daebd95fcd40018d1cd1717b3937 100644 (file)
@@ -201,6 +201,10 @@ CAST_OPERATION(IntegralToFloating)
 ///    (_Accum) 0.5r
 CAST_OPERATION(FixedPointCast)
 
+/// CK_FixedPointToBoolean - Fixed point to boolean.
+///    (bool) 0.5r
+CAST_OPERATION(FixedPointToBoolean)
+
 /// CK_FloatingToIntegral - Floating point to integral.  Rounds
 /// towards zero, discarding any fractional component.
 ///    (int) f
index 0f264afbc26ffa893a756ffeccc8037cc18d5fe5..e1e5c45efec4431cf1d987fff25849d97c1f4b9e 100644 (file)
@@ -1661,6 +1661,7 @@ bool CastExpr::CastConsistency() const {
   case CK_LValueBitCast:            // -> bool&
   case CK_UserDefinedConversion:    // operator bool()
   case CK_BuiltinFnToFnPtr:
+  case CK_FixedPointToBoolean:
   CheckNoBasePath:
     assert(path_empty() && "Cast kind should not have a base path!");
     break;
index a7da24db6a26553c41304ffb551a345bbbfb0b27..c64e335255efd14af96c2a9837b304e315780fe0 100644 (file)
@@ -9590,6 +9590,14 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
     return Success(IntResult, E);
   }
 
+  case CK_FixedPointToBoolean: {
+    // Unsigned padding does not affect this.
+    APValue Val;
+    if (!Evaluate(Val, Info, SubExpr))
+      return false;
+    return Success(Val.getInt().getBoolValue(), E);
+  }
+
   case CK_IntegralCast: {
     if (!Visit(SubExpr))
       return false;
@@ -10090,6 +10098,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
   case CK_AddressSpaceConversion:
   case CK_IntToOCLSampler:
   case CK_FixedPointCast:
+  case CK_FixedPointToBoolean:
     llvm_unreachable("invalid cast kind for complex value");
 
   case CK_LValueToRValue:
index c4e06b3af846bb5e08e18da6c5a4313d68340a1a..a8ee16c5fe8a9ef6c832ae8ba9737a2f5a58e5f4 100644 (file)
@@ -4154,6 +4154,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
   case CK_AddressSpaceConversion:
   case CK_IntToOCLSampler:
   case CK_FixedPointCast:
+  case CK_FixedPointToBoolean:
     return EmitUnsupportedLValue(E, "unexpected cast lvalue");
 
   case CK_Dependent:
index 7808c84c1268913da090095c065638ab0bb26082..42481939fa13235a4c2a81b7f696caf9f71033e0 100644 (file)
@@ -851,6 +851,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
   case CK_AddressSpaceConversion:
   case CK_IntToOCLSampler:
   case CK_FixedPointCast:
+  case CK_FixedPointToBoolean:
     llvm_unreachable("cast kind invalid for aggregate types");
   }
 }
index 773568e1798f119502b6ad62b35b54c6f558b444..c0b87c850e978d5b8b151ee159aae0eaf6015084 100644 (file)
@@ -509,6 +509,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
   case CK_AddressSpaceConversion:
   case CK_IntToOCLSampler:
   case CK_FixedPointCast:
+  case CK_FixedPointToBoolean:
     llvm_unreachable("invalid cast kind for complex value");
 
   case CK_FloatingRealToComplex:
index e1ad656de59a8311e5a01cf4f542d3bdd9a5e981..b8b6685cc7a9dce6bde8d4dae4fd69b44fcd1d71 100644 (file)
@@ -870,6 +870,7 @@ public:
     case CK_FloatingToBoolean:
     case CK_FloatingCast:
     case CK_FixedPointCast:
+    case CK_FixedPointToBoolean:
     case CK_ZeroToOCLOpaqueType:
       return nullptr;
     }
index be9a92a56816b94322c1871f2aad7077ff93303b..0351247e94ca8fb5a46994c3861d61aef1ecfe04 100644 (file)
@@ -1015,9 +1015,26 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
                                                QualType DstType,
                                                SourceLocation Loc,
                                                ScalarConversionOpts Opts) {
-  assert(!SrcType->isFixedPointType() && !DstType->isFixedPointType() &&
-         "Use the ScalarExprEmitter::EmitFixedPoint family functions for "
-         "handling conversions involving fixed point types.");
+  // All conversions involving fixed point types should be handled by the
+  // EmitFixedPoint family functions. This is done to prevent bloating up this
+  // function more, and although fixed point numbers are represented by
+  // integers, we do not want to follow any logic that assumes they should be
+  // treated as integers.
+  // TODO(leonardchan): When necessary, add another if statement checking for
+  // conversions to fixed point types from other types.
+  if (SrcType->isFixedPointType()) {
+    if (DstType->isFixedPointType()) {
+      return EmitFixedPointConversion(Src, SrcType, DstType, Loc);
+    } else if (DstType->isBooleanType()) {
+      // We do not need to check the padding bit on unsigned types if unsigned
+      // padding is enabled because overflow into this bit is undefined
+      // behavior.
+      return Builder.CreateIsNotNull(Src);
+    }
+
+    llvm_unreachable(
+        "Unhandled scalar conversion involving a fixed point type.");
+  }
 
   QualType NoncanonicalSrcType = SrcType;
   QualType NoncanonicalDstType = DstType;
@@ -1998,8 +2015,15 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
   }
 
   case CK_FixedPointCast:
-    return EmitFixedPointConversion(Visit(E), E->getType(), DestTy,
-                                    CE->getExprLoc());
+    return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+                                CE->getExprLoc());
+
+  case CK_FixedPointToBoolean:
+    assert(E->getType()->isFixedPointType() &&
+           "Expected src type to be fixed point type");
+    assert(DestTy->isBooleanType() && "Expected dest type to be boolean type");
+    return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+                                CE->getExprLoc());
 
   case CK_IntegralCast: {
     ScalarConversionOpts Opts;
index 5a7982a21d760ecb0437438ff15cf4a328ce324f..7c9ab170093fa3febe0c6664f19580c6ce56214c 100644 (file)
@@ -1086,6 +1086,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
       llvm_unreachable("OpenCL-specific cast in Objective-C?");
 
     case CK_FixedPointCast:
+    case CK_FixedPointToBoolean:
       llvm_unreachable("Fixed point types are disabled for Objective-C");
     }
   }
index 7e162029888de363e4c6a5f09eb0de7ce04ab950..d5d92287abd5aaeca08298c1159b441ef8677747 100644 (file)
@@ -533,8 +533,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
   case Type::STK_Floating: return CK_FloatingToBoolean;
   case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean;
   case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean;
-  case Type::STK_FixedPoint:
-    llvm_unreachable("Unknown cast from FixedPoint to boolean");
+  case Type::STK_FixedPoint: return CK_FixedPointToBoolean;
   }
   llvm_unreachable("unknown scalar type kind");
 }
index 597f220bc4c01e69e72b32f68ccc4330f6da8a63..2cee761da3c509c4beeb62c77e1bd12b1dff86b3 100644 (file)
@@ -5894,10 +5894,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
     case Type::STK_FixedPoint:
       return CK_FixedPointCast;
     case Type::STK_Bool:
-      Diag(Src.get()->getExprLoc(),
-           diag::err_unimplemented_conversion_with_fixed_point_type)
-          << DestTy;
-      return CK_IntegralToBoolean;
+      return CK_FixedPointToBoolean;
     case Type::STK_Integral:
     case Type::STK_Floating:
     case Type::STK_IntegralComplex:
@@ -12793,12 +12790,6 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
       if (Context.getLangOpts().CPlusPlus) {
         // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9:
         // operand contextually converted to bool.
-        if (resultType->getScalarTypeKind() == Type::STK_FixedPoint) {
-          return ExprError(
-              Diag(Input.get()->getExprLoc(),
-                   diag::err_unimplemented_conversion_with_fixed_point_type)
-              << resultType);
-        }
         Input = ImpCastExprToType(Input.get(), Context.BoolTy,
                                   ScalarTypeToBooleanCastKind(resultType));
       } else if (Context.getLangOpts().OpenCL &&
index bdf56af96b56e6386d1ae0c858c3e778aa8bcbd6..7a35c0acb001073ab8afdf3605362435ccee4286 100644 (file)
@@ -415,7 +415,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
       case CK_ZeroToOCLOpaqueType:
       case CK_IntToOCLSampler:
       case CK_LValueBitCast:
-      case CK_FixedPointCast: {
+      case CK_FixedPointCast:
+      case CK_FixedPointToBoolean: {
         state =
             handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
         continue;
diff --git a/test/Frontend/fixed_point_to_bool.c b/test/Frontend/fixed_point_to_bool.c
new file mode 100644 (file)
index 0000000..b5bfa6f
--- /dev/null
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s
+
+_Bool global_b = 1.0k;  // @global_b = {{*.}}global i8 1, align 1
+_Bool global_b2 = 0.0k; // @global_b2 = {{*.}}global i8 0, align 1
+
+void func() {
+  _Accum a = 0.5k;
+  unsigned _Accum ua = 0.5uk;
+  _Bool b;
+
+  // CHECK: store i8 1, i8* %b, align 1
+  // CHECK-NEXT: store i8 0, i8* %b, align 1
+  // CHECK: store i8 1, i8* %b, align 1
+  // CHECK-NEXT: store i8 0, i8* %b, align 1
+  b = 0.5k;
+  b = 0.0k;
+  b = 0.5uk;
+  b = 0.0uk;
+
+  // CHECK-NEXT: store i8 1, i8* %b, align 1
+  // CHECK-NEXT: store i8 0, i8* %b, align 1
+  // CHECK-NEXT: store i8 1, i8* %b, align 1
+  // CHECK-NEXT: store i8 0, i8* %b, align 1
+  b = (_Bool)0.5r;
+  b = (_Bool)0.0r;
+  b = (_Bool)0.5ur;
+  b = (_Bool)0.0ur;
+
+  // CHECK-NEXT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[NOTZERO:%[0-9]+]] = icmp ne i32 [[ACCUM]], 0
+  // CHECK-NEXT: %frombool = zext i1 [[NOTZERO]] to i8
+  // CHECK-NEXT: store i8 %frombool, i8* %b, align 1
+  b = a;
+
+  // CHECK-NEXT: [[ACCUM:%[0-9]+]] = load i32, i32* %ua, align 4
+  // CHECK-NEXT: [[NOTZERO:%[0-9]+]] = icmp ne i32 [[ACCUM]], 0
+  // CHECK-NEXT: %frombool1 = zext i1 [[NOTZERO]] to i8
+  // CHECK-NEXT: store i8 %frombool1, i8* %b, align 1
+  b = ua;
+
+  // CHECK-NEXT: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+  // CHECK-NEXT: [[NOTZERO:%[0-9]+]] = icmp ne i32 [[ACCUM]], 0
+  // CHECK-NEXT: br i1 [[NOTZERO]], label %if.then, label %if.end
+  if (a) {
+  }
+
+  // CHECK:      [[ACCUM:%[0-9]+]] = load i32, i32* %ua, align 4
+  // CHECK-NEXT: [[NOTZERO:%[0-9]+]] = icmp ne i32 [[ACCUM]], 0
+  // CHECK-NEXT: br i1 [[NOTZERO]], label %if.then{{[0-9]+}}, label %if.end{{[0-9]+}}
+  if (ua) {
+  }
+}
index 94b1fc32e9bd72302a099f9b5487a9405b23e5a0..0cd3d046ca0d97a878a8e25e8c94d4f88c11b5e2 100644 (file)
@@ -35,7 +35,6 @@ void func() {
   accum_ptr = ptr; // expected-warning{{incompatible pointer types assigning to '_Accum *' from 'int *'}}
   accum = i2;      // expected-error{{conversion between fixed point and 'int_t' (aka 'int') is not yet supported}}
 
-  b = accum;       // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
   c = accum;       // expected-error{{conversion between fixed point and 'char' is not yet supported}}
   i = accum;       // expected-error{{conversion between fixed point and 'int' is not yet supported}}
   f = accum;       // expected-error{{conversion between fixed point and 'float' is not yet supported}}