authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-23 21:46:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:36-07:00
logc0504a8fa87f66c5ddb2c02c35c10c945f4bb8b9
tree8a2c0bddff77844f915369c81eb7faafca80b0cf
parent1c8d50e0624c7099e82a35c78b135c59e2dbeaa3

fuzzer: get it working again


5 files changed, 146 insertions(+), 75 deletions(-)

lib/compiler/Maker.zig+2
...@@ -317,6 +317,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -317,6 +317,7 @@ pub fn main(init: process.Init.Minimal) !void {
317 if (webui_listen == null) webui_listen = .{ .ip6 = .loopback(0) };317 if (webui_listen == null) webui_listen = .{ .ip6 = .loopback(0) };
318 } else if (mem.eql(u8, arg, "--fuzz")) {318 } else if (mem.eql(u8, arg, "--fuzz")) {
319 fuzz = .{ .forever = undefined };319 fuzz = .{ .forever = undefined };
320 graph.fuzzing = true;
320 if (webui_listen == null) webui_listen = .{ .ip6 = .loopback(0) };321 if (webui_listen == null) webui_listen = .{ .ip6 = .loopback(0) };
321 } else if (mem.startsWith(u8, arg, "--fuzz=")) {322 } else if (mem.startsWith(u8, arg, "--fuzz=")) {
322 const value = arg["--fuzz=".len..];323 const value = arg["--fuzz=".len..];
...@@ -352,6 +353,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -352,6 +353,7 @@ pub fn main(init: process.Init.Minimal) !void {
352 .amount = normalized_amount,353 .amount = normalized_amount,
353 },354 },
354 };355 };
356 graph.fuzzing = true;
355 } else if (mem.eql(u8, arg, "-fincremental")) {357 } else if (mem.eql(u8, arg, "-fincremental")) {
356 graph.incremental = true;358 graph.incremental = true;
357 } else if (mem.eql(u8, arg, "-fno-incremental")) {359 } else if (mem.eql(u8, arg, "-fno-incremental")) {
lib/compiler/Maker/Fuzz.zig+123-64
...@@ -83,6 +83,7 @@ pub fn init(...@@ -83,6 +83,7 @@ pub fn init(
83 const graph = maker.graph;83 const graph = maker.graph;
84 const gpa = graph.cache.gpa;84 const gpa = graph.cache.gpa;
85 const io = graph.io;85 const io = graph.io;
86 const conf = &maker.scanned_config.configuration;
8687
87 const run_steps: []const Configuration.Step.Index = steps: {88 const run_steps: []const Configuration.Step.Index = steps: {
88 var steps: std.ArrayList(Configuration.Step.Index) = .empty;89 var steps: std.ArrayList(Configuration.Step.Index) = .empty;
...@@ -92,13 +93,13 @@ pub fn init(...@@ -92,13 +93,13 @@ pub fn init(
92 var rebuild_group: Io.Group = .init;93 var rebuild_group: Io.Group = .init;
93 defer rebuild_group.cancel(io);94 defer rebuild_group.cancel(io);
9495
95 for (all_steps) |step| {96 for (all_steps) |step_index| {
96 if (true) @panic("TODO update the fuzzer");97 const conf_run = step_index.ptr(conf).extended.cast(conf, Configuration.Step.Run) orelse continue;
97 const run = step.cast(std.Build.Step.Run) orelse continue;98 if (conf_run.producer.value == null) continue;
98 if (run.producer == null) continue;99 const run = &maker.stepByIndex(step_index).extended.run;
99 if (run.fuzz_tests.items.len == 0) continue;100 if (run.fuzz_tests.items.len == 0) continue;
100 try steps.append(gpa, run);101 try steps.append(gpa, step_index);
101 rebuild_group.async(io, rebuildTestsWorkerRun, .{ run, gpa, rebuild_node });102 rebuild_group.async(io, rebuildTestsWorkerRun, .{ maker, step_index, rebuild_node });
102 }103 }
103104
104 if (steps.items.len == 0) fatal("no fuzz tests found", .{});105 if (steps.items.len == 0) fatal("no fuzz tests found", .{});
...@@ -109,10 +110,10 @@ pub fn init(...@@ -109,10 +110,10 @@ pub fn init(
109 };110 };
110 errdefer gpa.free(run_steps);111 errdefer gpa.free(run_steps);
111112
112 for (run_steps) |run_step_index| {113 for (run_steps) |run_index| {
113 if (true) @panic("TODO update the fuzzer");114 const run = &maker.stepByIndex(run_index).extended.run;
114 assert(run_step_index.fuzz_tests.items.len > 0);115 assert(run.fuzz_tests.items.len > 0);
115 if (run_step_index.rebuilt_executable == null)116 if (run.rebuilt_executable == null)
116 fatal("one or more unit tests failed to be rebuilt in fuzz mode", .{});117 fatal("one or more unit tests failed to be rebuilt in fuzz mode", .{});
117 }118 }
118119
...@@ -144,11 +145,10 @@ pub fn start(fuzz: *Fuzz) void {...@@ -144,11 +145,10 @@ pub fn start(fuzz: *Fuzz) void {
144 fatal("unable to spawn coverage task: {t}", .{err});145 fatal("unable to spawn coverage task: {t}", .{err});
145 }146 }
146147
147 if (true) @panic("TODO update the fuzzer");148 for (fuzz.run_steps) |run_index| {
148149 const run = &maker.stepByIndex(run_index).extended.run;
149 for (fuzz.run_steps) |run| {
150 assert(run.rebuilt_executable != null);150 assert(run.rebuilt_executable != null);
151 fuzz.group.async(io, fuzzWorkerRun, .{ fuzz, run });151 fuzz.group.async(io, fuzzWorkerRun, .{ fuzz, run_index });
152 }152 }
153}153}
154154
...@@ -163,67 +163,111 @@ pub fn deinit(fuzz: *Fuzz) void {...@@ -163,67 +163,111 @@ pub fn deinit(fuzz: *Fuzz) void {
163 gpa.free(fuzz.run_steps);163 gpa.free(fuzz.run_steps);
164}164}
165165
166fn rebuildTestsWorkerRun(run: Configuration.Step.Index, gpa: Allocator, parent_prog_node: std.Progress.Node) void {166fn rebuildTestsWorkerRun(
167 rebuildTestsWorkerRunFallible(run, gpa, parent_prog_node) catch |err| {167 maker: *Maker,
168 const compile = run.producer.?;168 run_index: Configuration.Step.Index,
169 log.err("step '{s}': failed to rebuild in fuzz mode: {t}", .{ compile.step.name, err });169 parent_prog_node: std.Progress.Node,
170) void {
171 rebuildTestsWorkerRunFallible(maker, run_index, parent_prog_node) catch |err| {
172 const conf = &maker.scanned_config.configuration;
173 const conf_run = run_index.ptr(conf).extended.cast(conf, Configuration.Step.Run).?;
174 const comp_index = conf_run.producer.value.?;
175 const step_name = comp_index.ptr(conf).name.slice(conf);
176 log.err("step {s}: failed to rebuild in fuzz mode: {t}", .{ step_name, err });
170 };177 };
171}178}
172179
173fn rebuildTestsWorkerRunFallible(run: Configuration.Step.Index, gpa: Allocator, parent_prog_node: std.Progress.Node) !void {180fn rebuildTestsWorkerRunFallible(
174 const graph = run.step.owner.graph;181 maker: *Maker,
182 run_index: Configuration.Step.Index,
183 parent_prog_node: std.Progress.Node,
184) !void {
185 const graph = maker.graph;
175 const io = graph.io;186 const io = graph.io;
176 const compile = run.producer.?;187 const gpa = maker.gpa;
177 const prog_node = parent_prog_node.start(compile.step.name, 0);188 const conf = &maker.scanned_config.configuration;
189 const run = &maker.stepByIndex(run_index).extended.run;
190 const conf_run = run_index.ptr(conf).extended.cast(conf, Configuration.Step.Run).?;
191 const comp_index = conf_run.producer.value.?;
192 const comp_step = maker.stepByIndex(comp_index);
193 const comp = &comp_step.extended.compile;
194 const conf_comp_step = comp_index.ptr(conf);
195 const conf_comp = conf_comp_step.extended.cast(conf, Configuration.Step.Compile).?;
196 const root_module = conf_comp.root_module.get(conf);
197 const target = root_module.resolved_target.get(conf).?.result.get(conf);
198
199 const prog_node = parent_prog_node.start(conf_comp_step.name.slice(conf), 0);
178 defer prog_node.end();200 defer prog_node.end();
179201
180 const result = compile.rebuildInFuzzMode(gpa, prog_node);202 const result = comp.rebuildInFuzzMode(maker, comp_index, prog_node);
181203
182 const show_compile_errors = compile.step.result_error_bundle.errorMessageCount() > 0;204 const show_compile_errors = comp_step.result_error_bundle.errorMessageCount() > 0;
183 const show_error_msgs = compile.step.result_error_msgs.items.len > 0;205 const show_error_msgs = comp_step.result_error_msgs.items.len > 0;
184 const show_stderr = compile.step.result_stderr.len > 0;206 const show_stderr = comp_step.result_stderr.len > 0;
185207
186 if (show_error_msgs or show_compile_errors or show_stderr) {208 if (show_error_msgs or show_compile_errors or show_stderr) {
187 var buf: [256]u8 = undefined;209 var buf: [256]u8 = undefined;
188 const stderr = try io.lockStderr(&buf, graph.stderr_mode);210 const stderr = try io.lockStderr(&buf, graph.stderr_mode);
189 defer io.unlockStderr();211 defer io.unlockStderr();
190 Maker.printErrorMessages(gpa, &compile.step, .{}, stderr.terminal(), .verbose, .indent) catch {};212 maker.printErrorMessages(comp_index, .{}, stderr.terminal(), .verbose, .indent) catch {};
191 }213 }
192214
193 const rebuilt_bin_path = result catch |err| switch (err) {215 const rebuilt_bin_path = result catch |err| switch (err) {
194 error.MakeFailed => return,216 error.MakeFailed => return,
195 else => |other| return other,217 else => |other| return other,
196 };218 };
197 run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile.out_filename);219 const compile_filename = try std.zig.binNameAlloc(gpa, .{
220 .root_name = conf_comp.root_name.slice(conf),
221 .cpu_arch = target.flags.cpu_arch.unwrap().?,
222 .os_tag = target.flags.os_tag.unwrap().?,
223 .ofmt = target.flags.object_format.unwrap().?,
224 .abi = target.flags.abi.unwrap().?,
225 .output_mode = switch (conf_comp.flags3.kind) {
226 .lib => .Lib,
227 .obj, .test_obj => .Obj,
228 .exe, .@"test" => .Exe,
229 },
230 .link_mode = conf_comp.flags2.linkage.unwrap(),
231 .version = if (conf_comp.version.value) |v|
232 std.SemanticVersion.parse(v.slice(conf)) catch unreachable
233 else
234 null,
235 });
236 defer gpa.free(compile_filename);
237
238 run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile_filename);
198}239}
199240
200fn fuzzWorkerRun(fuzz: *Fuzz, run: Configuration.Step.Index) void {241fn fuzzWorkerRun(fuzz: *Fuzz, run_index: Configuration.Step.Index) void {
201 const owner = run.step.owner;242 const maker = fuzz.maker;
202 const gpa = owner.allocator;243 const graph = maker.graph;
203 const graph = owner.graph;
204 const io = graph.io;244 const io = graph.io;
245 const conf = &maker.scanned_config.configuration;
246 const run = &maker.stepByIndex(run_index).extended.run;
205247
206 run.rerunInFuzzMode(run, fuzz, fuzz.prog_node) catch |err| switch (err) {248 run.rerunInFuzzMode(run_index, fuzz, fuzz.prog_node) catch |err| switch (err) {
207 error.MakeFailed => {249 error.MakeFailed => {
208 var buf: [256]u8 = undefined;250 var buf: [256]u8 = undefined;
209 const stderr = io.lockStderr(&buf, graph.stderr_mode) catch |e| switch (e) {251 const stderr = io.lockStderr(&buf, graph.stderr_mode) catch |e| switch (e) {
210 error.Canceled => return,252 error.Canceled => return,
211 };253 };
212 defer io.unlockStderr();254 defer io.unlockStderr();
213 Maker.printErrorMessages(gpa, &run.step, .{}, stderr.terminal(), .verbose, .indent) catch {};255 maker.printErrorMessages(run_index, .{}, stderr.terminal(), .verbose, .indent) catch {};
214 return;256 return;
215 },257 },
216 else => {258 else => {
217 log.err("step '{s}': failed to rerun in fuzz mode: {t}", .{ run.step.name, err });259 const step_name = run_index.ptr(conf).name.slice(conf);
260 log.err("step {s}: failed to rerun in fuzz mode: {t}", .{ step_name, err });
218 return;261 return;
219 },262 },
220 };263 };
221}264}
222265
223pub fn serveSourcesTar(fuzz: *Fuzz, req: *std.http.Server.Request) !void {266pub fn serveSourcesTar(fuzz: *Fuzz, req: *std.http.Server.Request) !void {
224 if (true) @panic("TODO update the fuzzer");
225 assert(fuzz.mode == .forever);267 assert(fuzz.mode == .forever);
226 const gpa = fuzz.maker.gpa;268 const maker = fuzz.maker;
269 const gpa = maker.gpa;
270 const conf = &maker.scanned_config.configuration;
227271
228 var arena_state: std.heap.ArenaAllocator = .init(gpa);272 var arena_state: std.heap.ArenaAllocator = .init(gpa);
229 defer arena_state.deinit();273 defer arena_state.deinit();
...@@ -233,8 +277,11 @@ pub fn serveSourcesTar(fuzz: *Fuzz, req: *std.http.Server.Request) !void {...@@ -233,8 +277,11 @@ pub fn serveSourcesTar(fuzz: *Fuzz, req: *std.http.Server.Request) !void {
233 var dedup_table: DedupTable = .empty;277 var dedup_table: DedupTable = .empty;
234 defer dedup_table.deinit(gpa);278 defer dedup_table.deinit(gpa);
235279
236 for (fuzz.run_steps) |run_step| {280 for (fuzz.run_steps) |run_index| {
237 const compile_inputs = run_step.producer.?.step.inputs.table;281 const conf_run = run_index.ptr(conf).extended.cast(conf, Configuration.Step.Run) orelse continue;
282 const comp_index = conf_run.producer.value.?;
283 const comp_step = maker.stepByIndex(comp_index);
284 const compile_inputs = comp_step.inputs.table;
238 for (compile_inputs.keys(), compile_inputs.values()) |dir_path, *file_list| {285 for (compile_inputs.keys(), compile_inputs.values()) |dir_path, *file_list| {
239 try dedup_table.ensureUnusedCapacity(gpa, file_list.items.len);286 try dedup_table.ensureUnusedCapacity(gpa, file_list.items.len);
240 for (file_list.items) |sub_path| {287 for (file_list.items) |sub_path| {
...@@ -372,14 +419,15 @@ fn coverageRunCancelable(fuzz: *Fuzz) Io.Cancelable!void {...@@ -372,14 +419,15 @@ fn coverageRunCancelable(fuzz: *Fuzz) Io.Cancelable!void {
372 fuzz.msg_queue.clearRetainingCapacity();419 fuzz.msg_queue.clearRetainingCapacity();
373 }420 }
374}421}
375fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage_id: u64) error{ OutOfMemory, AlreadyReported, Canceled }!void {422fn prepareTables(fuzz: *Fuzz, run_index: Configuration.Step.Index, coverage_id: u64) error{ OutOfMemory, AlreadyReported, Canceled }!void {
376 if (true) @panic("TODO update the fuzzer");
377 assert(fuzz.mode == .forever);423 assert(fuzz.mode == .forever);
378 const ws = fuzz.mode.forever.ws;424 const ws = fuzz.mode.forever.ws;
379 const maker = fuzz.maker;425 const maker = fuzz.maker;
380 const graph = maker.graph;426 const graph = maker.graph;
381 const io = graph.io;427 const io = graph.io;
382 const gpa = maker.gpa;428 const gpa = maker.gpa;
429 const conf = &maker.scanned_config.configuration;
430 const cache_root = graph.local_cache_root;
383431
384 try fuzz.coverage_mutex.lock(io);432 try fuzz.coverage_mutex.lock(io);
385 defer fuzz.coverage_mutex.unlock(io);433 defer fuzz.coverage_mutex.unlock(io);
...@@ -405,37 +453,45 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage...@@ -405,37 +453,45 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage
405 };453 };
406 errdefer gop.value_ptr.coverage.deinit(gpa);454 errdefer gop.value_ptr.coverage.deinit(gpa);
407455
408 const rebuilt_exe_path = run_step_index.rebuilt_executable.?;456 const run_step = maker.stepByIndex(run_index);
409 const target = run_step_index.producer.?.rootModuleTarget();457 const conf_run_step = run_index.ptr(conf);
458 const conf_run = conf_run_step.extended.cast(conf, Configuration.Step.Run).?;
459 const comp_index = conf_run.producer.value.?;
460 const conf_comp_step = comp_index.ptr(conf);
461 const conf_comp = conf_comp_step.extended.cast(conf, Configuration.Step.Compile).?;
462 const rebuilt_exe_path = run_step.extended.run.rebuilt_executable.?;
463 const root_module = conf_comp.root_module.get(conf);
464 const target = root_module.resolved_target.get(conf).?.result.get(conf);
465
410 var debug_info = std.debug.Info.load(466 var debug_info = std.debug.Info.load(
411 gpa,467 gpa,
412 io,468 io,
413 rebuilt_exe_path,469 rebuilt_exe_path,
414 &gop.value_ptr.coverage,470 &gop.value_ptr.coverage,
415 target.ofmt,471 target.flags.object_format.unwrap().?,
416 target.cpu.arch,472 target.flags.cpu_arch.unwrap().?,
417 ) catch |err| {473 ) catch |err| {
418 log.err("step '{s}': failed to load debug information for '{f}': {t}", .{474 log.err("step {s}: failed to load debug information for {f}: {t}", .{
419 run_step_index.step.name, rebuilt_exe_path, err,475 conf_run_step.name.slice(conf), rebuilt_exe_path, err,
420 });476 });
421 return error.AlreadyReported;477 return error.AlreadyReported;
422 };478 };
423 defer debug_info.deinit(gpa);479 defer debug_info.deinit(gpa);
424480
425 const coverage_file_path: Build.Cache.Path = .{481 const coverage_file_path: Build.Cache.Path = .{
426 .root_dir = run_step_index.step.owner.cache_root,482 .root_dir = cache_root,
427 .sub_path = "v/" ++ std.fmt.hex(coverage_id),483 .sub_path = "v/" ++ std.fmt.hex(coverage_id),
428 };484 };
429 var coverage_file = coverage_file_path.root_dir.handle.openFile(io, coverage_file_path.sub_path, .{}) catch |err| {485 var coverage_file = coverage_file_path.root_dir.handle.openFile(io, coverage_file_path.sub_path, .{}) catch |err| {
430 log.err("step '{s}': failed to load coverage file '{f}': {t}", .{486 log.err("step {s}: failed to load coverage file {f}: {t}", .{
431 run_step_index.step.name, coverage_file_path, err,487 conf_run_step.name.slice(conf), coverage_file_path, err,
432 });488 });
433 return error.AlreadyReported;489 return error.AlreadyReported;
434 };490 };
435 defer coverage_file.close(io);491 defer coverage_file.close(io);
436492
437 const file_size = coverage_file.length(io) catch |err| {493 const file_size = coverage_file.length(io) catch |err| {
438 log.err("unable to check len of coverage file '{f}': {t}", .{ coverage_file_path, err });494 log.err("unable to check len of coverage file {f}: {t}", .{ coverage_file_path, err });
439 return error.AlreadyReported;495 return error.AlreadyReported;
440 };496 };
441497
...@@ -447,7 +503,7 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage...@@ -447,7 +503,7 @@ fn prepareTables(fuzz: *Fuzz, run_step_index: Configuration.Step.Index, coverage
447 coverage_file.handle,503 coverage_file.handle,
448 0,504 0,
449 ) catch |err| {505 ) catch |err| {
450 log.err("failed to map coverage file '{f}': {t}", .{ coverage_file_path, err });506 log.err("failed to map coverage file {f}: {t}", .{ coverage_file_path, err });
451 return error.AlreadyReported;507 return error.AlreadyReported;
452 };508 };
453 gop.value_ptr.mapped_memory = mapped_memory;509 gop.value_ptr.mapped_memory = mapped_memory;
...@@ -538,11 +594,12 @@ fn addEntryPoint(fuzz: *Fuzz, coverage_id: u64, addr: u64) error{ AlreadyReporte...@@ -538,11 +594,12 @@ fn addEntryPoint(fuzz: *Fuzz, coverage_id: u64, addr: u64) error{ AlreadyReporte
538}594}
539595
540pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {596pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {
541 if (true) @panic("TODO update the fuzzer");
542 assert(fuzz.mode == .limit);597 assert(fuzz.mode == .limit);
543 const maker = fuzz.maker;598 const maker = fuzz.maker;
544 const graph = maker.graph;599 const graph = maker.graph;
545 const io = graph.io;600 const io = graph.io;
601 const cache_root = graph.local_cache_root;
602 const conf = &maker.scanned_config.configuration;
546603
547 try fuzz.group.await(io);604 try fuzz.group.await(io);
548 fuzz.group = .init;605 fuzz.group = .init;
...@@ -552,13 +609,15 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {...@@ -552,13 +609,15 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {
552 if (msg != .coverage) continue;609 if (msg != .coverage) continue;
553610
554 const cov = msg.coverage;611 const cov = msg.coverage;
612 const run_step_name = cov.run.ptr(conf).name.slice(conf);
613 const run = &maker.stepByIndex(cov.run).extended.run;
555 const coverage_file_path: std.Build.Cache.Path = .{614 const coverage_file_path: std.Build.Cache.Path = .{
556 .root_dir = cov.run.step.owner.cache_root,615 .root_dir = cache_root,
557 .sub_path = "v/" ++ std.fmt.hex(cov.id),616 .sub_path = "v/" ++ std.fmt.hex(cov.id),
558 };617 };
559 var coverage_file = coverage_file_path.root_dir.handle.openFile(io, coverage_file_path.sub_path, .{}) catch |err| {618 var coverage_file = coverage_file_path.root_dir.handle.openFile(io, coverage_file_path.sub_path, .{}) catch |err| {
560 fatal("step '{s}': failed to load coverage file '{f}': {t}", .{619 fatal("step {s}: failed to load coverage file {f}: {t}", .{
561 cov.run.step.name, coverage_file_path, err,620 run_step_name, coverage_file_path, err,
562 });621 });
563 };622 };
564 defer coverage_file.close(io);623 defer coverage_file.close(io);
...@@ -569,14 +628,14 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {...@@ -569,14 +628,14 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {
569628
570 var header: fuzz_abi.SeenPcsHeader = undefined;629 var header: fuzz_abi.SeenPcsHeader = undefined;
571 r.interface.readSliceAll(std.mem.asBytes(&header)) catch |err| {630 r.interface.readSliceAll(std.mem.asBytes(&header)) catch |err| {
572 fatal("step '{s}': failed to read from coverage file '{f}': {t}", .{631 fatal("step {s}: failed to read from coverage file {f}: {t}", .{
573 cov.run.step.name, coverage_file_path, err,632 run_step_name, coverage_file_path, err,
574 });633 });
575 };634 };
576635
577 if (header.pcs_len == 0) {636 if (header.pcs_len == 0) {
578 fatal("step '{s}': corrupted coverage file '{f}': pcs_len was zero", .{637 fatal("step {s}: corrupted coverage file {f}: pcs_len was zero", .{
579 cov.run.step.name, coverage_file_path,638 run_step_name, coverage_file_path,
580 });639 });
581 }640 }
582641
...@@ -584,8 +643,8 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {...@@ -584,8 +643,8 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {
584 const chunk_count = fuzz_abi.SeenPcsHeader.seenElemsLen(header.pcs_len);643 const chunk_count = fuzz_abi.SeenPcsHeader.seenElemsLen(header.pcs_len);
585 for (0..chunk_count) |_| {644 for (0..chunk_count) |_| {
586 const seen = r.interface.takeInt(usize, .little) catch |err| {645 const seen = r.interface.takeInt(usize, .little) catch |err| {
587 fatal("step '{s}': failed to read from coverage file '{f}': {t}", .{646 fatal("step {s}: failed to read from coverage file {f}: {t}", .{
588 cov.run.step.name, coverage_file_path, err,647 run_step_name, coverage_file_path, err,
589 });648 });
590 };649 };
591 seen_count += @popCount(seen);650 seen_count += @popCount(seen);
...@@ -602,8 +661,8 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {...@@ -602,8 +661,8 @@ pub fn waitAndPrintReport(fuzz: *Fuzz) Io.Cancelable!void {
602 \\Coverage: {}/{} -> {}/{} ({:.02}%)661 \\Coverage: {}/{} -> {}/{} ({:.02}%)
603 \\662 \\
604 , .{663 , .{
605 cov.run.step.name,664 run_step_name,
606 cov.run.fuzz_tests.items[0],665 run.fuzz_tests.items[0],
607 cov.id,666 cov.id,
608 cov.cumulative.runs,667 cov.cumulative.runs,
609 header.n_runs,668 header.n_runs,
lib/compiler/Maker/Graph.zig+1
...@@ -31,6 +31,7 @@ reference_trace: ?u32 = null,...@@ -31,6 +31,7 @@ reference_trace: ?u32 = null,
31debug_log_scopes: std.ArrayList([]const u8) = .empty,31debug_log_scopes: std.ArrayList([]const u8) = .empty,
32debug_compile_errors: bool = false,32debug_compile_errors: bool = false,
33debug_incremental: bool = false,33debug_incremental: bool = false,
34fuzzing: bool = false,
34verbose: bool = false,35verbose: bool = false,
35verbose_air: bool = false,36verbose_air: bool = false,
36verbose_cc: bool = false,37verbose_cc: bool = false,
lib/compiler/Maker/Step/Compile.zig+6-9
...@@ -947,11 +947,11 @@ fn lowerZigArgs(...@@ -947,11 +947,11 @@ fn lowerZigArgs(
947pub fn rebuildInFuzzMode(947pub fn rebuildInFuzzMode(
948 compile: *Compile,948 compile: *Compile,
949 maker: *Maker,949 maker: *Maker,
950 step_index: Configuration.Step.Index,950 compile_index: Configuration.Step.Index,
951 progress_node: std.Progress.Node,951 progress_node: std.Progress.Node,
952) !Path {952) !Path {
953 const gpa = maker.graph.gpa;953 const gpa = maker.gpa;
954 const step = maker.stepByIndex(step_index);954 const step = maker.stepByIndex(compile_index);
955955
956 step.result_error_msgs.clearRetainingCapacity();956 step.result_error_msgs.clearRetainingCapacity();
957 step.result_stderr = "";957 step.result_stderr = "";
...@@ -966,8 +966,8 @@ pub fn rebuildInFuzzMode(...@@ -966,8 +966,8 @@ pub fn rebuildInFuzzMode(
966966
967 const zig_args = &compile.zig_args;967 const zig_args = &compile.zig_args;
968 zig_args.clearRetainingCapacity();968 zig_args.clearRetainingCapacity();
969 try lowerZigArgs(compile, maker, progress_node, zig_args, true);969 try lowerZigArgs(compile, compile_index, maker, progress_node, zig_args, true);
970 const maybe_output_bin_path = try step.evalZigProcess(zig_args.items, progress_node, false, maker);970 const maybe_output_bin_path = try Step.evalZigProcess(compile_index, maker, zig_args.items, progress_node, false);
971 return maybe_output_bin_path.?;971 return maybe_output_bin_path.?;
972}972}
973973
...@@ -980,10 +980,7 @@ fn addFlag(gpa: Allocator, args: *std.ArrayList([]const u8), comptime name: []co...@@ -980,10 +980,7 @@ fn addFlag(gpa: Allocator, args: *std.ArrayList([]const u8), comptime name: []co
980 try args.append(gpa, if (cond) "-f" ++ name else "-fno-" ++ name);980 try args.append(gpa, if (cond) "-f" ++ name else "-fno-" ++ name);
981}981}
982982
983fn checkCompileErrors(983fn checkCompileErrors(maker: *Maker, step_index: Configuration.Step.Index) Step.ExtendedMakeError!void {
984 maker: *Maker,
985 step_index: Configuration.Step.Index,
986) Step.ExtendedMakeError!void {
987 const step = maker.stepByIndex(step_index);984 const step = maker.stepByIndex(step_index);
988 const graph = maker.graph;985 const graph = maker.graph;
989 const arena = graph.arena; // TODO don't leak into the process arena986 const arena = graph.arena; // TODO don't leak into the process arena
lib/compiler/Maker/Step/Run.zig+14-2
...@@ -67,6 +67,7 @@ pub fn make(...@@ -67,6 +67,7 @@ pub fn make(
67 }67 }
68 }68 }
6969
70 man.hash.add(graph.fuzzing);
70 man.hash.add(conf_run.flags.color);71 man.hash.add(conf_run.flags.color);
71 man.hash.add(conf_run.flags.disable_zig_progress);72 man.hash.add(conf_run.flags.disable_zig_progress);
7273
...@@ -234,7 +235,8 @@ pub fn make(...@@ -234,7 +235,8 @@ pub fn make(
234 }235 }
235236
236 // Whether the Run step has side effects *other than* updating the output arguments.237 // Whether the Run step has side effects *other than* updating the output arguments.
237 const has_side_effects = conf_run.flags.has_side_effects or any_cli_positionals or238 // When fuzzing we need to always run the test runner to populate fuzz_tests.
239 const has_side_effects = graph.fuzzing or conf_run.flags.has_side_effects or any_cli_positionals or
238 switch (conf_run.flags.stdio) {240 switch (conf_run.flags.stdio) {
239 .infer_from_args => !any_output_args and241 .infer_from_args => !any_output_args and
240 conf_run.captured_stdout.value == null and242 conf_run.captured_stdout.value == null and
...@@ -1511,7 +1513,7 @@ const IndexedOutput = struct {...@@ -1511,7 +1513,7 @@ const IndexedOutput = struct {
1511pub fn rerunInFuzzMode(1513pub fn rerunInFuzzMode(
1512 run: *Run,1514 run: *Run,
1513 run_index: Configuration.Step.Index,1515 run_index: Configuration.Step.Index,
1514 fuzz: *std.Build.Fuzz,1516 fuzz: *Fuzz,
1515 prog_node: std.Progress.Node,1517 prog_node: std.Progress.Node,
1516) !void {1518) !void {
1517 const maker = fuzz.maker;1519 const maker = fuzz.maker;
...@@ -1524,6 +1526,7 @@ pub fn rerunInFuzzMode(...@@ -1524,6 +1526,7 @@ pub fn rerunInFuzzMode(
1524 const conf_step = run_index.ptr(conf);1526 const conf_step = run_index.ptr(conf);
1525 const conf_run = conf_step.extended.get(conf.extra).run;1527 const conf_run = conf_step.extended.get(conf.extra).run;
1526 const argv_list = &run.argv;1528 const argv_list = &run.argv;
1529 const cache_root = graph.local_cache_root;
15271530
1528 argv_list.clearRetainingCapacity();1531 argv_list.clearRetainingCapacity();
15291532
...@@ -1599,6 +1602,15 @@ pub fn rerunInFuzzMode(...@@ -1599,6 +1602,15 @@ pub fn rerunInFuzzMode(
1599 }1602 }
1600 }1603 }
16011604
1605 if (conf_run.flags.test_runner_mode) {
1606 const cache_dir_string = try convertPathArg(run_index, maker, .{ .root_dir = cache_root });
1607
1608 try argv_list.ensureUnusedCapacity(gpa, 3);
1609 argv_list.appendAssumeCapacity(try allocPrint(arena, "--cache-dir={s}", .{cache_dir_string}));
1610 argv_list.appendAssumeCapacity(try allocPrint(arena, "--seed=0x{x}", .{graph.random_seed}));
1611 argv_list.appendAssumeCapacity("--listen=-");
1612 }
1613
1602 if (step.result_failed_command) |cmd| {1614 if (step.result_failed_command) |cmd| {
1603 gpa.free(cmd);1615 gpa.free(cmd);
1604 step.result_failed_command = null;1616 step.result_failed_command = null;