diff options
| author | Matthew Lugg <mlugg@mlugg.co.uk> | 2024-02-06 11:33:07 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-06 11:33:07 +0000 |
| commit | 0c8072506883db21d5f8e3e7e7cb45b36d496f28 (patch) | |
| tree | 2bdfd1254c7931322ea75ffb2c5823000c5083d0 /src/Compilation.zig | |
| parent | 648b492ef1d962cabd7d2f017ef47aef73c0c3aa (diff) | |
| parent | 0784d389844a127248bb724352ce7101bc49784c (diff) | |
| download | zig-0c8072506883db21d5f8e3e7e7cb45b36d496f28.tar.gz zig-0c8072506883db21d5f8e3e7e7cb45b36d496f28.zip | |
Merge pull request #18814 from mlugg/incremental-dependencies
Begin re-implementing incremental compilation
Diffstat (limited to 'src/Compilation.zig')
| -rw-r--r-- | src/Compilation.zig | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index b735b15f79..d2ed241960 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -156,6 +156,7 @@ time_report: bool, stack_report: bool, debug_compiler_runtime_libs: bool, debug_compile_errors: bool, +debug_incremental: bool, job_queued_compiler_rt_lib: bool = false, job_queued_compiler_rt_obj: bool = false, job_queued_update_builtin_zig: bool, @@ -1079,6 +1080,7 @@ pub const CreateOptions = struct { verbose_llvm_cpu_features: bool = false, debug_compiler_runtime_libs: bool = false, debug_compile_errors: bool = false, + debug_incremental: bool = false, /// Normally when you create a `Compilation`, Zig will automatically build /// and link in required dependencies, such as compiler-rt and libc. When /// building such dependencies themselves, this flag must be set to avoid @@ -1508,6 +1510,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil .test_name_prefix = options.test_name_prefix, .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs, .debug_compile_errors = options.debug_compile_errors, + .debug_incremental = options.debug_incremental, .libcxx_abi_version = options.libcxx_abi_version, .root_name = root_name, .sysroot = sysroot, @@ -2141,7 +2144,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void if (comp.module) |module| { module.compile_log_text.shrinkAndFree(gpa, 0); - module.generation += 1; // Make sure std.zig is inside the import_table. We unconditionally need // it for start.zig. @@ -2807,6 +2809,13 @@ const Header = extern struct { limbs_len: u32, string_bytes_len: u32, tracked_insts_len: u32, + src_hash_deps_len: u32, + decl_val_deps_len: u32, + namespace_deps_len: u32, + namespace_name_deps_len: u32, + first_dependency_len: u32, + dep_entries_len: u32, + free_dep_entries_len: u32, }, }; @@ -2814,7 +2823,7 @@ const Header = extern struct { /// saved, such as the target and most CLI flags. A cache hit will only occur /// when subsequent compiler invocations use the same set of flags. pub fn saveState(comp: *Compilation) !void { - var bufs_list: [7]std.os.iovec_const = undefined; + var bufs_list: [19]std.os.iovec_const = undefined; var bufs_len: usize = 0; const lf = comp.bin_file orelse return; @@ -2828,6 +2837,13 @@ pub fn saveState(comp: *Compilation) !void { .limbs_len = @intCast(ip.limbs.items.len), .string_bytes_len = @intCast(ip.string_bytes.items.len), .tracked_insts_len = @intCast(ip.tracked_insts.count()), + .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), + .decl_val_deps_len = @intCast(ip.decl_val_deps.count()), + .namespace_deps_len = @intCast(ip.namespace_deps.count()), + .namespace_name_deps_len = @intCast(ip.namespace_name_deps.count()), + .first_dependency_len = @intCast(ip.first_dependency.count()), + .dep_entries_len = @intCast(ip.dep_entries.items.len), + .free_dep_entries_len = @intCast(ip.free_dep_entries.items.len), }, }; addBuf(&bufs_list, &bufs_len, mem.asBytes(&header)); @@ -2838,6 +2854,20 @@ pub fn saveState(comp: *Compilation) !void { addBuf(&bufs_list, &bufs_len, ip.string_bytes.items); addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.src_hash_deps.keys())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.src_hash_deps.values())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.decl_val_deps.keys())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.decl_val_deps.values())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_deps.keys())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_deps.values())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_name_deps.keys())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_name_deps.values())); + + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.first_dependency.keys())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.first_dependency.values())); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.dep_entries.items)); + addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.free_dep_entries.items)); + // TODO: compilation errors // TODO: files // TODO: namespaces @@ -3463,9 +3493,7 @@ pub fn performAllTheWork( if (comp.module) |mod| { try reportMultiModuleErrors(mod); - } - - if (comp.module) |mod| { + try mod.flushRetryableFailures(); mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); mod.sema_prog_node.activate(); } @@ -3486,6 +3514,17 @@ pub fn performAllTheWork( try processOneJob(comp, work_item, main_progress_node); continue; } + if (comp.module) |zcu| { + // If there's no work queued, check if there's anything outdated + // which we need to work on, and queue it if so. + if (try zcu.findOutdatedToAnalyze()) |outdated| { + switch (outdated.unwrap()) { + .decl => |decl| try comp.work_queue.writeItem(.{ .analyze_decl = decl }), + .func => |func| try comp.work_queue.writeItem(.{ .codegen_func = func }), + } + continue; + } + } break; } @@ -3509,17 +3548,14 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v switch (decl.analysis) { .unreferenced => unreachable, .in_progress => unreachable, - .outdated => unreachable, .file_failure, .sema_failure, - .liveness_failure, .codegen_failure, .dependency_failure, - .sema_failure_retryable, => return, - .complete, .codegen_failure_retryable => { + .complete => { const named_frame = tracy.namedFrame("codegen_decl"); defer named_frame.end(); @@ -3554,17 +3590,15 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v switch (decl.analysis) { .unreferenced => unreachable, .in_progress => unreachable, - .outdated => unreachable, .file_failure, .sema_failure, .dependency_failure, - .sema_failure_retryable, => return, // emit-h only requires semantic analysis of the Decl to be complete, // it does not depend on machine code generation to succeed. - .liveness_failure, .codegen_failure, .codegen_failure_retryable, .complete => { + .codegen_failure, .complete => { const named_frame = tracy.namedFrame("emit_h_decl"); defer named_frame.end(); @@ -3636,7 +3670,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v "unable to update line number: {s}", .{@errorName(err)}, )); - decl.analysis = .codegen_failure_retryable; + decl.analysis = .codegen_failure; + try module.retryable_failures.append(gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); }; }, .analyze_mod => |pkg| { |
