authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-02 14:11:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-02 14:11:37-07:00
logb4d6e85a339e971829404dc1a260bde4062735f8
tree7debe384b184d4b8c24f3d35e2ec8a32b9da8cd0
parent6b14c58f63a177c26ed7ac51c25738ecb115462d

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.

9 files changed, 58 insertions(+), 61 deletions(-)

lib/std/special/compiler_rt.zig+31-35
...@@ -221,21 +221,19 @@ comptime {...@@ -221,21 +221,19 @@ comptime {
221 const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3;221 const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3;
222 @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage });222 @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage });
223223
224 if (!builtin.zig_is_stage2) {224 const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3;
225 const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3;225 @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage });
226 @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage });226 const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3;
227 const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3;227 @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage });
228 @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage });228 const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3;
229 const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3;229 @export(__multf3, .{ .name = "__multf3", .linkage = linkage });
230 @export(__multf3, .{ .name = "__multf3", .linkage = linkage });230
231231 const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3;
232 const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3;232 @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage });
233 @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage });233 const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3;
234 const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3;234 @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage });
235 @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage });235 const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3;
236 const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3;236 @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage });
237 @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage });
238 }
239237
240 // Integral bit manipulation238 // Integral bit manipulation
241 const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3;239 const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3;
...@@ -251,26 +249,24 @@ comptime {...@@ -251,26 +249,24 @@ comptime {
251 const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3;249 const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3;
252 @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });250 @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage });
253251
254 if (!builtin.zig_is_stage2) {252 const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2;
255 const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2;253 @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });
256 @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });254 const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2;
257 const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2;255 @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage });
258 @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage });256 const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2;
259 const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2;257 @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage });
260 @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage });258 const __ctzsi2 = @import("compiler_rt/count0bits.zig").__ctzsi2;
261 const __ctzsi2 = @import("compiler_rt/count0bits.zig").__ctzsi2;259 @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = linkage });
262 @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = linkage });260 const __ctzdi2 = @import("compiler_rt/count0bits.zig").__ctzdi2;
263 const __ctzdi2 = @import("compiler_rt/count0bits.zig").__ctzdi2;261 @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = linkage });
264 @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = linkage });262 const __ctzti2 = @import("compiler_rt/count0bits.zig").__ctzti2;
265 const __ctzti2 = @import("compiler_rt/count0bits.zig").__ctzti2;263 @export(__ctzti2, .{ .name = "__ctzti2", .linkage = linkage });
266 @export(__ctzti2, .{ .name = "__ctzti2", .linkage = linkage });264 const __ffssi2 = @import("compiler_rt/count0bits.zig").__ffssi2;
267 const __ffssi2 = @import("compiler_rt/count0bits.zig").__ffssi2;265 @export(__ffssi2, .{ .name = "__ffssi2", .linkage = linkage });
268 @export(__ffssi2, .{ .name = "__ffssi2", .linkage = linkage });266 const __ffsdi2 = @import("compiler_rt/count0bits.zig").__ffsdi2;
269 const __ffsdi2 = @import("compiler_rt/count0bits.zig").__ffsdi2;267 @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage });
270 @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage });268 const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2;
271 const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2;269 @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage });
272 @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage });
273 }
274270
275 const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2;271 const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2;
276 @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage });272 @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage });
lib/std/special/compiler_rt/divdf3.zig+1-1
...@@ -35,7 +35,7 @@ pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {...@@ -35,7 +35,7 @@ pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {
35 var scale: i32 = 0;35 var scale: i32 = 0;
3636
37 // Detect if a or b is zero, denormal, infinity, or NaN.37 // Detect if a or b is zero, denormal, infinity, or NaN.
38 if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) {38 if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
39 const aAbs: Z = @bitCast(Z, a) & absMask;39 const aAbs: Z = @bitCast(Z, a) & absMask;
40 const bAbs: Z = @bitCast(Z, b) & absMask;40 const bAbs: Z = @bitCast(Z, b) & absMask;
4141
lib/std/special/compiler_rt/divsf3.zig+1-1
...@@ -34,7 +34,7 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {...@@ -34,7 +34,7 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
34 var scale: i32 = 0;34 var scale: i32 = 0;
3535
36 // Detect if a or b is zero, denormal, infinity, or NaN.36 // Detect if a or b is zero, denormal, infinity, or NaN.
37 if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) {37 if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
38 const aAbs: Z = @bitCast(Z, a) & absMask;38 const aAbs: Z = @bitCast(Z, a) & absMask;
39 const bAbs: Z = @bitCast(Z, b) & absMask;39 const bAbs: Z = @bitCast(Z, b) & absMask;
4040
lib/std/special/compiler_rt/divtf3.zig+1-1
...@@ -33,7 +33,7 @@ pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 {...@@ -33,7 +33,7 @@ pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 {
33 var scale: i32 = 0;33 var scale: i32 = 0;
3434
35 // Detect if a or b is zero, denormal, infinity, or NaN.35 // Detect if a or b is zero, denormal, infinity, or NaN.
36 if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) {36 if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
37 const aAbs: Z = @bitCast(Z, a) & absMask;37 const aAbs: Z = @bitCast(Z, a) & absMask;
38 const bAbs: Z = @bitCast(Z, b) & absMask;38 const bAbs: Z = @bitCast(Z, b) & absMask;
3939
lib/std/special/compiler_rt/mulXf3.zig+1-1
...@@ -56,7 +56,7 @@ fn mulXf3(comptime T: type, a: T, b: T) T {...@@ -56,7 +56,7 @@ fn mulXf3(comptime T: type, a: T, b: T) T {
56 var scale: i32 = 0;56 var scale: i32 = 0;
5757
58 // Detect if a or b is zero, denormal, infinity, or NaN.58 // Detect if a or b is zero, denormal, infinity, or NaN.
59 if (aExponent -% 1 >= maxExponent -% 1 or bExponent -% 1 >= maxExponent -% 1) {59 if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
60 const aAbs: Z = @bitCast(Z, a) & absMask;60 const aAbs: Z = @bitCast(Z, a) & absMask;
61 const bAbs: Z = @bitCast(Z, b) & absMask;61 const bAbs: Z = @bitCast(Z, b) & absMask;
6262
src/Sema.zig+12-11
...@@ -14634,11 +14634,11 @@ fn resolvePeerTypes(...@@ -14634,11 +14634,11 @@ fn resolvePeerTypes(
14634 instructions: []Air.Inst.Ref,14634 instructions: []Air.Inst.Ref,
14635 candidate_srcs: Module.PeerTypeCandidateSrc,14635 candidate_srcs: Module.PeerTypeCandidateSrc,
14636) !Type {14636) !Type {
14637 if (instructions.len == 0)14637 switch (instructions.len) {
14638 return Type.initTag(.noreturn);14638 0 => return Type.initTag(.noreturn),
1463914639 1 => return sema.typeOf(instructions[0]),
14640 if (instructions.len == 1)14640 else => {},
14641 return sema.typeOf(instructions[0]);14641 }
1464214642
14643 const target = sema.mod.getTarget();14643 const target = sema.mod.getTarget();
1464414644
...@@ -14668,13 +14668,14 @@ fn resolvePeerTypes(...@@ -14668,13 +14668,14 @@ fn resolvePeerTypes(
14668 continue;14668 continue;
14669 },14669 },
14670 .Int => {14670 .Int => {
14671 if (chosen_ty.isSignedInt() == candidate_ty.isSignedInt()) {14671 const chosen_info = chosen_ty.intInfo(target);
14672 if (chosen_ty.intInfo(target).bits < candidate_ty.intInfo(target).bits) {14672 const candidate_info = candidate_ty.intInfo(target);
14673 chosen = candidate;14673
14674 chosen_i = candidate_i + 1;14674 if (chosen_info.bits < candidate_info.bits) {
14675 }14675 chosen = candidate;
14676 continue;14676 chosen_i = candidate_i + 1;
14677 }14677 }
14678 continue;
14678 },14679 },
14679 .Pointer => if (chosen_ty.ptrSize() == .C) continue,14680 .Pointer => if (chosen_ty.ptrSize() == .C) continue,
14680 else => {},14681 else => {},
src/type.zig+2-2
...@@ -3106,9 +3106,9 @@ pub const Type = extern union {...@@ -3106,9 +3106,9 @@ pub const Type = extern union {
3106 .c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },3106 .c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
31073107
3108 .enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty,3108 .enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty,
3109 .enum_numbered => ty = self.castTag(.enum_numbered).?.data.tag_ty,3109 .enum_numbered => ty = ty.castTag(.enum_numbered).?.data.tag_ty,
3110 .enum_simple => {3110 .enum_simple => {
3111 const enum_obj = self.castTag(.enum_simple).?.data;3111 const enum_obj = ty.castTag(.enum_simple).?.data;
3112 const field_count = enum_obj.fields.count();3112 const field_count = enum_obj.fields.count();
3113 if (field_count == 0) return .{ .signedness = .unsigned, .bits = 0 };3113 if (field_count == 0) return .{ .signedness = .unsigned, .bits = 0 };
3114 return .{ .signedness = .unsigned, .bits = smallestUnsignedBits(field_count - 1) };3114 return .{ .signedness = .unsigned, .bits = smallestUnsignedBits(field_count - 1) };
test/behavior/cast.zig+9
...@@ -295,3 +295,12 @@ test "cast from ?[*]T to ??[*]T" {...@@ -295,3 +295,12 @@ test "cast from ?[*]T to ??[*]T" {
295 const a: ??[*]u8 = @as(?[*]u8, null);295 const a: ??[*]u8 = @as(?[*]u8, null);
296 try expect(a != null and a.? == null);296 try expect(a != null and a.? == null);
297}297}
298
299test "peer type unsigned int to signed" {
300 var w: u31 = 5;
301 var x: u8 = 7;
302 var y: i32 = -5;
303 var a = w + y + x;
304 comptime try expect(@TypeOf(a) == i32);
305 try expect(a == 7);
306}
test/behavior/cast_stage1.zig-9
...@@ -383,15 +383,6 @@ test "peer type resolve string lit with sentinel-terminated mutable slice" {...@@ -383,15 +383,6 @@ test "peer type resolve string lit with sentinel-terminated mutable slice" {
383 comptime try expect(@TypeOf("hi", slice) == [:0]const u8);383 comptime try expect(@TypeOf("hi", slice) == [:0]const u8);
384}384}
385385
386test "peer type unsigned int to signed" {
387 var w: u31 = 5;
388 var x: u8 = 7;
389 var y: i32 = -5;
390 var a = w + y + x;
391 comptime try expect(@TypeOf(a) == i32);
392 try expect(a == 7);
393}
394
395test "peer type resolve array pointers, one of them const" {386test "peer type resolve array pointers, one of them const" {
396 var array1: [4]u8 = undefined;387 var array1: [4]u8 = undefined;
397 const array2: [5]u8 = undefined;388 const array2: [5]u8 = undefined;