From 593d23c0d746deae1036b5209c683c1984dd0203 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 27 Feb 2022 10:00:15 +0200 Subject: [PATCH 1/6] stage2: get formatted printing (somewhat) working --- lib/std/special/test_runner.zig | 16 ++++++++++++++-- src/Sema.zig | 3 +-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/std/special/test_runner.zig b/lib/std/special/test_runner.zig index f8377f283b..6f392e710b 100644 --- a/lib/std/special/test_runner.zig +++ b/lib/std/special/test_runner.zig @@ -141,8 +141,20 @@ pub fn main2() anyerror!void { } }; } - if (builtin.zig_backend == .stage2_llvm or - builtin.zig_backend == .stage2_wasm or + if (builtin.zig_backend == .stage2_llvm) { + const stderr = std.io.getStdErr().writer(); + const ok_count = builtin.test_functions.len - skipped - failed; + if (ok_count == builtin.test_functions.len) { + try stderr.print("All {d} tests passed.\n", .{ok_count}); + } else { + try stderr.print("{d} passed; ", .{ok_count}); + try stderr.print("{d} skipped; ", .{skipped}); + try stderr.print("{d} failed.\n", .{failed}); + } + if (failed != 0) { + std.process.exit(1); + } + } else if (builtin.zig_backend == .stage2_wasm or builtin.zig_backend == .stage2_x86_64) { const passed = builtin.test_functions.len - skipped - failed; diff --git a/src/Sema.zig b/src/Sema.zig index 8e93d2525b..4302221c40 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -10975,8 +10975,7 @@ fn zirCondbr( if (try sema.resolveDefinedValue(parent_block, src, cond)) |cond_val| { const body = if (cond_val.toBool()) then_body else else_body; - _ = try sema.analyzeBody(parent_block, body); - return always_noreturn; + return sema.analyzeBodyInner(parent_block, body); } const gpa = sema.gpa; From 950d840be66deb9239c0effa90ee41a7c0884f95 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 27 Feb 2022 11:48:42 +0200 Subject: [PATCH 2/6] stage2: use stage1 test runner for stage2 --- lib/std/Progress.zig | 10 +++++-- lib/std/os/linux.zig | 2 +- lib/std/special/test_runner.zig | 49 +++++++++++++++++---------------- src/Module.zig | 2 +- src/Sema.zig | 19 +++++++++---- 5 files changed, 50 insertions(+), 32 deletions(-) diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index 07f9077844..5217d723c7 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -269,7 +269,12 @@ fn refreshWithHeldLock(self: *Progress) void { } if (eti > 0) { if (need_ellipse) self.bufWrite(&end, " ", .{}); - self.bufWrite(&end, "[{d}/{d}] ", .{ current_item, eti }); + if (builtin.zig_backend == .stage2_llvm) { + self.bufWrite(&end, "[{d}/ ", .{current_item}); + self.bufWrite(&end, "{d}] ", .{eti}); + } else { + self.bufWrite(&end, "[{d}/{d}] ", .{ current_item, eti }); + } need_ellipse = false; } else if (completed_items != 0) { if (need_ellipse) self.bufWrite(&end, " ", .{}); @@ -284,9 +289,10 @@ fn refreshWithHeldLock(self: *Progress) void { } } - _ = file.write(self.output_buffer[0..end]) catch { + _ = file.write(self.output_buffer[0..end]) catch blk: { // Stop trying to write to this file once it errors. self.terminal = null; + break :blk 0; // TODO stage2 requires this }; if (self.timer) |*timer| { self.prev_refresh_timestamp = timer.read(); diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index d8a8acc208..95f6222e97 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -871,7 +871,7 @@ var vdso_clock_gettime = @ptrCast(?*const anyopaque, init_vdso_clock_gettime); const vdso_clock_gettime_ty = fn (i32, *timespec) callconv(.C) usize; pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { - if (@hasDecl(VDSO, "CGT_SYM")) { + if (@hasDecl(VDSO, "CGT_SYM") and builtin.zig_backend == .stage1) { const ptr = @atomicLoad(?*const anyopaque, &vdso_clock_gettime, .Unordered); if (ptr) |fn_ptr| { const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr); diff --git a/lib/std/special/test_runner.zig b/lib/std/special/test_runner.zig index 6f392e710b..41431eb227 100644 --- a/lib/std/special/test_runner.zig +++ b/lib/std/special/test_runner.zig @@ -23,10 +23,12 @@ fn processArgs() void { } pub fn main() void { - if (builtin.zig_backend != .stage1) { + if (builtin.zig_backend != .stage1 and + builtin.zig_backend != .stage2_llvm) + { return main2() catch @panic("test failure"); } - processArgs(); + if (builtin.zig_backend == .stage1) processArgs(); const test_fn_list = builtin.test_functions; var ok_count: usize = 0; var skip_count: usize = 0; @@ -44,9 +46,9 @@ pub fn main() void { var leaks: usize = 0; for (test_fn_list) |test_fn, i| { - std.testing.allocator_instance = .{}; + if (builtin.zig_backend != .stage2_llvm) std.testing.allocator_instance = .{}; defer { - if (std.testing.allocator_instance.deinit()) { + if (builtin.zig_backend != .stage2_llvm and std.testing.allocator_instance.deinit()) { leaks += 1; } } @@ -56,9 +58,17 @@ pub fn main() void { test_node.activate(); progress.refresh(); if (!have_tty) { - std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name }); + if (builtin.zig_backend == .stage2_llvm) { + std.debug.print("{d}/", .{i + 1}); + std.debug.print("{d} ", .{test_fn_list.len}); + std.debug.print("{s}... ", .{test_fn.name}); + } else { + std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name }); + } } - const result = if (test_fn.async_frame_size) |size| switch (io_mode) { + const result = if (builtin.zig_backend == .stage2_llvm) + test_fn.func() + else if (test_fn.async_frame_size) |size| switch (io_mode) { .evented => blk: { if (async_frame_buffer.len < size) { std.heap.page_allocator.free(async_frame_buffer); @@ -90,9 +100,9 @@ pub fn main() void { fail_count += 1; progress.log("FAIL ({s})\n", .{@errorName(err)}); if (!have_tty) std.debug.print("FAIL ({s})\n", .{@errorName(err)}); - if (@errorReturnTrace()) |trace| { + if (builtin.zig_backend != .stage2_llvm) if (@errorReturnTrace()) |trace| { std.debug.dumpStackTrace(trace.*); - } + }; test_node.end(); }, } @@ -101,7 +111,13 @@ pub fn main() void { if (ok_count == test_fn_list.len) { std.debug.print("All {d} tests passed.\n", .{ok_count}); } else { - std.debug.print("{d} passed; {d} skipped; {d} failed.\n", .{ ok_count, skip_count, fail_count }); + if (builtin.zig_backend == .stage2_llvm) { + std.debug.print("{d} passed; ", .{ok_count}); + std.debug.print("{d} skipped; ", .{skip_count}); + std.debug.print("{d} failed.\n", .{fail_count}); + } else { + std.debug.print("{d} passed; {d} skipped; {d} failed.\n", .{ ok_count, skip_count, fail_count }); + } } if (log_err_count != 0) { std.debug.print("{d} errors were logged.\n", .{log_err_count}); @@ -141,20 +157,7 @@ pub fn main2() anyerror!void { } }; } - if (builtin.zig_backend == .stage2_llvm) { - const stderr = std.io.getStdErr().writer(); - const ok_count = builtin.test_functions.len - skipped - failed; - if (ok_count == builtin.test_functions.len) { - try stderr.print("All {d} tests passed.\n", .{ok_count}); - } else { - try stderr.print("{d} passed; ", .{ok_count}); - try stderr.print("{d} skipped; ", .{skipped}); - try stderr.print("{d} failed.\n", .{failed}); - } - if (failed != 0) { - std.process.exit(1); - } - } else if (builtin.zig_backend == .stage2_wasm or + if (builtin.zig_backend == .stage2_wasm or builtin.zig_backend == .stage2_x86_64) { const passed = builtin.test_functions.len - skipped - failed; diff --git a/src/Module.zig b/src/Module.zig index 048895e5bf..9bc61aa708 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3762,7 +3762,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { // Note this resolves the type of the Decl, not the value; if this Decl // is a struct, for example, this resolves `type` (which needs no resolution), // not the struct itself. - try sema.resolveTypeLayout(&block_scope, src, decl_tv.ty); + try sema.resolveTypeFully(&block_scope, src, decl_tv.ty); const decl_arena_state = try decl_arena_allocator.create(std.heap.ArenaAllocator.State); diff --git a/src/Sema.zig b/src/Sema.zig index 4302221c40..9877696a8a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -11947,19 +11947,27 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I var buffer: Value.ToTypeBuffer = undefined; const child_ty = child_val.toType(&buffer); + const ptr_size = size_val.toEnum(std.builtin.TypeInfo.Pointer.Size); + + var actual_sentinel: ?Value = null; if (!sentinel_val.isNull()) { - return sema.fail(block, src, "TODO: implement zirReify for pointer with non-null sentinel", .{}); + if (ptr_size == .One or ptr_size == .C) { + return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{}); + } + const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data; + const ptr_ty = try Type.ptr(sema.arena, .{ .@"addrspace" = .generic, .pointee_type = child_ty }); + actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?; } const ty = try Type.ptr(sema.arena, .{ - .size = size_val.toEnum(std.builtin.TypeInfo.Pointer.Size), + .size = ptr_size, .mutable = !is_const_val.toBool(), .@"volatile" = is_volatile_val.toBool(), .@"align" = @intCast(u8, alignment_val.toUnsignedInt()), // TODO: Validate this value. .@"addrspace" = address_space_val.toEnum(std.builtin.AddressSpace), .pointee_type = try child_ty.copy(sema.arena), .@"allowzero" = is_allowzero_val.toBool(), - .sentinel = null, + .sentinel = actual_sentinel, }); return sema.addType(ty); }, @@ -12069,6 +12077,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const type_res = try sema.resolveType(block, src, extra.lhs); try sema.checkPtrType(block, type_src, type_res); + _ = try sema.resolveTypeLayout(block, src, type_res.childType()); const ptr_align = type_res.ptrAlignment(sema.mod.getTarget()); if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { @@ -17586,7 +17595,7 @@ fn resolvePeerTypes( return chosen_ty; } -pub fn resolveTypeLayout( +fn resolveTypeLayout( sema: *Sema, block: *Block, src: LazySrcLoc, @@ -17659,7 +17668,7 @@ fn resolveUnionLayout( union_obj.status = .have_layout; } -fn resolveTypeFully( +pub fn resolveTypeFully( sema: *Sema, block: *Block, src: LazySrcLoc, From 1bbca4f9350ffd7ebbfc5c54a307f54d448f5929 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 27 Feb 2022 12:15:49 +0200 Subject: [PATCH 3/6] stage2: fix bitcast to optional ptr in llvm backend; omit safety check for intToPtr on optional ptr --- lib/std/os/linux.zig | 12 +++++++++--- src/codegen/llvm.zig | 2 +- src/type.zig | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 95f6222e97..7232bcfcd2 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -865,13 +865,19 @@ pub fn flock(fd: fd_t, operation: i32) usize { return syscall2(.flock, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, operation))); } -var vdso_clock_gettime = @ptrCast(?*const anyopaque, init_vdso_clock_gettime); +var vdso_clock_gettime = if (builtin.zig_backend == .stage1) + @ptrCast(?*const anyopaque, init_vdso_clock_gettime) +else + @ptrCast(?*const anyopaque, &init_vdso_clock_gettime); // We must follow the C calling convention when we call into the VDSO -const vdso_clock_gettime_ty = fn (i32, *timespec) callconv(.C) usize; +const vdso_clock_gettime_ty = if (builtin.zig_backend == .stage1) + fn (i32, *timespec) callconv(.C) usize +else + *const fn (i32, *timespec) callconv(.C) usize; pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { - if (@hasDecl(VDSO, "CGT_SYM") and builtin.zig_backend == .stage1) { + if (@hasDecl(VDSO, "CGT_SYM")) { const ptr = @atomicLoad(?*const anyopaque, &vdso_clock_gettime, .Unordered); if (ptr) |fn_ptr| { const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index c0642a59de..e349f0186e 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3892,7 +3892,7 @@ pub const FuncGen = struct { return self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), ""); } - if (operand_ty.zigTypeTag() == .Int and inst_ty.zigTypeTag() == .Pointer) { + if (operand_ty.zigTypeTag() == .Int and inst_ty.isPtrAtRuntime()) { return self.builder.buildIntToPtr(operand, llvm_dest_ty, ""); } diff --git a/src/type.zig b/src/type.zig index 68085500bc..a84a0f4520 100644 --- a/src/type.zig +++ b/src/type.zig @@ -2602,7 +2602,7 @@ pub const Type = extern union { const payload = self.castTag(.pointer).?.data; return payload.@"allowzero"; }, - else => false, + else => return self.zigTypeTag() == .Optional, }; } From 813f368a3c44133106584b0d7e30748cff79a776 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 27 Feb 2022 12:25:50 +0200 Subject: [PATCH 4/6] test runner: remove unnecessary stage2 workaround --- lib/std/Progress.zig | 2 +- lib/std/special/test_runner.zig | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index 5217d723c7..9edf39413f 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -270,7 +270,7 @@ fn refreshWithHeldLock(self: *Progress) void { if (eti > 0) { if (need_ellipse) self.bufWrite(&end, " ", .{}); if (builtin.zig_backend == .stage2_llvm) { - self.bufWrite(&end, "[{d}/ ", .{current_item}); + self.bufWrite(&end, "[{d}/", .{current_item}); self.bufWrite(&end, "{d}] ", .{eti}); } else { self.bufWrite(&end, "[{d}/{d}] ", .{ current_item, eti }); diff --git a/lib/std/special/test_runner.zig b/lib/std/special/test_runner.zig index 41431eb227..ae1d2bee1c 100644 --- a/lib/std/special/test_runner.zig +++ b/lib/std/special/test_runner.zig @@ -66,9 +66,7 @@ pub fn main() void { std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name }); } } - const result = if (builtin.zig_backend == .stage2_llvm) - test_fn.func() - else if (test_fn.async_frame_size) |size| switch (io_mode) { + const result = if (test_fn.async_frame_size) |size| switch (io_mode) { .evented => blk: { if (async_frame_buffer.len < size) { std.heap.page_allocator.free(async_frame_buffer); From 7a92b89a9d19f3e6d258c848f1be13a6e31fec97 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 27 Feb 2022 13:32:55 +0200 Subject: [PATCH 5/6] stage2: forward discard result loc to more expressions --- lib/std/Progress.zig | 3 +-- src/AstGen.zig | 9 ++++++++- test/behavior/basic.zig | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index 9edf39413f..efced20f42 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -289,10 +289,9 @@ fn refreshWithHeldLock(self: *Progress) void { } } - _ = file.write(self.output_buffer[0..end]) catch blk: { + _ = file.write(self.output_buffer[0..end]) catch { // Stop trying to write to this file once it errors. self.terminal = null; - break :blk 0; // TODO stage2 requires this }; if (self.timer) |*timer| { self.prev_refresh_timestamp = timer.read(); diff --git a/src/AstGen.zig b/src/AstGen.zig index b9ac0b5c43..e8d612fbc7 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -244,10 +244,14 @@ pub const ResultLoc = union(enum) { fn strategy(rl: ResultLoc, block_scope: *GenZir) Strategy { switch (rl) { // In this branch there will not be any store_to_block_ptr instructions. - .discard, .none, .ty, .coerced_ty, .ref => return .{ + .none, .ty, .coerced_ty, .ref => return .{ .tag = .break_operand, .elide_store_to_block_ptr_instructions = false, }, + .discard => return .{ + .tag = .break_void, + .elide_store_to_block_ptr_instructions = false, + }, // The pointer got passed through to the sub-expressions, so we will use // break_void here. // In this branch there will not be any store_to_block_ptr instructions. @@ -1766,6 +1770,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn // we assume the result location is written, and we break with void. _ = try parent_gz.addBreak(break_tag, block_inst, .void_value); }, + .discard => { + _ = try parent_gz.addBreak(break_tag, block_inst, .void_value); + }, else => { _ = try parent_gz.addBreak(break_tag, block_inst, operand); }, diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index d6447862cf..c36fa0c921 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -819,3 +819,37 @@ test "if expression type coercion" { const x: u16 = if (cond) 1 else 0; try expect(@as(u16, x) == 1); } + +test "discarding the result of various expressions" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + fn foo() !u32 { + return 1; + } + fn bar() ?u32 { + return 1; + } + }; + _ = S.bar() orelse { + // do nothing + }; + _ = S.foo() catch { + // do nothing + }; + _ = switch (1) { + 1 => 1, + 2 => {}, + else => return, + }; + _ = try S.foo(); + _ = if (S.bar()) |some| some else {}; + _ = blk: { + if (S.bar()) |some| break :blk some; + break :blk; + }; + _ = while (S.bar()) |some| break some else {}; + _ = for ("foo") |char| break char else {}; +} From 9f59189c954298fd2be576b7e3dd26388d07751d Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 27 Feb 2022 16:40:59 +0200 Subject: [PATCH 6/6] stage2: do not memoize calls that can mutate comptime state --- lib/std/Progress.zig | 7 +------ lib/std/special/test_runner.zig | 16 ++-------------- src/Sema.zig | 10 ++++++++-- test/behavior.zig | 4 ++-- 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index efced20f42..07f9077844 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -269,12 +269,7 @@ fn refreshWithHeldLock(self: *Progress) void { } if (eti > 0) { if (need_ellipse) self.bufWrite(&end, " ", .{}); - if (builtin.zig_backend == .stage2_llvm) { - self.bufWrite(&end, "[{d}/", .{current_item}); - self.bufWrite(&end, "{d}] ", .{eti}); - } else { - self.bufWrite(&end, "[{d}/{d}] ", .{ current_item, eti }); - } + self.bufWrite(&end, "[{d}/{d}] ", .{ current_item, eti }); need_ellipse = false; } else if (completed_items != 0) { if (need_ellipse) self.bufWrite(&end, " ", .{}); diff --git a/lib/std/special/test_runner.zig b/lib/std/special/test_runner.zig index ae1d2bee1c..91e402e533 100644 --- a/lib/std/special/test_runner.zig +++ b/lib/std/special/test_runner.zig @@ -58,13 +58,7 @@ pub fn main() void { test_node.activate(); progress.refresh(); if (!have_tty) { - if (builtin.zig_backend == .stage2_llvm) { - std.debug.print("{d}/", .{i + 1}); - std.debug.print("{d} ", .{test_fn_list.len}); - std.debug.print("{s}... ", .{test_fn.name}); - } else { - std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name }); - } + std.debug.print("{d}/{d} {s}... ", .{ i + 1, test_fn_list.len, test_fn.name }); } const result = if (test_fn.async_frame_size) |size| switch (io_mode) { .evented => blk: { @@ -109,13 +103,7 @@ pub fn main() void { if (ok_count == test_fn_list.len) { std.debug.print("All {d} tests passed.\n", .{ok_count}); } else { - if (builtin.zig_backend == .stage2_llvm) { - std.debug.print("{d} passed; ", .{ok_count}); - std.debug.print("{d} skipped; ", .{skip_count}); - std.debug.print("{d} failed.\n", .{fail_count}); - } else { - std.debug.print("{d} passed; {d} skipped; {d} failed.\n", .{ ok_count, skip_count, fail_count }); - } + std.debug.print("{d} passed; {d} skipped; {d} failed.\n", .{ ok_count, skip_count, fail_count }); } if (log_err_count != 0) { std.debug.print("{d} errors were logged.\n", .{log_err_count}); diff --git a/src/Sema.zig b/src/Sema.zig index 9877696a8a..7570cbb21b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4494,6 +4494,10 @@ fn analyzeCall( try sema.emitBackwardBranch(&child_block, call_src); + // Whether this call should be memoized, set to false if the call can mutate + // comptime state. + var should_memoize = true; + // This will have return instructions analyzed as break instructions to // the block_inst above. Here we are performing "comptime/inline semantic analysis" // for a function body, which means we must map the parameter ZIR instructions to @@ -4527,6 +4531,7 @@ fn analyzeCall( }, else => {}, } + should_memoize = should_memoize and !arg_val.isComptimeMutablePtr(); memoized_call_key.args[arg_i] = .{ .ty = param_ty, .val = arg_val, @@ -4552,6 +4557,7 @@ fn analyzeCall( }, else => {}, } + should_memoize = should_memoize and !arg_val.isComptimeMutablePtr(); memoized_call_key.args[arg_i] = .{ .ty = sema.typeOf(uncasted_arg), .val = arg_val, @@ -4597,7 +4603,7 @@ fn analyzeCall( // This `res2` is here instead of directly breaking from `res` due to a stage1 // bug generating invalid LLVM IR. const res2: Air.Inst.Ref = res2: { - if (is_comptime_call) { + if (should_memoize and is_comptime_call) { if (mod.memoized_calls.get(memoized_call_key)) |result| { const ty_inst = try sema.addType(fn_ret_ty); try sema.air_values.append(gpa, result.val); @@ -4621,7 +4627,7 @@ fn analyzeCall( break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); }; - if (is_comptime_call) { + if (should_memoize and is_comptime_call) { const result_val = try sema.resolveConstMaybeUndefVal(block, call_src, result); // TODO: check whether any external comptime memory was mutated by the diff --git a/test/behavior.zig b/test/behavior.zig index 76a7c55977..ea861d75cd 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -125,6 +125,7 @@ test { _ = @import("behavior/widening.zig"); _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/726.zig"); + _ = @import("behavior/bugs/828.zig"); _ = @import("behavior/bugs/1421.zig"); _ = @import("behavior/bugs/1442.zig"); _ = @import("behavior/bugs/1607.zig"); @@ -132,6 +133,7 @@ test { _ = @import("behavior/bugs/3384.zig"); _ = @import("behavior/bugs/3742.zig"); _ = @import("behavior/bugs/5398.zig"); + _ = @import("behavior/bugs/5413.zig"); _ = @import("behavior/bugs/5487.zig"); _ = @import("behavior/struct_contains_null_ptr_itself.zig"); _ = @import("behavior/switch_prong_err_enum.zig"); @@ -148,12 +150,10 @@ test { _ = @import("behavior/await_struct.zig"); _ = @import("behavior/bugs/529.zig"); _ = @import("behavior/bugs/718.zig"); - _ = @import("behavior/bugs/828.zig"); _ = @import("behavior/bugs/920.zig"); _ = @import("behavior/bugs/1120.zig"); _ = @import("behavior/bugs/1851.zig"); _ = @import("behavior/bugs/3779.zig"); - _ = @import("behavior/bugs/5413.zig"); _ = @import("behavior/bugs/6456.zig"); _ = @import("behavior/bugs/6781.zig"); _ = @import("behavior/bugs/7003.zig");