aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Module.zig')
-rw-r--r--src/Module.zig120
1 files changed, 34 insertions, 86 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 02df2dac67..499eb02f1e 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -834,6 +834,9 @@ pub const File = struct {
multi_pkg: bool = false,
/// List of references to this file, used for multi-package errors.
references: std.ArrayListUnmanaged(Reference) = .{},
+ /// The hash of the path to this file, used to store `InternPool.TrackedInst`.
+ /// undefined until `zir_loaded == true`.
+ path_digest: Cache.BinDigest = undefined,
/// Used by change detection algorithm, after astgen, contains the
/// set of decls that existed in the previous ZIR but not in the new one.
@@ -2594,7 +2597,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
const stat = try source_file.stat();
const want_local_cache = file.mod == mod.main_mod;
- const digest = hash: {
+ const bin_digest = hash: {
var path_hash: Cache.HashHelper = .{};
path_hash.addBytes(build_options.version);
path_hash.add(builtin.zig_backend);
@@ -2603,7 +2606,19 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
path_hash.addBytes(file.mod.root.sub_path);
}
path_hash.addBytes(file.sub_file_path);
- break :hash path_hash.final();
+ var bin: Cache.BinDigest = undefined;
+ path_hash.hasher.final(&bin);
+ break :hash bin;
+ };
+ file.path_digest = bin_digest;
+ const hex_digest = hex: {
+ var hex: Cache.HexDigest = undefined;
+ _ = std.fmt.bufPrint(
+ &hex,
+ "{s}",
+ .{std.fmt.fmtSliceHexLower(&bin_digest)},
+ ) catch unreachable;
+ break :hex hex;
};
const cache_directory = if (want_local_cache) mod.local_zir_cache else mod.global_zir_cache;
const zir_dir = cache_directory.handle;
@@ -2613,7 +2628,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
.never_loaded, .retryable_failure => lock: {
// First, load the cached ZIR code, if any.
log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{
- file.sub_file_path, want_local_cache, &digest,
+ file.sub_file_path, want_local_cache, &hex_digest,
});
break :lock .shared;
@@ -2640,7 +2655,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
// version. Likewise if we're working on AstGen and another process asks for
// the cached file, they'll get it.
const cache_file = while (true) {
- break zir_dir.createFile(&digest, .{
+ break zir_dir.createFile(&hex_digest, .{
.read = true,
.truncate = false,
.lock = lock,
@@ -2826,7 +2841,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
};
cache_file.writevAll(&iovecs) catch |err| {
log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{
- file.mod.root, file.sub_file_path, cache_directory, &digest, @errorName(err),
+ file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err),
});
};
@@ -2935,89 +2950,22 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File)
return zir;
}
-/// Patch ups:
-/// * Struct.zir_index
-/// * Decl.zir_index
-/// * Fn.zir_body_inst
-/// * Decl.zir_decl_index
-fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
- const gpa = mod.gpa;
- const new_zir = file.zir;
-
- // The root decl will be null if the previous ZIR had AST errors.
- const root_decl = file.root_decl.unwrap() orelse return;
+fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void {
+ const gpa = zcu.gpa;
- // Maps from old ZIR to new ZIR, declaration, struct_decl, enum_decl, etc. Any instruction which
- // creates a namespace, and any `declaration` instruction, gets mapped from old to new here.
var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
defer inst_map.deinit(gpa);
- try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map);
-
- // Walk the Decl graph, updating ZIR indexes, strings, and populating
- // the deleted and outdated lists.
-
- var decl_stack: ArrayListUnmanaged(Decl.Index) = .{};
- defer decl_stack.deinit(gpa);
-
- try decl_stack.append(gpa, root_decl);
-
- file.deleted_decls.clearRetainingCapacity();
- file.outdated_decls.clearRetainingCapacity();
-
- // The root decl is always outdated; otherwise we would not have had
- // to re-generate ZIR for the File.
- try file.outdated_decls.append(gpa, root_decl);
-
- const ip = &mod.intern_pool;
-
- while (decl_stack.popOrNull()) |decl_index| {
- const decl = mod.declPtr(decl_index);
- // Anonymous decls and the root decl have this set to 0. We still need
- // to walk them but we do not need to modify this value.
- // Anonymous decls should not be marked outdated. They will be re-generated
- // if their owner decl is marked outdated.
- if (decl.zir_decl_index.unwrap()) |old_zir_decl_index| {
- const new_zir_decl_index = inst_map.get(old_zir_decl_index) orelse {
- try file.deleted_decls.append(gpa, decl_index);
- continue;
- };
- const old_hash = decl.contentsHashZir(old_zir);
- decl.zir_decl_index = new_zir_decl_index.toOptional();
- const new_hash = decl.contentsHashZir(new_zir);
- if (!std.zig.srcHashEql(old_hash, new_hash)) {
- try file.outdated_decls.append(gpa, decl_index);
- }
- }
+ try mapOldZirToNew(gpa, old_zir, file.zir, &inst_map);
- if (!decl.owns_tv) continue;
-
- if (decl.getOwnedStruct(mod)) |struct_type| {
- struct_type.setZirIndex(ip, inst_map.get(struct_type.zir_index) orelse {
- try file.deleted_decls.append(gpa, decl_index);
- continue;
- });
- }
-
- if (decl.getOwnedUnion(mod)) |union_type| {
- union_type.setZirIndex(ip, inst_map.get(union_type.zir_index) orelse {
- try file.deleted_decls.append(gpa, decl_index);
- continue;
- });
- }
-
- if (decl.getOwnedFunction(mod)) |func| {
- func.zirBodyInst(ip).* = inst_map.get(func.zir_body_inst) orelse {
- try file.deleted_decls.append(gpa, decl_index);
- continue;
- };
- }
-
- if (decl.getOwnedInnerNamespace(mod)) |namespace| {
- for (namespace.decls.keys()) |sub_decl| {
- try decl_stack.append(gpa, sub_decl);
- }
- }
+ // TODO: this should be done after all AstGen workers complete, to avoid
+ // iterating over this full set for every updated file.
+ for (zcu.intern_pool.tracked_insts.keys()) |*ti| {
+ if (!std.mem.eql(u8, &ti.path_digest, &file.path_digest)) continue;
+ ti.inst = inst_map.get(ti.inst) orelse {
+ // TODO: invalidate this `TrackedInst` via the dependency mechanism
+ continue;
+ };
}
}
@@ -3494,7 +3442,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
const struct_ty = sema.getStructType(
new_decl_index,
new_namespace_index,
- .main_struct_inst,
+ try mod.intern_pool.trackZir(gpa, file, .main_struct_inst),
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
};
@@ -4472,7 +4420,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
};
defer inner_block.instructions.deinit(gpa);
- const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*);
+ const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).resolve(ip));
// Here we are performing "runtime semantic analysis" for a function body, which means
// we must map the parameter ZIR instructions to `arg` AIR instructions.
@@ -6125,7 +6073,7 @@ pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0]
const tags = file.zir.instructions.items(.tag);
const data = file.zir.instructions.items(.data);
- const param_body = file.zir.getParamBody(func.zir_body_inst);
+ const param_body = file.zir.getParamBody(func.zir_body_inst.resolve(&mod.intern_pool));
const param = param_body[index];
return switch (tags[@intFromEnum(param)]) {