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 {
809809 // and we avoid the code complexity here.
810810 const w = os.wasi;
811811 start_over: while (true) {
812 // TODO https://github.com/ziglang/zig/issues/12498
813 _ = @sizeOf(w.dirent_t) + 1;
814812 // According to the WASI spec, the last entry might be truncated,
815813 // so we need to check if the left buffer contains the whole dirent.
816814 if (self.end_index - self.index < @sizeOf(w.dirent_t)) {
src/Sema.zig+4-2
......@@ -20262,7 +20262,7 @@ fn analyzeShuffle(
2026220262 var buf: Value.ElemValueBuffer = undefined;
2026320263 const elem = mask.elemValueBuffer(sema.mod, i, &buf);
2026420264 if (elem.isUndef()) continue;
20265 const int = elem.toSignedInt();
20265 const int = elem.toSignedInt(sema.mod.getTarget());
2026620266 var unsigned: u32 = undefined;
2026720267 var chosen: u32 = undefined;
2026820268 if (int >= 0) {
......@@ -20304,7 +20304,7 @@ fn analyzeShuffle(
2030420304 values[i] = Value.undef;
2030520305 continue;
2030620306 }
20307 const int = mask_elem_val.toSignedInt();
20307 const int = mask_elem_val.toSignedInt(sema.mod.getTarget());
2030820308 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int);
2030920309 if (int >= 0) {
2031020310 values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned);
......@@ -28299,6 +28299,7 @@ fn cmpNumeric(
2829928299
2830028300 var lhs_bits: usize = undefined;
2830128301 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {
28302 try sema.resolveLazyValue(lhs_val);
2830228303 if (lhs_val.isUndef())
2830328304 return sema.addConstUndef(Type.bool);
2830428305 if (lhs_val.isNan()) switch (op) {
......@@ -28357,6 +28358,7 @@ fn cmpNumeric(
2835728358
2835828359 var rhs_bits: usize = undefined;
2835928360 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {
28361 try sema.resolveLazyValue(rhs_val);
2836028362 if (rhs_val.isUndef())
2836128363 return sema.addConstUndef(Type.bool);
2836228364 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 {
62476247 if (info.bits <= 64) {
62486248 const unsigned = switch (info.signedness) {
62496249 .signed => blk: {
6250 const signed = typed_value.val.toSignedInt();
6250 const signed = typed_value.val.toSignedInt(target);
62516251 break :blk @bitCast(u64, signed);
62526252 },
62536253 .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 {
61216121 if (info.bits <= ptr_bits) {
61226122 const unsigned = switch (info.signedness) {
61236123 .signed => blk: {
6124 const signed = @intCast(i32, typed_value.val.toSignedInt());
6124 const signed = @intCast(i32, typed_value.val.toSignedInt(target));
61256125 break :blk @bitCast(u32, signed);
61266126 },
61276127 .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 {
37863786 if (info.bits <= 64) {
37873787 const unsigned = switch (info.signedness) {
37883788 .signed => blk: {
3789 const signed = typed_value.val.toSignedInt();
3789 const signed = typed_value.val.toSignedInt(target);
37903790 break :blk @bitCast(u64, signed);
37913791 },
37923792 .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 {
27022702 switch (int_info.signedness) {
27032703 .signed => switch (int_info.bits) {
27042704 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement(
2705 val.toSignedInt(),
2705 val.toSignedInt(target),
27062706 @intCast(u6, int_info.bits),
27072707 )) },
27082708 33...64 => return WValue{ .imm64 = toTwosComplement(
2709 val.toSignedInt(),
2709 val.toSignedInt(target),
27102710 @intCast(u7, int_info.bits),
27112711 ) },
27122712 else => unreachable,
......@@ -2873,15 +2873,15 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {
28732873 }
28742874 },
28752875 .Int => switch (ty.intInfo(func.target).signedness) {
2876 .signed => return @truncate(i32, val.toSignedInt()),
2876 .signed => return @truncate(i32, val.toSignedInt(target)),
28772877 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt(target))),
28782878 },
28792879 .ErrorSet => {
28802880 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function
28812881 return @bitCast(i32, kv.value);
28822882 },
2883 .Bool => return @intCast(i32, val.toSignedInt()),
2884 .Pointer => return @intCast(i32, val.toSignedInt()),
2883 .Bool => return @intCast(i32, val.toSignedInt(target)),
2884 .Pointer => return @intCast(i32, val.toSignedInt(target)),
28852885 else => unreachable, // Programmer called this function for an illegal type
28862886 }
28872887}
src/arch/x86_64/CodeGen.zig+1-1
......@@ -7007,7 +7007,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
70077007 .Int => {
70087008 const info = typed_value.ty.intInfo(self.target.*);
70097009 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)) };
70117011 }
70127012 if (!(info.bits > ptr_bits or info.signedness == .signed)) {
70137013 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
src/codegen.zig+7-7
......@@ -459,7 +459,7 @@ pub fn generateSymbol(
459459 if (info.bits <= 8) {
460460 const x: u8 = switch (info.signedness) {
461461 .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))),
463463 };
464464 try code.append(x);
465465 return Result{ .appended = {} };
......@@ -488,13 +488,13 @@ pub fn generateSymbol(
488488 },
489489 .signed => {
490490 if (info.bits <= 16) {
491 const x = @intCast(i16, typed_value.val.toSignedInt());
491 const x = @intCast(i16, typed_value.val.toSignedInt(target));
492492 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
493493 } else if (info.bits <= 32) {
494 const x = @intCast(i32, typed_value.val.toSignedInt());
494 const x = @intCast(i32, typed_value.val.toSignedInt(target));
495495 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
496496 } else {
497 const x = typed_value.val.toSignedInt();
497 const x = typed_value.val.toSignedInt(target);
498498 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
499499 }
500500 },
......@@ -536,13 +536,13 @@ pub fn generateSymbol(
536536 },
537537 .signed => {
538538 if (info.bits <= 16) {
539 const x = @intCast(i16, int_val.toSignedInt());
539 const x = @intCast(i16, int_val.toSignedInt(target));
540540 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
541541 } else if (info.bits <= 32) {
542 const x = @intCast(i32, int_val.toSignedInt());
542 const x = @intCast(i32, int_val.toSignedInt(target));
543543 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
544544 } else {
545 const x = int_val.toSignedInt();
545 const x = int_val.toSignedInt(target);
546546 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
547547 }
548548 },
src/codegen/llvm.zig+1-1
......@@ -8932,7 +8932,7 @@ pub const FuncGen = struct {
89328932 if (elem.isUndef()) {
89338933 val.* = llvm_i32.getUndef();
89348934 } else {
8935 const int = elem.toSignedInt();
8935 const int = elem.toSignedInt(self.dg.module.getTarget());
89368936 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
89378937 val.* = llvm_i32.constInt(unsigned, .False);
89388938 }
src/codegen/spirv.zig+2-2
......@@ -360,7 +360,7 @@ pub const DeclGen = struct {
360360
361361 // Note, value is required to be sign-extended, so we don't need to mask off the upper bits.
362362 // 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
365365 const value: spec.LiteralContextDependentNumber = switch (backing_bits) {
366366 1...32 => .{ .uint32 = @truncate(u32, int_bits) },
......@@ -763,7 +763,7 @@ pub const DeclGen = struct {
763763 if (elem.isUndef()) {
764764 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);
765765 } else {
766 const int = elem.toSignedInt();
766 const int = elem.toSignedInt(self.getTarget());
767767 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
768768 self.func.body.writeOperand(spec.LiteralInteger, unsigned);
769769 }
src/link/Dwarf.zig+1-1
......@@ -409,7 +409,7 @@ pub const DeclState = struct {
409409 // See https://github.com/ziglang/zig/issues/645
410410 var int_buffer: Value.Payload.U64 = undefined;
411411 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));
413413 } else @intCast(u64, field_i);
414414 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);
415415 }
src/value.zig+15-6
......@@ -1201,8 +1201,8 @@ pub const Value = extern union {
12011201 }
12021202
12031203 /// Asserts the value is an integer and it fits in a i64
1204 pub fn toSignedInt(self: Value) i64 {
1205 switch (self.tag()) {
1204 pub fn toSignedInt(val: Value, target: Target) i64 {
1205 switch (val.tag()) {
12061206 .zero,
12071207 .bool_false,
12081208 .the_only_possible_value, // i0, u0
......@@ -1212,10 +1212,19 @@ pub const Value = extern union {
12121212 .bool_true,
12131213 => return 1,
12141214
1215 .int_u64 => return @intCast(i64, self.castTag(.int_u64).?.data),
1216 .int_i64 => return self.castTag(.int_i64).?.data,
1217 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,
1218 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,
1215 .int_u64 => return @intCast(i64, val.castTag(.int_u64).?.data),
1216 .int_i64 => return val.castTag(.int_i64).?.data,
1217 .int_big_positive => return val.castTag(.int_big_positive).?.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
12201229 .undef => unreachable,
12211230 else => unreachable,
test/behavior.zig+1
......@@ -90,6 +90,7 @@ test {
9090 _ = @import("behavior/bugs/12430.zig");
9191 _ = @import("behavior/bugs/12486.zig");
9292 _ = @import("behavior/bugs/12488.zig");
93 _ = @import("behavior/bugs/12498.zig");
9394 _ = @import("behavior/bugs/12551.zig");
9495 _ = @import("behavior/bugs/12644.zig");
9596 _ = @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}