Skip to content

Commit a3c9bfe

Browse files
Snektronandrewrk
authored andcommitted
stage2: truncation
* Also fixes a related case where big int truncate would assume that the input fits in the output limbs buffer
1 parent d49c601 commit a3c9bfe

File tree

4 files changed

+25
-6
lines changed

4 files changed

+25
-6
lines changed

lib/std/math/big/int.zig

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,13 +1405,16 @@ pub const Mutable = struct {
14051405
r.normalize(r.len);
14061406
}
14071407
} else {
1408-
r.copy(a);
1409-
if (r.len < req_limbs) {
1408+
if (a.limbs.len < req_limbs) {
14101409
// Integer fits within target bits, no wrapping required.
1410+
r.copy(a);
14111411
return;
14121412
}
14131413

1414-
r.len = req_limbs;
1414+
r.copy(.{
1415+
.positive = a.positive,
1416+
.limbs = a.limbs[0..req_limbs],
1417+
});
14151418
r.limbs[r.len - 1] &= mask;
14161419
r.normalize(r.len);
14171420

lib/std/math/big/int_test.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,18 @@ test "big.int truncate negative multi to single" {
16541654
try testing.expect((try a.to(i17)) == 0);
16551655
}
16561656

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+
16571669
test "big.int saturate single signed positive" {
16581670
var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB);
16591671
defer a.deinit();

src/Sema.zig

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9477,14 +9477,18 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
94779477
}
94789478

94799479
const target = sema.mod.getTarget();
9480-
const src_info = operand_ty.intInfo(target);
94819480
const dest_info = dest_ty.intInfo(target);
94829481

9483-
if (src_info.bits == 0 or dest_info.bits == 0) {
9482+
if (dest_info.bits == 0) {
94849483
return sema.addConstant(dest_ty, Value.zero);
94859484
}
94869485

94879486
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+
94889492
if (src_info.signedness != dest_info.signedness) {
94899493
return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{
94909494
@tagName(dest_info.signedness), operand_ty,

test/behavior.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ test {
5151
_ = @import("behavior/switch.zig");
5252
_ = @import("behavior/this.zig");
5353
_ = @import("behavior/translate_c_macros.zig");
54+
_ = @import("behavior/truncate.zig");
5455
_ = @import("behavior/underscore.zig");
5556
_ = @import("behavior/union.zig");
5657
_ = @import("behavior/usingnamespace.zig");
@@ -163,7 +164,6 @@ test {
163164
_ = @import("behavior/switch_prong_err_enum.zig");
164165
_ = @import("behavior/switch_prong_implicit_cast.zig");
165166
_ = @import("behavior/switch_stage1.zig");
166-
_ = @import("behavior/truncate.zig");
167167
_ = @import("behavior/try.zig");
168168
_ = @import("behavior/tuple.zig");
169169
_ = @import("behavior/type.zig");

0 commit comments

Comments
 (0)