authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-04-19 17:40:29+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-20 09:09:15-07:00
logfac120bc3ad58a10ab80952e42becd0084aec059
tree699fa2b825c0642a5b3865b390ee0f9f224fbe4b
parentd5f1a8823eb964c6149fc1d627ea6936d70ea7f1

Module: mark function body dependencies, don't re-analyze anonymous decls


2 files changed, 93 insertions(+), 53 deletions(-)

src/Module.zig+90-52
...@@ -564,7 +564,23 @@ pub const Decl = struct {...@@ -564,7 +564,23 @@ pub const Decl = struct {
564 }564 }
565 };565 };
566566
567 pub const DepsTable = std.AutoArrayHashMapUnmanaged(Decl.Index, void);567 pub const DepsTable = std.AutoArrayHashMapUnmanaged(Decl.Index, DepType);
568
569 /// Later types take priority; e.g. if a dependent decl has both `normal`
570 /// and `function_body` dependencies on another decl, it will be marked as
571 /// having a `function_body` dependency.
572 pub const DepType = enum {
573 /// The dependent references or uses the dependency's value, so must be
574 /// updated whenever it is changed. However, if the dependency is a
575 /// function and its type is unchanged, the dependent does not need to
576 /// be updated.
577 normal,
578 /// The dependent performs an inline or comptime call to the dependency,
579 /// or is a generic instantiation of it. It must therefore be updated
580 /// whenever the dependency is updated, even if the function type
581 /// remained the same.
582 function_body,
583 };
568584
569 pub fn clearName(decl: *Decl, gpa: Allocator) void {585 pub fn clearName(decl: *Decl, gpa: Allocator) void {
570 gpa.free(mem.sliceTo(decl.name, 0));586 gpa.free(mem.sliceTo(decl.name, 0));
...@@ -4155,53 +4171,63 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4155,53 +4171,63 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4155 decl_prog_node.activate();4171 decl_prog_node.activate();
4156 defer decl_prog_node.end();4172 defer decl_prog_node.end();
41574173
4158 const type_changed = mod.semaDecl(decl_index) catch |err| switch (err) {4174 const type_changed = blk: {
4159 error.AnalysisFail => {4175 if (decl.zir_decl_index == 0 and !mod.declIsRoot(decl_index)) {
4160 if (decl.analysis == .in_progress) {4176 // Anonymous decl. We don't semantically analyze these.
4161 // If this decl caused the compile error, the analysis field would4177 break :blk false; // tv unchanged
4162 // be changed to indicate it was this Decl's fault. Because this4178 }
4163 // did not happen, we infer here that it was a dependency failure.4179
4164 decl.analysis = .dependency_failure;4180 break :blk mod.semaDecl(decl_index) catch |err| switch (err) {
4165 }4181 error.AnalysisFail => {
4166 return error.AnalysisFail;4182 if (decl.analysis == .in_progress) {
4167 },4183 // If this decl caused the compile error, the analysis field would
4168 error.NeededSourceLocation => unreachable,4184 // be changed to indicate it was this Decl's fault. Because this
4169 error.GenericPoison => unreachable,4185 // did not happen, we infer here that it was a dependency failure.
4170 else => |e| {4186 decl.analysis = .dependency_failure;
4171 decl.analysis = .sema_failure_retryable;4187 }
4172 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);4188 return error.AnalysisFail;
4173 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(4189 },
4174 mod.gpa,4190 error.NeededSourceLocation => unreachable,
4175 decl.srcLoc(),4191 error.GenericPoison => unreachable,
4176 "unable to analyze: {s}",4192 else => |e| {
4177 .{@errorName(e)},4193 decl.analysis = .sema_failure_retryable;
4178 ));4194 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);
4179 return error.AnalysisFail;4195 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
4180 },4196 mod.gpa,
4197 decl.srcLoc(),
4198 "unable to analyze: {s}",
4199 .{@errorName(e)},
4200 ));
4201 return error.AnalysisFail;
4202 },
4203 };
4181 };4204 };
41824205
4183 if (subsequent_analysis) {4206 if (subsequent_analysis) {
4184 // We may need to chase the dependants and re-analyze them.4207 // Update all dependents which have at least this level of dependency.
4185 // However, if the decl is a function, and the type is the same, we do not need to.4208 // If our type remained the same and we're a function, only update
4186 if (type_changed or decl.ty.zigTypeTag() != .Fn) {4209 // decls which depend on our body; otherwise, update all dependents.
4187 for (decl.dependants.keys()) |dep_index| {4210 const update_level: Decl.DepType = if (!type_changed and decl.ty.zigTypeTag() == .Fn) .function_body else .normal;
4188 const dep = mod.declPtr(dep_index);4211
4189 switch (dep.analysis) {4212 for (decl.dependants.keys(), decl.dependants.values()) |dep_index, dep_type| {
4190 .unreferenced => unreachable,4213 if (@enumToInt(dep_type) < @enumToInt(update_level)) continue;
4191 .in_progress => continue, // already doing analysis, ok4214
4192 .outdated => continue, // already queued for update4215 const dep = mod.declPtr(dep_index);
41934216 switch (dep.analysis) {
4194 .file_failure,4217 .unreferenced => unreachable,
4195 .dependency_failure,4218 .in_progress => continue, // already doing analysis, ok
4196 .sema_failure,4219 .outdated => continue, // already queued for update
4197 .sema_failure_retryable,4220
4198 .codegen_failure,4221 .file_failure,
4199 .codegen_failure_retryable,4222 .dependency_failure,
4200 .complete,4223 .sema_failure,
4201 => if (dep.generation != mod.generation) {4224 .sema_failure_retryable,
4202 try mod.markOutdatedDecl(dep_index);4225 .codegen_failure,
4203 },4226 .codegen_failure_retryable,
4204 }4227 .complete,
4228 => if (dep.generation != mod.generation) {
4229 try mod.markOutdatedDecl(dep_index);
4230 },
4205 }4231 }
4206 }4232 }
4207 }4233 }
...@@ -4742,25 +4768,37 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4742,25 +4768,37 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47424768
4743/// Returns the depender's index of the dependee.4769/// Returns the depender's index of the dependee.
4744pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_index: Decl.Index) !void {4770pub fn declareDeclDependency(mod: *Module, depender_index: Decl.Index, dependee_index: Decl.Index) !void {
4771 return mod.declareDeclDependencyType(depender_index, dependee_index, .normal);
4772}
4773
4774/// Returns the depender's index of the dependee.
4775pub fn declareDeclDependencyType(mod: *Module, depender_index: Decl.Index, dependee_index: Decl.Index, dep_type: Decl.DepType) !void {
4745 if (depender_index == dependee_index) return;4776 if (depender_index == dependee_index) return;
47464777
4747 const depender = mod.declPtr(depender_index);4778 const depender = mod.declPtr(depender_index);
4748 const dependee = mod.declPtr(dependee_index);4779 const dependee = mod.declPtr(dependee_index);
47494780
4781 if (depender.dependencies.get(dependee_index)) |cur_type| {
4782 if (@enumToInt(cur_type) >= @enumToInt(dep_type)) {
4783 // We already have this dependency (or stricter) marked
4784 return;
4785 }
4786 }
4787
4750 log.debug("{*} ({s}) depends on {*} ({s})", .{4788 log.debug("{*} ({s}) depends on {*} ({s})", .{
4751 depender, depender.name, dependee, dependee.name,4789 depender, depender.name, dependee, dependee.name,
4752 });4790 });
47534791
4754 try depender.dependencies.ensureUnusedCapacity(mod.gpa, 1);
4755 try dependee.dependants.ensureUnusedCapacity(mod.gpa, 1);
4756
4757 if (dependee.deletion_flag) {4792 if (dependee.deletion_flag) {
4758 dependee.deletion_flag = false;4793 dependee.deletion_flag = false;
4759 assert(mod.deletion_set.swapRemove(dependee_index));4794 assert(mod.deletion_set.swapRemove(dependee_index));
4760 }4795 }
47614796
4762 dependee.dependants.putAssumeCapacity(depender_index, {});4797 try depender.dependencies.ensureUnusedCapacity(mod.gpa, 1);
4763 depender.dependencies.putAssumeCapacity(dependee_index, {});4798 try dependee.dependants.ensureUnusedCapacity(mod.gpa, 1);
4799
4800 dependee.dependants.putAssumeCapacity(depender_index, dep_type);
4801 depender.dependencies.putAssumeCapacity(dependee_index, dep_type);
4764}4802}
47654803
4766pub const ImportFileResult = struct {4804pub const ImportFileResult = struct {
...@@ -6342,8 +6380,8 @@ pub fn populateTestFunctions(...@@ -6342,8 +6380,8 @@ pub fn populateTestFunctions(
6342 try mod.declPtr(test_name_decl_index).finalizeNewArena(&name_decl_arena);6380 try mod.declPtr(test_name_decl_index).finalizeNewArena(&name_decl_arena);
6343 break :n test_name_decl_index;6381 break :n test_name_decl_index;
6344 };6382 };
6345 array_decl.dependencies.putAssumeCapacityNoClobber(test_decl_index, {});6383 array_decl.dependencies.putAssumeCapacityNoClobber(test_decl_index, .normal);
6346 array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl_index, {});6384 array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl_index, .normal);
6347 try mod.linkerUpdateDecl(test_name_decl_index);6385 try mod.linkerUpdateDecl(test_name_decl_index);
63486386
6349 const field_vals = try arena.create([3]Value);6387 const field_vals = try arena.create([3]Value);
src/Sema.zig+3-1
...@@ -6635,6 +6635,8 @@ fn analyzeCall(...@@ -6635,6 +6635,8 @@ fn analyzeCall(
6635 sema.code = fn_owner_decl.getFileScope().zir;6635 sema.code = fn_owner_decl.getFileScope().zir;
6636 defer sema.code = parent_zir;6636 defer sema.code = parent_zir;
66376637
6638 try mod.declareDeclDependencyType(sema.owner_decl_index, module_fn.owner_decl, .function_body);
6639
6638 const parent_inst_map = sema.inst_map;6640 const parent_inst_map = sema.inst_map;
6639 sema.inst_map = .{};6641 sema.inst_map = .{};
6640 defer {6642 defer {
...@@ -7331,7 +7333,7 @@ fn instantiateGenericCall(...@@ -7331,7 +7333,7 @@ fn instantiateGenericCall(
7331 // The generic function Decl is guaranteed to be the first dependency7333 // The generic function Decl is guaranteed to be the first dependency
7332 // of each of its instantiations.7334 // of each of its instantiations.
7333 assert(new_decl.dependencies.keys().len == 0);7335 assert(new_decl.dependencies.keys().len == 0);
7334 try mod.declareDeclDependency(new_decl_index, module_fn.owner_decl);7336 try mod.declareDeclDependencyType(new_decl_index, module_fn.owner_decl, .function_body);
73357337
7336 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);7338 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
7337 const new_decl_arena_allocator = new_decl_arena.allocator();7339 const new_decl_arena_allocator = new_decl_arena.allocator();