aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobin Voetter <robin@voetter.nl>2021-09-26 07:40:40 +0200
committerRobin Voetter <robin@voetter.nl>2021-10-04 11:25:29 +0200
commita73369244471cf15ed8eda624e86c435a5df295f (patch)
treef3141373dbf9aa9b90d998a3749a91864cb55a97 /src
parentb58cf6dab6ff64c3403d3776a430694534f7b818 (diff)
downloadzig-a73369244471cf15ed8eda624e86c435a5df295f.tar.gz
zig-a73369244471cf15ed8eda624e86c435a5df295f.zip
Update Value.intTrunc to use new big int truncate
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig2
-rw-r--r--src/value.zig24
2 files changed, 19 insertions, 7 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 731a5a8a8a..cef4564206 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -9017,7 +9017,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
if (val.isUndef()) return sema.addConstUndef(dest_ty);
- return sema.addConstant(dest_ty, try val.intTrunc(sema.arena, dest_info.bits));
+ return sema.addConstant(dest_ty, try val.intTrunc(sema.arena, dest_info.signedness, dest_info.bits));
}
try sema.requireRuntimeBlock(block, src);
diff --git a/src/value.zig b/src/value.zig
index 72fc46ef4c..fa11bb6ddb 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -2136,12 +2136,24 @@ pub const Value = extern union {
}
}
- pub fn intTrunc(val: Value, arena: *Allocator, bits: u16) !Value {
- const x = val.toUnsignedInt(); // TODO: implement comptime truncate on big ints
- if (bits == 64) return val;
- const mask = (@as(u64, 1) << @intCast(u6, bits)) - 1;
- const truncated = x & mask;
- return Tag.int_u64.create(arena, truncated);
+ pub fn intTrunc(val: Value, allocator: *Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {
+ var val_space: Value.BigIntSpace = undefined;
+ const val_bigint = val.toBigInt(&val_space);
+
+ const limbs = try allocator.alloc(
+ std.math.big.Limb,
+ std.math.big.int.calcTwosCompLimbCount(bits),
+ );
+ var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
+
+ result_bigint.truncate(val_bigint, signedness, bits);
+ const result_limbs = result_bigint.limbs[0..result_bigint.len];
+
+ if (result_bigint.positive) {
+ return Value.Tag.int_big_positive.create(allocator, result_limbs);
+ } else {
+ return Value.Tag.int_big_negative.create(allocator, result_limbs);
+ }
}
pub fn shl(lhs: Value, rhs: Value, allocator: *Allocator) !Value {