# Changeset View

Changeset View

# Standalone View

Standalone View

# lib/Sema/SemaExpr.cpp

- This file is larger than 256 KB, so syntax highlighting is disabled by default.

Show First 20 Lines • Show All 1252 Lines • ▼ Show 20 Line(s) | 1248 | static QualType handleIntToFixedPointConversion(Sema &S, | |||
---|---|---|---|---|---|

1253 | assert(IntTy->isIntegerType()); | 1253 | assert(IntTy->isIntegerType()); | ||

1254 | assert(FixedPointTy->isFixedPointType()); | 1254 | assert(FixedPointTy->isFixedPointType()); | ||

1255 | 1255 | | |||

1256 | IntExpr = | 1256 | IntExpr = | ||

1257 | S.ImpCastExprToType(IntExpr.get(), FixedPointTy, CK_IntegralToFixedPoint); | 1257 | S.ImpCastExprToType(IntExpr.get(), FixedPointTy, CK_IntegralToFixedPoint); | ||

1258 | return FixedPointTy; | 1258 | return FixedPointTy; | ||

1259 | } | 1259 | } | ||

1260 | 1260 | | |||

1261 | /// \brief Handle arithmethic conversion with fixed point types. Helper | 1261 | /// \brief Handle arithmethic conversion with fixed point types. The usual | ||

1262 | /// function of UsualArithmeticConversions(). | 1262 | /// arithmetic conversions do not apply to fixed point type conversions between | ||

1263 | /// integers or other fixed point types due to potential loss of precision. | ||||

1264 | /// For this case of fixed point types, the resulting type in a binary operation | ||||

ebevhan: This is incorrect. The resulting type of a binary operation is absolutely one of the two… | |||||

1265 | /// does not need to be exactly one of the 2 operand types. | ||||

1266 | /// Implemented according to Clause 6.3.1.8 of ISO/IEC JTC1 SC22 WG14 N1169. | ||||

1263 | static QualType handleFixedPointConversion(Sema &S, ExprResult &LHS, | 1267 | static QualType handleFixedPointConversion(Sema &S, ExprResult &LHS, | ||

1264 | ExprResult &RHS, QualType LHSType, | 1268 | ExprResult &RHS, QualType LHSType, | ||

1265 | QualType RHSType, | 1269 | QualType RHSType, | ||

1266 | bool IsCompAssign) { | 1270 | bool IsCompAssign) { | ||

1267 | // At this point, the only other type we should be able to convert to is | 1271 | // At this point, the only other type we should be able to convert to is | ||

1268 | // integer types since all prior types were handled beforehand in | 1272 | // integer types since all prior types were handled beforehand in | ||

1269 | // UsualArithmeticConventions(). | 1273 | // UsualArithmeticConventions(). | ||

1270 | bool LHSFixed = LHSType->isFixedPointType(); | 1274 | bool LHSFixed = LHSType->isFixedPointType(); | ||

1271 | bool RHSFixed = RHSType->isFixedPointType(); | 1275 | bool RHSFixed = RHSType->isFixedPointType(); | ||

1272 | 1276 | | |||

1273 | if (LHSFixed && RHSFixed) { | 1277 | if (LHSFixed && RHSFixed) { | ||

1274 | // Cast up the smaller operand to the bigger | | |||

1275 | int order = S.Context.getFixedPointTypeOrder(LHSType, RHSType); | | |||

1276 | if (order > 0) { | | |||

1277 | RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FixedPointCast); | | |||

1278 | return LHSType; | | |||

1279 | } else if (!order) { | | |||

1280 | bool LHSSigned = LHSType->isSignedFixedPointType(); | 1278 | bool LHSSigned = LHSType->isSignedFixedPointType(); | ||

1281 | bool RHSSigned = RHSType->isSignedFixedPointType(); | 1279 | bool RHSSigned = RHSType->isSignedFixedPointType(); | ||

1282 | if (LHSSigned && !RHSSigned) { | 1280 | bool LHSSat = LHSType->isSaturatedFixedPointType(); | ||

1283 | RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FixedPointCast); | 1281 | bool RHSSat = RHSType->isSaturatedFixedPointType(); | ||

1284 | return LHSType; | 1282 | int order = S.Context.getFixedPointTypeOrder(LHSType, RHSType); | ||

1285 | } else if (!LHSSigned && RHSSigned) { | 1283 | | ||

1286 | if (!IsCompAssign) | 1284 | QualType result = (order >= 0) ? LHSType : RHSType; | ||

1287 | LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FixedPointCast); | 1285 | if (LHSSigned || RHSSigned) | ||

1288 | return RHSType; | 1286 | result = getCorrespondingSignedFixedPointType(S.Context, *result); | ||

1289 | } else { | 1287 | if (LHSSat || RHSSat) | ||

1290 | assert(LHSType == RHSType); | 1288 | result = getCorrespondingSaturatedFixedPointType(S.Context, *result); | ||

1291 | return LHSType; | 1289 | | ||

1292 | } | 1290 | if (LHSType != result && !IsCompAssign) | ||

1293 | } else { | 1291 | LHS = S.ImpCastExprToType(LHS.get(), result, CK_FixedPointCast); | ||

1294 | if (!IsCompAssign) | 1292 | | ||

1295 | LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FixedPointCast); | 1293 | if (RHSType != result) | ||

1296 | return RHSType; | 1294 | RHS = S.ImpCastExprToType(RHS.get(), result, CK_FixedPointCast); | ||

1297 | } | 1295 | | ||

1296 | return result; | ||||

1298 | } else if (LHSFixed) { | 1297 | } else if (LHSFixed) { | ||

1299 | assert(RHSType->isIntegerType()); | 1298 | assert(RHSType->isIntegerType()); | ||

1300 | return handleIntToFixedPointConversion(S, LHS, RHS, LHSType, RHSType); | 1299 | return handleIntToFixedPointConversion(S, LHS, RHS, LHSType, RHSType); | ||

1301 | } else if (RHSFixed) { | 1300 | } else if (RHSFixed) { | ||

1302 | assert(LHSType->isIntegerType()); | 1301 | assert(LHSType->isIntegerType()); | ||

1303 | return handleIntToFixedPointConversion(S, RHS, LHS, RHSType, LHSType); | 1302 | return handleIntToFixedPointConversion(S, RHS, LHS, RHSType, LHSType); | ||

1304 | } else { | 1303 | } else { | ||

1305 | llvm_unreachable( | 1304 | llvm_unreachable( | ||

▲ Show 20 Lines • Show All 2238 Lines • ▼ Show 20 Line(s) | 3425 | if (Literal.isFixedPointLiteral()) { | |||

3544 | 3543 | | |||

3545 | // TODO: Check sizes to make sure we don't overflow or fit a value that | 3544 | // TODO: Check sizes to make sure we don't overflow or fit a value that | ||

3546 | // can't fit into the number of bits we have. | 3545 | // can't fit into the number of bits we have. | ||

3547 | double float_val = Val.convertToDouble(); | 3546 | double float_val = Val.convertToDouble(); | ||

3548 | assert(float_val >= 0); | 3547 | assert(float_val >= 0); | ||

3549 | double int_part; | 3548 | double int_part; | ||

3550 | double fract_part = modf(float_val, &int_part); | 3549 | double fract_part = modf(float_val, &int_part); | ||

3551 | uint64_t int_part_as_int = static_cast<uint64_t>(int_part); | 3550 | uint64_t int_part_as_int = static_cast<uint64_t>(int_part); | ||

3551 | uint64_t fract_part_as_int = | ||||

ebevhanUnsubmitted Not Done ReplyShould these changes not be part of the patch that adds the literal parsing code? ebevhan: Should these changes not be part of the patch that adds the literal parsing code? | |||||

3552 | static_cast<uint64_t>(fract_part * (1ULL << fbits)); | ||||

3553 | uint64_t final_fixed_point_as_int = | ||||

3554 | (int_part_as_int << fbits) + fract_part_as_int; | ||||

3552 | 3555 | | |||

3553 | if (Literal.fixedPointType == FPT_FRACT && int_part_as_int) { | 3556 | if (Literal.fixedPointType == FPT_FRACT) { | ||

3557 | if (float_val > 1) { | ||||

3554 | Diag(Tok.getLocation(), diag::err_integral_part_on_fract); | 3558 | Diag(Tok.getLocation(), diag::err_integral_part_on_fract); | ||

3555 | } else { | 3559 | } else if (int_part_as_int == 1) { | ||

3560 | // Represent 1.0r as the max possible value for this _Fract type | ||||

3561 | final_fixed_point_as_int = (1ULL << fbits) - 1; | ||||

3562 | } | ||||

3563 | } else if (Literal.fixedPointType == FPT_ACCUM) { | ||||

3556 | // Make sure the integral part fits into the integral bits we have. | 3564 | // Make sure the integral part fits into the integral bits we have. | ||

3557 | uint64_t max_int_val = 0; | 3565 | uint64_t max_int_val = 0; | ||

3558 | if (isSigned) { | 3566 | if (isSigned) { | ||

3559 | max_int_val = 1ULL << (ibits - 1); // min signed is -2^(n-1) | 3567 | max_int_val = 1ULL << (ibits - 1); // min signed is -2^(n-1) | ||

3560 | } else { | 3568 | } else { | ||

3561 | max_int_val = (1ULL << ibits) - 1; | 3569 | max_int_val = (1ULL << ibits) - 1; | ||

3562 | } | 3570 | } | ||

3563 | 3571 | | |||

3564 | // TODO: What should be done for literals with no unsigned suffix whose | 3572 | // TODO: What should be done for literals with no unsigned suffix whose | ||

3565 | // value is equal to the absolute value of the smallest possible value for | 3573 | // value is equal to the absolute value of the smallest possible value for | ||

3566 | // that type. Ie. 128.0hk -> -128.0hk? What happens is user writes | 3574 | // that type. Ie. 128.0hk -> -128.0hk? What happens is user writes | ||

3567 | // "-128.0hk" since we are only interpretting a literal and do now know of | 3575 | // "-128.0hk" since we are only interpretting a literal and do now know of | ||

3568 | // the unary operator? | 3576 | // the unary operator? | ||

3569 | if (int_part_as_int > max_int_val) { | 3577 | if (int_part_as_int > max_int_val) { | ||

3570 | Diag(Tok.getLocation(), diag::err_integral_part_of_accum_too_large) | 3578 | Diag(Tok.getLocation(), diag::err_integral_part_of_accum_too_large) | ||

3571 | << (isSigned ? 0 : 1); | 3579 | << (isSigned ? 0 : 1); | ||

3572 | } | 3580 | } | ||

3573 | } | 3581 | } | ||

3574 | 3582 | | |||

3575 | uint64_t fract_part_as_int = | | |||

3576 | static_cast<uint64_t>(fract_part * (1ULL << fbits)); | | |||

3577 | uint64_t final_fixed_point_as_int = | | |||

3578 | (int_part_as_int << fbits) + fract_part_as_int; | | |||

3579 | | ||||

3580 | llvm::APInt ResultVal(bit_width, final_fixed_point_as_int, isSigned); | 3583 | llvm::APInt ResultVal(bit_width, final_fixed_point_as_int, isSigned); | ||

3581 | Res = FixedPointLiteral::CreateFromRawInt(Context, ResultVal, Ty, | 3584 | Res = FixedPointLiteral::CreateFromRawInt(Context, ResultVal, Ty, | ||

3582 | Tok.getLocation()); | 3585 | Tok.getLocation()); | ||

3583 | } else if (Literal.isFloatingLiteral()) { | 3586 | } else if (Literal.isFloatingLiteral()) { | ||

3584 | QualType Ty; | 3587 | QualType Ty; | ||

3585 | if (Literal.isHalf){ | 3588 | if (Literal.isHalf){ | ||

3586 | if (getOpenCLOptions().isEnabled("cl_khr_fp16")) | 3589 | if (getOpenCLOptions().isEnabled("cl_khr_fp16")) | ||

3587 | Ty = Context.HalfTy; | 3590 | Ty = Context.HalfTy; | ||

▲ Show 20 Lines • Show All 12910 Lines • Show Last 20 Lines |

This is incorrect. The resulting type of a binary operation is absolutely one of the two operands. However, the calculation might be done as a type that is not one of the two, as it must be done in the full (combined) precision of both operands.

That is a detail reserved for CodeGen, however.