aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorVexu <git@vexu.eu>2020-10-17 01:09:42 +0300
committerVexu <git@vexu.eu>2020-10-30 15:58:13 +0200
commit12e4c648ccc68f5190dd5076088b3959ebeee65d (patch)
treee045157d9fba4648bb450510a4762f4937799308 /src/type.zig
parent4155d2ae242d18c0bc280aa22f733bf7dcb6e1f0 (diff)
downloadzig-12e4c648ccc68f5190dd5076088b3959ebeee65d.tar.gz
zig-12e4c648ccc68f5190dd5076088b3959ebeee65d.zip
stage2: implement switch validation for integers
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/type.zig b/src/type.zig
index f07df290fc..a706ad34bc 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -2863,6 +2863,78 @@ pub const Type = extern union {
};
}
+ /// Asserts that self.zigTypeTag() == .Int.
+ pub fn minInt(self: Type, arena: *std.heap.ArenaAllocator, target: Target) !Value {
+ assert(self.zigTypeTag() == .Int);
+ const info = self.intInfo(target);
+
+ if (!info.signed) {
+ return Value.initTag(.zero);
+ }
+
+ if ((info.bits - 1) <= std.math.maxInt(u6)) {
+ const payload = try arena.allocator.create(Value.Payload.Int_i64);
+ payload.* = .{
+ .int = -(@as(i64, 1) << @truncate(u6, info.bits - 1)),
+ };
+ return Value.initPayload(&payload.base);
+ }
+
+ var res = try std.math.big.int.Managed.initSet(&arena.allocator, 1);
+ try res.shiftLeft(res, info.bits - 1);
+ res.negate();
+
+ const res_const = res.toConst();
+ if (res_const.positive) {
+ const val_payload = try arena.allocator.create(Value.Payload.IntBigPositive);
+ val_payload.* = .{ .limbs = res_const.limbs };
+ return Value.initPayload(&val_payload.base);
+ } else {
+ const val_payload = try arena.allocator.create(Value.Payload.IntBigNegative);
+ val_payload.* = .{ .limbs = res_const.limbs };
+ return Value.initPayload(&val_payload.base);
+ }
+ }
+
+ /// Asserts that self.zigTypeTag() == .Int.
+ pub fn maxInt(self: Type, arena: *std.heap.ArenaAllocator, target: Target) !Value {
+ assert(self.zigTypeTag() == .Int);
+ const info = self.intInfo(target);
+
+ if (info.signed and (info.bits - 1) <= std.math.maxInt(u6)) {
+ const payload = try arena.allocator.create(Value.Payload.Int_i64);
+ payload.* = .{
+ .int = (@as(i64, 1) << @truncate(u6, info.bits - 1)) - 1,
+ };
+ return Value.initPayload(&payload.base);
+ } else if (!info.signed and info.bits <= std.math.maxInt(u6)) {
+ const payload = try arena.allocator.create(Value.Payload.Int_u64);
+ payload.* = .{
+ .int = (@as(u64, 1) << @truncate(u6, info.bits)) - 1,
+ };
+ return Value.initPayload(&payload.base);
+ }
+
+ var res = try std.math.big.int.Managed.initSet(&arena.allocator, 1);
+ try res.shiftLeft(res, info.bits - @boolToInt(info.signed));
+ const one = std.math.big.int.Const{
+ .limbs = &[_]std.math.big.Limb{1},
+ .positive = true,
+ };
+ res.sub(res.toConst(), one) catch unreachable;
+
+ const res_const = res.toConst();
+ if (res_const.positive) {
+ const val_payload = try arena.allocator.create(Value.Payload.IntBigPositive);
+ val_payload.* = .{ .limbs = res_const.limbs };
+ return Value.initPayload(&val_payload.base);
+ } else {
+ const val_payload = try arena.allocator.create(Value.Payload.IntBigNegative);
+ val_payload.* = .{ .limbs = res_const.limbs };
+ return Value.initPayload(&val_payload.base);
+ }
+ }
+
/// This enum does not directly correspond to `std.builtin.TypeId` because
/// it has extra enum tags in it, as a way of using less memory. For example,
/// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types