| ... | @@ -169,7 +169,11 @@ fn addWithOverflowScalar( | ... | @@ -169,7 +169,11 @@ fn addWithOverflowScalar( |
| 169 | .overflow_bit = .undef_u1, | 169 | .overflow_bit = .undef_u1, |
| 170 | .wrapped_result = try pt.undefValue(ty), | 170 | .wrapped_result = try pt.undefValue(ty), |
| 171 | }; | 171 | }; |
| 172 | return intAddWithOverflow(sema, lhs, rhs, ty); | 172 | const res = try intAddWithOverflow(sema, lhs, rhs, ty); |
| | 173 | return .{ |
| | 174 | .overflow_bit = if (res.overflow) .one_u1 else .zero_u1, |
| | 175 | .wrapped_result = res.wrapped_result, |
| | 176 | }; |
| 173 | } | 177 | } |
| 174 | | 178 | |
| 175 | /// `lhs` and `rhs` are of type `ty`. | 179 | /// `lhs` and `rhs` are of type `ty`. |
| ... | @@ -227,7 +231,12 @@ fn subWithOverflowScalar( | ... | @@ -227,7 +231,12 @@ fn subWithOverflowScalar( |
| 227 | .overflow_bit = .undef_u1, | 231 | .overflow_bit = .undef_u1, |
| 228 | .wrapped_result = try pt.undefValue(ty), | 232 | .wrapped_result = try pt.undefValue(ty), |
| 229 | }; | 233 | }; |
| 230 | return intSubWithOverflow(sema, lhs, rhs, ty); | 234 | |
| | 235 | const res = try intSubWithOverflow(sema, lhs, rhs, ty); |
| | 236 | return .{ |
| | 237 | .overflow_bit = if (res.overflow) .one_u1 else .zero_u1, |
| | 238 | .wrapped_result = res.wrapped_result, |
| | 239 | }; |
| 231 | } | 240 | } |
| 232 | | 241 | |
| 233 | /// `lhs` and `rhs` are of type `ty`. | 242 | /// `lhs` and `rhs` are of type `ty`. |
| ... | @@ -285,7 +294,11 @@ fn mulWithOverflowScalar( | ... | @@ -285,7 +294,11 @@ fn mulWithOverflowScalar( |
| 285 | .overflow_bit = .undef_u1, | 294 | .overflow_bit = .undef_u1, |
| 286 | .wrapped_result = try pt.undefValue(ty), | 295 | .wrapped_result = try pt.undefValue(ty), |
| 287 | }; | 296 | }; |
| 288 | return intMulWithOverflow(sema, lhs, rhs, ty); | 297 | const res = try intMulWithOverflow(sema, lhs, rhs, ty); |
| | 298 | return .{ |
| | 299 | .overflow_bit = if (res.overflow) .one_u1 else .zero_u1, |
| | 300 | .wrapped_result = res.wrapped_result, |
| | 301 | }; |
| 289 | } | 302 | } |
| 290 | | 303 | |
| 291 | /// Applies the `+` operator to comptime-known values. | 304 | /// Applies the `+` operator to comptime-known values. |
| ... | @@ -1108,7 +1121,7 @@ fn shlWithOverflowScalar( | ... | @@ -1108,7 +1121,7 @@ fn shlWithOverflowScalar( |
| 1108 | .int => { | 1121 | .int => { |
| 1109 | const result = try intShlWithOverflow(sema, block, lhs_ty, lhs_val, rhs_val, rhs_src, true, vec_idx); | 1122 | const result = try intShlWithOverflow(sema, block, lhs_ty, lhs_val, rhs_val, rhs_src, true, vec_idx); |
| 1110 | return .{ | 1123 | return .{ |
| 1111 | .overflow_bit = try pt.intValue(.u1, @intFromBool(result.overflow)), | 1124 | .overflow_bit = if (result.overflow) .one_u1 else .zero_u1, |
| 1112 | .wrapped_result = result.val, | 1125 | .wrapped_result = result.val, |
| 1113 | }; | 1126 | }; |
| 1114 | }, | 1127 | }, |
| ... | @@ -1390,17 +1403,12 @@ pub fn byteSwap(sema: *Sema, val: Value, ty: Type) CompileError!Value { | ... | @@ -1390,17 +1403,12 @@ pub fn byteSwap(sema: *Sema, val: Value, ty: Type) CompileError!Value { |
| 1390 | /// If the value overflowed the type, returns a comptime_int instead. | 1403 | /// If the value overflowed the type, returns a comptime_int instead. |
| 1391 | /// Only supports scalars. | 1404 | /// Only supports scalars. |
| 1392 | fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: bool, val: Value } { | 1405 | fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: bool, val: Value } { |
| 1393 | const pt = sema.pt; | | |
| 1394 | const zcu = pt.zcu; | | |
| 1395 | switch (ty.toIntern()) { | 1406 | switch (ty.toIntern()) { |
| 1396 | .comptime_int_type => return .{ .overflow = false, .val = try comptimeIntAdd(sema, lhs, rhs) }, | 1407 | .comptime_int_type => return .{ .overflow = false, .val = try comptimeIntAdd(sema, lhs, rhs) }, |
| 1397 | else => { | 1408 | else => { |
| 1398 | const res = try intAddWithOverflowInner(sema, lhs, rhs, ty); | 1409 | const res = try intAddWithOverflowInner(sema, lhs, rhs, ty); |
| 1399 | return switch (res.overflow_bit.toUnsignedInt(zcu)) { | 1410 | if (res.overflow) return .{ .overflow = true, .val = try comptimeIntAdd(sema, lhs, rhs) }; |
| 1400 | 0 => .{ .overflow = false, .val = res.wrapped_result }, | 1411 | return .{ .overflow = false, .val = res.wrapped_result }; |
| 1401 | 1 => .{ .overflow = true, .val = try comptimeIntAdd(sema, lhs, rhs) }, | | |
| 1402 | else => unreachable, | | |
| 1403 | }; | | |
| 1404 | }, | 1412 | }, |
| 1405 | } | 1413 | } |
| 1406 | } | 1414 | } |
| ... | @@ -1408,8 +1416,19 @@ fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: boo | ... | @@ -1408,8 +1416,19 @@ fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: boo |
| 1408 | fn comptimeIntAdd(sema: *Sema, lhs: Value, rhs: Value) !Value { | 1416 | fn comptimeIntAdd(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 1409 | const pt = sema.pt; | 1417 | const pt = sema.pt; |
| 1410 | const zcu = pt.zcu; | 1418 | const zcu = pt.zcu; |
| 1411 | // TODO is this a performance issue? maybe we should try the operation without | 1419 | |
| 1412 | // resorting to BigInt first. | 1420 | // Try the operation without resorting to BigInt first. |
| | 1421 | if (lhs.getUnsignedInt(zcu)) |lhs_val| { |
| | 1422 | if (rhs.getUnsignedInt(zcu)) |rhs_val| { |
| | 1423 | const result, const overflow = @addWithOverflow(lhs_val, rhs_val); |
| | 1424 | |
| | 1425 | if (overflow == 0) { |
| | 1426 | return pt.intValue(.comptime_int, result); |
| | 1427 | } |
| | 1428 | // It would overflow, fall back to BigInt. |
| | 1429 | } |
| | 1430 | } |
| | 1431 | |
| 1413 | var lhs_space: Value.BigIntSpace = undefined; | 1432 | var lhs_space: Value.BigIntSpace = undefined; |
| 1414 | var rhs_space: Value.BigIntSpace = undefined; | 1433 | var rhs_space: Value.BigIntSpace = undefined; |
| 1415 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); | 1434 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); |
| ... | @@ -1422,17 +1441,17 @@ fn comptimeIntAdd(sema: *Sema, lhs: Value, rhs: Value) !Value { | ... | @@ -1422,17 +1441,17 @@ fn comptimeIntAdd(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 1422 | result_bigint.add(lhs_bigint, rhs_bigint); | 1441 | result_bigint.add(lhs_bigint, rhs_bigint); |
| 1423 | return pt.intValue_big(.comptime_int, result_bigint.toConst()); | 1442 | return pt.intValue_big(.comptime_int, result_bigint.toConst()); |
| 1424 | } | 1443 | } |
| 1425 | fn intAddWithOverflow(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResult { | 1444 | fn intAddWithOverflow(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResultInt { |
| 1426 | switch (ty.toIntern()) { | 1445 | switch (ty.toIntern()) { |
| 1427 | .comptime_int_type => return .{ | 1446 | .comptime_int_type => return .{ |
| 1428 | .overflow_bit = .zero_u1, | 1447 | .overflow = false, |
| 1429 | .wrapped_result = try comptimeIntAdd(sema, lhs, rhs), | 1448 | .wrapped_result = try comptimeIntAdd(sema, lhs, rhs), |
| 1430 | }, | 1449 | }, |
| 1431 | else => return intAddWithOverflowInner(sema, lhs, rhs, ty), | 1450 | else => return intAddWithOverflowInner(sema, lhs, rhs, ty), |
| 1432 | } | 1451 | } |
| 1433 | } | 1452 | } |
| 1434 | /// Like `intAddWithOverflow`, but asserts that `ty` is not `Type.comptime_int`. | 1453 | /// Like `intAddWithOverflow`, but asserts that `ty` is not `Type.comptime_int`. |
| 1435 | fn intAddWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResult { | 1454 | fn intAddWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResultInt { |
| 1436 | assert(ty.toIntern() != .comptime_int_type); | 1455 | assert(ty.toIntern() != .comptime_int_type); |
| 1437 | const pt = sema.pt; | 1456 | const pt = sema.pt; |
| 1438 | const zcu = pt.zcu; | 1457 | const zcu = pt.zcu; |
| ... | @@ -1448,7 +1467,7 @@ fn intAddWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value | ... | @@ -1448,7 +1467,7 @@ fn intAddWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value |
| 1448 | var result_bigint: BigIntMutable = .{ .limbs = limbs, .positive = undefined, .len = undefined }; | 1467 | var result_bigint: BigIntMutable = .{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1449 | const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); | 1468 | const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| 1450 | return .{ | 1469 | return .{ |
| 1451 | .overflow_bit = try pt.intValue(.u1, @intFromBool(overflowed)), | 1470 | .overflow = overflowed, |
| 1452 | .wrapped_result = try pt.intValue_big(ty, result_bigint.toConst()), | 1471 | .wrapped_result = try pt.intValue_big(ty, result_bigint.toConst()), |
| 1453 | }; | 1472 | }; |
| 1454 | } | 1473 | } |
| ... | @@ -1472,17 +1491,12 @@ fn intAddSat(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { | ... | @@ -1472,17 +1491,12 @@ fn intAddSat(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 1472 | /// If the value overflowed the type, returns a comptime_int instead. | 1491 | /// If the value overflowed the type, returns a comptime_int instead. |
| 1473 | /// Only supports scalars. | 1492 | /// Only supports scalars. |
| 1474 | fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: bool, val: Value } { | 1493 | fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: bool, val: Value } { |
| 1475 | const pt = sema.pt; | | |
| 1476 | const zcu = pt.zcu; | | |
| 1477 | switch (ty.toIntern()) { | 1494 | switch (ty.toIntern()) { |
| 1478 | .comptime_int_type => return .{ .overflow = false, .val = try comptimeIntSub(sema, lhs, rhs) }, | 1495 | .comptime_int_type => return .{ .overflow = false, .val = try comptimeIntSub(sema, lhs, rhs) }, |
| 1479 | else => { | 1496 | else => { |
| 1480 | const res = try intSubWithOverflowInner(sema, lhs, rhs, ty); | 1497 | const res = try intSubWithOverflowInner(sema, lhs, rhs, ty); |
| 1481 | return switch (res.overflow_bit.toUnsignedInt(zcu)) { | 1498 | if (res.overflow) return .{ .overflow = true, .val = try comptimeIntSub(sema, lhs, rhs) }; |
| 1482 | 0 => .{ .overflow = false, .val = res.wrapped_result }, | 1499 | return .{ .overflow = false, .val = res.wrapped_result }; |
| 1483 | 1 => .{ .overflow = true, .val = try comptimeIntSub(sema, lhs, rhs) }, | | |
| 1484 | else => unreachable, | | |
| 1485 | }; | | |
| 1486 | }, | 1500 | }, |
| 1487 | } | 1501 | } |
| 1488 | } | 1502 | } |
| ... | @@ -1490,8 +1504,19 @@ fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: boo | ... | @@ -1490,8 +1504,19 @@ fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: boo |
| 1490 | fn comptimeIntSub(sema: *Sema, lhs: Value, rhs: Value) !Value { | 1504 | fn comptimeIntSub(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 1491 | const pt = sema.pt; | 1505 | const pt = sema.pt; |
| 1492 | const zcu = pt.zcu; | 1506 | const zcu = pt.zcu; |
| 1493 | // TODO is this a performance issue? maybe we should try the operation without | 1507 | |
| 1494 | // resorting to BigInt first. | 1508 | // Try the operation without resorting to BigInt first. |
| | 1509 | if (lhs.getUnsignedInt(zcu)) |lhs_val| { |
| | 1510 | if (rhs.getUnsignedInt(zcu)) |rhs_val| { |
| | 1511 | const result, const overflow = @subWithOverflow(lhs_val, rhs_val); |
| | 1512 | |
| | 1513 | if (overflow == 0) { |
| | 1514 | return pt.intValue(.comptime_int, result); |
| | 1515 | } |
| | 1516 | // It would overflow, fall back to BigInt. |
| | 1517 | } |
| | 1518 | } |
| | 1519 | |
| 1495 | var lhs_space: Value.BigIntSpace = undefined; | 1520 | var lhs_space: Value.BigIntSpace = undefined; |
| 1496 | var rhs_space: Value.BigIntSpace = undefined; | 1521 | var rhs_space: Value.BigIntSpace = undefined; |
| 1497 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); | 1522 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); |
| ... | @@ -1504,17 +1529,17 @@ fn comptimeIntSub(sema: *Sema, lhs: Value, rhs: Value) !Value { | ... | @@ -1504,17 +1529,17 @@ fn comptimeIntSub(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 1504 | result_bigint.sub(lhs_bigint, rhs_bigint); | 1529 | result_bigint.sub(lhs_bigint, rhs_bigint); |
| 1505 | return pt.intValue_big(.comptime_int, result_bigint.toConst()); | 1530 | return pt.intValue_big(.comptime_int, result_bigint.toConst()); |
| 1506 | } | 1531 | } |
| 1507 | fn intSubWithOverflow(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResult { | 1532 | fn intSubWithOverflow(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResultInt { |
| 1508 | switch (ty.toIntern()) { | 1533 | switch (ty.toIntern()) { |
| 1509 | .comptime_int_type => return .{ | 1534 | .comptime_int_type => return .{ |
| 1510 | .overflow_bit = .zero_u1, | 1535 | .overflow = false, |
| 1511 | .wrapped_result = try comptimeIntSub(sema, lhs, rhs), | 1536 | .wrapped_result = try comptimeIntSub(sema, lhs, rhs), |
| 1512 | }, | 1537 | }, |
| 1513 | else => return intSubWithOverflowInner(sema, lhs, rhs, ty), | 1538 | else => return intSubWithOverflowInner(sema, lhs, rhs, ty), |
| 1514 | } | 1539 | } |
| 1515 | } | 1540 | } |
| 1516 | /// Like `intSubWithOverflow`, but asserts that `ty` is not `Type.comptime_int`. | 1541 | /// Like `intSubWithOverflow`, but asserts that `ty` is not `Type.comptime_int`. |
| 1517 | fn intSubWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResult { | 1542 | fn intSubWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResultInt { |
| 1518 | assert(ty.toIntern() != .comptime_int_type); | 1543 | assert(ty.toIntern() != .comptime_int_type); |
| 1519 | const pt = sema.pt; | 1544 | const pt = sema.pt; |
| 1520 | const zcu = pt.zcu; | 1545 | const zcu = pt.zcu; |
| ... | @@ -1530,7 +1555,7 @@ fn intSubWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value | ... | @@ -1530,7 +1555,7 @@ fn intSubWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value |
| 1530 | var result_bigint: BigIntMutable = .{ .limbs = limbs, .positive = undefined, .len = undefined }; | 1555 | var result_bigint: BigIntMutable = .{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1531 | const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); | 1556 | const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| 1532 | return .{ | 1557 | return .{ |
| 1533 | .overflow_bit = try pt.intValue(.u1, @intFromBool(overflowed)), | 1558 | .overflow = overflowed, |
| 1534 | .wrapped_result = try pt.intValue_big(ty, result_bigint.toConst()), | 1559 | .wrapped_result = try pt.intValue_big(ty, result_bigint.toConst()), |
| 1535 | }; | 1560 | }; |
| 1536 | } | 1561 | } |
| ... | @@ -1554,17 +1579,12 @@ fn intSubSat(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { | ... | @@ -1554,17 +1579,12 @@ fn intSubSat(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value { |
| 1554 | /// If the value overflowed the type, returns a comptime_int instead. | 1579 | /// If the value overflowed the type, returns a comptime_int instead. |
| 1555 | /// Only supports scalars. | 1580 | /// Only supports scalars. |
| 1556 | fn intMul(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: bool, val: Value } { | 1581 | fn intMul(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: bool, val: Value } { |
| 1557 | const pt = sema.pt; | | |
| 1558 | const zcu = pt.zcu; | | |
| 1559 | switch (ty.toIntern()) { | 1582 | switch (ty.toIntern()) { |
| 1560 | .comptime_int_type => return .{ .overflow = false, .val = try comptimeIntMul(sema, lhs, rhs) }, | 1583 | .comptime_int_type => return .{ .overflow = false, .val = try comptimeIntMul(sema, lhs, rhs) }, |
| 1561 | else => { | 1584 | else => { |
| 1562 | const res = try intMulWithOverflowInner(sema, lhs, rhs, ty); | 1585 | const res = try intMulWithOverflowInner(sema, lhs, rhs, ty); |
| 1563 | return switch (res.overflow_bit.toUnsignedInt(zcu)) { | 1586 | if (res.overflow) return .{ .overflow = true, .val = try comptimeIntMul(sema, lhs, rhs) }; |
| 1564 | 0 => .{ .overflow = false, .val = res.wrapped_result }, | 1587 | return .{ .overflow = false, .val = res.wrapped_result }; |
| 1565 | 1 => .{ .overflow = true, .val = try comptimeIntMul(sema, lhs, rhs) }, | | |
| 1566 | else => unreachable, | | |
| 1567 | }; | | |
| 1568 | }, | 1588 | }, |
| 1569 | } | 1589 | } |
| 1570 | } | 1590 | } |
| ... | @@ -1572,8 +1592,19 @@ fn intMul(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: boo | ... | @@ -1572,8 +1592,19 @@ fn intMul(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !struct { overflow: boo |
| 1572 | fn comptimeIntMul(sema: *Sema, lhs: Value, rhs: Value) !Value { | 1592 | fn comptimeIntMul(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 1573 | const pt = sema.pt; | 1593 | const pt = sema.pt; |
| 1574 | const zcu = pt.zcu; | 1594 | const zcu = pt.zcu; |
| 1575 | // TODO is this a performance issue? maybe we should try the operation without | 1595 | |
| 1576 | // resorting to BigInt first. | 1596 | // Try the operation without resorting to BigInt first. |
| | 1597 | if (lhs.getUnsignedInt(zcu)) |lhs_val| { |
| | 1598 | if (rhs.getUnsignedInt(zcu)) |rhs_val| { |
| | 1599 | const result, const overflow = @mulWithOverflow(lhs_val, rhs_val); |
| | 1600 | |
| | 1601 | if (overflow == 0) { |
| | 1602 | return pt.intValue(.comptime_int, result); |
| | 1603 | } |
| | 1604 | // It would overflow, fall back to BigInt. |
| | 1605 | } |
| | 1606 | } |
| | 1607 | |
| 1577 | var lhs_space: Value.BigIntSpace = undefined; | 1608 | var lhs_space: Value.BigIntSpace = undefined; |
| 1578 | var rhs_space: Value.BigIntSpace = undefined; | 1609 | var rhs_space: Value.BigIntSpace = undefined; |
| 1579 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); | 1610 | const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); |
| ... | @@ -1590,17 +1621,17 @@ fn comptimeIntMul(sema: *Sema, lhs: Value, rhs: Value) !Value { | ... | @@ -1590,17 +1621,17 @@ fn comptimeIntMul(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 1590 | result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, sema.arena); | 1621 | result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, sema.arena); |
| 1591 | return pt.intValue_big(.comptime_int, result_bigint.toConst()); | 1622 | return pt.intValue_big(.comptime_int, result_bigint.toConst()); |
| 1592 | } | 1623 | } |
| 1593 | fn intMulWithOverflow(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResult { | 1624 | fn intMulWithOverflow(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResultInt { |
| 1594 | switch (ty.toIntern()) { | 1625 | switch (ty.toIntern()) { |
| 1595 | .comptime_int_type => return .{ | 1626 | .comptime_int_type => return .{ |
| 1596 | .overflow_bit = .zero_u1, | 1627 | .overflow = false, |
| 1597 | .wrapped_result = try comptimeIntMul(sema, lhs, rhs), | 1628 | .wrapped_result = try comptimeIntMul(sema, lhs, rhs), |
| 1598 | }, | 1629 | }, |
| 1599 | else => return intMulWithOverflowInner(sema, lhs, rhs, ty), | 1630 | else => return intMulWithOverflowInner(sema, lhs, rhs, ty), |
| 1600 | } | 1631 | } |
| 1601 | } | 1632 | } |
| 1602 | /// Like `intMulWithOverflow`, but asserts that `ty` is not `Type.comptime_int`. | 1633 | /// Like `intMulWithOverflow`, but asserts that `ty` is not `Type.comptime_int`. |
| 1603 | fn intMulWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResult { | 1634 | fn intMulWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResultInt { |
| 1604 | const pt = sema.pt; | 1635 | const pt = sema.pt; |
| 1605 | const zcu = pt.zcu; | 1636 | const zcu = pt.zcu; |
| 1606 | const info = ty.intInfo(zcu); | 1637 | const info = ty.intInfo(zcu); |
| ... | @@ -1617,7 +1648,7 @@ fn intMulWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value | ... | @@ -1617,7 +1648,7 @@ fn intMulWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value |
| 1617 | const overflowed = !result_bigint.toConst().fitsInTwosComp(info.signedness, info.bits); | 1648 | const overflowed = !result_bigint.toConst().fitsInTwosComp(info.signedness, info.bits); |
| 1618 | if (overflowed) result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits); | 1649 | if (overflowed) result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits); |
| 1619 | return .{ | 1650 | return .{ |
| 1620 | .overflow_bit = try pt.intValue(.u1, @intFromBool(overflowed)), | 1651 | .overflow = overflowed, |
| 1621 | .wrapped_result = try pt.intValue_big(ty, result_bigint.toConst()), | 1652 | .wrapped_result = try pt.intValue_big(ty, result_bigint.toConst()), |
| 1622 | }; | 1653 | }; |
| 1623 | } | 1654 | } |