From b4d6e85a339e971829404dc1a260bde4062735f8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 2 Jan 2022 14:11:37 -0700 Subject: [PATCH] Sema: implement peer type resolution of signed and unsigned ints This allows stage2 to build more of compiler-rt. I also changed `-%` to `-` for comptime ints in the div and mul implementations of compiler-rt. This is clearer code and also happens to work around a bug in stage2. --- lib/std/special/compiler_rt.zig | 64 ++++++++++++-------------- lib/std/special/compiler_rt/divdf3.zig | 2 +- lib/std/special/compiler_rt/divsf3.zig | 2 +- lib/std/special/compiler_rt/divtf3.zig | 2 +- lib/std/special/compiler_rt/mulXf3.zig | 2 +- src/Sema.zig | 23 ++++----- src/type.zig | 4 +- test/behavior/cast.zig | 9 ++++ test/behavior/cast_stage1.zig | 9 ---- 9 files changed, 57 insertions(+), 60 deletions(-) diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig index 29c6bdc7c3..7801772647 100644 --- a/lib/std/special/compiler_rt.zig +++ b/lib/std/special/compiler_rt.zig @@ -221,21 +221,19 @@ comptime { const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3; @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage }); - if (!builtin.zig_is_stage2) { - const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3; - @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage }); - const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3; - @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage }); - const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3; - @export(__multf3, .{ .name = "__multf3", .linkage = linkage }); + const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3; + @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage }); + const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3; + @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage }); + const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3; + @export(__multf3, .{ .name = "__multf3", .linkage = linkage }); - const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3; - @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage }); - const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3; - @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage }); - const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3; - @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage }); - } + const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3; + @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage }); + const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3; + @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage }); + const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3; + @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage }); // Integral bit manipulation const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3; @@ -251,26 +249,24 @@ comptime { const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3; @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage }); - if (!builtin.zig_is_stage2) { - const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2; - @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage }); - const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2; - @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage }); - const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2; - @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage }); - const __ctzsi2 = @import("compiler_rt/count0bits.zig").__ctzsi2; - @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = linkage }); - const __ctzdi2 = @import("compiler_rt/count0bits.zig").__ctzdi2; - @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = linkage }); - const __ctzti2 = @import("compiler_rt/count0bits.zig").__ctzti2; - @export(__ctzti2, .{ .name = "__ctzti2", .linkage = linkage }); - const __ffssi2 = @import("compiler_rt/count0bits.zig").__ffssi2; - @export(__ffssi2, .{ .name = "__ffssi2", .linkage = linkage }); - const __ffsdi2 = @import("compiler_rt/count0bits.zig").__ffsdi2; - @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage }); - const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2; - @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage }); - } + const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2; + @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage }); + const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2; + @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage }); + const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2; + @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage }); + const __ctzsi2 = @import("compiler_rt/count0bits.zig").__ctzsi2; + @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = linkage }); + const __ctzdi2 = @import("compiler_rt/count0bits.zig").__ctzdi2; + @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = linkage }); + const __ctzti2 = @import("compiler_rt/count0bits.zig").__ctzti2; + @export(__ctzti2, .{ .name = "__ctzti2", .linkage = linkage }); + const __ffssi2 = @import("compiler_rt/count0bits.zig").__ffssi2; + @export(__ffssi2, .{ .name = "__ffssi2", .linkage = linkage }); + const __ffsdi2 = @import("compiler_rt/count0bits.zig").__ffsdi2; + @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage }); + const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2; + @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage }); const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2; @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage }); diff --git a/lib/std/special/compiler_rt/divdf3.zig b/lib/std/special/compiler_rt/divdf3.zig index ebb139f324..2148902de2 100644 --- a/lib/std/special/compiler_rt/divdf3.zig +++ b/lib/std/special/compiler_rt/divdf3.zig @@ -35,7 +35,7 @@ pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 { var scale: i32 = 0; // Detect if a or b is zero, denormal, infinity, or NaN. - if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) { + if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { const aAbs: Z = @bitCast(Z, a) & absMask; const bAbs: Z = @bitCast(Z, b) & absMask; diff --git a/lib/std/special/compiler_rt/divsf3.zig b/lib/std/special/compiler_rt/divsf3.zig index af4cfaaa86..5e7dc7bb44 100644 --- a/lib/std/special/compiler_rt/divsf3.zig +++ b/lib/std/special/compiler_rt/divsf3.zig @@ -34,7 +34,7 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 { var scale: i32 = 0; // Detect if a or b is zero, denormal, infinity, or NaN. - if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) { + if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { const aAbs: Z = @bitCast(Z, a) & absMask; const bAbs: Z = @bitCast(Z, b) & absMask; diff --git a/lib/std/special/compiler_rt/divtf3.zig b/lib/std/special/compiler_rt/divtf3.zig index 4dce86087d..fc26c60266 100644 --- a/lib/std/special/compiler_rt/divtf3.zig +++ b/lib/std/special/compiler_rt/divtf3.zig @@ -33,7 +33,7 @@ pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 { var scale: i32 = 0; // Detect if a or b is zero, denormal, infinity, or NaN. - if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) { + if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { const aAbs: Z = @bitCast(Z, a) & absMask; const bAbs: Z = @bitCast(Z, b) & absMask; diff --git a/lib/std/special/compiler_rt/mulXf3.zig b/lib/std/special/compiler_rt/mulXf3.zig index 1e9171c8cb..48c31f47b1 100644 --- a/lib/std/special/compiler_rt/mulXf3.zig +++ b/lib/std/special/compiler_rt/mulXf3.zig @@ -56,7 +56,7 @@ fn mulXf3(comptime T: type, a: T, b: T) T { var scale: i32 = 0; // Detect if a or b is zero, denormal, infinity, or NaN. - if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) { + if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { const aAbs: Z = @bitCast(Z, a) & absMask; const bAbs: Z = @bitCast(Z, b) & absMask; diff --git a/src/Sema.zig b/src/Sema.zig index b65e88360f..42bf795bd9 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -14634,11 +14634,11 @@ fn resolvePeerTypes( instructions: []Air.Inst.Ref, candidate_srcs: Module.PeerTypeCandidateSrc, ) !Type { - if (instructions.len == 0) - return Type.initTag(.noreturn); - - if (instructions.len == 1) - return sema.typeOf(instructions[0]); + switch (instructions.len) { + 0 => return Type.initTag(.noreturn), + 1 => return sema.typeOf(instructions[0]), + else => {}, + } const target = sema.mod.getTarget(); @@ -14668,13 +14668,14 @@ fn resolvePeerTypes( continue; }, .Int => { - if (chosen_ty.isSignedInt() == candidate_ty.isSignedInt()) { - if (chosen_ty.intInfo(target).bits < candidate_ty.intInfo(target).bits) { - chosen = candidate; - chosen_i = candidate_i + 1; - } - continue; + const chosen_info = chosen_ty.intInfo(target); + const candidate_info = candidate_ty.intInfo(target); + + if (chosen_info.bits < candidate_info.bits) { + chosen = candidate; + chosen_i = candidate_i + 1; } + continue; }, .Pointer => if (chosen_ty.ptrSize() == .C) continue, else => {}, diff --git a/src/type.zig b/src/type.zig index 9de6bb25a8..b948093994 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3106,9 +3106,9 @@ pub const Type = extern union { .c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) }, .enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty, - .enum_numbered => ty = self.castTag(.enum_numbered).?.data.tag_ty, + .enum_numbered => ty = ty.castTag(.enum_numbered).?.data.tag_ty, .enum_simple => { - const enum_obj = self.castTag(.enum_simple).?.data; + const enum_obj = ty.castTag(.enum_simple).?.data; const field_count = enum_obj.fields.count(); if (field_count == 0) return .{ .signedness = .unsigned, .bits = 0 }; return .{ .signedness = .unsigned, .bits = smallestUnsignedBits(field_count - 1) }; diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index c4ebbc7643..d1edefeb2d 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -295,3 +295,12 @@ test "cast from ?[*]T to ??[*]T" { const a: ??[*]u8 = @as(?[*]u8, null); try expect(a != null and a.? == null); } + +test "peer type unsigned int to signed" { + var w: u31 = 5; + var x: u8 = 7; + var y: i32 = -5; + var a = w + y + x; + comptime try expect(@TypeOf(a) == i32); + try expect(a == 7); +} diff --git a/test/behavior/cast_stage1.zig b/test/behavior/cast_stage1.zig index a4854b30b2..ff4c657ed7 100644 --- a/test/behavior/cast_stage1.zig +++ b/test/behavior/cast_stage1.zig @@ -383,15 +383,6 @@ test "peer type resolve string lit with sentinel-terminated mutable slice" { comptime try expect(@TypeOf("hi", slice) == [:0]const u8); } -test "peer type unsigned int to signed" { - var w: u31 = 5; - var x: u8 = 7; - var y: i32 = -5; - var a = w + y + x; - comptime try expect(@TypeOf(a) == i32); - try expect(a == 7); -} - test "peer type resolve array pointers, one of them const" { var array1: [4]u8 = undefined; const array2: [5]u8 = undefined;