Add builtin.Signedness, use it instead of is_signed
parent
2b7781d82a
commit
25ec2dbc1e
|
@ -209,7 +209,7 @@ pub const TypeInfo = union(enum) {
|
|||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const Int = struct {
|
||||
is_signed: bool,
|
||||
signedness: Signedness,
|
||||
bits: comptime_int,
|
||||
};
|
||||
|
||||
|
@ -438,6 +438,13 @@ pub const Endian = enum {
|
|||
Little,
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const Signedness = enum {
|
||||
signed,
|
||||
unsigned,
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const OutputMode = enum {
|
||||
|
|
|
@ -1028,7 +1028,7 @@ pub fn formatInt(
|
|||
if (a == 0) break;
|
||||
}
|
||||
|
||||
if (value_info.is_signed) {
|
||||
if (value_info.signedness == .signed) {
|
||||
if (value < 0) {
|
||||
// Negative integer
|
||||
index -= 1;
|
||||
|
|
|
@ -73,7 +73,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
|
|||
|
||||
if (int_size == 1) {
|
||||
if (t_bit_count == 8) return @bitCast(T, buffer[0]);
|
||||
const PossiblySignedByte = std.meta.Int(if (@typeInfo(T).Int.is_signed) .signed else .unsigned, 8);
|
||||
const PossiblySignedByte = std.meta.Int(@typeInfo(T).Int.signedness, 8);
|
||||
return @truncate(T, @bitCast(PossiblySignedByte, buffer[0]));
|
||||
}
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type {
|
|||
self.popState();
|
||||
return;
|
||||
}
|
||||
if (value < 4503599627370496 and (!info.is_signed or value > -4503599627370496)) {
|
||||
if (value < 4503599627370496 and (info.signedness == .unsigned or value > -4503599627370496)) {
|
||||
try self.stream.print("{}", .{value});
|
||||
self.popState();
|
||||
return;
|
||||
|
|
|
@ -297,8 +297,8 @@ test "deserialize unsigned LEB128" {
|
|||
|
||||
fn test_write_leb128(value: anytype) !void {
|
||||
const T = @TypeOf(value);
|
||||
const t_signed = @typeInfo(T).Int.is_signed;
|
||||
const signedness = if (t_signed) .signed else .unsigned;
|
||||
const signedness = @typeInfo(T).Int.signedness;
|
||||
const t_signed = signedness == .signed;
|
||||
|
||||
const writeStream = if (t_signed) writeILEB128 else writeULEB128;
|
||||
const readStream = if (t_signed) readILEB128 else readULEB128;
|
||||
|
|
|
@ -313,7 +313,7 @@ pub fn floatExponentBits(comptime T: type) comptime_int {
|
|||
pub fn Min(comptime A: type, comptime B: type) type {
|
||||
switch (@typeInfo(A)) {
|
||||
.Int => |a_info| switch (@typeInfo(B)) {
|
||||
.Int => |b_info| if (!a_info.is_signed and !b_info.is_signed) {
|
||||
.Int => |b_info| if (a_info.signedness == .unsigned and b_info.signedness == .unsigned) {
|
||||
if (a_info.bits < b_info.bits) {
|
||||
return A;
|
||||
} else {
|
||||
|
@ -450,7 +450,7 @@ pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {
|
|||
}
|
||||
};
|
||||
|
||||
if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).Int.is_signed) {
|
||||
if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).Int.signedness == .signed) {
|
||||
if (shift_amt < 0) {
|
||||
return a >> casted_shift_amt;
|
||||
}
|
||||
|
@ -490,7 +490,7 @@ pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {
|
|||
}
|
||||
};
|
||||
|
||||
if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).Int.is_signed) {
|
||||
if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).Int.signedness == .signed) {
|
||||
if (shift_amt < 0) {
|
||||
return a << casted_shift_amt;
|
||||
}
|
||||
|
@ -518,12 +518,12 @@ test "math.shr" {
|
|||
pub fn rotr(comptime T: type, x: T, r: anytype) T {
|
||||
if (@typeInfo(T) == .Vector) {
|
||||
const C = @typeInfo(T).Vector.child;
|
||||
if (@typeInfo(C).Int.is_signed) {
|
||||
if (@typeInfo(C).Int.signedness == .signed) {
|
||||
@compileError("cannot rotate signed integers");
|
||||
}
|
||||
const ar = @intCast(Log2Int(C), @mod(r, @typeInfo(C).Int.bits));
|
||||
return (x >> @splat(@typeInfo(T).Vector.len, ar)) | (x << @splat(@typeInfo(T).Vector.len, 1 + ~ar));
|
||||
} else if (@typeInfo(T).Int.is_signed) {
|
||||
} else if (@typeInfo(T).Int.signedness == .signed) {
|
||||
@compileError("cannot rotate signed integer");
|
||||
} else {
|
||||
const ar = @mod(r, @typeInfo(T).Int.bits);
|
||||
|
@ -546,12 +546,12 @@ test "math.rotr" {
|
|||
pub fn rotl(comptime T: type, x: T, r: anytype) T {
|
||||
if (@typeInfo(T) == .Vector) {
|
||||
const C = @typeInfo(T).Vector.child;
|
||||
if (@typeInfo(C).Int.is_signed) {
|
||||
if (@typeInfo(C).Int.signedness == .signed) {
|
||||
@compileError("cannot rotate signed integers");
|
||||
}
|
||||
const ar = @intCast(Log2Int(C), @mod(r, @typeInfo(C).Int.bits));
|
||||
return (x << @splat(@typeInfo(T).Vector.len, ar)) | (x >> @splat(@typeInfo(T).Vector.len, 1 +% ~ar));
|
||||
} else if (@typeInfo(T).Int.is_signed) {
|
||||
} else if (@typeInfo(T).Int.signedness == .signed) {
|
||||
@compileError("cannot rotate signed integer");
|
||||
} else {
|
||||
const ar = @mod(r, @typeInfo(T).Int.bits);
|
||||
|
@ -585,7 +585,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
|
|||
if (from == 0 and to == 0) {
|
||||
return u0;
|
||||
}
|
||||
const sign: std.meta.Signedness = if (from < 0) .signed else .unsigned;
|
||||
const sign: std.builtin.Signedness = if (from < 0) .signed else .unsigned;
|
||||
const largest_positive_integer = max(if (from < 0) (-from) - 1 else from, to); // two's complement
|
||||
const base = log2(largest_positive_integer);
|
||||
const upper = (1 << base) - 1;
|
||||
|
@ -658,7 +658,7 @@ fn testOverflow() void {
|
|||
pub fn absInt(x: anytype) !@TypeOf(x) {
|
||||
const T = @TypeOf(x);
|
||||
comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
|
||||
comptime assert(@typeInfo(T).Int.is_signed); // must pass a signed integer to absInt
|
||||
comptime assert(@typeInfo(T).Int.signedness == .signed); // must pass a signed integer to absInt
|
||||
|
||||
if (x == minInt(@TypeOf(x))) {
|
||||
return error.Overflow;
|
||||
|
@ -691,7 +691,7 @@ fn testAbsFloat() void {
|
|||
pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
|
||||
@setRuntimeSafety(false);
|
||||
if (denominator == 0) return error.DivisionByZero;
|
||||
if (@typeInfo(T) == .Int and @typeInfo(T).Int.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
|
||||
if (@typeInfo(T) == .Int and @typeInfo(T).Int.signedness == .signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
|
||||
return @divTrunc(numerator, denominator);
|
||||
}
|
||||
|
||||
|
@ -712,7 +712,7 @@ fn testDivTrunc() void {
|
|||
pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
|
||||
@setRuntimeSafety(false);
|
||||
if (denominator == 0) return error.DivisionByZero;
|
||||
if (@typeInfo(T) == .Int and @typeInfo(T).Int.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
|
||||
if (@typeInfo(T) == .Int and @typeInfo(T).Int.signedness == .signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
|
||||
return @divFloor(numerator, denominator);
|
||||
}
|
||||
|
||||
|
@ -786,7 +786,7 @@ fn testDivCeil() void {
|
|||
pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
|
||||
@setRuntimeSafety(false);
|
||||
if (denominator == 0) return error.DivisionByZero;
|
||||
if (@typeInfo(T) == .Int and @typeInfo(T).Int.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
|
||||
if (@typeInfo(T) == .Int and @typeInfo(T).Int.signedness == .signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
|
||||
const result = @divTrunc(numerator, denominator);
|
||||
if (result * denominator != numerator) return error.UnexpectedRemainder;
|
||||
return result;
|
||||
|
@ -892,7 +892,7 @@ test "math.absCast" {
|
|||
/// Returns the negation of the integer parameter.
|
||||
/// Result is a signed integer.
|
||||
pub fn negateCast(x: anytype) !std.meta.Int(.signed, std.meta.bitCount(@TypeOf(x))) {
|
||||
if (@typeInfo(@TypeOf(x)).Int.is_signed) return negate(x);
|
||||
if (@typeInfo(@TypeOf(x)).Int.signedness == .signed) return negate(x);
|
||||
|
||||
const int = std.meta.Int(.signed, std.meta.bitCount(@TypeOf(x)));
|
||||
if (x > -minInt(int)) return error.Overflow;
|
||||
|
@ -981,11 +981,11 @@ fn testFloorPowerOfTwo() void {
|
|||
/// Returns the next power of two (if the value is not already a power of two).
|
||||
/// Only unsigned integers can be used. Zero is not an allowed input.
|
||||
/// Result is a type with 1 more bit than the input type.
|
||||
pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.Int(if (@typeInfo(T).Int.is_signed) .signed else .unsigned, @typeInfo(T).Int.bits + 1) {
|
||||
pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.Int(@typeInfo(T).Int.signedness, @typeInfo(T).Int.bits + 1) {
|
||||
comptime assert(@typeInfo(T) == .Int);
|
||||
comptime assert(!@typeInfo(T).Int.is_signed);
|
||||
comptime assert(@typeInfo(T).Int.signedness == .unsigned);
|
||||
assert(value != 0);
|
||||
comptime const PromotedType = std.meta.Int(if (@typeInfo(T).Int.is_signed) .signed else .unsigned, @typeInfo(T).Int.bits + 1);
|
||||
comptime const PromotedType = std.meta.Int(@typeInfo(T).Int.signedness, @typeInfo(T).Int.bits + 1);
|
||||
comptime const shiftType = std.math.Log2Int(PromotedType);
|
||||
return @as(PromotedType, 1) << @intCast(shiftType, @typeInfo(T).Int.bits - @clz(T, value - 1));
|
||||
}
|
||||
|
@ -996,8 +996,8 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.Int(if (@typeI
|
|||
pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) {
|
||||
comptime assert(@typeInfo(T) == .Int);
|
||||
const info = @typeInfo(T).Int;
|
||||
comptime assert(!info.is_signed);
|
||||
comptime const PromotedType = std.meta.Int(if (info.is_signed) .signed else .unsigned, info.bits + 1);
|
||||
comptime assert(info.signedness == .unsigned);
|
||||
comptime const PromotedType = std.meta.Int(info.signedness, info.bits + 1);
|
||||
comptime const overflowBit = @as(PromotedType, 1) << info.bits;
|
||||
var x = ceilPowerOfTwoPromote(T, value);
|
||||
if (overflowBit & x != 0) {
|
||||
|
@ -1090,13 +1090,13 @@ pub fn maxInt(comptime T: type) comptime_int {
|
|||
const info = @typeInfo(T);
|
||||
const bit_count = info.Int.bits;
|
||||
if (bit_count == 0) return 0;
|
||||
return (1 << (bit_count - @boolToInt(info.Int.is_signed))) - 1;
|
||||
return (1 << (bit_count - @boolToInt(info.Int.signedness == .signed))) - 1;
|
||||
}
|
||||
|
||||
pub fn minInt(comptime T: type) comptime_int {
|
||||
const info = @typeInfo(T);
|
||||
const bit_count = info.Int.bits;
|
||||
if (!info.Int.is_signed) return 0;
|
||||
if (info.Int.signedness == .unsigned) return 0;
|
||||
if (bit_count == 0) return 0;
|
||||
return -(1 << (bit_count - 1));
|
||||
}
|
||||
|
@ -1143,8 +1143,8 @@ test "max value type" {
|
|||
testing.expect(x == 2147483647);
|
||||
}
|
||||
|
||||
pub fn mulWide(comptime T: type, a: T, b: T) std.meta.Int(if (@typeInfo(T).Int.is_signed) .signed else .unsigned, @typeInfo(T).Int.bits * 2) {
|
||||
const ResultInt = std.meta.Int(if (@typeInfo(T).Int.is_signed) .signed else .unsigned, @typeInfo(T).Int.bits * 2);
|
||||
pub fn mulWide(comptime T: type, a: T, b: T) std.meta.Int(@typeInfo(T).Int.signedness, @typeInfo(T).Int.bits * 2) {
|
||||
const ResultInt = std.meta.Int(@typeInfo(T).Int.signedness, @typeInfo(T).Int.bits * 2);
|
||||
return @as(ResultInt, a) * @as(ResultInt, b);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ pub const Log2Limb = std.math.Log2Int(Limb);
|
|||
comptime {
|
||||
assert(std.math.floorPowerOfTwo(usize, limb_info.bits) == limb_info.bits);
|
||||
assert(limb_info.bits <= 64); // u128 set is unsupported
|
||||
assert(limb_info.is_signed == false);
|
||||
assert(limb_info.signedness == .unsigned);
|
||||
}
|
||||
|
||||
test "" {
|
||||
|
|
|
@ -24,7 +24,7 @@ pub fn calcLimbLen(scalar: anytype) usize {
|
|||
const T = @TypeOf(scalar);
|
||||
switch (@typeInfo(T)) {
|
||||
.Int => |info| {
|
||||
const UT = if (info.is_signed) std.meta.Int(.unsigned, info.bits - 1) else T;
|
||||
const UT = if (info.signedness == .signed) std.meta.Int(.unsigned, info.bits - 1) else T;
|
||||
return @sizeOf(UT) / @sizeOf(Limb);
|
||||
},
|
||||
.ComptimeInt => {
|
||||
|
@ -187,7 +187,7 @@ pub const Mutable = struct {
|
|||
|
||||
switch (@typeInfo(T)) {
|
||||
.Int => |info| {
|
||||
const UT = if (info.is_signed) std.meta.Int(.unsigned, info.bits - 1) else T;
|
||||
const UT = if (info.signedness == .signed) std.meta.Int(.unsigned, info.bits - 1) else T;
|
||||
|
||||
const needed_limbs = @sizeOf(UT) / @sizeOf(Limb);
|
||||
assert(needed_limbs <= self.limbs.len); // value too big
|
||||
|
@ -1054,22 +1054,22 @@ pub const Const = struct {
|
|||
return bits;
|
||||
}
|
||||
|
||||
pub fn fitsInTwosComp(self: Const, is_signed: bool, bit_count: usize) bool {
|
||||
pub fn fitsInTwosComp(self: Const, signedness: std.builtin.Signedness, bit_count: usize) bool {
|
||||
if (self.eqZero()) {
|
||||
return true;
|
||||
}
|
||||
if (!is_signed and !self.positive) {
|
||||
if (signedness == .unsigned and !self.positive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and is_signed);
|
||||
const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and signedness == .signed);
|
||||
return bit_count >= req_bits;
|
||||
}
|
||||
|
||||
/// Returns whether self can fit into an integer of the requested type.
|
||||
pub fn fits(self: Const, comptime T: type) bool {
|
||||
const info = @typeInfo(T).Int;
|
||||
return self.fitsInTwosComp(info.is_signed, info.bits);
|
||||
return self.fitsInTwosComp(info.signedness, info.bits);
|
||||
}
|
||||
|
||||
/// Returns the approximate size of the integer in the given base. Negative values accommodate for
|
||||
|
@ -1110,7 +1110,7 @@ pub const Const = struct {
|
|||
}
|
||||
}
|
||||
|
||||
if (!info.is_signed) {
|
||||
if (info.signedness == .unsigned) {
|
||||
return if (self.positive) @intCast(T, r) else error.NegativeIntoUnsigned;
|
||||
} else {
|
||||
if (self.positive) {
|
||||
|
@ -1558,8 +1558,8 @@ pub const Managed = struct {
|
|||
return self.toConst().bitCountTwosComp();
|
||||
}
|
||||
|
||||
pub fn fitsInTwosComp(self: Managed, is_signed: bool, bit_count: usize) bool {
|
||||
return self.toConst().fitsInTwosComp(is_signed, bit_count);
|
||||
pub fn fitsInTwosComp(self: Managed, signedness: std.builtin.Signedness, bit_count: usize) bool {
|
||||
return self.toConst().fitsInTwosComp(signedness, bit_count);
|
||||
}
|
||||
|
||||
/// Returns whether self can fit into an integer of the requested type.
|
||||
|
|
|
@ -48,7 +48,7 @@ pub fn powi(comptime T: type, x: T, y: T) (error{
|
|||
// powi(x, y) = Overflow for for y >= @sizeOf(x) - 1 y > 0
|
||||
// powi(x, y) = Underflow for for y > @sizeOf(x) - 1 y < 0
|
||||
const bit_size = @sizeOf(T) * 8;
|
||||
if (info.Int.is_signed) {
|
||||
if (info.Int.signedness == .signed) {
|
||||
if (x == -1) {
|
||||
// powi(-1, y) = -1 for for y an odd integer
|
||||
// powi(-1, y) = 1 for for y an even integer
|
||||
|
|
|
@ -718,15 +718,10 @@ pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const De
|
|||
|
||||
pub const IntType = @compileError("replaced by std.meta.Int");
|
||||
|
||||
pub const Signedness = enum {
|
||||
unsigned,
|
||||
signed,
|
||||
};
|
||||
|
||||
pub fn Int(comptime signedness: Signedness, comptime bit_count: u16) type {
|
||||
pub fn Int(comptime signedness: builtin.Signedness, comptime bit_count: u16) type {
|
||||
return @Type(TypeInfo{
|
||||
.Int = .{
|
||||
.is_signed = signedness == .signed,
|
||||
.signedness = signedness,
|
||||
.bits = bit_count,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -195,7 +195,7 @@ test "std.meta.trait.isPacked" {
|
|||
|
||||
pub fn isUnsignedInt(comptime T: type) bool {
|
||||
return switch (@typeInfo(T)) {
|
||||
.Int => |i| !i.is_signed,
|
||||
.Int => |i| i.signedness == .unsigned,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ test "isUnsignedInt" {
|
|||
pub fn isSignedInt(comptime T: type) bool {
|
||||
return switch (@typeInfo(T)) {
|
||||
.ComptimeInt => true,
|
||||
.Int => |i| i.is_signed,
|
||||
.Int => |i| i.signedness == .signed,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4868,12 +4868,7 @@ pub fn sendfile(
|
|||
var total_written: usize = 0;
|
||||
|
||||
// Prevents EOVERFLOW.
|
||||
const size_t = @Type(std.builtin.TypeInfo{
|
||||
.Int = .{
|
||||
.is_signed = false,
|
||||
.bits = @typeInfo(usize).Int.bits - 1,
|
||||
},
|
||||
});
|
||||
const size_t = std.meta.Int(.unsigned, @typeInfo(usize).Int.bits - 1);
|
||||
const max_count = switch (std.Target.current.os.tag) {
|
||||
.linux => 0x7ffff000,
|
||||
.macos, .ios, .watchos, .tvos => math.maxInt(i32),
|
||||
|
|
|
@ -777,7 +777,7 @@ pub fn seteuid(euid: uid_t) usize {
|
|||
// The setresuid(2) man page says that if -1 is passed the corresponding
|
||||
// id will not be changed. Since uid_t is unsigned, this wraps around to the
|
||||
// max value in C.
|
||||
comptime assert(@typeInfo(uid_t) == .Int and !@typeInfo(uid_t).Int.is_signed);
|
||||
comptime assert(@typeInfo(uid_t) == .Int and @typeInfo(uid_t).Int.signedness == .unsigned);
|
||||
return setresuid(std.math.maxInt(uid_t), euid, std.math.maxInt(uid_t));
|
||||
}
|
||||
|
||||
|
@ -788,7 +788,7 @@ pub fn setegid(egid: gid_t) usize {
|
|||
// The setresgid(2) man page says that if -1 is passed the corresponding
|
||||
// id will not be changed. Since gid_t is unsigned, this wraps around to the
|
||||
// max value in C.
|
||||
comptime assert(@typeInfo(uid_t) == .Int and !@typeInfo(uid_t).Int.is_signed);
|
||||
comptime assert(@typeInfo(uid_t) == .Int and @typeInfo(uid_t).Int.signedness == .unsigned);
|
||||
return setresgid(std.math.maxInt(gid_t), egid, std.math.maxInt(gid_t));
|
||||
}
|
||||
|
||||
|
|
|
@ -332,7 +332,7 @@ test "PackedIntArray" {
|
|||
comptime var bits = 0;
|
||||
inline while (bits <= max_bits) : (bits += 1) {
|
||||
//alternate unsigned and signed
|
||||
const sign: std.meta.Signedness = if (bits % 2 == 0) .signed else .unsigned;
|
||||
const sign: builtin.Signedness = if (bits % 2 == 0) .signed else .unsigned;
|
||||
const I = std.meta.Int(sign, bits);
|
||||
|
||||
const PackedArray = PackedIntArray(I, int_count);
|
||||
|
@ -384,7 +384,7 @@ test "PackedIntSlice" {
|
|||
comptime var bits = 0;
|
||||
inline while (bits <= max_bits) : (bits += 1) {
|
||||
//alternate unsigned and signed
|
||||
const sign: std.meta.Signedness = if (bits % 2 == 0) .signed else .unsigned;
|
||||
const sign: builtin.Signedness = if (bits % 2 == 0) .signed else .unsigned;
|
||||
const I = std.meta.Int(sign, bits);
|
||||
const P = PackedIntSlice(I);
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ pub const Random = struct {
|
|||
/// Constant-time implementation off `uintLessThan`.
|
||||
/// The results of this function may be biased.
|
||||
pub fn uintLessThanBiased(r: *Random, comptime T: type, less_than: T) T {
|
||||
comptime assert(@typeInfo(T).Int.is_signed == false);
|
||||
comptime assert(@typeInfo(T).Int.signedness == .unsigned);
|
||||
const bits = @typeInfo(T).Int.bits;
|
||||
comptime assert(bits <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
|
||||
assert(0 < less_than);
|
||||
|
@ -89,7 +89,7 @@ pub const Random = struct {
|
|||
/// this function is guaranteed to return.
|
||||
/// If you need deterministic runtime bounds, use `uintLessThanBiased`.
|
||||
pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T {
|
||||
comptime assert(@typeInfo(T).Int.is_signed == false);
|
||||
comptime assert(@typeInfo(T).Int.signedness == .unsigned);
|
||||
const bits = @typeInfo(T).Int.bits;
|
||||
comptime assert(bits <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
|
||||
assert(0 < less_than);
|
||||
|
@ -129,7 +129,7 @@ pub const Random = struct {
|
|||
/// Constant-time implementation off `uintAtMost`.
|
||||
/// The results of this function may be biased.
|
||||
pub fn uintAtMostBiased(r: *Random, comptime T: type, at_most: T) T {
|
||||
assert(@typeInfo(T).Int.is_signed == false);
|
||||
assert(@typeInfo(T).Int.signedness == .unsigned);
|
||||
if (at_most == maxInt(T)) {
|
||||
// have the full range
|
||||
return r.int(T);
|
||||
|
@ -141,7 +141,7 @@ pub const Random = struct {
|
|||
/// See `uintLessThan`, which this function uses in most cases,
|
||||
/// for commentary on the runtime of this function.
|
||||
pub fn uintAtMost(r: *Random, comptime T: type, at_most: T) T {
|
||||
assert(@typeInfo(T).Int.is_signed == false);
|
||||
assert(@typeInfo(T).Int.signedness == .unsigned);
|
||||
if (at_most == maxInt(T)) {
|
||||
// have the full range
|
||||
return r.int(T);
|
||||
|
@ -154,7 +154,7 @@ pub const Random = struct {
|
|||
pub fn intRangeLessThanBiased(r: *Random, comptime T: type, at_least: T, less_than: T) T {
|
||||
assert(at_least < less_than);
|
||||
const info = @typeInfo(T).Int;
|
||||
if (info.is_signed) {
|
||||
if (info.signedness == .signed) {
|
||||
// Two's complement makes this math pretty easy.
|
||||
const UnsignedT = std.meta.Int(.unsigned, info.bits);
|
||||
const lo = @bitCast(UnsignedT, at_least);
|
||||
|
@ -173,7 +173,7 @@ pub const Random = struct {
|
|||
pub fn intRangeLessThan(r: *Random, comptime T: type, at_least: T, less_than: T) T {
|
||||
assert(at_least < less_than);
|
||||
const info = @typeInfo(T).Int;
|
||||
if (info.is_signed) {
|
||||
if (info.signedness == .signed) {
|
||||
// Two's complement makes this math pretty easy.
|
||||
const UnsignedT = std.meta.Int(.unsigned, info.bits);
|
||||
const lo = @bitCast(UnsignedT, at_least);
|
||||
|
@ -191,7 +191,7 @@ pub const Random = struct {
|
|||
pub fn intRangeAtMostBiased(r: *Random, comptime T: type, at_least: T, at_most: T) T {
|
||||
assert(at_least <= at_most);
|
||||
const info = @typeInfo(T).Int;
|
||||
if (info.is_signed) {
|
||||
if (info.signedness == .signed) {
|
||||
// Two's complement makes this math pretty easy.
|
||||
const UnsignedT = std.meta.Int(.unsigned, info.bits);
|
||||
const lo = @bitCast(UnsignedT, at_least);
|
||||
|
@ -210,7 +210,7 @@ pub const Random = struct {
|
|||
pub fn intRangeAtMost(r: *Random, comptime T: type, at_least: T, at_most: T) T {
|
||||
assert(at_least <= at_most);
|
||||
const info = @typeInfo(T).Int;
|
||||
if (info.is_signed) {
|
||||
if (info.signedness == .signed) {
|
||||
// Two's complement makes this math pretty easy.
|
||||
const UnsignedT = std.meta.Int(.unsigned, info.bits);
|
||||
const lo = @bitCast(UnsignedT, at_least);
|
||||
|
@ -288,7 +288,7 @@ pub const Random = struct {
|
|||
/// into an integer 0 <= result < less_than.
|
||||
/// This function introduces a minor bias.
|
||||
pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T {
|
||||
comptime assert(@typeInfo(T).Int.is_signed == false);
|
||||
comptime assert(@typeInfo(T).Int.signedness == .unsigned);
|
||||
const bits = @typeInfo(T).Int.bits;
|
||||
const T2 = std.meta.Int(.unsigned, bits * 2);
|
||||
|
||||
|
|
|
@ -325,7 +325,7 @@ pub fn callMain() u8 {
|
|||
return 0;
|
||||
},
|
||||
.Int => |info| {
|
||||
if (info.bits != 8 or info.is_signed) {
|
||||
if (info.bits != 8 or info.signedness == .signed) {
|
||||
@compileError(bad_main_ret);
|
||||
}
|
||||
return root.main();
|
||||
|
@ -341,7 +341,7 @@ pub fn callMain() u8 {
|
|||
switch (@typeInfo(@TypeOf(result))) {
|
||||
.Void => return 0,
|
||||
.Int => |info| {
|
||||
if (info.bits != 8 or info.is_signed) {
|
||||
if (info.bits != 8 or info.signedness == .signed) {
|
||||
@compileError(bad_main_ret);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -2633,7 +2633,7 @@ pub fn cmpNumeric(
|
|||
dest_float_type = lhs.ty;
|
||||
} else {
|
||||
const int_info = lhs.ty.intInfo(self.getTarget());
|
||||
lhs_bits = int_info.bits + @boolToInt(!int_info.signed and dest_int_is_signed);
|
||||
lhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);
|
||||
}
|
||||
|
||||
var rhs_bits: usize = undefined;
|
||||
|
@ -2668,7 +2668,7 @@ pub fn cmpNumeric(
|
|||
dest_float_type = rhs.ty;
|
||||
} else {
|
||||
const int_info = rhs.ty.intInfo(self.getTarget());
|
||||
rhs_bits = int_info.bits + @boolToInt(!int_info.signed and dest_int_is_signed);
|
||||
rhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);
|
||||
}
|
||||
|
||||
const dest_type = if (dest_float_type) |ft| ft else blk: {
|
||||
|
@ -2817,9 +2817,9 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst
|
|||
|
||||
const src_info = inst.ty.intInfo(self.getTarget());
|
||||
const dst_info = dest_type.intInfo(self.getTarget());
|
||||
if ((src_info.signed == dst_info.signed and dst_info.bits >= src_info.bits) or
|
||||
if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or
|
||||
// small enough unsigned ints can get casted to large enough signed ints
|
||||
(src_info.signed and !dst_info.signed and dst_info.bits > src_info.bits))
|
||||
(src_info.signedness == .signed and dst_info.signedness == .unsigned and dst_info.bits > src_info.bits))
|
||||
{
|
||||
const b = try self.requireRuntimeBlock(scope, inst.src);
|
||||
return self.addUnOp(b, inst.src, dest_type, .intcast, inst);
|
||||
|
|
|
@ -203,7 +203,7 @@ pub fn generateSymbol(
|
|||
.Int => {
|
||||
// TODO populate .debug_info for the integer
|
||||
const info = typed_value.ty.intInfo(bin_file.options.target);
|
||||
if (info.bits == 8 and !info.signed) {
|
||||
if (info.bits == 8 and info.signedness == .unsigned) {
|
||||
const x = typed_value.val.toUnsignedInt();
|
||||
try code.append(@intCast(u8, x));
|
||||
return Result{ .appended = {} };
|
||||
|
@ -920,7 +920,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
const operand = try self.resolveInst(inst.operand);
|
||||
const info_a = inst.operand.ty.intInfo(self.target.*);
|
||||
const info_b = inst.base.ty.intInfo(self.target.*);
|
||||
if (info_a.signed != info_b.signed)
|
||||
if (info_a.signedness != info_b.signedness)
|
||||
return self.fail(inst.base.src, "TODO gen intcast sign safety in semantic analysis", .{});
|
||||
|
||||
if (info_a.bits == info_b.bits)
|
||||
|
@ -1780,7 +1780,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
fn genCmp(self: *Self, inst: *ir.Inst.BinOp, op: math.CompareOperator) !MCValue {
|
||||
// No side effects, so if it's unreferenced, do nothing.
|
||||
if (inst.base.isUnused())
|
||||
return MCValue.dead;
|
||||
return MCValue{ .dead = {} };
|
||||
switch (arch) {
|
||||
.x86_64 => {
|
||||
try self.code.ensureCapacity(self.code.items.len + 8);
|
||||
|
@ -1800,11 +1800,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
|
||||
try self.genX8664BinMathCode(inst.base.src, inst.base.ty, dst_mcv, src_mcv, 7, 0x38);
|
||||
const info = inst.lhs.ty.intInfo(self.target.*);
|
||||
if (info.signed) {
|
||||
return MCValue{ .compare_flags_signed = op };
|
||||
} else {
|
||||
return MCValue{ .compare_flags_unsigned = op };
|
||||
}
|
||||
return switch (info.signedness) {
|
||||
.signed => MCValue{ .compare_flags_signed = op },
|
||||
.unsigned => MCValue{ .compare_flags_unsigned = op },
|
||||
};
|
||||
},
|
||||
else => return self.fail(inst.base.src, "TODO implement cmp for {}", .{self.target.cpu.arch}),
|
||||
}
|
||||
|
@ -2904,12 +2903,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
switch (mcv) {
|
||||
.immediate => |imm| {
|
||||
// This immediate is unsigned.
|
||||
const U = @Type(.{
|
||||
.Int = .{
|
||||
.bits = ti.bits - @boolToInt(ti.is_signed),
|
||||
.is_signed = false,
|
||||
},
|
||||
});
|
||||
const U = std.meta.Int(.unsigned, ti.bits - @boolToInt(ti.signedness == .signed));
|
||||
if (imm >= math.maxInt(U)) {
|
||||
return MCValue{ .register = try self.copyToTmpRegister(inst.src, mcv) };
|
||||
}
|
||||
|
@ -2949,7 +2943,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
},
|
||||
.Int => {
|
||||
const info = typed_value.ty.intInfo(self.target.*);
|
||||
if (info.bits > ptr_bits or info.signed) {
|
||||
if (info.bits > ptr_bits or info.signedness == .signed) {
|
||||
return self.fail(src, "TODO const int bigger than ptr and signed int", .{});
|
||||
}
|
||||
return MCValue{ .immediate = typed_value.val.toUnsignedInt() };
|
||||
|
|
|
@ -2443,7 +2443,10 @@ fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !vo
|
|||
try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 12);
|
||||
dbg_info_buffer.appendAssumeCapacity(abbrev_base_type);
|
||||
// DW.AT_encoding, DW.FORM_data1
|
||||
dbg_info_buffer.appendAssumeCapacity(if (info.signed) DW.ATE_signed else DW.ATE_unsigned);
|
||||
dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) {
|
||||
.signed => DW.ATE_signed,
|
||||
.unsigned => DW.ATE_unsigned,
|
||||
});
|
||||
// DW.AT_byte_size, DW.FORM_data1
|
||||
dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(self.base.options.target)));
|
||||
// DW.AT_name, DW.FORM_string
|
||||
|
|
|
@ -25306,11 +25306,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
|
|||
ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 2);
|
||||
result->data.x_struct.fields = fields;
|
||||
|
||||
// is_signed: bool
|
||||
ensure_field_index(result->type, "is_signed", 0);
|
||||
// is_signed: Signedness
|
||||
ensure_field_index(result->type, "signedness", 0);
|
||||
fields[0]->special = ConstValSpecialStatic;
|
||||
fields[0]->type = ira->codegen->builtin_types.entry_bool;
|
||||
fields[0]->data.x_bool = type_entry->data.integral.is_signed;
|
||||
fields[0]->type = get_builtin_type(ira->codegen, "Signedness");
|
||||
bigint_init_unsigned(&fields[0]->data.x_enum_tag, !type_entry->data.integral.is_signed);
|
||||
// bits: u8
|
||||
ensure_field_index(result->type, "bits", 1);
|
||||
fields[1]->special = ConstValSpecialStatic;
|
||||
|
@ -26073,9 +26073,11 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
|
|||
BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "bits", 1);
|
||||
if (bi == nullptr)
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
bool is_signed;
|
||||
if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_signed", 0, &is_signed)))
|
||||
ZigValue *value = get_const_field(ira, source_instr->source_node, payload, "signedness", 0);
|
||||
if (value == nullptr)
|
||||
return ira->codegen->invalid_inst_gen->value->type;
|
||||
assert(value->type == get_builtin_type(ira->codegen, "Signedness"));
|
||||
bool is_signed = !bigint_as_u32(&value->data.x_enum_tag);
|
||||
return get_int_type(ira->codegen, is_signed, bigint_as_u32(bi));
|
||||
}
|
||||
case ZigTypeIdFloat:
|
||||
|
|
54
src/type.zig
54
src/type.zig
|
@ -186,7 +186,7 @@ pub const Type = extern union {
|
|||
// The target will not be branched upon, because we handled target-dependent cases above.
|
||||
const info_a = a.intInfo(@as(Target, undefined));
|
||||
const info_b = b.intInfo(@as(Target, undefined));
|
||||
return info_a.signed == info_b.signed and info_a.bits == info_b.bits;
|
||||
return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;
|
||||
},
|
||||
.Array => {
|
||||
if (a.arrayLen() != b.arrayLen())
|
||||
|
@ -266,7 +266,7 @@ pub const Type = extern union {
|
|||
// Remaining cases are arbitrary sized integers.
|
||||
// The target will not be branched upon, because we handled target-dependent cases above.
|
||||
const info = self.intInfo(@as(Target, undefined));
|
||||
std.hash.autoHash(&hasher, info.signed);
|
||||
std.hash.autoHash(&hasher, info.signedness);
|
||||
std.hash.autoHash(&hasher, info.bits);
|
||||
}
|
||||
},
|
||||
|
@ -1908,7 +1908,7 @@ pub const Type = extern union {
|
|||
}
|
||||
|
||||
/// Asserts the type is an integer.
|
||||
pub fn intInfo(self: Type, target: Target) struct { signed: bool, bits: u16 } {
|
||||
pub fn intInfo(self: Type, target: Target) struct { signedness: std.builtin.Signedness, bits: u16 } {
|
||||
return switch (self.tag()) {
|
||||
.f16,
|
||||
.f32,
|
||||
|
@ -1958,26 +1958,26 @@ pub const Type = extern union {
|
|||
.empty_struct,
|
||||
=> unreachable,
|
||||
|
||||
.int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
|
||||
.int_signed => .{ .signed = true, .bits = self.cast(Payload.IntSigned).?.bits },
|
||||
.u8 => .{ .signed = false, .bits = 8 },
|
||||
.i8 => .{ .signed = true, .bits = 8 },
|
||||
.u16 => .{ .signed = false, .bits = 16 },
|
||||
.i16 => .{ .signed = true, .bits = 16 },
|
||||
.u32 => .{ .signed = false, .bits = 32 },
|
||||
.i32 => .{ .signed = true, .bits = 32 },
|
||||
.u64 => .{ .signed = false, .bits = 64 },
|
||||
.i64 => .{ .signed = true, .bits = 64 },
|
||||
.usize => .{ .signed = false, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.isize => .{ .signed = true, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.c_short => .{ .signed = true, .bits = CType.short.sizeInBits(target) },
|
||||
.c_ushort => .{ .signed = false, .bits = CType.ushort.sizeInBits(target) },
|
||||
.c_int => .{ .signed = true, .bits = CType.int.sizeInBits(target) },
|
||||
.c_uint => .{ .signed = false, .bits = CType.uint.sizeInBits(target) },
|
||||
.c_long => .{ .signed = true, .bits = CType.long.sizeInBits(target) },
|
||||
.c_ulong => .{ .signed = false, .bits = CType.ulong.sizeInBits(target) },
|
||||
.c_longlong => .{ .signed = true, .bits = CType.longlong.sizeInBits(target) },
|
||||
.c_ulonglong => .{ .signed = false, .bits = CType.ulonglong.sizeInBits(target) },
|
||||
.int_unsigned => .{ .signedness = .unsigned, .bits = self.cast(Payload.IntUnsigned).?.bits },
|
||||
.int_signed => .{ .signedness = .signed, .bits = self.cast(Payload.IntSigned).?.bits },
|
||||
.u8 => .{ .signedness = .unsigned, .bits = 8 },
|
||||
.i8 => .{ .signedness = .signed, .bits = 8 },
|
||||
.u16 => .{ .signedness = .unsigned, .bits = 16 },
|
||||
.i16 => .{ .signedness = .signed, .bits = 16 },
|
||||
.u32 => .{ .signedness = .unsigned, .bits = 32 },
|
||||
.i32 => .{ .signedness = .signed, .bits = 32 },
|
||||
.u64 => .{ .signedness = .unsigned, .bits = 64 },
|
||||
.i64 => .{ .signedness = .signed, .bits = 64 },
|
||||
.usize => .{ .signedness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.isize => .{ .signedness = .signed, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.c_short => .{ .signedness = .signed, .bits = CType.short.sizeInBits(target) },
|
||||
.c_ushort => .{ .signedness = .unsigned, .bits = CType.ushort.sizeInBits(target) },
|
||||
.c_int => .{ .signedness = .signed, .bits = CType.int.sizeInBits(target) },
|
||||
.c_uint => .{ .signedness = .unsigned, .bits = CType.uint.sizeInBits(target) },
|
||||
.c_long => .{ .signedness = .signed, .bits = CType.long.sizeInBits(target) },
|
||||
.c_ulong => .{ .signedness = .unsigned, .bits = CType.ulong.sizeInBits(target) },
|
||||
.c_longlong => .{ .signedness = .signed, .bits = CType.longlong.sizeInBits(target) },
|
||||
.c_ulonglong => .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2869,7 +2869,7 @@ pub const Type = extern union {
|
|||
assert(self.zigTypeTag() == .Int);
|
||||
const info = self.intInfo(target);
|
||||
|
||||
if (!info.signed) {
|
||||
if (info.signedness == .unsigned) {
|
||||
return Value.initTag(.zero);
|
||||
}
|
||||
|
||||
|
@ -2902,13 +2902,13 @@ pub const Type = extern union {
|
|||
assert(self.zigTypeTag() == .Int);
|
||||
const info = self.intInfo(target);
|
||||
|
||||
if (info.signed and (info.bits - 1) <= std.math.maxInt(u6)) {
|
||||
if (info.signedness == .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)) {
|
||||
} else if (info.signedness == .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,
|
||||
|
@ -2917,7 +2917,7 @@ pub const Type = extern union {
|
|||
}
|
||||
|
||||
var res = try std.math.big.int.Managed.initSet(&arena.allocator, 1);
|
||||
try res.shiftLeft(res, info.bits - @boolToInt(info.signed));
|
||||
try res.shiftLeft(res, info.bits - @boolToInt(info.signedness == .signed));
|
||||
const one = std.math.big.int.Const{
|
||||
.limbs = &[_]std.math.big.Limb{1},
|
||||
.positive = true,
|
||||
|
|
|
@ -929,11 +929,10 @@ pub const Value = extern union {
|
|||
.bool_true,
|
||||
=> {
|
||||
const info = ty.intInfo(target);
|
||||
if (info.signed) {
|
||||
return info.bits >= 2;
|
||||
} else {
|
||||
return info.bits >= 1;
|
||||
}
|
||||
return switch (info.signedness) {
|
||||
.signed => info.bits >= 2,
|
||||
.unsigned => info.bits >= 1,
|
||||
};
|
||||
},
|
||||
|
||||
.int_u64 => switch (ty.zigTypeTag()) {
|
||||
|
@ -941,7 +940,7 @@ pub const Value = extern union {
|
|||
const x = self.cast(Payload.Int_u64).?.int;
|
||||
if (x == 0) return true;
|
||||
const info = ty.intInfo(target);
|
||||
const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signed);
|
||||
const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
|
||||
return info.bits >= needed_bits;
|
||||
},
|
||||
.ComptimeInt => return true,
|
||||
|
@ -952,7 +951,7 @@ pub const Value = extern union {
|
|||
const x = self.cast(Payload.Int_i64).?.int;
|
||||
if (x == 0) return true;
|
||||
const info = ty.intInfo(target);
|
||||
if (!info.signed and x < 0)
|
||||
if (info.signedness == .unsigned and x < 0)
|
||||
return false;
|
||||
@panic("TODO implement i64 intFitsInType");
|
||||
},
|
||||
|
@ -962,7 +961,7 @@ pub const Value = extern union {
|
|||
.int_big_positive => switch (ty.zigTypeTag()) {
|
||||
.Int => {
|
||||
const info = ty.intInfo(target);
|
||||
return self.cast(Payload.IntBigPositive).?.asBigInt().fitsInTwosComp(info.signed, info.bits);
|
||||
return self.cast(Payload.IntBigPositive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
|
||||
},
|
||||
.ComptimeInt => return true,
|
||||
else => unreachable,
|
||||
|
@ -970,7 +969,7 @@ pub const Value = extern union {
|
|||
.int_big_negative => switch (ty.zigTypeTag()) {
|
||||
.Int => {
|
||||
const info = ty.intInfo(target);
|
||||
return self.cast(Payload.IntBigNegative).?.asBigInt().fitsInTwosComp(info.signed, info.bits);
|
||||
return self.cast(Payload.IntBigNegative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
|
||||
},
|
||||
.ComptimeInt => return true,
|
||||
else => unreachable,
|
||||
|
|
|
@ -2687,7 +2687,10 @@ const EmitZIR = struct {
|
|||
},
|
||||
.Int => {
|
||||
const info = ty.intInfo(self.old_module.getTarget());
|
||||
const signed = try self.emitPrimitive(src, if (info.signed) .@"true" else .@"false");
|
||||
const signed = try self.emitPrimitive(src, switch (info.signedness) {
|
||||
.signed => .@"true",
|
||||
.unsigned => .@"false",
|
||||
});
|
||||
const bits_payload = try self.arena.allocator.create(Value.Payload.Int_u64);
|
||||
bits_payload.* = .{ .int = info.bits };
|
||||
const bits = try self.emitComptimeIntVal(src, Value.initPayload(&bits_payload.base));
|
||||
|
|
|
@ -72,6 +72,18 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
"tmp.zig:8:12: note: called from here",
|
||||
});
|
||||
|
||||
cases.add("@Type with TypeInfo.Int",
|
||||
\\const builtin = @import("builtin");
|
||||
\\export fn entry() void {
|
||||
\\ _ = @Type(builtin.TypeInfo.Int {
|
||||
\\ .signedness = .signed,
|
||||
\\ .bits = 8,
|
||||
\\ });
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:3:36: error: expected type 'std.builtin.TypeInfo', found 'std.builtin.Int'",
|
||||
});
|
||||
|
||||
cases.add("indexing a undefined slice at comptime",
|
||||
\\comptime {
|
||||
\\ var slice: []u8 = undefined;
|
||||
|
@ -1827,17 +1839,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
"tmp.zig:4:15: error: unable to evaluate constant expression",
|
||||
});
|
||||
|
||||
cases.add("@Type with TypeInfo.Int",
|
||||
\\const builtin = @import("builtin");
|
||||
\\export fn entry() void {
|
||||
\\ _ = @Type(builtin.TypeInfo.Int {
|
||||
\\ .is_signed = true,
|
||||
\\ .bits = 8,
|
||||
\\ });
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:3:36: error: expected type 'std.builtin.TypeInfo', found 'std.builtin.Int'",
|
||||
});
|
||||
cases.add("wrong type for argument tuple to @asyncCall",
|
||||
\\export fn entry1() void {
|
||||
\\ var frame: @Frame(foo) = undefined;
|
||||
|
|
|
@ -31,12 +31,12 @@ test "Type.NoReturn" {
|
|||
}
|
||||
|
||||
test "Type.Int" {
|
||||
testing.expect(u1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 1 } }));
|
||||
testing.expect(i1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 1 } }));
|
||||
testing.expect(u8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 8 } }));
|
||||
testing.expect(i8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 8 } }));
|
||||
testing.expect(u64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 64 } }));
|
||||
testing.expect(i64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 64 } }));
|
||||
testing.expect(u1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .unsigned, .bits = 1 } }));
|
||||
testing.expect(i1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .signed, .bits = 1 } }));
|
||||
testing.expect(u8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .unsigned, .bits = 8 } }));
|
||||
testing.expect(i8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .signed, .bits = 8 } }));
|
||||
testing.expect(u64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .unsigned, .bits = 64 } }));
|
||||
testing.expect(i64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .signedness = .signed, .bits = 64 } }));
|
||||
testTypes(&[_]type{ u8, u32, i64 });
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ test "type info: integer, floating point type info" {
|
|||
fn testIntFloat() void {
|
||||
const u8_info = @typeInfo(u8);
|
||||
expect(u8_info == .Int);
|
||||
expect(!u8_info.Int.is_signed);
|
||||
expect(u8_info.Int.signedness == .unsigned);
|
||||
expect(u8_info.Int.bits == 8);
|
||||
|
||||
const f64_info = @typeInfo(f64);
|
||||
|
|
Loading…
Reference in New Issue