authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-04 17:27:41+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-02-04 18:38:40+00:00
log0d8207c29236bf731f7d3bad189beb3a1e1b1d0c
treed7cb3a14a5c3b9ce77f299b24502204318993913
parent269c1ae649017836f15313d1d4977402be11eed5
signaturelock-open Commit is signed but in an unrecognized format.

Zcu: refactor Decl.analysis field

* Functions failing codegen now set this failure on the function analysis state. Decl analysis `codegen_failure` is reserved for failures generating constant values. * `liveness_failure` is consolidated into `codegen_failure`, as we do not need to distinguish these, and Liveness.Verify is just a debugging feature anyway. * `sema_failure_retryable` and `codegen_failure_retryable` are removed. Instead, retryable failures are recorded in the new `Zcu.retryable_failures` list. On an incremental update, this list is flushed, and all elements are marked as outdated so that we re-attempt analysis and code generation. Also remove the `generation` fields from `Zcu` and `Decl` as these are not needed by our new strategy for incremental updates.

4 files changed, 84 insertions(+), 87 deletions(-)

src/Compilation.zig+5-11
...@@ -2141,7 +2141,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2141,7 +2141,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
21412141
2142 if (comp.module) |module| {2142 if (comp.module) |module| {
2143 module.compile_log_text.shrinkAndFree(gpa, 0);2143 module.compile_log_text.shrinkAndFree(gpa, 0);
2144 module.generation += 1;
21452144
2146 // Make sure std.zig is inside the import_table. We unconditionally need2145 // Make sure std.zig is inside the import_table. We unconditionally need
2147 // it for start.zig.2146 // it for start.zig.
...@@ -3491,9 +3490,7 @@ pub fn performAllTheWork(...@@ -3491,9 +3490,7 @@ pub fn performAllTheWork(
34913490
3492 if (comp.module) |mod| {3491 if (comp.module) |mod| {
3493 try reportMultiModuleErrors(mod);3492 try reportMultiModuleErrors(mod);
3494 }3493 try mod.flushRetryableFailures();
3495
3496 if (comp.module) |mod| {
3497 mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);3494 mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
3498 mod.sema_prog_node.activate();3495 mod.sema_prog_node.activate();
3499 }3496 }
...@@ -3551,13 +3548,11 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v...@@ -3551,13 +3548,11 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
35513548
3552 .file_failure,3549 .file_failure,
3553 .sema_failure,3550 .sema_failure,
3554 .liveness_failure,
3555 .codegen_failure,3551 .codegen_failure,
3556 .dependency_failure,3552 .dependency_failure,
3557 .sema_failure_retryable,
3558 => return,3553 => return,
35593554
3560 .complete, .codegen_failure_retryable => {3555 .complete => {
3561 const named_frame = tracy.namedFrame("codegen_decl");3556 const named_frame = tracy.namedFrame("codegen_decl");
3562 defer named_frame.end();3557 defer named_frame.end();
35633558
...@@ -3592,17 +3587,15 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v...@@ -3592,17 +3587,15 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
3592 switch (decl.analysis) {3587 switch (decl.analysis) {
3593 .unreferenced => unreachable,3588 .unreferenced => unreachable,
3594 .in_progress => unreachable,3589 .in_progress => unreachable,
3595 .outdated => unreachable,
35963590
3597 .file_failure,3591 .file_failure,
3598 .sema_failure,3592 .sema_failure,
3599 .dependency_failure,3593 .dependency_failure,
3600 .sema_failure_retryable,
3601 => return,3594 => return,
36023595
3603 // emit-h only requires semantic analysis of the Decl to be complete,3596 // emit-h only requires semantic analysis of the Decl to be complete,
3604 // it does not depend on machine code generation to succeed.3597 // it does not depend on machine code generation to succeed.
3605 .liveness_failure, .codegen_failure, .codegen_failure_retryable, .complete => {3598 .codegen_failure, .complete => {
3606 const named_frame = tracy.namedFrame("emit_h_decl");3599 const named_frame = tracy.namedFrame("emit_h_decl");
3607 defer named_frame.end();3600 defer named_frame.end();
36083601
...@@ -3674,7 +3667,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v...@@ -3674,7 +3667,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
3674 "unable to update line number: {s}",3667 "unable to update line number: {s}",
3675 .{@errorName(err)},3668 .{@errorName(err)},
3676 ));3669 ));
3677 decl.analysis = .codegen_failure_retryable;3670 decl.analysis = .codegen_failure;
3671 try module.retryable_failures.append(gpa, InternPool.Depender.wrap(.{ .decl = decl_index }));
3678 };3672 };
3679 },3673 },
3680 .analyze_mod => |pkg| {3674 .analyze_mod => |pkg| {
src/InternPool.zig+5-5
...@@ -3483,6 +3483,11 @@ pub const FuncAnalysis = packed struct(u32) {...@@ -3483,6 +3483,11 @@ pub const FuncAnalysis = packed struct(u32) {
3483 /// This function might be OK but it depends on another Decl which did not3483 /// This function might be OK but it depends on another Decl which did not
3484 /// successfully complete semantic analysis.3484 /// successfully complete semantic analysis.
3485 dependency_failure,3485 dependency_failure,
3486 /// There will be a corresponding ErrorMsg in Module.failed_decls.
3487 /// Indicates that semantic analysis succeeded, but code generation for
3488 /// this function failed.
3489 codegen_failure,
3490 /// Semantic analysis and code generation of this function succeeded.
3486 success,3491 success,
3487 };3492 };
3488};3493};
...@@ -6182,7 +6187,6 @@ pub const GetFuncInstanceKey = struct {...@@ -6182,7 +6187,6 @@ pub const GetFuncInstanceKey = struct {
6182 is_noinline: bool,6187 is_noinline: bool,
6183 generic_owner: Index,6188 generic_owner: Index,
6184 inferred_error_set: bool,6189 inferred_error_set: bool,
6185 generation: u32,
6186};6190};
61876191
6188pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) Allocator.Error!Index {6192pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) Allocator.Error!Index {
...@@ -6249,7 +6253,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)...@@ -6249,7 +6253,6 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
6249 generic_owner,6253 generic_owner,
6250 func_index,6254 func_index,
6251 func_extra_index,6255 func_extra_index,
6252 arg.generation,
6253 func_ty,6256 func_ty,
6254 arg.section,6257 arg.section,
6255 );6258 );
...@@ -6381,7 +6384,6 @@ pub fn getFuncInstanceIes(...@@ -6381,7 +6384,6 @@ pub fn getFuncInstanceIes(
6381 generic_owner,6384 generic_owner,
6382 func_index,6385 func_index,
6383 func_extra_index,6386 func_extra_index,
6384 arg.generation,
6385 func_ty,6387 func_ty,
6386 arg.section,6388 arg.section,
6387 );6389 );
...@@ -6393,7 +6395,6 @@ fn finishFuncInstance(...@@ -6393,7 +6395,6 @@ fn finishFuncInstance(
6393 generic_owner: Index,6395 generic_owner: Index,
6394 func_index: Index,6396 func_index: Index,
6395 func_extra_index: u32,6397 func_extra_index: u32,
6396 generation: u32,
6397 func_ty: Index,6398 func_ty: Index,
6398 section: OptionalNullTerminatedString,6399 section: OptionalNullTerminatedString,
6399) Allocator.Error!Index {6400) Allocator.Error!Index {
...@@ -6413,7 +6414,6 @@ fn finishFuncInstance(...@@ -6413,7 +6414,6 @@ fn finishFuncInstance(
6413 .analysis = .complete,6414 .analysis = .complete,
6414 .zir_decl_index = fn_owner_decl.zir_decl_index,6415 .zir_decl_index = fn_owner_decl.zir_decl_index,
6415 .src_scope = fn_owner_decl.src_scope,6416 .src_scope = fn_owner_decl.src_scope,
6416 .generation = generation,
6417 .is_pub = fn_owner_decl.is_pub,6417 .is_pub = fn_owner_decl.is_pub,
6418 .is_exported = fn_owner_decl.is_exported,6418 .is_exported = fn_owner_decl.is_exported,
6419 .alive = true,6419 .alive = true,
src/Module.zig+74-64
...@@ -144,11 +144,6 @@ global_error_set: GlobalErrorSet = .{},...@@ -144,11 +144,6 @@ global_error_set: GlobalErrorSet = .{},
144/// Maximum amount of distinct error values, set by --error-limit144/// Maximum amount of distinct error values, set by --error-limit
145error_limit: ErrorInt,145error_limit: ErrorInt,
146146
147/// Incrementing integer used to compare against the corresponding Decl
148/// field to determine whether a Decl's status applies to an ongoing update, or a
149/// previous analysis.
150generation: u32 = 0,
151
152/// Value is the number of PO or outdated Decls which this Depender depends on.147/// Value is the number of PO or outdated Decls which this Depender depends on.
153potentially_outdated: std.AutoArrayHashMapUnmanaged(InternPool.Depender, u32) = .{},148potentially_outdated: std.AutoArrayHashMapUnmanaged(InternPool.Depender, u32) = .{},
154/// Value is the number of PO or outdated Decls which this Depender depends on.149/// Value is the number of PO or outdated Decls which this Depender depends on.
...@@ -164,6 +159,11 @@ outdated_ready: std.AutoArrayHashMapUnmanaged(InternPool.Depender, void) = .{},...@@ -164,6 +159,11 @@ outdated_ready: std.AutoArrayHashMapUnmanaged(InternPool.Depender, void) = .{},
164/// (only the namespace might change). If such a Decl is also `outdated`, the159/// (only the namespace might change). If such a Decl is also `outdated`, the
165/// struct type index must be recreated.160/// struct type index must be recreated.
166outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},161outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
162/// This contains a list of Dependers whose analysis or codegen failed, but the
163/// failure was something like running out of disk space, and trying again may
164/// succeed. On the next update, we will flush this list, marking all members of
165/// it as outdated.
166retryable_failures: std.ArrayListUnmanaged(InternPool.Depender) = .{},
167167
168stage1_flags: packed struct {168stage1_flags: packed struct {
169 have_winmain: bool = false,169 have_winmain: bool = false,
...@@ -380,21 +380,14 @@ pub const Decl = struct {...@@ -380,21 +380,14 @@ pub const Decl = struct {
380 alignment: Alignment,380 alignment: Alignment,
381 /// Populated when `has_tv`.381 /// Populated when `has_tv`.
382 @"addrspace": std.builtin.AddressSpace,382 @"addrspace": std.builtin.AddressSpace,
383 /// The direct parent namespace of the Decl.383 /// The direct parent namespace of the Decl. In the case of the Decl
384 /// Reference to externally owned memory.384 /// corresponding to a file, this is the namespace of the struct, since
385 /// In the case of the Decl corresponding to a file, this is385 /// there is no parent.
386 /// the namespace of the struct, since there is no parent.
387 src_namespace: Namespace.Index,386 src_namespace: Namespace.Index,
388387
389 /// The scope which lexically contains this decl. A decl must depend388 /// The scope which lexically contains this decl.
390 /// on its lexical parent, in order to ensure that this pointer is valid.
391 /// This scope is allocated out of the arena of the parent decl.
392 src_scope: CaptureScope.Index,389 src_scope: CaptureScope.Index,
393390
394 /// An integer that can be checked against the corresponding incrementing
395 /// generation field of Module. This is used to determine whether `complete` status
396 /// represents pre- or post- re-analysis.
397 generation: u32,
398 /// The AST node index of this declaration.391 /// The AST node index of this declaration.
399 /// Must be recomputed when the corresponding source file is modified.392 /// Must be recomputed when the corresponding source file is modified.
400 src_node: Ast.Node.Index,393 src_node: Ast.Node.Index,
...@@ -420,26 +413,19 @@ pub const Decl = struct {...@@ -420,26 +413,19 @@ pub const Decl = struct {
420 /// The file corresponding to this Decl had a parse error or ZIR error.413 /// The file corresponding to this Decl had a parse error or ZIR error.
421 /// There will be a corresponding ErrorMsg in Module.failed_files.414 /// There will be a corresponding ErrorMsg in Module.failed_files.
422 file_failure,415 file_failure,
423 /// This Decl might be OK but it depends on another one which did not successfully complete416 /// This Decl might be OK but it depends on another one which did not
424 /// semantic analysis.417 /// successfully complete semantic analysis.
425 dependency_failure,418 dependency_failure,
426 /// Semantic analysis failure.419 /// Semantic analysis failure.
427 /// There will be a corresponding ErrorMsg in Module.failed_decls.420 /// There will be a corresponding ErrorMsg in Module.failed_decls.
428 sema_failure,421 sema_failure,
429 /// There will be a corresponding ErrorMsg in Module.failed_decls.422 /// There will be a corresponding ErrorMsg in Module.failed_decls.
430 /// This indicates the failure was something like running out of disk space,
431 /// and attempting semantic analysis again may succeed.
432 sema_failure_retryable,
433 /// There will be a corresponding ErrorMsg in Module.failed_decls.
434 liveness_failure,
435 /// There will be a corresponding ErrorMsg in Module.failed_decls.
436 codegen_failure,423 codegen_failure,
437 /// There will be a corresponding ErrorMsg in Module.failed_decls.424 /// Sematic analysis and constant value codegen of this Decl has
438 /// This indicates the failure was something like running out of disk space,425 /// succeeded. However, the Decl may be outdated due to an in-progress
439 /// and attempting codegen again may succeed.426 /// update. Note that for a function, this does not mean codegen of the
440 codegen_failure_retryable,427 /// function body succeded: that state is indicated by the function's
441 /// Sematic analysis of this Decl has succeeded. However, the Decl may428 /// `analysis` field.
442 /// be outdated due to an incomplete update!
443 complete,429 complete,
444 },430 },
445 /// Whether `typed_value`, `align`, `linksection` and `addrspace` are populated.431 /// Whether `typed_value`, `align`, `linksection` and `addrspace` are populated.
...@@ -2495,6 +2481,7 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2495,6 +2481,7 @@ pub fn deinit(zcu: *Zcu) void {
2495 zcu.outdated.deinit(gpa);2481 zcu.outdated.deinit(gpa);
2496 zcu.outdated_ready.deinit(gpa);2482 zcu.outdated_ready.deinit(gpa);
2497 zcu.outdated_file_root.deinit(gpa);2483 zcu.outdated_file_root.deinit(gpa);
2484 zcu.retryable_failures.deinit(gpa);
24982485
2499 zcu.test_functions.deinit(gpa);2486 zcu.test_functions.deinit(gpa);
25002487
...@@ -3257,6 +3244,29 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.Depender {...@@ -3257,6 +3244,29 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.Depender {
3257 return InternPool.Depender.wrap(.{ .decl = chosen_decl_idx.? });3244 return InternPool.Depender.wrap(.{ .decl = chosen_decl_idx.? });
3258}3245}
32593246
3247/// During an incremental update, before semantic analysis, call this to flush all values from
3248/// `retryable_failures` and mark them as outdated so they get re-analyzed.
3249pub fn flushRetryableFailures(zcu: *Zcu) !void {
3250 const gpa = zcu.gpa;
3251 for (zcu.retryable_failures.items) |depender| {
3252 if (zcu.outdated.contains(depender)) continue;
3253 if (zcu.potentially_outdated.fetchSwapRemove(depender)) |kv| {
3254 // This Depender was already PO, but we now consider it outdated.
3255 // Any transitive dependencies are already marked PO.
3256 try zcu.outdated.put(gpa, depender, kv.value);
3257 continue;
3258 }
3259 // This Depender was not marked PO, but is now outdated. Mark it as
3260 // such, then recursively mark transitive dependencies as PO.
3261 try zcu.outdated.put(gpa, depender, 0);
3262 switch (depender.unwrap()) {
3263 .decl => |decl| try zcu.markDeclDependenciesPotentiallyOutdated(decl),
3264 .func => {},
3265 }
3266 }
3267 zcu.retryable_failures.clearRetainingCapacity();
3268}
3269
3260pub fn mapOldZirToNew(3270pub fn mapOldZirToNew(
3261 gpa: Allocator,3271 gpa: Allocator,
3262 old_zir: Zir,3272 old_zir: Zir,
...@@ -3415,15 +3425,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -3415,15 +3425,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
3415 switch (decl.analysis) {3425 switch (decl.analysis) {
3416 .in_progress => unreachable,3426 .in_progress => unreachable,
34173427
3418 .file_failure,3428 .file_failure => return error.AnalysisFail,
3419 .liveness_failure,
3420 .codegen_failure,
3421 .codegen_failure_retryable,
3422 .dependency_failure,
3423 => return error.AnalysisFail,
34243429
3425 .sema_failure,3430 .sema_failure,
3426 .sema_failure_retryable,3431 .dependency_failure,
3432 .codegen_failure,
3427 => if (!was_outdated) return error.AnalysisFail,3433 => if (!was_outdated) return error.AnalysisFail,
34283434
3429 .complete => if (!was_outdated) return,3435 .complete => if (!was_outdated) return,
...@@ -3434,6 +3440,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -3434,6 +3440,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
3434 if (was_outdated) {3440 if (was_outdated) {
3435 // The exports this Decl performs will be re-discovered, so we remove them here3441 // The exports this Decl performs will be re-discovered, so we remove them here
3436 // prior to re-analysis.3442 // prior to re-analysis.
3443 if (build_options.only_c) unreachable;
3437 try mod.deleteDeclExports(decl_index);3444 try mod.deleteDeclExports(decl_index);
3438 }3445 }
34393446
...@@ -3463,8 +3470,9 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -3463,8 +3470,9 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
3463 error.NeededSourceLocation => unreachable,3470 error.NeededSourceLocation => unreachable,
3464 error.GenericPoison => unreachable,3471 error.GenericPoison => unreachable,
3465 else => |e| {3472 else => |e| {
3466 decl.analysis = .sema_failure_retryable;3473 decl.analysis = .sema_failure;
3467 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);3474 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);
3475 try mod.retryable_failures.append(mod.gpa, InternPool.Depender.wrap(.{ .decl = decl_index }));
3468 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(3476 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
3469 mod.gpa,3477 mod.gpa,
3470 decl.srcLoc(mod),3478 decl.srcLoc(mod),
...@@ -3504,15 +3512,14 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError...@@ -3504,15 +3512,14 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError
3504 .unreferenced => unreachable,3512 .unreferenced => unreachable,
3505 .in_progress => unreachable,3513 .in_progress => unreachable,
35063514
3515 .codegen_failure => unreachable, // functions do not perform constant value generation
3516
3507 .file_failure,3517 .file_failure,
3508 .sema_failure,3518 .sema_failure,
3509 .liveness_failure,
3510 .codegen_failure,
3511 .dependency_failure,3519 .dependency_failure,
3512 .sema_failure_retryable,
3513 => return error.AnalysisFail,3520 => return error.AnalysisFail,
35143521
3515 .complete, .codegen_failure_retryable => {},3522 .complete => {},
3516 }3523 }
35173524
3518 const func_as_depender = InternPool.Depender.wrap(.{ .func = func_index });3525 const func_as_depender = InternPool.Depender.wrap(.{ .func = func_index });
...@@ -3524,11 +3531,14 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError...@@ -3524,11 +3531,14 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError
3524 }3531 }
35253532
3526 switch (func.analysis(ip).state) {3533 switch (func.analysis(ip).state) {
3527 .sema_failure, .dependency_failure => if (!was_outdated) return error.AnalysisFail,3534 .success,
3535 .sema_failure,
3536 .dependency_failure,
3537 .codegen_failure,
3538 => if (!was_outdated) return error.AnalysisFail,
3528 .none, .queued => {},3539 .none, .queued => {},
3529 .in_progress => unreachable,3540 .in_progress => unreachable,
3530 .inline_only => unreachable, // don't queue work for this3541 .inline_only => unreachable, // don't queue work for this
3531 .success => if (!was_outdated) return,
3532 }3542 }
35333543
3534 const gpa = zcu.gpa;3544 const gpa = zcu.gpa;
...@@ -3592,8 +3602,8 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError...@@ -3592,8 +3602,8 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError
3592 .{@errorName(err)},3602 .{@errorName(err)},
3593 ),3603 ),
3594 );3604 );
3595 decl.analysis = .liveness_failure;3605 func.analysis(ip).state = .codegen_failure;
3596 return error.AnalysisFail;3606 return;
3597 },3607 },
3598 };3608 };
3599 }3609 }
...@@ -3602,7 +3612,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError...@@ -3602,7 +3612,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError
3602 lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {3612 lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {
3603 error.OutOfMemory => return error.OutOfMemory,3613 error.OutOfMemory => return error.OutOfMemory,
3604 error.AnalysisFail => {3614 error.AnalysisFail => {
3605 decl.analysis = .codegen_failure;3615 func.analysis(ip).state = .codegen_failure;
3606 },3616 },
3607 else => {3617 else => {
3608 try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);3618 try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);
...@@ -3612,7 +3622,8 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError...@@ -3612,7 +3622,8 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError
3612 "unable to codegen: {s}",3622 "unable to codegen: {s}",
3613 .{@errorName(err)},3623 .{@errorName(err)},
3614 ));3624 ));
3615 decl.analysis = .codegen_failure_retryable;3625 func.analysis(ip).state = .codegen_failure;
3626 try zcu.retryable_failures.append(zcu.gpa, InternPool.Depender.wrap(.{ .func = func_index }));
3616 },3627 },
3617 };3628 };
3618 } else if (zcu.llvm_object) |llvm_object| {3629 } else if (zcu.llvm_object) |llvm_object| {
...@@ -3620,7 +3631,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError...@@ -3620,7 +3631,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError
3620 llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {3631 llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {
3621 error.OutOfMemory => return error.OutOfMemory,3632 error.OutOfMemory => return error.OutOfMemory,
3622 error.AnalysisFail => {3633 error.AnalysisFail => {
3623 decl.analysis = .codegen_failure;3634 func.analysis(ip).state = .codegen_failure;
3624 },3635 },
3625 };3636 };
3626 }3637 }
...@@ -3645,14 +3656,11 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)...@@ -3645,14 +3656,11 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)
36453656
3646 .file_failure,3657 .file_failure,
3647 .sema_failure,3658 .sema_failure,
3648 .liveness_failure,
3649 .codegen_failure,3659 .codegen_failure,
3650 .dependency_failure,3660 .dependency_failure,
3651 .sema_failure_retryable,3661 // Analysis of the function Decl itself failed, but we've already
3652 .codegen_failure_retryable,3662 // emitted an error for that. The callee doesn't need the function to be
3653 // The function analysis failed, but we've already emitted an error for3663 // analyzed right now, so its analysis can safely continue.
3654 // that. The callee doesn't need the function to be analyzed right now,
3655 // so its analysis can safely continue.
3656 => return,3664 => return,
36573665
3658 .complete => {},3666 .complete => {},
...@@ -3660,14 +3668,21 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)...@@ -3660,14 +3668,21 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)
36603668
3661 assert(decl.has_tv);3669 assert(decl.has_tv);
36623670
3671 const func_as_depender = InternPool.Depender.wrap(.{ .func = func_index });
3672 const is_outdated = mod.outdated.contains(func_as_depender) or
3673 mod.potentially_outdated.contains(func_as_depender);
3674
3663 switch (func.analysis(ip).state) {3675 switch (func.analysis(ip).state) {
3664 .none => {},3676 .none => {},
3665 .queued => return,3677 .queued => return,
3666 // As above, we don't need to forward errors here.3678 // As above, we don't need to forward errors here.
3667 .sema_failure, .dependency_failure => return,3679 .sema_failure,
3680 .dependency_failure,
3681 .codegen_failure,
3682 .success,
3683 => if (!is_outdated) return,
3668 .in_progress => return,3684 .in_progress => return,
3669 .inline_only => unreachable, // don't queue work for this3685 .inline_only => unreachable, // don't queue work for this
3670 .success => return,
3671 }3686 }
36723687
3673 // Decl itself is safely analyzed, and body analysis is not yet queued3688 // Decl itself is safely analyzed, and body analysis is not yet queued
...@@ -3727,7 +3742,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -3727,7 +3742,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
3727 new_decl.@"linksection" = .none;3742 new_decl.@"linksection" = .none;
3728 new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive.3743 new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive.
3729 new_decl.analysis = .in_progress;3744 new_decl.analysis = .in_progress;
3730 new_decl.generation = mod.generation;
37313745
3732 if (file.status != .success_zir) {3746 if (file.status != .success_zir) {
3733 new_decl.analysis = .file_failure;3747 new_decl.analysis = .file_failure;
...@@ -3966,7 +3980,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3966,7 +3980,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3966 decl.has_tv = true;3980 decl.has_tv = true;
3967 decl.owns_tv = false;3981 decl.owns_tv = false;
3968 decl.analysis = .complete;3982 decl.analysis = .complete;
3969 decl.generation = mod.generation;
39703983
3971 // TODO: usingnamespace cannot currently participate in incremental compilation3984 // TODO: usingnamespace cannot currently participate in incremental compilation
3972 return .{3985 return .{
...@@ -3997,7 +4010,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -3997,7 +4010,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
3997 decl.has_tv = true;4010 decl.has_tv = true;
3998 decl.owns_tv = owns_tv;4011 decl.owns_tv = owns_tv;
3999 decl.analysis = .complete;4012 decl.analysis = .complete;
4000 decl.generation = mod.generation;
40014013
4002 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;4014 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
4003 if (decl.is_exported) {4015 if (decl.is_exported) {
...@@ -4094,7 +4106,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -4094,7 +4106,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
4094 };4106 };
4095 decl.has_tv = true;4107 decl.has_tv = true;
4096 decl.analysis = .complete;4108 decl.analysis = .complete;
4097 decl.generation = mod.generation;
40984109
4099 const result: SemaDeclResult = if (old_has_tv) .{4110 const result: SemaDeclResult = if (old_has_tv) .{
4100 .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or !decl.val.eql(old_val, decl.ty, mod),4111 .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or !decl.val.eql(old_val, decl.ty, mod),
...@@ -5005,7 +5016,6 @@ pub fn allocateNewDecl(...@@ -5005,7 +5016,6 @@ pub fn allocateNewDecl(
5005 .analysis = .unreferenced,5016 .analysis = .unreferenced,
5006 .zir_decl_index = .none,5017 .zir_decl_index = .none,
5007 .src_scope = src_scope,5018 .src_scope = src_scope,
5008 .generation = 0,
5009 .is_pub = false,5019 .is_pub = false,
5010 .is_exported = false,5020 .is_exported = false,
5011 .alive = false,5021 .alive = false,
...@@ -5083,7 +5093,6 @@ pub fn initNewAnonDecl(...@@ -5083,7 +5093,6 @@ pub fn initNewAnonDecl(
5083 new_decl.@"linksection" = .none;5093 new_decl.@"linksection" = .none;
5084 new_decl.has_tv = true;5094 new_decl.has_tv = true;
5085 new_decl.analysis = .complete;5095 new_decl.analysis = .complete;
5086 new_decl.generation = mod.generation;
5087}5096}
50885097
5089pub fn errNoteNonLazy(5098pub fn errNoteNonLazy(
...@@ -5745,7 +5754,8 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void {...@@ -5745,7 +5754,8 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void {
5745 "unable to codegen: {s}",5754 "unable to codegen: {s}",
5746 .{@errorName(err)},5755 .{@errorName(err)},
5747 ));5756 ));
5748 decl.analysis = .codegen_failure_retryable;5757 decl.analysis = .codegen_failure;
5758 try zcu.retryable_failures.append(zcu.gpa, InternPool.Depender.wrap(.{ .decl = decl_index }));
5749 },5759 },
5750 };5760 };
5751 } else if (zcu.llvm_object) |llvm_object| {5761 } else if (zcu.llvm_object) |llvm_object| {
src/Sema.zig-7
...@@ -2583,7 +2583,6 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg)...@@ -2583,7 +2583,6 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg)
2583 ip.funcAnalysis(sema.owner_func_index).state = .sema_failure;2583 ip.funcAnalysis(sema.owner_func_index).state = .sema_failure;
2584 } else {2584 } else {
2585 sema.owner_decl.analysis = .sema_failure;2585 sema.owner_decl.analysis = .sema_failure;
2586 sema.owner_decl.generation = mod.generation;
2587 }2586 }
2588 if (sema.func_index != .none) {2587 if (sema.func_index != .none) {
2589 ip.funcAnalysis(sema.func_index).state = .sema_failure;2588 ip.funcAnalysis(sema.func_index).state = .sema_failure;
...@@ -9468,7 +9467,6 @@ fn funcCommon(...@@ -9468,7 +9467,6 @@ fn funcCommon(
9468 .inferred_error_set = inferred_error_set,9467 .inferred_error_set = inferred_error_set,
9469 .generic_owner = sema.generic_owner,9468 .generic_owner = sema.generic_owner,
9470 .comptime_args = sema.comptime_args,9469 .comptime_args = sema.comptime_args,
9471 .generation = mod.generation,
9472 });9470 });
9473 return finishFunc(9471 return finishFunc(
9474 sema,9472 sema,
...@@ -25957,7 +25955,6 @@ fn zirBuiltinExtern(...@@ -25957,7 +25955,6 @@ fn zirBuiltinExtern(
25957 new_decl.has_tv = true;25955 new_decl.has_tv = true;
25958 new_decl.owns_tv = true;25956 new_decl.owns_tv = true;
25959 new_decl.analysis = .complete;25957 new_decl.analysis = .complete;
25960 new_decl.generation = mod.generation;
2596125958
25962 try sema.ensureDeclAnalyzed(new_decl_index);25959 try sema.ensureDeclAnalyzed(new_decl_index);
2596325960
...@@ -36215,10 +36212,8 @@ pub fn resolveTypeFieldsStruct(...@@ -36215,10 +36212,8 @@ pub fn resolveTypeFieldsStruct(
36215 .file_failure,36212 .file_failure,
36216 .dependency_failure,36213 .dependency_failure,
36217 .sema_failure,36214 .sema_failure,
36218 .sema_failure_retryable,
36219 => {36215 => {
36220 sema.owner_decl.analysis = .dependency_failure;36216 sema.owner_decl.analysis = .dependency_failure;
36221 sema.owner_decl.generation = mod.generation;
36222 return error.AnalysisFail;36217 return error.AnalysisFail;
36223 },36218 },
36224 else => {},36219 else => {},
...@@ -36274,10 +36269,8 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Key....@@ -36274,10 +36269,8 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Key.
36274 .file_failure,36269 .file_failure,
36275 .dependency_failure,36270 .dependency_failure,
36276 .sema_failure,36271 .sema_failure,
36277 .sema_failure_retryable,
36278 => {36272 => {
36279 sema.owner_decl.analysis = .dependency_failure;36273 sema.owner_decl.analysis = .dependency_failure;
36280 sema.owner_decl.generation = mod.generation;
36281 return error.AnalysisFail;36274 return error.AnalysisFail;
36282 },36275 },
36283 else => {},36276 else => {},