leonardchan created this revision. leonardchan added reviewers: ebevhan, rjmccall, bjope. leonardchan added a project: clang.
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. Repository: rC Clang https://reviews.llvm.org/D53308 Files: clang/include/clang/AST/OperationKinds.def clang/lib/AST/Expr.cpp clang/lib/AST/ExprConstant.cpp clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CGExprAgg.cpp clang/lib/CodeGen/CGExprComplex.cpp clang/lib/CodeGen/CGExprConstant.cpp clang/lib/CodeGen/CGExprScalar.cpp clang/lib/Edit/RewriteObjCFoundationAPI.cpp clang/lib/Sema/Sema.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp clang/test/Frontend/fixed_point_to_bool.c clang/test/Frontend/fixed_point_unknown_conversions.c
Index: clang/test/Frontend/fixed_point_unknown_conversions.c =================================================================== --- clang/test/Frontend/fixed_point_unknown_conversions.c +++ clang/test/Frontend/fixed_point_unknown_conversions.c @@ -35,7 +35,6 @@ 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}} Index: clang/test/Frontend/fixed_point_to_bool.c =================================================================== --- /dev/null +++ clang/test/Frontend/fixed_point_to_bool.c @@ -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: clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -416,7 +416,8 @@ case CK_ZeroToOCLQueue: 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; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -5894,10 +5894,7 @@ 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 @@ 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: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -534,7 +534,7 @@ 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"); + return CK_FixedPointToBoolean; } llvm_unreachable("unknown scalar type kind"); } Index: clang/lib/Edit/RewriteObjCFoundationAPI.cpp =================================================================== --- clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1087,6 +1087,7 @@ 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: clang/lib/CodeGen/CGExprScalar.cpp =================================================================== --- clang/lib/CodeGen/CGExprScalar.cpp +++ clang/lib/CodeGen/CGExprScalar.cpp @@ -1015,9 +1015,26 @@ 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 since they + // are set to zero after operations that allow a bit to overflow into + // them. + return Builder.CreateIsNotNull(Src); + } + + llvm_unreachable( + "Unhandled scalar conversion involving a fixed point type."); + } QualType NoncanonicalSrcType = SrcType; QualType NoncanonicalDstType = DstType; @@ -1998,8 +2015,17 @@ } case CK_FixedPointCast: - return EmitFixedPointConversion(Visit(E), E->getType(), DestTy, - CE->getExprLoc()); + return EmitScalarConversion(Visit(E), E->getType(), DestTy, + CE->getExprLoc()); + + case CK_FixedPointToBoolean: + // We do not check the padding bit on unsigned types since they are zero'd + // out on operations that can cause overflow into the bit. + 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: clang/lib/CodeGen/CGExprConstant.cpp =================================================================== --- clang/lib/CodeGen/CGExprConstant.cpp +++ clang/lib/CodeGen/CGExprConstant.cpp @@ -872,6 +872,7 @@ case CK_ZeroToOCLEvent: case CK_ZeroToOCLQueue: case CK_FixedPointCast: + case CK_FixedPointToBoolean: return nullptr; } llvm_unreachable("Invalid CastKind"); Index: clang/lib/CodeGen/CGExprComplex.cpp =================================================================== --- clang/lib/CodeGen/CGExprComplex.cpp +++ clang/lib/CodeGen/CGExprComplex.cpp @@ -510,6 +510,7 @@ case CK_AddressSpaceConversion: case CK_IntToOCLSampler: case CK_FixedPointCast: + case CK_FixedPointToBoolean: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: Index: clang/lib/CodeGen/CGExprAgg.cpp =================================================================== --- clang/lib/CodeGen/CGExprAgg.cpp +++ clang/lib/CodeGen/CGExprAgg.cpp @@ -852,6 +852,7 @@ case CK_AddressSpaceConversion: case CK_IntToOCLSampler: case CK_FixedPointCast: + case CK_FixedPointToBoolean: llvm_unreachable("cast kind invalid for aggregate types"); } } Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -4154,6 +4154,7 @@ case CK_AddressSpaceConversion: case CK_IntToOCLSampler: case CK_FixedPointCast: + case CK_FixedPointToBoolean: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -9591,6 +9591,14 @@ 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; @@ -10092,6 +10100,7 @@ case CK_AddressSpaceConversion: case CK_IntToOCLSampler: case CK_FixedPointCast: + case CK_FixedPointToBoolean: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -1662,6 +1662,7 @@ 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: clang/include/clang/AST/OperationKinds.def =================================================================== --- clang/include/clang/AST/OperationKinds.def +++ clang/include/clang/AST/OperationKinds.def @@ -201,6 +201,10 @@ /// (_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
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits