mirror of
https://github.com/ziglang/zig.git
synced 2024-11-17 09:32:51 +00:00
stage2: CacheMode.whole: trigger loading zig source files
Previously the code asserted source files were already loaded, but this is not the case when cached ZIR is loaded. Now it will trigger .zig source code to be loaded for the purposes of hashing the source for `CacheMode.whole`. This additionally refactors stat_size, stat_inode, and stat_mtime fields into using the `Cache.File.Stat` struct.
This commit is contained in:
parent
dbd0a2c35d
commit
0ad2a99675
@ -421,7 +421,7 @@ pub const AllErrors = struct {
|
||||
const module_note = module_err_msg.notes[i];
|
||||
const source = try module_note.src_loc.file_scope.getSource(module.gpa);
|
||||
const byte_offset = try module_note.src_loc.byteOffset(module.gpa);
|
||||
const loc = std.zig.findLineColumn(source, byte_offset);
|
||||
const loc = std.zig.findLineColumn(source.bytes, byte_offset);
|
||||
const file_path = try module_note.src_loc.file_scope.fullPath(allocator);
|
||||
note.* = .{
|
||||
.src = .{
|
||||
@ -444,7 +444,7 @@ pub const AllErrors = struct {
|
||||
}
|
||||
const source = try module_err_msg.src_loc.file_scope.getSource(module.gpa);
|
||||
const byte_offset = try module_err_msg.src_loc.byteOffset(module.gpa);
|
||||
const loc = std.zig.findLineColumn(source, byte_offset);
|
||||
const loc = std.zig.findLineColumn(source.bytes, byte_offset);
|
||||
const file_path = try module_err_msg.src_loc.file_scope.fullPath(allocator);
|
||||
try errors.append(.{
|
||||
.src = .{
|
||||
|
156
src/Module.zig
156
src/Module.zig
@ -1463,11 +1463,7 @@ pub const File = struct {
|
||||
/// Whether this is populated depends on `source_loaded`.
|
||||
source: [:0]const u8,
|
||||
/// Whether this is populated depends on `status`.
|
||||
stat_size: u64,
|
||||
/// Whether this is populated depends on `status`.
|
||||
stat_inode: std.fs.File.INode,
|
||||
/// Whether this is populated depends on `status`.
|
||||
stat_mtime: i128,
|
||||
stat: Cache.File.Stat,
|
||||
/// Whether this is populated or not depends on `tree_loaded`.
|
||||
tree: Ast,
|
||||
/// Whether this is populated or not depends on `zir_loaded`.
|
||||
@ -1535,8 +1531,16 @@ pub const File = struct {
|
||||
file.* = undefined;
|
||||
}
|
||||
|
||||
pub fn getSource(file: *File, gpa: Allocator) ![:0]const u8 {
|
||||
if (file.source_loaded) return file.source;
|
||||
pub const Source = struct {
|
||||
bytes: [:0]const u8,
|
||||
stat: Cache.File.Stat,
|
||||
};
|
||||
|
||||
pub fn getSource(file: *File, gpa: Allocator) !Source {
|
||||
if (file.source_loaded) return Source{
|
||||
.bytes = file.source,
|
||||
.stat = file.stat,
|
||||
};
|
||||
|
||||
const root_dir_path = file.pkg.root_src_directory.path orelse ".";
|
||||
log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{
|
||||
@ -1565,14 +1569,21 @@ pub const File = struct {
|
||||
|
||||
file.source = source;
|
||||
file.source_loaded = true;
|
||||
return source;
|
||||
return Source{
|
||||
.bytes = source,
|
||||
.stat = .{
|
||||
.size = stat.size,
|
||||
.inode = stat.inode,
|
||||
.mtime = stat.mtime,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getTree(file: *File, gpa: Allocator) !*const Ast {
|
||||
if (file.tree_loaded) return &file.tree;
|
||||
|
||||
const source = try file.getSource(gpa);
|
||||
file.tree = try std.zig.parse(gpa, source);
|
||||
file.tree = try std.zig.parse(gpa, source.bytes);
|
||||
file.tree_loaded = true;
|
||||
return &file.tree;
|
||||
}
|
||||
@ -1631,9 +1642,7 @@ pub const EmbedFile = struct {
|
||||
/// Memory is stored in gpa, owned by EmbedFile.
|
||||
sub_file_path: []const u8,
|
||||
bytes: [:0]const u8,
|
||||
stat_size: u64,
|
||||
stat_inode: std.fs.File.INode,
|
||||
stat_mtime: i128,
|
||||
stat: Cache.File.Stat,
|
||||
/// Package that this file is a part of, managed externally.
|
||||
pkg: *Package,
|
||||
/// The Decl that was created from the `@embedFile` to own this resource.
|
||||
@ -2704,9 +2713,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
|
||||
keep_zir = true;
|
||||
file.zir = zir;
|
||||
file.zir_loaded = true;
|
||||
file.stat_size = header.stat_size;
|
||||
file.stat_inode = header.stat_inode;
|
||||
file.stat_mtime = header.stat_mtime;
|
||||
file.stat = .{
|
||||
.size = header.stat_size,
|
||||
.inode = header.stat_inode,
|
||||
.mtime = header.stat_mtime,
|
||||
};
|
||||
file.status = .success_zir;
|
||||
log.debug("AstGen cached success: {s}", .{file.sub_file_path});
|
||||
|
||||
@ -2724,9 +2735,9 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
|
||||
},
|
||||
.parse_failure, .astgen_failure, .success_zir => {
|
||||
const unchanged_metadata =
|
||||
stat.size == file.stat_size and
|
||||
stat.mtime == file.stat_mtime and
|
||||
stat.inode == file.stat_inode;
|
||||
stat.size == file.stat.size and
|
||||
stat.mtime == file.stat.mtime and
|
||||
stat.inode == file.stat.inode;
|
||||
|
||||
if (unchanged_metadata) {
|
||||
log.debug("unmodified metadata of file: {s}", .{file.sub_file_path});
|
||||
@ -2787,9 +2798,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
|
||||
if (amt != stat.size)
|
||||
return error.UnexpectedEndOfFile;
|
||||
|
||||
file.stat_size = stat.size;
|
||||
file.stat_inode = stat.inode;
|
||||
file.stat_mtime = stat.mtime;
|
||||
file.stat = .{
|
||||
.size = stat.size,
|
||||
.inode = stat.inode,
|
||||
.mtime = stat.mtime,
|
||||
};
|
||||
file.source = source;
|
||||
file.source_loaded = true;
|
||||
|
||||
@ -3069,9 +3082,11 @@ pub fn populateBuiltinFile(mod: *Module) !void {
|
||||
|
||||
try writeBuiltinFile(file, builtin_pkg);
|
||||
} else {
|
||||
file.stat_size = stat.size;
|
||||
file.stat_inode = stat.inode;
|
||||
file.stat_mtime = stat.mtime;
|
||||
file.stat = .{
|
||||
.size = stat.size,
|
||||
.inode = stat.inode,
|
||||
.mtime = stat.mtime,
|
||||
};
|
||||
}
|
||||
} else |err| switch (err) {
|
||||
error.BadPathName => unreachable, // it's always "builtin.zig"
|
||||
@ -3099,9 +3114,11 @@ pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {
|
||||
try af.file.writeAll(file.source);
|
||||
try af.finish();
|
||||
|
||||
file.stat_size = file.source.len;
|
||||
file.stat_inode = 0; // dummy value
|
||||
file.stat_mtime = 0; // dummy value
|
||||
file.stat = .{
|
||||
.size = file.source.len,
|
||||
.inode = 0, // dummy value
|
||||
.mtime = 0, // dummy value
|
||||
};
|
||||
}
|
||||
|
||||
pub fn mapOldZirToNew(
|
||||
@ -3382,16 +3399,16 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
|
||||
}
|
||||
|
||||
if (mod.comp.whole_cache_manifest) |man| {
|
||||
assert(file.source_loaded);
|
||||
const source = file.getSource(gpa) catch |err| {
|
||||
try reportRetryableFileError(mod, file, "unable to load source: {s}", .{@errorName(err)});
|
||||
return error.AnalysisFail;
|
||||
};
|
||||
const resolved_path = try file.pkg.root_src_directory.join(gpa, &.{
|
||||
file.sub_file_path,
|
||||
});
|
||||
errdefer gpa.free(resolved_path);
|
||||
try man.addFilePostContents(resolved_path, file.source, .{
|
||||
.size = file.stat_size,
|
||||
.inode = file.stat_inode,
|
||||
.mtime = file.stat_mtime,
|
||||
});
|
||||
|
||||
try man.addFilePostContents(resolved_path, source.bytes, source.stat);
|
||||
}
|
||||
} else {
|
||||
new_decl.analysis = .file_failure;
|
||||
@ -3723,9 +3740,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult {
|
||||
.source_loaded = false,
|
||||
.tree_loaded = false,
|
||||
.zir_loaded = false,
|
||||
.stat_size = undefined,
|
||||
.stat_inode = undefined,
|
||||
.stat_mtime = undefined,
|
||||
.stat = undefined,
|
||||
.tree = undefined,
|
||||
.zir = undefined,
|
||||
.status = .never_loaded,
|
||||
@ -3793,9 +3808,7 @@ pub fn importFile(
|
||||
.source_loaded = false,
|
||||
.tree_loaded = false,
|
||||
.zir_loaded = false,
|
||||
.stat_size = undefined,
|
||||
.stat_inode = undefined,
|
||||
.stat_mtime = undefined,
|
||||
.stat = undefined,
|
||||
.tree = undefined,
|
||||
.zir = undefined,
|
||||
.status = .never_loaded,
|
||||
@ -3840,8 +3853,13 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
|
||||
var file = try cur_file.pkg.root_src_directory.handle.openFile(sub_file_path, .{});
|
||||
defer file.close();
|
||||
|
||||
const stat = try file.stat();
|
||||
const size_usize = try std.math.cast(usize, stat.size);
|
||||
const actual_stat = try file.stat();
|
||||
const stat: Cache.File.Stat = .{
|
||||
.size = actual_stat.size,
|
||||
.inode = actual_stat.inode,
|
||||
.mtime = actual_stat.mtime,
|
||||
};
|
||||
const size_usize = try std.math.cast(usize, actual_stat.size);
|
||||
const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);
|
||||
errdefer gpa.free(bytes);
|
||||
|
||||
@ -3852,11 +3870,7 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
|
||||
if (mod.comp.whole_cache_manifest) |man| {
|
||||
const copied_resolved_path = try gpa.dupe(u8, resolved_path);
|
||||
errdefer gpa.free(copied_resolved_path);
|
||||
try man.addFilePostContents(copied_resolved_path, bytes, .{
|
||||
.size = stat.size,
|
||||
.inode = stat.inode,
|
||||
.mtime = stat.mtime,
|
||||
});
|
||||
try man.addFilePostContents(copied_resolved_path, bytes, stat);
|
||||
}
|
||||
|
||||
keep_resolved_path = true; // It's now owned by embed_table.
|
||||
@ -3864,9 +3878,7 @@ pub fn embedFile(mod: *Module, cur_file: *File, rel_file_path: []const u8) !*Emb
|
||||
new_file.* = .{
|
||||
.sub_file_path = sub_file_path,
|
||||
.bytes = bytes,
|
||||
.stat_size = stat.size,
|
||||
.stat_inode = stat.inode,
|
||||
.stat_mtime = stat.mtime,
|
||||
.stat = stat,
|
||||
.pkg = cur_file.pkg,
|
||||
.owner_decl = undefined, // Set by Sema immediately after this function returns.
|
||||
};
|
||||
@ -3880,9 +3892,9 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
|
||||
const stat = try file.stat();
|
||||
|
||||
const unchanged_metadata =
|
||||
stat.size == embed_file.stat_size and
|
||||
stat.mtime == embed_file.stat_mtime and
|
||||
stat.inode == embed_file.stat_inode;
|
||||
stat.size == embed_file.stat.size and
|
||||
stat.mtime == embed_file.stat.mtime and
|
||||
stat.inode == embed_file.stat.inode;
|
||||
|
||||
if (unchanged_metadata) return;
|
||||
|
||||
@ -3891,9 +3903,11 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
|
||||
const bytes = try file.readToEndAllocOptions(gpa, std.math.maxInt(u32), size_usize, 1, 0);
|
||||
gpa.free(embed_file.bytes);
|
||||
embed_file.bytes = bytes;
|
||||
embed_file.stat_size = stat.size;
|
||||
embed_file.stat_mtime = stat.mtime;
|
||||
embed_file.stat_inode = stat.inode;
|
||||
embed_file.stat = .{
|
||||
.size = stat.size,
|
||||
.mtime = stat.mtime,
|
||||
.inode = stat.inode,
|
||||
};
|
||||
|
||||
mod.comp.mutex.lock();
|
||||
defer mod.comp.mutex.unlock();
|
||||
@ -5024,3 +5038,35 @@ pub fn linkerUpdateDecl(mod: *Module, decl: *Decl) !void {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn reportRetryableFileError(
|
||||
mod: *Module,
|
||||
file: *File,
|
||||
comptime format: []const u8,
|
||||
args: anytype,
|
||||
) error{OutOfMemory}!void {
|
||||
file.status = .retryable_failure;
|
||||
|
||||
const err_msg = try ErrorMsg.create(
|
||||
mod.gpa,
|
||||
.{
|
||||
.file_scope = file,
|
||||
.parent_decl_node = 0,
|
||||
.lazy = .entire_file,
|
||||
},
|
||||
format,
|
||||
args,
|
||||
);
|
||||
errdefer err_msg.destroy(mod.gpa);
|
||||
|
||||
mod.comp.mutex.lock();
|
||||
defer mod.comp.mutex.unlock();
|
||||
|
||||
const gop = try mod.failed_files.getOrPut(mod.gpa, file);
|
||||
if (gop.found_existing) {
|
||||
if (gop.value_ptr.*) |old_err_msg| {
|
||||
old_err_msg.destroy(mod.gpa);
|
||||
}
|
||||
}
|
||||
gop.value_ptr.* = err_msg;
|
||||
}
|
||||
|
34
src/main.zig
34
src/main.zig
@ -3664,9 +3664,7 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void
|
||||
.zir_loaded = false,
|
||||
.sub_file_path = "<stdin>",
|
||||
.source = source_code,
|
||||
.stat_size = undefined,
|
||||
.stat_inode = undefined,
|
||||
.stat_mtime = undefined,
|
||||
.stat = undefined,
|
||||
.tree = tree,
|
||||
.tree_loaded = true,
|
||||
.zir = undefined,
|
||||
@ -3860,9 +3858,11 @@ fn fmtPathFile(
|
||||
.zir_loaded = false,
|
||||
.sub_file_path = file_path,
|
||||
.source = source_code,
|
||||
.stat_size = stat.size,
|
||||
.stat_inode = stat.inode,
|
||||
.stat_mtime = stat.mtime,
|
||||
.stat = .{
|
||||
.size = stat.size,
|
||||
.inode = stat.inode,
|
||||
.mtime = stat.mtime,
|
||||
},
|
||||
.tree = tree,
|
||||
.tree_loaded = true,
|
||||
.zir = undefined,
|
||||
@ -4458,9 +4458,7 @@ pub fn cmdAstCheck(
|
||||
.zir_loaded = false,
|
||||
.sub_file_path = undefined,
|
||||
.source = undefined,
|
||||
.stat_size = undefined,
|
||||
.stat_inode = undefined,
|
||||
.stat_mtime = undefined,
|
||||
.stat = undefined,
|
||||
.tree = undefined,
|
||||
.zir = undefined,
|
||||
.pkg = undefined,
|
||||
@ -4485,9 +4483,11 @@ pub fn cmdAstCheck(
|
||||
file.sub_file_path = file_name;
|
||||
file.source = source;
|
||||
file.source_loaded = true;
|
||||
file.stat_size = stat.size;
|
||||
file.stat_inode = stat.inode;
|
||||
file.stat_mtime = stat.mtime;
|
||||
file.stat = .{
|
||||
.size = stat.size,
|
||||
.inode = stat.inode,
|
||||
.mtime = stat.mtime,
|
||||
};
|
||||
} else {
|
||||
const stdin = io.getStdIn();
|
||||
const source = readSourceFileToEndAlloc(arena, &stdin, null) catch |err| {
|
||||
@ -4496,7 +4496,7 @@ pub fn cmdAstCheck(
|
||||
file.sub_file_path = "<stdin>";
|
||||
file.source = source;
|
||||
file.source_loaded = true;
|
||||
file.stat_size = source.len;
|
||||
file.stat.size = source.len;
|
||||
}
|
||||
|
||||
file.pkg = try Package.create(gpa, null, file.sub_file_path);
|
||||
@ -4609,9 +4609,11 @@ pub fn cmdChangelist(
|
||||
.zir_loaded = false,
|
||||
.sub_file_path = old_source_file,
|
||||
.source = undefined,
|
||||
.stat_size = stat.size,
|
||||
.stat_inode = stat.inode,
|
||||
.stat_mtime = stat.mtime,
|
||||
.stat = .{
|
||||
.size = stat.size,
|
||||
.inode = stat.inode,
|
||||
.mtime = stat.mtime,
|
||||
},
|
||||
.tree = undefined,
|
||||
.zir = undefined,
|
||||
.pkg = undefined,
|
||||
|
Loading…
Reference in New Issue
Block a user