diff options
| author | Vexu <git@vexu.eu> | 2020-10-17 01:09:42 +0300 |
|---|---|---|
| committer | Vexu <git@vexu.eu> | 2020-10-30 15:58:13 +0200 |
| commit | 12e4c648ccc68f5190dd5076088b3959ebeee65d (patch) | |
| tree | e045157d9fba4648bb450510a4762f4937799308 /src/type.zig | |
| parent | 4155d2ae242d18c0bc280aa22f733bf7dcb6e1f0 (diff) | |
| download | zig-12e4c648ccc68f5190dd5076088b3959ebeee65d.tar.gz zig-12e4c648ccc68f5190dd5076088b3959ebeee65d.zip | |
stage2: implement switch validation for integers
Diffstat (limited to 'src/type.zig')
| -rw-r--r-- | src/type.zig | 72 |
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 |
