| author | |
| committer | |
| log | a3c9bfef301e0a4675fcea57356653334e07df45 |
| tree | 6b5ca8affd586340ebb0f43d9aef8b558671e0f6 |
| parent | d49c601d623d0b5a90f47c95cb931fe21a13d89e |
* Also fixes a related case where big int truncate would assume that the
input fits in the output limbs buffer4 files changed, 25 insertions(+), 6 deletions(-)
lib/std/math/big/int.zig+6-3| ... | @@ -1405,13 +1405,16 @@ pub const Mutable = struct { | ... | @@ -1405,13 +1405,16 @@ pub const Mutable = struct { |
| 1405 | r.normalize(r.len); | 1405 | r.normalize(r.len); |
| 1406 | } | 1406 | } |
| 1407 | } else { | 1407 | } else { |
| 1408 | r.copy(a); | 1408 | if (a.limbs.len < req_limbs) { |
| 1409 | if (r.len < req_limbs) { | ||
| 1410 | // Integer fits within target bits, no wrapping required. | 1409 | // Integer fits within target bits, no wrapping required. |
| 1410 | r.copy(a); | ||
| 1411 | return; | 1411 | return; |
| 1412 | } | 1412 | } |
| 1413 | 1413 | ||
| 1414 | r.len = req_limbs; | 1414 | r.copy(.{ |
| 1415 | .positive = a.positive, | ||
| 1416 | .limbs = a.limbs[0..req_limbs], | ||
| 1417 | }); | ||
| 1415 | r.limbs[r.len - 1] &= mask; | 1418 | r.limbs[r.len - 1] &= mask; |
| 1416 | r.normalize(r.len); | 1419 | r.normalize(r.len); |
| 1417 | 1420 |
lib/std/math/big/int_test.zig+12| ... | @@ -1654,6 +1654,18 @@ test "big.int truncate negative multi to single" { | ... | @@ -1654,6 +1654,18 @@ test "big.int truncate negative multi to single" { |
| 1654 | try testing.expect((try a.to(i17)) == 0); | 1654 | try testing.expect((try a.to(i17)) == 0); |
| 1655 | } | 1655 | } |
| 1656 | 1656 | ||
| 1657 | test "big.int truncate multi unsigned many" { | ||
| 1658 | var a = try Managed.initSet(testing.allocator, 1); | ||
| 1659 | defer a.deinit(); | ||
| 1660 | try a.shiftLeft(a, 1023); | ||
| 1661 | |||
| 1662 | var b = try Managed.init(testing.allocator); | ||
| 1663 | defer b.deinit(); | ||
| 1664 | try b.truncate(a.toConst(), .signed, @bitSizeOf(i1)); | ||
| 1665 | |||
| 1666 | try testing.expect((try b.to(i1)) == 0); | ||
| 1667 | } | ||
| 1668 | |||
| 1657 | test "big.int saturate single signed positive" { | 1669 | test "big.int saturate single signed positive" { |
| 1658 | var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB); | 1670 | var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB); |
| 1659 | defer a.deinit(); | 1671 | defer a.deinit(); |
src/Sema.zig+6-2| ... | @@ -9477,14 +9477,18 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -9477,14 +9477,18 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9477 | } | 9477 | } |
| 9478 | 9478 | ||
| 9479 | const target = sema.mod.getTarget(); | 9479 | const target = sema.mod.getTarget(); |
| 9480 | const src_info = operand_ty.intInfo(target); | ||
| 9481 | const dest_info = dest_ty.intInfo(target); | 9480 | const dest_info = dest_ty.intInfo(target); |
| 9482 | 9481 | ||
| 9483 | if (src_info.bits == 0 or dest_info.bits == 0) { | 9482 | if (dest_info.bits == 0) { |
| 9484 | return sema.addConstant(dest_ty, Value.zero); | 9483 | return sema.addConstant(dest_ty, Value.zero); |
| 9485 | } | 9484 | } |
| 9486 | 9485 | ||
| 9487 | if (!src_is_comptime_int) { | 9486 | if (!src_is_comptime_int) { |
| 9487 | const src_info = operand_ty.intInfo(target); | ||
| 9488 | if (src_info.bits == 0) { | ||
| 9489 | return sema.addConstant(dest_ty, Value.zero); | ||
| 9490 | } | ||
| 9491 | |||
| 9488 | if (src_info.signedness != dest_info.signedness) { | 9492 | if (src_info.signedness != dest_info.signedness) { |
| 9489 | return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{ | 9493 | return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{ |
| 9490 | @tagName(dest_info.signedness), operand_ty, | 9494 | @tagName(dest_info.signedness), operand_ty, |
test/behavior.zig+1-1| ... | @@ -51,6 +51,7 @@ test { | ... | @@ -51,6 +51,7 @@ test { |
| 51 | _ = @import("behavior/switch.zig"); | 51 | _ = @import("behavior/switch.zig"); |
| 52 | _ = @import("behavior/this.zig"); | 52 | _ = @import("behavior/this.zig"); |
| 53 | _ = @import("behavior/translate_c_macros.zig"); | 53 | _ = @import("behavior/translate_c_macros.zig"); |
| 54 | _ = @import("behavior/truncate.zig"); | ||
| 54 | _ = @import("behavior/underscore.zig"); | 55 | _ = @import("behavior/underscore.zig"); |
| 55 | _ = @import("behavior/union.zig"); | 56 | _ = @import("behavior/union.zig"); |
| 56 | _ = @import("behavior/usingnamespace.zig"); | 57 | _ = @import("behavior/usingnamespace.zig"); |
| ... | @@ -163,7 +164,6 @@ test { | ... | @@ -163,7 +164,6 @@ test { |
| 163 | _ = @import("behavior/switch_prong_err_enum.zig"); | 164 | _ = @import("behavior/switch_prong_err_enum.zig"); |
| 164 | _ = @import("behavior/switch_prong_implicit_cast.zig"); | 165 | _ = @import("behavior/switch_prong_implicit_cast.zig"); |
| 165 | _ = @import("behavior/switch_stage1.zig"); | 166 | _ = @import("behavior/switch_stage1.zig"); |
| 166 | _ = @import("behavior/truncate.zig"); | ||
| 167 | _ = @import("behavior/try.zig"); | 167 | _ = @import("behavior/try.zig"); |
| 168 | _ = @import("behavior/tuple.zig"); | 168 | _ = @import("behavior/tuple.zig"); |
| 169 | _ = @import("behavior/type.zig"); | 169 | _ = @import("behavior/type.zig"); |