diff --git a/BRANCH_TODO b/BRANCH_TODO index 374ff7b2bf..e571db95ee 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,6 +1,5 @@ * look for cached zir code * save zir code to cache - * use list of imported strings to queue up more astgen tasks * keep track of file dependencies/dependants * unload files from memory when a dependency is dropped * implement zir error notes diff --git a/src/Compilation.zig b/src/Compilation.zig index 85a0820f05..3f0937c957 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -30,6 +30,7 @@ const c_codegen = @import("codegen/c.zig"); const ThreadPool = @import("ThreadPool.zig"); const WaitGroup = @import("WaitGroup.zig"); const libtsan = @import("libtsan.zig"); +const Zir = @import("Zir.zig"); /// General-purpose allocator. Used for both temporary and long-term storage. gpa: *Allocator, @@ -431,7 +432,6 @@ pub const AllErrors = struct { ) !void { assert(file.zir_loaded); assert(file.tree_loaded); - const Zir = @import("Zir.zig"); const payload_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.compile_errors)]; assert(payload_index != 0); @@ -2120,6 +2120,35 @@ fn workerAstGenFile( }; }, }; + + // Pre-emptively look for `@import` paths and queue them up. + // If we experience an error preemptively fetching the + // file, just ignore it and let it happen again later during Sema. + assert(file.zir_loaded); + const imports_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.imports)]; + if (imports_index != 0) { + const imports_len = file.zir.extra[imports_index]; + + for (file.zir.extra[imports_index + 1 ..][0..imports_len]) |str_index| { + const import_path = file.zir.nullTerminatedString(str_index); + + const import_result = blk: { + const lock = comp.mutex.acquire(); + defer lock.release(); + + break :blk mod.importFile(file.pkg, import_path) catch continue; + }; + if (import_result.is_new) { + wg.start(); + comp.thread_pool.spawn(workerAstGenFile, .{ + comp, import_result.file, prog_node, wg, + }) catch { + wg.finish(); + continue; + }; + } + } + } } pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest { diff --git a/src/Module.zig b/src/Module.zig index 15434fe159..9ecd8bab51 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -2628,7 +2628,16 @@ pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !vo depender.dependencies.putAssumeCapacity(dependee, {}); } -pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !*Scope.File { +pub const ImportFileResult = struct { + file: *Scope.File, + is_new: bool, +}; + +pub fn importFile( + mod: *Module, + cur_pkg: *Package, + import_string: []const u8, +) !ImportFileResult { const gpa = mod.gpa; const cur_pkg_dir_path = cur_pkg.root_src_directory.path orelse "."; @@ -2642,7 +2651,10 @@ pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !* defer if (!keep_resolved_path) gpa.free(resolved_path); const gop = try mod.import_table.getOrPut(gpa, resolved_path); - if (gop.found_existing) return gop.entry.value; + if (gop.found_existing) return ImportFileResult{ + .file = gop.entry.value, + .is_new = false, + }; if (found_pkg == null) { const resolved_root_path = try std.fs.path.resolve(gpa, &[_][]const u8{cur_pkg_dir_path}); @@ -2671,7 +2683,10 @@ pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !* .namespace = undefined, }; keep_resolved_path = true; - return new_file; + return ImportFileResult{ + .file = new_file, + .is_new = true, + }; } pub fn analyzeNamespace( diff --git a/src/Sema.zig b/src/Sema.zig index 5bc1241ae6..142d39f192 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -3904,7 +3904,7 @@ fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError! const src = inst_data.src(); const operand = inst_data.get(sema.code); - const file = mod.importFile(block.getFileScope().pkg, operand) catch |err| switch (err) { + const result = mod.importFile(block.getFileScope().pkg, operand) catch |err| switch (err) { error.ImportOutsidePkgPath => { return mod.fail(&block.base, src, "import of file outside package path: '{s}'", .{operand}); }, @@ -3914,7 +3914,7 @@ fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError! return mod.fail(&block.base, src, "unable to open '{s}': {s}", .{ operand, @errorName(err) }); }, }; - return mod.constType(sema.arena, src, file.namespace.ty); + return mod.constType(sema.arena, src, result.file.namespace.ty); } fn zirShl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {