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 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>; +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; def ext_cxx17_attr : Extension< Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -1655,6 +1655,7 @@ case CK_IntToOCLSampler: case CK_IntegralToFixedPoint: case CK_FixedPointCast: + case CK_FixedPointToFloating: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -9165,6 +9165,8 @@ case CK_IntegralToFixedPoint: llvm_unreachable( "IntExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint"); // TODO + case CK_FixedPointToFloating: + llvm_unreachable("CK_FixedPointCast"); // TODO case CK_BaseToDerived: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: @@ -9760,6 +9762,8 @@ case CK_IntegralToFixedPoint: llvm_unreachable( "ComplexExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint"); // TODO + case CK_FixedPointToFloating: + llvm_unreachable("CK_FixedPointCast"); // TODO case CK_BitCast: case CK_BaseToDerived: case CK_DerivedToBase: Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -4049,6 +4049,8 @@ case CK_IntegralToFixedPoint: llvm_unreachable( "CodeGenFunction::EmitCastLValue CK_IntegralToFixedPoint"); // TODO + case CK_FixedPointToFloating: + llvm_unreachable("CK_FixedPointToFloating"); // TODO case CK_ToVoid: case CK_BitCast: case CK_ArrayToPointerDecay: Index: lib/CodeGen/CGExprAgg.cpp =================================================================== --- lib/CodeGen/CGExprAgg.cpp +++ lib/CodeGen/CGExprAgg.cpp @@ -676,6 +676,8 @@ case CK_IntegralToFixedPoint: llvm_unreachable( "AggExprEmitter::VisitCastExpr CK_IntegralToFixedPoint"); // TODO + case CK_FixedPointToFloating: + llvm_unreachable("CK_FixedPointToFloating"); // TODO case CK_Dynamic: { // FIXME: Can this actually happen? We have no test coverage for it. assert(isa(E) && "CK_Dynamic without a dynamic_cast?"); Index: lib/CodeGen/CGExprComplex.cpp =================================================================== --- lib/CodeGen/CGExprComplex.cpp +++ lib/CodeGen/CGExprComplex.cpp @@ -451,6 +451,8 @@ case CK_IntegralToFixedPoint: llvm_unreachable( "ComplexExprEmitter::EmitCast CK_IntegralToFixedPoint"); // TODO + case CK_FixedPointToFloating: + llvm_unreachable("CK_FixedPointToFloating"); // TODO 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/CGExprConstant.cpp =================================================================== --- lib/CodeGen/CGExprConstant.cpp +++ lib/CodeGen/CGExprConstant.cpp @@ -686,6 +686,8 @@ 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: Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -1858,6 +1858,15 @@ 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/Edit/RewriteObjCFoundationAPI.cpp =================================================================== --- lib/Edit/RewriteObjCFoundationAPI.cpp +++ lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1008,6 +1008,9 @@ case CK_IntegralToFixedPoint: llvm_unreachable( "rewriteToNumericBoxedExpression CK_IntegralToFixedPoint"); // TODO + case CK_FixedPointToFloating: + llvm_unreachable( + "Unimplemented logic for CK_FixedPointToFloating"); case CK_LValueToRValue: case CK_NoOp: case CK_UserDefinedConversion: 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/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -1029,6 +1029,21 @@ 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 +1072,20 @@ 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 +1242,7 @@ CK_IntegralRealToComplex); return ComplexType; } + /// \brief Handle arithmetic conversion from integer to fixed point. Helper /// function of UsualArithmeticConversions() static QualType handleIntToFixedPointConversion(Sema &S, @@ -6041,9 +6066,20 @@ } 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/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -326,6 +326,8 @@ case CK_IntegralToFixedPoint: llvm_unreachable( "ExprEngine::VisitCast CK_IntegralToFixedPoint"); // TODO + case CK_FixedPointToFloating: + llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating"); case CK_LValueToRValue: llvm_unreachable("LValueToRValue casts handled earlier."); case CK_ToVoid: 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); }