stage2: truncation

* Also fixes a related case where big int truncate would assume that the
input fits in the output limbs buffer
This commit is contained in:
Robin Voetter 2021-10-22 01:24:38 +02:00 committed by Andrew Kelley
parent d49c601d62
commit a3c9bfef30
4 changed files with 25 additions and 6 deletions

View File

@ -1405,13 +1405,16 @@ pub const Mutable = struct {
r.normalize(r.len);
}
} else {
r.copy(a);
if (r.len < req_limbs) {
if (a.limbs.len < req_limbs) {
// Integer fits within target bits, no wrapping required.
r.copy(a);
return;
}
r.len = req_limbs;
r.copy(.{
.positive = a.positive,
.limbs = a.limbs[0..req_limbs],
});
r.limbs[r.len - 1] &= mask;
r.normalize(r.len);

View File

@ -1654,6 +1654,18 @@ test "big.int truncate negative multi to single" {
try testing.expect((try a.to(i17)) == 0);
}
test "big.int truncate multi unsigned many" {
var a = try Managed.initSet(testing.allocator, 1);
defer a.deinit();
try a.shiftLeft(a, 1023);
var b = try Managed.init(testing.allocator);
defer b.deinit();
try b.truncate(a.toConst(), .signed, @bitSizeOf(i1));
try testing.expect((try b.to(i1)) == 0);
}
test "big.int saturate single signed positive" {
var a = try Managed.initSet(testing.allocator, 0xBBBB_BBBB);
defer a.deinit();

View File

@ -9477,14 +9477,18 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
}
const target = sema.mod.getTarget();
const src_info = operand_ty.intInfo(target);
const dest_info = dest_ty.intInfo(target);
if (src_info.bits == 0 or dest_info.bits == 0) {
if (dest_info.bits == 0) {
return sema.addConstant(dest_ty, Value.zero);
}
if (!src_is_comptime_int) {
const src_info = operand_ty.intInfo(target);
if (src_info.bits == 0) {
return sema.addConstant(dest_ty, Value.zero);
}
if (src_info.signedness != dest_info.signedness) {
return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{
@tagName(dest_info.signedness), operand_ty,

View File

@ -51,6 +51,7 @@ test {
_ = @import("behavior/switch.zig");
_ = @import("behavior/this.zig");
_ = @import("behavior/translate_c_macros.zig");
_ = @import("behavior/truncate.zig");
_ = @import("behavior/underscore.zig");
_ = @import("behavior/union.zig");
_ = @import("behavior/usingnamespace.zig");
@ -163,7 +164,6 @@ test {
_ = @import("behavior/switch_prong_err_enum.zig");
_ = @import("behavior/switch_prong_implicit_cast.zig");
_ = @import("behavior/switch_stage1.zig");
_ = @import("behavior/truncate.zig");
_ = @import("behavior/try.zig");
_ = @import("behavior/tuple.zig");
_ = @import("behavior/type.zig");