authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-02 19:56:43+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-03 00:09:23+02:00
log0e38cc16d51178525e89774ce9151651b6a0e99a
tree41e3768824dc156b70fccf506362f4fa7277e3ae
parent7f9e841f746bb3eaf6ac205092a30bc7ed12a068

Sema: fix comparisons between lazy and runtime values

Closes #12498

14 files changed, 48 insertions(+), 30 deletions(-)

lib/std/fs.zig-2
...@@ -809,8 +809,6 @@ pub const IterableDir = struct {...@@ -809,8 +809,6 @@ pub const IterableDir = struct {
809 // and we avoid the code complexity here.809 // and we avoid the code complexity here.
810 const w = os.wasi;810 const w = os.wasi;
811 start_over: while (true) {811 start_over: while (true) {
812 // TODO https://github.com/ziglang/zig/issues/12498
813 _ = @sizeOf(w.dirent_t) + 1;
814 // According to the WASI spec, the last entry might be truncated,812 // According to the WASI spec, the last entry might be truncated,
815 // so we need to check if the left buffer contains the whole dirent.813 // so we need to check if the left buffer contains the whole dirent.
816 if (self.end_index - self.index < @sizeOf(w.dirent_t)) {814 if (self.end_index - self.index < @sizeOf(w.dirent_t)) {
src/Sema.zig+4-2
...@@ -20262,7 +20262,7 @@ fn analyzeShuffle(...@@ -20262,7 +20262,7 @@ fn analyzeShuffle(
20262 var buf: Value.ElemValueBuffer = undefined;20262 var buf: Value.ElemValueBuffer = undefined;
20263 const elem = mask.elemValueBuffer(sema.mod, i, &buf);20263 const elem = mask.elemValueBuffer(sema.mod, i, &buf);
20264 if (elem.isUndef()) continue;20264 if (elem.isUndef()) continue;
20265 const int = elem.toSignedInt();20265 const int = elem.toSignedInt(sema.mod.getTarget());
20266 var unsigned: u32 = undefined;20266 var unsigned: u32 = undefined;
20267 var chosen: u32 = undefined;20267 var chosen: u32 = undefined;
20268 if (int >= 0) {20268 if (int >= 0) {
...@@ -20304,7 +20304,7 @@ fn analyzeShuffle(...@@ -20304,7 +20304,7 @@ fn analyzeShuffle(
20304 values[i] = Value.undef;20304 values[i] = Value.undef;
20305 continue;20305 continue;
20306 }20306 }
20307 const int = mask_elem_val.toSignedInt();20307 const int = mask_elem_val.toSignedInt(sema.mod.getTarget());
20308 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int);20308 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int);
20309 if (int >= 0) {20309 if (int >= 0) {
20310 values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned);20310 values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned);
...@@ -28299,6 +28299,7 @@ fn cmpNumeric(...@@ -28299,6 +28299,7 @@ fn cmpNumeric(
2829928299
28300 var lhs_bits: usize = undefined;28300 var lhs_bits: usize = undefined;
28301 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {28301 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {
28302 try sema.resolveLazyValue(lhs_val);
28302 if (lhs_val.isUndef())28303 if (lhs_val.isUndef())
28303 return sema.addConstUndef(Type.bool);28304 return sema.addConstUndef(Type.bool);
28304 if (lhs_val.isNan()) switch (op) {28305 if (lhs_val.isNan()) switch (op) {
...@@ -28357,6 +28358,7 @@ fn cmpNumeric(...@@ -28357,6 +28358,7 @@ fn cmpNumeric(
2835728358
28358 var rhs_bits: usize = undefined;28359 var rhs_bits: usize = undefined;
28359 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {28360 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {
28361 try sema.resolveLazyValue(rhs_val);
28360 if (rhs_val.isUndef())28362 if (rhs_val.isUndef())
28361 return sema.addConstUndef(Type.bool);28363 return sema.addConstUndef(Type.bool);
28362 if (rhs_val.isNan()) switch (op) {28364 if (rhs_val.isNan()) switch (op) {
src/arch/aarch64/CodeGen.zig+1-1
...@@ -6247,7 +6247,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6247,7 +6247,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6247 if (info.bits <= 64) {6247 if (info.bits <= 64) {
6248 const unsigned = switch (info.signedness) {6248 const unsigned = switch (info.signedness) {
6249 .signed => blk: {6249 .signed => blk: {
6250 const signed = typed_value.val.toSignedInt();6250 const signed = typed_value.val.toSignedInt(target);
6251 break :blk @bitCast(u64, signed);6251 break :blk @bitCast(u64, signed);
6252 },6252 },
6253 .unsigned => typed_value.val.toUnsignedInt(target),6253 .unsigned => typed_value.val.toUnsignedInt(target),
src/arch/arm/CodeGen.zig+1-1
...@@ -6121,7 +6121,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6121,7 +6121,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6121 if (info.bits <= ptr_bits) {6121 if (info.bits <= ptr_bits) {
6122 const unsigned = switch (info.signedness) {6122 const unsigned = switch (info.signedness) {
6123 .signed => blk: {6123 .signed => blk: {
6124 const signed = @intCast(i32, typed_value.val.toSignedInt());6124 const signed = @intCast(i32, typed_value.val.toSignedInt(target));
6125 break :blk @bitCast(u32, signed);6125 break :blk @bitCast(u32, signed);
6126 },6126 },
6127 .unsigned => @intCast(u32, typed_value.val.toUnsignedInt(target)),6127 .unsigned => @intCast(u32, typed_value.val.toUnsignedInt(target)),
src/arch/sparc64/CodeGen.zig+1-1
...@@ -3786,7 +3786,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -3786,7 +3786,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
3786 if (info.bits <= 64) {3786 if (info.bits <= 64) {
3787 const unsigned = switch (info.signedness) {3787 const unsigned = switch (info.signedness) {
3788 .signed => blk: {3788 .signed => blk: {
3789 const signed = typed_value.val.toSignedInt();3789 const signed = typed_value.val.toSignedInt(target);
3790 break :blk @bitCast(u64, signed);3790 break :blk @bitCast(u64, signed);
3791 },3791 },
3792 .unsigned => typed_value.val.toUnsignedInt(target),3792 .unsigned => typed_value.val.toUnsignedInt(target),
src/arch/wasm/CodeGen.zig+5-5
...@@ -2702,11 +2702,11 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {...@@ -2702,11 +2702,11 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
2702 switch (int_info.signedness) {2702 switch (int_info.signedness) {
2703 .signed => switch (int_info.bits) {2703 .signed => switch (int_info.bits) {
2704 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement(2704 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement(
2705 val.toSignedInt(),2705 val.toSignedInt(target),
2706 @intCast(u6, int_info.bits),2706 @intCast(u6, int_info.bits),
2707 )) },2707 )) },
2708 33...64 => return WValue{ .imm64 = toTwosComplement(2708 33...64 => return WValue{ .imm64 = toTwosComplement(
2709 val.toSignedInt(),2709 val.toSignedInt(target),
2710 @intCast(u7, int_info.bits),2710 @intCast(u7, int_info.bits),
2711 ) },2711 ) },
2712 else => unreachable,2712 else => unreachable,
...@@ -2873,15 +2873,15 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {...@@ -2873,15 +2873,15 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {
2873 }2873 }
2874 },2874 },
2875 .Int => switch (ty.intInfo(func.target).signedness) {2875 .Int => switch (ty.intInfo(func.target).signedness) {
2876 .signed => return @truncate(i32, val.toSignedInt()),2876 .signed => return @truncate(i32, val.toSignedInt(target)),
2877 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt(target))),2877 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt(target))),
2878 },2878 },
2879 .ErrorSet => {2879 .ErrorSet => {
2880 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function2880 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function
2881 return @bitCast(i32, kv.value);2881 return @bitCast(i32, kv.value);
2882 },2882 },
2883 .Bool => return @intCast(i32, val.toSignedInt()),2883 .Bool => return @intCast(i32, val.toSignedInt(target)),
2884 .Pointer => return @intCast(i32, val.toSignedInt()),2884 .Pointer => return @intCast(i32, val.toSignedInt(target)),
2885 else => unreachable, // Programmer called this function for an illegal type2885 else => unreachable, // Programmer called this function for an illegal type
2886 }2886 }
2887}2887}
src/arch/x86_64/CodeGen.zig+1-1
...@@ -7007,7 +7007,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -7007,7 +7007,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
7007 .Int => {7007 .Int => {
7008 const info = typed_value.ty.intInfo(self.target.*);7008 const info = typed_value.ty.intInfo(self.target.*);
7009 if (info.bits <= ptr_bits and info.signedness == .signed) {7009 if (info.bits <= ptr_bits and info.signedness == .signed) {
7010 return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) };7010 return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt(target)) };
7011 }7011 }
7012 if (!(info.bits > ptr_bits or info.signedness == .signed)) {7012 if (!(info.bits > ptr_bits or info.signedness == .signed)) {
7013 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };7013 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
src/codegen.zig+7-7
...@@ -459,7 +459,7 @@ pub fn generateSymbol(...@@ -459,7 +459,7 @@ pub fn generateSymbol(
459 if (info.bits <= 8) {459 if (info.bits <= 8) {
460 const x: u8 = switch (info.signedness) {460 const x: u8 = switch (info.signedness) {
461 .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(target)),461 .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(target)),
462 .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt())),462 .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt(target))),
463 };463 };
464 try code.append(x);464 try code.append(x);
465 return Result{ .appended = {} };465 return Result{ .appended = {} };
...@@ -488,13 +488,13 @@ pub fn generateSymbol(...@@ -488,13 +488,13 @@ pub fn generateSymbol(
488 },488 },
489 .signed => {489 .signed => {
490 if (info.bits <= 16) {490 if (info.bits <= 16) {
491 const x = @intCast(i16, typed_value.val.toSignedInt());491 const x = @intCast(i16, typed_value.val.toSignedInt(target));
492 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);492 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
493 } else if (info.bits <= 32) {493 } else if (info.bits <= 32) {
494 const x = @intCast(i32, typed_value.val.toSignedInt());494 const x = @intCast(i32, typed_value.val.toSignedInt(target));
495 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);495 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
496 } else {496 } else {
497 const x = typed_value.val.toSignedInt();497 const x = typed_value.val.toSignedInt(target);
498 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);498 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
499 }499 }
500 },500 },
...@@ -536,13 +536,13 @@ pub fn generateSymbol(...@@ -536,13 +536,13 @@ pub fn generateSymbol(
536 },536 },
537 .signed => {537 .signed => {
538 if (info.bits <= 16) {538 if (info.bits <= 16) {
539 const x = @intCast(i16, int_val.toSignedInt());539 const x = @intCast(i16, int_val.toSignedInt(target));
540 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);540 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
541 } else if (info.bits <= 32) {541 } else if (info.bits <= 32) {
542 const x = @intCast(i32, int_val.toSignedInt());542 const x = @intCast(i32, int_val.toSignedInt(target));
543 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);543 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
544 } else {544 } else {
545 const x = int_val.toSignedInt();545 const x = int_val.toSignedInt(target);
546 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);546 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
547 }547 }
548 },548 },
src/codegen/llvm.zig+1-1
...@@ -8932,7 +8932,7 @@ pub const FuncGen = struct {...@@ -8932,7 +8932,7 @@ pub const FuncGen = struct {
8932 if (elem.isUndef()) {8932 if (elem.isUndef()) {
8933 val.* = llvm_i32.getUndef();8933 val.* = llvm_i32.getUndef();
8934 } else {8934 } else {
8935 const int = elem.toSignedInt();8935 const int = elem.toSignedInt(self.dg.module.getTarget());
8936 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);8936 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
8937 val.* = llvm_i32.constInt(unsigned, .False);8937 val.* = llvm_i32.constInt(unsigned, .False);
8938 }8938 }
src/codegen/spirv.zig+2-2
...@@ -360,7 +360,7 @@ pub const DeclGen = struct {...@@ -360,7 +360,7 @@ pub const DeclGen = struct {
360360
361 // Note, value is required to be sign-extended, so we don't need to mask off the upper bits.361 // Note, value is required to be sign-extended, so we don't need to mask off the upper bits.
362 // See https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Literal362 // See https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Literal
363 var int_bits = if (ty.isSignedInt()) @bitCast(u64, val.toSignedInt()) else val.toUnsignedInt(target);363 var int_bits = if (ty.isSignedInt()) @bitCast(u64, val.toSignedInt(target)) else val.toUnsignedInt(target);
364364
365 const value: spec.LiteralContextDependentNumber = switch (backing_bits) {365 const value: spec.LiteralContextDependentNumber = switch (backing_bits) {
366 1...32 => .{ .uint32 = @truncate(u32, int_bits) },366 1...32 => .{ .uint32 = @truncate(u32, int_bits) },
...@@ -763,7 +763,7 @@ pub const DeclGen = struct {...@@ -763,7 +763,7 @@ pub const DeclGen = struct {
763 if (elem.isUndef()) {763 if (elem.isUndef()) {
764 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);764 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);
765 } else {765 } else {
766 const int = elem.toSignedInt();766 const int = elem.toSignedInt(self.getTarget());
767 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);767 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
768 self.func.body.writeOperand(spec.LiteralInteger, unsigned);768 self.func.body.writeOperand(spec.LiteralInteger, unsigned);
769 }769 }
src/link/Dwarf.zig+1-1
...@@ -409,7 +409,7 @@ pub const DeclState = struct {...@@ -409,7 +409,7 @@ pub const DeclState = struct {
409 // See https://github.com/ziglang/zig/issues/645409 // See https://github.com/ziglang/zig/issues/645
410 var int_buffer: Value.Payload.U64 = undefined;410 var int_buffer: Value.Payload.U64 = undefined;
411 const field_int_val = value.enumToInt(ty, &int_buffer);411 const field_int_val = value.enumToInt(ty, &int_buffer);
412 break :value @bitCast(u64, field_int_val.toSignedInt());412 break :value @bitCast(u64, field_int_val.toSignedInt(target));
413 } else @intCast(u64, field_i);413 } else @intCast(u64, field_i);
414 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);414 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);
415 }415 }
src/value.zig+15-6
...@@ -1201,8 +1201,8 @@ pub const Value = extern union {...@@ -1201,8 +1201,8 @@ pub const Value = extern union {
1201 }1201 }
12021202
1203 /// Asserts the value is an integer and it fits in a i641203 /// Asserts the value is an integer and it fits in a i64
1204 pub fn toSignedInt(self: Value) i64 {1204 pub fn toSignedInt(val: Value, target: Target) i64 {
1205 switch (self.tag()) {1205 switch (val.tag()) {
1206 .zero,1206 .zero,
1207 .bool_false,1207 .bool_false,
1208 .the_only_possible_value, // i0, u01208 .the_only_possible_value, // i0, u0
...@@ -1212,10 +1212,19 @@ pub const Value = extern union {...@@ -1212,10 +1212,19 @@ pub const Value = extern union {
1212 .bool_true,1212 .bool_true,
1213 => return 1,1213 => return 1,
12141214
1215 .int_u64 => return @intCast(i64, self.castTag(.int_u64).?.data),1215 .int_u64 => return @intCast(i64, val.castTag(.int_u64).?.data),
1216 .int_i64 => return self.castTag(.int_i64).?.data,1216 .int_i64 => return val.castTag(.int_i64).?.data,
1217 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,1217 .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,
1218 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,1218 .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,
1219
1220 .lazy_align => {
1221 const ty = val.castTag(.lazy_align).?.data;
1222 return @intCast(i64, ty.abiAlignment(target));
1223 },
1224 .lazy_size => {
1225 const ty = val.castTag(.lazy_size).?.data;
1226 return @intCast(i64, ty.abiSize(target));
1227 },
12191228
1220 .undef => unreachable,1229 .undef => unreachable,
1221 else => unreachable,1230 else => unreachable,
test/behavior.zig+1
...@@ -90,6 +90,7 @@ test {...@@ -90,6 +90,7 @@ test {
90 _ = @import("behavior/bugs/12430.zig");90 _ = @import("behavior/bugs/12430.zig");
91 _ = @import("behavior/bugs/12486.zig");91 _ = @import("behavior/bugs/12486.zig");
92 _ = @import("behavior/bugs/12488.zig");92 _ = @import("behavior/bugs/12488.zig");
93 _ = @import("behavior/bugs/12498.zig");
93 _ = @import("behavior/bugs/12551.zig");94 _ = @import("behavior/bugs/12551.zig");
94 _ = @import("behavior/bugs/12644.zig");95 _ = @import("behavior/bugs/12644.zig");
95 _ = @import("behavior/bugs/12680.zig");96 _ = @import("behavior/bugs/12680.zig");
test/behavior/bugs/12498.zig created+8
...@@ -0,0 +1,8 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4const S = struct { a: usize };
5test "lazy abi size used in comparison" {
6 var rhs: i32 = 100;
7 try expect(@sizeOf(S) < rhs);
8}