| ... | ... | @@ -144,11 +144,6 @@ global_error_set: GlobalErrorSet = .{}, |
| 144 | 144 | /// Maximum amount of distinct error values, set by --error-limit |
| 145 | 145 | error_limit: ErrorInt, |
| 146 | 146 | |
| 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. |
| 150 | | generation: u32 = 0, |
| 151 | | |
| 152 | 147 | /// Value is the number of PO or outdated Decls which this Depender depends on. |
| 153 | 148 | potentially_outdated: std.AutoArrayHashMapUnmanaged(InternPool.Depender, u32) = .{}, |
| 154 | 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 | 159 | /// (only the namespace might change). If such a Decl is also `outdated`, the |
| 165 | 160 | /// struct type index must be recreated. |
| 166 | 161 | outdated_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. |
| 166 | retryable_failures: std.ArrayListUnmanaged(InternPool.Depender) = .{}, |
| 167 | 167 | |
| 168 | 168 | stage1_flags: packed struct { |
| 169 | 169 | have_winmain: bool = false, |
| ... | ... | @@ -380,21 +380,14 @@ pub const Decl = struct { |
| 380 | 380 | alignment: Alignment, |
| 381 | 381 | /// Populated when `has_tv`. |
| 382 | 382 | @"addrspace": std.builtin.AddressSpace, |
| 383 | | /// The direct parent namespace of the Decl. |
| 384 | | /// Reference to externally owned memory. |
| 385 | | /// In the case of the Decl corresponding to a file, this is |
| 386 | | /// the namespace of the struct, since there is no parent. |
| 383 | /// The direct parent namespace of the Decl. In the case of the Decl |
| 384 | /// corresponding to a file, this is the namespace of the struct, since |
| 385 | /// there is no parent. |
| 387 | 386 | src_namespace: Namespace.Index, |
| 388 | 387 | |
| 389 | | /// The scope which lexically contains this decl. A decl must depend |
| 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. |
| 388 | /// The scope which lexically contains this decl. |
| 392 | 389 | src_scope: CaptureScope.Index, |
| 393 | 390 | |
| 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 | 391 | /// The AST node index of this declaration. |
| 399 | 392 | /// Must be recomputed when the corresponding source file is modified. |
| 400 | 393 | src_node: Ast.Node.Index, |
| ... | ... | @@ -420,26 +413,19 @@ pub const Decl = struct { |
| 420 | 413 | /// The file corresponding to this Decl had a parse error or ZIR error. |
| 421 | 414 | /// There will be a corresponding ErrorMsg in Module.failed_files. |
| 422 | 415 | file_failure, |
| 423 | | /// This Decl might be OK but it depends on another one which did not successfully complete |
| 424 | | /// semantic analysis. |
| 416 | /// This Decl might be OK but it depends on another one which did not |
| 417 | /// successfully complete semantic analysis. |
| 425 | 418 | dependency_failure, |
| 426 | 419 | /// Semantic analysis failure. |
| 427 | 420 | /// There will be a corresponding ErrorMsg in Module.failed_decls. |
| 428 | 421 | sema_failure, |
| 429 | 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 | 423 | codegen_failure, |
| 437 | | /// There will be a corresponding ErrorMsg in Module.failed_decls. |
| 438 | | /// This indicates the failure was something like running out of disk space, |
| 439 | | /// and attempting codegen again may succeed. |
| 440 | | codegen_failure_retryable, |
| 441 | | /// Sematic analysis of this Decl has succeeded. However, the Decl may |
| 442 | | /// be outdated due to an incomplete update! |
| 424 | /// Sematic analysis and constant value codegen of this Decl has |
| 425 | /// succeeded. However, the Decl may be outdated due to an in-progress |
| 426 | /// update. Note that for a function, this does not mean codegen of the |
| 427 | /// function body succeded: that state is indicated by the function's |
| 428 | /// `analysis` field. |
| 443 | 429 | complete, |
| 444 | 430 | }, |
| 445 | 431 | /// Whether `typed_value`, `align`, `linksection` and `addrspace` are populated. |
| ... | ... | @@ -2495,6 +2481,7 @@ pub fn deinit(zcu: *Zcu) void { |
| 2495 | 2481 | zcu.outdated.deinit(gpa); |
| 2496 | 2482 | zcu.outdated_ready.deinit(gpa); |
| 2497 | 2483 | zcu.outdated_file_root.deinit(gpa); |
| 2484 | zcu.retryable_failures.deinit(gpa); |
| 2498 | 2485 | |
| 2499 | 2486 | zcu.test_functions.deinit(gpa); |
| 2500 | 2487 | |
| ... | ... | @@ -3257,6 +3244,29 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.Depender { |
| 3257 | 3244 | return InternPool.Depender.wrap(.{ .decl = chosen_decl_idx.? }); |
| 3258 | 3245 | } |
| 3259 | 3246 | |
| 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. |
| 3249 | pub 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 | |
| 3260 | 3270 | pub fn mapOldZirToNew( |
| 3261 | 3271 | gpa: Allocator, |
| 3262 | 3272 | old_zir: Zir, |
| ... | ... | @@ -3415,15 +3425,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 3415 | 3425 | switch (decl.analysis) { |
| 3416 | 3426 | .in_progress => unreachable, |
| 3417 | 3427 | |
| 3418 | | .file_failure, |
| 3419 | | .liveness_failure, |
| 3420 | | .codegen_failure, |
| 3421 | | .codegen_failure_retryable, |
| 3422 | | .dependency_failure, |
| 3423 | | => return error.AnalysisFail, |
| 3428 | .file_failure => return error.AnalysisFail, |
| 3424 | 3429 | |
| 3425 | 3430 | .sema_failure, |
| 3426 | | .sema_failure_retryable, |
| 3431 | .dependency_failure, |
| 3432 | .codegen_failure, |
| 3427 | 3433 | => if (!was_outdated) return error.AnalysisFail, |
| 3428 | 3434 | |
| 3429 | 3435 | .complete => if (!was_outdated) return, |
| ... | ... | @@ -3434,6 +3440,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 3434 | 3440 | if (was_outdated) { |
| 3435 | 3441 | // The exports this Decl performs will be re-discovered, so we remove them here |
| 3436 | 3442 | // prior to re-analysis. |
| 3443 | if (build_options.only_c) unreachable; |
| 3437 | 3444 | try mod.deleteDeclExports(decl_index); |
| 3438 | 3445 | } |
| 3439 | 3446 | |
| ... | ... | @@ -3463,8 +3470,9 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 3463 | 3470 | error.NeededSourceLocation => unreachable, |
| 3464 | 3471 | error.GenericPoison => unreachable, |
| 3465 | 3472 | else => |e| { |
| 3466 | | decl.analysis = .sema_failure_retryable; |
| 3473 | decl.analysis = .sema_failure; |
| 3467 | 3474 | try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1); |
| 3475 | try mod.retryable_failures.append(mod.gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); |
| 3468 | 3476 | mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( |
| 3469 | 3477 | mod.gpa, |
| 3470 | 3478 | decl.srcLoc(mod), |
| ... | ... | @@ -3504,15 +3512,14 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError |
| 3504 | 3512 | .unreferenced => unreachable, |
| 3505 | 3513 | .in_progress => unreachable, |
| 3506 | 3514 | |
| 3515 | .codegen_failure => unreachable, // functions do not perform constant value generation |
| 3516 | |
| 3507 | 3517 | .file_failure, |
| 3508 | 3518 | .sema_failure, |
| 3509 | | .liveness_failure, |
| 3510 | | .codegen_failure, |
| 3511 | 3519 | .dependency_failure, |
| 3512 | | .sema_failure_retryable, |
| 3513 | 3520 | => return error.AnalysisFail, |
| 3514 | 3521 | |
| 3515 | | .complete, .codegen_failure_retryable => {}, |
| 3522 | .complete => {}, |
| 3516 | 3523 | } |
| 3517 | 3524 | |
| 3518 | 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 | 3531 | } |
| 3525 | 3532 | |
| 3526 | 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 | 3539 | .none, .queued => {}, |
| 3529 | 3540 | .in_progress => unreachable, |
| 3530 | 3541 | .inline_only => unreachable, // don't queue work for this |
| 3531 | | .success => if (!was_outdated) return, |
| 3532 | 3542 | } |
| 3533 | 3543 | |
| 3534 | 3544 | const gpa = zcu.gpa; |
| ... | ... | @@ -3592,8 +3602,8 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError |
| 3592 | 3602 | .{@errorName(err)}, |
| 3593 | 3603 | ), |
| 3594 | 3604 | ); |
| 3595 | | decl.analysis = .liveness_failure; |
| 3596 | | return error.AnalysisFail; |
| 3605 | func.analysis(ip).state = .codegen_failure; |
| 3606 | return; |
| 3597 | 3607 | }, |
| 3598 | 3608 | }; |
| 3599 | 3609 | } |
| ... | ... | @@ -3602,7 +3612,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError |
| 3602 | 3612 | lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { |
| 3603 | 3613 | error.OutOfMemory => return error.OutOfMemory, |
| 3604 | 3614 | error.AnalysisFail => { |
| 3605 | | decl.analysis = .codegen_failure; |
| 3615 | func.analysis(ip).state = .codegen_failure; |
| 3606 | 3616 | }, |
| 3607 | 3617 | else => { |
| 3608 | 3618 | try zcu.failed_decls.ensureUnusedCapacity(gpa, 1); |
| ... | ... | @@ -3612,7 +3622,8 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError |
| 3612 | 3622 | "unable to codegen: {s}", |
| 3613 | 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 | 3629 | } else if (zcu.llvm_object) |llvm_object| { |
| ... | ... | @@ -3620,7 +3631,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError |
| 3620 | 3631 | llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { |
| 3621 | 3632 | error.OutOfMemory => return error.OutOfMemory, |
| 3622 | 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 | 3656 | |
| 3646 | 3657 | .file_failure, |
| 3647 | 3658 | .sema_failure, |
| 3648 | | .liveness_failure, |
| 3649 | 3659 | .codegen_failure, |
| 3650 | 3660 | .dependency_failure, |
| 3651 | | .sema_failure_retryable, |
| 3652 | | .codegen_failure_retryable, |
| 3653 | | // The function analysis failed, but we've already emitted an error for |
| 3654 | | // that. The callee doesn't need the function to be analyzed right now, |
| 3655 | | // so its analysis can safely continue. |
| 3661 | // Analysis of the function Decl itself failed, but we've already |
| 3662 | // emitted an error for that. The callee doesn't need the function to be |
| 3663 | // analyzed right now, so its analysis can safely continue. |
| 3656 | 3664 | => return, |
| 3657 | 3665 | |
| 3658 | 3666 | .complete => {}, |
| ... | ... | @@ -3660,14 +3668,21 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) |
| 3660 | 3668 | |
| 3661 | 3669 | assert(decl.has_tv); |
| 3662 | 3670 | |
| 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 | 3675 | switch (func.analysis(ip).state) { |
| 3664 | 3676 | .none => {}, |
| 3665 | 3677 | .queued => return, |
| 3666 | 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 | 3684 | .in_progress => return, |
| 3669 | 3685 | .inline_only => unreachable, // don't queue work for this |
| 3670 | | .success => return, |
| 3671 | 3686 | } |
| 3672 | 3687 | |
| 3673 | 3688 | // 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 | 3742 | new_decl.@"linksection" = .none; |
| 3728 | 3743 | new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive. |
| 3729 | 3744 | new_decl.analysis = .in_progress; |
| 3730 | | new_decl.generation = mod.generation; |
| 3731 | 3745 | |
| 3732 | 3746 | if (file.status != .success_zir) { |
| 3733 | 3747 | new_decl.analysis = .file_failure; |
| ... | ... | @@ -3966,7 +3980,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3966 | 3980 | decl.has_tv = true; |
| 3967 | 3981 | decl.owns_tv = false; |
| 3968 | 3982 | decl.analysis = .complete; |
| 3969 | | decl.generation = mod.generation; |
| 3970 | 3983 | |
| 3971 | 3984 | // TODO: usingnamespace cannot currently participate in incremental compilation |
| 3972 | 3985 | return .{ |
| ... | ... | @@ -3997,7 +4010,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 3997 | 4010 | decl.has_tv = true; |
| 3998 | 4011 | decl.owns_tv = owns_tv; |
| 3999 | 4012 | decl.analysis = .complete; |
| 4000 | | decl.generation = mod.generation; |
| 4001 | 4013 | |
| 4002 | 4014 | const is_inline = decl.ty.fnCallingConvention(mod) == .Inline; |
| 4003 | 4015 | if (decl.is_exported) { |
| ... | ... | @@ -4094,7 +4106,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 4094 | 4106 | }; |
| 4095 | 4107 | decl.has_tv = true; |
| 4096 | 4108 | decl.analysis = .complete; |
| 4097 | | decl.generation = mod.generation; |
| 4098 | 4109 | |
| 4099 | 4110 | const result: SemaDeclResult = if (old_has_tv) .{ |
| 4100 | 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 | 5016 | .analysis = .unreferenced, |
| 5006 | 5017 | .zir_decl_index = .none, |
| 5007 | 5018 | .src_scope = src_scope, |
| 5008 | | .generation = 0, |
| 5009 | 5019 | .is_pub = false, |
| 5010 | 5020 | .is_exported = false, |
| 5011 | 5021 | .alive = false, |
| ... | ... | @@ -5083,7 +5093,6 @@ pub fn initNewAnonDecl( |
| 5083 | 5093 | new_decl.@"linksection" = .none; |
| 5084 | 5094 | new_decl.has_tv = true; |
| 5085 | 5095 | new_decl.analysis = .complete; |
| 5086 | | new_decl.generation = mod.generation; |
| 5087 | 5096 | } |
| 5088 | 5097 | |
| 5089 | 5098 | pub fn errNoteNonLazy( |
| ... | ... | @@ -5745,7 +5754,8 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void { |
| 5745 | 5754 | "unable to codegen: {s}", |
| 5746 | 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 | 5761 | } else if (zcu.llvm_object) |llvm_object| { |