Skip to content

Commit 23c8175

Browse files
authored
Merge pull request #23836 from mlugg/incr-fixes
Incremental fixes, refactor `Zcu.File`
2 parents f2077f5 + 37a9a4e commit 23c8175

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2796
-2394
lines changed

build.zig

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -508,18 +508,19 @@ pub fn build(b: *std.Build) !void {
508508
test_step.dependOn(unit_tests_step);
509509

510510
const unit_tests = b.addTest(.{
511-
.root_module = b.createModule(.{
512-
.root_source_file = b.path("src/main.zig"),
511+
.root_module = addCompilerMod(b, .{
513512
.optimize = optimize,
514513
.target = target,
515-
.link_libc = link_libc,
516514
.single_threaded = single_threaded,
517515
}),
518516
.filters = test_filters,
519517
.use_llvm = use_llvm,
520518
.use_lld = use_llvm,
521519
.zig_lib_dir = b.path("lib"),
522520
});
521+
if (link_libc) {
522+
unit_tests.root_module.link_libc = true;
523+
}
523524
unit_tests.root_module.addOptions("build_options", exe_options);
524525
unit_tests_step.dependOn(&b.addRunArtifact(unit_tests).step);
525526

@@ -650,7 +651,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
650651
update_zig1_step.dependOn(&copy_zig_h.step);
651652
}
652653

653-
const AddCompilerStepOptions = struct {
654+
const AddCompilerModOptions = struct {
654655
optimize: std.builtin.OptimizeMode,
655656
target: std.Build.ResolvedTarget,
656657
strip: ?bool = null,
@@ -659,7 +660,7 @@ const AddCompilerStepOptions = struct {
659660
single_threaded: ?bool = null,
660661
};
661662

662-
fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.Step.Compile {
663+
fn addCompilerMod(b: *std.Build, options: AddCompilerModOptions) *std.Build.Module {
663664
const compiler_mod = b.createModule(.{
664665
.root_source_file = b.path("src/main.zig"),
665666
.target = options.target,
@@ -682,10 +683,14 @@ fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.St
682683
compiler_mod.addImport("aro", aro_mod);
683684
compiler_mod.addImport("aro_translate_c", aro_translate_c_mod);
684685

686+
return compiler_mod;
687+
}
688+
689+
fn addCompilerStep(b: *std.Build, options: AddCompilerModOptions) *std.Build.Step.Compile {
685690
const exe = b.addExecutable(.{
686691
.name = "zig",
687692
.max_rss = 7_800_000_000,
688-
.root_module = compiler_mod,
693+
.root_module = addCompilerMod(b, options),
689694
});
690695
exe.stack_size = stack_size;
691696

lib/std/Build/Cache.zig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,17 +1011,16 @@ pub const Manifest = struct {
10111011
}
10121012

10131013
/// Like `addFilePost` but when the file contents have already been loaded from disk.
1014-
/// On success, cache takes ownership of `resolved_path`.
10151014
pub fn addFilePostContents(
10161015
self: *Manifest,
1017-
resolved_path: []u8,
1016+
file_path: []const u8,
10181017
bytes: []const u8,
10191018
stat: File.Stat,
10201019
) !void {
10211020
assert(self.manifest_file != null);
10221021
const gpa = self.cache.gpa;
10231022

1024-
const prefixed_path = try self.cache.findPrefixResolved(resolved_path);
1023+
const prefixed_path = try self.cache.findPrefix(file_path);
10251024
errdefer gpa.free(prefixed_path.sub_path);
10261025

10271026
const gop = try self.files.getOrPutAdapted(gpa, prefixed_path, FilesAdapter{});

src/Builtin.zig

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,26 @@ code_model: std.builtin.CodeModel,
1919
omit_frame_pointer: bool,
2020
wasi_exec_model: std.builtin.WasiExecModel,
2121

22+
/// Compute an abstract hash representing this `Builtin`. This is *not* a hash
23+
/// of the resulting file contents.
24+
pub fn hash(opts: @This()) [std.Build.Cache.bin_digest_len]u8 {
25+
var h: Cache.Hasher = Cache.hasher_init;
26+
inline for (@typeInfo(@This()).@"struct".fields) |f| {
27+
if (comptime std.mem.eql(u8, f.name, "target")) {
28+
// This needs special handling.
29+
std.hash.autoHash(&h, opts.target.cpu);
30+
std.hash.autoHash(&h, opts.target.os.tag);
31+
std.hash.autoHash(&h, opts.target.os.versionRange());
32+
std.hash.autoHash(&h, opts.target.abi);
33+
std.hash.autoHash(&h, opts.target.ofmt);
34+
std.hash.autoHash(&h, opts.target.dynamic_linker);
35+
} else {
36+
std.hash.autoHash(&h, @field(opts, f.name));
37+
}
38+
}
39+
return h.finalResult();
40+
}
41+
2242
pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {
2343
var buffer = std.ArrayList(u8).init(allocator);
2444
try append(opts, &buffer);
@@ -263,50 +283,66 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
263283
}
264284
}
265285

266-
pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void {
267-
if (mod.root.statFile(mod.root_src_path)) |stat| {
286+
/// This essentially takes the place of `Zcu.PerThread.updateFile`, but for 'builtin' modules.
287+
/// Instead of reading the file from disk, its contents are generated in-memory.
288+
pub fn populateFile(opts: @This(), gpa: Allocator, file: *File) Allocator.Error!void {
289+
assert(file.is_builtin);
290+
assert(file.status == .never_loaded);
291+
assert(file.source == null);
292+
assert(file.tree == null);
293+
assert(file.zir == null);
294+
295+
file.source = try opts.generate(gpa);
296+
297+
log.debug("parsing and generating 'builtin.zig'", .{});
298+
299+
file.tree = try std.zig.Ast.parse(gpa, file.source.?, .zig);
300+
assert(file.tree.?.errors.len == 0); // builtin.zig must parse
301+
302+
file.zir = try AstGen.generate(gpa, file.tree.?);
303+
assert(!file.zir.?.hasCompileErrors()); // builtin.zig must not have astgen errors
304+
file.status = .success;
305+
}
306+
307+
/// After `populateFile` succeeds, call this function to write the generated file out to disk
308+
/// if necessary. This is useful for external tooling such as debuggers.
309+
/// Assumes that `file.mod` is correctly set to the builtin module.
310+
pub fn updateFileOnDisk(file: *File, comp: *Compilation) !void {
311+
assert(file.is_builtin);
312+
assert(file.status == .success);
313+
assert(file.source != null);
314+
315+
const root_dir, const sub_path = file.path.openInfo(comp.dirs);
316+
317+
if (root_dir.statFile(sub_path)) |stat| {
268318
if (stat.size != file.source.?.len) {
269319
std.log.warn(
270-
"the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++
320+
"the cached file '{}' had the wrong size. Expected {d}, found {d}. " ++
271321
"Overwriting with correct file contents now",
272-
.{ mod.root, mod.root_src_path, file.source.?.len, stat.size },
322+
.{ file.path.fmt(comp), file.source.?.len, stat.size },
273323
);
274-
275-
try writeFile(file, mod);
276324
} else {
277325
file.stat = .{
278326
.size = stat.size,
279327
.inode = stat.inode,
280328
.mtime = stat.mtime,
281329
};
330+
return;
282331
}
283332
} else |err| switch (err) {
284-
error.BadPathName => unreachable, // it's always "builtin.zig"
285-
error.NameTooLong => unreachable, // it's always "builtin.zig"
286-
error.PipeBusy => unreachable, // it's not a pipe
287-
error.NoDevice => unreachable, // it's not a pipe
288-
error.WouldBlock => unreachable, // not asking for non-blocking I/O
333+
error.FileNotFound => {},
289334

290-
error.FileNotFound => try writeFile(file, mod),
335+
error.WouldBlock => unreachable, // not asking for non-blocking I/O
336+
error.BadPathName => unreachable, // it's always "o/digest/builtin.zig"
337+
error.NameTooLong => unreachable, // it's always "o/digest/builtin.zig"
291338

339+
// We don't expect the file to be a pipe, but can't mark `error.PipeBusy` as `unreachable`,
340+
// because the user could always replace the file on disk.
292341
else => |e| return e,
293342
}
294343

295-
log.debug("parsing and generating '{s}'", .{mod.root_src_path});
296-
297-
file.tree = try std.zig.Ast.parse(comp.gpa, file.source.?, .zig);
298-
assert(file.tree.?.errors.len == 0); // builtin.zig must parse
299-
300-
file.zir = try AstGen.generate(comp.gpa, file.tree.?);
301-
assert(!file.zir.?.hasCompileErrors()); // builtin.zig must not have astgen errors
302-
file.status = .success;
303-
// Note that whilst we set `zir` here, we populated `path_digest`
304-
// all the way back in `Package.Module.create`.
305-
}
306-
307-
fn writeFile(file: *File, mod: *Module) !void {
308-
var buf: [std.fs.max_path_bytes]u8 = undefined;
309-
var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf);
344+
// `make_path` matters because the dir hasn't actually been created yet.
345+
var af = try root_dir.atomicFile(sub_path, .{ .make_path = true });
310346
defer af.deinit();
311347
try af.file.writeAll(file.source.?);
312348
af.finish() catch |err| switch (err) {
@@ -331,6 +367,7 @@ fn writeFile(file: *File, mod: *Module) !void {
331367
const builtin = @import("builtin");
332368
const std = @import("std");
333369
const Allocator = std.mem.Allocator;
370+
const Cache = std.Build.Cache;
334371
const build_options = @import("build_options");
335372
const Module = @import("Package/Module.zig");
336373
const assert = std.debug.assert;

0 commit comments

Comments
 (0)